resampler.cpp (3472B)
1 #include "resampler.h" 2 3 #include <algorithm> 4 #include <cassert> 5 #include <utility> 6 7 #include "libresample/include/libresample.h" 8 9 #include "dsp56kEmu/fastmath.h" 10 11 synthLib::Resampler::Resampler(const float _samplerateIn, const float _samplerateOut) 12 : m_samplerateIn(_samplerateIn) 13 , m_samplerateOut(_samplerateOut) 14 , m_factorInToOut(_samplerateIn / _samplerateOut) 15 , m_factorOutToIn(_samplerateOut / _samplerateIn) 16 , m_outputPtrs({}) 17 { 18 } 19 20 synthLib::Resampler::~Resampler() 21 { 22 destroyResamplers(); 23 } 24 25 uint32_t synthLib::Resampler::process(TAudioOutputs& _output, const uint32_t _numChannels, const uint32_t _numSamples, bool _allowLessOutput, const TProcessFunc& _processFunc) 26 { 27 assert(_numChannels <= m_outputPtrs.size()); 28 29 setChannelCount(_numChannels); 30 31 if (getSamplerateIn() == getSamplerateOut()) 32 { 33 _processFunc(_output, _numSamples); 34 return _numSamples; 35 } 36 37 uint32_t index = 0; 38 uint32_t remaining = _numSamples; 39 40 while (remaining > 0) 41 { 42 for (uint32_t i = 0; i < _numChannels; ++i) 43 m_outputPtrs[i] = &_output[i][index]; 44 45 const uint32_t outBufferUsed = processResample(m_outputPtrs, _numChannels, remaining, _processFunc); 46 47 index += outBufferUsed; 48 remaining -= outBufferUsed; 49 50 if(_allowLessOutput) 51 break; 52 // if (remaining > 0) 53 // LOG("outBufferUsed " << outBufferUsed << " outLen " << _numSamples); 54 } 55 56 return index; 57 } 58 59 uint32_t synthLib::Resampler::processResample(const TAudioOutputs& _output, const uint32_t _numChannels, const uint32_t _numSamples, const TProcessFunc& _processFunc) 60 { 61 // we need to preserve a constant, properly rounded, input length so accumulate the total number of samples we need and subtract the amount we use in this frame 62 m_inputLen += static_cast<double>(_numSamples) * m_factorInToOut; 63 const uint32_t inputLen = std::max(1, dsp56k::round_int(m_inputLen)); 64 m_inputLen -= inputLen; 65 66 const auto availableInputLen = static_cast<uint32_t>(m_tempOutput[0].size()); 67 68 if (availableInputLen < inputLen) 69 { 70 TAudioOutputs tempBuffers; 71 tempBuffers.fill(nullptr); 72 73 for (uint32_t i = 0; i < _numChannels; ++i) 74 { 75 m_tempOutput[i].resize(inputLen, 0.0f); 76 tempBuffers[i] = &m_tempOutput[i][availableInputLen]; 77 } 78 79 _processFunc(tempBuffers, inputLen - availableInputLen); 80 } 81 82 uint32_t outBufferUsed = 0; 83 int inBufferUsed = 0; 84 85 for (uint32_t i = 0; i < _numChannels; ++i) 86 { 87 float* output = _output[i]; 88 89 outBufferUsed = resample_process(m_resamplerOut[i], m_factorOutToIn, &m_tempOutput[i][0], static_cast<int>(inputLen), 0, &inBufferUsed, output, static_cast<int>(_numSamples)); 90 91 if (static_cast<uint32_t>(inBufferUsed) < inputLen) 92 { 93 // LOG("inBufferUsed " << inBufferUsed << " inputLen " << inputLen); 94 const auto remaining = inputLen - inBufferUsed; 95 96 m_tempOutput[i].erase(m_tempOutput[i].begin() + remaining, m_tempOutput[i].end()); 97 } 98 else 99 { 100 m_tempOutput[i].clear(); 101 } 102 } 103 104 return outBufferUsed; 105 } 106 107 void synthLib::Resampler::destroyResamplers() 108 { 109 for (const auto& resampler : m_resamplerOut) 110 resample_close(resampler); 111 m_resamplerOut.clear(); 112 } 113 114 void synthLib::Resampler::setChannelCount(uint32_t _numChannels) 115 { 116 if (m_tempOutput.size() == _numChannels) 117 return; 118 119 destroyResamplers(); 120 121 m_resamplerOut.resize(_numChannels); 122 m_tempOutput.resize(_numChannels); 123 124 for (auto& buf : m_tempOutput) 125 buf.clear(); 126 127 const auto factor = static_cast<double>(m_factorOutToIn); 128 129 for (auto& resampler : m_resamplerOut) 130 resampler = resample_open(1, factor, factor); 131 }