monoslicer/Source/SliceManager.h
Armin 73c4095139 Add octave offset dropdown, fix waveform sidebar, embed audio in plugin state
- Add octave offset combo (-3 to +3) in title bar for MIDI input transposition
- Fix waveform sidebar base note from C3 to C4
- Fix midiNoteToSliceIndex to compare pitch classes instead of raw MIDI notes
- Add colored slice indicator dots on waveform sidebar keys
- Embed audio data, file path, sample rate, and slices in plugin state for
  DAW project save/restore (falls back to file path if embedded data missing)
2026-07-21 15:20:49 +02:00

68 lines
2 KiB
C++

#pragma once
#include <juce_audio_processors/juce_audio_processors.h>
#include <juce_dsp/juce_dsp.h>
#include <vector>
#include <algorithm>
#include <cmath>
class SliceManager
{
public:
struct Slice
{
int startSample;
int endSample;
int midiNote; // pitch class (0 = C, 1 = C#, ..., 11 = B)
};
SliceManager();
void setSampleBuffer(juce::AudioBuffer<float>* buffer, double sampleRate);
void setSensitivity(float s);
void setBassGain(float g);
void setTrebleGain(float g);
void autoSlice();
void clearSlices();
void addSliceManual(int samplePos);
void removeSliceAt(int samplePos, int tolerance = 5);
void moveSlice(int fromSample, int toSample);
void trimStart(int sample);
void trimEnd(int sample);
void undo();
void redo();
bool canUndo() const;
bool canRedo() const;
const std::vector<Slice>& getSlices() const { return slices; }
int getNumSlices() const { return static_cast<int>(slices.size()); }
const Slice& getSlice(int index) const { return slices[static_cast<size_t>(index)]; }
int findSliceIndexForSample(int samplePos) const;
juce::AudioBuffer<float>* getMutableBuffer() { return sampleBuffer; }
private:
void sortSlices();
void assignMidiNotes();
void pushHistory();
void truncateHistory();
std::vector<Slice> slices;
std::vector<std::vector<Slice>> undoStack;
std::vector<std::vector<Slice>> redoStack;
static constexpr size_t maxHistory = 50;
juce::AudioBuffer<float>* sampleBuffer = nullptr;
double currentSampleRate = 44100.0;
float sensitivity = 0.5f;
float bassGain = 1.0f;
float trebleGain = 1.0f;
std::vector<float> computeEnvelope(const float* channelData, int numSamples);
std::vector<float> lowpassFilter(const std::vector<float>& input, float cutoffHz);
std::vector<float> highpassFilter(const std::vector<float>& input, float cutoffHz);
std::vector<float> detectOnsets(const std::vector<float>& envelope, float threshold);
};