Eliminate excessFileFrames from FilePool, use fixed padding buffer
This commit is contained in:
parent
dd5d11f4a3
commit
c94eea2a3f
2 changed files with 29 additions and 41 deletions
|
|
@ -39,11 +39,10 @@
|
||||||
#include <sndfile.hh>
|
#include <sndfile.hh>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
template <class T>
|
void readBaseFile(SndfileHandle& sndFile, sfz::FileAudioBuffer& output, uint32_t numFrames, bool reverse)
|
||||||
void readBaseFile(SndfileHandle& sndFile, sfz::AudioBuffer<T>& output, uint32_t numFrames, bool reverse)
|
|
||||||
{
|
{
|
||||||
output.reset();
|
output.reset();
|
||||||
output.resize(numFrames + 2 * sfz::config::excessFileFrames);
|
output.resize(numFrames);
|
||||||
|
|
||||||
if (reverse)
|
if (reverse)
|
||||||
sndFile.seek(-static_cast<sf_count_t>(numFrames), SEEK_END);
|
sndFile.seek(-static_cast<sf_count_t>(numFrames), SEEK_END);
|
||||||
|
|
@ -53,48 +52,42 @@ void readBaseFile(SndfileHandle& sndFile, sfz::AudioBuffer<T>& output, uint32_t
|
||||||
if (channels == 1) {
|
if (channels == 1) {
|
||||||
output.addChannel();
|
output.addChannel();
|
||||||
output.clear();
|
output.clear();
|
||||||
sndFile.readf(output.channelWriter(0) + sfz::config::excessFileFrames, numFrames);
|
sndFile.readf(output.channelWriter(0), numFrames);
|
||||||
} else if (channels == 2) {
|
} else if (channels == 2) {
|
||||||
output.addChannel();
|
output.addChannel();
|
||||||
output.addChannel();
|
output.addChannel();
|
||||||
output.clear();
|
output.clear();
|
||||||
sfz::Buffer<T> tempReadBuffer { 2 * numFrames };
|
sfz::Buffer<float> tempReadBuffer { 2 * numFrames };
|
||||||
sndFile.readf(tempReadBuffer.data(), numFrames);
|
sndFile.readf(tempReadBuffer.data(), numFrames);
|
||||||
sfz::readInterleaved<T>(tempReadBuffer,
|
sfz::readInterleaved<float>(tempReadBuffer, output.getSpan(0), output.getSpan(1));
|
||||||
output.getSpan(0).subspan(sfz::config::excessFileFrames, numFrames),
|
|
||||||
output.getSpan(1).subspan(sfz::config::excessFileFrames, numFrames)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reverse) {
|
if (reverse) {
|
||||||
for (unsigned c = 0; c < channels; ++c) {
|
for (unsigned c = 0; c < channels; ++c) {
|
||||||
// TODO: consider optimizing with SIMD
|
// TODO: consider optimizing with SIMD
|
||||||
absl::Span<float> channel = output.getSpan(c).subspan(sfz::config::excessFileFrames, numFrames);
|
absl::Span<float> channel = output.getSpan(c);
|
||||||
std::reverse(channel.begin(), channel.end());
|
std::reverse(channel.begin(), channel.end());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
std::unique_ptr<sfz::FileAudioBuffer> readFromFile(SndfileHandle& sndFile, uint32_t numFrames, sfz::Oversampling factor, bool reverse)
|
||||||
std::unique_ptr<sfz::AudioBuffer<T>> readFromFile(SndfileHandle& sndFile, uint32_t numFrames, sfz::Oversampling factor, bool reverse)
|
|
||||||
{
|
{
|
||||||
auto baseBuffer = absl::make_unique<sfz::AudioBuffer<T>>();
|
auto baseBuffer = absl::make_unique<sfz::FileAudioBuffer>();
|
||||||
readBaseFile(sndFile, *baseBuffer, numFrames, reverse);
|
readBaseFile(sndFile, *baseBuffer, numFrames, reverse);
|
||||||
|
|
||||||
if (factor == sfz::Oversampling::x1)
|
if (factor == sfz::Oversampling::x1)
|
||||||
return baseBuffer;
|
return baseBuffer;
|
||||||
|
|
||||||
auto outputBuffer = absl::make_unique<sfz::AudioBuffer<T>>(sndFile.channels(), numFrames * static_cast<int>(factor) + 2 * sfz::config::excessFileFrames);
|
auto outputBuffer = absl::make_unique<sfz::FileAudioBuffer>(sndFile.channels(), numFrames * static_cast<int>(factor));
|
||||||
outputBuffer->clear();
|
outputBuffer->clear();
|
||||||
auto baseSpan = sfz::AudioSpan<T>(*baseBuffer).subspan(sfz::config::excessFileFrames, numFrames);
|
|
||||||
auto outputSpan = sfz::AudioSpan<T>(*outputBuffer).subspan(sfz::config::excessFileFrames, numFrames * static_cast<int>(factor));
|
|
||||||
sfz::Oversampler oversampler { factor };
|
sfz::Oversampler oversampler { factor };
|
||||||
oversampler.stream(baseSpan, outputSpan);
|
oversampler.stream(*baseBuffer, *outputBuffer);
|
||||||
return outputBuffer;
|
return outputBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
void streamFromFile(SndfileHandle& sndFile, uint32_t numFrames, sfz::Oversampling factor, bool reverse, sfz::AudioBuffer<float>& output, std::atomic<size_t>* filledFrames = nullptr)
|
void streamFromFile(SndfileHandle& sndFile, uint32_t numFrames, sfz::Oversampling factor, bool reverse, sfz::FileAudioBuffer& output, std::atomic<size_t>* filledFrames = nullptr)
|
||||||
{
|
{
|
||||||
if (factor == sfz::Oversampling::x1) {
|
if (factor == sfz::Oversampling::x1) {
|
||||||
readBaseFile(sndFile, output, numFrames, reverse);
|
readBaseFile(sndFile, output, numFrames, reverse);
|
||||||
|
|
@ -103,15 +96,13 @@ void streamFromFile(SndfileHandle& sndFile, uint32_t numFrames, sfz::Oversamplin
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto baseBuffer = readFromFile<T>(sndFile, numFrames, sfz::Oversampling::x1, reverse);
|
auto baseBuffer = readFromFile(sndFile, numFrames, sfz::Oversampling::x1, reverse);
|
||||||
output.reset();
|
output.reset();
|
||||||
output.addChannels(baseBuffer->getNumChannels());
|
output.addChannels(baseBuffer->getNumChannels());
|
||||||
output.resize(numFrames * static_cast<int>(factor) + 2 * sfz::config::excessFileFrames);
|
output.resize(numFrames * static_cast<int>(factor));
|
||||||
output.clear();
|
output.clear();
|
||||||
sfz::Oversampler oversampler { factor };
|
sfz::Oversampler oversampler { factor };
|
||||||
auto baseSpan = sfz::AudioSpan<T>(*baseBuffer).subspan(sfz::config::excessFileFrames, numFrames);
|
oversampler.stream(*baseBuffer, output, filledFrames);
|
||||||
auto outputSpan = sfz::AudioSpan<T>(output).subspan(sfz::config::excessFileFrames, numFrames * static_cast<int>(factor));
|
|
||||||
oversampler.stream(baseSpan, outputSpan, filledFrames);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sfz::FilePool::FilePool(sfz::Logger& logger)
|
sfz::FilePool::FilePool(sfz::Logger& logger)
|
||||||
|
|
@ -272,12 +263,12 @@ bool sfz::FilePool::preloadFile(const FileId& fileId, uint32_t maxOffset) noexce
|
||||||
const auto existingFile = preloadedFiles.find(fileId);
|
const auto existingFile = preloadedFiles.find(fileId);
|
||||||
if (existingFile != preloadedFiles.end()) {
|
if (existingFile != preloadedFiles.end()) {
|
||||||
if (framesToLoad > existingFile->second.preloadedData->getNumFrames()) {
|
if (framesToLoad > existingFile->second.preloadedData->getNumFrames()) {
|
||||||
preloadedFiles[fileId].preloadedData = readFromFile<float>(sndFile, framesToLoad, oversamplingFactor, fileId.isReverse());
|
preloadedFiles[fileId].preloadedData = readFromFile(sndFile, framesToLoad, oversamplingFactor, fileId.isReverse());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fileInformation->sampleRate = static_cast<float>(oversamplingFactor) * static_cast<float>(sndFile.samplerate());
|
fileInformation->sampleRate = static_cast<float>(oversamplingFactor) * static_cast<float>(sndFile.samplerate());
|
||||||
FileDataHandle handle {
|
FileDataHandle handle {
|
||||||
readFromFile<float>(sndFile, framesToLoad, oversamplingFactor, fileId.isReverse()),
|
readFromFile(sndFile, framesToLoad, oversamplingFactor, fileId.isReverse()),
|
||||||
*fileInformation
|
*fileInformation
|
||||||
};
|
};
|
||||||
preloadedFiles.insert_or_assign(fileId, handle);
|
preloadedFiles.insert_or_assign(fileId, handle);
|
||||||
|
|
@ -302,7 +293,7 @@ absl::optional<sfz::FileDataHandle> sfz::FilePool::loadFile(const FileId& fileId
|
||||||
} else {
|
} else {
|
||||||
fileInformation->sampleRate = static_cast<float>(oversamplingFactor) * static_cast<float>(sndFile.samplerate());
|
fileInformation->sampleRate = static_cast<float>(oversamplingFactor) * static_cast<float>(sndFile.samplerate());
|
||||||
FileDataHandle handle {
|
FileDataHandle handle {
|
||||||
readFromFile<float>(sndFile, frames, oversamplingFactor, fileId.isReverse()),
|
readFromFile(sndFile, frames, oversamplingFactor, fileId.isReverse()),
|
||||||
*fileInformation
|
*fileInformation
|
||||||
};
|
};
|
||||||
loadedFiles.insert_or_assign(fileId, handle);
|
loadedFiles.insert_or_assign(fileId, handle);
|
||||||
|
|
@ -352,7 +343,7 @@ void sfz::FilePool::setPreloadSize(uint32_t preloadSize) noexcept
|
||||||
const auto maxOffset = numFrames > this->preloadSize ? static_cast<uint32_t>(numFrames) - this->preloadSize : 0;
|
const auto maxOffset = numFrames > this->preloadSize ? static_cast<uint32_t>(numFrames) - this->preloadSize : 0;
|
||||||
fs::path file { rootDirectory / preloadedFile.first.filename() };
|
fs::path file { rootDirectory / preloadedFile.first.filename() };
|
||||||
SndfileHandle sndFile(file.string().c_str());
|
SndfileHandle sndFile(file.string().c_str());
|
||||||
preloadedFile.second.preloadedData = readFromFile<float>(sndFile, preloadSize + maxOffset, oversamplingFactor, preloadedFile.first.isReverse());
|
preloadedFile.second.preloadedData = readFromFile(sndFile, preloadSize + maxOffset, oversamplingFactor, preloadedFile.first.isReverse());
|
||||||
}
|
}
|
||||||
this->preloadSize = preloadSize;
|
this->preloadSize = preloadSize;
|
||||||
}
|
}
|
||||||
|
|
@ -481,7 +472,7 @@ void sfz::FilePool::setOversamplingFactor(sfz::Oversampling factor) noexcept
|
||||||
const uint32_t maxOffset = numFrames > this->preloadSize ? static_cast<uint32_t>(numFrames) - this->preloadSize : 0;
|
const uint32_t maxOffset = numFrames > this->preloadSize ? static_cast<uint32_t>(numFrames) - this->preloadSize : 0;
|
||||||
fs::path file { rootDirectory / preloadedFile.first.filename() };
|
fs::path file { rootDirectory / preloadedFile.first.filename() };
|
||||||
SndfileHandle sndFile(file.string().c_str());
|
SndfileHandle sndFile(file.string().c_str());
|
||||||
preloadedFile.second.preloadedData = readFromFile<float>(sndFile, preloadSize + maxOffset, factor, preloadedFile.first.isReverse());
|
preloadedFile.second.preloadedData = readFromFile(sndFile, preloadSize + maxOffset, factor, preloadedFile.first.isReverse());
|
||||||
preloadedFile.second.information.sampleRate *= samplerateChange;
|
preloadedFile.second.information.sampleRate *= samplerateChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,9 @@
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
namespace sfz {
|
namespace sfz {
|
||||||
using AudioBufferPtr = std::shared_ptr<AudioBuffer<float>>;
|
using FileAudioBuffer = AudioBuffer<float, 2, SIMDConfig::defaultAlignment,
|
||||||
|
sfz::config::excessFileFrames, sfz::config::excessFileFrames>;
|
||||||
|
using FileAudioBufferPtr = std::shared_ptr<FileAudioBuffer>;
|
||||||
|
|
||||||
struct FileInformation {
|
struct FileInformation {
|
||||||
uint32_t end { Default::sampleEndRange.getEnd() };
|
uint32_t end { Default::sampleEndRange.getEnd() };
|
||||||
|
|
@ -56,7 +58,7 @@ struct FileInformation {
|
||||||
// Strict C++11 disallows member initialization if aggregate initialization is to be used...
|
// Strict C++11 disallows member initialization if aggregate initialization is to be used...
|
||||||
struct FileDataHandle
|
struct FileDataHandle
|
||||||
{
|
{
|
||||||
std::shared_ptr<AudioBuffer<float>> preloadedData;
|
FileAudioBufferPtr preloadedData;
|
||||||
FileInformation information;
|
FileInformation information;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -65,16 +67,11 @@ struct FilePromise
|
||||||
AudioSpan<const float> getData()
|
AudioSpan<const float> getData()
|
||||||
{
|
{
|
||||||
if (dataStatus == DataStatus::Ready)
|
if (dataStatus == DataStatus::Ready)
|
||||||
return AudioSpan<const float>(fileData)
|
return AudioSpan<const float>(fileData);
|
||||||
.subspan(sfz::config::excessFileFrames,
|
else if (availableFrames > preloadedData->getNumFrames())
|
||||||
fileData.getNumFrames() - 2 * sfz::config::excessFileFrames);
|
return AudioSpan<const float>(fileData).first(availableFrames);
|
||||||
else if (availableFrames > preloadedData->getNumFrames() + sfz::config::excessFileFrames)
|
|
||||||
return AudioSpan<const float>(fileData)
|
|
||||||
.subspan(sfz::config::excessFileFrames, availableFrames - sfz::config::excessFileFrames);
|
|
||||||
else
|
else
|
||||||
return AudioSpan<const float>(*preloadedData)
|
return AudioSpan<const float>(*preloadedData);
|
||||||
.subspan(sfz::config::excessFileFrames,
|
|
||||||
preloadedData->getNumFrames() - 2 * sfz::config::excessFileFrames);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset()
|
void reset()
|
||||||
|
|
@ -101,8 +98,8 @@ struct FilePromise
|
||||||
};
|
};
|
||||||
|
|
||||||
FileId fileId {};
|
FileId fileId {};
|
||||||
AudioBufferPtr preloadedData {};
|
FileAudioBufferPtr preloadedData {};
|
||||||
AudioBuffer<float> fileData {};
|
FileAudioBuffer fileData {};
|
||||||
float sampleRate { config::defaultSampleRate };
|
float sampleRate { config::defaultSampleRate };
|
||||||
Oversampling oversamplingFactor { config::defaultOversamplingFactor };
|
Oversampling oversamplingFactor { config::defaultOversamplingFactor };
|
||||||
std::atomic<size_t> availableFrames { 0 };
|
std::atomic<size_t> availableFrames { 0 };
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue