From 473708a427288f4941d85cc0cefb0f5929a1cbae Mon Sep 17 00:00:00 2001 From: Anthony Hall Date: Tue, 9 Sep 2025 17:51:31 -0700 Subject: [PATCH] Overhaul zoom and rotation, modify parameter details --- Source/audio/SpiralBitCrushEffect.h | 52 ++++++++++++++++++----------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/Source/audio/SpiralBitCrushEffect.h b/Source/audio/SpiralBitCrushEffect.h index b3fbe897..713fda1a 100644 --- a/Source/audio/SpiralBitCrushEffect.h +++ b/Source/audio/SpiralBitCrushEffect.h @@ -5,11 +5,12 @@ class SpiralBitCrushEffect : public osci::EffectApplication { public: osci::Point apply(int index, osci::Point input, const std::vector> &values, double sampleRate) override { // Completing one revolution in input space traverses the hypotenuse of one "domain" in log-polar space - double effectScale = juce::jlimit(0.0, 1.0, values[0].load()); - double domainX = juce::jmax(2.0, std::floor(values[1].load() + 0.0001)); + double effectScale = juce::jlimit(0.0, 1.0, values[0].load()); + double domainX = juce::jmax(2.0, std::floor(values[1].load() + 0.001)); double domainY = std::round(domainX * values[2].load()); - osci::Point offset(values[3].load(), values[4].load()); - + double zoom = values[3].load() * juce::MathConstants::twoPi; // Use same scale as angle + double rotation = values[4].load() * juce::MathConstants::twoPi; + double domainHypot = std::hypot(domainX, domainY); double domainTheta = std::atan2(domainY, domainX); double scale = domainHypot / juce::MathConstants::twoPi; @@ -22,17 +23,17 @@ public: double r = std::hypot(input.x, input.y); double logR = std::log(r); double theta = std::atan2(input.x, -input.y); - osci::Point logPolarCoords(theta, logR); + osci::Point logPolarCoords(theta - rotation, logR - zoom); logPolarCoords.rotate(0, 0, domainTheta); - logPolarCoords = logPolarCoords * scale - offset; + logPolarCoords = logPolarCoords * scale; // Round this point to the center of the log-polar cell the input lies in, convert back to Cartesian logPolarCoords.x = std::round(logPolarCoords.x); logPolarCoords.y = std::round(logPolarCoords.y); - logPolarCoords = (logPolarCoords + offset) / scale; + logPolarCoords = logPolarCoords / scale; logPolarCoords.rotate(0, 0, -domainTheta); - double outR = std::exp(logPolarCoords.y); - double outTheta = logPolarCoords.x; + double outR = std::exp(logPolarCoords.y + zoom); + double outTheta = logPolarCoords.x + rotation; output.x = outR * std::sin(outTheta); output.y = outR * -std::cos(outTheta); } @@ -42,24 +43,35 @@ public: if (input.z != 0) { double signZ = input.z > 0 ? 1.0 : -1.0; double logZ = std::log(std::abs(input.z)); - logZ = logZ * scale - offset.y; + logZ = (logZ - zoom) * scale; logZ = std::round(logZ); - logZ = (logZ + offset.y) / scale; + logZ = logZ / scale + zoom; output.z = signZ * std::exp(logZ); } return (1 - effectScale) * input + effectScale * output; } std::shared_ptr build() const override { - auto eff = std::make_shared( - std::make_shared(), - std::vector{ - new osci::EffectParameter("Spiral Bit Crush", "Constrains points to a spiral pattern.", "spiralBitCrushEnable", VERSION_HINT, 1.0, 0.0, 1.0), - new osci::EffectParameter("Spiral Density", "Controls the density of the spiral pattern.", "spiralDensity", VERSION_HINT, 13.0, 3.0, 30.0), - new osci::EffectParameter("Spiral Twist", "Controls how much the spiral pattern twists.", "spiralTwist", VERSION_HINT, -0.6, -1.0, 1.0), - new osci::EffectParameter("Angle Offset", "Rotates the spiral pattern.", "spiralOffsetX", VERSION_HINT, 0.0, 0.0, 1.0, 0.0001, osci::LfoType::Sawtooth, 0.4), - new osci::EffectParameter("Radial Offset", "Zooms the spiral pattern.", "spiralOffsetY", VERSION_HINT, 0.0, 0.0, 1.0, 0.0001, osci::LfoType::Sawtooth, 1.0) - }); + auto eff = std::make_shared( + std::make_shared(), + std::vector{ + new osci::EffectParameter("Spiral Bit Crush", + "Constrains points to a spiral pattern.", + "spiralBitCrush", VERSION_HINT, 1.0, 0.0, 1.0), + new osci::EffectParameter("Spiral Density", + "Controls the density of the spiral pattern.", + "spiralBitCrushDensity", VERSION_HINT, 13.0, 3.0, 30.0, 1.0), + new osci::EffectParameter("Spiral Twist", + "Controls how much the spiral pattern twists.", + "spiralBitCrushTwist", VERSION_HINT, 0.6, -1.0, 1.0), + new osci::EffectParameter("Zoom", + "Zooms the spiral pattern.", + "spiralBitCrushZoom", VERSION_HINT, 0.0, 0.0, 1.0, 0.0001, osci::LfoType::Sawtooth, 0.05), + new osci::EffectParameter("Rotation", + "Rotates the spiral pattern.", + "spiralBitCrushRotation", VERSION_HINT, 0.0, 0.0, 1.0, 0.0001, osci::LfoType::ReverseSawtooth, 0.02) + } + ); eff->setIcon(BinaryData::swirl_svg); return eff; }