gearmulator

Emulation of classic VA synths of the late 90s/2000s that are based on Motorola 56300 family DSPs
Log | Files | Refs | Submodules | README | LICENSE

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 }