From bb190a1e4548c08a274644067b860fdbc1a2bd92 Mon Sep 17 00:00:00 2001 From: James H Ball Date: Tue, 22 Oct 2024 14:41:09 +0100 Subject: [PATCH] Pass data through to opengl oscilloscope --- Source/components/VisualiserComponent.cpp | 13 ++-- Source/components/VisualiserComponent.h | 5 +- .../components/VisualiserOpenGLComponent.cpp | 64 +++++++++++-------- Source/components/VisualiserOpenGLComponent.h | 15 +++-- 4 files changed, 53 insertions(+), 44 deletions(-) diff --git a/Source/components/VisualiserComponent.cpp b/Source/components/VisualiserComponent.cpp index bfc8279d..9545f41a 100644 --- a/Source/components/VisualiserComponent.cpp +++ b/Source/components/VisualiserComponent.cpp @@ -75,6 +75,10 @@ void VisualiserComponent::mouseDoubleClick(const juce::MouseEvent& event) { void VisualiserComponent::setBuffer(std::vector& newBuffer) { juce::CriticalSection::ScopedLockType scope(lock); + if (!oldVisualiser) { + openGLVisualiser.updateBuffer(newBuffer); + return; + } buffer.clear(); int stride = oldVisualiser ? roughness.textBox.getValue() : 1; for (int i = 0; i < newBuffer.size(); i += stride) { @@ -137,10 +141,6 @@ void VisualiserComponent::run() { consumerManager.consumerRead(consumer); setBuffer(tempBuffer); - if (!oldVisualiser) { - audioUpdated = true; - // triggerAsyncUpdate(); - } } } @@ -292,10 +292,6 @@ void VisualiserComponent::resized() { settingsButton.setBounds(buttonRow.removeFromRight(30)); } -void VisualiserComponent::childChanged() { - -} - void VisualiserComponent::popoutWindow() { haltRecording(); auto visualiser = new VisualiserComponent(sampleRateManager, consumerManager, settings, this, oldVisualiser); @@ -304,7 +300,6 @@ void VisualiserComponent::popoutWindow() { visualiser->closeSettings = closeSettings; visualiser->recordingHalted = recordingHalted; child = visualiser; - childChanged(); popOutButton.setVisible(false); visualiser->setSize(300, 300); popout = std::make_unique("Software Oscilloscope", this); diff --git a/Source/components/VisualiserComponent.h b/Source/components/VisualiserComponent.h index e8aa9bf2..b0f7a83a 100644 --- a/Source/components/VisualiserComponent.h +++ b/Source/components/VisualiserComponent.h @@ -25,7 +25,6 @@ public: std::function openSettings; std::function closeSettings; - void childChanged(); void enableFullScreen(); void setFullScreenCallback(std::function callback); void mouseDoubleClick(const juce::MouseEvent& event) override; @@ -58,7 +57,6 @@ private: const double BUFFER_LENGTH_SECS = 1/60.0; const double DEFAULT_SAMPLE_RATE = 192000.0; - std::atomic audioUpdated = false; std::atomic timerId; std::atomic lastMouseX; std::atomic lastMouseY; @@ -91,7 +89,7 @@ private: VisualiserSettings& settings; - VisualiserOpenGLComponent openGLVisualiser {settings}; + VisualiserOpenGLComponent openGLVisualiser {settings, sampleRateManager}; std::unique_ptr chooser; juce::File tempVideoFile; @@ -109,7 +107,6 @@ public: void closeButtonPressed() override { parent->setPaused(wasPaused); parent->child = nullptr; - parent->childChanged(); parent->resized(); parent->popout.reset(); } diff --git a/Source/components/VisualiserOpenGLComponent.cpp b/Source/components/VisualiserOpenGLComponent.cpp index 54f7ed37..9664e4df 100644 --- a/Source/components/VisualiserOpenGLComponent.cpp +++ b/Source/components/VisualiserOpenGLComponent.cpp @@ -2,10 +2,9 @@ #include "VisualiserOpenGLComponent.h" -VisualiserOpenGLComponent::VisualiserOpenGLComponent(VisualiserSettings& settings) : settings(settings) { +VisualiserOpenGLComponent::VisualiserOpenGLComponent(VisualiserSettings& settings, SampleRateManager& sampleRateManager) : settings(settings), sampleRateManager(sampleRateManager) { openGLContext.setRenderer(this); openGLContext.attachTo(*this); - openGLContext.setContinuousRepainting(true); } VisualiserOpenGLComponent::~VisualiserOpenGLComponent() { @@ -279,7 +278,7 @@ void VisualiserOpenGLComponent::newOpenGLContextCreated() { glGenBuffers(1, &vertexBuffer); setupTextures(); - setupArrays(1024); + setupArrays(samples.size()); } void VisualiserOpenGLComponent::openGLContextClosing() { @@ -295,24 +294,41 @@ void VisualiserOpenGLComponent::openGLContextClosing() { glDeleteTextures(1, &blur3Texture.id); glDeleteTextures(1, &blur4Texture.id); screenOpenGLTexture.release(); + + simpleShader.reset(); + texturedShader.reset(); + blurShader.reset(); + lineShader.reset(); + outputShader.reset(); +} + +void VisualiserOpenGLComponent::updateBuffer(std::vector& buffer) { + juce::CriticalSection::ScopedLockType lock(samplesLock); + + if (samples.size() != buffer.size()) { + needsReattach = true; + } + samples.clear(); + for (auto& point : buffer) { + samples.push_back(point); + } + juce::MessageManager::getInstance()->callAsync([this] { + if (needsReattach) { + openGLContext.detach(); + openGLContext.attachTo(*this); + needsReattach = false; + } + repaint(); + }); } void VisualiserOpenGLComponent::renderOpenGL() { if (openGLContext.isActive()) { - xSamples.clear(); - ySamples.clear(); - zSamples.clear(); - for (int i = 0; i < 1024; i++) { - //xSamples.push_back(std::sin(i * 0.1)); - //ySamples.push_back(std::cos(i * 0.1)); - xSamples.push_back(0); - ySamples.push_back(0); - zSamples.push_back(1); - } + juce::CriticalSection::ScopedLockType lock(samplesLock); renderScale = (float) openGLContext.getRenderingScale(); - drawLineTexture(xSamples, ySamples, zSamples); + drawLineTexture(samples); checkGLErrors("drawLineTexture"); drawCRT(); checkGLErrors("drawCRT"); @@ -422,14 +438,14 @@ Texture VisualiserOpenGLComponent::makeTexture(int width, int height) { return { textureID, width, height }; } -void VisualiserOpenGLComponent::drawLineTexture(std::vector& xPoints, std::vector& yPoints, std::vector& zPoints) { +void VisualiserOpenGLComponent::drawLineTexture(std::vector& points) { using namespace juce::gl; float persistence = settings.parameters.persistenceEffect->getActualValue() - 1.33; fadeAmount = juce::jmin(1.0, std::pow(0.5, persistence) * 0.4); activateTargetTexture(lineTexture); fade(); - drawLine(xPoints, yPoints, zPoints); + drawLine(points); glBindTexture(GL_TEXTURE_2D, targetTexture.value().id); glGenerateMipmap(GL_TEXTURE_2D); } @@ -552,18 +568,18 @@ void VisualiserOpenGLComponent::setNormalBlending() { glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } -void VisualiserOpenGLComponent::drawLine(std::vector& xPoints, std::vector& yPoints, std::vector& zPoints) { +void VisualiserOpenGLComponent::drawLine(std::vector& points) { using namespace juce::gl; setAdditiveBlending(); - int nPoints = xPoints.size(); + int nPoints = points.size(); for (int i = 0; i < nPoints; ++i) { int p = i * 12; - scratchVertices[p] = scratchVertices[p + 3] = scratchVertices[p + 6] = scratchVertices[p + 9] = xPoints[i]; - scratchVertices[p + 1] = scratchVertices[p + 4] = scratchVertices[p + 7] = scratchVertices[p + 10] = yPoints[i]; - scratchVertices[p + 2] = scratchVertices[p + 5] = scratchVertices[p + 8] = scratchVertices[p + 11] = zPoints[i]; + scratchVertices[p] = scratchVertices[p + 3] = scratchVertices[p + 6] = scratchVertices[p + 9] = points[i].x; + scratchVertices[p + 1] = scratchVertices[p + 4] = scratchVertices[p + 7] = scratchVertices[p + 10] = points[i].y; + scratchVertices[p + 2] = scratchVertices[p + 5] = scratchVertices[p + 8] = scratchVertices[p + 11] = points[i].z; } glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); @@ -590,10 +606,8 @@ void VisualiserOpenGLComponent::drawLine(std::vector& xPoints, std::vecto lineShader->setUniform("uGain", 450.0f / 512.0f); lineShader->setUniform("uInvert", 1.0f); - // TODO: integrate sampleRate - int sampleRate = 192000; float modifiedIntensity = settings.parameters.intensityEffect->getActualValue() / 100; - float intensity = modifiedIntensity * (41000.0f / sampleRate); + float intensity = modifiedIntensity * (41000.0f / sampleRateManager.getSampleRate()); if (settings.parameters.upsamplingEnabled->getBoolValue()) { lineShader->setUniform("uIntensity", intensity); } else { @@ -606,7 +620,7 @@ void VisualiserOpenGLComponent::drawLine(std::vector& xPoints, std::vecto lineShader->setUniform("uNEdges", (GLfloat) nEdges); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vertexIndexBuffer); - int nEdgesThisTime = xPoints.size() - 1; + int nEdgesThisTime = points.size() - 1; glDrawElements(GL_TRIANGLES, nEdgesThisTime, GL_UNSIGNED_SHORT, 0); glDisableVertexAttribArray(glGetAttribLocation(lineShader->getProgramID(), "aStart")); diff --git a/Source/components/VisualiserOpenGLComponent.h b/Source/components/VisualiserOpenGLComponent.h index 3c8f852f..fa9fe8fd 100644 --- a/Source/components/VisualiserOpenGLComponent.h +++ b/Source/components/VisualiserOpenGLComponent.h @@ -2,6 +2,7 @@ #include #include "VisualiserSettings.h" +#include "../audio/SampleRateManager.h" struct Texture { GLuint id; @@ -11,13 +12,14 @@ struct Texture { class VisualiserOpenGLComponent : public juce::Component, public juce::OpenGLRenderer { public: - VisualiserOpenGLComponent(VisualiserSettings& settings); + VisualiserOpenGLComponent(VisualiserSettings& settings, SampleRateManager& sampleRateManager); ~VisualiserOpenGLComponent() override; void newOpenGLContextCreated() override; void renderOpenGL() override; void openGLContextClosing() override; void resized() override; + void updateBuffer(std::vector& buffer); private: juce::OpenGLContext openGLContext; @@ -31,9 +33,9 @@ private: int nPoints = 0; int nEdges = 0; - std::vector xSamples; - std::vector ySamples; - std::vector zSamples; + juce::CriticalSection samplesLock; + bool needsReattach = true; + std::vector samples = std::vector(2); std::vector scratchVertices; std::vector fullScreenQuad; @@ -56,19 +58,20 @@ private: juce::OpenGLShaderProgram* currentShader; VisualiserSettings& settings; + SampleRateManager& sampleRateManager; float fadeAmount; Texture makeTexture(int width, int height); void setupArrays(int num_points); void setupTextures(); - void drawLineTexture(std::vector& xPoints, std::vector& yPoints, std::vector& zPoints); + void drawLineTexture(std::vector& points); void saveTextureToFile(GLuint textureID, int width, int height, const juce::File& file); void activateTargetTexture(std::optional texture); void setShader(juce::OpenGLShaderProgram* program); void drawTexture(std::optional texture0, std::optional texture1 = std::nullopt, std::optional texture2 = std::nullopt, std::optional texture3 = std::nullopt); void setAdditiveBlending(); void setNormalBlending(); - void drawLine(std::vector& xPoints, std::vector& yPoints, std::vector& zPoints); + void drawLine(std::vector& points); void fade(); void drawCRT(); void checkGLErrors(const juce::String& location);