Skip to content

Commit

Permalink
Merge pull request #399 from shuchitak/mixer_fix
Browse files Browse the repository at this point in the history
refactor the mixer threads
  • Loading branch information
xross authored Jun 28, 2024
2 parents c4da4c5 + 8f42bfb commit fcf8aac
Show file tree
Hide file tree
Showing 12 changed files with 191 additions and 171 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
lib_xua change log
==================

UNRELEASED
----------

* CHANGED: Using lsats instruction for saturation in the mixer
* CHANGED: Simplified the mixer threads communication scheme

* Changes to dependencies:

- lib_xud: 2.3.1 -> 2.3.2

4.1.0
-----

Expand Down
2 changes: 1 addition & 1 deletion Jenkinsfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@Library('xmos_jenkins_shared_library@v0.27.0') _
@Library('xmos_jenkins_shared_library@v0.32.0') _

getApproval()

Expand Down
Binary file added lib_xua/doc/rst/images/mixer.pdf
Binary file not shown.
34 changes: 34 additions & 0 deletions lib_xua/doc/rst/images/mixer.plantuml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
@startuml


participant audiohub as audiohub
participant mixer1 as mixer1
participant mixer2 as mixer2
participant decoupler as decoupler


title "Mixer: MAX_MIX_COUNT > 0"
loop while(1)
audiohub -> mixer1 : receive request
mixer1 -> decoupler : forward request
mixer1 -> mixer1 : do mixer control

alt decoupler responds with command
decoupler -> mixer1 : get command
mixer1 -> audiohub : forward command
audiohub -> mixer1 : receive handshake
mixer1 -> decoupler : forward handshake
else decoupler responds with data
mixer2 -> mixer1 : synchronise
mixer1 -> audiohub : give samples
mixer1 <- audiohub : get samples
mixer1 <- decoupler : get samples
mixer1 -> decoupler : give samples
mixer1 -> mixer2 : trigger
par
mixer2 -> mixer2 : doMix
mixer1 -> mixer1 : doMix
end
end
end
@enduml
Binary file added lib_xua/doc/rst/images/mixer.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added lib_xua/doc/rst/images/mixer_passthrough.pdf
Binary file not shown.
26 changes: 26 additions & 0 deletions lib_xua/doc/rst/images/mixer_passthrough.plantuml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
@startuml

participant audiohub as audiohub
participant mixer1 as mixer1
participant decoupler as decoupler


title "Mixer: MAX_MIX_COUNT = 0"
loop while(1)
audiohub -> mixer1 : receive request
mixer1 -> decoupler : forward request

alt decoupler responds with command
decoupler -> mixer1 : get command
mixer1 -> audiohub : forward command
audiohub -> mixer1 : receive handshake
mixer1 -> decoupler : forward handshake
else decoupler responds with data
mixer1 -> audiohub : give samples
mixer1 <- audiohub : get samples
mixer1 <- decoupler : get samples
mixer1 -> decoupler : give samples
end
end

@enduml
Binary file added lib_xua/doc/rst/images/mixer_passthrough.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
76 changes: 56 additions & 20 deletions lib_xua/doc/rst/sw_mixer.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ Digital Mixer

The Mixer core(s) take outgoing audio from the Decouple core and incoming audio from the Audio Hub
core. It then applies the volume to each channel and passes incoming audio on to Decouple and outgoing
audio to Audio Hub. The volume update is achieved using the built-in 32bit to 64bit signed
audio to Audio Hub. The volume update is achieved using the built-in 32bit to 64bit signed
multiply-accumulate function (``macs``). The mixer is implemented in the file ``mixer.xc``.

The mixer takes (up to) two cores and can perform eight mixes with up to 18 inputs at sample rates
up to 96kHz and two mixes with up to 18 inputs at higher sample rates. The component automatically
The mixer takes (up to) two cores and can perform eight mixes with up to 18 inputs at sample rates
up to 96kHz and two mixes with up to 18 inputs at higher sample rates. The component automatically
reverts to generating two mixes when running at the higher rate.

The mixer can take inputs from either:
Expand All @@ -29,19 +29,55 @@ for each mix.
* The outputs to the audio interface on the device---these samples are sent to the Audio Hub
core

For each possible output from the device, a mapping exists to inform the mixer what it's source is.
For each possible output from the device, a mapping exists to inform the mixer what it's source is.
The possible sources are the output from the USB host, the inputs from the Audio Hub core or the
outputs from the mixes.

Essentially the mixer/router can be configured such that any device input can be used as an input to
any mix or routed directly to any device output. Additionally, any device output can be derived from
any mixer output or any device input.
any mixer output or any device input.

