3
\$\begingroup\$

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[1024];
  
  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[1024];

  int * I2S3_TxBUFF = getI2S3_TxBUFF();

  int INSAMPLE_I2S_MONO[1024];
  
  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];

    }
  }

Results: @ 6Hz enter image description here

@ 56Hz enter image description here

@ 1kHz enter image description here

@ 4khz enter image description here

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.

\$\endgroup\$
8
  • \$\begingroup\$ 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? \$\endgroup\$ Jun 12 at 1:16
  • \$\begingroup\$ 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 \$\endgroup\$
    – Leoc
    Jun 12 at 1:22
  • 2
    \$\begingroup\$ Cool! Thanks for the code cleanup. (now it's only duplicate empty lines) \$\endgroup\$ Jun 12 at 1:24
  • \$\begingroup\$ looks like you might be forgetting to fetch the current rx buffer pointer in your halftime callback? What microcontroller is this? \$\endgroup\$ Jun 12 at 1:26
  • \$\begingroup\$ 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. \$\endgroup\$ Jun 12 at 1:27
0
\$\begingroup\$

The issue was resolved with the help of Hilmar over at DSP Stackexchange

The problem was I was populating the array with half the samples (2048) of the I2S1_RxBUFF where it should have been the total 4096 samples

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.