Sfoglia il codice sorgente

added the maximum filter length to the parameters

dds
awalch6679 4 anni fa
parent
commit
7e7cb4dbb8
5 ha cambiato i file con 37 aggiunte e 44 eliminazioni
  1. +19
    -31
      Resampler.cpp
  2. +5
    -2
      Resampler.h
  3. +5
    -4
      async_input_spdif3.cpp
  4. +4
    -5
      async_input_spdif3.h
  5. +4
    -2
      examples/HardwareTesting/PassThroughAsyncSpdif/PassThroughAsyncSpdif.ino

+ 19
- 31
Resampler.cpp Vedi File

#include "Resampler.h" #include "Resampler.h"
#include <math.h> #include <math.h>


Resampler::Resampler(StepAdaptionParameters settings){
Resampler::Resampler(float attenuation, int32_t minHalfFilterLength, int32_t maxHalfFilterLength, StepAdaptionParameters settings): _targetAttenuation(attenuation)
{
_maxHalfFilterLength=max(1, min(MAX_HALF_FILTER_LENGTH, maxHalfFilterLength));
_minHalfFilterLength=max(1, min(maxHalfFilterLength, minHalfFilterLength));
#ifdef DEBUG_RESAMPLER #ifdef DEBUG_RESAMPLER
while (!Serial); while (!Serial);
#endif #endif
void Resampler::reset(){ void Resampler::reset(){
_initialized=false; _initialized=false;
} }
void Resampler::configure(float fs, float newFs, float attenuation, int32_t minHalfFilterLength){
void Resampler::configure(float fs, float newFs){
// Serial.print("configure, fs: "); // Serial.print("configure, fs: ");
// Serial.println(fs); // Serial.println(fs);
if (fs<=0. || newFs <=0.){ if (fs<=0. || newFs <=0.){
_initialized=false; _initialized=false;
return; return;
} }
_attenuation=_targetAttenuation;
_step=(double)fs/newFs; _step=(double)fs/newFs;
_configuredStep=_step; _configuredStep=_step;
_stepAdapted=_step; _stepAdapted=_step;
_oldDiffs[0]=0.; _oldDiffs[0]=0.;
_oldDiffs[1]=0.; _oldDiffs[1]=0.;
for (uint8_t i =0; i< MAX_NO_CHANNELS; i++){ for (uint8_t i =0; i< MAX_NO_CHANNELS; i++){
memset(_buffer[i], 0, sizeof(float)*MAX_HALF_FILTER_LENGTH*2);
memset(_buffer[i], 0, sizeof(float)*_maxHalfFilterLength*2);
} }


float cutOffFrequ, kaiserBeta; float cutOffFrequ, kaiserBeta;
_attenuation=0; _attenuation=0;
cutOffFrequ=1.; cutOffFrequ=1.;
kaiserBeta=10; kaiserBeta=10;
_halfFilterLength=min(minHalfFilterLength,MAX_HALF_FILTER_LENGTH);
_halfFilterLength=min(_minHalfFilterLength,_maxHalfFilterLength);
} }
else{ else{
cutOffFrequ=newFs/fs; cutOffFrequ=newFs/fs;
Serial.print("b: "); Serial.print("b: ");
Serial.println(b); Serial.println(b);
#endif #endif
double hfl=(int32_t)((attenuation-8)/(2.*2.285*TWO_PI*b)+0.5);
if (hfl >= minHalfFilterLength && hfl <= MAX_HALF_FILTER_LENGTH){
double hfl=(int32_t)((_attenuation-8)/(2.*2.285*TWO_PI*b)+0.5);
if (hfl >= _minHalfFilterLength && hfl <= _maxHalfFilterLength){
_halfFilterLength=hfl; _halfFilterLength=hfl;
#ifdef DEBUG_RESAMPLER
Serial.print("Attenuation: ");
#endif
} }
else if (hfl < minHalfFilterLength){
_halfFilterLength=minHalfFilterLength;
attenuation=((2*_halfFilterLength+1)-1)*(2.285*TWO_PI*b)+8;
#ifdef DEBUG_RESAMPLER
Serial.println("Resmapler: sinc filter length increased");
Serial.print("Attenuation increased to ");
#endif
else if (hfl < _minHalfFilterLength){
_halfFilterLength=_minHalfFilterLength;
_attenuation=((2*_halfFilterLength+1)-1)*(2.285*TWO_PI*b)+8;
} }
else{ else{
_halfFilterLength=MAX_HALF_FILTER_LENGTH;
attenuation=((2*_halfFilterLength+1)-1)*(2.285*TWO_PI*b)+8;
#ifdef DEBUG_RESAMPLER
Serial.println("Resmapler: needed sinc filter length too long");
Serial.print("Attenuation decreased to ");
#endif
_halfFilterLength=_maxHalfFilterLength;
_attenuation=((2*_halfFilterLength+1)-1)*(2.285*TWO_PI*b)+8;
} }
#ifdef DEBUG_RESAMPLER
Serial.print(attenuation);
Serial.println("dB");
#endif
if (attenuation>50.){
kaiserBeta=0.1102*(attenuation-8.7);
if (_attenuation>50.){
kaiserBeta=0.1102*(_attenuation-8.7);
} }
else if (21<=attenuation && attenuation<=50){
kaiserBeta=0.5842*(float)pow(attenuation-21.,0.4)+0.07886*(attenuation-21.);
else if (21<=_attenuation && _attenuation<=50){
kaiserBeta=0.5842*(float)pow(_attenuation-21.,0.4)+0.07886*(_attenuation-21.);
} }
else{ else{
kaiserBeta=0.; kaiserBeta=0.;
int32_t f = (noSamples-1)/(MAX_FILTER_SAMPLES-1)+1; int32_t f = (noSamples-1)/(MAX_FILTER_SAMPLES-1)+1;
_overSamplingFactor/=f; _overSamplingFactor/=f;
} }
_attenuation=attenuation;
} }


#ifdef DEBUG_RESAMPLER #ifdef DEBUG_RESAMPLER

+ 5
- 2
Resampler.h Vedi File

double ki=0.00012; double ki=0.00012;
double kd= 1.8; double kd= 1.8;
}; };
Resampler(StepAdaptionParameters settings=StepAdaptionParameters());
Resampler(float attenuation=100, int32_t minHalfFilterLength=20, int32_t maxHalfFilterLength=80, StepAdaptionParameters settings=StepAdaptionParameters());
void reset(); void reset();
///@param attenuation target attenuation [dB] of the anti-aliasing filter. Only used if newFs<fs. The attenuation can't be reached if the needed filter length exceeds 2*MAX_FILTER_SAMPLES+1 ///@param attenuation target attenuation [dB] of the anti-aliasing filter. Only used if newFs<fs. The attenuation can't be reached if the needed filter length exceeds 2*MAX_FILTER_SAMPLES+1
///@param minHalfFilterLength If newFs >= fs, the filter length of the resampling filter is 2*minHalfFilterLength+1. If fs y newFs the filter is maybe longer to reach the desired attenuation ///@param minHalfFilterLength If newFs >= fs, the filter length of the resampling filter is 2*minHalfFilterLength+1. If fs y newFs the filter is maybe longer to reach the desired attenuation
void configure(float fs, float newFs, float attenuation=100, int32_t minHalfFilterLength=20);
void configure(float fs, float newFs);
///@param input0 first input array/ channel ///@param input0 first input array/ channel
///@param input1 second input array/ channel ///@param input1 second input array/ channel
///@param inputLength length of each input array ///@param inputLength length of each input array
float _buffer[MAX_NO_CHANNELS][MAX_HALF_FILTER_LENGTH*2]; float _buffer[MAX_NO_CHANNELS][MAX_HALF_FILTER_LENGTH*2];
float* _endOfBuffer[MAX_NO_CHANNELS]; float* _endOfBuffer[MAX_NO_CHANNELS];


