kopia lustrzana https://github.com/jameshball/osci-render
Add basic volume visualiser with non-functioning sliders
rodzic
0a922847b4
commit
afdd4483b3
|
@ -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) {
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -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,8 +46,7 @@ OscirenderAudioProcessorEditor::OscirenderAudioProcessorEditor(OscirenderAudioPr
|
|||
|
||||
OscirenderAudioProcessorEditor::~OscirenderAudioProcessorEditor() {}
|
||||
|
||||
//==============================================================================
|
||||
void OscirenderAudioProcessorEditor::paint (juce::Graphics& g)
|
||||
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) {
|
||||
|
|
|
@ -6,14 +6,15 @@
|
|||
#include "MainComponent.h"
|
||||
#include "LuaComponent.h"
|
||||
#include "ObjComponent.h"
|
||||
#include "components/VolumeComponent.h"
|
||||
|
||||
|
||||
class OscirenderAudioProcessorEditor : public juce::AudioProcessorEditor, private juce::CodeDocument::Listener {
|
||||
public:
|
||||
OscirenderAudioProcessorEditor (OscirenderAudioProcessor&);
|
||||
OscirenderAudioProcessorEditor(OscirenderAudioProcessor&);
|
||||
~OscirenderAudioProcessorEditor() override;
|
||||
|
||||
void paint (juce::Graphics&) override;
|
||||
void paint(juce::Graphics&) override;
|
||||
void resized() override;
|
||||
|
||||
void addCodeEditor(int index);
|
||||
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
|
@ -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);
|
||||
}
|
|
@ -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)
|
||||
};
|
|
@ -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"
|
||||
|
|
Ładowanie…
Reference in New Issue