Realtime Audio Loopback, Measuring, and DSP

New to XMOS and XCore? Get started here.
student_researcher
Junior Member
Posts: 4
Joined: Sat Mar 13, 2021 7:29 pm

Realtime Audio Loopback, Measuring, and DSP

Post by student_researcher »

Hello,

I am a student researcher attempting to use the xCORE-200 MC Audio board for DSP. I am very new to xmos and DSP in general, but I have been spending a lot of time reading the manuals and code examples. I can use xTime Composer to successfully run the I2S loopback demo (AN00162), and I have read over the code and feel that I understand it well enough. However, when I try modify the i2s_loopback function to display the sample, the loopback stops working and I hear a high pitch sound. I suspect this is because I am interrupting the real time ADC and DAC. I do not understand why i2s stops working when I try to modify it. Please note that I have redirected stdout to the XTAG to preserve realtime functionality. For example, here is a custom interface I made:

Code: Select all

[[distributable]]
void read_signal(server interface share_signal_if i) {
    printf("Starting task: read_signal\n");
    while(1) {
        select {
            case i.share(int32_t sample):
                printf("Received sample: %d\n", sample);
                xscope_int(0, sample);
                break;
        }
    }
}
When I use a simple variable test, I can view the variable in console and loopback works just fine:

Code: Select all

    case i2s.receive(size_t n_chans, int32_t in_samps[n_chans]):
      first_sample = in_samps[0];
      delay_microseconds(10);
      for (int i = 0; i < n_chans; i++) samples[i] = in_samps[i]; // copy samples
      i.share(test);  // works just fine
      test++;
      if (test >= 10) {
          test = 0;
      }
      break;
But when I try to print anything related to the sample, the loopback stops working:

Code: Select all

    case i2s.receive(size_t n_chans, int32_t in_samps[n_chans]):
      first_sample = in_samps[0];
      delay_microseconds(10);
      for (int i = 0; i < n_chans; i++) samples[i] = in_samps[i]; // copy samples
      i.share(first_sample);  // breaks loopback
      test++;
      if (test >= 10) {
          test = 0;
      }
      break;
I have searched through the examples, manuals, and GitHub but I have not found any examples that perform real time DSP on this board. I was hoping I could be pointed in the right direction. It would be very helpful to look at specific examples of real-time audio processing, measuring, etc. For example, maybe I am going about this completely wrong and I should not be using i2s at all! I'm not sure.

The end goal of this project is to read audio from a microphone, perform some DSP (specifically active noise canceling), and output through a speaker. I am just using a small interview microphone that plugs into a 3.5mm jack, but the I2S loopback does not work with that, so any information on that front would also be appreciated.

Thank you for your time in reading this message. Any information on how to get started with this will be much appreciated.


User avatar
CousinItt
Respected Member
Posts: 275
Joined: Wed May 31, 2017 6:55 pm

Post by CousinItt »

Try using the debug printing library (see links below), remembering to enable the xscope link. Making your function distributable may also be slowing it (or something else) down, so try without if you can.

https://www.xmos.ai/download/AN00239:-U ... .0rc1).pdf

https://www.xmos.ai/download/lib_loggin ... .0rc1).pdf
student_researcher
Junior Member
Posts: 4
Joined: Sat Mar 13, 2021 7:29 pm

Post by student_researcher »

Hello, it has been a long time since I asked this question but thank you for the response! However I tried using the debug library as you suggested and unfortunately I still get the high pitched ringing sound.

In my time since asking this question, I have used a different DSP board and achieved much of what I want to accomplish. However, I am trying the xCORE-200 MC Audio Board again because there are more channels and it may be a faster board. Unfortunately, I am remembering how challenging working with this board is. Consider the code snippet from the AN00162 demo:

Code: Select all

    case i2s.receive(size_t index, int32_t sample):
      int32_t filter_out = 0;
      unsafe {
          int32_t * unsafe pI;
          *pInput = sample;
          pI = pInput;
          if(++pInput > &xInput[N])                       // update pointer, wrap if necessary
              pInput = xInput;                            // and store
          for (int32_t i = 0; i <= N; i++) {                      // do RIGHT channel FIR
              filter_out += *pI-- * B[i];                 // multiply and accumulate
              if(pI < &xInput[0])                     // check for pointer wrap around
                  pI = &xInput[N];
          }
      }
      samples[index] = sample; //filter_out;
      break;
I have modified the i2s.recieve function to perform an FIR filter on the input sample. Here are some global variables I added to the beginning of the code:

Code: Select all

// Global Variables
int32_t xInput[N+1];
unsafe {
    int32_t * unsafe pInput = xInput;
}
Now my problem is in the samples[index] = sample; // filter_out line. When set to sample, the loopback works completely fine. However, when set to filter_out, I receive a high-pitched ringing sound. I receive this ringing (sometimes high pitch, sometimes lower) very often when modifying this code. It would be VERY helpful if someone had any idea what might be causing this issue. I have attempted to use printf and debug_printf to view the filter output but this also causes ringing. I have changed the optimization using -O0 instead of -O2 and stepped through the debug but I get a bunch of zero values that don't make sense. Furthermore, if I leave the optimization at -O0 and run the code normally, I receive the high pitched ringing.