As mentioned in :ref:`usb_audio_sec_audio-requ-volume`, the mixer can also handle processing or
volume controls. If the mixer is configured to handle volume but the number of mixes is set to zero
(such that the core is solely doing volume setting) then the component will use only one core. This
is sometimes a useful configuration for large channel count devices.

A sequence diagram showing the communication between Audio Hub, Decouple and mixer threads is shown in :ref:`mixer_full`.
mixer1 thread exchanges data with Decouple and Audio Hub along with any volume control operations and performs
the mixing operations for the even output channel numbers. The mixing for the odd channels is offloaded to the mixer2 thread.


.. only:: latex

.. _mixer_full:

.. figure:: images/mixer.pdf

Mixer communication sequence diagram

.. only:: html

.. figure:: images/mixer.png

Mixer communication sequence diagram

The mixer can also be configured in passthrough mode (MAX_MIX_COUNT = 0), as shown in :ref:`mixer_passthrough`. In this mode, the mixer2 thread is
not present and the mixer1 exchanges data with Audio Hub and Decouple along with any volume control operations without doing any actual mixing.

.. only:: latex

.. _mixer_passthrough:

.. figure:: images/mixer_passthrough.pdf

Mixer in passthrough mode

.. only:: html

.. figure:: images/mixer_passthrough.png

Mixer in passthrough mode

Control
~~~~~~~

Expand Down Expand Up @@ -81,10 +117,10 @@ are described in :ref:`table_mixer_commands`.
Host Control
~~~~~~~~~~~~

The mixer can be controlled from a host PC by sending requests to Endpoint 0. XMOS provides a simple
The mixer can be controlled from a host PC by sending requests to Endpoint 0. XMOS provides a simple
command line based sample application demonstrating how the mixer can be controlled. This is
intended as an example of how you might add mixer control to your own control application. It is not
intended to be exposed to end users.
intended to be exposed to end users.

For details, consult the README file in the host_usb_mixer_control directory.
A list of arguments can also be seen with::
Expand All @@ -105,20 +141,20 @@ The main requirements of this control utility are to
functionality to their end users.

Whilst using the XMOS Host control example application, consider the example of setting the
mixer to perform a loop-back from analogue inputs 1 & 2 to analogue outputs 1 & 2.
mixer to perform a loop-back from analogue inputs 1 & 2 to analogue outputs 1 & 2.

.. note::

The command outputs shown are examples; the actual output will depend on the mixer configuration.

The following will show the index for each device output along with which channel is currently mapped to it.
In this example the analogue outputs 1 & 2 are 0 & 1 respectively::
In this example the analogue outputs 1 & 2 are 0 & 1 respectively::

$ ./xmos_mixer --display-aud-channel-map

Audio Output Channel Map
------------------------

0 (DEVICE OUT - Analogue 1) source is 0 (DAW OUT - Analogue 1)
1 (DEVICE OUT - Analogue 2) source is 1 (DAW OUT - Analogue 2)
2 (DEVICE OUT - SPDIF 1) source is 2 (DAW OUT - SPDIF 1)
Expand All @@ -131,7 +167,7 @@ The DAW Output Map can be seen with::

DAW Output To Host Channel Map
------------------------

0 (DEVICE IN - Analogue 1) source is 4 (DEVICE IN - Analogue 1)
1 (DEVICE IN - Analogue 2) source is 5 (DEVICE IN - Analogue 2)
$ _
Expand All @@ -140,8 +176,8 @@ The DAW Output Map can be seen with::

In both cases, by default, these bypass the mixer.

The following command will list the channels which can be mapped to the device outputs from the
Audio Output Channel Map. Note that, in this example, analogue inputs 1 & 2 are source 4 & 5 and
The following command will list the channels which can be mapped to the device outputs from the
Audio Output Channel Map. Note that, in this example, analogue inputs 1 & 2 are source 4 & 5 and
Mix 1 & 2 are source 6 & 7::

$ ./xmos_mixer --display-aud-channel-map-sources
Expand Down Expand Up @@ -171,7 +207,7 @@ You can confirm the effect of this by re-checking the map::

Audio Output Channel Map
------------------------

0 (DEVICE OUT - Analogue 1) source is 6 (MIX - Mix 1)
1 (DEVICE OUT - Analogue 2) source is 7 (MIX - Mix 2)
2 (DEVICE OUT - SPDIF 1) source is 2 (DAW OUT - SPDIF 1)
Expand Down Expand Up @@ -205,7 +241,7 @@ with the following command::
AUD - Analogue 2 10:[ -inf ] 11:[ -inf ]
$ _

