Back to block processing, more efficient and does not introduce delay

This commit is contained in:
Geoffrey Merck 2020-04-04 16:16:46 +02:00
parent 1770dc188f
commit 042188770b
9 changed files with 85 additions and 57 deletions

View File

@ -62,27 +62,33 @@ float CAGC::GetGain()
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
// process // process
inline float CAGC::ProcessSample(float input) inline void CAGC::ProcessSampleBlock(uint8* voice, int length)
{ {
//apply AGC for(int i = 0; i < length; i += 2)
// apply gain to input sample {
float output = input * m_Gain; float input = (float)(short)MAKEWORD(voice[i+1], voice[i]);
//apply AGC
// apply gain to input sample
float output = input * m_Gain;
// compute output signal energy, scaled to 0 to 1 // compute output signal energy, scaled to 0 to 1
float instantEnergy = abs(output) / m_targetEnergy; float instantEnergy = abs(output) / m_targetEnergy;
// smooth energy estimate using single-pole low-pass filter // smooth energy estimate using single-pole low-pass filter
m_EnergyPrime = (1.0f - m_Alpha) * m_EnergyPrime + m_Alpha * instantEnergy; m_EnergyPrime = (1.0f - m_Alpha) * m_EnergyPrime + m_Alpha * instantEnergy;
// update gain according to output energy // update gain according to output energy
if (m_EnergyPrime > 1e-6f) if (m_EnergyPrime > 1e-6f)
m_Gain *= exp( -0.5f * m_Alpha * log(m_EnergyPrime) ); m_Gain *= exp( -0.5f * m_Alpha * log(m_EnergyPrime) );
// clamp gain // clamp gain
if (m_Gain > m_GainMax) if (m_Gain > m_GainMax)
m_Gain = m_GainMax; m_Gain = m_GainMax;
else if(m_Gain < m_GainMin) else if(m_Gain < m_GainMin)
m_Gain = m_GainMin; m_Gain = m_GainMin;
return output; //write processed sample back
voice[i] = HIBYTE((short)output);
voice[i+1] = LOBYTE((short)output);
}
} }

View File

@ -28,16 +28,16 @@
#ifndef cagc_h #ifndef cagc_h
#define cagc_h #define cagc_h
#include "csampleprocessor.h" #include "csampleblockprocessor.h"
class CAGC : CSampleProcessor class CAGC : CSampleBlockProcessor
{ {
public: public:
//Constructor //Constructor
CAGC(float initialLeveldB); CAGC(float initialLeveldB);
//methods //methods
float ProcessSample(float input); void ProcessSampleBlock(uint8* voice, int length) ;
float GetGain();//gets current gain float GetGain();//gets current gain
private: private:

View File

@ -43,27 +43,33 @@ CFIRFilter::~CFIRFilter()
delete[] m_buffer; delete[] m_buffer;
} }
inline float CFIRFilter::ProcessSample(float inputSample) inline void CFIRFilter::ProcessSampleBlock(uint8* voice, int length)
{ {
float output = 0.0f; for(int i = 0; i < length; i++)
int iTaps = 0;
// Buffer latest sample into delay line
m_buffer[m_currentBufferPosition] = inputSample;
for(int i = m_currentBufferPosition; i >= 0; i--)
{ {
output += m_taps[iTaps++] * m_buffer[i]; float input = (float)(short)MAKEWORD(voice[i+1], voice[i]);
} float output = 0.0f;
int iTaps = 0;
for(int i = m_tapsLength - 1; i > m_currentBufferPosition; i--) // Buffer latest sample into delay line
{ m_buffer[m_currentBufferPosition] = input;
output += m_taps[iTaps++] * m_buffer[i];
}
m_currentBufferPosition = (m_currentBufferPosition + 1) % m_tapsLength;
return output; for(int i = m_currentBufferPosition; i >= 0; i--)
{
output += m_taps[iTaps++] * m_buffer[i];
}
for(int i = m_tapsLength - 1; i > m_currentBufferPosition; i--)
{
output += m_taps[iTaps++] * m_buffer[i];
}
m_currentBufferPosition = (m_currentBufferPosition + 1) % m_tapsLength;
//write processed sample back
voice[i] = HIBYTE((short)output);
voice[i+1] = LOBYTE((short)output);
}
} }

View File

