kopia lustrzana https://github.com/jameshball/osci-render
Get standalone software oscilloscope to compile
rodzic
b6465abc43
commit
44b6dea7ba
|
@ -27,7 +27,7 @@ private:
|
|||
EffectsListBoxModel listBoxModel;
|
||||
DraggableListBox listBox;
|
||||
|
||||
EffectComponent frequency = EffectComponent(audioProcessor, *audioProcessor.frequencyEffect, false);
|
||||
EffectComponent frequency = EffectComponent(*audioProcessor.frequencyEffect, false);
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(EffectsComponent)
|
||||
};
|
|
@ -34,8 +34,8 @@ private:
|
|||
DoubleTextBox offsetBox{ audioProcessor.animationOffset->min, audioProcessor.animationRate->max };
|
||||
|
||||
jux::SwitchButton invertImage{audioProcessor.invertImage};
|
||||
EffectComponent threshold{ audioProcessor, *audioProcessor.imageThreshold };
|
||||
EffectComponent stride{ audioProcessor, *audioProcessor.imageStride };
|
||||
EffectComponent threshold{*audioProcessor.imageThreshold};
|
||||
EffectComponent stride{*audioProcessor.imageStride};
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(FrameSettingsComponent)
|
||||
};
|
||||
|
|
|
@ -124,19 +124,21 @@ MainComponent::MainComponent(OscirenderAudioProcessor& p, OscirenderAudioProcess
|
|||
createFile.triggerClick();
|
||||
};
|
||||
|
||||
if (!audioProcessor.visualiserFullScreen->getBoolValue()) {
|
||||
BooleanParameter* visualiserFullScreen = audioProcessor.visualiserParameters.visualiserFullScreen;
|
||||
|
||||
if (!visualiserFullScreen->getBoolValue()) {
|
||||
addAndMakeVisible(pluginEditor.visualiser);
|
||||
}
|
||||
pluginEditor.visualiser.setFullScreenCallback([this](FullScreenMode mode) {
|
||||
pluginEditor.visualiser.setFullScreenCallback([this, visualiserFullScreen](FullScreenMode mode) {
|
||||
if (mode == FullScreenMode::TOGGLE) {
|
||||
audioProcessor.visualiserFullScreen->setBoolValueNotifyingHost(!audioProcessor.visualiserFullScreen->getBoolValue());
|
||||
visualiserFullScreen->setBoolValueNotifyingHost(!visualiserFullScreen->getBoolValue());
|
||||
} else if (mode == FullScreenMode::FULL_SCREEN) {
|
||||
audioProcessor.visualiserFullScreen->setBoolValueNotifyingHost(true);
|
||||
visualiserFullScreen->setBoolValueNotifyingHost(true);
|
||||
} else if (mode == FullScreenMode::MAIN_COMPONENT) {
|
||||
audioProcessor.visualiserFullScreen->setBoolValueNotifyingHost(false);
|
||||
visualiserFullScreen->setBoolValueNotifyingHost(false);
|
||||
}
|
||||
|
||||
pluginEditor.visualiser.setFullScreen(audioProcessor.visualiserFullScreen->getBoolValue());
|
||||
pluginEditor.visualiser.setFullScreen(visualiserFullScreen->getBoolValue());
|
||||
|
||||
pluginEditor.resized();
|
||||
pluginEditor.repaint();
|
||||
|
@ -228,7 +230,7 @@ void MainComponent::resized() {
|
|||
frequencyLabel.setBounds(bounds.removeFromTop(20));
|
||||
|
||||
bounds.removeFromTop(padding);
|
||||
if (!audioProcessor.visualiserFullScreen->getBoolValue()) {
|
||||
if (!audioProcessor.visualiserParameters.visualiserFullScreen->getBoolValue()) {
|
||||
auto minDim = juce::jmin(bounds.getWidth(), bounds.getHeight());
|
||||
juce::Point<int> localTopLeft = {bounds.getX(), bounds.getY()};
|
||||
juce::Point<int> topLeft = pluginEditor.getLocalPoint(this, localTopLeft);
|
||||
|
|
|
@ -16,8 +16,8 @@ private:
|
|||
OscirenderAudioProcessor& audioProcessor;
|
||||
OscirenderAudioProcessorEditor& pluginEditor;
|
||||
|
||||
EffectComponent perspective{audioProcessor, *audioProcessor.perspective, 0};
|
||||
EffectComponent focalLength{audioProcessor, *audioProcessor.perspective, 1};
|
||||
EffectComponent perspective{*audioProcessor.perspective, 0};
|
||||
EffectComponent focalLength{*audioProcessor.perspective, 1};
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PerspectiveComponent)
|
||||
};
|
||||
|
|
|
@ -164,7 +164,7 @@ void OscirenderAudioProcessorEditor::paint(juce::Graphics& g) {
|
|||
void OscirenderAudioProcessorEditor::resized() {
|
||||
auto area = getLocalBounds();
|
||||
|
||||
if (audioProcessor.visualiserFullScreen->getBoolValue()) {
|
||||
if (audioProcessor.visualiserParameters.visualiserFullScreen->getBoolValue()) {
|
||||
visualiser.setBounds(area);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -49,9 +49,9 @@ public:
|
|||
|
||||
std::atomic<bool> editingCustomFunction = false;
|
||||
|
||||
VisualiserSettings visualiserSettings = VisualiserSettings(audioProcessor);
|
||||
VisualiserSettings visualiserSettings = VisualiserSettings(audioProcessor.visualiserParameters);
|
||||
SettingsWindow visualiserSettingsWindow = SettingsWindow("Visualiser Settings");
|
||||
VisualiserComponent visualiser{audioProcessor, visualiserSettings, nullptr, audioProcessor.legacyVisualiserEnabled->getBoolValue()};
|
||||
VisualiserComponent visualiser{audioProcessor, audioProcessor, visualiserSettings, nullptr, audioProcessor.visualiserParameters.legacyVisualiserEnabled->getBoolValue()};
|
||||
|
||||
SettingsComponent settings{audioProcessor, *this};
|
||||
|
||||
|
|
|
@ -149,10 +149,10 @@ OscirenderAudioProcessor::OscirenderAudioProcessor()
|
|||
permanentEffects.push_back(thresholdEffect);
|
||||
permanentEffects.push_back(imageThreshold);
|
||||
permanentEffects.push_back(imageStride);
|
||||
permanentEffects.push_back(brightnessEffect);
|
||||
permanentEffects.push_back(intensityEffect);
|
||||
permanentEffects.push_back(persistenceEffect);
|
||||
permanentEffects.push_back(hueEffect);
|
||||
permanentEffects.push_back(visualiserParameters.brightnessEffect);
|
||||
permanentEffects.push_back(visualiserParameters.intensityEffect);
|
||||
permanentEffects.push_back(visualiserParameters.persistenceEffect);
|
||||
permanentEffects.push_back(visualiserParameters.hueEffect);
|
||||
|
||||
for (int i = 0; i < 26; i++) {
|
||||
addLuaSlider();
|
||||
|
@ -176,11 +176,11 @@ OscirenderAudioProcessor::OscirenderAudioProcessor()
|
|||
booleanParameters.push_back(animateFrames);
|
||||
booleanParameters.push_back(animationSyncBPM);
|
||||
booleanParameters.push_back(invertImage);
|
||||
booleanParameters.push_back(graticuleEnabled);
|
||||
booleanParameters.push_back(smudgesEnabled);
|
||||
booleanParameters.push_back(upsamplingEnabled);
|
||||
booleanParameters.push_back(legacyVisualiserEnabled);
|
||||
booleanParameters.push_back(visualiserFullScreen);
|
||||
booleanParameters.push_back(visualiserParameters.graticuleEnabled);
|
||||
booleanParameters.push_back(visualiserParameters.smudgesEnabled);
|
||||
booleanParameters.push_back(visualiserParameters.upsamplingEnabled);
|
||||
booleanParameters.push_back(visualiserParameters.legacyVisualiserEnabled);
|
||||
booleanParameters.push_back(visualiserParameters.visualiserFullScreen);
|
||||
|
||||
for (auto parameter : booleanParameters) {
|
||||
addParameter(parameter);
|
||||
|
@ -212,11 +212,18 @@ OscirenderAudioProcessor::OscirenderAudioProcessor()
|
|||
}
|
||||
|
||||
voices->addListener(this);
|
||||
|
||||
for (int i = 0; i < luaEffects.size(); i++) {
|
||||
luaEffects[i]->parameters[0]->addListener(this);
|
||||
}
|
||||
|
||||
synth.addSound(defaultSound);
|
||||
}
|
||||
|
||||
OscirenderAudioProcessor::~OscirenderAudioProcessor() {
|
||||
for (int i = luaEffects.size() - 1; i >= 0; i--) {
|
||||
luaEffects[i]->parameters[0]->removeListener(this);
|
||||
}
|
||||
voices->removeListener(this);
|
||||
}
|
||||
|
||||
|
@ -332,7 +339,7 @@ void OscirenderAudioProcessor::addLuaSlider() {
|
|||
|
||||
luaEffects.push_back(std::make_shared<Effect>(
|
||||
[this, sliderIndex](int index, Point input, const std::vector<std::atomic<double>>& values, double sampleRate) {
|
||||
luaValues[sliderIndex] = values[0];
|
||||
luaValues[sliderIndex].store(values[0]);
|
||||
return input;
|
||||
}, new EffectParameter(
|
||||
"Lua Slider " + sliderName,
|
||||
|
@ -822,8 +829,8 @@ void OscirenderAudioProcessor::getStateInformation(juce::MemoryBlock& destData)
|
|||
xml->setAttribute("currentFile", currentFile);
|
||||
|
||||
auto visualiserXml = xml->createNewChildElement("visualiser");
|
||||
visualiserXml->setAttribute("roughness", roughness);
|
||||
visualiserXml->setAttribute("intensity", intensity);
|
||||
visualiserXml->setAttribute("roughness", visualiserParameters.roughness);
|
||||
visualiserXml->setAttribute("intensity", visualiserParameters.intensity);
|
||||
|
||||
copyXmlToBinary(*xml, destData);
|
||||
}
|
||||
|
@ -941,8 +948,8 @@ void OscirenderAudioProcessor::setStateInformation(const void* data, int sizeInB
|
|||
|
||||
auto visualiserXml = xml->getChildByName("visualiser");
|
||||
if (visualiserXml != nullptr) {
|
||||
roughness = visualiserXml->getIntAttribute("roughness");
|
||||
intensity = visualiserXml->getDoubleAttribute("intensity");
|
||||
visualiserParameters.roughness = visualiserXml->getIntAttribute("roughness");
|
||||
visualiserParameters.intensity = visualiserXml->getDoubleAttribute("intensity");
|
||||
}
|
||||
|
||||
broadcaster.sendChangeMessage();
|
||||
|
@ -950,28 +957,12 @@ void OscirenderAudioProcessor::setStateInformation(const void* data, int sizeInB
|
|||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<BufferConsumer> OscirenderAudioProcessor::consumerRegister(std::vector<float>& buffer) {
|
||||
std::shared_ptr<BufferConsumer> consumer = std::make_shared<BufferConsumer>(buffer);
|
||||
juce::SpinLock::ScopedLockType scope(consumerLock);
|
||||
consumers.push_back(consumer);
|
||||
|
||||
return consumer;
|
||||
}
|
||||
|
||||
void OscirenderAudioProcessor::consumerRead(std::shared_ptr<BufferConsumer> consumer) {
|
||||
consumer->waitUntilFull();
|
||||
juce::SpinLock::ScopedLockType scope(consumerLock);
|
||||
consumers.erase(std::remove(consumers.begin(), consumers.end(), consumer), consumers.end());
|
||||
}
|
||||
|
||||
void OscirenderAudioProcessor::consumerStop(std::shared_ptr<BufferConsumer> consumer) {
|
||||
if (consumer != nullptr) {
|
||||
juce::SpinLock::ScopedLockType scope(consumerLock);
|
||||
consumer->forceNotify();
|
||||
}
|
||||
}
|
||||
|
||||
void OscirenderAudioProcessor::parameterValueChanged(int parameterIndex, float newValue) {
|
||||
for (auto effect : luaEffects) {
|
||||
if (parameterIndex == effect->parameters[0]->getParameterIndex()) {
|
||||
effect->apply();
|
||||
}
|
||||
}
|
||||
if (parameterIndex == voices->getParameterIndex()) {
|
||||
int numVoices = voices->getValueUnnormalised();
|
||||
// if the number of voices has changed, update the synth without clearing all the voices
|
||||
|
@ -1019,6 +1010,10 @@ void OscirenderAudioProcessor::envelopeChanged(EnvelopeComponent* changedEnvelop
|
|||
}
|
||||
}
|
||||
|
||||
double OscirenderAudioProcessor::getSampleRate() {
|
||||
return currentSampleRate;
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
// This creates new instances of the plugin..
|
||||
|
|
|
@ -8,13 +8,17 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#define VERSION_HINT 2
|
||||
|
||||
#include <JuceHeader.h>
|
||||
#include "shape/Shape.h"
|
||||
#include "concurrency/BufferConsumer.h"
|
||||
#include "concurrency/ConsumerManager.h"
|
||||
#include "components/VisualiserSettings.h"
|
||||
#include "audio/Effect.h"
|
||||
#include "audio/ShapeSound.h"
|
||||
#include "audio/ShapeVoice.h"
|
||||
#include "audio/PublicSynthesiser.h"
|
||||
#include "audio/SampleRateManager.h"
|
||||
#include <numbers>
|
||||
#include "audio/DelayEffect.h"
|
||||
#include "audio/PitchDetector.h"
|
||||
|
@ -29,7 +33,7 @@
|
|||
//==============================================================================
|
||||
/**
|
||||
*/
|
||||
class OscirenderAudioProcessor : public juce::AudioProcessor, juce::AudioProcessorParameter::Listener, public EnvelopeComponentListener
|
||||
class OscirenderAudioProcessor : public juce::AudioProcessor, juce::AudioProcessorParameter::Listener, public EnvelopeComponentListener, public ConsumerManager, public SampleRateManager
|
||||
#if JucePlugin_Enable_ARA
|
||||
, public juce::AudioProcessorARAExtension
|
||||
#endif
|
||||
|
@ -65,24 +69,17 @@ public:
|
|||
void changeProgramName(int index, const juce::String& newName) override;
|
||||
void getStateInformation(juce::MemoryBlock& destData) override;
|
||||
void setStateInformation(const void* data, int sizeInBytes) override;
|
||||
std::shared_ptr<BufferConsumer> consumerRegister(std::vector<float>& buffer);
|
||||
void consumerStop(std::shared_ptr<BufferConsumer> consumer);
|
||||
void consumerRead(std::shared_ptr<BufferConsumer> consumer);
|
||||
void parameterValueChanged(int parameterIndex, float newValue) override;
|
||||
void parameterGestureChanged(int parameterIndex, bool gestureIsStarting) override;
|
||||
void envelopeChanged(EnvelopeComponent* changedEnvelope) override;
|
||||
|
||||
int VERSION_HINT = 2;
|
||||
double getSampleRate() override;
|
||||
|
||||
std::atomic<double> currentSampleRate = 0.0;
|
||||
|
||||
std::atomic<int> roughness = 4;
|
||||
std::atomic<double> intensity = 1.0;
|
||||
|
||||
juce::SpinLock effectsLock;
|
||||
std::vector<std::shared_ptr<Effect>> toggleableEffects;
|
||||
std::vector<std::shared_ptr<Effect>> luaEffects;
|
||||
double luaValues[26] = { 0.0 };
|
||||
std::atomic<double> luaValues[26] = { 0.0 };
|
||||
|
||||
std::shared_ptr<Effect> frequencyEffect = std::make_shared<Effect>(
|
||||
[this](int index, Point input, const std::vector<std::atomic<double>>& values, double sampleRate) {
|
||||
|
@ -156,46 +153,8 @@ public:
|
|||
new EffectParameter("Focal Length", "Controls the focal length of the 3D perspective effect. A higher focal length makes the image look more flat, and a lower focal length makes the image look more 3D.", "perspectiveFocalLength", VERSION_HINT, 2.0, 0.0, 10.0),
|
||||
}
|
||||
);
|
||||
|
||||
// visualiser settings
|
||||
BooleanParameter* graticuleEnabled = new BooleanParameter("Show Graticule", "graticuleEnabled", VERSION_HINT, true, "Show the graticule or grid lines over the oscilloscope display.");
|
||||
BooleanParameter* smudgesEnabled = new BooleanParameter("Show Smudges", "smudgesEnabled", VERSION_HINT, true, "Adds a subtle layer of dirt/smudges to the oscilloscope display to make it look more realistic.");
|
||||
BooleanParameter* upsamplingEnabled = new BooleanParameter("Upsample Audio", "upsamplingEnabled", VERSION_HINT, false, "Upsamples the audio before visualising it to make it appear more realistic, at the expense of performance.");
|
||||
BooleanParameter* legacyVisualiserEnabled = new BooleanParameter("Use Legacy Visualiser", "legacyVisualiserEnabled", VERSION_HINT, false, "Replaces the realistic oscilloscope visualiser with the legacy visualiser. This may improve performance.");
|
||||
BooleanParameter* visualiserFullScreen = new BooleanParameter("Visualiser Fullscreen", "visualiserFullScreen", VERSION_HINT, false, "Makes the software visualiser fullscreen.");
|
||||
|
||||
std::shared_ptr<Effect> persistenceEffect = std::make_shared<Effect>(
|
||||
new EffectParameter(
|
||||
"Persistence",
|
||||
"Controls how long the light glows for on the oscilloscope display.",
|
||||
"persistence",
|
||||
VERSION_HINT, 0.5, 0, 6.0
|
||||
)
|
||||
);
|
||||
std::shared_ptr<Effect> hueEffect = std::make_shared<Effect>(
|
||||
new EffectParameter(
|
||||
"Hue",
|
||||
"Controls the hue/colour of the oscilloscope display.",
|
||||
"hue",
|
||||
VERSION_HINT, 125, 0, 359, 1
|
||||
)
|
||||
);
|
||||
std::shared_ptr<Effect> brightnessEffect = std::make_shared<Effect>(
|
||||
new EffectParameter(
|
||||
"Brightness",
|
||||
"Controls how bright the light glows for on the oscilloscope display.",
|
||||
"brightness",
|
||||
VERSION_HINT, 3.0, 0.0, 10.0
|
||||
)
|
||||
);
|
||||
std::shared_ptr<Effect> intensityEffect = std::make_shared<Effect>(
|
||||
new EffectParameter(
|
||||
"Intensity",
|
||||
"Controls how bright the electron beam of the oscilloscope is.",
|
||||
"intensity",
|
||||
VERSION_HINT, 3.0, 0.0, 10.0
|
||||
)
|
||||
);
|
||||
VisualiserParameters visualiserParameters;
|
||||
|
||||
BooleanParameter* midiEnabled = new BooleanParameter("MIDI Enabled", "midiEnabled", VERSION_HINT, false, "Enable MIDI input for the synth. If disabled, the synth will play a constant tone, as controlled by the frequency slider.");
|
||||
BooleanParameter* inputEnabled = new BooleanParameter("Audio Input Enabled", "inputEnabled", VERSION_HINT, false, "Enable to use input audio, instead of the generated audio.");
|
||||
|
@ -264,11 +223,6 @@ public:
|
|||
);
|
||||
|
||||
double animationTime = 0.f;
|
||||
|
||||
private:
|
||||
juce::SpinLock consumerLock;
|
||||
std::vector<std::shared_ptr<BufferConsumer>> consumers;
|
||||
public:
|
||||
|
||||
PitchDetector pitchDetector{*this};
|
||||
std::shared_ptr<WobbleEffect> wobbleEffect = std::make_shared<WobbleEffect>(pitchDetector);
|
||||
|
|
|
@ -0,0 +1,151 @@
|
|||
#include "SosciPluginProcessor.h"
|
||||
#include "SosciPluginEditor.h"
|
||||
#include <juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h>
|
||||
|
||||
SosciPluginEditor::SosciPluginEditor(SosciAudioProcessor& p)
|
||||
: AudioProcessorEditor(&p), audioProcessor(p)
|
||||
{
|
||||
#if JUCE_LINUX
|
||||
// use OpenGL on Linux for much better performance. The default on Mac is CoreGraphics, and on Window is Direct2D which is much faster.
|
||||
openGlContext.attachTo(*getTopLevelComponent());
|
||||
#endif
|
||||
|
||||
setLookAndFeel(&lookAndFeel);
|
||||
|
||||
// #if JUCE_MAC
|
||||
// if (audioProcessor.wrapperType == juce::AudioProcessor::WrapperType::wrapperType_Standalone) {
|
||||
// usingNativeMenuBar = true;
|
||||
// menuBarModel.setMacMainMenu(&menuBarModel);
|
||||
// }
|
||||
// #endif
|
||||
|
||||
// if (!usingNativeMenuBar) {
|
||||
// menuBar.setModel(&menuBarModel);
|
||||
// addAndMakeVisible(menuBar);
|
||||
// }
|
||||
|
||||
if (juce::JUCEApplicationBase::isStandaloneApp()) {
|
||||
if (juce::TopLevelWindow::getNumTopLevelWindows() > 0) {
|
||||
juce::TopLevelWindow* w = juce::TopLevelWindow::getTopLevelWindow(0);
|
||||
juce::DocumentWindow* dw = dynamic_cast<juce::DocumentWindow*>(w);
|
||||
if (dw != nullptr) {
|
||||
dw->setBackgroundColour(Colours::veryDark);
|
||||
dw->setColour(juce::ResizableWindow::backgroundColourId, Colours::veryDark);
|
||||
dw->setTitleBarButtonsRequired(juce::DocumentWindow::allButtons, false);
|
||||
dw->setUsingNativeTitleBar(true);
|
||||
}
|
||||
}
|
||||
|
||||
juce::StandalonePluginHolder* standalone = juce::StandalonePluginHolder::getInstance();
|
||||
if (standalone != nullptr) {
|
||||
standalone->getMuteInputValue().setValue(false);
|
||||
}
|
||||
}
|
||||
|
||||
addAndMakeVisible(visualiser);
|
||||
|
||||
setSize(750, 750);
|
||||
setResizable(true, true);
|
||||
setResizeLimits(250, 250, 999999, 999999);
|
||||
}
|
||||
|
||||
SosciPluginEditor::~SosciPluginEditor() {
|
||||
setLookAndFeel(nullptr);
|
||||
juce::Desktop::getInstance().setDefaultLookAndFeel(nullptr);
|
||||
|
||||
// #if JUCE_MAC
|
||||
// if (usingNativeMenuBar) {
|
||||
// menuBarModel.setMacMainMenu(nullptr);
|
||||
// }
|
||||
// #endif
|
||||
}
|
||||
|
||||
void SosciPluginEditor::paint(juce::Graphics& g) {
|
||||
g.fillAll(getLookAndFeel().findColour(juce::ResizableWindow::backgroundColourId));
|
||||
}
|
||||
|
||||
void SosciPluginEditor::resized() {
|
||||
auto area = getLocalBounds();
|
||||
visualiser.setBounds(area);
|
||||
|
||||
// if (!usingNativeMenuBar) {
|
||||
// menuBar.setBounds(area.removeFromTop(25));
|
||||
// }
|
||||
}
|
||||
|
||||
bool SosciPluginEditor::keyPressed(const juce::KeyPress& key) {
|
||||
if (key.getModifiers().isCommandDown() && key.getModifiers().isShiftDown() && key.getKeyCode() == 'S') {
|
||||
saveProjectAs();
|
||||
} else if (key.getModifiers().isCommandDown() && key.getKeyCode() == 'S') {
|
||||
saveProject();
|
||||
} else if (key.getModifiers().isCommandDown() && key.getKeyCode() == 'O') {
|
||||
openProject();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void SosciPluginEditor::openProject() {
|
||||
chooser = std::make_unique<juce::FileChooser>("Load sosci Project", audioProcessor.lastOpenedDirectory, "*.sosci");
|
||||
auto flags = juce::FileBrowserComponent::openMode |
|
||||
juce::FileBrowserComponent::canSelectFiles;
|
||||
|
||||
chooser->launchAsync(flags, [this](const juce::FileChooser& chooser) {
|
||||
auto file = chooser.getResult();
|
||||
if (file != juce::File()) {
|
||||
auto data = juce::MemoryBlock();
|
||||
if (file.loadFileAsData(data)) {
|
||||
audioProcessor.setStateInformation(data.getData(), data.getSize());
|
||||
}
|
||||
audioProcessor.currentProjectFile = file.getFullPathName();
|
||||
audioProcessor.lastOpenedDirectory = file.getParentDirectory();
|
||||
updateTitle();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void SosciPluginEditor::saveProject() {
|
||||
if (audioProcessor.currentProjectFile.isEmpty()) {
|
||||
saveProjectAs();
|
||||
} else {
|
||||
auto data = juce::MemoryBlock();
|
||||
audioProcessor.getStateInformation(data);
|
||||
auto file = juce::File(audioProcessor.currentProjectFile);
|
||||
file.create();
|
||||
file.replaceWithData(data.getData(), data.getSize());
|
||||
updateTitle();
|
||||
}
|
||||
}
|
||||
|
||||
void SosciPluginEditor::saveProjectAs() {
|
||||
chooser = std::make_unique<juce::FileChooser>("Save sosci Project", audioProcessor.lastOpenedDirectory, "*.sosci");
|
||||
auto flags = juce::FileBrowserComponent::saveMode;
|
||||
|
||||
chooser->launchAsync(flags, [this](const juce::FileChooser& chooser) {
|
||||
auto file = chooser.getResult();
|
||||
if (file != juce::File()) {
|
||||
audioProcessor.currentProjectFile = file.getFullPathName();
|
||||
saveProject();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void SosciPluginEditor::updateTitle() {
|
||||
juce::String title = "sosci";
|
||||
if (!audioProcessor.currentProjectFile.isEmpty()) {
|
||||
title += " - " + audioProcessor.currentProjectFile;
|
||||
}
|
||||
getTopLevelComponent()->setName(title);
|
||||
}
|
||||
|
||||
void SosciPluginEditor::openAudioSettings() {
|
||||
juce::StandalonePluginHolder* standalone = juce::StandalonePluginHolder::getInstance();
|
||||
standalone->showAudioSettingsDialog();
|
||||
}
|
||||
|
||||
void SosciPluginEditor::resetToDefault() {
|
||||
juce::StandaloneFilterWindow* window = findParentComponentOfClass<juce::StandaloneFilterWindow>();
|
||||
if (window != nullptr) {
|
||||
window->resetToDefaultState();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
#pragma once
|
||||
|
||||
#include <JuceHeader.h>
|
||||
#include "SosciPluginProcessor.h"
|
||||
#include "components/VisualiserComponent.h"
|
||||
#include "LookAndFeel.h"
|
||||
#include "components/VisualiserSettings.h"
|
||||
|
||||
class SosciPluginEditor : public juce::AudioProcessorEditor {
|
||||
public:
|
||||
SosciPluginEditor(SosciAudioProcessor&);
|
||||
~SosciPluginEditor() override;
|
||||
|
||||
void paint(juce::Graphics&) override;
|
||||
void resized() override;
|
||||
|
||||
void openProject();
|
||||
void saveProject();
|
||||
void saveProjectAs();
|
||||
void updateTitle();
|
||||
void openAudioSettings();
|
||||
void resetToDefault();
|
||||
|
||||
private:
|
||||
SosciAudioProcessor& audioProcessor;
|
||||
public:
|
||||
OscirenderLookAndFeel lookAndFeel;
|
||||
|
||||
VisualiserSettings visualiserSettings = VisualiserSettings(audioProcessor.parameters);
|
||||
SettingsWindow visualiserSettingsWindow = SettingsWindow("Visualiser Settings");
|
||||
VisualiserComponent visualiser{audioProcessor, audioProcessor, visualiserSettings, nullptr, audioProcessor.parameters.legacyVisualiserEnabled->getBoolValue()};
|
||||
|
||||
std::unique_ptr<juce::FileChooser> chooser;
|
||||
// MainMenuBarModel menuBarModel{audioProcessor, *this};
|
||||
// juce::MenuBarComponent menuBar;
|
||||
|
||||
juce::TooltipWindow tooltipWindow{nullptr, 0};
|
||||
|
||||
//bool usingNativeMenuBar = false;
|
||||
|
||||
#if JUCE_LINUX
|
||||
juce::OpenGLContext openGlContext;
|
||||
#endif
|
||||
|
||||
bool keyPressed(const juce::KeyPress& key) override;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(SosciPluginEditor)
|
||||
};
|
|
@ -0,0 +1,327 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file contains the basic framework code for a JUCE plugin processor.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "SosciPluginProcessor.h"
|
||||
#include "SosciPluginEditor.h"
|
||||
#include "audio/EffectParameter.h"
|
||||
|
||||
//==============================================================================
|
||||
SosciAudioProcessor::SosciAudioProcessor()
|
||||
#ifndef JucePlugin_PreferredChannelConfigurations
|
||||
: AudioProcessor (BusesProperties()
|
||||
#if ! JucePlugin_IsMidiEffect
|
||||
#if ! JucePlugin_IsSynth
|
||||
.withInput ("Input", juce::AudioChannelSet::stereo(), true)
|
||||
#endif
|
||||
.withOutput ("Output", juce::AudioChannelSet::stereo(), true)
|
||||
#endif
|
||||
)
|
||||
#endif
|
||||
{
|
||||
// locking isn't necessary here because we are in the constructor
|
||||
|
||||
allEffects.push_back(parameters.brightnessEffect);
|
||||
allEffects.push_back(parameters.intensityEffect);
|
||||
allEffects.push_back(parameters.persistenceEffect);
|
||||
allEffects.push_back(parameters.hueEffect);
|
||||
|
||||
for (auto effect : allEffects) {
|
||||
for (auto effectParameter : effect->parameters) {
|
||||
auto parameters = effectParameter->getParameters();
|
||||
for (auto parameter : parameters) {
|
||||
addParameter(parameter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
booleanParameters.push_back(parameters.graticuleEnabled);
|
||||
booleanParameters.push_back(parameters.smudgesEnabled);
|
||||
booleanParameters.push_back(parameters.upsamplingEnabled);
|
||||
booleanParameters.push_back(parameters.legacyVisualiserEnabled);
|
||||
booleanParameters.push_back(parameters.visualiserFullScreen);
|
||||
|
||||
for (auto parameter : booleanParameters) {
|
||||
addParameter(parameter);
|
||||
}
|
||||
|
||||
for (auto parameter : floatParameters) {
|
||||
addParameter(parameter);
|
||||
}
|
||||
|
||||
for (auto parameter : intParameters) {
|
||||
addParameter(parameter);
|
||||
}
|
||||
}
|
||||
|
||||
SosciAudioProcessor::~SosciAudioProcessor() {}
|
||||
|
||||
const juce::String SosciAudioProcessor::getName() const {
|
||||
return JucePlugin_Name;
|
||||
}
|
||||
|
||||
bool SosciAudioProcessor::acceptsMidi() const {
|
||||
#if JucePlugin_WantsMidiInput
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool SosciAudioProcessor::producesMidi() const {
|
||||
#if JucePlugin_ProducesMidiOutput
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool SosciAudioProcessor::isMidiEffect() const {
|
||||
#if JucePlugin_IsMidiEffect
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
double SosciAudioProcessor::getTailLengthSeconds() const {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
int SosciAudioProcessor::getNumPrograms() {
|
||||
return 1; // NB: some hosts don't cope very well if you tell them there are 0 programs,
|
||||
// so this should be at least 1, even if you're not really implementing programs.
|
||||
}
|
||||
|
||||
int SosciAudioProcessor::getCurrentProgram() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SosciAudioProcessor::setCurrentProgram(int index) {
|
||||
}
|
||||
|
||||
const juce::String SosciAudioProcessor::getProgramName(int index) {
|
||||
return {};
|
||||
}
|
||||
|
||||
void SosciAudioProcessor::changeProgramName(int index, const juce::String& newName) {}
|
||||
|
||||
void SosciAudioProcessor::prepareToPlay(double sampleRate, int samplesPerBlock) {
|
||||
currentSampleRate = sampleRate;
|
||||
|
||||
for (auto& effect : allEffects) {
|
||||
effect->updateSampleRate(currentSampleRate);
|
||||
}
|
||||
}
|
||||
|
||||
void SosciAudioProcessor::releaseResources() {
|
||||
// When playback stops, you can use this as an opportunity to free up any
|
||||
// spare memory, etc.
|
||||
}
|
||||
|
||||
#ifndef JucePlugin_PreferredChannelConfigurations
|
||||
bool SosciAudioProcessor::isBusesLayoutSupported (const BusesLayout& layouts) const
|
||||
{
|
||||
#if JucePlugin_IsMidiEffect
|
||||
juce::ignoreUnused (layouts);
|
||||
return true;
|
||||
#else
|
||||
// This is the place where you check if the layout is supported.
|
||||
// In this template code we only support mono or stereo.
|
||||
// Some plugin hosts, such as certain GarageBand versions, will only
|
||||
// load plugins that support stereo bus layouts.
|
||||
if (layouts.getMainOutputChannelSet() != juce::AudioChannelSet::mono()
|
||||
&& layouts.getMainOutputChannelSet() != juce::AudioChannelSet::stereo())
|
||||
return false;
|
||||
|
||||
// This checks if the input layout matches the output layout
|
||||
#if ! JucePlugin_IsSynth
|
||||
if (layouts.getMainOutputChannelSet() != layouts.getMainInputChannelSet())
|
||||
return false;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
// effectsLock should be held when calling this
|
||||
std::shared_ptr<Effect> SosciAudioProcessor::getEffect(juce::String id) {
|
||||
for (auto& effect : allEffects) {
|
||||
if (effect->getId() == id) {
|
||||
return effect;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// effectsLock should be held when calling this
|
||||
BooleanParameter* SosciAudioProcessor::getBooleanParameter(juce::String id) {
|
||||
for (auto& parameter : booleanParameters) {
|
||||
if (parameter->paramID == id) {
|
||||
return parameter;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// effectsLock should be held when calling this
|
||||
FloatParameter* SosciAudioProcessor::getFloatParameter(juce::String id) {
|
||||
for (auto& parameter : floatParameters) {
|
||||
if (parameter->paramID == id) {
|
||||
return parameter;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// effectsLock should be held when calling this
|
||||
IntParameter* SosciAudioProcessor::getIntParameter(juce::String id) {
|
||||
for (auto& parameter : intParameters) {
|
||||
if (parameter->paramID == id) {
|
||||
return parameter;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void SosciAudioProcessor::processBlock(juce::AudioBuffer<float>& buffer, juce::MidiBuffer& midiMessages) {
|
||||
juce::ScopedNoDenormals noDenormals;
|
||||
// Audio info variables
|
||||
int numInputs = getTotalNumInputChannels();
|
||||
int numOutputs = getTotalNumOutputChannels();
|
||||
double sampleRate = getSampleRate();
|
||||
|
||||
midiMessages.clear();
|
||||
|
||||
auto* channelData = buffer.getArrayOfWritePointers();
|
||||
|
||||
for (int sample = 0; sample < buffer.getNumSamples(); ++sample) {
|
||||
juce::SpinLock::ScopedLockType scope(consumerLock);
|
||||
|
||||
double x = numOutputs > 0 ? channelData[0][sample] : 0;
|
||||
double y = numOutputs > 1 ? channelData[1][sample] : 0;
|
||||
double z = numOutputs > 2 ? channelData[2][sample] : 0;
|
||||
|
||||
for (auto consumer : consumers) {
|
||||
consumer->write(x);
|
||||
consumer->write(y);
|
||||
consumer->notifyIfFull();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
bool SosciAudioProcessor::hasEditor() const {
|
||||
return true; // (change this to false if you choose to not supply an editor)
|
||||
}
|
||||
|
||||
juce::AudioProcessorEditor* SosciAudioProcessor::createEditor() {
|
||||
auto editor = new SosciPluginEditor(*this);
|
||||
return editor;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void SosciAudioProcessor::getStateInformation(juce::MemoryBlock& destData) {
|
||||
juce::SpinLock::ScopedLockType lock2(effectsLock);
|
||||
|
||||
std::unique_ptr<juce::XmlElement> xml = std::make_unique<juce::XmlElement>("project");
|
||||
xml->setAttribute("version", ProjectInfo::versionString);
|
||||
auto effectsXml = xml->createNewChildElement("effects");
|
||||
for (auto effect : allEffects) {
|
||||
effect->save(effectsXml->createNewChildElement("effect"));
|
||||
}
|
||||
|
||||
auto booleanParametersXml = xml->createNewChildElement("booleanParameters");
|
||||
for (auto parameter : booleanParameters) {
|
||||
auto parameterXml = booleanParametersXml->createNewChildElement("parameter");
|
||||
parameter->save(parameterXml);
|
||||
}
|
||||
|
||||
auto floatParametersXml = xml->createNewChildElement("floatParameters");
|
||||
for (auto parameter : floatParameters) {
|
||||
auto parameterXml = floatParametersXml->createNewChildElement("parameter");
|
||||
parameter->save(parameterXml);
|
||||
}
|
||||
|
||||
auto intParametersXml = xml->createNewChildElement("intParameters");
|
||||
for (auto parameter : intParameters) {
|
||||
auto parameterXml = intParametersXml->createNewChildElement("parameter");
|
||||
parameter->save(parameterXml);
|
||||
}
|
||||
|
||||
copyXmlToBinary(*xml, destData);
|
||||
}
|
||||
|
||||
void SosciAudioProcessor::setStateInformation(const void* data, int sizeInBytes) {
|
||||
std::unique_ptr<juce::XmlElement> xml;
|
||||
|
||||
const uint32_t magicXmlNumber = 0x21324356;
|
||||
if (sizeInBytes > 8 && juce::ByteOrder::littleEndianInt(data) == magicXmlNumber) {
|
||||
// this is a binary xml format
|
||||
xml = getXmlFromBinary(data, sizeInBytes);
|
||||
} else {
|
||||
// this is a text xml format
|
||||
xml = juce::XmlDocument::parse(juce::String((const char*)data, sizeInBytes));
|
||||
}
|
||||
|
||||
if (xml.get() != nullptr && xml->hasTagName("project")) {
|
||||
juce::SpinLock::ScopedLockType lock2(effectsLock);
|
||||
|
||||
auto effectsXml = xml->getChildByName("effects");
|
||||
if (effectsXml != nullptr) {
|
||||
for (auto effectXml : effectsXml->getChildIterator()) {
|
||||
auto effect = getEffect(effectXml->getStringAttribute("id"));
|
||||
if (effect != nullptr) {
|
||||
effect->load(effectXml);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto booleanParametersXml = xml->getChildByName("booleanParameters");
|
||||
if (booleanParametersXml != nullptr) {
|
||||
for (auto parameterXml : booleanParametersXml->getChildIterator()) {
|
||||
auto parameter = getBooleanParameter(parameterXml->getStringAttribute("id"));
|
||||
if (parameter != nullptr) {
|
||||
parameter->load(parameterXml);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto floatParametersXml = xml->getChildByName("floatParameters");
|
||||
if (floatParametersXml != nullptr) {
|
||||
for (auto parameterXml : floatParametersXml->getChildIterator()) {
|
||||
auto parameter = getFloatParameter(parameterXml->getStringAttribute("id"));
|
||||
if (parameter != nullptr) {
|
||||
parameter->load(parameterXml);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto intParametersXml = xml->getChildByName("intParameters");
|
||||
if (intParametersXml != nullptr) {
|
||||
for (auto parameterXml : intParametersXml->getChildIterator()) {
|
||||
auto parameter = getIntParameter(parameterXml->getStringAttribute("id"));
|
||||
if (parameter != nullptr) {
|
||||
parameter->load(parameterXml);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double SosciAudioProcessor::getSampleRate() {
|
||||
return currentSampleRate;
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
// This creates new instances of the plugin..
|
||||
juce::AudioProcessor* JUCE_CALLTYPE createPluginFilter()
|
||||
{
|
||||
return new SosciAudioProcessor();
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file contains the basic framework code for a JUCE plugin processor.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <JuceHeader.h>
|
||||
#include "concurrency/ConsumerManager.h"
|
||||
#include "audio/SampleRateManager.h"
|
||||
#include "components/VisualiserSettings.h"
|
||||
#include "audio/Effect.h"
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
*/
|
||||
class SosciAudioProcessor : public juce::AudioProcessor, public ConsumerManager, public SampleRateManager
|
||||
#if JucePlugin_Enable_ARA
|
||||
, public juce::AudioProcessorARAExtension
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
SosciAudioProcessor();
|
||||
~SosciAudioProcessor() override;
|
||||
|
||||
void prepareToPlay (double sampleRate, int samplesPerBlock) override;
|
||||
void releaseResources() override;
|
||||
|
||||
#ifndef JucePlugin_PreferredChannelConfigurations
|
||||
bool isBusesLayoutSupported (const BusesLayout& layouts) const override;
|
||||
#endif
|
||||
|
||||
void processBlock (juce::AudioBuffer<float>&, juce::MidiBuffer&) override;
|
||||
|
||||
juce::AudioProcessorEditor* createEditor() override;
|
||||
bool hasEditor() const override;
|
||||
|
||||
const juce::String getName() const override;
|
||||
|
||||
void setAudioThreadCallback(std::function<void(const juce::AudioBuffer<float>&)> callback);
|
||||
|
||||
bool acceptsMidi() const override;
|
||||
bool producesMidi() const override;
|
||||
bool isMidiEffect() const override;
|
||||
double getTailLengthSeconds() const override;
|
||||
int getNumPrograms() override;
|
||||
int getCurrentProgram() override;
|
||||
void setCurrentProgram(int index) override;
|
||||
const juce::String getProgramName(int index) override;
|
||||
void changeProgramName(int index, const juce::String& newName) override;
|
||||
void getStateInformation(juce::MemoryBlock& destData) override;
|
||||
void setStateInformation(const void* data, int sizeInBytes) override;
|
||||
double getSampleRate() override;
|
||||
|
||||
std::atomic<double> currentSampleRate = 0.0;
|
||||
juce::SpinLock effectsLock;
|
||||
VisualiserParameters parameters;
|
||||
|
||||
private:
|
||||
juce::SpinLock consumerLock;
|
||||
std::vector<std::shared_ptr<BufferConsumer>> consumers;
|
||||
public:
|
||||
|
||||
// shouldn't be accessed by audio thread, but needs to persist when GUI is closed
|
||||
// so should only be accessed by message thread
|
||||
juce::String currentProjectFile;
|
||||
juce::File lastOpenedDirectory = juce::File::getSpecialLocation(juce::File::userHomeDirectory);
|
||||
|
||||
private:
|
||||
|
||||
std::vector<BooleanParameter*> booleanParameters;
|
||||
std::vector<FloatParameter*> floatParameters;
|
||||
std::vector<IntParameter*> intParameters;
|
||||
std::vector<std::shared_ptr<Effect>> allEffects;
|
||||
std::vector<std::shared_ptr<Effect>> permanentEffects;
|
||||
|
||||
std::shared_ptr<Effect> getEffect(juce::String id);
|
||||
BooleanParameter* getBooleanParameter(juce::String id);
|
||||
FloatParameter* getFloatParameter(juce::String id);
|
||||
IntParameter* getIntParameter(juce::String id);
|
||||
|
||||
//==============================================================================
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SosciAudioProcessor)
|
||||
};
|
|
@ -5,7 +5,7 @@
|
|||
const juce::String CustomEffect::UNIQUE_ID = "6a3580b0-c5fc-4b28-a33e-e26a487f052f";
|
||||
const juce::String CustomEffect::FILE_NAME = "Custom Lua Effect";
|
||||
|
||||
CustomEffect::CustomEffect(std::function<void(int, juce::String, juce::String)> errorCallback, double (&luaValues)[26]) : errorCallback(errorCallback), luaValues(luaValues) {
|
||||
CustomEffect::CustomEffect(std::function<void(int, juce::String, juce::String)> errorCallback, std::atomic<double>* luaValues) : errorCallback(errorCallback), luaValues(luaValues) {
|
||||
vars.isEffect = true;
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,7 @@ Point CustomEffect::apply(int index, Point input, const std::vector<std::atomic<
|
|||
vars.y = y;
|
||||
vars.z = z;
|
||||
|
||||
std::copy(std::begin(luaValues), std::end(luaValues), std::begin(vars.sliders));
|
||||
std::copy(luaValues, luaValues + 26, std::begin(vars.sliders));
|
||||
|
||||
auto result = parser->run(L, vars);
|
||||
if (result.size() >= 2) {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
class CustomEffect : public EffectApplication {
|
||||
public:
|
||||
CustomEffect(std::function<void(int, juce::String, juce::String)> errorCallback, double (&luaValues)[26]);
|
||||
CustomEffect(std::function<void(int, juce::String, juce::String)> errorCallback, std::atomic<double>* luaValues);
|
||||
~CustomEffect();
|
||||
|
||||
// arbitrary UUID
|
||||
|
@ -32,5 +32,5 @@ private:
|
|||
lua_State *L = nullptr;
|
||||
|
||||
LuaVariables vars;
|
||||
double(&luaValues)[26];
|
||||
std::atomic<double>* luaValues;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
class SampleRateManager {
|
||||
public:
|
||||
SampleRateManager() {}
|
||||
~SampleRateManager() {}
|
||||
|
||||
virtual double getSampleRate() = 0;
|
||||
};
|
|
@ -1,7 +1,7 @@
|
|||
#include "EffectComponent.h"
|
||||
#include "../LookAndFeel.h"
|
||||
|
||||
EffectComponent::EffectComponent(OscirenderAudioProcessor& p, Effect& effect, int index) : effect(effect), index(index), audioProcessor(p) {
|
||||
EffectComponent::EffectComponent(Effect& effect, int index) : effect(effect), index(index) {
|
||||
addAndMakeVisible(slider);
|
||||
addChildComponent(lfoSlider);
|
||||
addAndMakeVisible(lfo);
|
||||
|
@ -46,7 +46,7 @@ EffectComponent::EffectComponent(OscirenderAudioProcessor& p, Effect& effect, in
|
|||
setupComponent();
|
||||
}
|
||||
|
||||
EffectComponent::EffectComponent(OscirenderAudioProcessor& p, Effect& effect) : EffectComponent(p, effect, 0) {}
|
||||
EffectComponent::EffectComponent(Effect& effect) : EffectComponent(effect, 0) {}
|
||||
|
||||
void EffectComponent::setupComponent() {
|
||||
EffectParameter* parameter = effect.parameters[index];
|
||||
|
@ -167,11 +167,6 @@ void EffectComponent::parameterGestureChanged(int parameterIndex, bool gestureIs
|
|||
void EffectComponent::handleAsyncUpdate() {
|
||||
setupComponent();
|
||||
getParentComponent()->repaint();
|
||||
juce::SpinLock::ScopedLockType lock1(audioProcessor.parsersLock);
|
||||
juce::SpinLock::ScopedLockType lock2(audioProcessor.effectsLock);
|
||||
if (effect.getId().contains("lua")) {
|
||||
effect.apply();
|
||||
}
|
||||
}
|
||||
|
||||
void EffectComponent::setComponent(std::shared_ptr<juce::Component> component) {
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
#pragma once
|
||||
#include <JuceHeader.h>
|
||||
#include "../PluginProcessor.h"
|
||||
#include "../audio/Effect.h"
|
||||
#include "LabelledTextBox.h"
|
||||
#include "SvgButton.h"
|
||||
|
||||
class EffectComponent : public juce::Component, public juce::AudioProcessorParameter::Listener, juce::AsyncUpdater, public juce::SettableTooltipClient {
|
||||
public:
|
||||
EffectComponent(OscirenderAudioProcessor& p, Effect& effect, int index);
|
||||
EffectComponent(OscirenderAudioProcessor& p, Effect& effect);
|
||||
EffectComponent(Effect& effect, int index);
|
||||
EffectComponent(Effect& effect);
|
||||
~EffectComponent();
|
||||
|
||||
void resized() override;
|
||||
|
@ -89,7 +88,6 @@ private:
|
|||
bool lfoEnabled = true;
|
||||
bool sidechainEnabled = true;
|
||||
std::shared_ptr<juce::Component> component;
|
||||
OscirenderAudioProcessor& audioProcessor;
|
||||
|
||||
std::unique_ptr<SvgButton> sidechainButton;
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ EffectsListComponent::EffectsListComponent(DraggableListBox& lb, AudioEffectList
|
|||
effect(effect), audioProcessor(data.audioProcessor), editor(data.editor) {
|
||||
auto parameters = effect.parameters;
|
||||
for (int i = 0; i < parameters.size(); i++) {
|
||||
std::shared_ptr<EffectComponent> effectComponent = std::make_shared<EffectComponent>(audioProcessor, effect, i);
|
||||
std::shared_ptr<EffectComponent> effectComponent = std::make_shared<EffectComponent>(effect, i);
|
||||
selected.setToggleState(effect.enabled == nullptr || effect.enabled->getValue(), juce::dontSendNotification);
|
||||
// using weak_ptr to avoid circular reference and memory leak
|
||||
std::weak_ptr<EffectComponent> weakEffectComponent = effectComponent;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include "LuaListComponent.h"
|
||||
|
||||
LuaListComponent::LuaListComponent(OscirenderAudioProcessor& p, Effect& effect) {
|
||||
effectComponent = std::make_shared<EffectComponent>(p, effect);
|
||||
effectComponent = std::make_shared<EffectComponent>(effect);
|
||||
|
||||
effectComponent->slider.onValueChange = [this, &effect, &p] {
|
||||
effect.setValue(effectComponent->slider.getValue());
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
#include "../PluginProcessor.h"
|
||||
|
||||
MainMenuBarModel::MainMenuBarModel(OscirenderAudioProcessor& p, OscirenderAudioProcessorEditor& editor) : audioProcessor(p), editor(editor) {
|
||||
audioProcessor.legacyVisualiserEnabled->addListener(this);
|
||||
audioProcessor.visualiserParameters.legacyVisualiserEnabled->addListener(this);
|
||||
}
|
||||
|
||||
MainMenuBarModel::~MainMenuBarModel() {
|
||||
audioProcessor.legacyVisualiserEnabled->removeListener(this);
|
||||
audioProcessor.visualiserParameters.legacyVisualiserEnabled->removeListener(this);
|
||||
}
|
||||
|
||||
void MainMenuBarModel::parameterValueChanged(int parameterIndex, float legacyVisualiserEnabled) {
|
||||
|
@ -36,7 +36,7 @@ juce::PopupMenu MainMenuBarModel::getMenuForIndex(int topLevelMenuIndex, const j
|
|||
menu.addItem(4, "Create New Project");
|
||||
}
|
||||
} else if (topLevelMenuIndex == 1) {
|
||||
menu.addItem(1, "Use Legacy Visualiser", true, audioProcessor.legacyVisualiserEnabled->getBoolValue());
|
||||
menu.addItem(1, "Use Legacy Visualiser", true, audioProcessor.visualiserParameters.legacyVisualiserEnabled->getBoolValue());
|
||||
} else if (topLevelMenuIndex == 2) {
|
||||
menu.addItem(1, "About osci-render");
|
||||
} else if (topLevelMenuIndex == 3) {
|
||||
|
@ -67,7 +67,7 @@ void MainMenuBarModel::menuItemSelected(int menuItemID, int topLevelMenuIndex) {
|
|||
}
|
||||
break;
|
||||
case 1: {
|
||||
audioProcessor.legacyVisualiserEnabled->setBoolValueNotifyingHost(!audioProcessor.legacyVisualiserEnabled->getBoolValue());
|
||||
audioProcessor.visualiserParameters.legacyVisualiserEnabled->setBoolValueNotifyingHost(!audioProcessor.visualiserParameters.legacyVisualiserEnabled->getBoolValue());
|
||||
menuItemsChanged();
|
||||
} break;
|
||||
case 2: {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
#include <JuceHeader.h>
|
||||
#include "../audio/BooleanParameter.h"
|
||||
|
||||
class SvgButton : public juce::DrawableButton, public juce::AudioProcessorParameter::Listener, public juce::AsyncUpdater {
|
||||
public:
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include "../LookAndFeel.h"
|
||||
#include "VisualiserComponent.h"
|
||||
|
||||
VisualiserComponent::VisualiserComponent(OscirenderAudioProcessor& p, VisualiserSettings& settings, VisualiserComponent* parent, bool useOldVisualiser) : settings(settings), backgroundColour(juce::Colours::black), waveformColour(juce::Colour(0xff00ff00)), audioProcessor(p), oldVisualiser(useOldVisualiser), juce::Thread("VisualiserComponent"), parent(parent) {
|
||||
VisualiserComponent::VisualiserComponent(SampleRateManager& sampleRateManager, ConsumerManager& consumerManager, VisualiserSettings& settings, VisualiserComponent* parent, bool useOldVisualiser) : settings(settings), backgroundColour(juce::Colours::black), waveformColour(juce::Colour(0xff00ff00)), sampleRateManager(sampleRateManager), consumerManager(consumerManager), oldVisualiser(useOldVisualiser), juce::Thread("VisualiserComponent"), parent(parent) {
|
||||
resetBuffer();
|
||||
if (!oldVisualiser) {
|
||||
initialiseBrowser();
|
||||
|
@ -12,13 +12,13 @@ VisualiserComponent::VisualiserComponent(OscirenderAudioProcessor& p, Visualiser
|
|||
setMouseCursor(juce::MouseCursor::PointingHandCursor);
|
||||
setWantsKeyboardFocus(true);
|
||||
|
||||
roughness.textBox.setValue(audioProcessor.roughness);
|
||||
roughness.textBox.setValue(settings.parameters.roughness);
|
||||
roughness.textBox.onValueChange = [this]() {
|
||||
audioProcessor.roughness = (int) roughness.textBox.getValue();
|
||||
this->settings.parameters.roughness = (int) roughness.textBox.getValue();
|
||||
};
|
||||
intensity.textBox.setValue(audioProcessor.intensity);
|
||||
intensity.textBox.setValue(settings.parameters.intensity);
|
||||
intensity.textBox.onValueChange = [this]() {
|
||||
audioProcessor.intensity = intensity.textBox.getValue();
|
||||
this->settings.parameters.intensity = intensity.textBox.getValue();
|
||||
};
|
||||
|
||||
if (parent == nullptr) {
|
||||
|
@ -52,7 +52,7 @@ VisualiserComponent::VisualiserComponent(OscirenderAudioProcessor& p, Visualiser
|
|||
VisualiserComponent::~VisualiserComponent() {
|
||||
{
|
||||
juce::CriticalSection::ScopedLockType scope(consumerLock);
|
||||
audioProcessor.consumerStop(consumer);
|
||||
consumerManager.consumerStop(consumer);
|
||||
}
|
||||
stopThread(1000);
|
||||
masterReference.clear();
|
||||
|
@ -127,15 +127,15 @@ void VisualiserComponent::timerCallback() {
|
|||
|
||||
void VisualiserComponent::run() {
|
||||
while (!threadShouldExit()) {
|
||||
if (sampleRate != (int) audioProcessor.currentSampleRate) {
|
||||
if (sampleRate != (int) sampleRateManager.getSampleRate()) {
|
||||
resetBuffer();
|
||||
}
|
||||
|
||||
{
|
||||
juce::CriticalSection::ScopedLockType scope(consumerLock);
|
||||
consumer = audioProcessor.consumerRegister(tempBuffer);
|
||||
consumer = consumerManager.consumerRegister(tempBuffer);
|
||||
}
|
||||
audioProcessor.consumerRead(consumer);
|
||||
consumerManager.consumerRead(consumer);
|
||||
|
||||
setBuffer(tempBuffer);
|
||||
if (!oldVisualiser) {
|
||||
|
@ -153,7 +153,7 @@ void VisualiserComponent::setPaused(bool paused) {
|
|||
} else {
|
||||
{
|
||||
juce::CriticalSection::ScopedLockType scope(consumerLock);
|
||||
audioProcessor.consumerStop(consumer);
|
||||
consumerManager.consumerStop(consumer);
|
||||
}
|
||||
stopTimer();
|
||||
stopThread(1000);
|
||||
|
@ -329,7 +329,7 @@ void VisualiserComponent::initialiseBrowser() {
|
|||
}
|
||||
|
||||
void VisualiserComponent::resetBuffer() {
|
||||
sampleRate = (int) audioProcessor.currentSampleRate;
|
||||
sampleRate = (int) sampleRateManager.getSampleRate();
|
||||
tempBuffer = std::vector<float>(2 * sampleRate * BUFFER_LENGTH_SECS);
|
||||
if (!oldVisualiser && isShowing()) {
|
||||
restartBrowser = true;
|
||||
|
@ -373,7 +373,7 @@ void VisualiserComponent::childChanged() {
|
|||
}
|
||||
|
||||
void VisualiserComponent::popoutWindow() {
|
||||
auto visualiser = new VisualiserComponent(audioProcessor, settings, this, oldVisualiser);
|
||||
auto visualiser = new VisualiserComponent(sampleRateManager, consumerManager, settings, this, oldVisualiser);
|
||||
visualiser->settings.setLookAndFeel(&getLookAndFeel());
|
||||
visualiser->openSettings = openSettings;
|
||||
visualiser->closeSettings = closeSettings;
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
#include <algorithm>
|
||||
#include <JuceHeader.h>
|
||||
#include "../LookAndFeel.h"
|
||||
#include "../concurrency/BufferConsumer.h"
|
||||
#include "../PluginProcessor.h"
|
||||
#include "../concurrency/ConsumerManager.h"
|
||||
#include "../audio/SampleRateManager.h"
|
||||
#include "LabelledTextBox.h"
|
||||
#include "SvgButton.h"
|
||||
#include "VisualiserSettings.h"
|
||||
|
@ -18,7 +18,7 @@ enum class FullScreenMode {
|
|||
class VisualiserWindow;
|
||||
class VisualiserComponent : public juce::Component, public juce::Timer, public juce::Thread, public juce::MouseListener, public juce::SettableTooltipClient, public juce::AsyncUpdater {
|
||||
public:
|
||||
VisualiserComponent(OscirenderAudioProcessor& p, VisualiserSettings& settings, VisualiserComponent* parent = nullptr, bool useOldVisualiser = false);
|
||||
VisualiserComponent(SampleRateManager& sampleRateManager, ConsumerManager& consumerManager, VisualiserSettings& settings, VisualiserComponent* parent = nullptr, bool useOldVisualiser = false);
|
||||
~VisualiserComponent() override;
|
||||
|
||||
std::function<void()> openSettings;
|
||||
|
@ -65,7 +65,8 @@ private:
|
|||
std::vector<float> buffer;
|
||||
std::vector<juce::Line<float>> prevLines;
|
||||
juce::Colour backgroundColour, waveformColour;
|
||||
OscirenderAudioProcessor& audioProcessor;
|
||||
SampleRateManager& sampleRateManager;
|
||||
ConsumerManager& consumerManager;
|
||||
int sampleRate = DEFAULT_SAMPLE_RATE;
|
||||
LabelledTextBox roughness{"Roughness", 1, 8, 1};
|
||||
LabelledTextBox intensity{"Intensity", 0, 1, 0.01};
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include "../PluginEditor.h"
|
||||
|
||||
|
||||
VisualiserSettings::VisualiserSettings(OscirenderAudioProcessor& p) : audioProcessor(p) {
|
||||
VisualiserSettings::VisualiserSettings(VisualiserParameters& parameters) : parameters(parameters) {
|
||||
addAndMakeVisible(brightness);
|
||||
addAndMakeVisible(intensity);
|
||||
addAndMakeVisible(persistence);
|
||||
|
@ -34,12 +34,12 @@ void VisualiserSettings::resized() {
|
|||
|
||||
juce::var VisualiserSettings::getSettings() {
|
||||
auto settings = new juce::DynamicObject();
|
||||
settings->setProperty("brightness", audioProcessor.brightnessEffect->getActualValue() - 2);
|
||||
settings->setProperty("intensity", audioProcessor.intensityEffect->getActualValue() / 100);
|
||||
settings->setProperty("persistence", audioProcessor.persistenceEffect->getActualValue() - 1.33);
|
||||
settings->setProperty("hue", audioProcessor.hueEffect->getActualValue());
|
||||
settings->setProperty("graticule", audioProcessor.graticuleEnabled->getBoolValue());
|
||||
settings->setProperty("smudges", audioProcessor.smudgesEnabled->getBoolValue());
|
||||
settings->setProperty("upsampling", audioProcessor.upsamplingEnabled->getBoolValue());
|
||||
settings->setProperty("brightness", parameters.brightnessEffect->getActualValue() - 2);
|
||||
settings->setProperty("intensity", parameters.intensityEffect->getActualValue() / 100);
|
||||
settings->setProperty("persistence", parameters.persistenceEffect->getActualValue() - 1.33);
|
||||
settings->setProperty("hue", parameters.hueEffect->getActualValue());
|
||||
settings->setProperty("graticule", parameters.graticuleEnabled->getBoolValue());
|
||||
settings->setProperty("smudges", parameters.smudgesEnabled->getBoolValue());
|
||||
settings->setProperty("upsampling", parameters.upsamplingEnabled->getBoolValue());
|
||||
return juce::var(settings);
|
||||
}
|
||||
|
|
|
@ -1,29 +1,77 @@
|
|||
#pragma once
|
||||
|
||||
#define VERSION_HINT 2
|
||||
|
||||
#include <JuceHeader.h>
|
||||
#include "EffectComponent.h"
|
||||
#include "SvgButton.h"
|
||||
#include "../LookAndFeel.h"
|
||||
#include "SwitchButton.h"
|
||||
|
||||
class VisualiserParameters {
|
||||
public:
|
||||
std::atomic<int> roughness = 4;
|
||||
std::atomic<double> intensity = 1.0;
|
||||
|
||||
BooleanParameter* graticuleEnabled = new BooleanParameter("Show Graticule", "graticuleEnabled", VERSION_HINT, true, "Show the graticule or grid lines over the oscilloscope display.");
|
||||
BooleanParameter* smudgesEnabled = new BooleanParameter("Show Smudges", "smudgesEnabled", VERSION_HINT, true, "Adds a subtle layer of dirt/smudges to the oscilloscope display to make it look more realistic.");
|
||||
BooleanParameter* upsamplingEnabled = new BooleanParameter("Upsample Audio", "upsamplingEnabled", VERSION_HINT, false, "Upsamples the audio before visualising it to make it appear more realistic, at the expense of performance.");
|
||||
BooleanParameter* legacyVisualiserEnabled = new BooleanParameter("Use Legacy Visualiser", "legacyVisualiserEnabled", VERSION_HINT, false, "Replaces the realistic oscilloscope visualiser with the legacy visualiser. This may improve performance.");
|
||||
BooleanParameter* visualiserFullScreen = new BooleanParameter("Visualiser Fullscreen", "visualiserFullScreen", VERSION_HINT, false, "Makes the software visualiser fullscreen.");
|
||||
|
||||
std::shared_ptr<Effect> persistenceEffect = std::make_shared<Effect>(
|
||||
new EffectParameter(
|
||||
"Persistence",
|
||||
"Controls how long the light glows for on the oscilloscope display.",
|
||||
"persistence",
|
||||
VERSION_HINT, 0.5, 0, 6.0
|
||||
)
|
||||
);
|
||||
std::shared_ptr<Effect> hueEffect = std::make_shared<Effect>(
|
||||
new EffectParameter(
|
||||
"Hue",
|
||||
"Controls the hue/colour of the oscilloscope display.",
|
||||
"hue",
|
||||
VERSION_HINT, 125, 0, 359, 1
|
||||
)
|
||||
);
|
||||
std::shared_ptr<Effect> brightnessEffect = std::make_shared<Effect>(
|
||||
new EffectParameter(
|
||||
"Brightness",
|
||||
"Controls how bright the light glows for on the oscilloscope display.",
|
||||
"brightness",
|
||||
VERSION_HINT, 3.0, 0.0, 10.0
|
||||
)
|
||||
);
|
||||
std::shared_ptr<Effect> intensityEffect = std::make_shared<Effect>(
|
||||
new EffectParameter(
|
||||
"Intensity",
|
||||
"Controls how bright the electron beam of the oscilloscope is.",
|
||||
"intensity",
|
||||
VERSION_HINT, 3.0, 0.0, 10.0
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
class VisualiserSettings : public juce::Component {
|
||||
public:
|
||||
VisualiserSettings(OscirenderAudioProcessor&);
|
||||
VisualiserSettings(VisualiserParameters&);
|
||||
~VisualiserSettings();
|
||||
|
||||
void resized() override;
|
||||
juce::var getSettings();
|
||||
private:
|
||||
OscirenderAudioProcessor& audioProcessor;
|
||||
|
||||
EffectComponent brightness{audioProcessor, *audioProcessor.brightnessEffect};
|
||||
EffectComponent intensity{audioProcessor, *audioProcessor.intensityEffect};
|
||||
EffectComponent persistence{audioProcessor, *audioProcessor.persistenceEffect};
|
||||
EffectComponent hue{audioProcessor, *audioProcessor.hueEffect};
|
||||
VisualiserParameters& parameters;
|
||||
|
||||
private:
|
||||
EffectComponent brightness{*parameters.brightnessEffect};
|
||||
EffectComponent intensity{*parameters.intensityEffect};
|
||||
EffectComponent persistence{*parameters.persistenceEffect};
|
||||
EffectComponent hue{*parameters.hueEffect};
|
||||
|
||||
jux::SwitchButton graticuleToggle{audioProcessor.graticuleEnabled};
|
||||
jux::SwitchButton smudgeToggle{audioProcessor.smudgesEnabled};
|
||||
jux::SwitchButton upsamplingToggle{audioProcessor.upsamplingEnabled};
|
||||
jux::SwitchButton graticuleToggle{parameters.graticuleEnabled};
|
||||
jux::SwitchButton smudgeToggle{parameters.smudgesEnabled};
|
||||
jux::SwitchButton upsamplingToggle{parameters.upsamplingEnabled};
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(VisualiserSettings)
|
||||
};
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
#pragma once
|
||||
|
||||
#include <JuceHeader.h>
|
||||
#include "BufferConsumer.h"
|
||||
|
||||
|
||||
class ConsumerManager {
|
||||
public:
|
||||
ConsumerManager() {}
|
||||
~ConsumerManager() {}
|
||||
|
||||
std::shared_ptr<BufferConsumer> consumerRegister(std::vector<float>& buffer) {
|
||||
std::shared_ptr<BufferConsumer> consumer = std::make_shared<BufferConsumer>(buffer);
|
||||
juce::SpinLock::ScopedLockType scope(consumerLock);
|
||||
consumers.push_back(consumer);
|
||||
|
||||
return consumer;
|
||||
}
|
||||
|
||||
void consumerRead(std::shared_ptr<BufferConsumer> consumer) {
|
||||
consumer->waitUntilFull();
|
||||
juce::SpinLock::ScopedLockType scope(consumerLock);
|
||||
consumers.erase(std::remove(consumers.begin(), consumers.end(), consumer), consumers.end());
|
||||
}
|
||||
|
||||
void consumerStop(std::shared_ptr<BufferConsumer> consumer) {
|
||||
if (consumer != nullptr) {
|
||||
juce::SpinLock::ScopedLockType scope(consumerLock);
|
||||
consumer->forceNotify();
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
juce::SpinLock consumerLock;
|
||||
std::vector<std::shared_ptr<BufferConsumer>> consumers;
|
||||
};
|
|
@ -100,6 +100,8 @@
|
|||
<FILE id="rQC2gX" name="PitchDetector.h" compile="0" resource="0" file="Source/audio/PitchDetector.h"/>
|
||||
<FILE id="t5g8pf" name="PublicSynthesiser.h" compile="0" resource="0"
|
||||
file="Source/audio/PublicSynthesiser.h"/>
|
||||
<FILE id="Q5kjpU" name="SampleRateManager.h" compile="0" resource="0"
|
||||
file="Source/audio/SampleRateManager.h"/>
|
||||
<FILE id="dBaZAV" name="ShapeSound.cpp" compile="1" resource="0" file="Source/audio/ShapeSound.cpp"/>
|
||||
<FILE id="VKBirB" name="ShapeSound.h" compile="0" resource="0" file="Source/audio/ShapeSound.h"/>
|
||||
<FILE id="UcPZ09" name="ShapeVoice.cpp" compile="1" resource="0" file="Source/audio/ShapeVoice.cpp"/>
|
||||
|
@ -188,6 +190,8 @@
|
|||
<FILE id="F5kUMH" name="BlockingQueue.h" compile="0" resource="0" file="Source/concurrency/BlockingQueue.h"/>
|
||||
<FILE id="WQ2W15" name="BufferConsumer.h" compile="0" resource="0"
|
||||
file="Source/concurrency/BufferConsumer.h"/>
|
||||
<FILE id="VMSdiT" name="ConsumerManager.h" compile="0" resource="0"
|
||||
file="Source/concurrency/ConsumerManager.h"/>
|
||||
</GROUP>
|
||||
<GROUP id="{A3E24187-62A5-AB8D-8837-14043B89A640}" name="gpla">
|
||||
<FILE id="KvDV8j" name="LineArtParser.cpp" compile="1" resource="0"
|
||||
|
@ -658,9 +662,9 @@
|
|||
</LINUX_MAKE>
|
||||
<VS2022 targetFolder="Builds/VisualStudio2022" smallIcon="pSc1mq" bigIcon="pSc1mq">
|
||||
<CONFIGURATIONS>
|
||||
<CONFIGURATION isDebug="1" name="Debug" targetName="osci-render" useRuntimeLibDLL="0"/>
|
||||
<CONFIGURATION isDebug="1" name="Debug" targetName="osci-render"/>
|
||||
<CONFIGURATION isDebug="0" name="Release" targetName="osci-render" alwaysGenerateDebugSymbols="1"
|
||||
debugInformationFormat="ProgramDatabase" useRuntimeLibDLL="0"/>
|
||||
debugInformationFormat="ProgramDatabase"/>
|
||||
</CONFIGURATIONS>
|
||||
<MODULEPATHS>
|
||||
<MODULEPATH id="juce_audio_basics" path="../../../JUCE/modules"/>
|
||||
|
|
|
@ -0,0 +1,197 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<JUCERPROJECT id="HH2E72" name="sosci" projectType="audioplug" useAppConfig="0"
|
||||
addUsingNamespaceToJuceHeader="0" jucerFormatVersion="1" pluginManufacturer="jameshball"
|
||||
aaxIdentifier="sh.ball.sosci" cppLanguageStandard="20" projectLineFeed=" "
|
||||
headerPath="./include" version="1.0.0" companyName="James H Ball"
|
||||
companyWebsite="https://osci-render.com" companyEmail="james@ball.sh"
|
||||
defines="NOMINMAX=1" pluginAUMainType="'aumf'" binaryDataNamespace="SosciBinaryData">
|
||||
<MAINGROUP id="j5Ge2T" name="sosci">
|
||||
<GROUP id="{5ABCED88-0059-A7AF-9596-DBF91DDB0292}" name="Resources">
|
||||
<GROUP id="{525C568C-29E9-D0A2-9773-8A04981C5575}" name="images">
|
||||
<FILE id="jI9VSZ" name="logo.png" compile="0" resource="1" file="Resources/images/logo.png"/>
|
||||
</GROUP>
|
||||
<GROUP id="{F3C16D02-63B4-E3DA-7498-901173C37D6C}" name="oscilloscope">
|
||||
<GROUP id="{DD5ACF8F-4E4F-E277-176A-5FD4A9717037}" name="juce">
|
||||
<FILE id="FCfppP" name="check_native_interop.js" compile="0" resource="1"
|
||||
file="Resources/oscilloscope/juce/check_native_interop.js"/>
|
||||
<FILE id="ZEUE5w" name="index.js" compile="0" resource="1" file="Resources/oscilloscope/juce/index.js"/>
|
||||
<FILE id="hWk293" name="package.json" compile="0" resource="1" file="Resources/oscilloscope/juce/package.json"/>
|
||||
</GROUP>
|
||||
<FILE id="qpPhpN" name="empty.jpg" compile="0" resource="1" file="Resources/oscilloscope/empty.jpg"/>
|
||||
<FILE id="dNtZYs" name="noise.jpg" compile="0" resource="1" file="Resources/oscilloscope/noise.jpg"/>
|
||||
<FILE id="YPMnjq" name="oscilloscope.html" compile="0" resource="1"
|
||||
file="Resources/oscilloscope/oscilloscope.html"/>
|
||||
<FILE id="BeXHj7" name="oscilloscope.js" compile="0" resource="1" file="Resources/oscilloscope/oscilloscope.js"/>
|
||||
</GROUP>
|
||||
<GROUP id="{82BCD6F1-A8BF-F30B-5587-81EE70168883}" name="svg">
|
||||
<FILE id="rl17ZK" name="cog.svg" compile="0" resource="1" file="Resources/svg/cog.svg"/>
|
||||
<FILE id="sDajXu" name="delete.svg" compile="0" resource="1" file="Resources/svg/delete.svg"/>
|
||||
<FILE id="IqXIZW" name="demo.svg" compile="0" resource="1" file="Resources/svg/demo.svg"/>
|
||||
<FILE id="YwkQpy" name="fixed_rotate.svg" compile="0" resource="1"
|
||||
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="PxYKbt" name="microphone.svg" compile="0" resource="1" file="Resources/svg/microphone.svg"/>
|
||||
<FILE id="hJHxFY" name="open_in_new.svg" compile="0" resource="1" file="Resources/svg/open_in_new.svg"/>
|
||||
<FILE id="pSc1mq" name="osci.svg" compile="0" resource="1" file="Resources/svg/osci.svg"/>
|
||||
<FILE id="f2D5tv" name="pause.svg" compile="0" resource="1" file="Resources/svg/pause.svg"/>
|
||||
<FILE id="D2AI1b" name="pencil.svg" compile="0" resource="1" file="Resources/svg/pencil.svg"/>
|
||||
<FILE id="PFc2q2" name="random.svg" compile="0" resource="1" file="Resources/svg/random.svg"/>
|
||||
<FILE id="CE6di2" name="range.svg" compile="0" resource="1" file="Resources/svg/range.svg"/>
|
||||
<FILE id="n79IAy" name="record.svg" compile="0" resource="1" file="Resources/svg/record.svg"/>
|
||||
<FILE id="OaqZb1" name="right_arrow.svg" compile="0" resource="1" file="Resources/svg/right_arrow.svg"/>
|
||||
<FILE id="rXjNlx" name="threshold.svg" compile="0" resource="1" file="Resources/svg/threshold.svg"/>
|
||||
<FILE id="rFYmV8" name="timer.svg" compile="0" resource="1" file="Resources/svg/timer.svg"/>
|
||||
<FILE id="qC6QiP" name="volume.svg" compile="0" resource="1" file="Resources/svg/volume.svg"/>
|
||||
</GROUP>
|
||||
</GROUP>
|
||||
<GROUP id="{75439074-E50C-362F-1EDF-8B4BE9011259}" name="Source">
|
||||
<GROUP id="{85A33213-D880-BD92-70D8-1901DA6D23F0}" name="audio">
|
||||
<FILE id="S5ChqG" name="BooleanParameter.h" compile="0" resource="0"
|
||||
file="Source/audio/BooleanParameter.h"/>
|
||||
<FILE id="mP5lpY" name="Effect.cpp" compile="1" resource="0" file="Source/audio/Effect.cpp"/>
|
||||
<FILE id="LKeNnY" name="Effect.h" compile="0" resource="0" file="Source/audio/Effect.h"/>
|
||||
<FILE id="ca2VrC" name="EffectApplication.cpp" compile="1" resource="0"
|
||||
file="Source/audio/EffectApplication.cpp"/>
|
||||
<FILE id="MIYJ9y" name="EffectApplication.h" compile="0" resource="0"
|
||||
file="Source/audio/EffectApplication.h"/>
|
||||
<FILE id="aE0RtD" name="EffectParameter.h" compile="0" resource="0"
|
||||
file="Source/audio/EffectParameter.h"/>
|
||||
<FILE id="aziWU2" name="SampleRateManager.h" compile="0" resource="0"
|
||||
file="Source/audio/SampleRateManager.h"/>
|
||||
</GROUP>
|
||||
<GROUP id="{CD81913A-7F0E-5898-DA77-5EBEB369DEB1}" name="components">
|
||||
<FILE id="xLAEHK" name="EffectComponent.cpp" compile="1" resource="0"
|
||||
file="Source/components/EffectComponent.cpp"/>
|
||||
<FILE id="u4UCwb" name="EffectComponent.h" compile="0" resource="0"
|
||||
file="Source/components/EffectComponent.h"/>
|
||||
<FILE id="qzfstC" name="SwitchButton.h" compile="0" resource="0" file="Source/components/SwitchButton.h"/>
|
||||
<FILE id="y3UiR0" name="VisualiserComponent.cpp" compile="1" resource="0"
|
||||
file="Source/components/VisualiserComponent.cpp"/>
|
||||
<FILE id="ZueyNl" name="VisualiserComponent.h" compile="0" resource="0"
|
||||
file="Source/components/VisualiserComponent.h"/>
|
||||
<FILE id="uOtHbQ" name="VisualiserSettings.cpp" compile="1" resource="0"
|
||||
file="Source/components/VisualiserSettings.cpp"/>
|
||||
<FILE id="GcbeeZ" name="VisualiserSettings.h" compile="0" resource="0"
|
||||
file="Source/components/VisualiserSettings.h"/>
|
||||
</GROUP>
|
||||
<GROUP id="{9F5970A9-8094-E7F3-7AC1-812AE5589B9F}" name="concurrency">
|
||||
<FILE id="F5kUMH" name="BlockingQueue.h" compile="0" resource="0" file="Source/concurrency/BlockingQueue.h"/>
|
||||
<FILE id="WQ2W15" name="BufferConsumer.h" compile="0" resource="0"
|
||||
file="Source/concurrency/BufferConsumer.h"/>
|
||||
<FILE id="HIYtj5" name="ConsumerManager.h" compile="0" resource="0"
|
||||
file="Source/concurrency/ConsumerManager.h"/>
|
||||
</GROUP>
|
||||
<GROUP id="{92CEA658-C82C-9CEB-15EB-945EF6B6B5C8}" name="shape">
|
||||
<FILE id="G5fbub" name="Shape.cpp" compile="1" resource="0" file="Source/shape/Shape.cpp"/>
|
||||
<FILE id="nUpro8" name="Point.cpp" compile="1" resource="0" file="Source/shape/Point.cpp"/>
|
||||
<FILE id="X6A0jk" name="Point.h" compile="0" resource="0" file="Source/shape/Point.h"/>
|
||||
<FILE id="NmptSY" name="Shape.h" compile="0" resource="0" file="Source/shape/Shape.h"/>
|
||||
</GROUP>
|
||||
<FILE id="d2zFqF" name="LookAndFeel.cpp" compile="1" resource="0" file="Source/LookAndFeel.cpp"/>
|
||||
<FILE id="TJDqWs" name="LookAndFeel.h" compile="0" resource="0" file="Source/LookAndFeel.h"/>
|
||||
<FILE id="ajg1QS" name="SosciPluginEditor.cpp" compile="1" resource="0"
|
||||
file="Source/SosciPluginEditor.cpp"/>
|
||||
<FILE id="SgIFr0" name="SosciPluginEditor.h" compile="0" resource="0"
|
||||
file="Source/SosciPluginEditor.h"/>
|
||||
<FILE id="uSfvvP" name="SosciPluginProcessor.cpp" compile="1" resource="0"
|
||||
file="Source/SosciPluginProcessor.cpp"/>
|
||||
<FILE id="nSDgxn" name="SosciPluginProcessor.h" compile="0" resource="0"
|
||||
file="Source/SosciPluginProcessor.h"/>
|
||||
</GROUP>
|
||||
</MAINGROUP>
|
||||
<JUCEOPTIONS JUCE_STRICT_REFCOUNTEDPOINTER="1" JUCE_VST3_CAN_REPLACE_VST2="0"
|
||||
JUCE_WIN_PER_MONITOR_DPI_AWARE="0" JUCE_USE_WIN_WEBVIEW2_WITH_STATIC_LINKING="1"
|
||||
JUCE_USE_WIN_WEBVIEW2="1"/>
|
||||
<EXPORTFORMATS>
|
||||
<LINUX_MAKE targetFolder="Builds/sosci/LinuxMakefile" smallIcon="pSc1mq"
|
||||
bigIcon="pSc1mq">
|
||||
<CONFIGURATIONS>
|
||||
<CONFIGURATION isDebug="1" name="Debug" targetName="osci-render"/>
|
||||
<CONFIGURATION isDebug="0" name="Release" targetName="osci-render"/>
|
||||
</CONFIGURATIONS>
|
||||
<MODULEPATHS>
|
||||
<MODULEPATH id="juce_audio_basics" path="../../../JUCE/modules"/>
|
||||
<MODULEPATH id="juce_audio_devices" path="../../../JUCE/modules"/>
|
||||
<MODULEPATH id="juce_audio_formats" path="../../../JUCE/modules"/>
|
||||
<MODULEPATH id="juce_audio_plugin_client" path="../../../JUCE/modules"/>
|
||||
<MODULEPATH id="juce_audio_processors" path="../../../JUCE/modules"/>
|
||||
<MODULEPATH id="juce_audio_utils" path="../../../JUCE/modules"/>
|
||||
<MODULEPATH id="juce_core" path="../../../JUCE/modules"/>
|
||||
<MODULEPATH id="juce_data_structures" path="../../../JUCE/modules"/>
|
||||
<MODULEPATH id="juce_events" path="../../../JUCE/modules"/>
|
||||
<MODULEPATH id="juce_graphics" path="../../../JUCE/modules"/>
|
||||
<MODULEPATH id="juce_gui_basics" path="../../../JUCE/modules"/>
|
||||
<MODULEPATH id="juce_gui_extra" path="../../../JUCE/modules"/>
|
||||
<MODULEPATH id="juce_opengl" path="../../../JUCE/modules"/>
|
||||
<MODULEPATH id="juce_dsp" path="../../JUCE/modules"/>
|
||||
</MODULEPATHS>
|
||||
</LINUX_MAKE>
|
||||
<VS2022 targetFolder="Builds/sosci/VisualStudio2022" smallIcon="pSc1mq"
|
||||
bigIcon="pSc1mq">
|
||||
<CONFIGURATIONS>
|
||||
<CONFIGURATION isDebug="1" name="Debug" targetName="osci-render"/>
|
||||
<CONFIGURATION isDebug="0" name="Release" targetName="osci-render" alwaysGenerateDebugSymbols="1"
|
||||
debugInformationFormat="ProgramDatabase"/>
|
||||
</CONFIGURATIONS>
|
||||
<MODULEPATHS>
|
||||
<MODULEPATH id="juce_audio_basics" path="../../../JUCE/modules"/>
|
||||
<MODULEPATH id="juce_audio_devices" path="../../../JUCE/modules"/>
|
||||
<MODULEPATH id="juce_audio_formats" path="../../../JUCE/modules"/>
|
||||
<MODULEPATH id="juce_audio_plugin_client" path="../../../JUCE/modules"/>
|
||||
<MODULEPATH id="juce_audio_processors" path="../../../JUCE/modules"/>
|
||||
<MODULEPATH id="juce_audio_utils" path="../../../JUCE/modules"/>
|
||||
<MODULEPATH id="juce_core" path="../../../JUCE/modules"/>
|
||||
<MODULEPATH id="juce_data_structures" path="../../../JUCE/modules"/>
|
||||
<MODULEPATH id="juce_events" path="../../../JUCE/modules"/>
|
||||
<MODULEPATH id="juce_graphics" path="../../../JUCE/modules"/>
|
||||
<MODULEPATH id="juce_gui_basics" path="../../../JUCE/modules"/>
|
||||
<MODULEPATH id="juce_gui_extra" path="../../../JUCE/modules"/>
|
||||
<MODULEPATH id="juce_opengl" path="../../../JUCE/modules"/>
|
||||
<MODULEPATH id="juce_dsp" path="../../JUCE/modules"/>
|
||||
</MODULEPATHS>
|
||||
</VS2022>
|
||||
<XCODE_MAC targetFolder="Builds/sosci/MacOSX" extraLinkerFlags="-Wl,-weak_reference_mismatches,weak"
|
||||
extraDefs="JUCE_SILENCE_XCODE_15_LINKER_WARNING=1" smallIcon="pSc1mq"
|
||||
bigIcon="pSc1mq" applicationCategory="public.app-category.music">
|
||||
<CONFIGURATIONS>
|
||||
<CONFIGURATION isDebug="1" name="Debug" targetName="osci-render"/>
|
||||
<CONFIGURATION name="Release" targetName="osci-render"/>
|
||||
</CONFIGURATIONS>
|
||||
<MODULEPATHS>
|
||||
<MODULEPATH id="juce_audio_basics" path="../../../JUCE/modules"/>
|
||||
<MODULEPATH id="juce_audio_devices" path="../../../JUCE/modules"/>
|
||||
<MODULEPATH id="juce_audio_formats" path="../../../JUCE/modules"/>
|
||||
<MODULEPATH id="juce_audio_plugin_client" path="../../../JUCE/modules"/>
|
||||
<MODULEPATH id="juce_audio_processors" path="../../../JUCE/modules"/>
|
||||
<MODULEPATH id="juce_audio_utils" path="../../../JUCE/modules"/>
|
||||
<MODULEPATH id="juce_core" path="../../../JUCE/modules"/>
|
||||
<MODULEPATH id="juce_data_structures" path="../../../JUCE/modules"/>
|
||||
<MODULEPATH id="juce_events" path="../../../JUCE/modules"/>
|
||||
<MODULEPATH id="juce_graphics" path="../../../JUCE/modules"/>
|
||||
<MODULEPATH id="juce_gui_basics" path="../../../JUCE/modules"/>
|
||||
<MODULEPATH id="juce_gui_extra" path="../../../JUCE/modules"/>
|
||||
<MODULEPATH id="juce_opengl" path="../../../JUCE/modules"/>
|
||||
<MODULEPATH id="juce_dsp" path="../../JUCE/modules"/>
|
||||
</MODULEPATHS>
|
||||
</XCODE_MAC>
|
||||
</EXPORTFORMATS>
|
||||
<MODULES>
|
||||
<MODULE id="juce_audio_basics" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
|
||||
<MODULE id="juce_audio_devices" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
|
||||
<MODULE id="juce_audio_formats" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
|
||||
<MODULE id="juce_audio_plugin_client" showAllCode="1" useLocalCopy="0"
|
||||
useGlobalPath="1"/>
|
||||
<MODULE id="juce_audio_processors" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
|
||||
<MODULE id="juce_audio_utils" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
|
||||
<MODULE id="juce_core" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
|
||||
<MODULE id="juce_data_structures" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
|
||||
<MODULE id="juce_dsp" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
|
||||
<MODULE id="juce_events" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
|
||||
<MODULE id="juce_graphics" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
|
||||
<MODULE id="juce_gui_basics" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
|
||||
<MODULE id="juce_gui_extra" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
|
||||
<MODULE id="juce_opengl" showAllCode="1" useLocalCopy="0" useGlobalPath="1"/>
|
||||
</MODULES>
|
||||
</JUCERPROJECT>
|
Ładowanie…
Reference in New Issue