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

audioProcessor.cpp (2501B)


      1 #include "audioProcessor.h"
      2 
      3 #include <vector>
      4 
      5 #include "esaiListenerToFile.h"
      6 #include "dsp56kEmu/types.h"
      7 
      8 #include "synthLib/wavWriter.h"
      9 
     10 #include "virusLib/dspSingle.h"
     11 
     12 AudioProcessor::AudioProcessor(uint32_t _samplerate, std::string _outputFilename, bool _terminateOnSilence, uint32_t _maxSamplecount, virusLib::DspSingle* _dsp1, virusLib::DspSingle* _dsp2)
     13 : m_samplerate(_samplerate)
     14 , m_outputFilname(std::move(_outputFilename))
     15 , m_terminateOnSilence(_terminateOnSilence)
     16 , m_maxSampleCount(_maxSamplecount)
     17 , m_dsp1(_dsp1)
     18 , m_dsp2(_dsp2)
     19 , m_writer(m_outputFilname, _samplerate, _terminateOnSilence)
     20 {
     21 	m_outputBuffers.resize(2);
     22 	m_inputBuffers.resize(2);
     23 }
     24 
     25 AudioProcessor::~AudioProcessor() = default;
     26 
     27 void AudioProcessor::processBlock(const uint32_t _blockSize)
     28 {
     29 	if(m_outputBuffers[0].size() < _blockSize)
     30 	{
     31 		for(size_t i=0; i<m_outputBuffers.size(); ++i)
     32 		{
     33 			m_outputBuffers[i].resize(_blockSize);
     34 			m_inputBuffers[i].resize(_blockSize);
     35 
     36 			m_inputs[i] = m_inputBuffers[i].data();
     37 			m_outputs[i] = m_outputBuffers[i].data();
     38 		}
     39 
     40 		m_stereoOutput.reserve(m_outputBuffers.size() * 2);
     41 	}
     42 
     43 	const bool terminateOnSilence = m_terminateOnSilence;
     44 
     45 	auto sampleCount = static_cast<uint32_t>(m_inputBuffers[0].size());
     46 
     47 	if(terminateOnSilence && m_writer.getSilenceDuration() >= m_samplerate * 5)
     48 	{
     49 		m_writer.setFinished();
     50 		return;
     51 	}
     52 
     53 	if(m_maxSampleCount && m_processedSampleCount >= m_maxSampleCount)
     54 	{
     55 		m_writer.setFinished();
     56 		return;
     57 	}
     58 
     59 	if(m_maxSampleCount && m_maxSampleCount - m_processedSampleCount < sampleCount)
     60 	{
     61 		sampleCount = m_maxSampleCount - m_processedSampleCount;
     62 	}
     63 
     64 	// reduce thread contention by waiting for the DSP to do some work first.
     65 	// If we don't, the ESAI writeTX function will lock/unlock a mutex to inform the waiting thread (us)
     66 	// that there is new audio data available. This costs more than 5% of performance
     67 /*	const auto& esai = m_dsp1->getPeriphX().getEsai();
     68 
     69 	while(esai.getAudioInputs().size() > (_blockSize>>1))
     70 		std::this_thread::yield();
     71 */
     72 	m_dsp1->processAudio(m_inputs, m_outputs, sampleCount, _blockSize);
     73 
     74 	m_processedSampleCount += sampleCount;
     75 
     76 	{
     77 		m_writer.append([&](std::vector<dsp56k::TWord>& _dst)
     78 		{
     79 			_dst.reserve(m_stereoOutput.size() + sampleCount * 2);
     80 
     81 			for(size_t iSrc=0; iSrc<sampleCount; ++iSrc)
     82 			{
     83 				_dst.push_back(m_outputs[0][iSrc]);
     84 				_dst.push_back(m_outputs[1][iSrc]);
     85 			}
     86 		});
     87 	}
     88 
     89 	if(m_maxSampleCount && m_processedSampleCount >= m_maxSampleCount)
     90 		m_writer.setFinished();
     91 }