Add drop-down for screen type, remove brightness slider, add ambient light slider, add real oscilloscope display

pre-release-3
James H Ball 2024-12-26 23:00:52 +00:00
rodzic 330381f559
commit 12c755c697
12 zmienionych plików z 164 dodań i 62 usunięć

2
.gitignore vendored
Wyświetl plik

@ -5,6 +5,8 @@
.DS_Store .DS_Store
*.psd
# ignore JUCE # ignore JUCE
**/Builds **/Builds
**/JuceLibraryCode **/JuceLibraryCode

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 79 KiB

Wyświetl plik

@ -47,9 +47,9 @@ CommonPluginEditor::CommonPluginEditor(CommonAudioProcessor& p, juce::String app
}; };
visualiserSettings.setLookAndFeel(&getLookAndFeel()); visualiserSettings.setLookAndFeel(&getLookAndFeel());
visualiserSettings.setSize(550, 400); visualiserSettings.setSize(550, 450);
visualiserSettingsWindow.setContentNonOwned(&visualiserSettings, true); visualiserSettingsWindow.setContentNonOwned(&visualiserSettings, true);
visualiserSettingsWindow.centreWithSize(550, 400); visualiserSettingsWindow.centreWithSize(550, 450);
#if JUCE_WINDOWS #if JUCE_WINDOWS
// if not standalone, use native title bar for compatibility with DAWs // if not standalone, use native title bar for compatibility with DAWs
visualiserSettingsWindow.setUsingNativeTitleBar(processor.wrapperType == juce::AudioProcessor::WrapperType::wrapperType_Standalone); visualiserSettingsWindow.setUsingNativeTitleBar(processor.wrapperType == juce::AudioProcessor::WrapperType::wrapperType_Standalone);

Wyświetl plik

@ -30,6 +30,10 @@ CommonAudioProcessor::CommonAudioProcessor()
for (auto parameter : visualiserParameters.booleans) { for (auto parameter : visualiserParameters.booleans) {
booleanParameters.push_back(parameter); booleanParameters.push_back(parameter);
} }
for (auto parameter : visualiserParameters.integers) {
intParameters.push_back(parameter);
}
} }
void CommonAudioProcessor::addAllParameters() { void CommonAudioProcessor::addAllParameters() {

Wyświetl plik

@ -128,7 +128,7 @@ public:
std::shared_ptr<Effect> perspective = std::make_shared<Effect>( std::shared_ptr<Effect> perspective = std::make_shared<Effect>(
perspectiveEffect, perspectiveEffect,
std::vector<EffectParameter*>{ std::vector<EffectParameter*>{
new EffectParameter("3D Perspective", "Controls the strength of the 3D perspective projection.", "perspectiveStrength", VERSION_HINT, 1.0, 0.0, 1.0), new EffectParameter("Perspective", "Controls the strength of the 3D perspective projection.", "perspectiveStrength", VERSION_HINT, 1.0, 0.0, 1.0),
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), 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),
} }
); );

Wyświetl plik

@ -7,6 +7,8 @@ std::string lineFragmentShader = R"(
uniform float uSize; uniform float uSize;
uniform float uIntensity; uniform float uIntensity;
uniform float uOffset;
uniform float uScale;
uniform sampler2D uScreen; uniform sampler2D uScreen;
varying float vSize; varying float vSize;
varying vec4 uvl; varying vec4 uvl;
@ -27,6 +29,7 @@ float erf(float x) {
void main() { void main() {
vec2 texCoord = (vTexCoord - 0.5) / uScale + 0.5 + uOffset;
float len = uvl.z; float len = uvl.z;
vec2 xy = uvl.xy; vec2 xy = uvl.xy;
float brightness; float brightness;
@ -42,7 +45,7 @@ void main() {
} }
brightness *= uvl.w; brightness *= uvl.w;
gl_FragColor = 2.0 * texture2D(uScreen, vTexCoord) * brightness; gl_FragColor = 2.0 * texture2D(uScreen, texCoord) * brightness;
gl_FragColor.a = 1.0; gl_FragColor.a = 1.0;
} }

Wyświetl plik

