Skip to content

Commit

Permalink
Add sweep / V-T functionality and update mac icon
Browse files Browse the repository at this point in the history
  • Loading branch information
jameshball committed Jan 3, 2025
1 parent 587e82e commit bfe497c
Show file tree
Hide file tree
Showing 12 changed files with 126 additions and 22 deletions.
Binary file added Resources/images/osci_mac.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions Source/CommonPluginEditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ CommonPluginEditor::CommonPluginEditor(CommonAudioProcessor& p, juce::String app
};

visualiserSettings.setLookAndFeel(&getLookAndFeel());
visualiserSettings.setSize(550, 600);
visualiserSettingsWindow.centreWithSize(550, 450);
visualiserSettings.setSize(550, 550);
visualiserSettingsWindow.centreWithSize(550, 400);
#if JUCE_WINDOWS
// if not standalone, use native title bar for compatibility with DAWs
visualiserSettingsWindow.setUsingNativeTitleBar(processor.wrapperType == juce::AudioProcessor::WrapperType::wrapperType_Standalone);
Expand Down
1 change: 0 additions & 1 deletion Source/CommonPluginProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ CommonAudioProcessor::CommonAudioProcessor()
}

effects.push_back(visualiserParameters.smoothEffect);
permanentEffects.push_back(visualiserParameters.smoothEffect);

