Corrected a big error in the file loading for mono files

This commit is contained in:
paulfd 2019-08-29 02:23:33 +02:00
parent 0ee2717559
commit 392813dd6d
12 changed files with 176 additions and 46 deletions

View file

@ -1,6 +1,11 @@
#include "FilePool.h" #include "FilePool.h"
#include "Globals.h"
#include "absl/types/span.h"
#include <chrono> #include <chrono>
#include <fstream>
#include <memory> #include <memory>
#include <sstream>
#include <string>
using namespace std::chrono_literals; using namespace std::chrono_literals;
std::optional<sfz::FilePool::FileInformation> sfz::FilePool::getFileInformation(std::string_view filename) 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 {}; return {};
SndfileHandle sndFile(reinterpret_cast<const char*>(file.c_str())); 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; FileInformation returnedValue;
returnedValue.end = static_cast<uint32_t>(sndFile.frames()); returnedValue.end = static_cast<uint32_t>(sndFile.frames());
returnedValue.sampleRate = static_cast<double>(sndFile.samplerate()); returnedValue.sampleRate = static_cast<double>(sndFile.samplerate());
SF_INSTRUMENT instrumentInfo; SF_INSTRUMENT instrumentInfo;
sndFile.command(SFC_GET_INSTRUMENT, &instrumentInfo, sizeof(instrumentInfo)); sndFile.command(SFC_GET_INSTRUMENT, &instrumentInfo, sizeof(instrumentInfo));
if (instrumentInfo.loop_count == 1) { if (instrumentInfo.loop_count == 1) {
returnedValue.loopBegin = instrumentInfo.loops[0].start; returnedValue.loopBegin = instrumentInfo.loops[0].start;
returnedValue.loopEnd = instrumentInfo.loops[0].end; 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); 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; 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] ; // char buffer [2048] ;
// sndFile.command(SFC_GET_LOG_INFO, buffer, sizeof(buffer)) ; // sndFile.command(SFC_GET_LOG_INFO, buffer, sizeof(buffer)) ;
// DBG(buffer); // DBG(buffer);
@ -58,13 +89,19 @@ void sfz::FilePool::loadingThread()
} }
SndfileHandle sndFile(reinterpret_cast<const char*>(file.c_str())); SndfileHandle sndFile(reinterpret_cast<const char*>(file.c_str()));
// auto deleteAndTrackBuffers = [this] auto fileLoaded = std::make_unique<StereoBuffer<float>>(fileToLoad.numFrames);
std::unique_ptr<StereoBuffer<float>, std::function<void(StereoBuffer<float>*)>> fileLoaded(new StereoBuffer<float>(fileToLoad.numFrames), deleteAndTrackBuffers); if (sndFile.channels() == 1) {
auto readBuffer = std::make_unique<Buffer<float>>(fileToLoad.numFrames * 2); tempReadBuffer.resize(fileToLoad.numFrames);
sndFile.readf(readBuffer->data(), fileToLoad.numFrames); sndFile.readf(tempReadBuffer.data(), fileToLoad.numFrames);
fileLoaded->readInterleaved(*readBuffer); std::copy(tempReadBuffer.begin(), tempReadBuffer.end(), fileLoaded->begin(Channel::left));
ASSERT(fileLoaded != nullptr); std::copy(tempReadBuffer.begin(), tempReadBuffer.end(), fileLoaded->begin(Channel::right));
fileBuffers++; } 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)); fileToLoad.voice->setFileData(std::move(fileLoaded));
} }
} }

View file

@ -55,14 +55,12 @@ private:
}; };
inline static std::atomic<int> fileBuffers { 0 }; inline static std::atomic<int> fileBuffers { 0 };
int preloadedFilesWritten {0};
moodycamel::BlockingReaderWriterQueue<FileLoadingInformation> loadingQueue; moodycamel::BlockingReaderWriterQueue<FileLoadingInformation> loadingQueue;
void loadingThread(); void loadingThread();
std::thread fileLoadingThread; std::thread fileLoadingThread;
bool quitThread { false }; bool quitThread { false };
Buffer<float> tempReadBuffer { config::preloadSize * 2 }; Buffer<float> tempReadBuffer;
// std::map<std::string_view, std::shared_ptr<StereoBuffer<float>>> preloadedData;
absl::flat_hash_map<std::string_view, std::shared_ptr<StereoBuffer<float>>> preloadedData; absl::flat_hash_map<std::string_view, std::shared_ptr<StereoBuffer<float>>> preloadedData;
LEAK_DETECTOR(FilePool); LEAK_DETECTOR(FilePool);
}; };

