pull/213/head
James Ball 2024-01-27 13:57:18 +00:00 zatwierdzone przez James H Ball
rodzic f5d3f83a2f
commit cad5bad853
10 zmienionych plików z 157 dodań i 25 usunięć

Wyświetl plik

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M12,9A3,3 0 0,1 15,12A3,3 0 0,1 12,15A3,3 0 0,1 9,12A3,3 0 0,1 12,9Z" /></svg>

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 222 B

Wyświetl plik

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M6,2H18V8H18V8L14,12L18,16V16H18V22H6V16H6V16L10,12L6,8V8H6V2M16,16.5L12,12.5L8,16.5V20H16V16.5M12,11.5L16,7.5V4H8V7.5L12,11.5M10,6H14V6.75L12,8.75L10,6.75V6Z" /></svg>

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 237 B

Wyświetl plik

@ -26,7 +26,7 @@ private:
std::unique_ptr<juce::FileChooser> chooser;
juce::TextButton fileButton;
juce::TextButton closeFileButton;
SvgButton inputEnabled{"inputEnabled", juce::String(BinaryData::microphone_svg), "white", "red", audioProcessor.inputEnabled};
SvgButton inputEnabled{"inputEnabled", juce::String(BinaryData::microphone_svg), juce::Colours::white, juce::Colours::red, audioProcessor.inputEnabled};
juce::Label fileLabel;
juce::TextEditor fileName;

Wyświetl plik

@ -27,9 +27,9 @@ private:
juce::TextButton resetRotation{"Reset Rotation"};
juce::ToggleButton mouseRotate{"Rotate with Mouse (Esc to disable)"};
std::shared_ptr<SvgButton> fixedRotateX = std::make_shared<SvgButton>("fixedRotateX", juce::String(BinaryData::fixed_rotate_svg), "white", "red", audioProcessor.fixedRotateX);
std::shared_ptr<SvgButton> fixedRotateY = std::make_shared<SvgButton>("fixedRotateY", juce::String(BinaryData::fixed_rotate_svg), "white", "red", audioProcessor.fixedRotateY);
std::shared_ptr<SvgButton> fixedRotateZ = std::make_shared<SvgButton>("fixedRotateZ", juce::String(BinaryData::fixed_rotate_svg), "white", "red", audioProcessor.fixedRotateZ);
std::shared_ptr<SvgButton> fixedRotateX = std::make_shared<SvgButton>("fixedRotateX", juce::String(BinaryData::fixed_rotate_svg), juce::Colours::white, juce::Colours::red, audioProcessor.fixedRotateX);
std::shared_ptr<SvgButton> fixedRotateY = std::make_shared<SvgButton>("fixedRotateY", juce::String(BinaryData::fixed_rotate_svg), juce::Colours::white, juce::Colours::red, audioProcessor.fixedRotateY);
std::shared_ptr<SvgButton> fixedRotateZ = std::make_shared<SvgButton>("fixedRotateZ", juce::String(BinaryData::fixed_rotate_svg), juce::Colours::white, juce::Colours::red, audioProcessor.fixedRotateZ);
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ObjComponent)
};

Wyświetl plik

