Mixer, DSP, MIDI

Discussions relating to the XK-EVK-XU316
hohoho
Member
Posts: 9
Joined: Tue Jun 02, 2020 3:40 pm

Mixer, DSP, MIDI

Post by hohoho »

Hi,

I have a few questions regarding Mixer, DSP and MIDI in XK-AUDIO-316-MC.

I have flashed it with the sw_usb_audio reference firmware. My configuration is:

INCLUDE_ONLY_IN_2AMi8o8mxxxxx_mix8 =
XCC_FLAGS_2AMi8o8mxxxxx_mix8 = $(BUILD_FLAGS)        -DMAX_MIX_COUNT=8 \
                                                     -DSPDIF_TX=0 \
                                                     -DMIDI=1 \
                                                     -DLEVEL_METER_HOST=1 \
                                                     -DIN_VOLUME_IN_MIXER=1 \
                                                     -DIN_VOLUME_AFTER_MIX=0 \
                                                     -DOUT_VOLUME_IN_MIXER=1 \
                                                     -DOUT_VOLUME_AFTER_MIX=1

I have also built xmos_mixer from host_usb_mixer_control. I am on Mac. The amount of code is overwhelming and I seek guidance.

1. There is only one volume control (like
./xmos_mixer --set-value 0 64 0
), but from the code (and my configuration), there should be both input and output volume adjustments. How to adjust both input and output volumes with the xmos_mixer utility?

2.
./xmos_mixer --get-mixer-levels-output
doesn't work. When I call it, the audio stops, the device becomes unresponsive (I need to unplug it from USB and plug it back again to bring it back to life). After a quick look, it seems that
datalength = usb_mixer_mem_get(dst, offset, levels);
call in mixer_app.cpp hangs everything and never returns.

3. Could you guide me how to insert DSP (like FIR filters and effects you have in a separate sw_audio_effects repository) in between the audio input and the mixer. My desired pipeline for each channel is:

                     Direct Monitoring for minimal latency
                    ___________________________________________________
                  /                                                     \
Audio In -> DSP -                                     USB Host Out ------> Audio Out
                  \          
                    -- USB Host In

I currently seem to be able to have it (minus the DSP part) with something like:
./xmos_mixer --set-aud-channel-map 0 16 # Mix 1 out to audio channel 1 out
./xmos_mixer --set-aud-channel-map 1 17 # Mix 2 out to audio channel 2 out
...
./xmos_mixer --set-value 0 0 0 # DAW channel 1 to Mix 1
./xmos_mixer --set-value 0 64 0 # Audio channel 1 to Mix 1
./xmos_mixer --set-value 0 9 0 # DAW channel 2 to Mix 2
./xmos_mixer --set-value 0 73 0 # Audio channel 2 to Mix 2
...
So, I get:
  Audio Output Channel Map
  ------------------------

0 (DEVICE OUT - Analogue 1) source is 16 (MIX - Mix 1)
1 (DEVICE OUT - Analogue 2) source is 17 (MIX - Mix 2)
2 (DEVICE OUT - Analogue 3) source is 18 (MIX - Mix 3)
3 (DEVICE OUT - Analogue 4) source is 19 (MIX - Mix 4)
4 (DEVICE OUT - Analogue 5) source is 20 (MIX - Mix 5)
5 (DEVICE OUT - Analogue 6) source is 21 (MIX - Mix 6)
6 (DEVICE OUT - Analogue 7) source is 22 (MIX - Mix 7)
7 (DEVICE OUT - Analogue 8) source is 23 (MIX - Mix 8)
and:
  Mixer Values (0)
  ----------------

  			Mixer Outputs
		                 1               2               3               4               5               6               7               8
  DAW - Analogue 1    	  0:[0000.000]	  1:[  -inf  ]	  2:[  -inf  ]	  3:[  -inf  ]	  4:[  -inf  ]	  5:[  -inf  ]	  6:[  -inf  ]	  7:[  -inf  ]
  DAW - Analogue 2    	  8:[  -inf  ]	  9:[0000.000]	 10:[  -inf  ]	 11:[  -inf  ]	 12:[  -inf  ]	 13:[  -inf  ]	 14:[  -inf  ]	 15:[  -inf  ]
  DAW - Analogue 3    	 16:[  -inf  ]	 17:[  -inf  ]	 18:[0000.000]	 19:[  -inf  ]	 20:[  -inf  ]	 21:[  -inf  ]	 22:[  -inf  ]	 23:[  -inf  ]
  DAW - Analogue 4    	 24:[  -inf  ]	 25:[  -inf  ]	 26:[  -inf  ]	 27:[0000.000]	 28:[  -inf  ]	 29:[  -inf  ]	 30:[  -inf  ]	 31:[  -inf  ]
  DAW - Analogue 5    	 32:[  -inf  ]	 33:[  -inf  ]	 34:[  -inf  ]	 35:[  -inf  ]	 36:[0000.000]	 37:[  -inf  ]	 38:[  -inf  ]	 39:[  -inf  ]
  DAW - Analogue 6    	 40:[  -inf  ]	 41:[  -inf  ]	 42:[  -inf  ]	 43:[  -inf  ]	 44:[  -inf  ]	 45:[0000.000]	 46:[  -inf  ]	 47:[  -inf  ]
  DAW - Analogue 7    	 48:[  -inf  ]	 49:[  -inf  ]	 50:[  -inf  ]	 51:[  -inf  ]	 52:[  -inf  ]	 53:[  -inf  ]	 54:[0000.000]	 55:[  -inf  ]
  DAW - Analogue 8    	 56:[  -inf  ]	 57:[  -inf  ]	 58:[  -inf  ]	 59:[  -inf  ]	 60:[  -inf  ]	 61:[  -inf  ]	 62:[  -inf  ]	 63:[0000.000]
  AUD - Analogue 1    	 64:[0000.000]	 65:[  -inf  ]	 66:[  -inf  ]	 67:[  -inf  ]	 68:[  -inf  ]	 69:[  -inf  ]	 70:[  -inf  ]	 71:[  -inf  ]
  AUD - Analogue 2    	 72:[  -inf  ]	 73:[0000.000]	 74:[  -inf  ]	 75:[  -inf  ]	 76:[  -inf  ]	 77:[  -inf  ]	 78:[  -inf  ]	 79:[  -inf  ]
  AUD - Analogue 3    	 80:[  -inf  ]	 81:[  -inf  ]	 82:[0000.000]	 83:[  -inf  ]	 84:[  -inf  ]	 85:[  -inf  ]	 86:[  -inf  ]	 87:[  -inf  ]
  AUD - Analogue 4    	 88:[  -inf  ]	 89:[  -inf  ]	 90:[  -inf  ]	 91:[0000.000]	 92:[  -inf  ]	 93:[  -inf  ]	 94:[  -inf  ]	 95:[  -inf  ]
  AUD - Analogue 5    	 96:[  -inf  ]	 97:[  -inf  ]	 98:[  -inf  ]	 99:[  -inf  ]	100:[0000.000]	101:[  -inf  ]	102:[  -inf  ]	103:[  -inf  ]
  AUD - Analogue 6    	104:[  -inf  ]	105:[  -inf  ]	106:[  -inf  ]	107:[  -inf  ]	108:[  -inf  ]	109:[0000.000]	110:[  -inf  ]	111:[  -inf  ]
  AUD - Analogue 7    	112:[  -inf  ]	113:[  -inf  ]	114:[  -inf  ]	115:[  -inf  ]	116:[  -inf  ]	117:[  -inf  ]	118:[0000.000]	119:[  -inf  ]
  AUD - Analogue 8    	120:[  -inf  ]	121:[  -inf  ]	122:[  -inf  ]	123:[  -inf  ]	124:[  -inf  ]	125:[  -inf  ]	126:[  -inf  ]	127:[0000.000]
                      	128:[  -inf  ]	129:[  -inf  ]	130:[  -inf  ]	131:[  -inf  ]	132:[  -inf  ]	133:[  -inf  ]	134:[  -inf  ]	135:[  -inf  ]
                      	136:[  -inf  ]	137:[  -inf  ]	138:[  -inf  ]	139:[  -inf  ]	140:[  -inf  ]	141:[  -inf  ]	142:[  -inf  ]	143:[  -inf  ]