@ -26,9 +26,9 @@
#ifndef cfirfilter_h #ifndef cfirfilter_h
#define cfirfilter_h #define cfirfilter_h
#include "csampleprocessor.h" #include "csampleblockprocessor.h"
class CFIRFilter : CSampleProcessor class CFIRFilter : CSampleBlockProcessor
{ {
public : public :
//Constructor //Constructor
@ -38,7 +38,7 @@ public :
~CFIRFilter(); ~CFIRFilter();
// Processing // Processing
float ProcessSample(float inputSample); void ProcessSampleBlock(uint8* voice, int length);
private: private:
float* m_taps; float* m_taps;

View File

@ -38,7 +38,16 @@ CFixedGain::CFixedGain(float gaindB)
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
// processing // processing
inline float CFixedGain::ProcessSample(float input) inline void CFixedGain::ProcessSampleBlock(uint8* voice, int length)
{ {
return input * m_gainLinear; for(int i = 0; i < length; i++)
{
float input = (float)(short)MAKEWORD(voice[i+1], voice[i]);
//apply gain
float output = input * m_gainLinear;
//write processed sample back
voice[i] = HIBYTE((short)output);
voice[i+1] = LOBYTE((short)output);
}
} }

View File

@ -26,16 +26,16 @@
#ifndef cfixedgain_h #ifndef cfixedgain_h
#define cfixedgain_h #define cfixedgain_h
#include "csampleprocessor.h" #include "csampleblockprocessor.h"
class CFixedGain : CSampleProcessor class CFixedGain : CSampleBlockProcessor
{ {
public: public:
//Constructor //Constructor
CFixedGain(float gaindB); CFixedGain(float gaindB);
//processing //processing
float ProcessSample(float input); void ProcessSampleBlock(uint8* voice, int length);
private: private:
float m_gaindB; //gain in dB float m_gaindB; //gain in dB

View File

@ -23,14 +23,16 @@
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Geoffrey Merck F4FXL / KC3FRA // Geoffrey Merck F4FXL / KC3FRA
#ifndef csampleprocessor_h #ifndef csamplebloclprocessor_h
#define csampleprocessor_h #define csamplebloclprocessor_h
class CSampleProcessor #include "main.h"
class CSampleBlockProcessor
{ {
public: public:
//processing //processing
virtual float ProcessSample(float input) = 0; virtual void ProcessSampleBlock(uint8* voice, int length) = 0;
}; };
#endif /* csampleprocessor_h */ #endif /* csampleprocessor_h */

View File

@ -43,12 +43,12 @@
CSignalProcessor::CSignalProcessor(float gaindB) CSignalProcessor::CSignalProcessor(float gaindB)
{ {
#if USE_BANDPASSFILTER #if USE_BANDPASSFILTER
m_sampleProcessors.push_back((CSampleProcessor*)new CFIRFilter(FILTER_TAPS, FILTER_TAPS_LENGTH)); m_sampleProcessors.push_back((CSampleBlockProcessor*)new CFIRFilter(FILTER_TAPS, FILTER_TAPS_LENGTH));
#endif #endif
#if USE_AGC == 1 #if USE_AGC == 1
m_sampleProcessors.push_back((CSampleProcessor*)new CAGC(gaindB)); m_sampleProcessors.push_back((CSampleProcessor*)new CAGC(gaindB));
#else #else
m_sampleProcessors.push_back((CSampleProcessor*)new CFixedGain(gaindB)); m_sampleProcessors.push_back((CSampleBlockProcessor*)new CFixedGain(gaindB));
#endif #endif
} }
@ -68,11 +68,16 @@ CSignalProcessor::~CSignalProcessor()
void CSignalProcessor::Process(uint8* voice, int length) void CSignalProcessor::Process(uint8* voice, int length)
{ {
float sample; /*float sample;
int j; int j;*/
auto processorsSize = m_sampleProcessors.size(); auto processorsSize = m_sampleProcessors.size();
for(int i = 0; i < length; i += 2) for(int j = 0; j < processorsSize; j++)
{
m_sampleProcessors[j]->ProcessSampleBlock(voice, length);
}
/*for(int i = 0; i < length; i += 2)
{ {
//Get the sample //Get the sample
sample = (float)(short)MAKEWORD(voice[i+1], voice[i]); sample = (float)(short)MAKEWORD(voice[i+1], voice[i]);
@ -85,5 +90,5 @@ void CSignalProcessor::Process(uint8* voice, int length)
//write processed sample back //write processed sample back
voice[i] = HIBYTE((short)sample); voice[i] = HIBYTE((short)sample);
voice[i+1] = LOBYTE((short)sample); voice[i+1] = LOBYTE((short)sample);
} }*/
} }

View File

@ -27,7 +27,7 @@
#define csignalprocessor_h #define csignalprocessor_h
#include <vector> #include <vector>
#include "csampleprocessor.h" #include "csampleblockprocessor.h"
class CSignalProcessor class CSignalProcessor
{ {
@ -42,7 +42,7 @@ public:
void Process(uint8* voice, int length); void Process(uint8* voice, int length);
private: private:
std::vector<CSampleProcessor *> m_sampleProcessors; std::vector<CSampleBlockProcessor *> m_sampleProcessors;
}; };
#endif /* csignalprocessor_h */ #endif /* csignalprocessor_h */