View file

@ -27,6 +27,7 @@ constexpr bool fill { true };
constexpr bool gain { false }; constexpr bool gain { false };
constexpr bool mathfuns { false }; constexpr bool mathfuns { false };
constexpr bool loopingSFZIndex { true }; constexpr bool loopingSFZIndex { true };
constexpr bool saturatingSFZIndex { true };
constexpr bool linearRamp { false }; constexpr bool linearRamp { false };
constexpr bool multiplicativeRamp { true }; constexpr bool multiplicativeRamp { true };
constexpr bool add { false }; constexpr bool add { false };

View file

@ -92,7 +92,7 @@ int process(jack_nframes_t numFrames, void* arg [[maybe_unused]])
break; break;
} }
} }
// DBG("Num frames: " << numFrames);
StereoSpan<float> output { StereoSpan<float> output {
jack_port_get_buffer(outputPort1, numFrames), jack_port_get_buffer(outputPort1, numFrames),
jack_port_get_buffer(outputPort2, numFrames), jack_port_get_buffer(outputPort2, numFrames),
@ -100,6 +100,7 @@ int process(jack_nframes_t numFrames, void* arg [[maybe_unused]])
}; };
synth->renderBlock(output); synth->renderBlock(output);
return 0; return 0;
} }

View file

@ -323,6 +323,7 @@ bool sfz::Region::parseOpcode(const Opcode& opcode)
break; break;
case hash("pitch_random"): case hash("pitch_random"):
setValueFromOpcode(opcode, pitchRandom, Default::pitchRandomRange); setValueFromOpcode(opcode, pitchRandom, Default::pitchRandomRange);
pitchDistribution.param(std::uniform_int_distribution<int>::param_type(-pitchRandom, pitchRandom));
break; break;
case hash("transpose"): case hash("transpose"):
setValueFromOpcode(opcode, transpose, Default::transposeRange); setValueFromOpcode(opcode, transpose, Default::transposeRange);

View file

@ -32,6 +32,16 @@ struct Region {
void registerAftertouch(int channel, uint8_t aftertouch); void registerAftertouch(int channel, uint8_t aftertouch);
void registerTempo(float secondsPerQuarter); void registerTempo(float secondsPerQuarter);
bool isStereo() const noexcept; 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 getBaseGain()
{ {
float baseGaindB { volume }; float baseGaindB { volume };
@ -51,6 +61,13 @@ struct Region {
{ {
return min(sampleEnd, loopRange.getEnd()); 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); bool parseOpcode(const Opcode& opcode);
// Sound source: sample playback // 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> gainDistribution { -sfz::Default::ampRandom, sfz::Default::ampRandom };
std::uniform_real_distribution<float> delayDistribution { 0, sfz::Default::delayRandom }; 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<uint32_t> offsetDistribution { 0, sfz::Default::offsetRandom };
std::uniform_int_distribution<int> pitchDistribution { -sfz::Default::pitchRandom, sfz::Default::pitchRandom };
LEAK_DETECTOR(Region); LEAK_DETECTOR(Region);
}; };

View file

@ -56,11 +56,18 @@ void applyGain<float, true>(absl::Span<const float> gain, absl::Span<const float
} }
template <> 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 <> template <>
float linearRamp<float, true>(absl::Span<float> output, float start, float step) noexcept float linearRamp<float, true>(absl::Span<float> output, float start, float step) noexcept
{ {

View file

@ -133,7 +133,7 @@ inline void snippetSaturatingIndex(const T*& jump, T*& leftCoeff, T*& rightCoeff
} }
template <class T, bool SIMD = SIMDConfig::saturatingSFZIndex> 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() >= jumps.size());
ASSERT(indices.size() == leftCoeffs.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) while (jump < sentinel)
snippetSaturatingIndex<T>(jump, leftCoeff, rightCoeff, index, floatIndex, loopEnd); snippetSaturatingIndex<T>(jump, leftCoeff, rightCoeff, index, floatIndex, loopEnd);
return floatIndex;
} }
template <> 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> template <class T>
inline void snippetLoopingIndex(const T*& jump, T*& leftCoeff, T*& rightCoeff, int*& index, T& floatIndex, T loopEnd, T loopStart) 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> 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() >= jumps.size());
ASSERT(indices.size() == leftCoeffs.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) while (jump < sentinel)
snippetLoopingIndex<T>(jump, leftCoeff, rightCoeff, index, floatIndex, loopEnd, loopStart); snippetLoopingIndex<T>(jump, leftCoeff, rightCoeff, index, floatIndex, loopEnd, loopStart);
return floatIndex;
} }
template <> 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> template <class T>
inline void snippetGain(T gain, const T*& input, T*& output) inline void snippetGain(T gain, const T*& input, T*& output)

