Add noise and glow effects, and make upsampling button work

pull/261/head
James H Ball 2024-11-09 21:37:20 +00:00 zatwierdzone przez James H Ball
rodzic 7f12ee9490
commit a106e09876
9 zmienionych plików z 75 dodań i 56 usunięć

Wyświetl plik

@ -119,9 +119,9 @@ OscirenderAudioProcessorEditor::OscirenderAudioProcessorEditor(OscirenderAudioPr
visualiserSettingsWindow.setUsingNativeTitleBar(true); visualiserSettingsWindow.setUsingNativeTitleBar(true);
#endif #endif
visualiserSettings.setLookAndFeel(&getLookAndFeel()); visualiserSettings.setLookAndFeel(&getLookAndFeel());
visualiserSettings.setSize(550, 310); visualiserSettings.setSize(550, 370);
visualiserSettingsWindow.setContentNonOwned(&visualiserSettings, true); visualiserSettingsWindow.setContentNonOwned(&visualiserSettings, true);
visualiserSettingsWindow.centreWithSize(550, 310); visualiserSettingsWindow.centreWithSize(550, 370);
tooltipDropShadow.setOwner(&tooltipWindow); tooltipDropShadow.setOwner(&tooltipWindow);
} }

Wyświetl plik

@ -149,13 +149,10 @@ OscirenderAudioProcessor::OscirenderAudioProcessor()
permanentEffects.push_back(thresholdEffect); permanentEffects.push_back(thresholdEffect);
permanentEffects.push_back(imageThreshold); permanentEffects.push_back(imageThreshold);
permanentEffects.push_back(imageStride); permanentEffects.push_back(imageStride);
permanentEffects.push_back(visualiserParameters.brightnessEffect);
permanentEffects.push_back(visualiserParameters.intensityEffect); for (auto effect : visualiserParameters.effects) {
permanentEffects.push_back(visualiserParameters.persistenceEffect); permanentEffects.push_back(effect);
permanentEffects.push_back(visualiserParameters.hueEffect); }
permanentEffects.push_back(visualiserParameters.saturationEffect);
permanentEffects.push_back(visualiserParameters.focusEffect);
permanentEffects.push_back(visualiserParameters.noiseEffect);
for (int i = 0; i < 26; i++) { for (int i = 0; i < 26; i++) {
addLuaSlider(); addLuaSlider();
@ -179,10 +176,10 @@ OscirenderAudioProcessor::OscirenderAudioProcessor()
booleanParameters.push_back(animateFrames); booleanParameters.push_back(animateFrames);
booleanParameters.push_back(animationSyncBPM); booleanParameters.push_back(animationSyncBPM);
booleanParameters.push_back(invertImage); booleanParameters.push_back(invertImage);
booleanParameters.push_back(visualiserParameters.graticuleEnabled);
booleanParameters.push_back(visualiserParameters.smudgesEnabled); for (auto parameter : visualiserParameters.booleans) {
booleanParameters.push_back(visualiserParameters.upsamplingEnabled); booleanParameters.push_back(parameter);
booleanParameters.push_back(visualiserParameters.visualiserFullScreen); }
for (auto parameter : booleanParameters) { for (auto parameter : booleanParameters) {
addParameter(parameter); addParameter(parameter);

Wyświetl plik

@ -51,13 +51,13 @@ SosciPluginEditor::SosciPluginEditor(SosciAudioProcessor& p)
visualiserSettingsWindow.setUsingNativeTitleBar(true); visualiserSettingsWindow.setUsingNativeTitleBar(true);
#endif #endif
visualiserSettings.setLookAndFeel(&getLookAndFeel()); visualiserSettings.setLookAndFeel(&getLookAndFeel());
visualiserSettings.setSize(550, 340); visualiserSettings.setSize(550, 370);
visualiserSettingsWindow.setContentNonOwned(&visualiserSettings, true); visualiserSettingsWindow.setContentNonOwned(&visualiserSettings, true);
visualiserSettingsWindow.centreWithSize(550, 340); visualiserSettingsWindow.centreWithSize(550, 370);
menuBar.toFront(true); menuBar.toFront(true);
setSize(725, 750); setSize(700, 750);
setResizable(true, true); setResizable(true, true);
setResizeLimits(250, 250, 999999, 999999); setResizeLimits(250, 250, 999999, 999999);
} }
@ -72,12 +72,11 @@ void SosciPluginEditor::paint(juce::Graphics& g) {
} }
void SosciPluginEditor::resized() { void SosciPluginEditor::resized() {
auto area = getLocalBounds(); auto topBar = getLocalBounds().removeFromTop(25).removeFromLeft(200);
auto topBar = area.removeFromTop(25).removeFromLeft(200);
menuBar.setBounds(topBar); menuBar.setBounds(topBar);
visualiser.setBounds(getLocalBounds()); auto visualiserArea = getLocalBounds();
visualiserArea.removeFromTop(25);
visualiser.setBounds(visualiserArea);
} }
bool SosciPluginEditor::keyPressed(const juce::KeyPress& key) { bool SosciPluginEditor::keyPressed(const juce::KeyPress& key) {

Wyświetl plik

@ -16,16 +16,12 @@ SosciAudioProcessor::SosciAudioProcessor()
: AudioProcessor (BusesProperties().withInput("Input", juce::AudioChannelSet::namedChannelSet(3), true) : AudioProcessor (BusesProperties().withInput("Input", juce::AudioChannelSet::namedChannelSet(3), true)
.withOutput("Output", juce::AudioChannelSet::stereo(), true)) .withOutput("Output", juce::AudioChannelSet::stereo(), true))
#endif #endif
{ {
// locking isn't necessary here because we are in the constructor // locking isn't necessary here because we are in the constructor
allEffects.push_back(parameters.brightnessEffect); for (auto effect : parameters.effects) {
allEffects.push_back(parameters.intensityEffect); allEffects.push_back(effect);
allEffects.push_back(parameters.persistenceEffect); }
allEffects.push_back(parameters.hueEffect);
allEffects.push_back(parameters.saturationEffect);
allEffects.push_back(parameters.focusEffect);
allEffects.push_back(parameters.noiseEffect);
for (auto effect : allEffects) { for (auto effect : allEffects) {
for (auto effectParameter : effect->parameters) { for (auto effectParameter : effect->parameters) {
@ -35,11 +31,10 @@ SosciAudioProcessor::SosciAudioProcessor()
} }
} }
} }
booleanParameters.push_back(parameters.graticuleEnabled); for (auto parameter : parameters.booleans) {
booleanParameters.push_back(parameters.smudgesEnabled); booleanParameters.push_back(parameter);
booleanParameters.push_back(parameters.upsamplingEnabled); }
booleanParameters.push_back(parameters.visualiserFullScreen);
for (auto parameter : booleanParameters) { for (auto parameter : booleanParameters) {
addParameter(parameter); addParameter(parameter);

Wyświetl plik

@ -6,6 +6,9 @@ uniform sampler2D uTexture2; //big glow
uniform sampler2D uTexture3; //screen uniform sampler2D uTexture3; //screen
uniform float uExposure; uniform float uExposure;
uniform float uSaturation; uniform float uSaturation;
uniform float uNoise;
uniform float uTime;
uniform float uGlow;
uniform vec3 uColour; uniform vec3 uColour;
varying vec2 vTexCoord; varying vec2 vTexCoord;
varying vec2 vTexCoordCanvas; varying vec2 vTexCoordCanvas;
@ -16,10 +19,8 @@ vec3 desaturate(vec3 color, float factor) {
return vec3(mix(color, gray, factor)); return vec3(mix(color, gray, factor));
} }
/* Gradient noise from Jorge Jimenez's presentation: */ float noise(in vec2 uv, in float time) {
/* http://www.iryoku.com/next-generation-post-processing-in-call-of-duty-advanced-warfare */ return (fract(sin(dot(uv, vec2(12.9898,78.233)*2.0 + time)) * 43758.5453)) - 0.5;
float gradientNoise(in vec2 uv) {
return fract(52.9829189 * fract(dot(uv, vec2(0.06711056, 0.00583715))));
} }
void main() { void main() {
@ -28,13 +29,13 @@ void main() {
vec4 screen = texture2D(uTexture3, vTexCoord); vec4 screen = texture2D(uTexture3, vTexCoord);
vec4 tightGlow = texture2D(uTexture1, vTexCoord); vec4 tightGlow = texture2D(uTexture1, vTexCoord);
vec4 scatter = texture2D(uTexture2, vTexCoord)+0.35; vec4 scatter = texture2D(uTexture2, vTexCoord)+0.35;
float light = line.r + 1.5*screen.g*screen.g*tightGlow.r; float light = line.r + uGlow * 1.5 * screen.g * screen.g * tightGlow.r;
light += 0.4*scatter.g * (2.0+1.0*screen.g + 0.5*screen.r); light += uGlow * 0.4 * 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;
gl_FragColor.rgb = desaturate(gl_FragColor.rgb, 1.0 - uSaturation); gl_FragColor.rgb = desaturate(gl_FragColor.rgb, 1.0 - uSaturation);
gl_FragColor.rgb += (1.0 / 255.0) * gradientNoise(gl_FragCoord.xy) - (0.5 / 255.0); gl_FragColor.rgb += uNoise * noise(gl_FragCoord.xy, uTime);
gl_FragColor.a = 1.0; gl_FragColor.a = 1.0;
} }

Wyświetl plik

@ -141,11 +141,7 @@ void VisualiserComponent::haltRecording() {
void VisualiserComponent::resized() { void VisualiserComponent::resized() {
auto area = getLocalBounds(); auto area = getLocalBounds();
if (visualiserOnly) { buttonRow = area.removeFromBottom(25);
buttonRow = area.removeFromTop(25);
} else {
buttonRow = area.removeFromBottom(25);
}
if (parent == nullptr && !visualiserOnly) { if (parent == nullptr && !visualiserOnly) {
fullScreenButton.setBounds(buttonRow.removeFromRight(30)); fullScreenButton.setBounds(buttonRow.removeFromRight(30));
} }
@ -230,7 +226,7 @@ void VisualiserComponent::newOpenGLContextCreated() {
glGenBuffers(1, &vertexBuffer); glGenBuffers(1, &vertexBuffer);
setupTextures(); setupTextures();
setupArrays(smoothedXSamples.size()); setupArrays(xSamples.size() * RESAMPLE_RATIO);
} }
void VisualiserComponent::openGLContextClosing() { void VisualiserComponent::openGLContextClosing() {
@ -255,7 +251,7 @@ void VisualiserComponent::openGLContextClosing() {
} }
void VisualiserComponent::handleAsyncUpdate() { void VisualiserComponent::handleAsyncUpdate() {
{ if (settings.parameters.upsamplingEnabled->getBoolValue()) {
juce::CriticalSection::ScopedLockType lock(samplesLock); juce::CriticalSection::ScopedLockType lock(samplesLock);
int newResampledSize = xSamples.size() * RESAMPLE_RATIO; int newResampledSize = xSamples.size() * RESAMPLE_RATIO;
@ -280,6 +276,7 @@ void VisualiserComponent::handleAsyncUpdate() {
void VisualiserComponent::renderOpenGL() { void VisualiserComponent::renderOpenGL() {
if (openGLContext.isActive()) { if (openGLContext.isActive()) {
time += 0.01f;
juce::OpenGLHelpers::clear(juce::Colours::black); juce::OpenGLHelpers::clear(juce::Colours::black);
if (active) { if (active) {
juce::CriticalSection::ScopedLockType lock(samplesLock); juce::CriticalSection::ScopedLockType lock(samplesLock);
@ -292,7 +289,11 @@ void VisualiserComponent::renderOpenGL() {
renderScale = (float) openGLContext.getRenderingScale(); renderScale = (float) openGLContext.getRenderingScale();
drawLineTexture(smoothedXSamples, smoothedYSamples, smoothedZSamples); if (settings.parameters.upsamplingEnabled->getBoolValue()) {
drawLineTexture(smoothedXSamples, smoothedYSamples, smoothedZSamples);
} else {
drawLineTexture(xSamples, ySamples, zSamples);
}
checkGLErrors("drawLineTexture"); checkGLErrors("drawLineTexture");
drawCRT(); drawCRT();
checkGLErrors("drawCRT"); checkGLErrors("drawCRT");
@ -312,7 +313,7 @@ void VisualiserComponent::viewportChanged(juce::Rectangle<int> area) {
float minDim = juce::jmin(realWidth, realHeight); float minDim = juce::jmin(realWidth, realHeight);
float x = (realWidth - minDim) / 2 + area.getX() * renderScale + xOffset; float x = (realWidth - minDim) / 2 + area.getX() * renderScale + xOffset;
float y = (realHeight - minDim) / 2 + area.getY() * renderScale + yOffset; float y = (realHeight - minDim) / 2 - area.getY() * renderScale + yOffset;
glViewport(juce::roundToInt(x), juce::roundToInt(y), juce::roundToInt(minDim), juce::roundToInt(minDim)); glViewport(juce::roundToInt(x), juce::roundToInt(y), juce::roundToInt(minDim), juce::roundToInt(minDim));
} }
@ -567,9 +568,7 @@ void VisualiserComponent::drawLine(const std::vector<float>& xPoints, const std:
if (settings.getUpsamplingEnabled()) { if (settings.getUpsamplingEnabled()) {
lineShader->setUniform("uIntensity", intensity); lineShader->setUniform("uIntensity", intensity);
} else { } else {
// TODO: filter steps lineShader->setUniform("uIntensity", (GLfloat) (intensity * RESAMPLE_RATIO * 1.5));
int steps = 6;
lineShader->setUniform("uIntensity", (GLfloat) (intensity * (steps + 1.5)));
} }
lineShader->setUniform("uFadeAmount", fadeAmount); lineShader->setUniform("uFadeAmount", fadeAmount);
@ -642,6 +641,9 @@ void VisualiserComponent::drawCRT() {
float brightness = std::pow(2, settings.getBrightness() - 2); float brightness = std::pow(2, settings.getBrightness() - 2);
outputShader->setUniform("uExposure", brightness); outputShader->setUniform("uExposure", brightness);
outputShader->setUniform("uSaturation", (float) settings.getSaturation()); outputShader->setUniform("uSaturation", (float) settings.getSaturation());
outputShader->setUniform("uNoise", (float) settings.getNoise());
outputShader->setUniform("uTime", time);
outputShader->setUniform("uGlow", (float) settings.getGlow());
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());

Wyświetl plik

@ -84,6 +84,8 @@ private:
juce::OpenGLContext openGLContext; juce::OpenGLContext openGLContext;
float time = 0;
juce::Rectangle<int> buttonRow; juce::Rectangle<int> buttonRow;
juce::Rectangle<int> viewportArea; juce::Rectangle<int> viewportArea;

Wyświetl plik

@ -10,6 +10,8 @@ VisualiserSettings::VisualiserSettings(VisualiserParameters& parameters, int num
addAndMakeVisible(hue); addAndMakeVisible(hue);
addAndMakeVisible(saturation); addAndMakeVisible(saturation);
addAndMakeVisible(focus); addAndMakeVisible(focus);
addAndMakeVisible(noise);
addAndMakeVisible(glow);
addAndMakeVisible(graticuleToggle); addAndMakeVisible(graticuleToggle);
addAndMakeVisible(smudgeToggle); addAndMakeVisible(smudgeToggle);
addAndMakeVisible(upsamplingToggle); addAndMakeVisible(upsamplingToggle);
@ -20,6 +22,8 @@ VisualiserSettings::VisualiserSettings(VisualiserParameters& parameters, int num
hue.setSliderOnValueChange(); hue.setSliderOnValueChange();
saturation.setSliderOnValueChange(); saturation.setSliderOnValueChange();
focus.setSliderOnValueChange(); focus.setSliderOnValueChange();
noise.setSliderOnValueChange();
glow.setSliderOnValueChange();
} }
VisualiserSettings::~VisualiserSettings() {} VisualiserSettings::~VisualiserSettings() {}
@ -33,6 +37,8 @@ void VisualiserSettings::resized() {
hue.setBounds(area.removeFromTop(rowHeight)); hue.setBounds(area.removeFromTop(rowHeight));
saturation.setBounds(area.removeFromTop(rowHeight)); saturation.setBounds(area.removeFromTop(rowHeight));
focus.setBounds(area.removeFromTop(rowHeight)); focus.setBounds(area.removeFromTop(rowHeight));
noise.setBounds(area.removeFromTop(rowHeight));
glow.setBounds(area.removeFromTop(rowHeight));
graticuleToggle.setBounds(area.removeFromTop(rowHeight)); graticuleToggle.setBounds(area.removeFromTop(rowHeight));
smudgeToggle.setBounds(area.removeFromTop(rowHeight)); smudgeToggle.setBounds(area.removeFromTop(rowHeight));
upsamplingToggle.setBounds(area.removeFromTop(rowHeight)); upsamplingToggle.setBounds(area.removeFromTop(rowHeight));

Wyświetl plik

@ -12,7 +12,7 @@ class VisualiserParameters {
public: public:
BooleanParameter* graticuleEnabled = new BooleanParameter("Show Graticule", "graticuleEnabled", VERSION_HINT, true, "Show the graticule or grid lines over the oscilloscope display."); 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* 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* 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* 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.");
std::shared_ptr<Effect> persistenceEffect = std::make_shared<Effect>( std::shared_ptr<Effect> persistenceEffect = std::make_shared<Effect>(
@ -68,9 +68,20 @@ public:
"Noise", "Noise",
"Controls how much noise/grain is added to the oscilloscope display.", "Controls how much noise/grain is added to the oscilloscope display.",
"noise", "noise",
VERSION_HINT, 1.0, 0.01, 1.0 VERSION_HINT, 0.1, 0.0, 1.0
) )
); );
std::shared_ptr<Effect> glowEffect = std::make_shared<Effect>(
new EffectParameter(
"Glow",
"Controls how much the light glows on the oscilloscope display.",
"glow",
VERSION_HINT, 0.3, 0.0, 1.0
)
);
std::vector<std::shared_ptr<Effect>> effects = {persistenceEffect, hueEffect, brightnessEffect, intensityEffect, saturationEffect, focusEffect, noiseEffect, glowEffect};
std::vector<BooleanParameter*> booleans = {graticuleEnabled, smudgesEnabled, upsamplingEnabled, visualiserFullScreen};
}; };
class VisualiserSettings : public juce::Component { class VisualiserSettings : public juce::Component {
@ -108,6 +119,10 @@ public:
return parameters.noiseEffect->getActualValue(); return parameters.noiseEffect->getActualValue();
} }
double getGlow() {
return parameters.glowEffect->getActualValue() * 3;
}
bool getGraticuleEnabled() { bool getGraticuleEnabled() {
return parameters.graticuleEnabled->getBoolValue(); return parameters.graticuleEnabled->getBoolValue();
} }
@ -130,6 +145,8 @@ private:
EffectComponent hue{*parameters.hueEffect}; EffectComponent hue{*parameters.hueEffect};
EffectComponent saturation{*parameters.saturationEffect}; EffectComponent saturation{*parameters.saturationEffect};
EffectComponent focus{*parameters.focusEffect}; EffectComponent focus{*parameters.focusEffect};
EffectComponent noise{*parameters.noiseEffect};
EffectComponent glow{*parameters.glowEffect};
jux::SwitchButton graticuleToggle{parameters.graticuleEnabled}; jux::SwitchButton graticuleToggle{parameters.graticuleEnabled};
jux::SwitchButton smudgeToggle{parameters.smudgesEnabled}; jux::SwitchButton smudgeToggle{parameters.smudgesEnabled};