With mixer outputs 1 & 2 mapped to device outputs analogue 1 & 2; to get the audio from the analogue inputs to device
With mixer outputs 1 & 2 mapped to device outputs analogue 1 & 2; to get the audio from the analogue inputs to device
outputs mixer_id 0 node 8 and node 11 need to be set to 0db::

$ ./xmos_mixer --set-value 0 8 0
Expand All @@ -218,11 +254,11 @@ At the same time, the original mixer outputs can be muted::
$ ./xmos_mixer --set-value 0 3 -inf
$ _

Now audio inputs on analogue 1 and 2 should be heard on outputs 1 and 2 respectively.
Now audio inputs on analogue 1 and 2 should be heard on outputs 1 and 2 respectively.

As mentioned above, the flexibility of the mixer is such that there will be multiple ways to create
a particular mix. Another option to create the same routing would be to change the mixer sources
such that mixer outputs 1 and 2 come from the analogue inputs 1 and 2.
such that mixer outputs 1 and 2 come from the analogue inputs 1 and 2.

To demonstrate this, firstly undo the changes above (or simply reset the device)::

Expand All @@ -232,7 +268,7 @@ To demonstrate this, firstly undo the changes above (or simply reset the device)
$ ./xmos_mixer --set-value 0 3 0
$ _

The mixer should now have the default values. The sources for mixer 0 output 1 and 2 can now be changed
The mixer should now have the default values. The sources for mixer 0 output 1 and 2 can now be changed
using indices from the Audio Output Channel Map Source List::

$ ./xmos_mixer --set-mixer-source 0 0 4
Expand All @@ -244,8 +280,8 @@ using indices from the Audio Output Channel Map Source List::
$ _

If you re-run the following command then the first column now has "AUD - Analogue 1 and 2" rather
than "DAW (Digital Audio Workstation i.e. the host) - Analogue 1 and 2" confirming the new mapping.
than "DAW (Digital Audio Workstation i.e. the host) - Analogue 1 and 2" confirming the new mapping.
Again, by playing audio into analogue inputs 1/2 this can be heard looped through to analogue outputs 1/2::

$ ./xmos_mixer --display-mixer-nodes 0

2 changes: 1 addition & 1 deletion lib_xua/lib_build_info.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ set(LIB_DEPENDENT_MODULES "lib_adat(1.2.0)"
"lib_spdif(6.1.0)"
"lib_sw_pll(2.2.0)"
"lib_xassert(4.2.0)"
"lib_xud(2.3.1)")
"lib_xud(2.3.2)")

set(LIB_COMPILER_FLAGS -O3 -DREF_CLK_FREQ=100 -fasm-linenum -fcomment-asm)

Expand Down
33 changes: 5 additions & 28 deletions lib_xua/src/core/mixer/fastmix.S
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2018-2023 XMOS LIMITED.
// Copyright 2018-2024 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.

#include "xua.h"
Expand Down Expand Up @@ -36,19 +36,16 @@ doMix##i##: ;\
lsub r0, r1, r0, r0, r0;\
.label_##i##:

// Saturate the maccs result to 25bits
#define DOMIX_BOT(i) \
ldap r11, _dp; \
set dp, r11;\
ldap r11, _cp;\
set cp, r11;\
\
mov r0, r1;\
ldc r2, 0x19;\
sext r0, r2;\
eq r0, r0, r1;\
bf r0, .L20; \
\
shl r0, r1, 0x7;\
ldc r2, 0x19; \
lsats r1, r0, r2; \
shl r0, r1, 7; \
retsp 0x0;\
\
\
Expand All @@ -64,14 +61,6 @@ doMix##i##: ;\

.text

.L20:\
lss r0, r1, r3;\
bt r0, .L16; \
ldw r0, cp[.LC0];\
retsp 0x0; \
.L16:\
ldw r0, cp[.LC1];\
retsp 0x0; \


#if(MAX_MIX_COUNT > 0)
Expand Down Expand Up @@ -167,18 +156,6 @@ setPtr_go:
.size setPtr, .-setPtr
.cc_bottom setPtr.function

.section .cp.const4, "acM", @progbits, 4
.cc_top .LC0.data
.align 4
.LC0:
.int 0x7fffff00
.cc_bottom .LC0.data
.cc_top .LC1.data
.align 4
.LC1:
.int 0x80000000
.cc_bottom .LC1.data

#undef N
#undef BODY

Expand Down
Loading

0 comments on commit fcf8aac

Please sign in to comment.