kopia lustrzana https://github.com/jameshball/osci-render
Fix most major bugs with opengl implementation and add upsampling
rodzic
eff8b3f635
commit
8296014272
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"));
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Ładowanie…
Reference in New Issue