Corrected a big error in the file loading for mono files
This commit is contained in:
parent
0ee2717559
commit
392813dd6d
12 changed files with 176 additions and 46 deletions
|
|
@ -1,6 +1,11 @@
|
|||
#include "FilePool.h"
|
||||
#include "Globals.h"
|
||||
#include "absl/types/span.h"
|
||||
#include <chrono>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
std::optional<sfz::FilePool::FileInformation> sfz::FilePool::getFileInformation(std::string_view filename)
|
||||
|
|
@ -10,21 +15,47 @@ std::optional<sfz::FilePool::FileInformation> sfz::FilePool::getFileInformation(
|
|||
return {};
|
||||
|
||||
SndfileHandle sndFile(reinterpret_cast<const char*>(file.c_str()));
|
||||
if (sndFile.channels() != 1 && sndFile.channels() != 2) {
|
||||
DBG("Missing logic for " << sndFile.channels() <<", discarding sample " << filename);
|
||||
return {};
|
||||
}
|
||||
FileInformation returnedValue;
|
||||
returnedValue.end = static_cast<uint32_t>(sndFile.frames());
|
||||
returnedValue.sampleRate = static_cast<double>(sndFile.samplerate());
|
||||
SF_INSTRUMENT instrumentInfo;
|
||||
sndFile.command(SFC_GET_INSTRUMENT, &instrumentInfo, sizeof(instrumentInfo));
|
||||
|
||||
if (instrumentInfo.loop_count == 1) {
|
||||
returnedValue.loopBegin = instrumentInfo.loops[0].start;
|
||||
returnedValue.loopEnd = instrumentInfo.loops[0].end;
|
||||
}
|
||||
auto preloadedSize = std::min(returnedValue.end, static_cast<uint32_t>(config::preloadSize));
|
||||
|
||||
const auto preloadedSize = [&]() {
|
||||
if (config::preloadSize == 0)
|
||||
return returnedValue.end;
|
||||
else
|
||||
return std::min(returnedValue.end, static_cast<uint32_t>(config::preloadSize));
|
||||
}();
|
||||
returnedValue.preloadedData = std::make_shared<StereoBuffer<float>>(preloadedSize);
|
||||
sndFile.readf(tempReadBuffer.data(), preloadedSize);
|
||||
returnedValue.preloadedData->readInterleaved(absl::MakeSpan(tempReadBuffer).first(preloadedSize));
|
||||
preloadedData[filename] = returnedValue.preloadedData;
|
||||
// auto tempReadBuffer = std::make_unique<Buffer<float>>(2 * preloadedSize);
|
||||
if (sndFile.channels() == 1) {
|
||||
tempReadBuffer.resize(preloadedSize);
|
||||
sndFile.readf(tempReadBuffer.data(), preloadedSize);
|
||||
std::copy(tempReadBuffer.begin(), tempReadBuffer.end(), returnedValue.preloadedData->begin(Channel::left));
|
||||
std::copy(tempReadBuffer.begin(), tempReadBuffer.end(), returnedValue.preloadedData->begin(Channel::right));
|
||||
} else if (sndFile.channels() == 2) {
|
||||
tempReadBuffer.resize(preloadedSize * 2);
|
||||
sndFile.readf(tempReadBuffer.data(), preloadedSize);
|
||||
returnedValue.preloadedData->readInterleaved(tempReadBuffer);
|
||||
}
|
||||
// std::stringstream dumpName { };
|
||||
// dumpName << filename << ".preloaded" << preloadedFilesWritten << ".bin";
|
||||
// dumpName << filename << ".preloaded" << ".bin";
|
||||
// std::ofstream ofile(dumpName.str(), std::ios::binary);
|
||||
// preloadedFilesWritten++;
|
||||
// for (auto& floatValue: tempReadBuffer)
|
||||
// ofile.write((char*) &floatValue, sizeof(float));
|
||||
// ofile.close();
|
||||
// char buffer [2048] ;
|
||||
// sndFile.command(SFC_GET_LOG_INFO, buffer, sizeof(buffer)) ;
|
||||
// DBG(buffer);
|
||||
|
|
@ -58,13 +89,19 @@ void sfz::FilePool::loadingThread()
|
|||
}
|
||||
|
||||
SndfileHandle sndFile(reinterpret_cast<const char*>(file.c_str()));
|
||||
// auto deleteAndTrackBuffers = [this]
|
||||
std::unique_ptr<StereoBuffer<float>, std::function<void(StereoBuffer<float>*)>> fileLoaded(new StereoBuffer<float>(fileToLoad.numFrames), deleteAndTrackBuffers);
|
||||
auto readBuffer = std::make_unique<Buffer<float>>(fileToLoad.numFrames * 2);
|
||||
sndFile.readf(readBuffer->data(), fileToLoad.numFrames);
|
||||
fileLoaded->readInterleaved(*readBuffer);
|
||||
ASSERT(fileLoaded != nullptr);
|
||||
fileBuffers++;
|
||||
auto fileLoaded = std::make_unique<StereoBuffer<float>>(fileToLoad.numFrames);
|
||||
if (sndFile.channels() == 1) {
|
||||
tempReadBuffer.resize(fileToLoad.numFrames);
|
||||
sndFile.readf(tempReadBuffer.data(), fileToLoad.numFrames);
|
||||
std::copy(tempReadBuffer.begin(), tempReadBuffer.end(), fileLoaded->begin(Channel::left));
|
||||
std::copy(tempReadBuffer.begin(), tempReadBuffer.end(), fileLoaded->begin(Channel::right));
|
||||
} else if (sndFile.channels() == 2) {
|
||||
tempReadBuffer.resize(fileToLoad.numFrames * 2);
|
||||
sndFile.readf(tempReadBuffer.data(), fileToLoad.numFrames);
|
||||
fileLoaded->readInterleaved(tempReadBuffer);
|
||||
}
|
||||
// std::unique_ptr<StereoBuffer<float>, std::function<void(StereoBuffer<float>*)>> fileLoaded(new StereoBuffer<float>(framesRead), deleteAndTrackBuffers);
|
||||
// fileBuffers++;
|
||||
fileToLoad.voice->setFileData(std::move(fileLoaded));
|
||||
}
|
||||
}
|
||||
|
|
@ -55,14 +55,12 @@ private:
|
|||
};
|
||||
|
||||
inline static std::atomic<int> fileBuffers { 0 };
|
||||
|
||||
int preloadedFilesWritten {0};
|
||||
moodycamel::BlockingReaderWriterQueue<FileLoadingInformation> loadingQueue;
|
||||
void loadingThread();
|
||||
std::thread fileLoadingThread;
|
||||
bool quitThread { false };
|
||||
Buffer<float> tempReadBuffer { config::preloadSize * 2 };
|
||||
|
||||
// std::map<std::string_view, std::shared_ptr<StereoBuffer<float>>> preloadedData;
|
||||
Buffer<float> tempReadBuffer;
|
||||
absl::flat_hash_map<std::string_view, std::shared_ptr<StereoBuffer<float>>> preloadedData;
|
||||
LEAK_DETECTOR(FilePool);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ constexpr bool fill { true };
|
|||
constexpr bool gain { false };
|
||||
constexpr bool mathfuns { false };
|
||||
constexpr bool loopingSFZIndex { true };
|
||||
constexpr bool saturatingSFZIndex { true };
|
||||
constexpr bool linearRamp { false };
|
||||
constexpr bool multiplicativeRamp { true };
|
||||
constexpr bool add { false };
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ int process(jack_nframes_t numFrames, void* arg [[maybe_unused]])
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// DBG("Num frames: " << numFrames);
|
||||
StereoSpan<float> output {
|
||||
jack_port_get_buffer(outputPort1, numFrames),
|
||||
jack_port_get_buffer(outputPort2, numFrames),
|
||||
|
|
@ -100,6 +100,7 @@ int process(jack_nframes_t numFrames, void* arg [[maybe_unused]])
|
|||
};
|
||||
|
||||
synth->renderBlock(output);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -323,6 +323,7 @@ bool sfz::Region::parseOpcode(const Opcode& opcode)
|
|||
break;
|
||||
case hash("pitch_random"):
|
||||
setValueFromOpcode(opcode, pitchRandom, Default::pitchRandomRange);
|
||||
pitchDistribution.param(std::uniform_int_distribution<int>::param_type(-pitchRandom, pitchRandom));
|
||||
break;
|
||||
case hash("transpose"):
|
||||
setValueFromOpcode(opcode, transpose, Default::transposeRange);
|
||||
|
|
|
|||
|
|
@ -32,6 +32,16 @@ struct Region {
|
|||
void registerAftertouch(int channel, uint8_t aftertouch);
|
||||
void registerTempo(float secondsPerQuarter);
|
||||
bool isStereo() const noexcept;
|
||||
float getBasePitchVariation(int noteNumber, uint8_t velocity) noexcept
|
||||
{
|
||||
auto pitchVariationInCents = pitchKeytrack * (noteNumber - (int)pitchKeycenter); // note difference with pitch center
|
||||
pitchVariationInCents += tune; // sample tuning
|
||||
pitchVariationInCents += config::centPerSemitone * transpose; // sample transpose
|
||||
pitchVariationInCents += velocity / 127 * pitchVeltrack; // track velocity
|
||||
if (pitchRandom > 0)
|
||||
pitchVariationInCents += pitchDistribution(Random::randomGenerator); // random pitch changes
|
||||
return centsFactor(pitchVariationInCents);
|
||||
}
|
||||
float getBaseGain()
|
||||
{
|
||||
float baseGaindB { volume };
|
||||
|
|
@ -51,6 +61,13 @@ struct Region {
|
|||
{
|
||||
return min(sampleEnd, loopRange.getEnd());
|
||||
}
|
||||
bool canUsePreloadedData()
|
||||
{
|
||||
if (preloadedData == nullptr)
|
||||
return false;
|
||||
|
||||
return trueSampleEnd() < static_cast<uint32_t>(preloadedData->getNumFrames());
|
||||
}
|
||||
|
||||
bool parseOpcode(const Opcode& opcode);
|
||||
// Sound source: sample playback
|
||||
|
|
@ -152,6 +169,7 @@ private:
|
|||
std::uniform_real_distribution<float> gainDistribution { -sfz::Default::ampRandom, sfz::Default::ampRandom };
|
||||
std::uniform_real_distribution<float> delayDistribution { 0, sfz::Default::delayRandom };
|
||||
std::uniform_int_distribution<uint32_t> offsetDistribution { 0, sfz::Default::offsetRandom };
|
||||
std::uniform_int_distribution<int> pitchDistribution { -sfz::Default::pitchRandom, sfz::Default::pitchRandom };
|
||||
LEAK_DETECTOR(Region);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -56,11 +56,18 @@ void applyGain<float, true>(absl::Span<const float> gain, absl::Span<const float
|
|||
}
|
||||
|
||||
template <>
|
||||
void loopingSFZIndex<float, true>(absl::Span<const float> jumps, absl::Span<float> leftCoeff, absl::Span<float> rightCoeff, absl::Span<int> indices, float floatIndex, float loopEnd, float loopStart) noexcept
|
||||
float loopingSFZIndex<float, true>(absl::Span<const float> jumps, absl::Span<float> leftCoeff, absl::Span<float> rightCoeff, absl::Span<int> indices, float floatIndex, float loopEnd, float loopStart) noexcept
|
||||
{
|
||||
loopingSFZIndex<float, false>(jumps, leftCoeff, rightCoeff, indices, floatIndex, loopEnd, loopStart);
|
||||
return loopingSFZIndex<float, false>(jumps, leftCoeff, rightCoeff, indices, floatIndex, loopEnd, loopStart);
|
||||
}
|
||||
|
||||
template <>
|
||||
float saturatingSFZIndex<float, true>(absl::Span<const float> jumps, absl::Span<float> leftCoeff, absl::Span<float> rightCoeff, absl::Span<int> indices, float floatIndex, float loopEnd) noexcept
|
||||
{
|
||||
return saturatingSFZIndex<float, false>(jumps, leftCoeff, rightCoeff, indices, floatIndex, loopEnd);
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
float linearRamp<float, true>(absl::Span<float> output, float start, float step) noexcept
|
||||
{
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ inline void snippetSaturatingIndex(const T*& jump, T*& leftCoeff, T*& rightCoeff
|
|||
}
|
||||
|
||||
template <class T, bool SIMD = SIMDConfig::saturatingSFZIndex>
|
||||
void saturatingSFZIndex(absl::Span<const T> jumps, absl::Span<T> leftCoeffs, absl::Span<T> rightCoeffs, absl::Span<int> indices, T floatIndex, T loopEnd) noexcept
|
||||
float saturatingSFZIndex(absl::Span<const T> jumps, absl::Span<T> leftCoeffs, absl::Span<T> rightCoeffs, absl::Span<int> indices, T floatIndex, T loopEnd) noexcept
|
||||
{
|
||||
ASSERT(indices.size() >= jumps.size());
|
||||
ASSERT(indices.size() == leftCoeffs.size());
|
||||
|
|
@ -148,10 +148,11 @@ void saturatingSFZIndex(absl::Span<const T> jumps, absl::Span<T> leftCoeffs, abs
|
|||
|
||||
while (jump < sentinel)
|
||||
snippetSaturatingIndex<T>(jump, leftCoeff, rightCoeff, index, floatIndex, loopEnd);
|
||||
return floatIndex;
|
||||
}
|
||||
|
||||
template <>
|
||||
void saturatingSFZIndex<float, true>(absl::Span<const float> jumps, absl::Span<float> leftCoeffs, absl::Span<float> rightCoeffs, absl::Span<int> indices, float floatIndex, float loopEnd) noexcept;
|
||||
float saturatingSFZIndex<float, true>(absl::Span<const float> jumps, absl::Span<float> leftCoeffs, absl::Span<float> rightCoeffs, absl::Span<int> indices, float floatIndex, float loopEnd) noexcept;
|
||||
|
||||
template <class T>
|
||||
inline void snippetLoopingIndex(const T*& jump, T*& leftCoeff, T*& rightCoeff, int*& index, T& floatIndex, T loopEnd, T loopStart)
|
||||
|
|
@ -169,7 +170,7 @@ inline void snippetLoopingIndex(const T*& jump, T*& leftCoeff, T*& rightCoeff, i
|
|||
}
|
||||
|
||||
template <class T, bool SIMD = SIMDConfig::loopingSFZIndex>
|
||||
void loopingSFZIndex(absl::Span<const T> jumps, absl::Span<T> leftCoeffs, absl::Span<T> rightCoeffs, absl::Span<int> indices, T floatIndex, T loopEnd, T loopStart) noexcept
|
||||
float loopingSFZIndex(absl::Span<const T> jumps, absl::Span<T> leftCoeffs, absl::Span<T> rightCoeffs, absl::Span<int> indices, T floatIndex, T loopEnd, T loopStart) noexcept
|
||||
{
|
||||
ASSERT(indices.size() >= jumps.size());
|
||||
ASSERT(indices.size() == leftCoeffs.size());
|
||||
|
|
@ -184,10 +185,11 @@ void loopingSFZIndex(absl::Span<const T> jumps, absl::Span<T> leftCoeffs, absl::
|
|||
|
||||
while (jump < sentinel)
|
||||
snippetLoopingIndex<T>(jump, leftCoeff, rightCoeff, index, floatIndex, loopEnd, loopStart);
|
||||
return floatIndex;
|
||||
}
|
||||
|
||||
template <>
|
||||
void loopingSFZIndex<float, true>(absl::Span<const float> jumps, absl::Span<float> leftCoeff, absl::Span<float> rightCoeff, absl::Span<int> indices, float floatIndex, float loopEnd, float loopStart) noexcept;
|
||||
float loopingSFZIndex<float, true>(absl::Span<const float> jumps, absl::Span<float> leftCoeff, absl::Span<float> rightCoeff, absl::Span<int> indices, float floatIndex, float loopEnd, float loopStart) noexcept;
|
||||
|
||||
template <class T>
|
||||
inline void snippetGain(T gain, const T*& input, T*& output)
|
||||
|
|
|
|||
|
|
@ -283,7 +283,7 @@ void applyGain<float, true>(absl::Span<const float> gain, absl::Span<const float
|
|||
}
|
||||
|
||||
template <>
|
||||
void loopingSFZIndex<float, true>(absl::Span<const float> jumps,
|
||||
float loopingSFZIndex<float, true>(absl::Span<const float> jumps,
|
||||
absl::Span<float> leftCoeffs,
|
||||
absl::Span<float> rightCoeffs,
|
||||
absl::Span<int> indices,
|
||||
|
|
@ -341,10 +341,11 @@ void loopingSFZIndex<float, true>(absl::Span<const float> jumps,
|
|||
floatIndex = _mm_cvtss_f32(mmFloatIndex);
|
||||
while (jump < sentinel)
|
||||
snippetLoopingIndex<float>(jump, leftCoeff, rightCoeff, index, floatIndex, loopEnd, loopStart);
|
||||
return floatIndex;
|
||||
}
|
||||
|
||||
template <>
|
||||
void saturatingSFZIndex<float, true>(absl::Span<const float> jumps,
|
||||
float saturatingSFZIndex<float, true>(absl::Span<const float> jumps,
|
||||
absl::Span<float> leftCoeffs,
|
||||
absl::Span<float> rightCoeffs,
|
||||
absl::Span<int> indices,
|
||||
|
|
@ -398,6 +399,7 @@ void saturatingSFZIndex<float, true>(absl::Span<const float> jumps,
|
|||
floatIndex = _mm_cvtss_f32(mmFloatIndex);
|
||||
while (jump < sentinel)
|
||||
snippetSaturatingIndex<float>(jump, leftCoeff, rightCoeff, index, floatIndex, loopEnd);
|
||||
return floatIndex;
|
||||
}
|
||||
|
||||
template <>
|
||||
|
|
|
|||
|
|
@ -34,7 +34,14 @@ public:
|
|||
ASSERT(leftBuffer.size() == rightBuffer.size());
|
||||
}
|
||||
|
||||
StereoSpan(StereoBuffer<const ValueType>& buffer)
|
||||
StereoSpan(StereoBuffer<ValueType>&& buffer)
|
||||
: numFrames(buffer.getNumFrames())
|
||||
, leftBuffer(buffer.getSpan(Channel::left))
|
||||
, rightBuffer(buffer.getSpan(Channel::right))
|
||||
{
|
||||
}
|
||||
|
||||
StereoSpan(StereoBuffer<const ValueType>&& buffer)
|
||||
: leftBuffer(buffer.getConstSpan(Channel::left))
|
||||
, rightBuffer(buffer.getConstSpan(Channel::right))
|
||||
, numFrames(buffer.getNumFrames())
|
||||
|
|
@ -48,6 +55,13 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
StereoSpan(StereoBuffer<const ValueType>& buffer)
|
||||
: leftBuffer(buffer.getConstSpan(Channel::left))
|
||||
, rightBuffer(buffer.getConstSpan(Channel::right))
|
||||
, numFrames(buffer.getNumFrames())
|
||||
{
|
||||
}
|
||||
|
||||
StereoSpan(StereoBuffer<ValueType>& buffer, size_t numFrames)
|
||||
: numFrames(numFrames)
|
||||
, leftBuffer(buffer.getSpan(Channel::left).first(numFrames))
|
||||
|
|
@ -74,6 +88,7 @@ public:
|
|||
, leftBuffer(span.left())
|
||||
, rightBuffer(span.right())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void fill(Type value) noexcept
|
||||
|
|
|
|||
|
|
@ -62,11 +62,11 @@ public:
|
|||
{
|
||||
ScopedFTZ ftz;
|
||||
buffer.fill(0.0f);
|
||||
|
||||
StereoSpan<float> tempSpan { tempBuffer, buffer.size() };
|
||||
for (auto& voice : voices) {
|
||||
voice->renderBlock(tempSpan);
|
||||
buffer.add(tempSpan);
|
||||
tempBuffer.fill(0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -108,6 +108,7 @@ public:
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cc(int delay, int channel, int ccNumber, uint8_t ccValue)
|
||||
{
|
||||
for (auto& voice : voices)
|
||||
|
|
@ -155,7 +156,7 @@ private:
|
|||
activeVoices++;
|
||||
}
|
||||
DBG("Active voices:" << activeVoices << " | Stray buffers: " << FilePool::getFileBuffers());
|
||||
std::this_thread::sleep_for(1s);
|
||||
std::this_thread::sleep_for(200ms);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,10 +41,11 @@ public:
|
|||
|
||||
state = State::playing;
|
||||
speedRatio = static_cast<float>(region->sampleRate / this->sampleRate);
|
||||
pitchRatio = region->getBasePitchVariation(number, value);
|
||||
baseGain = region->getBaseGain();
|
||||
sourcePosition = region->getOffset();
|
||||
initialDelay = delay + region->getDelay();
|
||||
baseFrequency = midiNoteFrequency(number);
|
||||
baseFrequency = midiNoteFrequency(number) * pitchRatio;
|
||||
prepareEGEnvelope(delay, value);
|
||||
}
|
||||
|
||||
|
|
@ -64,10 +65,10 @@ public:
|
|||
normalizePercents(region->amplitudeEG.getStart(ccState, velocity)));
|
||||
}
|
||||
|
||||
void setFileData(std::unique_ptr<StereoBuffer<float>, std::function<void(StereoBuffer<float>*)>> file)
|
||||
void setFileData(std::unique_ptr<StereoBuffer<float>> file)
|
||||
{
|
||||
fileData = std::move(file);
|
||||
dataReady.store(true, std::memory_order_seq_cst);
|
||||
dataReady.store(true);
|
||||
}
|
||||
|
||||
bool isFree()
|
||||
|
|
@ -114,8 +115,10 @@ public:
|
|||
this->samplesPerBlock = samplesPerBlock;
|
||||
tempBuffer1.resize(samplesPerBlock);
|
||||
tempBuffer2.resize(samplesPerBlock);
|
||||
indexBuffer.resize(samplesPerBlock);
|
||||
tempSpan1 = absl::MakeSpan(tempBuffer1);
|
||||
tempSpan2 = absl::MakeSpan(tempBuffer2);
|
||||
indexSpan = absl::MakeSpan(indexBuffer);
|
||||
}
|
||||
|
||||
void renderBlock(StereoSpan<float> buffer)
|
||||
|
|
@ -129,13 +132,14 @@ public:
|
|||
|
||||
if (region->isGenerator())
|
||||
fillWithGenerator(buffer);
|
||||
else
|
||||
else
|
||||
fillWithData(buffer);
|
||||
|
||||
egEnvelope.getBlock(tempSpan1.first(numSamples));
|
||||
buffer.applyGain(tempSpan1);
|
||||
// buffer.applyGain(baseGain);
|
||||
|
||||
buffer.applyGain(baseGain);
|
||||
auto envelopeSpan = tempSpan1.first(numSamples);
|
||||
egEnvelope.getBlock(envelopeSpan);
|
||||
// buffer.applyGain(envelopeSpan);
|
||||
|
||||
if (!egEnvelope.isSmoothing())
|
||||
reset();
|
||||
|
|
@ -143,20 +147,57 @@ public:
|
|||
|
||||
void fillWithData(StereoSpan<float> buffer)
|
||||
{
|
||||
const StereoSpan<const float> source([&]() -> StereoBuffer<float>& {
|
||||
// TODO: shouldn't need to check fileData here, something is a bit strange...
|
||||
if (dataReady.load(std::memory_order_seq_cst) && fileData != nullptr)
|
||||
return *fileData;
|
||||
auto source { [&]() {
|
||||
if (region->canUsePreloadedData() || !dataReady)
|
||||
return StereoSpan<const float>(*region->preloadedData);
|
||||
else
|
||||
return *region->preloadedData;
|
||||
}());
|
||||
return StereoSpan<const float>(*fileData);
|
||||
}()};
|
||||
|
||||
const auto actualBlockSize = min(buffer.size(), source.size() - sourcePosition);
|
||||
buffer.add(source.subspan(sourcePosition, actualBlockSize));
|
||||
sourcePosition += actualBlockSize;
|
||||
auto indices = indexSpan.first(buffer.size());
|
||||
auto jumps = tempSpan1.first(buffer.size());
|
||||
auto leftCoeffs = tempSpan1.first(buffer.size());
|
||||
auto rightCoeffs = tempSpan2.first(buffer.size());
|
||||
|
||||
if (sourcePosition == source.size())
|
||||
::fill<float>(jumps, pitchRatio * speedRatio);
|
||||
if (region->shouldLoop() && region->trueSampleEnd() <= source.size()) {
|
||||
floatPosition = ::loopingSFZIndex<float, false>(
|
||||
jumps,
|
||||
leftCoeffs,
|
||||
rightCoeffs,
|
||||
indices,
|
||||
floatPosition,
|
||||
region->trueSampleEnd() - 1,
|
||||
region->loopRange.getStart());
|
||||
} else {
|
||||
floatPosition = ::saturatingSFZIndex<float, false>(
|
||||
jumps,
|
||||
leftCoeffs,
|
||||
rightCoeffs,
|
||||
indices,
|
||||
floatPosition,
|
||||
source.size() - 1);
|
||||
}
|
||||
|
||||
auto ind = indices.data();
|
||||
auto leftCoeff = leftCoeffs.data();
|
||||
auto rightCoeff = rightCoeffs.data();
|
||||
auto left = buffer.left().data();
|
||||
auto right = buffer.right().data();
|
||||
while (ind < indices.end()) {
|
||||
*left = source.left()[*ind] * (*leftCoeff) + source.left()[*ind + 1] * (*rightCoeff);
|
||||
*right = source.right()[*ind] * (*leftCoeff) + source.right()[*ind + 1] * (*rightCoeff);
|
||||
left++;
|
||||
right++;
|
||||
ind++;
|
||||
leftCoeff++;
|
||||
rightCoeff++;
|
||||
}
|
||||
|
||||
if (!region->shouldLoop() && (floatPosition + 1.01) > source.size()) {
|
||||
DBG("Releasing " << region->sample);
|
||||
egEnvelope.startRelease(buffer.size());
|
||||
}
|
||||
}
|
||||
|
||||
void fillWithGenerator(StereoSpan<float> buffer)
|
||||
|
|
@ -168,7 +209,7 @@ public:
|
|||
phase = ::linearRamp<float>(tempSpan1, phase, step);
|
||||
::sin<float>(tempSpan1.first(buffer.size()), buffer.left());
|
||||
absl::c_copy(buffer.left(), buffer.right().begin());
|
||||
|
||||
|
||||
sourcePosition += buffer.size();
|
||||
}
|
||||
|
||||
|
|
@ -209,6 +250,8 @@ public:
|
|||
if (region != nullptr) {
|
||||
DBG("Reset voice with sample " << region->sample);
|
||||
}
|
||||
sourcePosition = 0;
|
||||
floatPosition = 0.0f;
|
||||
region = nullptr;
|
||||
noteIsOff = false;
|
||||
}
|
||||
|
|
@ -242,15 +285,19 @@ private:
|
|||
float phase { 0.0f };
|
||||
|
||||
uint32_t sourcePosition { 0 };
|
||||
float floatPosition { 0.0f };
|
||||
uint32_t initialDelay { 0 };
|
||||
|
||||
std::atomic<bool> dataReady { false };
|
||||
std::unique_ptr<StereoBuffer<float>, std::function<void(StereoBuffer<float>*)>> fileData { nullptr };
|
||||
// std::unique_ptr<StereoBuffer<float>, std::function<void(StereoBuffer<float>*)>> fileData { nullptr };
|
||||
std::unique_ptr<StereoBuffer<float>> fileData { nullptr };
|
||||
|
||||
Buffer<float> tempBuffer1;
|
||||
Buffer<float> tempBuffer2;
|
||||
Buffer<int> indexBuffer;
|
||||
absl::Span<float> tempSpan1 { absl::MakeSpan(tempBuffer1) };
|
||||
absl::Span<float> tempSpan2 { absl::MakeSpan(tempBuffer2) };
|
||||
absl::Span<int> indexSpan { absl::MakeSpan(indexBuffer) };
|
||||
|
||||
int samplesPerBlock { config::defaultSamplesPerBlock };
|
||||
double sampleRate { config::defaultSampleRate };
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue