Add functional sliders for bit crush and bulge

pull/170/head
James Ball 2023-03-28 13:12:41 +01:00
rodzic 0ed2a10ac4
commit 3056ae3997
8 zmienionych plików z 89 dodań i 70 usunięć

Wyświetl plik

@ -23,22 +23,19 @@ EffectsComponent::EffectsComponent(OscirenderAudioProcessor& p) : audioProcessor
auto effect = effects[i];
effect->setValue(0.5);
audioProcessor.enableEffect(effect);
itemData.data.push_back(effect);
}
itemData.data.push_back(juce::String("Item 1"));
itemData.data.push_back(juce::String("Item 2"));
itemData.data.push_back(juce::String("Item 3"));
addBtn.setButtonText("Add Item...");
/*addBtn.setButtonText("Add Item...");
addBtn.onClick = [this]()
{
itemData.data.push_back(juce::String("Item " + juce::String(1 + itemData.getNumItems())));
listBox.updateContent();
};
addAndMakeVisible(addBtn);
addAndMakeVisible(addBtn);*/
listBox.setModel(&listBoxModel);
listBox.setRowHeight(40);
listBox.setRowHeight(30);
addAndMakeVisible(listBox);
}

Wyświetl plik

@ -4,9 +4,20 @@ BitCrushEffect::BitCrushEffect() {}
BitCrushEffect::~BitCrushEffect() {}
// algorithm from https://www.kvraudio.com/forum/viewtopic.php?t=163880
Vector2 BitCrushEffect::apply(int index, Vector2 input) {
double crush = 3.0 * (1.0 - value);
return Vector2(bitCrush(input.x, crush), bitCrush(input.y, crush));
// change rage of value from 0-1 to 0.0-0.78
double rangedValue = value * 0.78;
double powValue = pow(2.0f, 1.0 - rangedValue) - 1.0;
double crush = powValue * 12;
double x = powf(2.0f, crush);
double quant = 0.5 * x;
double dequant = 1.0f / quant;
return Vector2(dequant * (int)(input.x * quant), dequant * (int)(input.y * quant));
}
double BitCrushEffect::getValue() {
return value;
}
void BitCrushEffect::setValue(double value) {
@ -25,9 +36,10 @@ void BitCrushEffect::setPrecedence(int precedence) {
this->precedence = precedence;
}
double BitCrushEffect::bitCrush(double value, double places) {
long factor = (long) pow(10, places);
value = value * factor;
long tmp = round(value);
return (double) tmp / factor;
juce::String BitCrushEffect::getName() {
return juce::String("Bit Crush");
}
juce::String BitCrushEffect::getId() {
return juce::String("bitCrush");
}

Wyświetl plik

@ -8,15 +8,16 @@ public:
~BitCrushEffect();
Vector2 apply(int index, Vector2 input) override;
double getValue() override;
void setValue(double value) override;
void setFrequency(double frequency) override;
int getPrecedence() override;
void setPrecedence(int precedence) override;
juce::String getName() override;
juce::String getId() override;
private:
double value = 0.0;
double frequency = 1.0;
int precedence = -1;
double bitCrush(double value, double places);
};

Wyświetl plik

@ -14,6 +14,10 @@ Vector2 BulgeEffect::apply(int index, Vector2 input) {
return Vector2(rn * cos(theta), rn * sin(theta));
}
double BulgeEffect::getValue() {
return value;
}
void BulgeEffect::setValue(double value) {
this->value = value;
}
@ -29,3 +33,11 @@ int BulgeEffect::getPrecedence() {
void BulgeEffect::setPrecedence(int precedence) {
this->precedence = precedence;
}
juce::String BulgeEffect::getName() {
return juce::String("Bulge");
}
juce::String BulgeEffect::getId() {
return juce::String("bulge");
}

Wyświetl plik

@ -7,13 +7,14 @@ public:
BulgeEffect();
~BulgeEffect();
Vector2 apply(int index, Vector2 input) override;
double getValue() override;
void setValue(double value) override;
void setFrequency(double frequency) override;
int getPrecedence() override;
void setPrecedence(int precedence) override;
juce::String getName() override;
juce::String getId() override;
private:
double value = 0.0;

Wyświetl plik

@ -1,13 +1,17 @@
#pragma once
#include "../shape/Vector2.h"
#include <JuceHeader.h>
class Effect {
public:
Effect();
virtual Vector2 apply(int index, Vector2 input) = 0;
virtual double getValue() = 0;
virtual void setValue(double value) = 0;
virtual void setFrequency(double frequency) = 0;
virtual int getPrecedence() = 0;
virtual void setPrecedence(int precedence) = 0;
virtual juce::String getName() = 0;
virtual juce::String getId() = 0;
};

Wyświetl plik

@ -1,45 +1,35 @@
#include "MyListComponent.h"
MyListComponent::MyListComponent(DraggableListBox& lb, MyListBoxItemData& data, int rn)
: DraggableListBoxItem(lb, data, rn)
{
actionBtn.setButtonText("Action");
actionBtn.onClick = [this]()
{
((MyListBoxItemData&)modelData).doItemAction(rowNum);
};
addAndMakeVisible(actionBtn);
MyListComponent::MyListComponent(DraggableListBox& lb, MyListBoxItemData& data, int rn) : DraggableListBoxItem(lb, data, rn) {
addAndMakeVisible(slider);
addAndMakeVisible(label);
deleteBtn.setButtonText("Delete");
deleteBtn.onClick = [this]()
{
modelData.deleteItem(rowNum);
listBox.updateContent();
};
addAndMakeVisible(deleteBtn);
label.setText(data.getText(rn), juce::dontSendNotification);
label.attachToComponent(&slider, true);
slider.setSliderStyle(juce::Slider::LinearHorizontal);
slider.setTextBoxStyle(juce::Slider::TextBoxRight, false, 90, slider.getTextBoxHeight());
slider.setRange(0.0, 1.0, 0.01);
slider.setValue(data.getValue(rn), juce::dontSendNotification);
slider.onValueChange = [this] {
((MyListBoxItemData&)modelData).setValue(rowNum, slider.getValue());
};
}
MyListComponent::~MyListComponent()
{
}
MyListComponent::~MyListComponent() {}
void MyListComponent::paint (juce::Graphics& g)
{
void MyListComponent::paint (juce::Graphics& g) {
modelData.paintContents(rowNum, g, dataArea);
DraggableListBoxItem::paint(g);
}
void MyListComponent::resized()
{
dataArea = getLocalBounds();
actionBtn.setBounds(dataArea.removeFromLeft(70).withSizeKeepingCentre(56, 24));
deleteBtn.setBounds(dataArea.removeFromRight(70).withSizeKeepingCentre(56, 24));
void MyListComponent::resized() {
auto sliderLeft = 100;
slider.setBounds(sliderLeft, 0, getWidth() - 110, getHeight());
}
juce::Component* MyListBoxModel::refreshComponentForRow(int rowNumber, bool isRowSelected, juce::Component *existingComponentToUpdate)
{
juce::Component* MyListBoxModel::refreshComponentForRow(int rowNumber, bool isRowSelected, juce::Component *existingComponentToUpdate) {
std::unique_ptr<MyListComponent> item(dynamic_cast<MyListComponent*>(existingComponentToUpdate));
if (juce::isPositiveAndBelow(rowNumber, modelData.getNumItems()))
{

Wyświetl plik

@ -1,39 +1,33 @@
#pragma once
#include "DraggableListBox.h"
#include <JuceHeader.h>
#include "../audio/Effect.h"
// Application-specific data container
struct MyListBoxItemData : public DraggableListBoxItemData
{
std::vector<juce::String> data;
std::vector<std::shared_ptr<Effect>> data;
int getNumItems() override
{
int getNumItems() override {
return data.size();
}
void deleteItem(int indexOfItemToDelete) override
{
void deleteItem(int indexOfItemToDelete) override {
data.erase(data.begin() + indexOfItemToDelete);
}
void addItemAtEnd() override
{
data.push_back(juce::String("Yahoo"));
void addItemAtEnd() override {
// data.push_back(juce::String("Yahoo"));
}
void paintContents(int rowNum, juce::Graphics& g, juce::Rectangle<int> bounds) override
{
void paintContents(int rowNum, juce::Graphics& g, juce::Rectangle<int> bounds) override {
g.fillAll(juce::Colours::lightgrey);
g.setColour(juce::Colours::black);
g.drawRect(bounds);
if (rowNum < data.size()) {
g.drawText(data[rowNum], bounds, juce::Justification::centred);
}
}
void moveBefore(int indexOfItemToMove, int indexOfItemToPlaceBefore) override {
juce::String temp = data[indexOfItemToMove];
auto temp = data[indexOfItemToMove];
if (indexOfItemToMove < indexOfItemToPlaceBefore) {
move(data, indexOfItemToMove, indexOfItemToPlaceBefore - 1);
@ -43,7 +37,7 @@ struct MyListBoxItemData : public DraggableListBoxItemData
}
void moveAfter(int indexOfItemToMove, int indexOfItemToPlaceAfter) override {
juce::String temp = data[indexOfItemToMove];
auto temp = data[indexOfItemToMove];
if (indexOfItemToMove <= indexOfItemToPlaceAfter) {
move(data, indexOfItemToMove, indexOfItemToPlaceAfter);
@ -52,20 +46,25 @@ struct MyListBoxItemData : public DraggableListBoxItemData
}
}
template <typename t> void move(std::vector<t>& v, size_t oldIndex, size_t newIndex)
{
template <typename t> void move(std::vector<t>& v, size_t oldIndex, size_t newIndex) {
if (oldIndex > newIndex) {
std::rotate(v.rend() - oldIndex - 1, v.rend() - oldIndex, v.rend() - newIndex);
} else {
std::rotate(v.begin() + oldIndex, v.begin() + oldIndex + 1, v.begin() + newIndex + 1);
}
}
// This is an example of an operation on a single list item.
void doItemAction(int itemIndex)
{
DBG(data[itemIndex]);
void setValue(int itemIndex, double value) {
data[itemIndex]->setValue(value);
}
juce::String getText(int itemIndex) {
return data[itemIndex]->getName();
}
double getValue(int itemIndex) {
return data[itemIndex]->getValue();
}
};
// Custom list-item Component (which includes item-delete button)
@ -80,7 +79,10 @@ public:
protected:
juce::Rectangle<int> dataArea;
juce::TextButton actionBtn, deleteBtn;
juce::Slider slider;
juce::Label label;
juce::String id;
private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(MyListComponent)