So, I seem to have the proper routing out of the box. And I want to extend the code to insert effects so that the DSP processed result goes to both direct monitoring and to the USB host. I see lib_dsp module in the repository, and I am seeking help about how to inject it properly. The effects for each input channel are supposed to be different, so that the DSP part should be channel-aware and should allow to chain more than one effect/filter.

4. I want to be able to send MIDI messages to the USB host from the DSP part. Will that be possible and how to do that properly?

5. And I suppose it should be fairly simple to load data to DSP from the host via USB. Like I am able to control the mixer with the xmos_mixer tool, I would want to be able to enable/disable effects, load FIR coefficients and so on. Could you point me to some examples for that?

6. If I run my app_usb_aud_xk_316_mc.xe with xsim — is it possible to have some kind of virtual usb device so that it is possible to test things without the device?
User avatar
fabriceo
XCore Addict
Posts: 222
Joined: Mon Jan 08, 2018 4:14 pm

Post by fabriceo »

Hello and welcome,
you ask a list of valid questions where I cannot remember that an answer exist as such in the xmos documents...
so it means you have to experiment a bit and go deep in the source code...
Also and unfortunately the xmos specialists who have been working on the sw_usb_audio app are not supporting the forum in a timely manner but more on a good will and personal voluntary mode.

from my experience, and to try giving you some directions:
- when you activate the MIXER in your xua config file, the decouple task, in charge of sending the samples to the I2S task, will route them to the "c_mix_ctl" channel, and then the mixer task will route them to the audio task for I2S serialization. In both direction for DAC and ADC. The mixer comes "in-between" the 2 tasks.
- there is a recent app note on xmos website on how to interface DSP tasks with the I2S samples buffer. This will work between the mixer and the I2S tasks : everything coming from the ADC can be transformed with DSP code and then will go to the mixer as a replacement. if you want a more complex routing then you will have to interface your DSP routines with the sample tables used in the mixer task but there is no api for this.
- the usb midi interface is integrated in the application: the usb endpoint transfers are in the buffer task and some controls are implemented in the enpoint0 task. the serialization tx/rx is implemented in the midi task. To intercept messages you will have to insert some code in some of these tasks. Maybe you don't need the physical tx/rx feature and can remove this code and replace it with your own code to handle the data flow instead.
- for sending parameters to your dsp tasks you can implement some specific Vendor Request command. the endpoint0 source file is ready for this with some defines in the code. then you will be able to send upto 64bytes packets by using libusb commands. this is reliable and easy to implement by leveraging the mixer host source code. If you plan to use a windows host with thesycon driver then you will have to include the thesycon sdk h file, like in the mixer host.
Probably you will want to save the dsp parameters in the flash data partition. this is also relatively easy to do with the flash library and implementing read/write vendor request.

sorry, this is not a turnkey solution, I ve done all of that for a commercial product so I cannot share everything. hope this helps
fabriceo