I start with the "simple" task of down sampling PCM using ssrc from lib_src (add to Makefile: USED_MODULES += lib_src). This could become what was planned as AN00230, i.e. adding ssrc to the usb audio framework.
So, mission is to down sample 352/384 > 192, but lets start with what should work out-of-the box, 176/192 > 96.
The code below compiles (using build app_usb_aud_xk_216_mc_2i10o10xxxxxx). It detects different PCM sample rates from usb (checked with LRCLK, running foobar, ASIO, TUSBAudio). However, xDAC_SDn is 0.
* Do not understand how to properly execute ssrc_init(...) within the framework.
* Moreover, lacking proper understanding for where to intercept the audio stream in order to perform the sample rate conversion. In the code below it's in the same place as was used for user_dsp example in the thread mentioned below (adding dsp functionality to the framework).
Have commented the code with thoughts and questions and hope that we can sort this out and get an additional application example for the usb framework.
* I imagine that we need to intercept the audiostream between the decoupler and the audio driver in a similar fashion as discussed in
thread. In audio.xc we declare a global streaming chanend c_src_glob and perform init. However, there is probably more to be done in the init in order to set up ssrc with ssrc_init().
Code: Select all
...
#include "print.h"
// Datapath to SRC tasks. We use a global channel end to avoid plumbing all through the USB audio stack
#include "user_src.h"
unsafe streaming chanend c_src_glob;
void src_init_chanend(streaming chanend c_src) {
// todo: how/where do the ssrc_init(...)
// Placed here produces error: ssrc_ctrl undeclared. But user_src.h is included.
// ssrc_init(FS_CODE_192, FS_CODE_96, ssrc_ctrl, SSRC_CHANNELS_PER_INSTANCE, SSRC_N_IN_SAMPLES, OFF);
unsafe {
c_src_glob = (unsafe streaming chanend) c_src;
}
}
static unsigned samplesOut[NUM_USB_CHAN_OUT];
...
* Also in audio.xc, streaming decoupler > ssrc > audiodriver, however big question mark
Code: Select all
...
#else
inuint(c_out);
#endif
unsafe{
/* SSRC.
* Is this correct? ssrc needs min 4 samples, We have stereo from usb, i.e. sending 8 samples to
* the task. Performing decimation by 2 so I expect only 4 samples back. But I dont quite understand how I
* should express it in the framework in order to correctly match a fixed samplerate of 192k for audiodriver (i2s)
* and still allow for higher samplerates from the USB host?
* lib_src user guide page 5 discusses the ratio between streaming in and out of ssrc. In the framework that would
* corrspond to different word clocks for decoupler and audiodriver, respectively. Is it possible? Have I completely
* misunderstood where ssrc should be placed in the audio path of the framework?!
* The final code here will only run when samplerate is above the fixed
* samplerate of the DSP. At all other samplerates, the DSP can perform the conversions
*/
// if (samplerate > 192000) {
// do something with the clock?
// set samplerate to 192000 and downsample with ssrc
for(int i=0; i<(SSRC_N_IN_SAMPLES*SSRC_CHANNELS_PER_INSTANCE); i++) c_src_glob <: samplesOut[i]; // 4x2=8
for(int i=0; i<(SSRC_N_OUT_SAMPLES*SSRC_CHANNELS_PER_INSTANCE); i++) c_src_glob :> samplesOut[i]; // 2*2=4
// }
}
#if NUM_USB_CHAN_IN > 0
...
* user_main.h should be the same, it defines the streaming channels and places it on a tile. Since we intend to run in sync we do not need to use fancy buffering as in AN00231 and asrc, or am I wrong?
Code: Select all
#ifndef _USER_MAIN_H_
#define _USER_MAIN_H_
#include "customdefines.h"
#include "user_src.h"
#define USER_MAIN_DECLARATIONS \
streaming chan chan_src; \
#define USER_MAIN_CORES \
on tile[AUDIO_IO_TILE]: user_src(chan_src); \
on tile[AUDIO_IO_TILE]: src_init_chanend(chan_src);
#endif /* _USER_MAIN_H_ */
* user_src.h and user_src.xc (with user_main.h, placed in /src/extensions):
Code: Select all
#ifndef __USER_SRC_H__
#define __USER_SRC_H__
#ifdef __XC__
#include <xs1.h>
#include <src.h>
#define SSRC_CHANNELS_PER_INSTANCE 2 // USB stereo, output from ssrc is composed of left and right samples, interleaved
#define SSRC_N_IN_SAMPLES 4 // Min value of samples for ssrc
#define SSRC_N_OUT_CHANNELS SSRC_CHANNELS_PER_INSTANCE // Still stereo
#define SSRC_N_OUT_SAMPLES 2 // ??? Trying to do decimation by 2, i.e 4/2 = 2...
//SSRC_STACK_LENGTH_MULT is determined in ssrc.h
void user_src(streaming chanend c_src);
void src_init_chanend(streaming chanend c_src);
#endif
#endif /* __USER_SRC_H_ */
Code: Select all
#include <xs1.h>
#include "user_src.h"
// lib_src user guide, XM010383, states that following structures must be used for ssrc
ssrc_state_t ssrc_state[SSRC_CHANNELS_PER_INSTANCE];
// todo: Getting error: size of array not constant
//int ssrc_stack[SSRC_CHANNELS_PER_INSTANCE][SSRC_STACK_LENGTH_MULT * SSRC_N_IN_SAMPLES];
int ssrc_stack[2][2*4*4];
ssrc_ctrl_t ssrc_ctrl[SSRC_CHANNELS_PER_INSTANCE];
// todo: src_init_chanend is performed in audio.xc, but shouldn't it be here?
/*
void src_init_chanend(streaming chanend c_src) {
ssrc_init(FS_CODE_192, FS_CODE_96, ssrc_ctrl, SSRC_CHANNELS_PER_INSTANCE, SSRC_N_IN_SAMPLES, OFF);
unsafe {
c_src_glob = (unsafe streaming chanend) c_src;
}
}
*/
void user_src(streaming chanend c_src) {
int samps_src_pre[SSRC_N_IN_SAMPLES*SSRC_CHANNELS_PER_INSTANCE] = {0};
int samps_src_post[SSRC_N_OUT_SAMPLES*SSRC_CHANNELS_PER_INSTANCE] = {0};
int n_out_ssrc = 0; // return value from ssrc_process, expecting 8/2 = 4 for each call
// left[0], right[0], left[1], right[1], oldest first
while(1) {
//Sample exchange
for(int i = 0; i < SSRC_N_IN_SAMPLES; i++) c_src :> samps_src_pre[i];
for(int i = 0; i < SSRC_N_OUT_SAMPLES; i++) c_src <: samps_src_post[i];
// Process data
// Sending interleaved data in and getting sample rate converted interleaved data out
n_out_ssrc = ssrc_process(samps_src_pre, samps_src_post, ssrc_ctrl);
}
}