int32_t _minHalfFilterLength;
int32_t _maxHalfFilterLength;
int32_t _overSamplingFactor; int32_t _overSamplingFactor;
int32_t _halfFilterLength; int32_t _halfFilterLength;
int32_t _filterLength; int32_t _filterLength;
double _oldDiffs[2]; double _oldDiffs[2];
double _attenuation=0; double _attenuation=0;
float _targetAttenuation=100;
}; };


#endif #endif

+ 5
- 4
async_input_spdif3.cpp Vedi File

} }


PROGMEM PROGMEM
AsyncAudioInputSPDIF3::AsyncAudioInputSPDIF3(bool dither, bool noiseshaping,float attenuation, int32_t minHalfFilterLength) : AudioStream(0, NULL) {
_attenuation=attenuation;
_minHalfFilterLength=minHalfFilterLength;
AsyncAudioInputSPDIF3::AsyncAudioInputSPDIF3(bool dither, bool noiseshaping,float attenuation, int32_t minHalfFilterLength, int32_t maxHalfFilterLength):
AudioStream(0, NULL),
_resampler(attenuation, minHalfFilterLength, maxHalfFilterLength)
{
const float factor = powf(2, 15)-1.f; // to 16 bit audio const float factor = powf(2, 15)-1.f; // to 16 bit audio
quantizer[0]=new Quantizer(AUDIO_SAMPLE_RATE_EXACT); quantizer[0]=new Quantizer(AUDIO_SAMPLE_RATE_EXACT);
quantizer[0]->configure(noiseshaping, dither, factor); quantizer[0]->configure(noiseshaping, dither, factor);
__disable_irq(); __disable_irq();
resample_offset = targetLatency <= buffer_offset ? buffer_offset - targetLatency : bufferLength -(targetLatency-buffer_offset); resample_offset = targetLatency <= buffer_offset ? buffer_offset - targetLatency : bufferLength -(targetLatency-buffer_offset);
__enable_irq(); __enable_irq();
_resampler.configure(inputF, AUDIO_SAMPLE_RATE_EXACT, _attenuation, _minHalfFilterLength);
_resampler.configure(inputF, AUDIO_SAMPLE_RATE_EXACT);
#ifdef DEBUG_SPDIF_IN #ifdef DEBUG_SPDIF_IN
Serial.print("_maxLatency: "); Serial.print("_maxLatency: ");
Serial.println(_maxLatency); Serial.println(_maxLatency);

+ 4
- 5
async_input_spdif3.h Vedi File

class AsyncAudioInputSPDIF3 : public AudioStream class AsyncAudioInputSPDIF3 : public AudioStream
{ {
public: public:
///@param attenuation target attenuation [dB] of the anti-aliasing filter. Only used if newFs<fs. The attenuation can't be reached if the needed filter length exceeds 2*MAX_FILTER_SAMPLES+1
///@param minHalfFilterLength If newFs >= fs, the filter length of the resampling filter is 2*minHalfFilterLength+1. If fs y newFs the filter is maybe longer to reach the desired attenuation
AsyncAudioInputSPDIF3(bool dither=true, bool noiseshaping=true,float attenuation=100, int32_t minHalfFilterLength=20);
///@param attenuation target attenuation [dB] of the anti-aliasing filter. Only used if AUDIO_SAMPLE_RATE_EXACT < input sample rate (input fs). The attenuation can't be reached if the needed filter length exceeds 2*MAX_FILTER_SAMPLES+1
///@param minHalfFilterLength If AUDIO_SAMPLE_RATE_EXACT >= input fs), the filter length of the resampling filter is 2*minHalfFilterLength+1. If AUDIO_SAMPLE_RATE_EXACT < input fs the filter is maybe longer to reach the desired attenuation
///@param maxHalfFilterLength Can be used to restrict the maximum filter length at the cost of a lower attenuation
AsyncAudioInputSPDIF3(bool dither=true, bool noiseshaping=true,float attenuation=100, int32_t minHalfFilterLength=20, int32_t maxHalfFilterLength=80);
~AsyncAudioInputSPDIF3(); ~AsyncAudioInputSPDIF3();
virtual void update(void); virtual void update(void);
void begin(); void begin();
static volatile uint32_t microsLast; static volatile uint32_t microsLast;
//==================== //====================


float _attenuation;
int32_t _minHalfFilterLength;
Resampler _resampler; Resampler _resampler;
Quantizer* quantizer[2]; Quantizer* quantizer[2];
arm_biquad_cascade_df2T_instance_f32 _bufferLPFilter; arm_biquad_cascade_df2T_instance_f32 _bufferLPFilter;

+ 4
- 2
examples/HardwareTesting/PassThroughAsyncSpdif/PassThroughAsyncSpdif.ino Vedi File



#include <Audio.h> #include <Audio.h>


AsyncAudioInputSPDIF3 spdifIn(false, false, 100, 20); //dither = false, noiseshaping = false, anti-aliasing attenuation=100dB, minimum resampling filter length=20
AsyncAudioInputSPDIF3 spdifIn(false, false, 100, 20, 80); //dither = true, noiseshaping = true, anti-aliasing attenuation=100dB, minimum half resampling filter length=20, maximum half resampling filter length=80
AudioOutputSPDIF3 spdifOut; AudioOutputSPDIF3 spdifOut;


AudioConnection patchCord1(spdifIn, 0, spdifOut, 0); AudioConnection patchCord1(spdifIn, 0, spdifOut, 0);
Serial.print("resampling goup delay [milli seconds]: "); Serial.print("resampling goup delay [milli seconds]: ");
Serial.println(spdifIn.getHalfFilterLength()/inputFrequency*1e3,2); Serial.println(spdifIn.getHalfFilterLength()/inputFrequency*1e3,2);
Serial.print("half filter length: ");
Serial.println(spdifIn.getHalfFilterLength());
double pUsageIn=spdifIn.processorUsage(); double pUsageIn=spdifIn.processorUsage();
Serial.print("processor usage [%]: "); Serial.print("processor usage [%]: ");

Loading…
Annulla
Salva