View file

@ -283,7 +283,7 @@ void applyGain<float, true>(absl::Span<const float> gain, absl::Span<const float
} }
template <> 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> leftCoeffs,
absl::Span<float> rightCoeffs, absl::Span<float> rightCoeffs,
absl::Span<int> indices, absl::Span<int> indices,
@ -341,10 +341,11 @@ void loopingSFZIndex<float, true>(absl::Span<const float> jumps,
floatIndex = _mm_cvtss_f32(mmFloatIndex); floatIndex = _mm_cvtss_f32(mmFloatIndex);
while (jump < sentinel) while (jump < sentinel)
snippetLoopingIndex<float>(jump, leftCoeff, rightCoeff, index, floatIndex, loopEnd, loopStart); snippetLoopingIndex<float>(jump, leftCoeff, rightCoeff, index, floatIndex, loopEnd, loopStart);
return floatIndex;
} }
template <> 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> leftCoeffs,
absl::Span<float> rightCoeffs, absl::Span<float> rightCoeffs,
absl::Span<int> indices, absl::Span<int> indices,
@ -398,6 +399,7 @@ void saturatingSFZIndex<float, true>(absl::Span<const float> jumps,
floatIndex = _mm_cvtss_f32(mmFloatIndex); floatIndex = _mm_cvtss_f32(mmFloatIndex);
while (jump < sentinel) while (jump < sentinel)
snippetSaturatingIndex<float>(jump, leftCoeff, rightCoeff, index, floatIndex, loopEnd); snippetSaturatingIndex<float>(jump, leftCoeff, rightCoeff, index, floatIndex, loopEnd);
return floatIndex;
} }
template <> template <>

View file

@ -34,7 +34,14 @@ public:
ASSERT(leftBuffer.size() == rightBuffer.size()); 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)) : leftBuffer(buffer.getConstSpan(Channel::left))
, rightBuffer(buffer.getConstSpan(Channel::right)) , rightBuffer(buffer.getConstSpan(Channel::right))
, numFrames(buffer.getNumFrames()) , 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) StereoSpan(StereoBuffer<ValueType>& buffer, size_t numFrames)
: numFrames(numFrames) : numFrames(numFrames)
, leftBuffer(buffer.getSpan(Channel::left).first(numFrames)) , leftBuffer(buffer.getSpan(Channel::left).first(numFrames))
@ -74,6 +88,7 @@ public:
, leftBuffer(span.left()) , leftBuffer(span.left())
, rightBuffer(span.right()) , rightBuffer(span.right())
{ {
} }
void fill(Type value) noexcept void fill(Type value) noexcept

View file

@ -62,11 +62,11 @@ public:
{ {
ScopedFTZ ftz; ScopedFTZ ftz;
buffer.fill(0.0f); buffer.fill(0.0f);
StereoSpan<float> tempSpan { tempBuffer, buffer.size() }; StereoSpan<float> tempSpan { tempBuffer, buffer.size() };
for (auto& voice : voices) { for (auto& voice : voices) {
voice->renderBlock(tempSpan); voice->renderBlock(tempSpan);
buffer.add(tempSpan); buffer.add(tempSpan);
tempBuffer.fill(0.0f);
} }
} }
@ -108,6 +108,7 @@ public:
} }
} }
} }
void cc(int delay, int channel, int ccNumber, uint8_t ccValue) void cc(int delay, int channel, int ccNumber, uint8_t ccValue)
{ {
for (auto& voice : voices) for (auto& voice : voices)
@ -155,7 +156,7 @@ private:
activeVoices++; activeVoices++;
} }
DBG("Active voices:" << activeVoices << " | Stray buffers: " << FilePool::getFileBuffers()); DBG("Active voices:" << activeVoices << " | Stray buffers: " << FilePool::getFileBuffers());
std::this_thread::sleep_for(1s); std::this_thread::sleep_for(200ms);
} }
} }

View file

