I got Ron's PhaseChange() to work on the Teensy 4 to remove images using OpenAudio_Library 32bit floating point objects.
Had to make some changes.
1. Change the int16_t arrays to float32_t
2. Change the 32767 to 1.0f
Plugged in the begin() functions after the sgtl5000.enable().
ex: PhaseQ.begin(PhaseIfir, 2);
I assigned PhaseChanges(1) to a button to cycle through the 3 combos.
Code follows with some usage comments added
__________________________________________________ ______________________________________________
HTML Code:
// Manual I2S codec Phase Correction Utility by Ron Carr
// Reference: [URL]https://forum.pjrc.com/threads/57362-AudioSDR-A-single-Audio-block-SDR-(software-defined-radio)-processor-demodulator?p=263048&viewfull=1#post263048[/URL]
// Updated for Teensy 4.0/1 using the OpenAudio_Library (F32) by K7MDL on 24 Feb 2022
//
// Usage: Paste in the code below as-is in the appropriate sections.
// There is nothing to configure.
// Normally you would attach the function PhaseChange(1) to a user control.
// When you see a mirror image at startup, operate the control to try each of
// the 3 combos until you see the mirror image go away.
//
//.............................
// Phase correction FIRs. Apparently sometimes the I2s audio samples are 1 step out of phase
// and waterfall shows very little opposite sideband suppression
//
float32_t PhaseIfir[2] = { 1.0f, 0 }; // swap constants to change phasing
float32_t PhaseQfir[2] = { 1.0f, 0 };
//.............................
// Your pgrogam should already have these lines
float sample_rate_Hz = 48000.0f; // set to your preference
const int audio_block_samples = 128; // do not change this!
AudioSettings_F32 audio_settings(sample_rate_Hz, audio_block_samples);
// Add the below code in the approriate places
AudioFilterFIR_F32 PhaseI(audio_settings);
AudioFilterFIR_F32 PhaseQ(audio_settings);
// Attach PhaseI and PhaseQ to the i2s inputs. Here is an example.
AudioConnection_F32 patchCord_RX_In_L(Input,0, PhaseI,0); // route raw input audio to the FFT display
AudioConnection_F32 patchCord_RX_In_R(Input,1, PhaseQ,0);
AudioConnection_F32 patchCord_RX_Ph_L(PhaseI,0, I_Switch,0); // route raw input audio to the FFT display
AudioConnection_F32 patchCord_RX_Ph_R(PhaseQ,0, Q_Switch,0);
// ------------------- PhaseChange() -------------------------------------
// I2S audio sometimes starts with I and Q out of order
// --------------------------------- -------------------------------------
void PhaseChange(uint8_t chg)
{
static int val;
if( chg ){
if( ++val > 2 ) val = 0; // rotate through the settings
}
// print
Serial.print("Ph: ");
switch( val ){
case 0:
PhaseIfir[0] = 1.0f; PhaseIfir[1] = 0; // normal in phase
PhaseQfir[0] = 1.0f; PhaseQfir[1] = 0;
Serial.println("1010");
break;
case 1:
PhaseIfir[0] = 1.0f; PhaseIfir[1] = 0;
PhaseQfir[0] = 0; PhaseQfir[1] = 1.0f; // delay Q ( delay I if fir runs backward )
Serial.println("1001");
break;
case 2:
PhaseIfir[0] = 0; PhaseIfir[1] = 1.0f; // delay I
PhaseQfir[0] = 1.0f; PhaseQfir[1] = 0;
Serial.println("0110");
break;
}
}
setup()
{
PhaseI.begin(PhaseIfir, 2);
PhaseQ.begin(PhaseQfir, 2);
}
loop()
{
. . .
// Call this from a UI control to manually try al l3 combos.
// A value of 1 will cause the function increment the count internally to the function
PhaseChange(1); // deal with "twin-peaks problem" - 3 combos, call this until the problem goes away
. . .
}