Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SlicerT reversed slices and bug fixes #6992

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 36 additions & 28 deletions plugins/SlicerT/SlicerT.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,8 @@ SlicerT::SlicerT(InstrumentTrack* instrumentTrack)

void SlicerT::playNote(NotePlayHandle* handle, sampleFrame* workingBuffer)
{
if (m_originalSample.frames() <= 1) { return; }
if (m_sampleData.size() <= 1) { return; }

int noteIndex = handle->key() - m_parentTrack->baseNote();
const fpp_t frames = handle->framesLeftForCurrentPeriod();
const f_cnt_t offset = handle->noteOffset();
const int bpm = Engine::getSong()->getTempo();
Expand All @@ -89,19 +88,18 @@ void SlicerT::playNote(NotePlayHandle* handle, sampleFrame* workingBuffer)
speedRatio *= pitchRatio;
speedRatio *= Engine::audioEngine()->processingSampleRate() / static_cast<float>(m_originalSample.sampleRate());

float sliceStart, sliceEnd;
if (noteIndex == 0) // full sample at base note
{
sliceStart = 0;
sliceEnd = 1;
}
else if (noteIndex > 0 && noteIndex < m_slicePoints.size())
float sliceStart = 0;
float sliceEnd = 1;
bool reversed = false;
int noteIndex = handle->key() - m_parentTrack->baseNote();
if (std::abs(noteIndex) < m_slicePoints.size() && noteIndex != 0)
{
noteIndex -= 1;
if (noteIndex < 0) { reversed = true; }
noteIndex = std::abs(noteIndex) - 1;
sliceStart = m_slicePoints[noteIndex];
sliceEnd = m_slicePoints[noteIndex + 1];
}
else
else if (noteIndex != 0)
{
emit isPlaying(-1, 0, 0);
return;
Expand All @@ -115,25 +113,26 @@ void SlicerT::playNote(NotePlayHandle* handle, sampleFrame* workingBuffer)

if (noteLeft > 0)
{
int noteFrame = noteDone * m_originalSample.frames();
int noteFrame = noteDone * m_sampleData.size();

SRC_STATE* resampleState = playbackState->resamplingState();
SRC_DATA resampleData;
resampleData.data_in = (m_originalSample.data() + noteFrame)->data();
if (reversed) { resampleData.data_in = (m_reversedSampleData.data() + noteFrame)->data(); }
else { resampleData.data_in = (m_sampleData.data() + noteFrame)->data(); }
resampleData.data_out = (workingBuffer + offset)->data();
resampleData.input_frames = noteLeft * m_originalSample.frames();
resampleData.input_frames = noteLeft * m_sampleData.size();
resampleData.output_frames = frames;
resampleData.src_ratio = speedRatio;

src_process(resampleState, &resampleData);

float nextNoteDone = noteDone + frames * (1.0f / speedRatio) / m_originalSample.frames();
float nextNoteDone = noteDone + frames * (1.0f / speedRatio) / m_sampleData.size();
playbackState->setNoteDone(nextNoteDone);

// exponential fade out, applyRelease() not used since it extends the note length
int fadeOutFrames = m_fadeOutFrames.value() / 1000.0f * Engine::audioEngine()->processingSampleRate();
int noteFramesLeft = noteLeft * m_originalSample.frames() * speedRatio;
for (int i = 0; i < frames; i++)
int noteFramesLeft = noteLeft * m_sampleData.size() * speedRatio;
for (int i = 0; i < frames && fadeOutFrames != 0; i++)
{
float fadeValue = static_cast<float>(noteFramesLeft - i) / fadeOutFrames;
fadeValue = std::clamp(fadeValue, 0.0f, 1.0f);
Expand All @@ -143,8 +142,7 @@ void SlicerT::playNote(NotePlayHandle* handle, sampleFrame* workingBuffer)
workingBuffer[i + offset][1] *= fadeValue;
}

instrumentTrack()->processAudioBuffer(workingBuffer, frames + offset, handle);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed the two lines above in #7174

if (reversed) { noteDone = sliceEnd - noteDone + sliceStart; }
emit isPlaying(noteDone, sliceStart, sliceEnd);
}
else { emit isPlaying(-1, 0, 0); }
Expand All @@ -160,7 +158,7 @@ void SlicerT::deleteNotePluginData(NotePlayHandle* handle)
// http://www.iro.umontreal.ca/~pift6080/H09/documents/papers/bello_onset_tutorial.pdf
void SlicerT::findSlices()
{
if (m_originalSample.frames() <= 1) { return; }
if (m_sampleData.size() <= 1) { return; }
m_slicePoints = {};

const int windowSize = 512;
Expand All @@ -170,10 +168,10 @@ void SlicerT::findSlices()
int minDist = sampleRate * minBeatLength;

float maxMag = -1;
std::vector<float> singleChannel(m_originalSample.frames(), 0);
for (int i = 0; i < m_originalSample.frames(); i++)
std::vector<float> singleChannel(m_sampleData.size(), 0);
for (int i = 0; i < m_sampleData.size(); i++)
{
singleChannel[i] = (m_originalSample.data()[i][0] + m_originalSample.data()[i][1]) / 2;
singleChannel[i] = (m_sampleData[i][0] + m_sampleData[i][1]) / 2;
maxMag = std::max(maxMag, singleChannel[i]);
}

Expand Down Expand Up @@ -232,7 +230,7 @@ void SlicerT::findSlices()
spectralFlux = 1E-10; // again for no divison by zero
}

m_slicePoints.push_back(m_originalSample.frames());
m_slicePoints.push_back(m_sampleData.size());

for (float& sliceValue : m_slicePoints)
{
Expand All @@ -255,7 +253,7 @@ void SlicerT::findSlices()

for (float& sliceIndex : m_slicePoints)
{
sliceIndex /= m_originalSample.frames();
sliceIndex /= m_sampleData.size();
}

m_slicePoints[0] = 0;
Expand All @@ -268,10 +266,10 @@ void SlicerT::findSlices()
// and lies in the 100 - 200 bpm range
void SlicerT::findBPM()
{
if (m_originalSample.frames() <= 1) { return; }
if (m_sampleData.size() <= 1) { return; }

float sampleRate = m_originalSample.sampleRate();
float totalFrames = m_originalSample.frames();
float totalFrames = m_sampleData.size();
float sampleLength = totalFrames / sampleRate;

float bpmEstimate = 240.0f / sampleLength;
Expand All @@ -295,7 +293,7 @@ std::vector<Note> SlicerT::getMidi()
std::vector<Note> outputNotes;

float speedRatio = static_cast<float>(m_originalBPM.value()) / Engine::getSong()->getTempo();
float outFrames = m_originalSample.frames() * speedRatio;
float outFrames = m_sampleData.size() * speedRatio;

float framesPerTick = Engine::framesPerTick();
float totalTicks = outFrames / framesPerTick;
Expand All @@ -321,6 +319,11 @@ std::vector<Note> SlicerT::getMidi()
void SlicerT::updateFile(QString file)
{
m_originalSample.setAudioFile(file);
m_sampleData.resize(m_originalSample.frames());
m_reversedSampleData.resize(m_originalSample.frames());
std::copy_n(m_originalSample.data(), m_originalSample.frames(), m_sampleData.data());
std::copy_n(m_originalSample.data(), m_originalSample.frames(), m_reversedSampleData.data());
std::reverse(m_reversedSampleData.begin(), m_reversedSampleData.end());

findBPM();
findSlices();
Expand Down Expand Up @@ -360,6 +363,11 @@ void SlicerT::loadSettings(const QDomElement& element)
if (!element.attribute("src").isEmpty())
{
m_originalSample.setAudioFile(element.attribute("src"));
m_sampleData.resize(m_originalSample.frames());
m_reversedSampleData.resize(m_originalSample.frames());
std::copy_n(m_originalSample.data(), m_originalSample.frames(), m_sampleData.data());
std::copy_n(m_originalSample.data(), m_originalSample.frames(), m_reversedSampleData.data());
std::reverse(m_reversedSampleData.begin(), m_reversedSampleData.end());

QString absolutePath = PathUtil::toAbsolute(m_originalSample.audioFile());
if (!QFileInfo(absolutePath).exists())
Expand Down
2 changes: 2 additions & 0 deletions plugins/SlicerT/SlicerT.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ public slots:
BoolModel m_enableSync;

SampleBuffer m_originalSample;
std::vector<sampleFrame> m_sampleData;
std::vector<sampleFrame> m_reversedSampleData;

std::vector<float> m_slicePoints;

Expand Down
Loading