USB Audio Reference Changes

Sub forums for various specialist XMOS applications. e.g. USB audio, motor control and robotics.
jshi
Member
Posts: 9
Joined: Tue Jan 16, 2018 8:37 pm

USB Audio Reference Changes

Post by jshi »

I am trying to make the following changes using app_usb_aud_xk_216_mc:

1. Take the channel inputs from USB and downmix them into stereo.

2. Output the stereo mix through i2s to an external codec. It looks like the SDIO1 pin (I've added a header to the board) would be good for this. Looks like that maps to XS1_PORT_1I.

3. I'd also like to disable the rest of the functionality, such as the onboard DAC/ADC i2s pathways, midi, spdif, adat. Some of the latter look easy to disable from customdefines.h

For #1, I haven't found any examples of how to use the mixer. There is no documentation titled `mixer` that I've seen.

For #2, I guess I need to add the i2s library, but will that conflict with the i2s code that is already in module_usb_audio? Do I just need to add it to the USB tile? Can I fit all my functionality on one tile?
User avatar
akp
XCore Expert
Posts: 580
Joined: Thu Nov 26, 2015 11:47 pm

Post by akp »

Is there a reason you want to downmix on the board? Why don't you just make the board have 2 ch input, have your PC do the downmix automatically, and bypass the DAC with your CODEC?
jshi
Member
Posts: 9
Joined: Tue Jan 16, 2018 8:37 pm

Post by jshi »

The reason for down-mixing on the board is because the product will have controls for mixing the channels further down the road.
User avatar
infiniteimprobability
Verified
XCore Legend
Posts: 1143
Joined: Thu May 27, 2010 10:08 am

Post by infiniteimprobability »

I am trying to make the following changes using app_usb_aud_xk_216_mc:

1. Take the channel inputs from USB and downmix them into stereo.
You could quite easily do this by adding some code in DoSampleTransfer() in audio.xc. There is an audio path from I2S to the host using samplesIn_1/0[] which you can modify on the way in and an audio path from the host to I2S via samplesOut[] which you can modify too.

2. Output the stereo mix through i2s to an external codec. It looks like the SDIO1 pin (I've added a header to the board) would be good for this. Looks like that maps to XS1_PORT_1I.
Yes, SDIO1 is fine - it maps to DAC0 in the port declarations in main.xc and corresponds to samplesOut[0..1] in the above function. The board is quite nice because you can pull the jumpers off and tap into the signals using headers.
3. I'd also like to disable the rest of the functionality, such as the onboard DAC/ADC i2s pathways, midi, spdif, adat. Some of the latter look easy to disable from customdefines.h
Yes, customdefines.h is your friend. Be aware that I2S_CHANS_xxx and I2S_CHANS_xxx do not have to be equal. So you could have two channels from the host and 4 channels to the DAC if you so choose, for example.
For #1, I haven't found any examples of how to use the mixer. There is no documentation titled `mixer` that I've seen.
It's not 100% comprehensive, but section 3.6 of https://www.xmos.com/download/private/s ... rc1%29.pdf has some info. If you are doing a simple down mix (mono = (left >> 1) + (right >> 1) it may be simpler to go with the above approach.
For #2, I guess I need to add the i2s library, but will that conflict with the i2s code that is already in module_usb_audio? Do I just need to add it to the USB tile?
You would struggle with this approach. Just change I2S_CHANS_xxx to get what you want.
Can I fit all my functionality on one tile?
Definitely (it's 5 threads for the basic ref design with no spif, midi or mixer)
Engineer at XMOS
jshi
Member
Posts: 9
Joined: Tue Jan 16, 2018 8:37 pm

Post by jshi »

Thank you for your response--it will help me get this up and running today I think.
1. Take the channel inputs from USB and downmix them into stereo.
You could quite easily do this by adding some code in DoSampleTransfer() in audio.xc. There is an audio path from I2S to the host using samplesIn_1/0[] which you can modify on the way in and an audio path from the host to I2S via samplesOut[] which you can modify too.
I think I can see the path to just passing two channels through to is2 in this approach, but if I need to do a more complex mix than two channels, where would a better place to start be?
RitchRock
XCore Addict
Posts: 199
Joined: Tue Jan 17, 2017 9:25 pm

Post by RitchRock »

jshi wrote:Thank you for your response--it will help me get this up and running today I think.
1. Take the channel inputs from USB and downmix them into stereo.
You could quite easily do this by adding some code in DoSampleTransfer() in audio.xc. There is an audio path from I2S to the host using samplesIn_1/0[] which you can modify on the way in and an audio path from the host to I2S via samplesOut[] which you can modify too.
I think I can see the path to just passing two channels through to is2 in this approach, but if I need to do a more complex mix than two channels, where would a better place to start be?
DoSampleTranser handles as many audio channels as you have specified. I would use a streaming chanend to send audio out of DoSampleTransfer() to your own mixer. Do whatever processing you want in your own mixer. Then send the audio back over the streaming chanend to DoSampleTransfer(). For example, in one app, within DoSampleTransfer I send 4 channels from I2S ADC in and 4 channels from USB Playback to my custom mixer. I then do some processing and with the streaming chanend, send a L/R mix for headphones and 4 channels USB input back to DoSampleTransfer().
jshi
Member
Posts: 9
Joined: Tue Jan 16, 2018 8:37 pm

Post by jshi »

RitchRock wrote:DoSampleTranser handles as many audio channels as you have specified. I would use a streaming chanend to send audio out of DoSampleTransfer() to your own mixer. Do whatever processing you want in your own mixer. Then send the audio back over the streaming chanend to DoSampleTransfer(). For example, in one app, within DoSampleTransfer I send 4 channels from I2S ADC in and 4 channels from USB Playback to my custom mixer. I then do some processing and with the streaming chanend, send a L/R mix for headphones and 4 channels USB input back to DoSampleTransfer().
Am I supposed to hardcode this within the function such as:

Code: Select all

    streaming chan c_mixer_in;
    streaming chan c_mixer_out_left;
    streaming chan c_mixer_out_right;
    
    for(int i = I2S_CHANS_ADC; i < NUM_USB_CHAN_IN; i++)
        {
            outuint(c_mixer_in, samplesIn_0[i]);
        }
    }

    doMyMix(c_mixer_in, c_mixer_out_left, c_mixer_out_right);

    outuint(c_mixer_out_left, samplesOut[0]);
    outuint(c_mixer_out_right,samplesOut[1]);
instead of relying on the c_out parameter of DoSampleTransfer()?
RitchRock
XCore Addict
Posts: 199
Joined: Tue Jan 17, 2017 9:25 pm

Post by RitchRock »

First, review XMOS Programmign Guide section 2.2.3: https://www.xmos.com/download/private/X ... on)(E).pdf

I'm assuming doMymix() is your mixer. That should be started in parallel with audio() back in your main function, along with the streaming chanend. Then, the streaming chanend would be passed through audio() into DoSampleTransfer(). You can send audio to/from your mixer with calls like this:

Code: Select all

        //First, fill a mixer buffer with the data you want to send to the mixer
        //Something like mixSend[NUM_USB_CHAN_OUT + ADC_CHANS_IN]
        //Once your buffer is filled with the latest samples, send to your streaming chanend associated with mixer input.
        // I'm calling it c_Mixer in the code below

#pragma loop unroll
        for(int k = 0; k < (NUM_USB_CHAN_OUT + ADC_CHANS_IN); k++)
        {
            c_Mixer <: mixSend[k];
        }

       //Nowreceive the processed samples back usinig the :> operator

         c_Mixer :> mixReturn[k];
jshi
Member
Posts: 9
Joined: Tue Jan 16, 2018 8:37 pm

Post by jshi »

I do not currently have a doMyMix() function; it was hypothetical.

I have had a little more time to look into this and because I'm starting with the USB reference application, it seems complicated. I read through the current mixer.xc file and tried to map out what it is doing to help understand.

Image

I guess I will try wiping out what is in the DoSampleTransfer() down to only stuff that I need, and replacing the preconstructed mixer with my own, but it seems like the host device control software is supposed to be able to control path of mixes, so it should be possible to do what I need it to with the current code, but I'm not sure how host commands interact with the mixer yet.