for (auto parameter : visualiserParameters.booleans) {
booleanParameters.push_back(parameter);
Expand Down
2 changes: 1 addition & 1 deletion Source/audio/EffectParameter.h
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ class EffectParameter : public FloatParameter {
public:
std::atomic<bool> smoothValueChange = true;
LfoTypeParameter* lfo = new LfoTypeParameter(name + " LFO", paramID + "Lfo", getVersionHint(), 1);
FloatParameter* lfoRate = new FloatParameter(name + " LFO Rate", paramID + "LfoRate", getVersionHint(), 1.0f, 0.0f, 1000.0f, 0.01f, "Hz");
FloatParameter* lfoRate = new FloatParameter(name + " LFO Rate", paramID + "LfoRate", getVersionHint(), 1.0f, 0.0f, 10000.0f, 0.01f, "Hz");
BooleanParameter* sidechain = new BooleanParameter(name + " Sidechain Enabled", paramID + "Sidechain", getVersionHint(), false, "Toggles " + name + " Sidechain.");
std::atomic<float> phase = 0.0f;
juce::String description;
Expand Down
1 change: 1 addition & 0 deletions Source/components/OsciMainMenuBarModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ OsciMainMenuBarModel::OsciMainMenuBarModel(OscirenderAudioProcessor& p, Oscirend
"A huge thank you to:\n"
"DJ_Level_3, for contributing several features to osci-render\n"
"BUS ERROR Collective, for providing the source code for the Hilligoss encoder\n"
"Jean Perbet (@jeanprbt) for the osci-render macOS icon\n"
"All the community, for suggesting features and reporting issues!\n\n"
"I am open for commissions! Email me at [email protected]."
);
Expand Down
74 changes: 66 additions & 8 deletions Source/visualiser/VisualiserComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,42 @@ void VisualiserComponent::runTask(const std::vector<OsciPoint>& points) {
xSamples.clear();
ySamples.clear();
zSamples.clear();
for (auto& point : points) {
OsciPoint smoothPoint = settings.parameters.smoothEffect->apply(0, point);
xSamples.push_back(smoothPoint.x);
ySamples.push_back(smoothPoint.y);
zSamples.push_back(smoothPoint.z);

if (settings.isSweepEnabled()) {
double sweepIncrement = getSweepIncrement();
long samplesPerSweep = sampleRate * settings.getSweepSeconds();

double triggerValue = settings.getTriggerValue();
bool belowTrigger = false;

for (auto& point : points) {
OsciPoint smoothPoint = settings.parameters.smoothEffect->apply(0, point);

long samplePosition = sampleCount - lastTriggerPosition;
double startPoint = 1.135;
double sweep = samplePosition * sweepIncrement * 2 * startPoint - startPoint;

double value = smoothPoint.x;

if (sweep > startPoint && belowTrigger && value >= triggerValue) {
lastTriggerPosition = sampleCount;
}

belowTrigger = value < triggerValue;

xSamples.push_back(sweep);
ySamples.push_back(value);
zSamples.push_back(1);

sampleCount++;
}
} else {
for (auto& point : points) {
OsciPoint smoothPoint = settings.parameters.smoothEffect->apply(0, point);
xSamples.push_back(smoothPoint.x);
ySamples.push_back(smoothPoint.y);
zSamples.push_back(smoothPoint.z);
}
}

sampleBufferCount++;
Expand All @@ -137,7 +168,25 @@ void VisualiserComponent::runTask(const std::vector<OsciPoint>& points) {
smoothedZSamples.resize(newResampledSize);
smoothedZSamples.resize(newResampledSize);

xResampler.process(xSamples.data(), smoothedXSamples.data(), xSamples.size());
if (settings.isSweepEnabled()) {
// interpolate between sweep values to avoid any artifacts from quickly going from one sweep to the next
for (int i = 0; i < newResampledSize; ++i) {
int index = i / RESAMPLE_RATIO;
if (index < xSamples.size() - 1) {
double thisSample = xSamples[index];
double nextSample = xSamples[index + 1];
if (nextSample > thisSample) {
smoothedXSamples[i] = xSamples[index] + (i % (int) RESAMPLE_RATIO) * (nextSample - thisSample) / RESAMPLE_RATIO;
} else {
smoothedXSamples[i] = xSamples[index];
}
} else {
smoothedXSamples[i] = xSamples[index];
}
}
} else {
xResampler.process(xSamples.data(), smoothedXSamples.data(), xSamples.size());
}
yResampler.process(ySamples.data(), smoothedYSamples.data(), ySamples.size());
zResampler.process(zSamples.data(), smoothedZSamples.data(), zSamples.size());
}
Expand Down Expand Up @@ -167,6 +216,10 @@ void VisualiserComponent::stopTask() {
renderingSemaphore.release();
}

double VisualiserComponent::getSweepIncrement() {
return 1.0 / (sampleRate * settings.getSweepSeconds());
}

void VisualiserComponent::setPaused(bool paused) {
active = !paused;
renderingSemaphore.release();
Expand Down Expand Up @@ -506,7 +559,11 @@ void VisualiserComponent::renderOpenGL() {
}

if (recordingAudio) {
audioRecorder.audioThreadCallback(xSamples, ySamples);
if (settings.isSweepEnabled()) {
audioRecorder.audioThreadCallback(ySamples, ySamples);
} else {
audioRecorder.audioThreadCallback(xSamples, ySamples);
}
}
}

Expand Down Expand Up @@ -753,7 +810,8 @@ void VisualiserComponent::drawLine(const std::vector<float>& xPoints, const std:
using namespace juce::gl;

setAdditiveBlending();


// TODO: need to add the last point from the previous frame to the start of the frame so they connect?
int nPoints = xPoints.size();

// Without this, there's an access violation that seems to occur only on some systems
Expand Down
4 changes: 4 additions & 0 deletions Source/visualiser/VisualiserComponent.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ class VisualiserComponent : public juce::Component, public AudioBackgroundThread
int nEdges = 0;

juce::CriticalSection samplesLock;
long sampleCount = 0;
std::vector<float> xSamples{2};
std::vector<float> ySamples{2};
std::vector<float> zSamples{2};
Expand All @@ -160,6 +161,7 @@ class VisualiserComponent : public juce::Component, public AudioBackgroundThread
std::vector<float> smoothedZSamples;
int sampleBufferCount = 0;
int prevSampleBufferCount = 0;
long lastTriggerPosition = 0;

std::vector<float> scratchVertices;
std::vector<float> fullScreenQuad;
Expand Down Expand Up @@ -242,6 +244,8 @@ class VisualiserComponent : public juce::Component, public AudioBackgroundThread

void renderScope(const std::vector<float>& xPoints, const std::vector<float>& yPoints, const std::vector<float>& zPoints);
int renderAudioFile(juce::File& sourceAudio, int method = 1, int width = 1024, int height = 1024);

double getSweepIncrement();

Texture createScreenTexture();
Texture createReflectionTexture();
Expand Down
17 changes: 12 additions & 5 deletions Source/visualiser/VisualiserSettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ VisualiserSettings::VisualiserSettings(VisualiserParameters& p, int numChannels)
addAndMakeVisible(glow);
addAndMakeVisible(ambient);
addAndMakeVisible(smooth);
addChildComponent(sweepMs);
addAndMakeVisible(sweepMs);
addAndMakeVisible(triggerValue);
addAndMakeVisible(upsamplingToggle);
addAndMakeVisible(sweepToggle);
addAndMakeVisible(screenTypeLabel);
Expand All @@ -37,9 +38,16 @@ VisualiserSettings::VisualiserSettings(VisualiserParameters& p, int numChannels)
ambient.setSliderOnValueChange();
smooth.setSliderOnValueChange();
sweepMs.setSliderOnValueChange();
triggerValue.setSliderOnValueChange();

sweepMs.setEnabled(sweepToggle.getToggleState());
triggerValue.setEnabled(sweepToggle.getToggleState());

sweepMs.slider.setSkewFactorFromMidPoint(100);

sweepToggle.onClick = [this] {
sweepMs.setVisible(sweepToggle.getToggleState());
sweepMs.setEnabled(sweepToggle.getToggleState());
triggerValue.setEnabled(sweepToggle.getToggleState());
resized();
};
}
Expand Down Expand Up @@ -68,7 +76,6 @@ void VisualiserSettings::resized() {
upsamplingToggle.setBounds(area.removeFromTop(rowHeight));

sweepToggle.setBounds(area.removeFromTop(rowHeight));
if (sweepToggle.getToggleState()) {
sweepMs.setBounds(area.removeFromTop(rowHeight));
}
sweepMs.setBounds(area.removeFromTop(rowHeight));
triggerValue.setBounds(area.removeFromTop(rowHeight));
}
27 changes: 24 additions & 3 deletions Source/visualiser/VisualiserSettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,11 +171,19 @@ class VisualiserParameters {
"Sweep (ms)",
"The number of milliseconds it takes for the oscilloscope to sweep from left to right.",
"sweepMs",
VERSION_HINT, 0.3, 0.0, 1.0
VERSION_HINT, 30.0, 0.0, 1000.0
)
);
std::shared_ptr<Effect> triggerValueEffect = std::make_shared<Effect>(
new EffectParameter(
"Trigger Value",
"The trigger value sets the signal level that starts waveform capture to display a stable waveform.",
"triggerValue",
VERSION_HINT, 0.0, -1.0, 1.0
)
);

std::vector<std::shared_ptr<Effect>> effects = {persistenceEffect, hueEffect, intensityEffect, saturationEffect, focusEffect, noiseEffect, glowEffect, ambientEffect, sweepMsEffect};
std::vector<std::shared_ptr<Effect>> effects = {persistenceEffect, hueEffect, intensityEffect, saturationEffect, focusEffect, noiseEffect, glowEffect, ambientEffect, sweepMsEffect, triggerValueEffect};
std::vector<BooleanParameter*> booleans = {upsamplingEnabled, visualiserFullScreen, sweepEnabled};
std::vector<IntParameter*> integers = {screenType};
};
Expand Down Expand Up @@ -226,6 +234,18 @@ class VisualiserSettings : public juce::Component {
bool getUpsamplingEnabled() {
return parameters.upsamplingEnabled->getBoolValue();
}

bool isSweepEnabled() {
return parameters.sweepEnabled->getBoolValue();
}

double getSweepSeconds() {
return parameters.sweepMsEffect->getActualValue() / 1000.0;
}

double getTriggerValue() {
return parameters.triggerValueEffect->getActualValue();
}

VisualiserParameters& parameters;
int numChannels;
Expand All @@ -241,6 +261,7 @@ class VisualiserSettings : public juce::Component {
EffectComponent ambient{*parameters.ambientEffect};
EffectComponent smooth{*parameters.smoothEffect};
EffectComponent sweepMs{*parameters.sweepMsEffect};
EffectComponent triggerValue{*parameters.triggerValueEffect};

juce::Label screenTypeLabel{"Screen Type", "Screen Type"};
juce::ComboBox screenType;
Expand All @@ -257,7 +278,7 @@ class SettingsWindow : public juce::DocumentWindow {
juce::Component::addAndMakeVisible(viewport);
setResizable(false, false);
viewport.setViewedComponent(&component, false);
viewport.setScrollBarsShown(false, false, true, false);
viewport.setScrollBarsShown(true, false, true, false);
setAlwaysOnTop(true);
}

Expand Down
9 changes: 9 additions & 0 deletions ci/setup-env.sh
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,15 @@ else
PROJUCER_PATH="$ROOT/ci/bin/JUCE/Projucer.exe"
fi

# Get the Spout SDK and SpoutLibrary.dll
if [ "$OS" = "win" ]; then
curl -s -S -L https://github.com/leadedge/Spout2/releases/download/2.007.015/Spout-SDK-binaries_2-007-015.zip -o Spout.zip
unzip Spout.zip
ls -R
# move to system32
cp Spout-SDK-binaries/2-007-015/Libs/MD/bin/SpoutLibrary.dll /c/Windows/System32
fi

# Set global path
GLOBAL_PATH_COMMAND="$PROJUCER_PATH --set-global-search-path $PROJUCER_OS 'defaultJuceModulePath' '$ROOT/ci/bin/JUCE/modules'"
eval "$GLOBAL_PATH_COMMAND"
Expand Down
7 changes: 5 additions & 2 deletions osci-render.jucer
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
</GROUP>
<GROUP id="{525C568C-29E9-D0A2-9773-8A04981C5575}" name="images">
<FILE id="jI9VSZ" name="logo.png" compile="0" resource="1" file="Resources/images/logo.png"/>
<FILE id="aZXbCi" name="osci_mac.png" compile="0" resource="1" file="Resources/images/osci_mac.png"/>
</GROUP>
<GROUP id="{C2609827-4F4A-1ADA-8BA1-A40C1D92649C}" name="lua">
<FILE id="xANsA8" name="demo.lua" compile="0" resource="1" file="Resources/lua/demo.lua"/>
Expand Down Expand Up @@ -775,8 +776,8 @@
</MODULEPATHS>
</VS2022>
<XCODE_MAC targetFolder="Builds/osci-render/MacOSX" extraLinkerFlags="-Wl,-weak_reference_mismatches,weak"
extraDefs="JUCE_SILENCE_XCODE_15_LINKER_WARNING=1" smallIcon="pSc1mq"
bigIcon="pSc1mq" applicationCategory="public.app-category.music"
extraDefs="JUCE_SILENCE_XCODE_15_LINKER_WARNING=1" smallIcon="aZXbCi"
bigIcon="aZXbCi" applicationCategory="public.app-category.music"
microphonePermissionNeeded="1" frameworkSearchPaths="../../../External/syphon"
embeddedFrameworks="../../../External/syphon/Syphon.framework"
extraCustomFrameworks="../../../External/syphon/Syphon.framework"
Expand All @@ -787,6 +788,8 @@
codeSigningIdentity="Developer ID Application: James Ball (D86A3M3H2L)"/>
<CONFIGURATION name="Release" targetName="osci-render" customXcodeFlags="LD_RUNPATH_SEARCH_PATHS = '@executable_path/../Frameworks' '@executable_path/',CODE_SIGN_INJECT_BASE_ENTITLEMENTS=NO,OTHER_CODE_SIGN_FLAGS = --timestamp --force --deep"
codeSigningIdentity="Developer ID Application: James Ball (D86A3M3H2L)"/>
<CONFIGURATION name="Release (Development)" targetName="osci-render" customXcodeFlags="LD_RUNPATH_SEARCH_PATHS = '@executable_path/../Frameworks' '@executable_path/',OTHER_CODE_SIGN_FLAGS = --timestamp --force --deep"
codeSigningIdentity="Developer ID Application: James Ball (D86A3M3H2L)"/>
</CONFIGURATIONS>
<MODULEPATHS>
<MODULEPATH id="juce_audio_basics" path="../../../JUCE/modules"/>
Expand Down
2 changes: 2 additions & 0 deletions sosci.jucer
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,8 @@
codeSigningIdentity="Developer ID Application: James Ball (D86A3M3H2L)"/>
<CONFIGURATION name="Release" targetName="sosci" customXcodeFlags="LD_RUNPATH_SEARCH_PATHS = '@executable_path/../Frameworks' '@executable_path/',CODE_SIGN_INJECT_BASE_ENTITLEMENTS=NO,OTHER_CODE_SIGN_FLAGS = --timestamp --force --deep"
codeSigningIdentity="Developer ID Application: James Ball (D86A3M3H2L)"/>
<CONFIGURATION name="Release (Development)" targetName="sosci" customXcodeFlags="LD_RUNPATH_SEARCH_PATHS = '@executable_path/../Frameworks' '@executable_path/',OTHER_CODE_SIGN_FLAGS = --timestamp --force --deep"
codeSigningIdentity="Developer ID Application: James Ball (D86A3M3H2L)"/>
</CONFIGURATIONS>
<MODULEPATHS>
<MODULEPATH id="juce_audio_basics" path="../../../JUCE/modules"/>
Expand Down

0 comments on commit bfe497c

Please sign in to comment.