Add excessFileFrames at the beginning of the file dataRecenter the 4-sample splines from -1 to 2 (relative to the interpolated sample) rather than 0 to 3
This commit is contained in:
parent
c48e14ee2b
commit
590af85823
6 changed files with 44 additions and 19 deletions
|
|
@ -27,6 +27,7 @@
|
|||
#include "FileInstrument.h"
|
||||
#include "Buffer.h"
|
||||
#include "AudioBuffer.h"
|
||||
#include "AudioSpan.h"
|
||||
#include "Config.h"
|
||||
#include "Debug.h"
|
||||
#include "Oversampler.h"
|
||||
|
|
@ -42,7 +43,7 @@ template <class T>
|
|||
void readBaseFile(SndfileHandle& sndFile, sfz::AudioBuffer<T>& output, uint32_t numFrames, bool reverse)
|
||||
{
|
||||
output.reset();
|
||||
output.resize(numFrames + sfz::config::excessFileFrames);
|
||||
output.resize(numFrames + 2 * sfz::config::excessFileFrames);
|
||||
|
||||
if (reverse)
|
||||
sndFile.seek(-static_cast<sf_count_t>(numFrames), SEEK_END);
|
||||
|
|
@ -52,20 +53,23 @@ void readBaseFile(SndfileHandle& sndFile, sfz::AudioBuffer<T>& output, uint32_t
|
|||
if (channels == 1) {
|
||||
output.addChannel();
|
||||
output.clear();
|
||||
sndFile.readf(output.channelWriter(0), numFrames);
|
||||
sndFile.readf(output.channelWriter(0) + sfz::config::excessFileFrames, numFrames);
|
||||
} else if (channels == 2) {
|
||||
output.addChannel();
|
||||
output.addChannel();
|
||||
output.clear();
|
||||
sfz::Buffer<T> tempReadBuffer { 2 * numFrames };
|
||||
sndFile.readf(tempReadBuffer.data(), numFrames);
|
||||
sfz::readInterleaved<T>(tempReadBuffer, output.getSpan(0).first(numFrames), output.getSpan(1).first(numFrames));
|
||||
sfz::readInterleaved<T>(tempReadBuffer,
|
||||
output.getSpan(0).subspan(sfz::config::excessFileFrames, numFrames),
|
||||
output.getSpan(1).subspan(sfz::config::excessFileFrames, numFrames)
|
||||
);
|
||||
}
|
||||
|
||||
if (reverse) {
|
||||
for (unsigned c = 0; c < channels; ++c) {
|
||||
// TODO: consider optimizing with SIMD
|
||||
absl::Span<float> channel = output.getSpan(c).first(numFrames);
|
||||
absl::Span<float> channel = output.getSpan(c).subspan(sfz::config::excessFileFrames, numFrames);
|
||||
std::reverse(channel.begin(), channel.end());
|
||||
}
|
||||
}
|
||||
|
|
@ -80,10 +84,12 @@ std::unique_ptr<sfz::AudioBuffer<T>> readFromFile(SndfileHandle& sndFile, uint32
|
|||
if (factor == sfz::Oversampling::x1)
|
||||
return baseBuffer;
|
||||
|
||||
auto outputBuffer = absl::make_unique<sfz::AudioBuffer<T>>(sndFile.channels(), numFrames * static_cast<int>(factor) + sfz::config::excessFileFrames);
|
||||
auto outputBuffer = absl::make_unique<sfz::AudioBuffer<T>>(sndFile.channels(), numFrames * static_cast<int>(factor) + 2 * sfz::config::excessFileFrames);
|
||||
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 };
|
||||
oversampler.stream(*baseBuffer, *outputBuffer);
|
||||
oversampler.stream(baseSpan, outputSpan);
|
||||
return outputBuffer;
|
||||
}
|
||||
|
||||
|
|
@ -100,10 +106,12 @@ void streamFromFile(SndfileHandle& sndFile, uint32_t numFrames, sfz::Oversamplin
|
|||
auto baseBuffer = readFromFile<T>(sndFile, numFrames, sfz::Oversampling::x1, reverse);
|
||||
output.reset();
|
||||
output.addChannels(baseBuffer->getNumChannels());
|
||||
output.resize(numFrames * static_cast<int>(factor) + sfz::config::excessFileFrames);
|
||||
output.resize(numFrames * static_cast<int>(factor) + 2 * sfz::config::excessFileFrames);
|
||||
output.clear();
|
||||
sfz::Oversampler oversampler { factor };
|
||||
oversampler.stream(*baseBuffer, output, filledFrames);
|
||||
auto baseSpan = sfz::AudioSpan<T>(*baseBuffer).subspan(sfz::config::excessFileFrames, numFrames);
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -66,11 +66,14 @@ struct FilePromise
|
|||
{
|
||||
if (dataStatus == DataStatus::Ready)
|
||||
return AudioSpan<const float>(fileData)
|
||||
.first(fileData.getNumFrames() - sfz::config::excessFileFrames);
|
||||
.subspan(sfz::config::excessFileFrames,
|
||||
fileData.getNumFrames() - 2 * sfz::config::excessFileFrames);
|
||||
else if (availableFrames > preloadedData->getNumFrames())
|
||||
return AudioSpan<const float>(fileData).first(availableFrames);
|
||||
return AudioSpan<const float>(fileData).subspan(sfz::config::excessFileFrames, availableFrames);
|
||||
else
|
||||
return AudioSpan<const float>(*preloadedData);
|
||||
return AudioSpan<const float>(*preloadedData)
|
||||
.subspan(sfz::config::excessFileFrames,
|
||||
preloadedData->getNumFrames() - sfz::config::excessFileFrames);
|
||||
}
|
||||
|
||||
void reset()
|
||||
|
|
|
|||
|
|
@ -17,6 +17,19 @@ enum InterpolatorModel : int {
|
|||
kInterpolatorBspline3,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Interpolate from a vector of values
|
||||
*
|
||||
* @tparam M the interpolator model
|
||||
* @tparam R the sample type
|
||||
* @param values Pointer to a value in a larger vector of values.
|
||||
* Depending on the interpolator the algorithm may
|
||||
* read samples before and after. Usually you need
|
||||
* to ensure that you have order - 1 samples available
|
||||
* before and after the pointer, padding if necessary.
|
||||
* @param coeff the interpolation coefficient
|
||||
* @return R
|
||||
*/
|
||||
template <InterpolatorModel M, class R>
|
||||
R interpolate(const R* values, R coeff);
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ public:
|
|||
{
|
||||
__m128 x = _mm_sub_ps(_mm_setr_ps(-1, 0, 1, 2), _mm_set1_ps(coeff));
|
||||
__m128 h = hermite3x4(x);
|
||||
__m128 y = _mm_mul_ps(h, _mm_loadu_ps(values));
|
||||
__m128 y = _mm_mul_ps(h, _mm_loadu_ps(values - 1));
|
||||
// sum 4 to 1
|
||||
__m128 xmm0 = y;
|
||||
__m128 xmm1 = _mm_shuffle_ps(xmm0, xmm0, 0xe5);
|
||||
|
|
@ -68,8 +68,8 @@ public:
|
|||
static inline R process(const R* values, R coeff)
|
||||
{
|
||||
R y = 0;
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
R h = hermite3<R>(i - 1 - coeff);
|
||||
for (int i = -1; i < 3; ++i) {
|
||||
R h = hermite3<R>(i - coeff);
|
||||
y += h * values[i];
|
||||
}
|
||||
return y;
|
||||
|
|
@ -88,7 +88,7 @@ public:
|
|||
{
|
||||
__m128 x = _mm_sub_ps(_mm_setr_ps(-1, 0, 1, 2), _mm_set1_ps(coeff));
|
||||
__m128 h = bspline3x4(x);
|
||||
__m128 y = _mm_mul_ps(h, _mm_loadu_ps(values));
|
||||
__m128 y = _mm_mul_ps(h, _mm_loadu_ps(values - 1));
|
||||
// sum 4 to 1
|
||||
__m128 xmm0 = y;
|
||||
__m128 xmm1 = _mm_shuffle_ps(xmm0, xmm0, 0xe5);
|
||||
|
|
@ -112,8 +112,8 @@ public:
|
|||
static inline R process(const R* values, R coeff)
|
||||
{
|
||||
R y = 0;
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
R h = bspline3<R>(i - 1 - coeff);
|
||||
for (int i = -1; i < 3; ++i) {
|
||||
R h = bspline3<R>(i - coeff);
|
||||
y += h * values[i];
|
||||
}
|
||||
return y;
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ sfz::Oversampler::Oversampler(sfz::Oversampling factor, size_t chunkSize)
|
|||
|
||||
}
|
||||
|
||||
void sfz::Oversampler::stream(const sfz::AudioBuffer<float>& input, sfz::AudioBuffer<float>& output, std::atomic<size_t>* framesReady)
|
||||
void sfz::Oversampler::stream(AudioSpan<float> input, AudioSpan<float> output, std::atomic<size_t>* framesReady)
|
||||
{
|
||||
ASSERT(output.getNumFrames() >= input.getNumFrames() * static_cast<int>(factor));
|
||||
ASSERT(output.getNumChannels() == input.getNumChannels());
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#include "Debug.h"
|
||||
#include "Buffer.h"
|
||||
#include "AudioBuffer.h"
|
||||
#include "AudioSpan.h"
|
||||
#include "Config.h"
|
||||
|
||||
namespace sfz {
|
||||
|
|
@ -39,7 +40,7 @@ public:
|
|||
* @param output
|
||||
* @param framesReady an atomic counter for the ready frames. If null no signaling is done.
|
||||
*/
|
||||
void stream(const AudioBuffer<float>& input, AudioBuffer<float>& output, std::atomic<size_t>* framesReady = nullptr);
|
||||
void stream(AudioSpan<float> input, AudioSpan<float> output, std::atomic<size_t>* framesReady = nullptr);
|
||||
|
||||
Oversampler() = delete;
|
||||
Oversampler(const Oversampler&) = delete;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue