# Why is my frequency being effectively doubled?

I'll try to explain everything with detail as this is one will be a hard one to explain.

Essentially what I am trying to achieve is sum both the left & right channel to produce a mono signal to be outputted via I2S as the subwoofer line.

The problem I am having right now is that after summing the samples and sending it back to the peripheral I am observing at least double the frequency compare to the input and I have no idea why. Also at lower frequencies the signal looks chopped (see pictures)

What I have done for you is:

• Ensured the I2S Clock is running correctly
• Without summing just sending 1:1 samples and it's a mirror image of the input

The I2S3 DMA is setup as follow:

• Length = 2048 (Tx_BUFF)

The I2S1 DMA is setup as follow:

• Length = 4096 (Rx_BUFF)
• Length - 4096 (Tx_BUFF)

Code: I2S_HALFCOMPLETE_CALLBACK()

void I2S_HALFCOMPLETE_CALLBACK() {

int * I2S3_TxBUFF = getI2S3_TxBUFF();
int INSAMPLE_I2S_MONO;

for (int i = 0; i < 2048; i++) {

if ((i % 2) == 0){ // L Samples

INSAMPLE_I2S_MONO[i >> 1] = I2S1_RxBUFF[i];

} else if ((i % 2) == 1){ // R Samples

if (inputSourceMode == INPUT_INLINE) {

INSAMPLE_I2S_MONO[(i - 1) >> 1] += I2S1_RxBUFF[i];
INSAMPLE_I2S_MONO[(i - 1) >> 1]  =  INSAMPLE_I2S_MONO[(i - 1) >> 1] >> 1;
}
}
}

for (int i = 0; i < 2048; i++) {

if ((i % 2) == 0) { // L Samples

}   else if ((i % 2) == 1) { // R Samples

}

if (i < 1024) {
I2S3_TxBUFF[i] =  INSAMPLE_I2S_MONO[i];
}

}

}


CODE: I2S_TRANSFERCOMPLETE_CALLBACK()

void I2S_TRANSFERCOMPLETE_CALLBACK() {

int * I2S3_TxBUFF = getI2S3_TxBUFF();
int INSAMPLE_I2S_MONO;

int * I2S3_TxBUFF = getI2S3_TxBUFF();

int INSAMPLE_I2S_MONO;

for (int i = 2048; i < 4096; i++) {

if ((i % 2) == 0) { // L Samples

INSAMPLE_I2S_MONO[(i >> 1)-1024] = I2S1_RxBUFF[i];

} else if ((i % 2) == 1){ // R Samples

INSAMPLE_I2S_MONO[((i - 1) >> 1) - 1024] += I2S1_RxBUFF[i];
INSAMPLE_I2S_MONO[((i - 1) >> 1) - 1024]  =  INSAMPLE_I2S_MONO[((i - 1) >> 1) - 1024] >> 1;

}

}

for (int i = 2048; i < 4096; i++) {

if ((i % 2) == 0) { // L Samples

} else if ((i % 2) == 1){ // R Samples

}

if (i < 3072) {

I2S3_TxBUFF[i - 1024] =  INSAMPLE_I2S_MONO[i-2048];

}
}


UPDATE 1:

I still dont have a clue, but since the frequencies are being doubled, does it have to do with feeding the audio samples at half? For example I am receiving a total of 4096 samples but when summing I am only sending back out 2048. Is that why? Its trying to send 2048 within the 4096 sample period?

UPDATE 2:

Another gut feeling is coming from adding the two samples together. I feel like it has something to do with the sampling rate. Tried output L + R samples and it works fine, but when I combine them the sample rate is doubled.

• seems a complex problem. But you really should clean up your code – delete all that's commented out. Not only is this kind of something you should generally do out of politeness before discussing your code, it also helps yourself concentrate. Also, I can guarantee that you don't want double on a microcontroller, that will just be terrible performance-wise, and you don't need it. So, let go of that code – and delete it. You're using git to track your code changes, anyway. Right? Jun 12 at 1:16
• Hi!, sorry you're right, ill tidy that up. Yes, I agree with you on the double, however it's there to do double arithmetic for the DSP. The MCU i am using has a double - FPU. And yes using git to track revisions
– Leoc
Jun 12 at 1:22
• Cool! Thanks for the code cleanup. (now it's only duplicate empty lines) Jun 12 at 1:24
• looks like you might be forgetting to fetch the current rx buffer pointer in your halftime callback? What microcontroller is this? Jun 12 at 1:26
• also, make sure your callback actually completes in the time it takes the hardware to work half a buffer. You're doing a lot of non-DMA copying, and you're using 4 kB (I assume 32 bit ints) of Stack space – that's actually not great. Jun 12 at 1:27