kopia lustrzana https://github.com/jameshball/osci-render
Merge pull request #251 from jameshball/wav-file-input
Fix visualiser bugs, add support for .wav and .aiff files, and add brightness slider to visualiserpull/252/head
commit
49af99ebfe
|
@ -103,7 +103,8 @@
|
|||
sweepMsDiv : 1,
|
||||
sweepTriggerValue : 0,
|
||||
mainGain : 0.0,
|
||||
exposureStops : 0.0,
|
||||
brightness : 0.0,
|
||||
intensity: 0.02,
|
||||
hue : 125,
|
||||
invertXY : false,
|
||||
grid : true,
|
||||
|
|
|
@ -297,7 +297,7 @@ var Render =
|
|||
|
||||
this.activateTargetTexture(null);
|
||||
this.setShader(this.outputShader);
|
||||
var brightness = Math.pow(2, controls.exposureStops-2.0);
|
||||
var brightness = Math.pow(2, controls.brightness-2.0);
|
||||
//if (controls.disableFilter) brightness *= Filter.steps;
|
||||
gl.uniform1f(this.outputShader.uExposure, brightness);
|
||||
gl.uniform1f(this.outputShader.uResizeForCanvas, this.lineTexture.width/1024);
|
||||
|
@ -433,7 +433,7 @@ var Render =
|
|||
if (controls.invertXY) gl.uniform1f(program.uInvert, -1.0);
|
||||
else gl.uniform1f(program.uInvert, 1.0);
|
||||
|
||||
var intensity = 0.02 * (41000 / externalSampleRate);
|
||||
var intensity = controls.intensity * (41000 / externalSampleRate);
|
||||
|
||||
if (controls.disableFilter) gl.uniform1f(program.uIntensity, intensity *(Filter.steps+1.5));
|
||||
// +1.5 needed above for some reason for the brightness to match
|
||||
|
@ -688,7 +688,8 @@ function doScriptProcessor(bufferBase64) {
|
|||
|
||||
const getSettingsFn = Juce.getNativeFunction("getSettings");
|
||||
getSettingsFn().then(settings => {
|
||||
controls.exposureStops = settings.intensity;
|
||||
controls.brightness = settings.brightness;
|
||||
controls.intensity = settings.intensity;
|
||||
controls.persistence = settings.persistence;
|
||||
controls.hue = settings.hue;
|
||||
controls.disableFilter = !settings.upsampling;
|
||||
|
|
|
@ -10,7 +10,7 @@ MainComponent::MainComponent(OscirenderAudioProcessor& p, OscirenderAudioProcess
|
|||
fileButton.setButtonText("Choose File(s)");
|
||||
|
||||
fileButton.onClick = [this] {
|
||||
chooser = std::make_unique<juce::FileChooser>("Open", audioProcessor.lastOpenedDirectory, "*.obj;*.svg;*.lua;*.txt;*.gpla;*.gif;*.png;*.jpg;*.jpeg");
|
||||
chooser = std::make_unique<juce::FileChooser>("Open", audioProcessor.lastOpenedDirectory, "*.obj;*.svg;*.lua;*.txt;*.gpla;*.gif;*.png;*.jpg;*.jpeg;*.wav;*.aiff");
|
||||
auto flags = juce::FileBrowserComponent::openMode | juce::FileBrowserComponent::canSelectMultipleItems |
|
||||
juce::FileBrowserComponent::canSelectFiles;
|
||||
|
||||
|
|
|
@ -102,6 +102,22 @@ OscirenderAudioProcessorEditor::OscirenderAudioProcessorEditor(OscirenderAudioPr
|
|||
addAndMakeVisible(lua);
|
||||
addAndMakeVisible(luaResizerBar);
|
||||
addAndMakeVisible(visualiser);
|
||||
|
||||
visualiser.openSettings = [this] {
|
||||
visualiserSettingsWindow.setVisible(true);
|
||||
visualiserSettingsWindow.toFront(true);
|
||||
};
|
||||
|
||||
visualiser.closeSettings = [this] {
|
||||
visualiserSettingsWindow.setVisible(false);
|
||||
};
|
||||
|
||||
visualiserSettingsWindow.setResizable(false, false);
|
||||
visualiserSettingsWindow.setUsingNativeTitleBar(true);
|
||||
visualiserSettings.setLookAndFeel(&getLookAndFeel());
|
||||
visualiserSettings.setSize(550, 260);
|
||||
visualiserSettingsWindow.setContentNonOwned(&visualiserSettings, true);
|
||||
visualiserSettingsWindow.centreWithSize(550, 260);
|
||||
|
||||
tooltipDropShadow.setOwner(&tooltipWindow);
|
||||
}
|
||||
|
@ -121,7 +137,7 @@ OscirenderAudioProcessorEditor::~OscirenderAudioProcessorEditor() {
|
|||
}
|
||||
|
||||
bool OscirenderAudioProcessorEditor::isBinaryFile(juce::String name) {
|
||||
return name.endsWith(".gpla") || name.endsWith(".gif") || name.endsWith(".png") || name.endsWith(".jpg") || name.endsWith(".jpeg");
|
||||
return name.endsWith(".gpla") || name.endsWith(".gif") || name.endsWith(".png") || name.endsWith(".jpg") || name.endsWith(".jpeg") || name.endsWith(".wav") || name.endsWith(".aiff");
|
||||
}
|
||||
|
||||
// parsersLock must be held
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "LookAndFeel.h"
|
||||
#include "components/ErrorCodeEditorComponent.h"
|
||||
#include "components/LuaConsole.h"
|
||||
#include "components/VisualiserSettings.h"
|
||||
|
||||
class OscirenderAudioProcessorEditor : public juce::AudioProcessorEditor, private juce::CodeDocument::Listener, public juce::AsyncUpdater, public juce::ChangeListener {
|
||||
public:
|
||||
|
@ -48,7 +49,10 @@ public:
|
|||
|
||||
std::atomic<bool> editingCustomFunction = false;
|
||||
|
||||
VisualiserComponent visualiser{audioProcessor, nullptr, audioProcessor.legacyVisualiserEnabled->getBoolValue()};
|
||||
VisualiserSettings visualiserSettings = VisualiserSettings(audioProcessor);
|
||||
SettingsWindow visualiserSettingsWindow = SettingsWindow("Visualiser Settings");
|
||||
VisualiserComponent visualiser{audioProcessor, visualiserSettings, nullptr, audioProcessor.legacyVisualiserEnabled->getBoolValue()};
|
||||
|
||||
SettingsComponent settings{audioProcessor, *this};
|
||||
|
||||
juce::ComponentAnimator codeEditorAnimator;
|
||||
|
|
|
@ -149,6 +149,7 @@ OscirenderAudioProcessor::OscirenderAudioProcessor()
|
|||
permanentEffects.push_back(thresholdEffect);
|
||||
permanentEffects.push_back(imageThreshold);
|
||||
permanentEffects.push_back(imageStride);
|
||||
permanentEffects.push_back(brightnessEffect);
|
||||
permanentEffects.push_back(intensityEffect);
|
||||
permanentEffects.push_back(persistenceEffect);
|
||||
permanentEffects.push_back(hueEffect);
|
||||
|
|
|
@ -180,10 +180,18 @@ public:
|
|||
VERSION_HINT, 125, 0, 359, 1
|
||||
)
|
||||
);
|
||||
std::shared_ptr<Effect> brightnessEffect = std::make_shared<Effect>(
|
||||
new EffectParameter(
|
||||
"Brightness",
|
||||
"Controls how bright the light glows for on the oscilloscope display.",
|
||||
"brightness",
|
||||
VERSION_HINT, 3.0, 0.0, 10.0
|
||||
)
|
||||
);
|
||||
std::shared_ptr<Effect> intensityEffect = std::make_shared<Effect>(
|
||||
new EffectParameter(
|
||||
"Intensity",
|
||||
"Controls how bright the light glows for on the oscilloscope display.",
|
||||
"Controls how bright the electron beam of the oscilloscope is.",
|
||||
"intensity",
|
||||
VERSION_HINT, 3.0, 0.0, 10.0
|
||||
)
|
||||
|
|
|
@ -1,20 +1,13 @@
|
|||
#include "../LookAndFeel.h"
|
||||
#include "VisualiserComponent.h"
|
||||
|
||||
VisualiserComponent::VisualiserComponent(OscirenderAudioProcessor& p, VisualiserComponent* parent, bool useOldVisualiser) : backgroundColour(juce::Colours::black), waveformColour(juce::Colour(0xff00ff00)), audioProcessor(p), oldVisualiser(useOldVisualiser), juce::Thread("VisualiserComponent"), parent(parent) {
|
||||
VisualiserComponent::VisualiserComponent(OscirenderAudioProcessor& p, VisualiserSettings& settings, VisualiserComponent* parent, bool useOldVisualiser) : settings(settings), backgroundColour(juce::Colours::black), waveformColour(juce::Colour(0xff00ff00)), audioProcessor(p), oldVisualiser(useOldVisualiser), juce::Thread("VisualiserComponent"), parent(parent) {
|
||||
setVisualiserType(oldVisualiser);
|
||||
|
||||
resetBuffer();
|
||||
startTimerHz(60);
|
||||
startThread();
|
||||
|
||||
settingsWindow.setResizable(false, false);
|
||||
settingsWindow.setUsingNativeTitleBar(true);
|
||||
settings.setLookAndFeel(&getLookAndFeel());
|
||||
settings.setSize(550, 230);
|
||||
settingsWindow.setContentNonOwned(&settings, true);
|
||||
settingsWindow.centreWithSize(550, 230);
|
||||
|
||||
setMouseCursor(juce::MouseCursor::PointingHandCursor);
|
||||
setWantsKeyboardFocus(true);
|
||||
|
||||
|
@ -228,6 +221,9 @@ void VisualiserComponent::setVisualiserType(bool oldVisualiser) {
|
|||
}
|
||||
if (oldVisualiser) {
|
||||
browser.reset();
|
||||
if (closeSettings != nullptr) {
|
||||
closeSettings();
|
||||
}
|
||||
} else {
|
||||
initialiseBrowser();
|
||||
}
|
||||
|
@ -349,8 +345,10 @@ void VisualiserComponent::childChanged() {
|
|||
}
|
||||
|
||||
void VisualiserComponent::popoutWindow() {
|
||||
auto visualiser = new VisualiserComponent(audioProcessor, this, oldVisualiser);
|
||||
auto visualiser = new VisualiserComponent(audioProcessor, settings, this, oldVisualiser);
|
||||
visualiser->settings.setLookAndFeel(&getLookAndFeel());
|
||||
visualiser->openSettings = openSettings;
|
||||
visualiser->closeSettings = closeSettings;
|
||||
child = visualiser;
|
||||
childChanged();
|
||||
popOutButton.setVisible(false);
|
||||
|
@ -365,8 +363,3 @@ void VisualiserComponent::popoutWindow() {
|
|||
resized();
|
||||
popOutButton.setVisible(false);
|
||||
}
|
||||
|
||||
void VisualiserComponent::openSettings() {
|
||||
settingsWindow.setVisible(true);
|
||||
settingsWindow.toFront(true);
|
||||
}
|
||||
|
|
|
@ -18,10 +18,12 @@ enum class FullScreenMode {
|
|||
class VisualiserWindow;
|
||||
class VisualiserComponent : public juce::Component, public juce::Timer, public juce::Thread, public juce::MouseListener, public juce::SettableTooltipClient {
|
||||
public:
|
||||
VisualiserComponent(OscirenderAudioProcessor& p, VisualiserComponent* parent = nullptr, bool useOldVisualiser = false);
|
||||
VisualiserComponent(OscirenderAudioProcessor& p, VisualiserSettings& settings, VisualiserComponent* parent = nullptr, bool useOldVisualiser = false);
|
||||
~VisualiserComponent() override;
|
||||
|
||||
void openSettings();
|
||||
std::function<void()> openSettings;
|
||||
std::function<void()> closeSettings;
|
||||
|
||||
void childChanged();
|
||||
void enableFullScreen();
|
||||
void setFullScreenCallback(std::function<void(FullScreenMode)> callback);
|
||||
|
@ -76,8 +78,8 @@ private:
|
|||
std::shared_ptr<BufferConsumer> consumer;
|
||||
|
||||
std::function<void(FullScreenMode)> fullScreenCallback;
|
||||
VisualiserSettings settings = VisualiserSettings(audioProcessor, *this);
|
||||
SettingsWindow settingsWindow = SettingsWindow("Visualiser Settings");
|
||||
|
||||
VisualiserSettings& settings;
|
||||
|
||||
juce::WebBrowserComponent::ResourceProvider provider = [this](const juce::String& path) {
|
||||
juce::String mimeType;
|
||||
|
|
|
@ -2,14 +2,17 @@
|
|||
#include "VisualiserComponent.h"
|
||||
#include "../PluginEditor.h"
|
||||
|
||||
VisualiserSettings::VisualiserSettings(OscirenderAudioProcessor& p, VisualiserComponent& visualiser) : audioProcessor(p), visualiser(visualiser) {
|
||||
addAndMakeVisible(intensity);
|
||||
|
||||
VisualiserSettings::VisualiserSettings(OscirenderAudioProcessor& p) : audioProcessor(p) {
|
||||
addAndMakeVisible(brightness);
|
||||
addAndMakeVisible(intensity);
|
||||
addAndMakeVisible(persistence);
|
||||
addAndMakeVisible(hue);
|
||||
addAndMakeVisible(graticuleToggle);
|
||||
addAndMakeVisible(smudgeToggle);
|
||||
addAndMakeVisible(upsamplingToggle);
|
||||
|
||||
brightness.setSliderOnValueChange();
|
||||
intensity.setSliderOnValueChange();
|
||||
persistence.setSliderOnValueChange();
|
||||
hue.setSliderOnValueChange();
|
||||
|
@ -20,6 +23,7 @@ VisualiserSettings::~VisualiserSettings() {}
|
|||
void VisualiserSettings::resized() {
|
||||
auto area = getLocalBounds().reduced(20);
|
||||
double rowHeight = 30;
|
||||
brightness.setBounds(area.removeFromTop(rowHeight));
|
||||
intensity.setBounds(area.removeFromTop(rowHeight));
|
||||
persistence.setBounds(area.removeFromTop(rowHeight));
|
||||
hue.setBounds(area.removeFromTop(rowHeight));
|
||||
|
@ -30,7 +34,8 @@ void VisualiserSettings::resized() {
|
|||
|
||||
juce::var VisualiserSettings::getSettings() {
|
||||
auto settings = new juce::DynamicObject();
|
||||
settings->setProperty("intensity", audioProcessor.intensityEffect->getActualValue() - 2);
|
||||
settings->setProperty("brightness", audioProcessor.brightnessEffect->getActualValue() - 2);
|
||||
settings->setProperty("intensity", audioProcessor.intensityEffect->getActualValue() / 100);
|
||||
settings->setProperty("persistence", audioProcessor.persistenceEffect->getActualValue() - 1.33);
|
||||
settings->setProperty("hue", audioProcessor.hueEffect->getActualValue());
|
||||
settings->setProperty("graticule", audioProcessor.graticuleEnabled->getBoolValue());
|
||||
|
|
|
@ -6,18 +6,17 @@
|
|||
#include "../LookAndFeel.h"
|
||||
#include "SwitchButton.h"
|
||||
|
||||
class VisualiserComponent;
|
||||
class VisualiserSettings : public juce::Component {
|
||||
public:
|
||||
VisualiserSettings(OscirenderAudioProcessor&, VisualiserComponent&);
|
||||
VisualiserSettings(OscirenderAudioProcessor&);
|
||||
~VisualiserSettings();
|
||||
|
||||
void resized() override;
|
||||
juce::var getSettings();
|
||||
private:
|
||||
OscirenderAudioProcessor& audioProcessor;
|
||||
VisualiserComponent& visualiser;
|
||||
|
||||
EffectComponent brightness{audioProcessor, *audioProcessor.brightnessEffect};
|
||||
EffectComponent intensity{audioProcessor, *audioProcessor.intensityEffect};
|
||||
EffectComponent persistence{audioProcessor, *audioProcessor.persistenceEffect};
|
||||
EffectComponent hue{audioProcessor, *audioProcessor.hueEffect};
|
||||
|
|
|
@ -18,6 +18,7 @@ void FileParser::parse(juce::String fileId, juce::String extension, std::unique_
|
|||
gpla = nullptr;
|
||||
lua = nullptr;
|
||||
img = nullptr;
|
||||
wav = nullptr;
|
||||
|
||||
if (extension == ".obj") {
|
||||
object = std::make_shared<WorldObject>(stream->readEntireStreamAsString().toStdString());
|
||||
|
@ -33,10 +34,12 @@ void FileParser::parse(juce::String fileId, juce::String extension, std::unique_
|
|||
juce::MemoryBlock buffer{};
|
||||
int bytesRead = stream->readIntoMemoryBlock(buffer);
|
||||
img = std::make_shared<ImageParser>(audioProcessor, extension, buffer);
|
||||
} else if (extension == ".wav" || extension == ".aiff") {
|
||||
wav = std::make_shared<WavParser>(audioProcessor, std::move(stream));
|
||||
}
|
||||
|
||||
isAnimatable = gpla != nullptr || (img != nullptr && extension == ".gif");
|
||||
sampleSource = lua != nullptr || img != nullptr;
|
||||
sampleSource = lua != nullptr || img != nullptr || wav != nullptr;
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<Shape>> FileParser::nextFrame() {
|
||||
|
@ -72,7 +75,9 @@ Point FileParser::nextSample(lua_State*& L, LuaVariables& vars) {
|
|||
}
|
||||
} else if (img != nullptr) {
|
||||
return img->getSample();
|
||||
}
|
||||
} else if (wav != nullptr) {
|
||||
return wav->getSample();
|
||||
}
|
||||
|
||||
return Point();
|
||||
}
|
||||
|
@ -122,3 +127,7 @@ std::shared_ptr<LuaParser> FileParser::getLua() {
|
|||
std::shared_ptr<ImageParser> FileParser::getImg() {
|
||||
return img;
|
||||
}
|
||||
|
||||
std::shared_ptr<WavParser> FileParser::getWav() {
|
||||
return wav;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "../gpla/LineArtParser.h"
|
||||
#include "../lua/LuaParser.h"
|
||||
#include "../img/ImageParser.h"
|
||||
#include "../wav/WavParser.h"
|
||||
|
||||
class OscirenderAudioProcessor;
|
||||
class FileParser {
|
||||
|
@ -29,6 +30,7 @@ public:
|
|||
std::shared_ptr<LineArtParser> getLineArt();
|
||||
std::shared_ptr<LuaParser> getLua();
|
||||
std::shared_ptr<ImageParser> getImg();
|
||||
std::shared_ptr<WavParser> getWav();
|
||||
|
||||
bool isAnimatable = false;
|
||||
|
||||
|
@ -46,6 +48,7 @@ private:
|
|||
std::shared_ptr<LineArtParser> gpla;
|
||||
std::shared_ptr<LuaParser> lua;
|
||||
std::shared_ptr<ImageParser> img;
|
||||
std::shared_ptr<WavParser> wav;
|
||||
|
||||
juce::String fallbackLuaScript = "return { 0.0, 0.0 }";
|
||||
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
#include "WavParser.h"
|
||||
#include "../PluginProcessor.h"
|
||||
|
||||
|
||||
WavParser::WavParser(OscirenderAudioProcessor& p, std::unique_ptr<juce::InputStream> stream) : audioProcessor(p) {
|
||||
juce::AudioFormatManager formatManager;
|
||||
formatManager.registerBasicFormats();
|
||||
juce::AudioFormatReader* reader = formatManager.createReaderFor(std::move(stream));
|
||||
auto* afSource = new juce::AudioFormatReaderSource(reader, true);
|
||||
afSource->setLooping(true);
|
||||
source = std::make_unique<juce::ResamplingAudioSource>(afSource, true);
|
||||
fileSampleRate = reader->sampleRate;
|
||||
audioBuffer.setSize(reader->numChannels, 1);
|
||||
setSampleRate(audioProcessor.currentSampleRate);
|
||||
source->prepareToPlay(1, audioProcessor.currentSampleRate);
|
||||
}
|
||||
|
||||
WavParser::~WavParser() {
|
||||
}
|
||||
|
||||
void WavParser::setSampleRate(double sampleRate) {
|
||||
double ratio = fileSampleRate / sampleRate;
|
||||
source->setResamplingRatio(ratio);
|
||||
source->prepareToPlay(1, sampleRate);
|
||||
currentSampleRate = sampleRate;
|
||||
}
|
||||
|
||||
Point WavParser::getSample() {
|
||||
if (currentSampleRate != audioProcessor.currentSampleRate) {
|
||||
setSampleRate(audioProcessor.currentSampleRate);
|
||||
}
|
||||
if (source == nullptr) {
|
||||
return Point();
|
||||
}
|
||||
|
||||
source->getNextAudioBlock(juce::AudioSourceChannelInfo(audioBuffer));
|
||||
|
||||
if (audioBuffer.getNumChannels() == 1) {
|
||||
return Point(audioBuffer.getSample(0, 0), audioBuffer.getSample(0, 0));
|
||||
} else {
|
||||
return Point(audioBuffer.getSample(0, 0), audioBuffer.getSample(1, 0));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
#pragma once
|
||||
#include "../shape/Point.h"
|
||||
#include <JuceHeader.h>
|
||||
|
||||
class OscirenderAudioProcessor;
|
||||
class WavParser {
|
||||
public:
|
||||
WavParser(OscirenderAudioProcessor& p, std::unique_ptr<juce::InputStream> stream);
|
||||
~WavParser();
|
||||
|
||||
Point getSample();
|
||||
|
||||
private:
|
||||
void setSampleRate(double sampleRate);
|
||||
|
||||
std::unique_ptr<juce::ResamplingAudioSource> source;
|
||||
juce::AudioBuffer<float> audioBuffer;
|
||||
int currentSample = 0;
|
||||
int fileSampleRate;
|
||||
int currentSampleRate;
|
||||
OscirenderAudioProcessor& audioProcessor;
|
||||
};
|
|
@ -584,6 +584,10 @@
|
|||
<FILE id="mC1tUv" name="ugen_JuceUtility.h" compile="0" resource="0"
|
||||
file="Source/UGen/ugen_JuceUtility.h"/>
|
||||
</GROUP>
|
||||
<GROUP id="{DC345620-B6F6-F3B9-D359-C265590B0F00}" name="wav">
|
||||
<FILE id="vYzJlF" name="WavParser.cpp" compile="1" resource="0" file="Source/wav/WavParser.cpp"/>
|
||||
<FILE id="ZRT5Xk" name="WavParser.h" compile="0" resource="0" file="Source/wav/WavParser.h"/>
|
||||
</GROUP>
|
||||
<FILE id="I44EdJ" name="EffectsComponent.cpp" compile="1" resource="0"
|
||||
file="Source/EffectsComponent.cpp"/>
|
||||
<FILE id="qxxNX3" name="EffectsComponent.h" compile="0" resource="0"
|
||||
|
|
Ładowanie…
Reference in New Issue