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);
#endif
visualiserSettings.setLookAndFeel(&getLookAndFeel());
visualiserSettings.setSize(550, 310);
visualiserSettings.setSize(550, 370);
visualiserSettingsWindow.setContentNonOwned(&visualiserSettings, true);
visualiserSettingsWindow.centreWithSize(550, 310);
visualiserSettingsWindow.centreWithSize(550, 370);
tooltipDropShadow.setOwner(&tooltipWindow);
}

Wyświetl plik

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

Wyświetl plik

@ -51,13 +51,13 @@ SosciPluginEditor::SosciPluginEditor(SosciAudioProcessor& p)
visualiserSettingsWindow.setUsingNativeTitleBar(true);
#endif
visualiserSettings.setLookAndFeel(&getLookAndFeel());
visualiserSettings.setSize(550, 340);
visualiserSettings.setSize(550, 370);
visualiserSettingsWindow.setContentNonOwned(&visualiserSettings, true);
visualiserSettingsWindow.centreWithSize(550, 340);
visualiserSettingsWindow.centreWithSize(550, 370);
menuBar.toFront(true);
setSize(725, 750);
setSize(700, 750);
setResizable(true, true);
setResizeLimits(250, 250, 999999, 999999);
}
@ -72,12 +72,11 @@ void SosciPluginEditor::paint(juce::Graphics& g) {
}
void SosciPluginEditor::resized() {
auto area = getLocalBounds();
auto topBar = area.removeFromTop(25).removeFromLeft(200);
auto topBar = getLocalBounds().removeFromTop(25).removeFromLeft(200);
menuBar.setBounds(topBar);
visualiser.setBounds(getLocalBounds());
auto visualiserArea = getLocalBounds();
visualiserArea.removeFromTop(25);
visualiser.setBounds(visualiserArea);
}
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)
.withOutput("Output", juce::AudioChannelSet::stereo(), true))
#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);
allEffects.push_back(parameters.saturationEffect);
allEffects.push_back(parameters.focusEffect);
allEffects.push_back(parameters.noiseEffect);
for (auto effect : parameters.effects) {
allEffects.push_back(effect);
}
for (auto effect : allEffects) {
for (auto effectParameter : effect->parameters) {
@ -35,11 +31,10 @@ SosciAudioProcessor::SosciAudioProcessor()
}
}
}
booleanParameters.push_back(parameters.graticuleEnabled);
booleanParameters.push_back(parameters.smudgesEnabled);
booleanParameters.push_back(parameters.upsamplingEnabled);
booleanParameters.push_back(parameters.visualiserFullScreen);
for (auto parameter : parameters.booleans) {
booleanParameters.push_back(parameter);
}
for (auto parameter : booleanParameters) {
addParameter(parameter);

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

@ -12,7 +12,7 @@ class VisualiserParameters {
public:
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* 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.");
std::shared_ptr<Effect> persistenceEffect = std::make_shared<Effect>(
@ -68,9 +68,20 @@ public:
"Noise",
"Controls how much noise/grain is added to the oscilloscope display.",
"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 {
@ -108,6 +119,10 @@ public:
return parameters.noiseEffect->getActualValue();
}
double getGlow() {
return parameters.glowEffect->getActualValue() * 3;
}
bool getGraticuleEnabled() {
return parameters.graticuleEnabled->getBoolValue();
}
@ -130,6 +145,8 @@ private:
EffectComponent hue{*parameters.hueEffect};
EffectComponent saturation{*parameters.saturationEffect};
EffectComponent focus{*parameters.focusEffect};
EffectComponent noise{*parameters.noiseEffect};
EffectComponent glow{*parameters.glowEffect};
jux::SwitchButton graticuleToggle{parameters.graticuleEnabled};
jux::SwitchButton smudgeToggle{parameters.smudgesEnabled};