In the meantime,
for my personal experiments,
i can implement my code as if it was 96000 sample rate and port/use the /2 downsampler i have already coded for the Axoloti (O2_to_SR_59 59 tap 1/2 downsampler) .
I found some time to experiment and implement the 59 tap decimator.
Here are the results for a sine sweeping from 9KHz to 48KHz.
- without Dec59 connected to the PC
- aliasing (freq folding) when the sine goes above 48KHz
- background noise caused by the PC
- with Dec59 still connected to the PC
- the aliasing is mostly suppressed
- the background noise is still there
- with Dec59 and powerbank powered
The remaining artefacts are sidelobes infered by the pitch sweep and maybe some artefacts related to the EIEpro.
Dec59.h
#ifndef TIAR_DEC59_H
#define TIAR_DEC59_H
namespace tiar
{
/** /2 decimator */
class Dec59
{
public:
Dec59() {}
~Dec59() {}
void init();
float proc(float x1,float x0);
private:
float R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15,
R16, R17, R18, R19, R20, R21, R22, R23, R24, R25, R26, R27, R28, R29, R30;
};
} // namespace tiar
#endif
Dec59.cpp
#include "dec59.h"
using namespace tiar;
void Dec59::init(){
R1=R2=R3=R4=R5=R6=R7=R8=R9=R10=R11=R12=R13=R14=R15=
R16=R17=R18=R19=R20=R21=R22=R23=R24=R25=R26=R27=R28=R29=R30=0;
}
float Dec59::proc(float x1, float x0){
float h1x1 = x1*0.3167967114236291f; float h3x1 = x1*-0.10164126581474016f;
float h5x1 = x1*0.056472878314649574f; float h7x1 = x1*-0.03590356425550024f;
float h9x1 = x1*0.023854182328325296f; float h11x1 = x1*-0.015966909428751137f;
float h13x1 = x1*0.010553528578562761f; float h15x1 = x1*-0.006794829937625732f;
float h17x1 = x1*0.004212042043030732f; float h19x1 = x1*-0.002484841082005066f;
float h21x1 = x1*0.0013753503068182293f; float h23x1 = x1*-0.0007008749315804081f;
float h25x1 = x1*0.00031898286827647583f; float h27x1 = x1*-0.00012279053509672562f;
float h29x1 = x1*0.000035881628440564505f;
R30 = R29 + h29x1; R29 = R28 + h27x1;
R28 = R27 + h25x1; R27 = R26 + h23x1; R26 = R25 + h21x1;
R25 = R24 + h19x1; R24 = R23 + h17x1; R23 = R22 + h15x1;
R22 = R21 + h13x1; R21 = R20 + h11x1; R20 = R19 + h9x1;
R19 = R18 + h7x1; R18 = R17 + h5x1; R17 = R16 + h3x1;
R16 = R15 + h1x1;
R15 = R14 + h1x1 + 0.50000063464071f * x0;
R14 = R13 + h3x1; R13 = R12 + h5x1; R12 = R11 + h7x1;
R11 = R10 + h9x1; R10 = R9 + h11x1; R9 = R8 + h13x1;
R8 = R7 + h15x1; R7 = R6 + h17x1; R6 = R5 + h19x1;
R5 = R4 + h21x1; R4 = R3 + h23x1; R3 = R2 + h25x1;
R2 = R1 + h27x1; R1 = h29x1;
return R30;
}
test.ino
#include <Dec59.h>
#include "DaisyDuino.h"
using namespace tiar;
Dec59 dec;
DaisyHardware hw;
size_t num_channels;
Oscillator osc;
float f=440.0f;
void MyCallback(float **in, float **out, size_t size){
// frequency sweep to test aliasing
f *= 1.0005f;
if(f > 48000.0f) f=440.0f;
osc.SetFreq(f);
for (size_t i = 0; i < size; i++) {
out[0][i] = out[1][i] = dec.proc(osc.Process(), osc.Process());
// osc.Process();
// out[0][i] = out[1][i] = osc.Process();
}
}
void setup() {
Serial.begin(); // no rate needed since this isn't really a UART
float sample_rate;
// DOES NOT ACTUALLY SET THE HARDWARE TO 96K
// BUT MODULES BELIEVE SO... and the Dec59
// makes it right.
hw = DAISY.init(DAISY_SEED, AUDIO_SR_96K);
num_channels = hw.num_channels;
sample_rate = DAISY.get_samplerate();
// Initialize Oscillator, and set parameters.
osc.Init(sample_rate);
osc.SetWaveform(osc.WAVE_SIN);
osc.SetAmp(0.5f);
dec.init();
DAISY.begin(MyCallback);
}
void loop() {
delay(1000);
}