chromaflock/Source/PluginProcessor.h

98 lines
3.4 KiB
C
Raw Normal View History

2026-07-13 20:57:38 +02:00
#pragma once
#include <juce_audio_processors/juce_audio_processors.h>
#include <juce_audio_basics/juce_audio_basics.h>
#include <juce_dsp/juce_dsp.h>
#include "DSP/Voice.h"
#include "DSP/Distortion.h"
#include "DSP/Compressor.h"
#include "DSP/Delay.h"
#include "DSP/Reverb.h"
#include "PresetManager.h"
#include <array>
#include <atomic>
const juce::StringArray& getSemitoneChoices();
2026-07-13 20:57:38 +02:00
class ChromaFlockProcessor : public juce::AudioProcessor {
public:
ChromaFlockProcessor();
~ChromaFlockProcessor() override;
void prepareToPlay(double sampleRate, int samplesPerBlock) override;
void releaseResources() override;
void processBlock(juce::AudioBuffer<float>&, juce::MidiBuffer&) override;
juce::AudioProcessorEditor* createEditor() override;
bool hasEditor() const override { return true; }
const juce::String getName() const override { return "ChromaFlock"; }
bool acceptsMidi() const override { return true; }
bool producesMidi() const override { return false; }
bool isMidiEffect() const override { return false; }
double getTailLengthSeconds() const override { return 0.0; }
int getNumPrograms() override { return 1; }
int getCurrentProgram() override { return 0; }
void setCurrentProgram(int) override {}
const juce::String getProgramName(int) override { return {}; }
void changeProgramName(int, const juce::String&) override {}
void getStateInformation(juce::MemoryBlock& destData) override;
void setStateInformation(const void* data, int sizeInBytes) override;
juce::AudioProcessorValueTreeState apvts;
PresetManager presetManager;
static constexpr int scopeBufferSize = 1024;
std::array<float, scopeBufferSize> scopeBuffer{};
std::atomic<int> scopeWritePos{0};
static constexpr int fftOrder = 11;
static constexpr int fftSize = 1 << fftOrder;
std::array<float, fftSize> fftInput{};
std::atomic<int> fftWritePos{0};
float getRmsLevel() const { return rmsLevel.load(); }
void noteOn(int midiNote, float velocity) {
if (midiNote >= 0 && midiNote < 128)
activeNotes[midiNote].store(true, std::memory_order_relaxed);
synth.noteOn(1, juce::jlimit(0, 127, midiNote + getTransposeSemitones()), velocity);
2026-07-13 20:57:38 +02:00
}
void noteOff(int midiNote) {
if (midiNote >= 0 && midiNote < 128)
activeNotes[midiNote].store(false, std::memory_order_relaxed);
synth.noteOff(1, juce::jlimit(0, 127, midiNote + getTransposeSemitones()), 0.0f, true);
2026-07-13 20:57:38 +02:00
}
bool isNoteActive(int midiNote) const {
return midiNote >= 0 && midiNote < 128
&& activeNotes[midiNote].load(std::memory_order_relaxed);
}
int getTransposeSemitones() const;
2026-07-13 20:57:38 +02:00
std::atomic<float> pitchBendValue{0.0f};
float getPitchBend() const { return pitchBendValue.load(std::memory_order_relaxed); }
private:
juce::AudioProcessorValueTreeState::ParameterLayout createParameterLayout();
void updateVoiceParameters();
juce::Synthesiser synth;
static constexpr int maxVoices = 16;
Distortion distortion;
Compressor compressor;
Delay delay;
ReverbFX reverbFX;
float autoPanPhase = 0.0f;
double currentSampleRate = 44100.0;
double currentBpm = 120.0;
2026-07-13 20:57:38 +02:00
std::atomic<float> rmsLevel{0.0f};
std::array<std::atomic<bool>, 128> activeNotes{};
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ChromaFlockProcessor)
};