@ -9,6 +9,10 @@ uniform float uSaturation;
uniform float uNoise; uniform float uNoise;
uniform float uTime; uniform float uTime;
uniform float uGlow; uniform float uGlow;
uniform float uAmbient;
uniform float uRealScreen;
uniform vec2 uOffset;
uniform vec2 uScale;
uniform vec3 uColour; uniform vec3 uColour;
varying vec2 vTexCoord; varying vec2 vTexCoord;
varying vec2 vTexCoordCanvas; varying vec2 vTexCoordCanvas;
@ -24,16 +28,21 @@ float noise(in vec2 uv, in float time) {
} }
void main() { void main() {
vec4 line = texture2D(uTexture0, vTexCoordCanvas); vec2 linePos = (vTexCoordCanvas - 0.5) / uScale + 0.5 + uOffset;
vec4 line = texture2D(uTexture0, linePos);
// r components have grid; g components do not. // r components have grid; g components do not.
vec4 screen = texture2D(uTexture3, vTexCoord); vec4 screen = texture2D(uTexture3, vTexCoord);
vec4 tightGlow = texture2D(uTexture1, vTexCoord); vec4 tightGlow = texture2D(uTexture1, linePos);
vec4 scatter = texture2D(uTexture2, vTexCoord)+0.35; vec4 scatter = texture2D(uTexture2, linePos) + (1.0 - uRealScreen) * max(uAmbient - 0.45, 0.0);
float light = line.r + uGlow * 1.5 * screen.g * screen.g * tightGlow.r; float light = line.r + uGlow * 1.5 * screen.g * screen.g * tightGlow.r;
light += uGlow * 0.3 * scatter.g * (2.0 + 1.0 * screen.g + 0.5 * screen.r); light += uGlow * 0.3 * scatter.g * (2.0 + 1.0 * screen.g + 0.5 * screen.r);
float tlight = 1.0-pow(2.0, -uExposure*light); float tlight = 1.0-pow(2.0, -uExposure*light);
float tlight2 = tlight * tlight * tlight; float tlight2 = tlight * tlight * tlight;
gl_FragColor.rgb = mix(uColour, vec3(1.0), 0.3+tlight2*tlight2*0.5)*tlight; gl_FragColor.rgb = mix(uColour, vec3(1.0), 0.3+tlight2*tlight2*0.5) * tlight;
if (uRealScreen > 0.5) {
float ambient = pow(2.0, uExposure) * uAmbient;
gl_FragColor.rgb += ambient * screen.rgb;
}
gl_FragColor.rgb = desaturate(gl_FragColor.rgb, 1.0 - uSaturation); gl_FragColor.rgb = desaturate(gl_FragColor.rgb, 1.0 - uSaturation);
gl_FragColor.rgb += uNoise * noise(gl_FragCoord.xy, uTime); gl_FragColor.rgb += uNoise * noise(gl_FragCoord.xy, uTime);
gl_FragColor.a = 1.0; gl_FragColor.a = 1.0;

Wyświetl plik

@ -289,25 +289,26 @@ void VisualiserComponent::setRecording(bool recording) {
void VisualiserComponent::resized() { void VisualiserComponent::resized() {
auto area = getLocalBounds(); auto area = getLocalBounds();
buttonRow = area.removeFromBottom(25); buttonRow = area.removeFromBottom(25);
auto buttons = buttonRow;
if (parent == nullptr && !visualiserOnly) { if (parent == nullptr && !visualiserOnly) {
fullScreenButton.setBounds(buttonRow.removeFromRight(30)); fullScreenButton.setBounds(buttons.removeFromRight(30));
} }
if (child == nullptr && parent == nullptr && !visualiserOnly) { if (child == nullptr && parent == nullptr && !visualiserOnly) {
popOutButton.setBounds(buttonRow.removeFromRight(30)); popOutButton.setBounds(buttons.removeFromRight(30));
} }
settingsButton.setBounds(buttonRow.removeFromRight(30)); settingsButton.setBounds(buttons.removeFromRight(30));
//if (visualiserOnly) { //if (visualiserOnly) {
sharedTextureButton.setBounds(buttonRow.removeFromRight(30)); sharedTextureButton.setBounds(buttons.removeFromRight(30));
//} //}
record.setBounds(buttonRow.removeFromRight(25)); record.setBounds(buttons.removeFromRight(25));
if (record.getToggleState()) { if (record.getToggleState()) {
stopwatch.setVisible(true); stopwatch.setVisible(true);
stopwatch.setBounds(buttonRow.removeFromRight(100)); stopwatch.setBounds(buttons.removeFromRight(100));
} else { } else {
stopwatch.setVisible(false); stopwatch.setVisible(false);
} }
if (child == nullptr) { if (child == nullptr) {
auto bounds = buttonRow.removeFromRight(160); auto bounds = buttons.removeFromRight(160);
ffmpegDownloader.setBounds(bounds.withSizeKeepingCentre(bounds.getWidth() - 10, bounds.getHeight() - 10)); ffmpegDownloader.setBounds(bounds.withSizeKeepingCentre(bounds.getWidth() - 10, bounds.getHeight() - 10));
} }
viewportArea = area; viewportArea = area;
@ -377,7 +378,6 @@ void VisualiserComponent::newOpenGLContextCreated() {
juce::CriticalSection::ScopedLockType lock(samplesLock); juce::CriticalSection::ScopedLockType lock(samplesLock);
juce::OpenGLHelpers::clear(juce::Colours::black);
glColorMask(true, true, true, true); glColorMask(true, true, true, true);
viewportChanged(viewportArea); viewportChanged(viewportArea);
@ -455,7 +455,7 @@ void VisualiserComponent::renderOpenGL() {
using namespace juce::gl; using namespace juce::gl;
if (openGLContext.isActive()) { if (openGLContext.isActive()) {
juce::OpenGLHelpers::clear(juce::Colours::black); juce::OpenGLHelpers::clear(Colours::veryDark);
// we have a new buffer to render // we have a new buffer to render
if (sampleBufferCount != prevSampleBufferCount) { if (sampleBufferCount != prevSampleBufferCount) {
@ -586,8 +586,10 @@ Texture VisualiserComponent::makeTexture(int width, int height) {
// Set texture filtering and wrapping // Set texture filtering and wrapping
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
float borderColor[] = { 0.0f, 0.0f, 0.0f, 1.0f };
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
glBindTexture(GL_TEXTURE_2D, 0); // Unbind glBindTexture(GL_TEXTURE_2D, 0); // Unbind
@ -780,6 +782,11 @@ void VisualiserComponent::drawLine(const std::vector<float>& xPoints, const std:
lineShader->setUniform("uFadeAmount", fadeAmount); lineShader->setUniform("uFadeAmount", fadeAmount);
lineShader->setUniform("uNEdges", (GLfloat) nEdges); lineShader->setUniform("uNEdges", (GLfloat) nEdges);
OsciPoint offset = settings.getScreenType() == ScreenType::Real ? REAL_SCREEN_OFFSET : OsciPoint();
OsciPoint scale = settings.getScreenType() == ScreenType::Real ? REAL_SCREEN_SCALE : OsciPoint(1);
lineShader->setUniform("uOffset", (float) offset.x, (float) offset.y);
lineShader->setUniform("uScale", (float) scale.x, (float) scale.y);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vertexIndexBuffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vertexIndexBuffer);
int nEdgesThisTime = xPoints.size() - 1; int nEdgesThisTime = xPoints.size() - 1;
@ -847,12 +854,17 @@ void VisualiserComponent::drawCRT() {
activateTargetTexture(renderTexture); activateTargetTexture(renderTexture);
setShader(outputShader.get()); setShader(outputShader.get());
float brightness = std::pow(2, settings.getBrightness() - 2); outputShader->setUniform("uExposure", 0.25f);
outputShader->setUniform("uExposure", brightness);
outputShader->setUniform("uSaturation", (float) settings.getSaturation()); outputShader->setUniform("uSaturation", (float) settings.getSaturation());
outputShader->setUniform("uNoise", (float) settings.getNoise()); outputShader->setUniform("uNoise", (float) settings.getNoise());
outputShader->setUniform("uTime", time); outputShader->setUniform("uTime", time);
outputShader->setUniform("uGlow", (float) settings.getGlow()); outputShader->setUniform("uGlow", (float) settings.getGlow());
outputShader->setUniform("uAmbient", (float) settings.getAmbient());
OsciPoint offset = settings.getScreenType() == ScreenType::Real ? REAL_SCREEN_OFFSET : OsciPoint();
OsciPoint scale = settings.getScreenType() == ScreenType::Real ? REAL_SCREEN_SCALE : OsciPoint(1);
outputShader->setUniform("uOffset", (float) offset.x, (float) offset.y);
outputShader->setUniform("uScale", (float) scale.x, (float) scale.y);
outputShader->setUniform("uRealScreen", settings.getScreenType() == ScreenType::Real ? 1.0f : 0.0f);
outputShader->setUniform("uResizeForCanvas", lineTexture.width / 1024.0f); outputShader->setUniform("uResizeForCanvas", lineTexture.width / 1024.0f);
juce::Colour colour = juce::Colour::fromHSV(settings.getHue() / 360.0f, 1.0, 1.0, 1.0); juce::Colour colour = juce::Colour::fromHSV(settings.getHue() / 360.0f, 1.0, 1.0, 1.0);
outputShader->setUniform("uColour", colour.getFloatRed(), colour.getFloatGreen(), colour.getFloatBlue()); outputShader->setUniform("uColour", colour.getFloatRed(), colour.getFloatGreen(), colour.getFloatBlue());
@ -862,14 +874,16 @@ void VisualiserComponent::drawCRT() {
Texture VisualiserComponent::createScreenTexture() { Texture VisualiserComponent::createScreenTexture() {
using namespace juce::gl; using namespace juce::gl;
if (settings.getSmudgesEnabled()) { if (screenType == ScreenType::Smudged || screenType == ScreenType::SmudgedGraticule) {
screenOpenGLTexture.loadImage(screenTextureImage); screenOpenGLTexture.loadImage(screenTextureImage);
} else if (screenType == ScreenType::Real) {
screenOpenGLTexture.loadImage(oscilloscopeImage);
} else { } else {
screenOpenGLTexture.loadImage(emptyScreenImage); screenOpenGLTexture.loadImage(emptyScreenImage);
} }
Texture texture = { screenOpenGLTexture.getTextureID(), screenTextureImage.getWidth(), screenTextureImage.getHeight() }; Texture texture = { screenOpenGLTexture.getTextureID(), screenTextureImage.getWidth(), screenTextureImage.getHeight() };
if (settings.getGraticuleEnabled()) { if (screenType == ScreenType::Graticule || screenType == ScreenType::SmudgedGraticule) {
activateTargetTexture(texture); activateTargetTexture(texture);
setNormalBlending(); setNormalBlending();
setShader(simpleShader.get()); setShader(simpleShader.get());
@ -919,7 +933,7 @@ Texture VisualiserComponent::createScreenTexture() {
glVertexAttribPointer(glGetAttribLocation(simpleShader->getProgramID(), "vertexPosition"), 2, GL_FLOAT, GL_FALSE, 0, nullptr); glVertexAttribPointer(glGetAttribLocation(simpleShader->getProgramID(), "vertexPosition"), 2, GL_FLOAT, GL_FALSE, 0, nullptr);
glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ARRAY_BUFFER, 0);
simpleShader->setUniform("colour", 0.01f, 0.1f, 0.01f, 1.0f); simpleShader->setUniform("colour", 0.01f, 0.1f, 0.01f, 1.0f);
glLineWidth(1.0f); glLineWidth(2.0f);
glDrawArrays(GL_LINES, 0, data.size()); glDrawArrays(GL_LINES, 0, data.size());
glBindTexture(GL_TEXTURE_2D, targetTexture.value().id); glBindTexture(GL_TEXTURE_2D, targetTexture.value().id);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
@ -950,7 +964,7 @@ void VisualiserComponent::checkGLErrors(const juce::String& location) {
void VisualiserComponent::paint(juce::Graphics& g) { void VisualiserComponent::paint(juce::Graphics& g) {
g.setColour(juce::Colours::black); g.setColour(settings.getScreenType() == ScreenType::Real ? Colours::dark : Colours::veryDark);
g.fillRect(buttonRow); g.fillRect(buttonRow);
if (!active) { if (!active) {
// draw a translucent overlay // draw a translucent overlay
@ -967,9 +981,8 @@ void VisualiserComponent::paint(juce::Graphics& g) {
void VisualiserComponent::renderScope(const std::vector<float>& xPoints, const std::vector<float>& yPoints, const std::vector<float>& zPoints) { void VisualiserComponent::renderScope(const std::vector<float>& xPoints, const std::vector<float>& yPoints, const std::vector<float>& zPoints) {
time += 0.01f; time += 0.01f;
if (graticuleEnabled != settings.getGraticuleEnabled() || smudgesEnabled != settings.getSmudgesEnabled()) { if (screenType != settings.getScreenType()) {
graticuleEnabled = settings.getGraticuleEnabled(); screenType = settings.getScreenType();
smudgesEnabled = settings.getSmudgesEnabled();
screenTexture = createScreenTexture(); screenTexture = createScreenTexture();
} }

Wyświetl plik

@ -172,6 +172,11 @@ private:
juce::OpenGLTexture screenOpenGLTexture; juce::OpenGLTexture screenOpenGLTexture;
juce::Image screenTextureImage = juce::ImageFileFormat::loadFrom(BinaryData::noise_jpg, BinaryData::noise_jpgSize); juce::Image screenTextureImage = juce::ImageFileFormat::loadFrom(BinaryData::noise_jpg, BinaryData::noise_jpgSize);
juce::Image emptyScreenImage = juce::ImageFileFormat::loadFrom(BinaryData::empty_jpg, BinaryData::empty_jpgSize); juce::Image emptyScreenImage = juce::ImageFileFormat::loadFrom(BinaryData::empty_jpg, BinaryData::empty_jpgSize);
juce::Image oscilloscopeImage = juce::ImageFileFormat::loadFrom(BinaryData::real_jpg, BinaryData::real_jpgSize);
OsciPoint REAL_SCREEN_OFFSET = { 0.02, -0.15 };
OsciPoint REAL_SCREEN_SCALE = { 0.6 };
Texture screenTexture; Texture screenTexture;
std::optional<Texture> targetTexture = std::nullopt; std::optional<Texture> targetTexture = std::nullopt;
@ -184,8 +189,7 @@ private:
juce::OpenGLShaderProgram* currentShader; juce::OpenGLShaderProgram* currentShader;
float fadeAmount; float fadeAmount;
bool smudgesEnabled = settings.getSmudgesEnabled(); ScreenType screenType = settings.getScreenType();
bool graticuleEnabled = settings.getGraticuleEnabled();
const double RESAMPLE_RATIO = 6.0; const double RESAMPLE_RATIO = 6.0;
double sampleRate = -1; double sampleRate = -1;

Wyświetl plik

@ -3,8 +3,7 @@
#include "../PluginEditor.h" #include "../PluginEditor.h"
VisualiserSettings::VisualiserSettings(VisualiserParameters& parameters, int numChannels) : parameters(parameters), numChannels(numChannels) { VisualiserSettings::VisualiserSettings(VisualiserParameters& p, int numChannels) : parameters(p), numChannels(numChannels) {
addAndMakeVisible(brightness);
addAndMakeVisible(intensity); addAndMakeVisible(intensity);
addAndMakeVisible(persistence); addAndMakeVisible(persistence);
addAndMakeVisible(hue); addAndMakeVisible(hue);
@ -12,14 +11,22 @@ VisualiserSettings::VisualiserSettings(VisualiserParameters& parameters, int num
addAndMakeVisible(focus); addAndMakeVisible(focus);
addAndMakeVisible(noise); addAndMakeVisible(noise);
addAndMakeVisible(glow); addAndMakeVisible(glow);
addAndMakeVisible(ambient);
addAndMakeVisible(smooth); addAndMakeVisible(smooth);
addChildComponent(sweepMs); addChildComponent(sweepMs);
addAndMakeVisible(graticuleToggle);
addAndMakeVisible(smudgeToggle);
addAndMakeVisible(upsamplingToggle); addAndMakeVisible(upsamplingToggle);
addAndMakeVisible(sweepToggle); addAndMakeVisible(sweepToggle);
addAndMakeVisible(screenTypeLabel);
addAndMakeVisible(screenType);
for (int i = 1; i <= parameters.screenType->max; i++) {
screenType.addItem(parameters.screenType->getText(parameters.screenType->getNormalisedValue(i)), i);
}
screenType.setSelectedId(parameters.screenType->getValueUnnormalised());
screenType.onChange = [this] {
parameters.screenType->setUnnormalisedValueNotifyingHost(screenType.getSelectedId());
};
brightness.setSliderOnValueChange();
intensity.setSliderOnValueChange(); intensity.setSliderOnValueChange();
persistence.setSliderOnValueChange(); persistence.setSliderOnValueChange();
hue.setSliderOnValueChange(); hue.setSliderOnValueChange();
@ -27,6 +34,7 @@ VisualiserSettings::VisualiserSettings(VisualiserParameters& parameters, int num
focus.setSliderOnValueChange(); focus.setSliderOnValueChange();
noise.setSliderOnValueChange(); noise.setSliderOnValueChange();
glow.setSliderOnValueChange(); glow.setSliderOnValueChange();
ambient.setSliderOnValueChange();
smooth.setSliderOnValueChange(); smooth.setSliderOnValueChange();
sweepMs.setSliderOnValueChange(); sweepMs.setSliderOnValueChange();
@ -39,9 +47,14 @@ VisualiserSettings::VisualiserSettings(VisualiserParameters& parameters, int num
VisualiserSettings::~VisualiserSettings() {} VisualiserSettings::~VisualiserSettings() {}
void VisualiserSettings::resized() { void VisualiserSettings::resized() {
auto area = getLocalBounds().reduced(20); auto area = getLocalBounds().reduced(20, 0).withTrimmedBottom(20);
double rowHeight = 30; double rowHeight = 30;
brightness.setBounds(area.removeFromTop(rowHeight));
auto screenTypeArea = area.removeFromTop(2 * rowHeight);
screenTypeArea = screenTypeArea.withSizeKeepingCentre(300, rowHeight);
screenTypeLabel.setBounds(screenTypeArea.removeFromLeft(120));
screenType.setBounds(screenTypeArea.removeFromRight(180));
intensity.setBounds(area.removeFromTop(rowHeight)); intensity.setBounds(area.removeFromTop(rowHeight));
persistence.setBounds(area.removeFromTop(rowHeight)); persistence.setBounds(area.removeFromTop(rowHeight));
hue.setBounds(area.removeFromTop(rowHeight)); hue.setBounds(area.removeFromTop(rowHeight));
@ -49,9 +62,9 @@ void VisualiserSettings::resized() {
focus.setBounds(area.removeFromTop(rowHeight)); focus.setBounds(area.removeFromTop(rowHeight));
noise.setBounds(area.removeFromTop(rowHeight)); noise.setBounds(area.removeFromTop(rowHeight));
glow.setBounds(area.removeFromTop(rowHeight)); glow.setBounds(area.removeFromTop(rowHeight));
ambient.setBounds(area.removeFromTop(rowHeight));
smooth.setBounds(area.removeFromTop(rowHeight)); smooth.setBounds(area.removeFromTop(rowHeight));
graticuleToggle.setBounds(area.removeFromTop(rowHeight));
smudgeToggle.setBounds(area.removeFromTop(rowHeight));
upsamplingToggle.setBounds(area.removeFromTop(rowHeight)); upsamplingToggle.setBounds(area.removeFromTop(rowHeight));
sweepToggle.setBounds(area.removeFromTop(rowHeight)); sweepToggle.setBounds(area.removeFromTop(rowHeight));

Wyświetl plik

@ -9,10 +9,65 @@
#include "../components/SwitchButton.h" #include "../components/SwitchButton.h"
#include "../audio/SmoothEffect.h" #include "../audio/SmoothEffect.h"
enum class ScreenType : int {
Empty = 1,
Graticule = 2,
Smudged = 3,
SmudgedGraticule = 4,
Real = 5
};
class ScreenTypeParameter : public IntParameter {
public:
ScreenTypeParameter(juce::String name, juce::String id, int versionHint, ScreenType value) : IntParameter(name, id, versionHint, (int) value, 1, 5) {}
juce::String getText(float value, int maximumStringLength = 100) const override {
switch ((ScreenType)(int)getUnnormalisedValue(value)) {
case ScreenType::Empty:
return "Empty";
case ScreenType::Graticule:
return "Graticule";
case ScreenType::Smudged:
return "Smudged";
case ScreenType::SmudgedGraticule:
return "Smudged Graticule";
case ScreenType::Real:
return "Real Oscilloscope";
default:
return "Unknown";
}
}
float getValueForText(const juce::String& text) const override {
int unnormalisedValue;
if (text == "Empty") {
unnormalisedValue = (int)ScreenType::Empty;
} else if (text == "Graticule") {
unnormalisedValue = (int)ScreenType::Graticule;
} else if (text == "Smudged") {
unnormalisedValue = (int)ScreenType::Smudged;
} else if (text == "Smudged Graticule") {
unnormalisedValue = (int)ScreenType::SmudgedGraticule;
} else if (text == "Real Oscilloscope") {
unnormalisedValue = (int)ScreenType::Real;
} else {
unnormalisedValue = (int)ScreenType::Empty;
}
return getNormalisedValue(unnormalisedValue);
}
void save(juce::XmlElement* xml) {
xml->setAttribute("screenType", getText(getValue()));
}
void load(juce::XmlElement* xml) {
setValueNotifyingHost(getValueForText(xml->getStringAttribute("screenType")));
}
};
class VisualiserParameters { class VisualiserParameters {
public: public:
BooleanParameter* graticuleEnabled = new BooleanParameter("Show Graticule", "graticuleEnabled", VERSION_HINT, true, "Show the graticule or grid lines over the oscilloscope display."); ScreenTypeParameter* screenType = new ScreenTypeParameter("Screen Type", "screenType", VERSION_HINT, ScreenType::SmudgedGraticule);
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, true, "Upsamples the audio before visualising it to make it appear more realistic, at the expense of performance."); BooleanParameter* upsamplingEnabled = new BooleanParameter("Upsample Audio", "upsamplingEnabled", VERSION_HINT, true, "Upsamples the audio before visualising it to make it appear more realistic, at the expense of performance.");
BooleanParameter* sweepEnabled = new BooleanParameter("Sweep", "sweepEnabled", VERSION_HINT, false, "Plots the audio signal over time, sweeping from left to right"); BooleanParameter* sweepEnabled = new BooleanParameter("Sweep", "sweepEnabled", VERSION_HINT, false, "Plots the audio signal over time, sweeping from left to right");
BooleanParameter* visualiserFullScreen = new BooleanParameter("Visualiser Fullscreen", "visualiserFullScreen", VERSION_HINT, false, "Makes the software visualiser fullscreen."); BooleanParameter* visualiserFullScreen = new BooleanParameter("Visualiser Fullscreen", "visualiserFullScreen", VERSION_HINT, false, "Makes the software visualiser fullscreen.");
@ -33,14 +88,6 @@ public:
VERSION_HINT, 125, 0, 359, 1 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, 2.0, 0.0, 10.0
)
);
std::shared_ptr<Effect> intensityEffect = std::make_shared<Effect>( std::shared_ptr<Effect> intensityEffect = std::make_shared<Effect>(
new EffectParameter( new EffectParameter(
"Intensity", "Intensity",
@ -81,6 +128,14 @@ public:
VERSION_HINT, 0.3, 0.0, 1.0 VERSION_HINT, 0.3, 0.0, 1.0
) )
); );
std::shared_ptr<Effect> ambientEffect = std::make_shared<Effect>(
new EffectParameter(
"Ambient Light",
"Controls how much ambient light is added to the oscilloscope display.",
"ambient",
VERSION_HINT, 0.8, 0.0, 5.0
)
);
std::shared_ptr<Effect> smoothEffect = std::make_shared<Effect>( std::shared_ptr<Effect> smoothEffect = std::make_shared<Effect>(
std::make_shared<SmoothEffect>(), std::make_shared<SmoothEffect>(),
new EffectParameter( new EffectParameter(
@ -99,8 +154,9 @@ public:
) )
); );
std::vector<std::shared_ptr<Effect>> effects = {persistenceEffect, hueEffect, brightnessEffect, intensityEffect, saturationEffect, focusEffect, noiseEffect, glowEffect, sweepMsEffect}; std::vector<std::shared_ptr<Effect>> effects = {persistenceEffect, hueEffect, intensityEffect, saturationEffect, focusEffect, noiseEffect, glowEffect, ambientEffect, sweepMsEffect};
std::vector<BooleanParameter*> booleans = {graticuleEnabled, smudgesEnabled, upsamplingEnabled, visualiserFullScreen, sweepEnabled}; std::vector<BooleanParameter*> booleans = {upsamplingEnabled, visualiserFullScreen, sweepEnabled};
std::vector<IntParameter*> integers = {screenType};
}; };
class VisualiserSettings : public juce::Component { class VisualiserSettings : public juce::Component {
@ -110,10 +166,6 @@ public:
void resized() override; void resized() override;
double getBrightness() {
return parameters.brightnessEffect->getActualValue() - 2;
}
double getIntensity() { double getIntensity() {
return parameters.intensityEffect->getActualValue() / 100; return parameters.intensityEffect->getActualValue() / 100;
} }
@ -142,12 +194,12 @@ public:
return parameters.glowEffect->getActualValue() * 3; return parameters.glowEffect->getActualValue() * 3;
} }
bool getGraticuleEnabled() { double getAmbient() {
return parameters.graticuleEnabled->getBoolValue(); return parameters.ambientEffect->getActualValue();
} }
bool getSmudgesEnabled() { ScreenType getScreenType() {
return parameters.smudgesEnabled->getBoolValue(); return (ScreenType)parameters.screenType->getValueUnnormalised();
} }
bool getUpsamplingEnabled() { bool getUpsamplingEnabled() {
@ -158,7 +210,6 @@ public:
int numChannels; int numChannels;
private: private:
EffectComponent brightness{*parameters.brightnessEffect};
EffectComponent intensity{*parameters.intensityEffect}; EffectComponent intensity{*parameters.intensityEffect};
EffectComponent persistence{*parameters.persistenceEffect}; EffectComponent persistence{*parameters.persistenceEffect};
EffectComponent hue{*parameters.hueEffect}; EffectComponent hue{*parameters.hueEffect};
@ -166,11 +217,13 @@ private:
EffectComponent focus{*parameters.focusEffect}; EffectComponent focus{*parameters.focusEffect};
EffectComponent noise{*parameters.noiseEffect}; EffectComponent noise{*parameters.noiseEffect};
EffectComponent glow{*parameters.glowEffect}; EffectComponent glow{*parameters.glowEffect};
EffectComponent ambient{*parameters.ambientEffect};
EffectComponent smooth{*parameters.smoothEffect}; EffectComponent smooth{*parameters.smoothEffect};
EffectComponent sweepMs{*parameters.sweepMsEffect}; EffectComponent sweepMs{*parameters.sweepMsEffect};
jux::SwitchButton graticuleToggle{parameters.graticuleEnabled}; juce::Label screenTypeLabel{"Screen Type", "Screen Type"};
jux::SwitchButton smudgeToggle{parameters.smudgesEnabled}; juce::ComboBox screenType;
jux::SwitchButton upsamplingToggle{parameters.upsamplingEnabled}; jux::SwitchButton upsamplingToggle{parameters.upsamplingEnabled};
jux::SwitchButton sweepToggle{parameters.sweepEnabled}; jux::SwitchButton sweepToggle{parameters.sweepEnabled};

Wyświetl plik

@ -34,6 +34,7 @@
<GROUP id="{F3C16D02-63B4-E3DA-7498-901173C37D6C}" name="oscilloscope"> <GROUP id="{F3C16D02-63B4-E3DA-7498-901173C37D6C}" name="oscilloscope">
<FILE id="qpPhpN" name="empty.jpg" compile="0" resource="1" file="Resources/oscilloscope/empty.jpg"/> <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="dNtZYs" name="noise.jpg" compile="0" resource="1" file="Resources/oscilloscope/noise.jpg"/>
<FILE id="FyEDbA" name="real.jpg" compile="0" resource="1" file="Resources/oscilloscope/real.jpg"/>
</GROUP> </GROUP>
<GROUP id="{82BCD6F1-A8BF-F30B-5587-81EE70168883}" name="svg"> <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="rl17ZK" name="cog.svg" compile="0" resource="1" file="Resources/svg/cog.svg"/>