kopia lustrzana https://github.com/jameshball/osci-render
				
				
				
			Merge pull request #46 from jameshball/translate-effect
Add translate effect and other improvementspull/170/head
						commit
						26535b7a69
					
				| 
						 | 
				
			
			@ -129,5 +129,6 @@ void MainComponent::resized() {
 | 
			
		|||
	frequencyLabel.setBounds(bounds.removeFromTop(20));
 | 
			
		||||
 | 
			
		||||
	bounds.removeFromTop(padding);
 | 
			
		||||
	visualiser.setBounds(bounds);
 | 
			
		||||
	auto minDim = juce::jmin(bounds.getWidth(), bounds.getHeight());
 | 
			
		||||
	visualiser.setBounds(bounds.withSizeKeepingCentre(minDim, minDim));
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,25 +22,9 @@ ObjComponent::ObjComponent(OscirenderAudioProcessor& p, OscirenderAudioProcessor
 | 
			
		|||
 | 
			
		||||
	auto onRotationChange = [this]() {
 | 
			
		||||
		juce::SpinLock::ScopedLockType lock(audioProcessor.parsersLock);
 | 
			
		||||
		double x = fixedRotateX->getToggleState() ? 0 : rotateX.slider.getValue();
 | 
			
		||||
		double y = fixedRotateY->getToggleState() ? 0 : rotateY.slider.getValue();
 | 
			
		||||
		double z = fixedRotateZ->getToggleState() ? 0 : rotateZ.slider.getValue();
 | 
			
		||||
		audioProcessor.rotateX->setValue(x);
 | 
			
		||||
		audioProcessor.rotateY->setValue(y);
 | 
			
		||||
		audioProcessor.rotateZ->setValue(z);
 | 
			
		||||
 | 
			
		||||
		if (fixedRotateX->getToggleState()) {
 | 
			
		||||
			audioProcessor.currentRotateX->setValue(rotateX.slider.getValue());
 | 
			
		||||
			audioProcessor.currentRotateX->apply();
 | 
			
		||||
		}
 | 
			
		||||
		if (fixedRotateY->getToggleState()) {
 | 
			
		||||
			audioProcessor.currentRotateY->setValue(rotateY.slider.getValue());
 | 
			
		||||
			audioProcessor.currentRotateY->apply();
 | 
			
		||||
		}
 | 
			
		||||
		if (fixedRotateZ->getToggleState()) {
 | 
			
		||||
			audioProcessor.currentRotateZ->setValue(rotateZ.slider.getValue());
 | 
			
		||||
			audioProcessor.currentRotateZ->apply();
 | 
			
		||||
		}
 | 
			
		||||
		audioProcessor.rotateX->setValue(rotateX.slider.getValue());
 | 
			
		||||
		audioProcessor.rotateY->setValue(rotateY.slider.getValue());
 | 
			
		||||
		audioProcessor.rotateZ->setValue(rotateZ.slider.getValue());
 | 
			
		||||
 | 
			
		||||
		audioProcessor.fixedRotateX = fixedRotateX->getToggleState();
 | 
			
		||||
		audioProcessor.fixedRotateY = fixedRotateY->getToggleState();
 | 
			
		||||
| 
						 | 
				
			
			@ -73,12 +57,14 @@ ObjComponent::ObjComponent(OscirenderAudioProcessor& p, OscirenderAudioProcessor
 | 
			
		|||
		mouseRotate.setToggleState(false, juce::NotificationType::dontSendNotification);
 | 
			
		||||
 | 
			
		||||
		juce::SpinLock::ScopedLockType lock(audioProcessor.parsersLock);
 | 
			
		||||
		audioProcessor.currentRotateX->setValue(0);
 | 
			
		||||
		audioProcessor.currentRotateY->setValue(0);
 | 
			
		||||
		audioProcessor.currentRotateZ->setValue(0);
 | 
			
		||||
		audioProcessor.currentRotateX->apply();
 | 
			
		||||
		audioProcessor.currentRotateY->apply();
 | 
			
		||||
		audioProcessor.currentRotateZ->apply();
 | 
			
		||||
		if (audioProcessor.getCurrentFileIndex() != -1) {
 | 
			
		||||
			auto obj = audioProcessor.getCurrentFileParser()->getObject();
 | 
			
		||||
			if (obj != nullptr) {
 | 
			
		||||
				obj->setCurrentRotationX(0);
 | 
			
		||||
				obj->setCurrentRotationY(0);
 | 
			
		||||
				obj->setCurrentRotationZ(0);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	auto doc = juce::XmlDocument::parse(BinaryData::fixed_rotate_svg);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -50,15 +50,22 @@ OscirenderAudioProcessor::OscirenderAudioProcessor()
 | 
			
		|||
    ));
 | 
			
		||||
    toggleableEffects.push_back(std::make_shared<Effect>(
 | 
			
		||||
        std::make_shared<VectorCancellingEffect>(),
 | 
			
		||||
        new EffectParameter("Vector cancelling", "vectorCancelling", 0.0, 0.0, 1.0)
 | 
			
		||||
    ));
 | 
			
		||||
    toggleableEffects.push_back(std::make_shared<Effect>(
 | 
			
		||||
        std::make_shared<DistortEffect>(true),
 | 
			
		||||
        new EffectParameter("Vertical shift", "verticalDistort", 0.0, 0.0, 1.0)
 | 
			
		||||
        new EffectParameter("Vector Cancelling", "vectorCancelling", 0.0, 0.0, 1.0)
 | 
			
		||||
    ));
 | 
			
		||||
    toggleableEffects.push_back(std::make_shared<Effect>(
 | 
			
		||||
        std::make_shared<DistortEffect>(false),
 | 
			
		||||
        new EffectParameter("Horizontal shift", "horizontalDistort", 0.0, 0.0, 1.0)
 | 
			
		||||
        new EffectParameter("Horizontal Distort", "horizontalDistort", 0.0, 0.0, 1.0)
 | 
			
		||||
    ));
 | 
			
		||||
    toggleableEffects.push_back(std::make_shared<Effect>(
 | 
			
		||||
        std::make_shared<DistortEffect>(true),
 | 
			
		||||
        new EffectParameter("Vertical Distort", "verticalDistort", 0.0, 0.0, 1.0)
 | 
			
		||||
    ));
 | 
			
		||||
    toggleableEffects.push_back(std::make_shared<Effect>(
 | 
			
		||||
        [this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
 | 
			
		||||
            input.x += values[0];
 | 
			
		||||
            input.y += values[1];
 | 
			
		||||
            return input;
 | 
			
		||||
        }, std::vector<EffectParameter*>{new EffectParameter("Translate x", "translateX", 0.0, -1.0, 1.0), new EffectParameter("Translate y", "translateY", 0.0, -1.0, 1.0)}
 | 
			
		||||
    ));
 | 
			
		||||
    toggleableEffects.push_back(std::make_shared<Effect>(
 | 
			
		||||
        std::make_shared<SmoothEffect>(),
 | 
			
		||||
| 
						 | 
				
			
			@ -103,19 +110,9 @@ OscirenderAudioProcessor::OscirenderAudioProcessor()
 | 
			
		|||
            addParameter(parameter);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    hiddenEffects.push_back(currentRotateX);
 | 
			
		||||
    hiddenEffects.push_back(currentRotateY);
 | 
			
		||||
    hiddenEffects.push_back(currentRotateZ);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
OscirenderAudioProcessor::~OscirenderAudioProcessor() {
 | 
			
		||||
    for (auto effect : hiddenEffects) {
 | 
			
		||||
        for (auto parameter : effect->parameters) {
 | 
			
		||||
            delete parameter;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
OscirenderAudioProcessor::~OscirenderAudioProcessor() {}
 | 
			
		||||
 | 
			
		||||
const juce::String OscirenderAudioProcessor::getName() const {
 | 
			
		||||
    return JucePlugin_Name;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -105,12 +105,21 @@ public:
 | 
			
		|||
            return input;
 | 
			
		||||
		}, new EffectParameter("Focal length", "focalLength", 1.0, 0.0, 2.0)
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    std::atomic<bool> fixedRotateX = false;
 | 
			
		||||
    std::atomic<bool> fixedRotateY = false;
 | 
			
		||||
    std::atomic<bool> fixedRotateZ = false;
 | 
			
		||||
    std::shared_ptr<Effect> rotateX = std::make_shared<Effect>(
 | 
			
		||||
        [this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
 | 
			
		||||
            if (getCurrentFileIndex() != -1) {
 | 
			
		||||
                auto obj = getCurrentFileParser()->getObject();
 | 
			
		||||
                if (obj == nullptr) return input;
 | 
			
		||||
                obj->setBaseRotationX(values[0] * std::numbers::pi);
 | 
			
		||||
                auto rotation = values[0] * std::numbers::pi;
 | 
			
		||||
                if (fixedRotateX) {
 | 
			
		||||
                    obj->setCurrentRotationX(rotation);
 | 
			
		||||
                } else {
 | 
			
		||||
                    obj->setBaseRotationX(rotation);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return input;
 | 
			
		||||
        }, new EffectParameter("Rotate x", "rotateX", 1.0, -1.0, 1.0)
 | 
			
		||||
| 
						 | 
				
			
			@ -120,7 +129,12 @@ public:
 | 
			
		|||
            if (getCurrentFileIndex() != -1) {
 | 
			
		||||
                auto obj = getCurrentFileParser()->getObject();
 | 
			
		||||
                if (obj == nullptr) return input;
 | 
			
		||||
                obj->setBaseRotationY(values[0] * std::numbers::pi);
 | 
			
		||||
                auto rotation = values[0] * std::numbers::pi;
 | 
			
		||||
                if (fixedRotateY) {
 | 
			
		||||
                    obj->setCurrentRotationY(rotation);
 | 
			
		||||
                } else {
 | 
			
		||||
                    obj->setBaseRotationY(rotation);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return input;
 | 
			
		||||
        }, new EffectParameter("Rotate y", "rotateY", 1.0, -1.0, 1.0)
 | 
			
		||||
| 
						 | 
				
			
			@ -130,41 +144,16 @@ public:
 | 
			
		|||
            if (getCurrentFileIndex() != -1) {
 | 
			
		||||
                auto obj = getCurrentFileParser()->getObject();
 | 
			
		||||
                if (obj == nullptr) return input;
 | 
			
		||||
                obj->setBaseRotationZ(values[0] * std::numbers::pi);
 | 
			
		||||
                auto rotation = values[0] * std::numbers::pi;
 | 
			
		||||
                if (fixedRotateZ) {
 | 
			
		||||
                    obj->setCurrentRotationZ(rotation);
 | 
			
		||||
                } else {
 | 
			
		||||
                    obj->setBaseRotationZ(rotation);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return input;
 | 
			
		||||
        }, new EffectParameter("Rotate z", "rotateZ", 0.0, -1.0, 1.0)
 | 
			
		||||
    );
 | 
			
		||||
    std::shared_ptr<Effect> currentRotateX = std::make_shared<Effect>(
 | 
			
		||||
        [this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
 | 
			
		||||
            if (getCurrentFileIndex() != -1) {
 | 
			
		||||
                auto obj = getCurrentFileParser()->getObject();
 | 
			
		||||
                if (obj == nullptr) return input;
 | 
			
		||||
                obj->setCurrentRotationX(values[0] * std::numbers::pi);
 | 
			
		||||
            }
 | 
			
		||||
            return input;
 | 
			
		||||
        }, new EffectParameter("Current Rotate x", "currentRotateX", 0.0, 0.0, 1.0, 0.001, false)
 | 
			
		||||
    );
 | 
			
		||||
    std::shared_ptr<Effect> currentRotateY = std::make_shared<Effect>(
 | 
			
		||||
        [this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
 | 
			
		||||
            if (getCurrentFileIndex() != -1) {
 | 
			
		||||
                auto obj = getCurrentFileParser()->getObject();
 | 
			
		||||
                if (obj == nullptr) return input;
 | 
			
		||||
                obj->setCurrentRotationY(values[0] * std::numbers::pi);
 | 
			
		||||
            }
 | 
			
		||||
            return input;
 | 
			
		||||
        }, new EffectParameter("Current Rotate y", "currentRotateY", 0.0, 0.0, 1.0, 0.001, false)
 | 
			
		||||
    );
 | 
			
		||||
    std::shared_ptr<Effect> currentRotateZ = std::make_shared<Effect>(
 | 
			
		||||
        [this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
 | 
			
		||||
            if (getCurrentFileIndex() != -1) {
 | 
			
		||||
                auto obj = getCurrentFileParser()->getObject();
 | 
			
		||||
                if (obj == nullptr) return input;
 | 
			
		||||
                obj->setCurrentRotationZ(values[0] * std::numbers::pi);
 | 
			
		||||
            }
 | 
			
		||||
            return input;
 | 
			
		||||
        }, new EffectParameter("Current Rotate z", "currentRotateZ", 0.0, 0.0, 1.0, 0.001, false)
 | 
			
		||||
    );
 | 
			
		||||
    std::shared_ptr<Effect> rotateSpeed = std::make_shared<Effect>(
 | 
			
		||||
        [this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
 | 
			
		||||
            if (getCurrentFileIndex() != -1) {
 | 
			
		||||
| 
						 | 
				
			
			@ -175,9 +164,6 @@ public:
 | 
			
		|||
            return input;
 | 
			
		||||
		}, new EffectParameter("Rotate speed", "rotateSpeed", 0.0, -1.0, 1.0)
 | 
			
		||||
    );
 | 
			
		||||
    std::atomic<bool> fixedRotateX = false;
 | 
			
		||||
    std::atomic<bool> fixedRotateY = false;
 | 
			
		||||
    std::atomic<bool> fixedRotateZ = false;
 | 
			
		||||
 | 
			
		||||
    std::shared_ptr<DelayEffect> delayEffect = std::make_shared<DelayEffect>();
 | 
			
		||||
    
 | 
			
		||||
| 
						 | 
				
			
			@ -227,9 +213,6 @@ private:
 | 
			
		|||
    bool invalidateFrameBuffer = false;
 | 
			
		||||
 | 
			
		||||
    std::vector<std::shared_ptr<Effect>> permanentEffects;
 | 
			
		||||
    // any effects that are not added as a plugin parameter must be deleted manually
 | 
			
		||||
    // as JUCE will not delete them upon destruction of the AudioProcessor
 | 
			
		||||
    std::vector<std::shared_ptr<Effect>> hiddenEffects;
 | 
			
		||||
 | 
			
		||||
    std::shared_ptr<Effect> traceMax = std::make_shared<Effect>(
 | 
			
		||||
        [this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -259,7 +259,6 @@ public:
 | 
			
		|||
                if (auto* rowComp = getComponentForRow (row))
 | 
			
		||||
                {
 | 
			
		||||
                    rowComp->setBounds (0, owner.getPositionForRow (row), w, owner.getRowHeight (row));
 | 
			
		||||
                    DBG (String (i) + " " + rowComp->getBounds().toString());
 | 
			
		||||
                    rowComp->update (row, owner.isRowSelected (row));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,16 +29,12 @@ void VisualiserComponent::paint(juce::Graphics& g) {
 | 
			
		|||
    g.fillAll(backgroundColour);
 | 
			
		||||
 | 
			
		||||
    auto r = getLocalBounds().toFloat();
 | 
			
		||||
    auto channelHeight = r.getHeight() / (float)numChannels;
 | 
			
		||||
    auto minDim = juce::jmin(r.getWidth(), r.getHeight());
 | 
			
		||||
 | 
			
		||||
    g.setColour(waveformColour);
 | 
			
		||||
    juce::SpinLock::ScopedLockType scope(lock);
 | 
			
		||||
    if (buffer.size() > 0) {
 | 
			
		||||
        paintXY(g, r.removeFromRight(r.getHeight()));
 | 
			
		||||
 | 
			
		||||
        for (int i = 0; i < numChannels; ++i) {
 | 
			
		||||
            paintChannel(g, r.removeFromTop(channelHeight), i);
 | 
			
		||||
        }
 | 
			
		||||
        g.setColour(waveformColour);
 | 
			
		||||
        paintXY(g, r.withSizeKeepingCentre(minDim, minDim));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -77,17 +73,19 @@ void VisualiserComponent::paintChannel(juce::Graphics& g, juce::Rectangle<float>
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
void VisualiserComponent::paintXY(juce::Graphics& g, juce::Rectangle<float> area) {
 | 
			
		||||
    juce::Path path;
 | 
			
		||||
 | 
			
		||||
    path.startNewSubPath(buffer[0], buffer[1]);
 | 
			
		||||
    auto transform = juce::AffineTransform::fromTargetPoints(-1.0f, -1.0f, area.getX(), area.getBottom(), 1.0f, 1.0f, area.getRight(), area.getY(), 1.0f, -1.0f, area.getRight(), area.getBottom());
 | 
			
		||||
    std::vector<juce::Line<float>> lines;
 | 
			
		||||
 | 
			
		||||
    for (int i = 2; i < buffer.size(); i += 2) {
 | 
			
		||||
        path.lineTo(buffer[i + 0], buffer[i + 1]);
 | 
			
		||||
        lines.emplace_back(buffer[i - 2], buffer[i - 1], buffer[i], buffer[i + 1]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // apply affine transform to path to fit in area
 | 
			
		||||
    auto transform = juce::AffineTransform::fromTargetPoints(-1.0f, -1.0f, area.getX(), area.getBottom(), 1.0f, 1.0f, area.getRight(), area.getY(), 1.0f, -1.0f, area.getRight(), area.getBottom());
 | 
			
		||||
    path.applyTransform(transform);
 | 
			
		||||
 | 
			
		||||
    g.strokePath(path, juce::PathStrokeType(1.0f));
 | 
			
		||||
    for (auto& line : lines) {
 | 
			
		||||
        line.applyTransform(transform);
 | 
			
		||||
        float lengthScale = 1.0f / (line.getLength() + 1.0f);
 | 
			
		||||
        double strength = 10;
 | 
			
		||||
        lengthScale = std::log(strength * lengthScale + 1) / std::log(strength + 1);
 | 
			
		||||
        g.setColour(waveformColour.withAlpha(lengthScale));
 | 
			
		||||
        g.drawLine(line, 1.0f);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,8 +23,8 @@ private:
 | 
			
		|||
    int numChannels = 2;
 | 
			
		||||
    juce::Colour backgroundColour, waveformColour;
 | 
			
		||||
	OscirenderAudioProcessor& audioProcessor;
 | 
			
		||||
	std::shared_ptr<BufferConsumer> consumer = std::make_shared<BufferConsumer>(2048);
 | 
			
		||||
	int precision = 2;
 | 
			
		||||
	std::shared_ptr<BufferConsumer> consumer = std::make_shared<BufferConsumer>(4096);
 | 
			
		||||
    int precision = 4;
 | 
			
		||||
 | 
			
		||||
    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(VisualiserComponent)
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -45,7 +45,6 @@ Vector2 LuaParser::draw() {
 | 
			
		|||
            for (int i = 0; i < variableNames.size(); i++) {
 | 
			
		||||
                lua_pushnumber(L, variables[i]);
 | 
			
		||||
                lua_setglobal(L, variableNames[i].toUTF8());
 | 
			
		||||
                DBG("set " << variableNames[i] << " to " << variables[i]);
 | 
			
		||||
            }
 | 
			
		||||
            variableNames.clear();
 | 
			
		||||
            variables.clear();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Ładowanie…
	
		Reference in New Issue