Add basic volume visualiser with non-functioning sliders

pull/170/head
James Ball 2023-07-10 13:17:04 +01:00
rodzic 0a922847b4
commit afdd4483b3
10 zmienionych plików z 164 dodań i 51 usunięć

Wyświetl plik

@ -79,17 +79,10 @@ MainComponent::MainComponent(OscirenderAudioProcessor& p, OscirenderAudioProcess
};
addAndMakeVisible(visualiser);
audioProcessor.audioProducer.registerConsumer(consumer);
visualiserProcessor.startThread();
addAndMakeVisible(frequencyLabel);
pitchDetector.startThread();
}
MainComponent::~MainComponent() {
audioProcessor.audioProducer.unregisterConsumer(consumer);
visualiserProcessor.stopThread(1000);
}
MainComponent::~MainComponent() {}
void MainComponent::updateFileLabel() {
if (audioProcessor.getCurrentFileIndex() == -1) {

Wyświetl plik

@ -29,8 +29,6 @@ private:
juce::TextButton createFile{"Create File"};
VisualiserComponent visualiser{2, audioProcessor};
std::shared_ptr<BufferConsumer> consumer = std::make_shared<BufferConsumer>(2048);
VisualiserProcessor visualiserProcessor{consumer, visualiser};
juce::Label frequencyLabel;
PitchDetector pitchDetector{

Wyświetl plik

@ -1,22 +1,14 @@
/*
==============================================================================
This file contains the basic framework code for a JUCE plugin editor.
==============================================================================
*/
#include "PluginProcessor.h"
#include "PluginEditor.h"
//==============================================================================
OscirenderAudioProcessorEditor::OscirenderAudioProcessorEditor(OscirenderAudioProcessor& p)
: AudioProcessorEditor(&p), audioProcessor(p), effects(p), main(p, *this), collapseButton("Collapse", juce::Colours::white, juce::Colours::white, juce::Colours::white), lua(p, *this), obj(p, *this)
: AudioProcessorEditor(&p), audioProcessor(p), collapseButton("Collapse", juce::Colours::white, juce::Colours::white, juce::Colours::white)
{
addAndMakeVisible(effects);
addAndMakeVisible(main);
addChildComponent(lua);
addChildComponent(obj);
addAndMakeVisible(volume);
addAndMakeVisible(collapseButton);
collapseButton.onClick = [this] {
@ -54,7 +46,6 @@ OscirenderAudioProcessorEditor::OscirenderAudioProcessorEditor(OscirenderAudioPr
OscirenderAudioProcessorEditor::~OscirenderAudioProcessorEditor() {}
//==============================================================================
void OscirenderAudioProcessorEditor::paint(juce::Graphics& g)
{
g.fillAll(getLookAndFeel().findColour(juce::ResizableWindow::backgroundColourId));
@ -65,6 +56,7 @@ void OscirenderAudioProcessorEditor::paint (juce::Graphics& g)
void OscirenderAudioProcessorEditor::resized() {
auto area = getLocalBounds();
volume.setBounds(area.removeFromLeft(50));
auto sections = 2;
int index = audioProcessor.getCurrentFileIndex();
if (index != -1) {

Wyświetl plik

@ -6,6 +6,7 @@
#include "MainComponent.h"
#include "LuaComponent.h"
#include "ObjComponent.h"
#include "components/VolumeComponent.h"
class OscirenderAudioProcessorEditor : public juce::AudioProcessorEditor, private juce::CodeDocument::Listener {
@ -22,10 +23,11 @@ public:
private:
OscirenderAudioProcessor& audioProcessor;
MainComponent main;
LuaComponent lua;
ObjComponent obj;
EffectsComponent effects;
MainComponent main{audioProcessor, *this};
LuaComponent lua{audioProcessor, *this};
ObjComponent obj{audioProcessor, *this};
EffectsComponent effects{audioProcessor};
VolumeComponent volume{audioProcessor};
std::vector<std::shared_ptr<juce::CodeDocument>> codeDocuments;
std::vector<std::shared_ptr<juce::CodeEditorComponent>> codeEditors;
juce::LuaTokeniser luaTokeniser;

Wyświetl plik

@ -1,7 +1,9 @@
#include "PitchDetector.h"
#include "PitchDetector.h"
PitchDetector::PitchDetector(OscirenderAudioProcessor& p, std::function<void(float)> frequencyCallback) : juce::Thread("PitchDetector"), audioProcessor(p), frequencyCallback(frequencyCallback) {}
PitchDetector::PitchDetector(OscirenderAudioProcessor& p, std::function<void(float)> frequencyCallback) : juce::Thread("PitchDetector"), audioProcessor(p), frequencyCallback(frequencyCallback) {
startThread();
}
PitchDetector::~PitchDetector() {
audioProcessor.audioProducer.unregisterConsumer(consumer);

Wyświetl plik

@ -1,11 +1,15 @@
#include "VisualiserComponent.h"
VisualiserComponent::VisualiserComponent(int numChannels, OscirenderAudioProcessor& p) : numChannels(numChannels), backgroundColour(juce::Colours::black), waveformColour(juce::Colour(0xff00ff00)), audioProcessor(p) {
VisualiserComponent::VisualiserComponent(int numChannels, OscirenderAudioProcessor& p) : numChannels(numChannels), backgroundColour(juce::Colours::black), waveformColour(juce::Colour(0xff00ff00)), audioProcessor(p), juce::Thread("VisualiserComponent") {
setOpaque(true);
startTimerHz(60);
startThread();
}
VisualiserComponent::~VisualiserComponent() {}
VisualiserComponent::~VisualiserComponent() {
audioProcessor.audioProducer.unregisterConsumer(consumer);
stopThread(1000);
}
void VisualiserComponent::setBuffer(std::vector<float>& newBuffer) {
juce::SpinLock::ScopedLockType scope(lock);
@ -40,6 +44,16 @@ void VisualiserComponent::timerCallback() {
repaint();
}
void VisualiserComponent::run() {
audioProcessor.audioProducer.registerConsumer(consumer);
while (!threadShouldExit()) {
auto buffer = consumer->startProcessing();
setBuffer(*buffer);
consumer->finishedProcessing();
}
}
void VisualiserComponent::paintChannel(juce::Graphics& g, juce::Rectangle<float> area, int channel) {
juce::Path path;

Wyświetl plik

@ -4,7 +4,7 @@
#include "../concurrency/BufferConsumer.h"
#include "../PluginProcessor.h"
class VisualiserComponent : public juce::Component, public juce::Timer {
class VisualiserComponent : public juce::Component, public juce::Timer, public juce::Thread {
public:
VisualiserComponent(int numChannels, OscirenderAudioProcessor& p);
~VisualiserComponent() override;
@ -15,6 +15,7 @@ public:
void paintXY(juce::Graphics&, juce::Rectangle<float> bounds);
void paint(juce::Graphics&) override;
void timerCallback() override;
void run() override;
private:
juce::SpinLock lock;
@ -22,26 +23,8 @@ private:
int numChannels = 2;
juce::Colour backgroundColour, waveformColour;
OscirenderAudioProcessor& audioProcessor;
std::shared_ptr<BufferConsumer> consumer = std::make_shared<BufferConsumer>(2048);
int precision = 2;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(VisualiserComponent)
};
class VisualiserProcessor : public juce::Thread {
public:
VisualiserProcessor(std::shared_ptr<BufferConsumer> consumer, VisualiserComponent& visualiser) : juce::Thread("VisualiserProcessor"), consumer(consumer), visualiser(visualiser) {}
~VisualiserProcessor() override {}
void run() override {
while (!threadShouldExit()) {
auto buffer = consumer->startProcessing();
visualiser.setBuffer(*buffer);
consumer->finishedProcessing();
}
}
private:
std::shared_ptr<BufferConsumer> consumer;
VisualiserComponent& visualiser;
};

Wyświetl plik

@ -0,0 +1,95 @@
#include "VolumeComponent.h"
VolumeComponent::VolumeComponent(OscirenderAudioProcessor& p) : audioProcessor(p), juce::Thread("VolumeComponent") {
setOpaque(false);
startTimerHz(60);
startThread();
addAndMakeVisible(volumeSlider);
volumeSlider.setSliderStyle(juce::Slider::SliderStyle::LinearVertical);
volumeSlider.setTextBoxStyle(juce::Slider::NoTextBox, true, 0, 0);
volumeSlider.setColour(juce::Slider::ColourIds::backgroundColourId, juce::Colours::transparentWhite);
volumeSlider.setColour(juce::Slider::ColourIds::trackColourId, juce::Colours::transparentWhite);
volumeSlider.setOpaque(false);
volumeSlider.setRange(0, 1, 0.001);
addAndMakeVisible(thresholdSlider);
thresholdSlider.setSliderStyle(juce::Slider::SliderStyle::LinearVertical);
thresholdSlider.setTextBoxStyle(juce::Slider::NoTextBox, true, 0, 0);
thresholdSlider.setColour(juce::Slider::ColourIds::backgroundColourId, juce::Colours::transparentWhite);
thresholdSlider.setColour(juce::Slider::ColourIds::trackColourId, juce::Colours::transparentWhite);
thresholdSlider.setOpaque(false);
thresholdSlider.setRange(0, 1, 0.001);
}
VolumeComponent::~VolumeComponent() {
audioProcessor.audioProducer.unregisterConsumer(consumer);
stopThread(1000);
}
void VolumeComponent::paint(juce::Graphics& g) {
auto r = getLocalBounds().toFloat();
r.removeFromRight(r.getWidth() / 2);
g.setColour(juce::Colours::white);
g.fillRect(r);
auto channelHeight = r.getHeight();
auto leftVolumeHeight = channelHeight * leftVolume;
auto rightVolumeHeight = channelHeight * rightVolume;
auto leftRect = r.removeFromLeft(r.getWidth() / 2);
auto rightRect = r;
auto leftRegion = leftRect;
auto rightRegion = rightRect;
g.setGradientFill(juce::ColourGradient(juce::Colours::green, 0, leftRect.getBottom(), juce::Colours::red, 0, leftRect.getY(), false));
g.fillRect(leftRect.removeFromBottom(leftVolumeHeight));
g.setGradientFill(juce::ColourGradient(juce::Colours::green, 0, rightRect.getBottom(), juce::Colours::red, 0, rightRect.getY(), false));
g.fillRect(rightRect.removeFromBottom(rightVolumeHeight));
// draw average volume as new rectangles on each channel 10 pixels tall
g.setColour(juce::Colours::black);
g.fillRect(leftRegion.getX(), leftRegion.getBottom() - (avgLeftVolume * channelHeight), leftRegion.getWidth(), 5.0f);
g.fillRect(rightRegion.getX(), rightRegion.getBottom() - (avgRightVolume * channelHeight), rightRegion.getWidth(), 5.0f);
}
void VolumeComponent::timerCallback() {
repaint();
}
void VolumeComponent::run() {
audioProcessor.audioProducer.registerConsumer(consumer);
while (!threadShouldExit()) {
auto buffer = consumer->startProcessing();
float leftVolume = 0;
float rightVolume = 0;
for (int i = 0; i < buffer->size(); i += 2) {
leftVolume += buffer->at(i) * buffer->at(i);
rightVolume += buffer->at(i + 1) * buffer->at(i + 1);
}
// RMS
leftVolume = std::sqrt(leftVolume / (buffer->size() / 2));
rightVolume = std::sqrt(rightVolume / (buffer->size() / 2));
this->leftVolume = leftVolume;
this->rightVolume = rightVolume;
avgLeftVolume = (avgLeftVolume * 0.95) + (leftVolume * 0.05);
avgRightVolume = (avgRightVolume * 0.95) + (rightVolume * 0.05);
consumer->finishedProcessing();
}
}
void VolumeComponent::resized() {
auto r = getLocalBounds();
volumeSlider.setBounds(r.removeFromLeft(r.getWidth() / 2));
thresholdSlider.setBounds(r);
}

Wyświetl plik

@ -0,0 +1,30 @@
#pragma once
#include <JuceHeader.h>
#include "../concurrency/BufferConsumer.h"
#include "../PluginProcessor.h"
class VolumeComponent : public juce::Component, public juce::Timer, public juce::Thread {
public:
VolumeComponent(OscirenderAudioProcessor& p);
~VolumeComponent() override;
void paint(juce::Graphics&) override;
void timerCallback() override;
void run() override;
void resized() override;
private:
OscirenderAudioProcessor& audioProcessor;
std::shared_ptr<BufferConsumer> consumer = std::make_shared<BufferConsumer>(1 << 11);
std::atomic<float> leftVolume = 0;
std::atomic<float> rightVolume = 0;
std::atomic<float> avgLeftVolume = 0;
std::atomic<float> avgRightVolume = 0;
juce::Slider volumeSlider;
juce::Slider thresholdSlider;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(VolumeComponent)
};

Wyświetl plik

@ -127,6 +127,10 @@
file="Source/components/VisualiserComponent.cpp"/>
<FILE id="ZueyNl" name="VisualiserComponent.h" compile="0" resource="0"
file="Source/components/VisualiserComponent.h"/>
<FILE id="s8EVcE" name="VolumeComponent.cpp" compile="1" resource="0"
file="Source/components/VolumeComponent.cpp"/>
<FILE id="MWkfTv" name="VolumeComponent.h" compile="0" resource="0"
file="Source/components/VolumeComponent.h"/>
</GROUP>
<GROUP id="{85A33213-D880-BD92-70D8-1901DA6D23F0}" name="audio">
<FILE id="NWuowi" name="BitCrushEffect.cpp" compile="1" resource="0"