Fix most major bugs with opengl implementation and add upsampling

pull/261/head
James H Ball 2024-10-26 18:15:53 +01:00 zatwierdzone przez James H Ball
rodzic eff8b3f635
commit 8296014272
3 zmienionych plików z 53 dodań i 33 usunięć

Wyświetl plik

@ -159,6 +159,7 @@ void VisualiserComponent::run() {
} }
consumerManager.consumerRead(consumer); consumerManager.consumerRead(consumer);
// TODO: Find a way to immediately call consumerRegister after consumerRead so that no audio is missed
setBuffer(tempBuffer); setBuffer(tempBuffer);
} }
} }

Wyświetl plik

@ -279,7 +279,7 @@ void VisualiserOpenGLComponent::newOpenGLContextCreated() {
glGenBuffers(1, &vertexBuffer); glGenBuffers(1, &vertexBuffer);
setupTextures(); setupTextures();
setupArrays(samples.size()); setupArrays(smoothedXSamples.size());
} }
void VisualiserOpenGLComponent::openGLContextClosing() { void VisualiserOpenGLComponent::openGLContextClosing() {
@ -304,36 +304,53 @@ void VisualiserOpenGLComponent::openGLContextClosing() {
} }
void VisualiserOpenGLComponent::updateBuffer(std::vector<OsciPoint>& buffer) { void VisualiserOpenGLComponent::updateBuffer(std::vector<OsciPoint>& buffer) {
juce::CriticalSection::ScopedLockType lock(samplesLock); // TODO: Figure out whether locking on samplesLock is required
//juce::CriticalSection::ScopedLockType lock(samplesLock);
int newResampledSize = buffer.size() * RESAMPLE_RATIO + 1; if (xSamples.size() != buffer.size()) {
if (samples.size() != buffer.size()) {
needsReattach = true; needsReattach = true;
} }
samples.clear(); xSamples.clear();
ySamples.clear();
zSamples.clear();
for (auto& point : buffer) { for (auto& point : buffer) {
samples.push_back(point); xSamples.push_back(point.x);
ySamples.push_back(point.y);
zSamples.push_back(point.z);
} }
triggerAsyncUpdate();
}
void VisualiserOpenGLComponent::handleAsyncUpdate() {
int newResampledSize = xSamples.size() * RESAMPLE_RATIO;
smoothedXSamples.resize(newResampledSize);
smoothedYSamples.resize(newResampledSize);
smoothedZSamples.resize(newResampledSize);
if (sampleRate != sampleRateManager.getSampleRate()) { if (sampleRate != sampleRateManager.getSampleRate()) {
sampleRate = sampleRateManager.getSampleRate(); sampleRate = sampleRateManager.getSampleRate();
resampler.prepare(sampleRate, RESAMPLE_RATIO); xResampler.prepare(sampleRate, RESAMPLE_RATIO);
yResampler.prepare(sampleRate, RESAMPLE_RATIO);
zResampler.prepare(sampleRate, RESAMPLE_RATIO);
} }
juce::MessageManager::getInstance()->callAsync([this] { xResampler.process(xSamples.data(), smoothedXSamples.data(), xSamples.size());
yResampler.process(ySamples.data(), smoothedYSamples.data(), ySamples.size());
zResampler.process(zSamples.data(), smoothedZSamples.data(), zSamples.size());
if (needsReattach) { if (needsReattach) {
openGLContext.detach(); openGLContext.detach();
openGLContext.attachTo(*this); openGLContext.attachTo(*this);
needsReattach = false; needsReattach = false;
} }
repaint(); repaint();
});
} }
void VisualiserOpenGLComponent::renderOpenGL() { void VisualiserOpenGLComponent::renderOpenGL() {
if (openGLContext.isActive()) { if (openGLContext.isActive()) {
juce::CriticalSection::ScopedLockType lock(samplesLock); //juce::CriticalSection::ScopedLockType lock(samplesLock);
if (graticuleEnabled != settings.getGraticuleEnabled() || smudgesEnabled != settings.getSmudgesEnabled()) { if (graticuleEnabled != settings.getGraticuleEnabled() || smudgesEnabled != settings.getSmudgesEnabled()) {
graticuleEnabled = settings.getGraticuleEnabled(); graticuleEnabled = settings.getGraticuleEnabled();
@ -343,7 +360,7 @@ void VisualiserOpenGLComponent::renderOpenGL() {
renderScale = (float) openGLContext.getRenderingScale(); renderScale = (float) openGLContext.getRenderingScale();
drawLineTexture(samples); drawLineTexture(smoothedXSamples, smoothedYSamples, smoothedZSamples);
checkGLErrors("drawLineTexture"); checkGLErrors("drawLineTexture");
drawCRT(); drawCRT();
checkGLErrors("drawCRT"); checkGLErrors("drawCRT");
@ -452,13 +469,13 @@ Texture VisualiserOpenGLComponent::makeTexture(int width, int height) {
return { textureID, width, height }; return { textureID, width, height };
} }
void VisualiserOpenGLComponent::drawLineTexture(std::vector<OsciPoint>& points) { void VisualiserOpenGLComponent::drawLineTexture(const std::vector<float>& xPoints, const std::vector<float>& yPoints, const std::vector<float>& zPoints) {
using namespace juce::gl; using namespace juce::gl;
fadeAmount = juce::jmin(1.0, std::pow(0.5, settings.getPersistence()) * 0.4); fadeAmount = juce::jmin(1.0, std::pow(0.5, settings.getPersistence()) * 0.4);
activateTargetTexture(lineTexture); activateTargetTexture(lineTexture);
fade(); fade();
drawLine(points); drawLine(xPoints, yPoints, zPoints);
glBindTexture(GL_TEXTURE_2D, targetTexture.value().id); glBindTexture(GL_TEXTURE_2D, targetTexture.value().id);
glGenerateMipmap(GL_TEXTURE_2D); glGenerateMipmap(GL_TEXTURE_2D);
} }
@ -581,18 +598,18 @@ void VisualiserOpenGLComponent::setNormalBlending() {
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
} }
void VisualiserOpenGLComponent::drawLine(std::vector<OsciPoint>& points) { void VisualiserOpenGLComponent::drawLine(const std::vector<float>& xPoints, const std::vector<float>& yPoints, const std::vector<float>& zPoints) {
using namespace juce::gl; using namespace juce::gl;
setAdditiveBlending(); setAdditiveBlending();
int nPoints = points.size(); int nPoints = xPoints.size();
for (int i = 0; i < nPoints; ++i) { for (int i = 0; i < nPoints; ++i) {
int p = i * 12; int p = i * 12;
scratchVertices[p] = scratchVertices[p + 3] = scratchVertices[p + 6] = scratchVertices[p + 9] = points[i].x; 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] = points[i].y; 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] = points[i].z; scratchVertices[p + 2] = scratchVertices[p + 5] = scratchVertices[p + 8] = scratchVertices[p + 11] = zPoints[i];
} }
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
@ -630,8 +647,8 @@ void VisualiserOpenGLComponent::drawLine(std::vector<OsciPoint>& points) {
lineShader->setUniform("uNEdges", (GLfloat) nEdges); lineShader->setUniform("uNEdges", (GLfloat) nEdges);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vertexIndexBuffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vertexIndexBuffer);
int nEdgesThisTime = points.size() - 1; int nEdgesThisTime = xPoints.size() - 1;
glDrawElements(GL_TRIANGLES, nEdgesThisTime, GL_UNSIGNED_SHORT, 0); glDrawElements(GL_TRIANGLES, nEdgesThisTime * 6, GL_UNSIGNED_SHORT, 0);
glDisableVertexAttribArray(glGetAttribLocation(lineShader->getProgramID(), "aStart")); glDisableVertexAttribArray(glGetAttribLocation(lineShader->getProgramID(), "aStart"));
glDisableVertexAttribArray(glGetAttribLocation(lineShader->getProgramID(), "aEnd")); glDisableVertexAttribArray(glGetAttribLocation(lineShader->getProgramID(), "aEnd"));

Wyświetl plik

@ -11,7 +11,7 @@ struct Texture {
int height; int height;
}; };
class VisualiserOpenGLComponent : public juce::Component, public juce::OpenGLRenderer { class VisualiserOpenGLComponent : public juce::Component, public juce::OpenGLRenderer, public juce::AsyncUpdater {
public: public:
VisualiserOpenGLComponent(VisualiserSettings& settings, SampleRateManager& sampleRateManager); VisualiserOpenGLComponent(VisualiserSettings& settings, SampleRateManager& sampleRateManager);
~VisualiserOpenGLComponent() override; ~VisualiserOpenGLComponent() override;
@ -23,6 +23,7 @@ public:
void paint(juce::Graphics& g) override; void paint(juce::Graphics& g) override;
void updateBuffer(std::vector<OsciPoint>& buffer); void updateBuffer(std::vector<OsciPoint>& buffer);
void setPaused(bool paused); void setPaused(bool paused);
void handleAsyncUpdate() override;
private: private:
juce::OpenGLContext openGLContext; juce::OpenGLContext openGLContext;
@ -38,8 +39,7 @@ private:
juce::CriticalSection samplesLock; juce::CriticalSection samplesLock;
bool needsReattach = true; bool needsReattach = true;
std::vector<OsciPoint> samples = std::vector<OsciPoint>(2); std::vector<float> xSamples{2};
std::vector<float> xSamples;
std::vector<float> ySamples; std::vector<float> ySamples;
std::vector<float> zSamples; std::vector<float> zSamples;
std::vector<float> smoothedXSamples; std::vector<float> smoothedXSamples;
@ -78,19 +78,21 @@ private:
const double RESAMPLE_RATIO = 6.0; const double RESAMPLE_RATIO = 6.0;
double sampleRate = -1; double sampleRate = -1;
chowdsp::ResamplingTypes::LanczosResampler<4096, 8> resampler; chowdsp::ResamplingTypes::LanczosResampler<2048, 8> xResampler;
chowdsp::ResamplingTypes::LanczosResampler<2048, 8> yResampler;
chowdsp::ResamplingTypes::LanczosResampler<2048, 8> zResampler;
Texture makeTexture(int width, int height); Texture makeTexture(int width, int height);
void setupArrays(int num_points); void setupArrays(int num_points);
void setupTextures(); void setupTextures();
void drawLineTexture(std::vector<OsciPoint>& points); void drawLineTexture(const std::vector<float>& xPoints, const std::vector<float>& yPoints, const std::vector<float>& zPoints);
void saveTextureToFile(GLuint textureID, int width, int height, const juce::File& file); void saveTextureToFile(GLuint textureID, int width, int height, const juce::File& file);
void activateTargetTexture(std::optional<Texture> texture); void activateTargetTexture(std::optional<Texture> texture);
void setShader(juce::OpenGLShaderProgram* program); void setShader(juce::OpenGLShaderProgram* program);
void drawTexture(std::optional<Texture> texture0, std::optional<Texture> texture1 = std::nullopt, std::optional<Texture> texture2 = std::nullopt, std::optional<Texture> texture3 = std::nullopt); void drawTexture(std::optional<Texture> texture0, std::optional<Texture> texture1 = std::nullopt, std::optional<Texture> texture2 = std::nullopt, std::optional<Texture> texture3 = std::nullopt);
void setAdditiveBlending(); void setAdditiveBlending();
void setNormalBlending(); void setNormalBlending();
void drawLine(std::vector<OsciPoint>& points); void drawLine(const std::vector<float>& xPoints, const std::vector<float>& yPoints, const std::vector<float>& zPoints);
void fade(); void fade();
void drawCRT(); void drawCRT();
void checkGLErrors(const juce::String& location); void checkGLErrors(const juce::String& location);