View Single Post
  #6 (permalink)  
Old 12-15-2004, 04:17 PM
Jaime Andrés Aranguren Cardona
Guest
 
Posts: n/a
Default Re: Sample Rate Conversion (Downsampling)

"Jon Harris" <[email protected]> escribió en el mensaje
news:[email protected]..
> Good suggestion. For some reason, I usually find the order is backwards

from
> what I would intuitively think!


Hello Sirs,

I tried reversing the coefficients, but that simply didn't work. This was my
original code (please excuse me for posting this long stuff here, but I
don't see any other method to let you know what I did):


// The Sample Rate Conversion Routines - Saving data, stage 1
void SrcSaveStage1 (float sample)
{
int i;
static int sampleCount;
float tmpSample;

// Update the delay line to input to SRC algo
for (i = SRC_STAGE1_N_FILT-1; i > 0; i--) {
srcStage1_Delay[i] = srcStage1_Delay[i-1];
}
srcStage1_Delay[0] = sample;

// Increment sample counter
sampleCount++;
if (sampleCount == SRC_STAGE1_N_FILT) {
// Toggle flag everytime we downsampled by 10
ToggleFlag4_9(8);
tmpSample = SrcProcessStage1(); // Process one of each M1(=10) samples,
SRC algo stage 1
SrcSaveStage2 (tmpSample); // And save for M2(4), stage 2
sampleCount = 0;
}
}

// The Sample Rate Conversion Routines - Saving data, stage 2
void SrcSaveStage2 (float sample)
{
int i;
static int sampleCount;

// Update the delay line to input to SRC algo
for (i = SRC_STAGE2_N_FILT-1; i > 0; i--) {
srcStage2_Delay[i] = srcStage2_Delay[i-1];
}
srcStage2_Delay[0] = sample;

// Increment sample counter
sampleCount++;
if (sampleCount == SRC_STAGE2_N_FILT) {
srcOut = SrcProcessStage2(); // Process one of each M1(=10) samples, SRC
algo stage 1
srcReady = true; // Set the flag
sampleCount = 0; // Restart counter
}
else {
srcReady = false; // Keep flag cleared
}
}

// The Sample Rate Conversion Routines - Processing data, stage 1
float SrcProcessStage1 (void)
{
float outSamples[SRC_STAGE1_N_FILT];
float output;
int i;

output = 0;
outSamples[0] = fir(srcStage1_Delay[0], srcStage1_1Coeffs,
srcStage1_1State, SRC_STAGE1_FILT_LEN);
outSamples[1] = fir(srcStage1_Delay[1], srcStage1_2Coeffs,
srcStage1_2State, SRC_STAGE1_FILT_LEN);
outSamples[2] = fir(srcStage1_Delay[2], srcStage1_3Coeffs,
srcStage1_3State, SRC_STAGE1_FILT_LEN);
outSamples[3] = fir(srcStage1_Delay[3], srcStage1_4Coeffs,
srcStage1_4State, SRC_STAGE1_FILT_LEN);
outSamples[4] = fir(srcStage1_Delay[4], srcStage1_5Coeffs,
srcStage1_5State, SRC_STAGE1_FILT_LEN);
outSamples[5] = fir(srcStage1_Delay[5], srcStage1_6Coeffs,
srcStage1_6State, SRC_STAGE1_FILT_LEN);
outSamples[6] = fir(srcStage1_Delay[6], srcStage1_7Coeffs,
srcStage1_7State, SRC_STAGE1_FILT_LEN);
outSamples[7] = fir(srcStage1_Delay[7], srcStage1_8Coeffs,
srcStage1_8State, SRC_STAGE1_FILT_LEN);
outSamples[8] = fir(srcStage1_Delay[8], srcStage1_9Coeffs,
srcStage1_9State, SRC_STAGE1_FILT_LEN);
outSamples[9] = fir(srcStage1_Delay[9], srcStage1_10Coeffs,
srcStage1_10State, SRC_STAGE1_FILT_LEN);

for (i = 0; i < SRC_STAGE1_N_FILT; i++) {
output += outSamples[i];
}

return output;
}

// The Sample Rate Conversion Routines - Processing data, stage 2
float SrcProcessStage2 (void)
{
float outSamples[SRC_STAGE2_N_FILT];
float output;
int i;

output = 0;
outSamples[0] = fir(srcStage2_Delay[0], srcStage2_1Coeffs,
srcStage2_1State, SRC_STAGE2_FILT_LEN);
outSamples[1] = fir(srcStage2_Delay[1], srcStage2_2Coeffs,
srcStage2_2State, SRC_STAGE2_FILT_LEN);
outSamples[2] = fir(srcStage2_Delay[2], srcStage2_3Coeffs,
srcStage2_3State, SRC_STAGE2_FILT_LEN);
outSamples[3] = fir(srcStage2_Delay[3], srcStage2_4Coeffs,
srcStage2_4State, SRC_STAGE2_FILT_LEN);

for (i = 0; i < SRC_STAGE2_N_FILT; i++) {
output += outSamples[i];
}

return output;
}

--------------------------

Every time a sample arrives (every 125 us, 8kHz sample rate), I execute
SrcSaveStage1(). In this routine I simply put the samples in the 10-tap
delay line, the one at the input of the "Polyphase Iimplementation Stage 1"
in the Simulink model. Once I have 10 samples aquired (and the delay line
full) I do the processing of it. This act of processing only when the 10
samples acquired implements the downsampling by 10 in the simulink model.
The processing is done in the SrcProcessStage1() routine. This one simply
consists on a bank of 10 FIR filters, with coefficients as defined in
Matlab, the same ones for the Simulink simulation. The input for each of the
filters is a tap from the delay line, so the input to the filter is
downsampled by 10, as desired. The output of the filters is summed up.

Once I have a sample out of the stage 1 (every 1250 uS, 800 Hz), I do the
same processing for stage 1, very similar as it was for stage 1, but with
the respective filters and downsampling factor (4).

So the final output is sampled at 200 Hz.

I think I was moving the downsampling blocks of each branch of the structure
(refer to Vaydianathan's book) BEFORE the input delay line. So I modified my
code, here it is:

--------------------------
// The Sample Rate Conversion Routines - Saving data, stage 1
void SrcSaveStage1 (float sample)
{
int i;
static int sampleCount;

// Update the delay line to input to SRC algo
for (i = SRC_STAGE1_N_FILT-1; i > 0; i--) {
srcStage1_Delay[i] = srcStage1_Delay[i-1];
}
srcStage1_Delay[0] = sample;

// Increment sample counter
sampleCount++;
if (sampleCount == SRC_STAGE1_N_FILT) {
sampleCount = 0;
}

SrcProcessStage1(); // Do the downsampling and filtering every 10 samples
}

// The Sample Rate Conversion Routines - Saving data, stage 2
void SrcSaveStage2 (float sample)
{
int i;
static int sampleCount;

// Update the delay line to input to SRC algo
for (i = SRC_STAGE2_N_FILT-1; i > 0; i--) {
srcStage2_Delay[i] = srcStage2_Delay[i-1];
}
srcStage2_Delay[0] = sample;

// Increment sample counter
sampleCount++;
if (sampleCount == SRC_STAGE2_N_FILT) {
sampleCount = 0;
}

SrcProcessStage2(); // Do the downsampling and filtering every 4 samples
}

// The Sample Rate Conversion Routines - Processing data, stage 1
void SrcProcessStage1 (void)
{
float outSamples[SRC_STAGE1_N_FILT];
float output;
int i;

static int sampleCount;

// Store data from input delay line into
// downsampling delay lines
srcStage1_Delay1[sampleCount] = srcStage1_Delay[0];
srcStage1_Delay2[sampleCount] = srcStage1_Delay[1];
srcStage1_Delay3[sampleCount] = srcStage1_Delay[2];
srcStage1_Delay4[sampleCount] = srcStage1_Delay[3];
srcStage1_Delay5[sampleCount] = srcStage1_Delay[4];
srcStage1_Delay6[sampleCount] = srcStage1_Delay[5];
srcStage1_Delay7[sampleCount] = srcStage1_Delay[6];
srcStage1_Delay8[sampleCount] = srcStage1_Delay[7];
srcStage1_Delay9[sampleCount] = srcStage1_Delay[8];
srcStage1_Delay10[sampleCount] = srcStage1_Delay[9];

sampleCount++; //Increment counter

// Once every delay line for downsampling has M1 = 10 samples,
// filter with the oldest sample on each delay line
if (sampleCount == SRC_STAGE1_N_FILT) {
// Toggle flag everytime we downsampled by 10
ToggleFlag4_9(8);

// Do the filtering
output = 0;
outSamples[0] = fir(srcStage1_Delay1[0], srcStage1_1Coeffs,
srcStage1_1State, SRC_STAGE1_FILT_LEN);
outSamples[1] = fir(srcStage1_Delay2[0], srcStage1_2Coeffs,
srcStage1_2State, SRC_STAGE1_FILT_LEN);
outSamples[2] = fir(srcStage1_Delay3[0], srcStage1_3Coeffs,
srcStage1_3State, SRC_STAGE1_FILT_LEN);
outSamples[3] = fir(srcStage1_Delay4[0], srcStage1_4Coeffs,
srcStage1_4State, SRC_STAGE1_FILT_LEN);
outSamples[4] = fir(srcStage1_Delay5[0], srcStage1_5Coeffs,
srcStage1_5State, SRC_STAGE1_FILT_LEN);
outSamples[5] = fir(srcStage1_Delay6[0], srcStage1_6Coeffs,
srcStage1_6State, SRC_STAGE1_FILT_LEN);
outSamples[6] = fir(srcStage1_Delay7[0], srcStage1_7Coeffs,
srcStage1_7State, SRC_STAGE1_FILT_LEN);
outSamples[7] = fir(srcStage1_Delay8[0], srcStage1_8Coeffs,
srcStage1_8State, SRC_STAGE1_FILT_LEN);
outSamples[8] = fir(srcStage1_Delay9[0], srcStage1_9Coeffs,
srcStage1_9State, SRC_STAGE1_FILT_LEN);
outSamples[9] = fir(srcStage1_Delay10[0], srcStage1_10Coeffs,
srcStage1_10State, SRC_STAGE1_FILT_LEN);

// Final sum of filter outputs
for (i = 0; i < SRC_STAGE1_N_FILT; i++) {
output += outSamples[i];
}

sampleCount = 0; // Restart counter (index)

SrcSaveStage2 (output); // And save for M2 = 4, stage 2
}
}

// The Sample Rate Conversion Routines - Processing data, stage 2
void SrcProcessStage2 (void)
{
float outSamples[SRC_STAGE2_N_FILT];
float output;
int i;

static int sampleCount;

// Store data from input delay line into
// downsampling delay lines
srcStage2_Delay1[sampleCount] = srcStage2_Delay[0];
srcStage2_Delay2[sampleCount] = srcStage2_Delay[1];
srcStage2_Delay3[sampleCount] = srcStage2_Delay[2];
srcStage2_Delay4[sampleCount] = srcStage2_Delay[3];

sampleCount++; //Increment counter

// Once every delay line for downsampling has M2 = 4 samples,
// filter with the oldest sample on each delay line
if (sampleCount == SRC_STAGE2_N_FILT) {
// Toggle flag everytime we downsampled by 4 (this means, by 40)
ToggleFlag4_9(7);

// Do the filtering
output = 0;
outSamples[0] = fir(srcStage2_Delay1[0], srcStage1_1Coeffs,
srcStage1_1State, SRC_STAGE1_FILT_LEN);
outSamples[1] = fir(srcStage2_Delay2[0], srcStage1_2Coeffs,
srcStage1_2State, SRC_STAGE1_FILT_LEN);
outSamples[2] = fir(srcStage2_Delay3[0], srcStage1_3Coeffs,
srcStage1_3State, SRC_STAGE1_FILT_LEN);
outSamples[3] = fir(srcStage2_Delay4[0], srcStage1_4Coeffs,
srcStage1_4State, SRC_STAGE1_FILT_LEN);

// Final sum of filter outputs
for (i = 0; i < SRC_STAGE1_N_FILT; i++) {
output += outSamples[i];
}

sampleCount = 0; // Restart counter (index)
srcReady = true; // Set the flag

srcOut = output; // Save the oufinal output data
}
else {
srcReady = false; // Clear the flag
}
}

--------------------------

Now, every 125 us I update the input delay line, and store the data from
each tap on this delay line into a delay line for downsampling. Once I have
M1 = 10 samples in the downsampling delay lines, I run my M1 = 10 filters,
taking only the oldest sample of the downsampling delay lines as input, and
sum up the result.

Then I trigger the corresponding process for the second stage, but I get the
same results as from the very beginning. Reversing the filter coefficients
does not help at all.

What else could I try, guys? I'd really appreciate if you can take a look at
my code, and help me find out where the mistakes can be, or provide me with
some reference C code.

Thanks you very much in advance,

--
Jaime Andrés Aranguren Cardona
[email protected]
SanJaaC Electronics
Soluciones en DSP
www.sanjaac.com

(Remove "nospam" from e-mail address)


Reply With Quote