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]; auto effect = effects[i];
effect->setValue(0.5); effect->setValue(0.5);
audioProcessor.enableEffect(effect); audioProcessor.enableEffect(effect);
itemData.data.push_back(effect);
} }
itemData.data.push_back(juce::String("Item 1")); /*addBtn.setButtonText("Add Item...");
itemData.data.push_back(juce::String("Item 2"));
itemData.data.push_back(juce::String("Item 3"));
addBtn.setButtonText("Add Item...");
addBtn.onClick = [this]() addBtn.onClick = [this]()
{ {
itemData.data.push_back(juce::String("Item " + juce::String(1 + itemData.getNumItems()))); itemData.data.push_back(juce::String("Item " + juce::String(1 + itemData.getNumItems())));
listBox.updateContent(); listBox.updateContent();
}; };
addAndMakeVisible(addBtn); addAndMakeVisible(addBtn);*/
listBox.setModel(&listBoxModel); listBox.setModel(&listBoxModel);
listBox.setRowHeight(40); listBox.setRowHeight(30);
addAndMakeVisible(listBox); addAndMakeVisible(listBox);
} }

Wyświetl plik

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

Wyświetl plik

@ -8,15 +8,16 @@ public:
~BitCrushEffect(); ~BitCrushEffect();
Vector2 apply(int index, Vector2 input) override; Vector2 apply(int index, Vector2 input) override;
double getValue() override;
void setValue(double value) override; void setValue(double value) override;
void setFrequency(double frequency) override; void setFrequency(double frequency) override;
int getPrecedence() override; int getPrecedence() override;
void setPrecedence(int precedence) override; void setPrecedence(int precedence) override;
juce::String getName() override;
juce::String getId() override;
private: private:
double value = 0.0; double value = 0.0;
double frequency = 1.0; double frequency = 1.0;
int precedence = -1; 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)); return Vector2(rn * cos(theta), rn * sin(theta));
} }
double BulgeEffect::getValue() {
return value;
}
void BulgeEffect::setValue(double value) { void BulgeEffect::setValue(double value) {
this->value = value; this->value = value;
} }
@ -29,3 +33,11 @@ int BulgeEffect::getPrecedence() {
void BulgeEffect::setPrecedence(int precedence) { void BulgeEffect::setPrecedence(int precedence) {
this->precedence = 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();
~BulgeEffect(); ~BulgeEffect();
Vector2 apply(int index, Vector2 input) override; Vector2 apply(int index, Vector2 input) override;
double getValue() override;
void setValue(double value) override; void setValue(double value) override;
void setFrequency(double frequency) override; void setFrequency(double frequency) override;
int getPrecedence() override; int getPrecedence() override;
void setPrecedence(int precedence) override; void setPrecedence(int precedence) override;
juce::String getName() override;
juce::String getId() override;
private: private:
double value = 0.0; double value = 0.0;

Wyświetl plik

@ -1,13 +1,17 @@
#pragma once #pragma once
#include "../shape/Vector2.h" #include "../shape/Vector2.h"
#include <JuceHeader.h>
class Effect { class Effect {
public: public:
Effect(); Effect();
virtual Vector2 apply(int index, Vector2 input) = 0; virtual Vector2 apply(int index, Vector2 input) = 0;
virtual double getValue() = 0;
virtual void setValue(double value) = 0; virtual void setValue(double value) = 0;
virtual void setFrequency(double frequency) = 0; virtual void setFrequency(double frequency) = 0;
virtual int getPrecedence() = 0; virtual int getPrecedence() = 0;
virtual void setPrecedence(int precedence) = 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" #include "MyListComponent.h"
MyListComponent::MyListComponent(DraggableListBox& lb, MyListBoxItemData& data, int rn) MyListComponent::MyListComponent(DraggableListBox& lb, MyListBoxItemData& data, int rn) : DraggableListBoxItem(lb, data, rn) {
: DraggableListBoxItem(lb, data, rn) addAndMakeVisible(slider);
{ addAndMakeVisible(label);
actionBtn.setButtonText("Action");
actionBtn.onClick = [this]()
{
((MyListBoxItemData&)modelData).doItemAction(rowNum);
};
addAndMakeVisible(actionBtn);
deleteBtn.setButtonText("Delete"); label.setText(data.getText(rn), juce::dontSendNotification);
deleteBtn.onClick = [this]() label.attachToComponent(&slider, true);
{
modelData.deleteItem(rowNum); slider.setSliderStyle(juce::Slider::LinearHorizontal);
listBox.updateContent(); slider.setTextBoxStyle(juce::Slider::TextBoxRight, false, 90, slider.getTextBoxHeight());
}; slider.setRange(0.0, 1.0, 0.01);
addAndMakeVisible(deleteBtn); 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); modelData.paintContents(rowNum, g, dataArea);
DraggableListBoxItem::paint(g); DraggableListBoxItem::paint(g);
} }
void MyListComponent::resized() void MyListComponent::resized() {
{ auto sliderLeft = 100;
dataArea = getLocalBounds(); slider.setBounds(sliderLeft, 0, getWidth() - 110, getHeight());
actionBtn.setBounds(dataArea.removeFromLeft(70).withSizeKeepingCentre(56, 24));
deleteBtn.setBounds(dataArea.removeFromRight(70).withSizeKeepingCentre(56, 24));
} }
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)); std::unique_ptr<MyListComponent> item(dynamic_cast<MyListComponent*>(existingComponentToUpdate));
if (juce::isPositiveAndBelow(rowNumber, modelData.getNumItems())) if (juce::isPositiveAndBelow(rowNumber, modelData.getNumItems()))
{ {

Wyświetl plik

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