Other things I don't understand: decreasing the MASTER_CLOCK_FREQUENCY by an arbitrary amount also causes the ringing sound. Changing the SAMPLE_FREQUENCY from 48000 to 24000 causes silent audio. However I can change the sample rate to 44.1k and the master clock frequency to 22.5792 MHz (from spec sheet) and the talk through still works.

Any insight on what the ringing is, how to debug, or otherwise would be very helpful. Thank you.
Last edited by student_researcher on Wed Aug 11, 2021 8:42 pm, edited 2 times in total.
User avatar
akp
XCore Expert
Posts: 544
Joined: Thu Nov 26, 2015 11:47 pm

Post by akp »

The most likely causes of your audio artifact are:
1. The code cannot run real time
2. The FIR is incorrectly implemented

It seems to me that when optimization is enabled the filter may not run at all because filter_out is unused, it may be entirely optimized away. So it's not clear at all if the artifact is caused by (1) or (2).

Your FIR implementation looks odd to me. It's quite possible it will overflow since when you multiply two 32 bit numbers together obviously you get a 64 bit result, whereas your accumulator is 32 bits.

I think you can rule out (1) as the cause if you get the same result no matter how slow you go, like even 1k or less sample rate. Furthermore, if you're running as I2S master, you can simply probe your I2S bit clock and word clock to make sure they're running at the right rate, if the i2s receive has too much back pressure (i.e. can't run real time) then it will cause the i2s bit clock and word clock to go out of the correct rate (of course this applies in master mode only, since when it's an i2s slave the XMOS MCU doesn't generate those clocks).

Running your code under the simulator can also be helpful for finding errors, you can probably output the data to a 32 bit port or something and read the values directly from the simulator output. Or maybe you can do realtime xscope of the values at runtime.
student_researcher
Junior Member
Posts: 4
Joined: Sat Mar 13, 2021 7:29 pm

Post by student_researcher »

Hi, thank you for replying. I appreciate your point about the overflow with my FIR implementation. This is something I haven't considered and I will look into. In the time since my last post, I have switched to using the frame based version of i2s. This actually caused the ringing issue to go away. I am able to implement some sort of filtering effect in that I can make audio silent or louder. However, I would like to use a more official FIR filter implementation. So I am trying to use the DSP library which I have downloaded from here: https://github.com/xmos/lib_dsp/tree/master. I can successfully run and compile the examples included in the repository. But, when I try to include the dsp library in my own project, I get errors saying that dsp_qformat.h is not found in dsp_adaptive.c. Here is the exact error:

Code: Select all

WARNING: Required version of lib_logging is >=2.1.0 and actual version has greater major version: 3.1.0. There could be API incompatibilities.
Using build modules: lib_dsp(6.2.0) lib_gpio(1.1.0) lib_i2c(5.0.0) lib_i2s(3.0.0) lib_logging(3.1.0) lib_xassert(3.0.0)
Analyzing dsp_adaptive.c
"C:\Program Files (x86)\XMOS\xTIMEcomposer\Community_14.4.1\build\xcommon\module_xcommon/build/mkdir.bat"  .build _l_dsp src  > nul 2>&1
cd .build && xcc -pre-compilation-analysis  -O2 -report -g     -DCONFIG=Default      @_iflag.rsp "C:/Users/user/Documents/Research/Active Noise Canceling/xTime Workspace/lib_dsp/lib_dsp/src/dsp_adaptive.c" -x none ".././src/XR-AUDIO-216-MC.xn"  "..\.\config.xscope" -o "../.build/_l_dsp/src/dsp_adaptive.c.pca.xml.decouple" > nul
C:/Users/user/Documents/Research/Active Noise Canceling/xTime Workspace/lib_dsp/lib_dsp/src/dsp_adaptive.c:5:10: fatal error: 'dsp_qformat.h' file not found
#include "dsp_qformat.h"
         ^
1 error generated.
xmake[1]: *** [.build/_l_dsp/src/dsp_adaptive.c.pca.xml.decouple] Error 1
xmake: *** [analyze] Error 2

I am not sure why it works with the example, but not with my project. I am using #include <dsp.h> at the top of my main.xc and I am including lib_dsp in the Makefile. Any idea what may be causing this issue?

EDIT: I just noticed I have a Warning that says: Invalid project path: Include path not found (\Users\andrew\sandboxes\sw3510\Installs\Mac\target\include\c++\v1) which it states is a Path Entry Problem. I have no user named 'andrew' on my computer and I am using Windows, so this is clearly wrong. I have many similar Warnings. How can I fix this?
Last edited by student_researcher on Wed Aug 18, 2021 9:21 pm, edited 1 time in total.