 
          3-Channel to 2-Channel Matrixer Filter Ft3To2 1.00
          --------------------------------------------------
                        for VSOS 3.66 or higher
                       2023-02-28  VLSI Solution




The Ft3To2 filter drivers offers arbitrary matrix operations between a
3-channel source and 2-channel destination. With it, it is possible to
handle differential or multi-channel inputs and potentially create a
differential LR output. To use the package, copy the .dl3 files to your
VS1005 system disk SYS/ folder, then follow the instructions in this manual.
The matrix filter can be accessed both from C programs using ioctl() calls,
or from the VSOS Shell command line.

An example of a 3-channel source that may need to be matrixed into two
channels is the 3-channel analog audio input driver AUI3ADC.DL3.

This package consists of the following programs:

Name    Description
FtO3To2 3-channel to 2-channel matrixer that connects to stdaudioout
FtI3To2 3-channel to 2-channel matrixer that connects to stdaudioin
Set3To2 User program to set and display parameters for the matrixer

The filter is extremely lightweight. The size of the driver is less than 400
instruction words, and for 48 kHz audio the CPU usage is approximately
1.3/0.7 MIPS for 32-bit/16-bit data, respectively.

Note:
This driver handles all 32 bits when run with 32-bit data. When 16-bit
data is used, internal calculations are done using 32 bits, then results
are rounded to 16 bits.

Note:
The source code is the same for both FtO3To2 and FtI3To2. For
FtO3To2, the project defines the preprocessor symbol USE_STDAUDIOOUT,
and for FtI3To2, USE_STDAUDIOIN is defined. Then, code is compiled
conditionally.

Note:
More information for this driver is provided in the VS1005 VSOS Audio
Subsystem document.



Starting FtI3To2.DL3 in config.txt after activating 3-channel input
driver AUI3ADC.DL3, then setting it to output left and right channels
with an amplification factor of 1, and the third input as mono with
an amplification factor of 0.5:
# Start 3-channel audio input driver
AUI3ADC
# Set inputs to mic1, mic2, and (implicit) line1_3
RUN AuInput -r48000 mic1 mic2
# Starts matrixer from stdaudioin
FtI3To2
# Set matrix so that:
#   input ch0 -> output left (mic1)
#   input ch1 -> output right (mic2)
#   input ch2 -> both output left and right with amplification 0.5 (line1_3)
RUN Set3To2 -s1024,0,0,1024,512,512

Note: FtO3To2 is loaded and stays in memory. Because Set3To2 doesn't need to
stay in memory, it is started from config.txt with the RUN command.


Starting FtI3To2.DL3 on the command line after activating 3-channel input
driver AUI3ADC.DL3, then setting it to output left (mic1) and right (mic2)
channels with an amplification factor of 1, and the third input (line1_3)
as mono with an amplification factor of 0.5:
S:>driver +AUI3ADC s
S:>auinput -r48000 mic1 mic2
S:>driver +FtI3To2
S:>auinput
stdaudioin:      0x2573, FtI3To2::audioFile=0x0823(2083)
  ->Identify():  0x4290, auiadc::Identify returns "AUIADC"
  ->op:          0x256e, FtI3To2::audioFileOps=0x0000(0)
    ->Ioctl():   0x45dd, FtI3To2::AudioIoctl
    ->Read():    0x4646, FtI3To2::AudioRead
Sample rate:     48000
Bits per sample: 16
Buffer size:     512 16-bit words (256 16-bit stereo samples)
Buffer fill:     508 16-bit words (254 16-bit stereo samples)
Sample counter:  777466
S:>Set3To2 -i
Matrix is from 3 to 2 channels
  in ch0 to out ch0 gain   1024 ~=   1.00 ~=  +0.0dB
  in ch0 to out ch1 gain      0 ~=   0.00 ~= -99.9dB
  in ch1 to out ch0 gain      0 ~=   0.00 ~= -99.9dB
  in ch1 to out ch1 gain   1024 ~=   1.00 ~=  +0.0dB
  in ch2 to out ch0 gain   1024 ~=   1.00 ~=  +0.0dB
  in ch2 to out ch1 gain   1024 ~=   1.00 ~=  +0.0dB

Command line option for current coeffs:
  -s1024,0,0,1024,1024,1024
S:>Set3To2 -v -s1024,0,0,1024,512,512
Matrix is from 3 to 2 channels
  in ch0 to out ch0 gain   1024 ~=   1.00 ~=  +0.0dB
  in ch0 to out ch1 gain      0 ~=   0.00 ~= -99.9dB
  in ch1 to out ch0 gain      0 ~=   0.00 ~= -99.9dB
  in ch1 to out ch1 gain   1024 ~=   1.00 ~=  +0.0dB
  in ch2 to out ch0 gain    512 ~=   0.50 ~=  -6.0dB
  in ch2 to out ch1 gain    512 ~=   0.50 ~=  -6.0dB

Command line option for current coeffs:
  -s1024,0,0,1024,512,512