@ -47,6 +47,7 @@
*******************************************************************************/
#pragma once
#include "DoubleTextBox.h"
//==============================================================================
class AudioRecorder final : public juce::Thread {
@ -115,6 +116,12 @@ public:
while (!threadShouldExit()) {
consumer = audioProcessor.consumerRegister(buffer);
audioProcessor.consumerRead(consumer);
if (nextSampleNum >= recordingLength * audioProcessor.currentSampleRate) {
stop();
stopCallback();
continue;
}
const juce::ScopedLock sl(writerLock);
int numSamples = buffer.size() / 2;
@ -135,6 +142,12 @@ public:
}
}
void setRecordLength(double recordLength) {
recordingLength = recordLength;
}
std::function<void()> stopCallback;
private:
OscirenderAudioProcessor& audioProcessor;
@ -145,6 +158,8 @@ private:
std::vector<float> buffer = std::vector<float>(2 << 12);
std::shared_ptr<BufferConsumer> consumer;
double recordingLength = 99999999999.0;
juce::CriticalSection writerLock;
std::atomic<juce::AudioFormatWriter::ThreadedWriter*> activeWriter { nullptr };
};
@ -177,10 +192,7 @@ public:
: juce::jmax(30.0, thumbnail.getTotalLength());
auto thumbArea = getLocalBounds();
thumbnail.drawChannels(g, thumbArea.reduced(2), 0.0, endTime, 2.0f);
} else {
g.setFont(14.0f);
g.drawFittedText("(No file recorded)", getLocalBounds(), juce::Justification::centred, 2);
thumbnail.drawChannels(g, thumbArea.reduced(2), 0.0, endTime, 1.0f);
}
}
@ -204,12 +216,35 @@ class AudioRecordingComponent final : public juce::Component {
public:
AudioRecordingComponent(OscirenderAudioProcessor& p) : audioProcessor(p) {
addAndMakeVisible(recordButton);
addAndMakeVisible(timedRecord);
addAndMakeVisible(recordLength);
recordButton.setTooltip("Start recording audio to a WAV file. Press again to stop and save the recording.");
timedRecord.setTooltip("Record for a set amount of time. When enabled, the recording will automatically stop once the time is reached.");
recordLength.setValue(1);
recordButton.onClick = [this] {
if (recorder.isRecording())
stopRecording();
else
startRecording();
if (recordButton.getToggleState()) {
startRecording();
} else {
stopRecording();
}
};
timedRecord.onClick = [this] {
if (timedRecord.getToggleState()) {
addAndMakeVisible(recordLength);
} else {
removeChildComponent(&recordLength);
}
resized();
};
recorder.stopCallback = [this] {
juce::MessageManager::callAsync([this] {
recordButton.setToggleState(false, juce::sendNotification);
});
};
addAndMakeVisible(recordingThumbnail);
@ -217,9 +252,16 @@ public:
}
void resized() override {
double iconSize = 25;
auto area = getLocalBounds();
recordButton.setBounds(area.removeFromLeft(80));
recordButton.setBounds(area.removeFromLeft(iconSize).withSizeKeepingCentre(iconSize, iconSize));
area.removeFromLeft(5);
timedRecord.setBounds(area.removeFromLeft(iconSize).withSizeKeepingCentre(iconSize, iconSize));
if (timedRecord.getToggleState()) {
recordLength.setBounds(area.removeFromLeft(80).withSizeKeepingCentre(60, 25));
}
area.removeFromLeft(5);
recordingThumbnail.setBounds(area);
}
@ -229,16 +271,22 @@ private:
RecordingThumbnail recordingThumbnail;
AudioRecorder recorder{ audioProcessor, recordingThumbnail.getAudioThumbnail() };
juce::TextButton recordButton{ "Record" };
SvgButton recordButton{ "record", BinaryData::record_svg, juce::Colours::white, juce::Colours::red };
juce::File lastRecording;
juce::FileChooser chooser { "Output file...", juce::File::getCurrentWorkingDirectory().getChildFile("recording.wav"), "*.wav" };
SvgButton timedRecord{ "timedRecord", BinaryData::timer_svg, juce::Colours::white, juce::Colours::red };
DoubleTextBox recordLength{ 0, 60 * 60 * 24 };
void startRecording() {
auto parentDir = juce::File::getSpecialLocation(juce::File::tempDirectory);
lastRecording = parentDir.getNonexistentChildFile("osci-render-recording", ".wav");
if (timedRecord.getToggleState()) {
recorder.setRecordLength(recordLength.getValue());
} else {
recorder.setRecordLength(99999999999.0);
}
recorder.startRecording(lastRecording);
recordButton.setButtonText("Stop");
recordButton.setColour(juce::TextButton::buttonColourId, juce::Colours::red);
recordButton.setColour(juce::TextButton::textColourOnId, juce::Colours::black);
@ -247,8 +295,6 @@ private:
void stopRecording() {
recorder.stop();
recordButton.setButtonText("Record");
recordButton.setColour(juce::TextButton::buttonColourId, findColour(juce::TextButton::buttonColourId));
recordButton.setColour(juce::TextButton::textColourOnId, findColour(juce::TextButton::textColourOnId));

Wyświetl plik

@ -0,0 +1,59 @@
#pragma once
#include <JuceHeader.h>
class DoubleTextBox : public juce::TextEditor {
public:
DoubleTextBox(double minValue, double maxValue) : minValue(minValue), maxValue(maxValue) {
setText(juce::String(minValue, 2), false);
setMultiLine(false);
setJustification(juce::Justification::centred);
setFont(juce::Font(15.0f, juce::Font::plain));
onTextChange = [this]() {
setText(getText(), false);
};
}
double getValue() {
return getText().getDoubleValue();
}
void setValue(double value, bool sendChangeMessage = true) {
setText(juce::String(value, 2), sendChangeMessage);
}
void setText(const juce::String& newText, bool sendChangeMessage = true) {
// remove all non-digits
juce::String text = newText.retainCharacters("0123456789.-");
// only keep first decimal point
int firstDecimal = text.indexOfChar('.');
if (firstDecimal != -1) {
juce::String remainder = text.substring(firstDecimal + 1);
remainder = remainder.retainCharacters("0123456789");
text = text.substring(0, firstDecimal + 1) + remainder;
}
// only keep negative sign at beginning
if (text.contains("-")) {
juce::String remainder = text.substring(1);
remainder = remainder.retainCharacters("0123456789");
text = text.substring(0, 1) + remainder;
}
double value = text.getDoubleValue();
if (value < minValue || value > maxValue) {
text = juce::String(prevValue);
} else {
prevValue = value;
}
juce::TextEditor::setText(text, sendChangeMessage);
}
~DoubleTextBox() override {}
private:
double minValue;
double maxValue;
double prevValue = minValue;
};

Wyświetl plik

@ -9,7 +9,7 @@ EffectComponent::EffectComponent(OscirenderAudioProcessor& p, Effect& effect, in
sidechainEnabled = effect.parameters[0]->sidechain != nullptr;
if (sidechainEnabled) {
sidechainButton = std::make_unique<SvgButton>(effect.parameters[0]->name, BinaryData::microphone_svg, "white", "red", effect.parameters[0]->sidechain);
sidechainButton = std::make_unique<SvgButton>(effect.parameters[0]->name, BinaryData::microphone_svg, juce::Colours::white, juce::Colours::red, effect.parameters[0]->sidechain);
sidechainButton->setTooltip("When enabled, the volume of the input audio controls the value of the slider, acting like a sidechain effect.");
addAndMakeVisible(*sidechainButton);
}

Wyświetl plik

@ -97,14 +97,14 @@ std::shared_ptr<juce::Component> EffectsListComponent::createComponent(EffectPar
toggle = audioProcessor.perspectiveEffect->fixedRotateZ;
axis = "Z";
}
std::shared_ptr<SvgButton> button = std::make_shared<SvgButton>(parameter->name, BinaryData::fixed_rotate_svg, "white", "red", toggle);
std::shared_ptr<SvgButton> button = std::make_shared<SvgButton>(parameter->name, BinaryData::fixed_rotate_svg, juce::Colours::white, juce::Colours::red, toggle);
button->setTooltip("Toggles whether the rotation around the " + axis + " axis is fixed, or changes according to the rotation speed.");
button->onClick = [this, toggle] {
toggle->setBoolValueNotifyingHost(!toggle->getBoolValue());
};
return button;
} else if (parameter->paramID == "perspectiveStrength") {
std::shared_ptr<SvgButton> button = std::make_shared<SvgButton>(parameter->name, BinaryData::pencil_svg, "white", "red");
std::shared_ptr<SvgButton> button = std::make_shared<SvgButton>(parameter->name, BinaryData::pencil_svg, juce::Colours::white, juce::Colours::red);
std::weak_ptr<SvgButton> weakButton = button;
button->setEdgeIndent(5);
button->setToggleState(editor.editingPerspective, juce::dontSendNotification);

Wyświetl plik

@ -3,19 +3,33 @@
class SvgButton : public juce::DrawableButton, public juce::AudioProcessorParameter::Listener, public juce::AsyncUpdater {
public:
SvgButton(juce::String name, juce::String svg, juce::String colour, juce::String colourOn, BooleanParameter* toggle = nullptr) : juce::DrawableButton(name, juce::DrawableButton::ButtonStyle::ImageFitted), toggle(toggle) {
SvgButton(juce::String name, juce::String svg, juce::Colour colour, juce::Colour colourOn, BooleanParameter* toggle = nullptr) : juce::DrawableButton(name, juce::DrawableButton::ButtonStyle::ImageFitted), toggle(toggle) {
auto doc = juce::XmlDocument::parse(svg);
changeSvgColour(doc.get(), colour);
normalImage = juce::Drawable::createFromSVG(*doc);
changeSvgColour(doc.get(), colour.withBrightness(0.7f));
overImage = juce::Drawable::createFromSVG(*doc);
changeSvgColour(doc.get(), colour.withBrightness(0.5f));
downImage = juce::Drawable::createFromSVG(*doc);
changeSvgColour(doc.get(), colour.withBrightness(0.3f));
disabledImage = juce::Drawable::createFromSVG(*doc);
changeSvgColour(doc.get(), colourOn);
normalImageOn = juce::Drawable::createFromSVG(*doc);
changeSvgColour(doc.get(), colourOn.withBrightness(0.7f));
overImageOn = juce::Drawable::createFromSVG(*doc);
changeSvgColour(doc.get(), colourOn.withBrightness(0.5f));
downImageOn = juce::Drawable::createFromSVG(*doc);
changeSvgColour(doc.get(), colourOn.withBrightness(0.3f));
disabledImageOn = juce::Drawable::createFromSVG(*doc);
getLookAndFeel().setColour(juce::DrawableButton::backgroundOnColourId, juce::Colours::transparentWhite);
if (colour != colourOn) {
setClickingTogglesState(true);
}
setImages(normalImage.get(), nullptr, nullptr, nullptr, normalImageOn.get());
setImages(normalImage.get(), overImage.get(), downImage.get(), disabledImage.get(), normalImageOn.get(), overImageOn.get(), downImageOn.get(), disabledImageOn.get());
if (toggle != nullptr) {
toggle->addListener(this);
@ -23,7 +37,7 @@ class SvgButton : public juce::DrawableButton, public juce::AudioProcessorParame
}
}
SvgButton(juce::String name, juce::String svg, juce::String colour) : SvgButton(name, svg, colour, colour) {}
SvgButton(juce::String name, juce::String svg, juce::Colour colour) : SvgButton(name, svg, colour, colour) {}
~SvgButton() override {
if (toggle != nullptr) {
@ -42,12 +56,20 @@ class SvgButton : public juce::DrawableButton, public juce::AudioProcessorParame
}
private:
std::unique_ptr<juce::Drawable> normalImage;
std::unique_ptr<juce::Drawable> overImage;
std::unique_ptr<juce::Drawable> downImage;
std::unique_ptr<juce::Drawable> disabledImage;
std::unique_ptr<juce::Drawable> normalImageOn;
std::unique_ptr<juce::Drawable> overImageOn;
std::unique_ptr<juce::Drawable> downImageOn;
std::unique_ptr<juce::Drawable> disabledImageOn;
BooleanParameter* toggle;
void changeSvgColour(juce::XmlElement* xml, juce::String colour) {
void changeSvgColour(juce::XmlElement* xml, juce::Colour colour) {
forEachXmlChildElement(*xml, xmlnode) {
xmlnode->setAttribute("fill", colour);
xmlnode->setAttribute("fill", '#' + colour.toDisplayString(false));
}
}
};

Wyświetl plik

@ -22,7 +22,9 @@
<FILE id="PxYKbt" name="microphone.svg" compile="0" resource="1" file="Resources/svg/microphone.svg"/>
<FILE id="pSc1mq" name="osci.svg" compile="0" resource="1" file="Resources/svg/osci.svg"/>
<FILE id="D2AI1b" name="pencil.svg" compile="0" resource="1" file="Resources/svg/pencil.svg"/>
<FILE id="n79IAy" name="record.svg" compile="0" resource="1" file="Resources/svg/record.svg"/>
<FILE id="rXjNlx" name="threshold.svg" compile="0" resource="1" file="Resources/svg/threshold.svg"/>
<FILE id="rFYmV8" name="timer.svg" compile="0" resource="1" file="Resources/svg/timer.svg"/>
<FILE id="qC6QiP" name="volume.svg" compile="0" resource="1" file="Resources/svg/volume.svg"/>
</GROUP>
<GROUP id="{F8A3D32C-4187-9A2F-5D78-040259957E9B}" name="text">
@ -106,6 +108,7 @@
<FILE id="kUinTt" name="ComponentList.cpp" compile="1" resource="0"
file="Source/components/ComponentList.cpp"/>
<FILE id="HGTPEW" name="ComponentList.h" compile="0" resource="0" file="Source/components/ComponentList.h"/>
<FILE id="IvySRY" name="DoubleTextBox.h" compile="0" resource="0" file="Source/components/DoubleTextBox.h"/>
<FILE id="poPVxL" name="DraggableListBox.cpp" compile="1" resource="0"
file="Source/components/DraggableListBox.cpp"/>
<FILE id="Y9NEGn" name="DraggableListBox.h" compile="0" resource="0"