Fix LP24 filter with proper 2-stage cascade, thread-safe SliceManager, improve state save/load

This commit is contained in:
Armin 2026-07-21 23:15:37 +02:00
commit ac6f17d9ae
4 changed files with 109 additions and 58 deletions

View file

@ -2,8 +2,29 @@
SliceManager::SliceManager() = default;
std::vector<SliceManager::Slice> SliceManager::getSlices() const
{
const juce::CriticalSection::ScopedLockType lock(mutex);
return slices;
}
int SliceManager::getNumSlices() const
{
const juce::CriticalSection::ScopedLockType lock(mutex);
return static_cast<int>(slices.size());
}
SliceManager::Slice SliceManager::getSlice(int index) const
{
const juce::CriticalSection::ScopedLockType lock(mutex);
if (index < 0 || index >= static_cast<int>(slices.size()))
return { 0, 0, 0 };
return slices[static_cast<size_t>(index)];
}
void SliceManager::setSampleBuffer(juce::AudioBuffer<float>* buffer, double sampleRate)
{
const juce::CriticalSection::ScopedLockType lock(mutex);
sampleBuffer = buffer;
currentSampleRate = sampleRate;
slices.clear();
@ -15,6 +36,7 @@ void SliceManager::setTrebleGain(float g) { trebleGain = juce::jlimit(0.0f, 2.
void SliceManager::autoSlice()
{
const juce::CriticalSection::ScopedLockType lock(mutex);
if (!sampleBuffer || sampleBuffer->getNumSamples() == 0)
return;
@ -83,12 +105,21 @@ void SliceManager::autoSlice()
void SliceManager::clearSlices()
{
const juce::CriticalSection::ScopedLockType lock(mutex);
pushHistory();
slices.clear();
}
void SliceManager::setSlices(const std::vector<Slice>& newSlices)
{
const juce::CriticalSection::ScopedLockType lock(mutex);
slices = newSlices;
assignMidiNotes();
}
void SliceManager::addSliceManual(int samplePos)
{
const juce::CriticalSection::ScopedLockType lock(mutex);
if (!sampleBuffer) return;
const int numSamples = sampleBuffer->getNumSamples();
samplePos = juce::jlimit(1, numSamples - 1, samplePos);
@ -127,13 +158,18 @@ void SliceManager::addSliceManual(int samplePos)
void SliceManager::removeSliceAt(int samplePos, int tolerance)
{
const juce::CriticalSection::ScopedLockType lock(mutex);
for (auto it = slices.begin(); it != slices.end(); ++it)
{
int dist = std::abs(it->startSample - samplePos);
if (dist <= tolerance)
{
pushHistory();
int removedEnd = it->endSample;
auto idx = static_cast<int>(std::distance(slices.begin(), it));
slices.erase(it);
if (idx > 0 && idx - 1 < static_cast<int>(slices.size()))
slices[static_cast<size_t>(idx - 1)].endSample = removedEnd;
assignMidiNotes();
return;
}
@ -142,6 +178,7 @@ void SliceManager::removeSliceAt(int samplePos, int tolerance)
void SliceManager::moveSlice(int fromSample, int toSample)
{
const juce::CriticalSection::ScopedLockType lock(mutex);
for (size_t i = 0; i < slices.size(); ++i)
{
if (std::abs(slices[i].startSample - fromSample) < 10)
@ -160,6 +197,7 @@ void SliceManager::moveSlice(int fromSample, int toSample)
void SliceManager::trimStart(int sample)
{
const juce::CriticalSection::ScopedLockType lock(mutex);
if (!sampleBuffer || sampleBuffer->getNumSamples() == 0) return;
sample = juce::jlimit(0, sampleBuffer->getNumSamples() - 1, sample);
if (sample <= 0) return;
@ -199,6 +237,7 @@ void SliceManager::trimStart(int sample)
void SliceManager::trimEnd(int sample)
{
const juce::CriticalSection::ScopedLockType lock(mutex);
if (!sampleBuffer || sampleBuffer->getNumSamples() == 0) return;
const int numSamples = sampleBuffer->getNumSamples();
sample = juce::jlimit(0, numSamples, sample);
@ -341,6 +380,7 @@ void SliceManager::truncateHistory()
void SliceManager::undo()
{
const juce::CriticalSection::ScopedLockType lock(mutex);
if (undoStack.empty()) return;
redoStack.push_back(slices);
slices = undoStack.back();
@ -349,6 +389,7 @@ void SliceManager::undo()
void SliceManager::redo()
{
const juce::CriticalSection::ScopedLockType lock(mutex);
if (redoStack.empty()) return;
undoStack.push_back(slices);
slices = redoStack.back();