// // Created by versustune on 11.06.20. // #include "Waveforms.h" #include #include "../../../Core/Config.h" #include "../../../Utils.h" #include "../../../VenoInstance.h" #include "../../../Fonts/Fonts.h" Waveforms::Waveforms(const std::string &processId) : BaseComponent(processId) { m_context.setOpenGLVersionRequired(OpenGLContext::OpenGLVersion::openGL3_2); m_context.setRenderer(this); m_context.setContinuousRepainting(false); m_context.setComponentPaintingEnabled(true); m_context.attachTo(*this); auto fps = Config::getInstance()->getFps(); startTimerHz(Config::getInstance()->getFps()); std::srand(unsigned(time(nullptr))); pickRandomText = (std::rand() % RANDOM_TEXT_COUNT); m_ticks = 0; // is something that m_time_needed = roundToInt(4000 / (1000 / fps)); m_time_needed_startup = roundToInt(1000 / (1000 / fps)); } Waveforms::~Waveforms() { stopTimer(); shaderProgram.reset(); m_context.detach(); } void Waveforms::newOpenGLContextCreated() { compileOpenGLShaderProgram(); } void Waveforms::openGLContextClosing() { } void Waveforms::renderOpenGL() { if (!isShowing() || shaderProgram == nullptr || !shaderProgram->getLastError().isEmpty()) { return; } auto theme = Config::getInstance()->getCurrentTheme(); if (theme == nullptr) { return; } glViewport(0, 0, getWidth(), getHeight()); OpenGLHelpers::clear(theme->getColour(ThemeColour::lcd_bg)); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); shaderProgram->use(); auto color = theme->getColour(ThemeColour::lcd); shaderProgram->setUniform("color", color.getFloatRed(), color.getFloatGreen(), color.getFloatBlue(), color.getFloatAlpha()); if (m_isWelcome || m_isStarting || m_isChangingData) { return; } switch (m_mode) { case 1: drawAudioOutput(); break; case 2: drawWaveTable(); break; case 3: drawSpectrum(); break; default: drawPeakMeter(); } } void Waveforms::handleAsyncUpdate() { } void Waveforms::compileOpenGLShaderProgram() { std::unique_ptr shaderProgramAttempt = std::make_unique(m_context); if (shaderProgramAttempt->addVertexShader({BinaryData::WaveForm_vertex_glsl}) && shaderProgramAttempt->addFragmentShader({BinaryData::WaveForm_fragment_glsl}) && shaderProgramAttempt->link()) { shaderProgram = std::move(shaderProgramAttempt); } } void Waveforms::mouseDown(const MouseEvent &e) { if (!m_enableModeToggle) { return; } m_mode++; if (m_mode > 3) { m_mode = 0; } } void Waveforms::mouseDrag(const MouseEvent &e) { //do nothing... you faggot } void Waveforms::timerCallback() { if (m_isWelcome || m_isStarting || m_isChangingData || needToClear) { repaint(); } else { if (m_context.isAttached()) { m_context.triggerRepaint(); } } } void Waveforms::drawWaveTable() { // this will draw the current selected oscillator :D } void Waveforms::drawAudioOutput() { // draw audio from the oscillators auto instance = VenoInstance::getInstance(BaseComponent::m_processId); auto buffer = instance->audioBuffer->getBuffer(); glBegin(GL_LINE_STRIP); float posX = -1; float inc = 2.0f / buffer.size(); for (float i : buffer) { glVertex2f(posX, i); posX += inc; } glEnd(); } void Waveforms::drawPeakMeter() { auto theme = Config::getInstance()->getCurrentTheme(); if (theme == nullptr) { return; } auto instance = VenoInstance::getInstance(BaseComponent::m_processId); instance->audioBuffer->calcPeak(); // draw peak signal auto leftChannel = jmap(Decibels::gainToDecibels(instance->audioBuffer->leftPeak, -80.0f), -80.0f, 6.0f, -1.0f, 1.0f); selectColourByPeak(leftChannel); glBegin(GL_TRIANGLES); glVertex2f(-0.9f, leftChannel); glVertex2f(-0.9f, -1.0f); glVertex2f(-0.01f, -1.0f); glVertex2f(-0.9f, leftChannel); glVertex2f(-0.01f, leftChannel); glVertex2f(-0.01f, -1.0f); glEnd(); auto rightChannel = jmap(Decibels::gainToDecibels(instance->audioBuffer->rightPeak, -80.0f), -80.0f, 6.0f, -1.0f, 1.0f); selectColourByPeak(rightChannel); glBegin(GL_TRIANGLES); glVertex2f(0.9f, rightChannel); glVertex2f(0.9f, -1.0f); glVertex2f(0.01f, -1.0f); glVertex2f(0.9f, rightChannel); glVertex2f(0.01f, rightChannel); glVertex2f(0.01f, -1.0f); glEnd(); } void Waveforms::paint(Graphics &g) { std::shared_ptr theme = Config::getInstance()->getCurrentTheme(); auto accent = theme->getColour(ThemeColour::lcd); g.setColour(accent); g.setFont(VenoFonts::getLCD()); VeNo::Utils::setFontSize(16.0f, g); if (m_isWelcome) { drawWelcome(g, getWidth(), getHeight(), 0, 0); m_ticks++; if (m_ticks > m_time_needed_startup) { m_isWelcome = false; m_ticks = 0; needToClear = true; } } else if (m_isStarting) { g.drawText(m_warmUpText[pickRandomText], 0, 0, getWidth(), getHeight(), Justification::centred, true); m_ticks++; if (m_ticks > m_time_needed_startup) { m_isStarting = false; m_ticks = 0; needToClear = true; } } else if (m_isChangingData) { drawChangedParameter(g, getWidth(), getHeight(), 0, 0); m_ticks++; if (m_ticks > m_time_needed) { m_isChangingData = false; m_ticks = 0; needToClear = true; } } else { g.resetToDefaultState(); needToClear = false; } } void Waveforms::drawChangedParameter(Graphics &g, int w, int h, int x, int y) const { int halfHeight = h / 2; float font = VeNo::Utils::setFontSize(12, g); g.drawText(changingParameter, x, y + halfHeight - font, w, font, Justification::centred, true); g.drawText(std::to_string(changedValue), x, y + halfHeight + 4, w, font, Justification::centred, true); } void Waveforms::drawWelcome(Graphics &g, int w, int h, int x, int y) { float font = VeNo::Utils::setFontSize(12, g); int halfHeight = h / 2; g.drawText(m_readyText, x, y + halfHeight - font, w, font, Justification::centred, true); g.drawText(SystemStats::getLogonName(), x, y + halfHeight + 4, w, font, Justification::centred, true); } void Waveforms::drawSpectrum() { } void Waveforms::selectColourByPeak(float value) { auto theme = Config::getInstance()->getCurrentTheme(); if (theme == nullptr) { return; } auto color = theme->getColour(ThemeColour::lcd); if (value > 0.8 && value < 0.9) { color = theme->getColour(ThemeColour::warning); } if (value > 0.9) { color = theme->getColour(ThemeColour::clip); } shaderProgram->setUniform("color", color.getFloatRed(), color.getFloatGreen(), color.getFloatBlue(), color.getFloatAlpha()); }