@ -41,10 +41,11 @@ public:
state = State::playing; state = State::playing;
speedRatio = static_cast<float>(region->sampleRate / this->sampleRate); speedRatio = static_cast<float>(region->sampleRate / this->sampleRate);
pitchRatio = region->getBasePitchVariation(number, value);
baseGain = region->getBaseGain(); baseGain = region->getBaseGain();
sourcePosition = region->getOffset(); sourcePosition = region->getOffset();
initialDelay = delay + region->getDelay(); initialDelay = delay + region->getDelay();
baseFrequency = midiNoteFrequency(number); baseFrequency = midiNoteFrequency(number) * pitchRatio;
prepareEGEnvelope(delay, value); prepareEGEnvelope(delay, value);
} }
@ -64,10 +65,10 @@ public:
normalizePercents(region->amplitudeEG.getStart(ccState, velocity))); 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); fileData = std::move(file);
dataReady.store(true, std::memory_order_seq_cst); dataReady.store(true);
} }
bool isFree() bool isFree()
@ -114,8 +115,10 @@ public:
this->samplesPerBlock = samplesPerBlock; this->samplesPerBlock = samplesPerBlock;
tempBuffer1.resize(samplesPerBlock); tempBuffer1.resize(samplesPerBlock);
tempBuffer2.resize(samplesPerBlock); tempBuffer2.resize(samplesPerBlock);
indexBuffer.resize(samplesPerBlock);
tempSpan1 = absl::MakeSpan(tempBuffer1); tempSpan1 = absl::MakeSpan(tempBuffer1);
tempSpan2 = absl::MakeSpan(tempBuffer2); tempSpan2 = absl::MakeSpan(tempBuffer2);
indexSpan = absl::MakeSpan(indexBuffer);
} }
void renderBlock(StereoSpan<float> buffer) void renderBlock(StereoSpan<float> buffer)
@ -132,10 +135,11 @@ public:
else else
fillWithData(buffer); fillWithData(buffer);
egEnvelope.getBlock(tempSpan1.first(numSamples)); // buffer.applyGain(baseGain);
buffer.applyGain(tempSpan1);
buffer.applyGain(baseGain); auto envelopeSpan = tempSpan1.first(numSamples);
egEnvelope.getBlock(envelopeSpan);
// buffer.applyGain(envelopeSpan);
if (!egEnvelope.isSmoothing()) if (!egEnvelope.isSmoothing())
reset(); reset();
@ -143,20 +147,57 @@ public:
void fillWithData(StereoSpan<float> buffer) void fillWithData(StereoSpan<float> buffer)
{ {
const StereoSpan<const float> source([&]() -> StereoBuffer<float>& { auto source { [&]() {
// TODO: shouldn't need to check fileData here, something is a bit strange... if (region->canUsePreloadedData() || !dataReady)
if (dataReady.load(std::memory_order_seq_cst) && fileData != nullptr) return StereoSpan<const float>(*region->preloadedData);
return *fileData;
else else
return *region->preloadedData; return StereoSpan<const float>(*fileData);
}()); }()};
const auto actualBlockSize = min(buffer.size(), source.size() - sourcePosition); auto indices = indexSpan.first(buffer.size());
buffer.add(source.subspan(sourcePosition, actualBlockSize)); auto jumps = tempSpan1.first(buffer.size());
sourcePosition += actualBlockSize; 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()); egEnvelope.startRelease(buffer.size());
}
} }
void fillWithGenerator(StereoSpan<float> buffer) void fillWithGenerator(StereoSpan<float> buffer)
@ -209,6 +250,8 @@ public:
if (region != nullptr) { if (region != nullptr) {
DBG("Reset voice with sample " << region->sample); DBG("Reset voice with sample " << region->sample);
} }
sourcePosition = 0;
floatPosition = 0.0f;
region = nullptr; region = nullptr;
noteIsOff = false; noteIsOff = false;
} }
@ -242,15 +285,19 @@ private:
float phase { 0.0f }; float phase { 0.0f };
uint32_t sourcePosition { 0 }; uint32_t sourcePosition { 0 };
float floatPosition { 0.0f };
uint32_t initialDelay { 0 }; uint32_t initialDelay { 0 };
std::atomic<bool> dataReady { false }; 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> tempBuffer1;
Buffer<float> tempBuffer2; Buffer<float> tempBuffer2;
Buffer<int> indexBuffer;
absl::Span<float> tempSpan1 { absl::MakeSpan(tempBuffer1) }; absl::Span<float> tempSpan1 { absl::MakeSpan(tempBuffer1) };
absl::Span<float> tempSpan2 { absl::MakeSpan(tempBuffer2) }; absl::Span<float> tempSpan2 { absl::MakeSpan(tempBuffer2) };
absl::Span<int> indexSpan { absl::MakeSpan(indexBuffer) };
int samplesPerBlock { config::defaultSamplesPerBlock }; int samplesPerBlock { config::defaultSamplesPerBlock };
double sampleRate { config::defaultSampleRate }; double sampleRate { config::defaultSampleRate };