monoslicer/Source/PluginProcessor.h

146 lines
4.8 KiB
C
Raw Normal View History

2026-07-21 02:06:45 +02:00
#pragma once
#include <juce_audio_processors/juce_audio_processors.h>
#include <juce_audio_formats/juce_audio_formats.h>
#include <juce_dsp/juce_dsp.h>
#include "SliceManager.h"
class MonoslicerProcessor : public juce::AudioProcessor
2026-07-21 02:06:45 +02:00
{
public:
MonoslicerProcessor();
~MonoslicerProcessor() override;
2026-07-21 02:06:45 +02:00
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 JucePlugin_Name; }
bool acceptsMidi() const override { return true; }
bool producesMidi() const override { return true; }
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;
void loadAudioFile(const juce::File& file);
void clearSample();
2026-07-21 02:06:45 +02:00
void loadNextSample();
void loadPreviousSample();
void triggerSlice(int sliceIndex, float velocity = 0.8f);
void releaseSlice();
void stretchToBeats(int numBeats, float bpm);
void psolaStretch(int targetLength);
float getHostBpm() const;
void undo();
void redo();
bool canUndo() const;
bool canRedo() const;
2026-07-21 02:06:45 +02:00
juce::AudioProcessorValueTreeState& getAPVTS() { return apvts; }
SliceManager& getSliceManager() { return sliceManager; }
const juce::AudioBuffer<float>& getSampleBuffer() const { return sampleBuffer; }
double getSampleRateLoaded() const { return loadedSampleRate; }
const juce::File& getCurrentFile() const { return currentFile; }
int getCurrentFileIndex() const { return currentFileIndex; }
int getNumFilesInFolder() const { return static_cast<int>(folderFiles.size()); }
std::atomic<bool> stateRestored { false };
2026-07-21 02:06:45 +02:00
std::atomic<int> currentPlaybackSample { -1 };
std::atomic<int> currentActiveSlice { -1 };
std::atomic<int> selectedSlice { -1 };
std::atomic<float> outputLevelL { 0.0f };
std::atomic<float> outputLevelR { 0.0f };
2026-07-21 02:06:45 +02:00
private:
juce::AudioProcessorValueTreeState apvts;
juce::AudioProcessorValueTreeState::ParameterLayout createParameterLayout();
SliceManager sliceManager;
juce::AudioFormatManager formatManager;
juce::AudioBuffer<float> sampleBuffer;
double loadedSampleRate = 44100.0;
double currentSampleRate = 44100.0;
juce::File currentFile;
juce::Array<juce::File> folderFiles;
int currentFileIndex = -1;
void refreshFolderList();
struct UndoState
{
juce::File file;
std::vector<SliceManager::Slice> slices;
};
std::vector<UndoState> undoStack;
std::vector<UndoState> redoStack;
static constexpr int maxUndoDepth = 10;
void pushUndoState();
bool restoringFromUndo = false;
2026-07-21 02:06:45 +02:00
enum class AmpStage { Idle, Attack, Decay, Sustain, Release };
enum class FilterType { LP12, LP24, HP, BP, Notch };
struct BiquadState
{
float x1 = 0.0f, x2 = 0.0f, y1 = 0.0f, y2 = 0.0f;
float b0 = 0.0f, b1 = 0.0f, b2 = 0.0f;
float a1 = 0.0f, a2 = 0.0f;
void reset() { x1 = x2 = y1 = y2 = 0.0f; }
float process(float input)
{
float output = b0 * input + b1 * x1 + b2 * x2 - a1 * y1 - a2 * y2;
x2 = x1; x1 = input;
y2 = y1; y1 = output;
return output;
}
};
struct Voice
{
bool active = false;
int sliceIndex = -1;
float position = 0.0f;
float velocity = 0.0f;
bool midiNoteSent = false;
AmpStage ampStage = AmpStage::Idle;
float ampEnv = 0.0f;
int ampSamplesToNext = 0;
AmpStage filterStage = AmpStage::Idle;
float filterEnv = 0.0f;
int filterSamplesToNext = 0;
BiquadState filterL, filterR;
BiquadState filterL2, filterR2;
2026-07-21 02:06:45 +02:00
};
static constexpr int maxVoices = 16;
std::array<Voice, maxVoices> voices;
void handleNoteOn(int noteNumber, float velocity);
void handleNoteOff();
void advanceAmpEnvelope(Voice& voice, int samples);
void advanceFilterEnvelope(Voice& voice, int samples);
void computeBiquadCoeffs(FilterType type, float cutoff, float resonance, float sampleRate,
float& b0, float& b1, float& b2, float& a1, float& a2);
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(MonoslicerProcessor)
2026-07-21 02:06:45 +02:00
};