Unloading the FtI3To2.dl3 driver using the VSOS Shell:
S:>driver -FtI3To2

Unloading the FtO3To2.dl3 driver using the VSOS Shell:
S:>driver -FtO3To2


Example usage
-------------

Stereo line input (line1_1, line1_3) audio and mic2
mixed on top of them as mono.

S:>auinput line1_1 mic2
S:>set3to2 -v -i -s256,0,1024,1024,0,256
Matrix is from 3 to 2 channels
  in ch0 to out ch0 gain    256 ~=   0.250 ~= -12.0dB
  in ch0 to out ch1 gain      0 ~=   0.000 ~= -99.9dB
  in ch1 to out ch0 gain   1024 ~=   1.000 ~=  +0.0dB
  in ch1 to out ch1 gain   1024 ~=   1.000 ~=  +0.0dB
  in ch2 to out ch0 gain      0 ~=   0.000 ~= -99.9dB
  in ch2 to out ch1 gain    256 ~=   0.250 ~= -12.0dB

Command line option for current coeffs:
  -s256,0,1024,1024,0,256
or
  -f0.25,0,1,1,0,0.25
S:>


Starting Fti3To2.dl3 using C code: // Change name as necessary #define
  LIB_NAME "fti3to2"

  u_int16 *matrixLib = NULL;
  FILE *matrixFP = NULL;

  matrixLib = LoadLibrary(LIB_NAME);
  if (!matrixLib) {
    printf("Cannot load " LIB_NAME ".dl3 library\n");
    goto finally;
  }
  matrixFP = stdaudioout;

Note that if you have started FtO3To2/FtI3To2 from config.txt, you don't
need to open it from your software, but instead you can directly send
ioctl() calls to stdaudioout/stdaudioin.



Closing the driver:
  finally:
  if (matrixLib) {
    DropLibrary(matrixLib);
    matrixLib = NULL;
  }




Matrix coefficients:

The matrix coefficients are ordered in such a way that destination
indices run faster than source indices. Thus, for a 3-input 2-output
matrix, the order of the coefficients is:
- Input 0 to Output 0 (L) coefficient
- Input 0 to Output 1 (R) coefficient
- Input 1 to Output 0 (L) coefficient
- Input 1 to Output 1 (R) coefficient
- Input 2 to Output 0 (L) coefficient
- Input 2 to Output 1 (R) coefficient

The coefficients are 16-bit signed integers, scaled so that value 1024
corresponds to gain factor 1.0, and value 0 corresponds to gain 0.0. The
limits are -32768 for a gain of -32, and 32767 for a gain of just under 32.



Data structures:

If using an earlier version than VSOS 3.67, the following data structures
are not yet in aucommon.h, so you need to add this to your source code:

#ifndef IOCTL_AUDIO_GET_MATRIX_DIM

#define IOCTL_AUDIO_GET_MATRIX_DIM	330
#define IOCTL_AUDIO_SET_MATRIX_DIM	331
#define IOCTL_AUDIO_GET_MATRIX_COEFF	332
#define IOCTL_AUDIO_SET_MATRIX_COEFF	333

#define MATRIX_SCALE 1024

#endif /* !IOCTL_AUDIO_GET_MATRIX_DIM */




IOCTL Controls:
  All ioctl controls except those listed here are forwarded to the underlying
  audio driver.

  Read current matrixer source and destination dimensions:
    s_int16 matrixDim = ioctl(matrixFP, IOCTL_AUDIO_GET_MATRIX_DIM, NULL);
    if (matrixDim<0) {
      printf("Fail\n);
    } else {
      int fromCh = (matrixDim>>8) & 0xff; /* Number of source channels */
      int toCh = matrixDim & 0xff;        /* Number of destination channels */
      int matrixSize = fromCh*toCh;       /* Size of conversion matrix */
    }

  Set matrixer source and destination dimensions. Note that with this driver,
  only 3 source and 2 destination channels are supported, so 0x0302 is the
  only valid parameter:
    if (ioctl(matrixFP, IOCTL_AUDIO_GET_MATRIX_DIM, (void *)0x0302) != S_OK) {
      printf("Fail\n");
    }

  Read current matrix to vector. Note that the number of elements written to
  the target vector is matrixSize from the IOCTL_AUDIO_GET_MATRIX_DIM example:
    s_int16 matrixCoeff[6];
    if (ioctl(matrixFp, IOCTL_AUDIO_GET_MATRIX_COEFF, matrixCoeff) != S_OK) {
      printf("Fail\n);
    }

  Set matrix from vector. Note that the number of elements read from the
  source vector is matrixSize from the IOCTL_AUDIO_GET_MATRIX_DIM example:
    s_int16 matrixCoeff[6];
    if (ioctl(matrixFp, IOCTL_AUDIO_SET_MATRIX_COEFF, matrixCoeff) != S_OK) {
      printf("Fail\n);
    }


License:
This code may be used freely in any product containing one or more ICs
by VLSI Solution.


Disclaimer:
No guarantee is given for the usability of this code.


History:
2023-02-28 HH 1.00  First release.
