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
inline float CAGC::ProcessSample(float input)
inline void CAGC::ProcessSampleBlock(uint8* voice, int length)
{
//apply AGC
// apply gain to input sample
float output = input * m_Gain;
for(int i = 0; i < length; i += 2)
{
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
float instantEnergy = abs(output) / m_targetEnergy;
// compute output signal energy, scaled to 0 to 1
float instantEnergy = abs(output) / m_targetEnergy;
// smooth energy estimate using single-pole low-pass filter
m_EnergyPrime = (1.0f - m_Alpha) * m_EnergyPrime + m_Alpha * instantEnergy;
// smooth energy estimate using single-pole low-pass filter
m_EnergyPrime = (1.0f - m_Alpha) * m_EnergyPrime + m_Alpha * instantEnergy;
// update gain according to output energy
if (m_EnergyPrime > 1e-6f)
m_Gain *= exp( -0.5f * m_Alpha * log(m_EnergyPrime) );
// update gain according to output energy
if (m_EnergyPrime > 1e-6f)
m_Gain *= exp( -0.5f * m_Alpha * log(m_EnergyPrime) );
// clamp gain
if (m_Gain > m_GainMax)
m_Gain = m_GainMax;
else if(m_Gain < m_GainMin)
m_Gain = m_GainMin;
// clamp gain
if (m_Gain > m_GainMax)
m_Gain = m_GainMax;
else if(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
#define cagc_h
#include "csampleprocessor.h"
#include "csampleblockprocessor.h"
class CAGC : CSampleProcessor
class CAGC : CSampleBlockProcessor
{
public:
//Constructor
CAGC(float initialLeveldB);
//methods
float ProcessSample(float input);
void ProcessSampleBlock(uint8* voice, int length) ;
float GetGain();//gets current gain
private:

View File

@ -43,27 +43,33 @@ CFIRFilter::~CFIRFilter()
delete[] m_buffer;
}
inline float CFIRFilter::ProcessSample(float inputSample)
inline void CFIRFilter::ProcessSampleBlock(uint8* voice, int length)
{
float output = 0.0f;
int iTaps = 0;
// Buffer latest sample into delay line
m_buffer[m_currentBufferPosition] = inputSample;
for(int i = m_currentBufferPosition; i >= 0; i--)
for(int i = 0; i < length; 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--)
{
output += m_taps[iTaps++] * m_buffer[i];
}
m_currentBufferPosition = (m_currentBufferPosition + 1) % m_tapsLength;
// Buffer latest sample into delay line
m_buffer[m_currentBufferPosition] = input;
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
#define cfirfilter_h
#include "csampleprocessor.h"
#include "csampleblockprocessor.h"
class CFIRFilter : CSampleProcessor
class CFIRFilter : CSampleBlockProcessor
{
public :
//Constructor
@ -38,7 +38,7 @@ public :
~CFIRFilter();
// Processing
float ProcessSample(float inputSample);
void ProcessSampleBlock(uint8* voice, int length);
private:
float* m_taps;

View File

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

View File

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

View File

@ -43,12 +43,12 @@
CSignalProcessor::CSignalProcessor(float gaindB)
{
#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
#if USE_AGC == 1
m_sampleProcessors.push_back((CSampleProcessor*)new CAGC(gaindB));
#else
m_sampleProcessors.push_back((CSampleProcessor*)new CFixedGain(gaindB));
m_sampleProcessors.push_back((CSampleBlockProcessor*)new CFixedGain(gaindB));
#endif
}
@ -68,11 +68,16 @@ CSignalProcessor::~CSignalProcessor()
void CSignalProcessor::Process(uint8* voice, int length)
{
float sample;
int j;
/*float sample;
int j;*/
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
sample = (float)(short)MAKEWORD(voice[i+1], voice[i]);
@ -85,5 +90,5 @@ void CSignalProcessor::Process(uint8* voice, int length)
//write processed sample back
voice[i] = HIBYTE((short)sample);
voice[i+1] = LOBYTE((short)sample);
}
}*/
}

View File

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