📄 rt_2band_eq.c
字号:
//
// Project: Experiment 5.7.8: DSP/BIOS implementation 2-band equalizer in real-time - Chapter 5
// File name: rt_2band_eq.c
//
// Description: This is the test file for the example of real-time IIR using DSPBIOS
//
// For the book "Real Time Digital Signal Processing:
// Implementation and Application, 2nd Ed"
// By Sen M. Kuo, Bob H. Lee, and Wenshun Tian
// Publisher: John Wiley and Sons, Ltd
//
// Tools used: CCS v.2.12.07
// TMS320VC5510 DSK Rev-C
//
//
//
// This example demonstrates the use of LIO drivers with PIPs and the
// lio_pip adapter code.
//
// The application performs IIR filter loopback in real-time as a two-band
// equalizer, that reads audio data from rx PIP connected to an input LIO
// channel, the data is boosted or attenuated by the equalizer and then written
// back out to a PIP connected to an output LIO channel. Every 20 sec, the
// high band and the low band equalizer coefficients are switched.
//
// The following objects need to be created in the DSP/BIOS
// configuration for this application:
//
// 1 A SWI object named swiAudioProcess.
// Configure the function as _audioProcess and the mailbox value as 3.
//
// 2 Two PIP objects, one named pipTx, the other pipRx. The length of the
// buffers should be the same and. Our example requires 128.
// See the comments by the declarations below of pipTx and pipRx for the
// writer and reader notify function settings.
//
// 3 The period object controlled by the timer and SWI that calls the
// function switchBand() to change upper and lower band coefficients for
// a given time.
//
#include <math.h>
#include <std.h>
#include <pip.h>
#include <swi.h>
#include <sys.h>
#include <lio.h>
#include <plio.h>
#include "dsk5510_led.h"
// Set CONTROLLER_FXN_TABLE in the linker command file
#define CONTROLLER_FXN_TABLE DSK5510_DMA_AIC23_ILIO
extern LIO_Fxns CONTROLLER_FXN_TABLE;
static LIO_Fxns *controller = &CONTROLLER_FXN_TABLE;
extern PIP_Obj pipRx; // writerNotify -> PLIO_rxPrime(plioRx)
// readerNotify -> SWI_andn(swiEcho,1)
extern PIP_Obj pipTx; // writerNotify -> SWI_andn(swiEcho,2)
// readerNotify -> PLIO_txPrime(plioTx)
// 'plioRx' and 'plioTx' objects will be initialized by PLIO_new().
PLIO_Obj plioRx, plioTx;
// Codec configuration settings
#include "dsk5510_aic23.h"
DSK5510_AIC23_Config config = { \
0x0017, /* 0 DSK5510_AIC23_LEFTINVOL Left line input channel volume */ \
0x0017, /* 1 DSK5510_AIC23_RIGHTINVOL Right line input channel volume */\
0x01f9, /* 2 DSK5510_AIC23_LEFTHPVOL Left channel headphone volume */ \
0x01f9, /* 3 DSK5510_AIC23_RIGHTHPVOL Right channel headphone volume */ \
0x0010, /* 4 DSK5510_AIC23_ANAPATH Analog audio path control */ \
0x0000, /* 5 DSK5510_AIC23_DIGPATH Digital audio path control */ \
0x0000, /* 6 DSK5510_AIC23_POWERDOWN Power down control */ \
0x0043, /* 7 DSK5510_AIC23_DIGIF Digital audio interface format */ \
0x008D, /* 8 DSK5510_AIC23_SAMPLERATE Sample rate control */ \
0x0001 /* 9 DSK5510_AIC23_DIGACT Digital interface activation */ \
};
// IIR filter related variables
#include "asmIIR.h"
#define SECTIONS 2 // Number of 2nd order sections
short C[SECTIONS*5]; // Filter coefficients obtained from example 5.14 MATLAB FDATool
// C[]=A[i][1], A[i][2], B[i][2], B[i][0], B[i][1]...
short w[SECTIONS*2]; // Filter delay line
// w[]=w[i][n-1],w[i+1][n-1],...,w[i][n-2],w[i+1][n-2],...
#define SIZE 128 // This size must be the same as the PIP of the DSP/BIOS setting
// for stereo settings
short in[SIZE/2],out[SIZE/2]; // SIZE/2 is due to we only work on a single channel
double gain200[13][2]={ // Lower band parameter at 200 Hz
// rz rp
{0.8900, 0.8000}, // -6 dB
{0.8775, 0.8000}, // -5 dB
{0.8640, 0.8000}, // -4 dB
{0.8495, 0.8000}, // -3 dB
{0.8340, 0.8000}, // -2 dB
{0.8174, 0.8000}, // -1 dB
{0.8000, 0.8000}, // 0 dB
{0.8000, 0.8174}, // 1 dB
{0.8000, 0.8340}, // 2 dB
{0.8000, 0.8495}, // 3 dB
{0.8000, 0.8640}, // 4 dB
{0.8000, 0.8775}, // 5 dB
{0.8000, 0.8900}}; // 6 dB
double gain1000[13][2]={ // Upper band parameter at 1000 Hz
// rz rp
{0.9048, 0.8000}, // -6 dB
{0.8925, 0.8000}, // -5 dB
{0.8784, 0.8000}, // -4 dB
{0.8627, 0.8000}, // -3 dB
{0.8445, 0.8000}, // -2 dB
{0.8238, 0.8000}, // -1 dB
{0.8000, 0.8000}, // 0 dB
{0.8000, 0.8238}, // 1 dB
{0.8000, 0.8445}, // 2 dB
{0.8000, 0.8627}, // 3 dB
{0.8000, 0.8784}, // 4 dB
{0.8000, 0.8925}, // 5 dB
{0.8000, 0.9048}}; // 6 dB
short bandFlag;
enum {
NEG_6dB=0,NEG_5dB,NEG_4dB,NEG_3dB,NEG_2dB,NEG_1dB,
ZERO_dB,POS_1dB,POS_2dB,POS_3dB,POS_4dB,POS_5dB,POS_6dB
};
static void coefGen(double (*gainTbl)[2], short gain, short *c, float freq);
void switchBand();
void main()
{
// Initializes the AIC23 device
DSK5510_DMA_AIC23_init();
// AIC23 configures, if parameter is NULL
// Open AIC23 for 8 kHz sampling rate, Line-in, 16-bit data
DSK5510_AIC23_openCodec(0, &config);
// Link the PIPs to LIO channels
PLIO_new(&plioRx, &pipRx, LIO_INPUT, controller, NULL);
PLIO_new(&plioTx, &pipTx, LIO_OUTPUT, controller, NULL);
//
// Prime the transmit side with buffers of silence.
// The transmitter should be started before the receiver.
// This results in input-to-output latency being one full
// buffer period if the pipes is configured for 2 frames.
//
PLIO_txStart(&plioTx, PIP_getWriterNumFrames(&pipTx), 0);
// Prime the receive side with empty buffers to be filled.
PLIO_rxStart(&plioRx, PIP_getWriterNumFrames(&pipRx));
// Initialize two-band equalizer coefficients
bandFlag = 1;
switchBand();
}
//
// This function (swiAudioProcess) is executed from DSP/BIOS SWI thread
// created statically with the DSP/BIOS configuration tool.
//
// The PLIO adapter posts the swi when an input PIP has a buffer of data
// and the output PIP has an empty buffer to put new data into.
//
// This function passes the input PIP to the sample rate convertor for
// sample rate decimation, process, and interpolation, and then places the
// processed and interpolated samples to output PIP.
//
Void audioProcess(Void)
{
short *src, *dst, size, i;
// Get the full rx buffer from the receive PIP
PIP_get(&pipRx);
src = PIP_getReaderAddr(&pipRx);
size = PIP_getReaderSize(&pipRx) * sizeof(short);
// Get the empty tx buffer from the transmit PIP
PIP_alloc(&pipTx);
dst = PIP_getWriterAddr(&pipTx);
// Since we are single IIR, we only use one channel data
// the size represents stereo, so we divide it by 2.
for(i=0; i<(size>>1); i++)
{
in[i] = *src++; // Get left input channel
src++; // Skip right input channel
}
// Filter a block of samples, size/2 for mono channel IIR
asmIIR(in,(size>>1),out,C,SECTIONS,w);
for(i=0; i<(size>>1); i++)
{
*dst++ = out[i]; // Output to left channel
*dst++ = out[i]; // Copy data to right channel as well
}
// Record the amount of actual data being sent
PIP_setWriterSize(&pipTx, PIP_getReaderSize(&pipRx));
// Free the receive buffer, put the transmit buffer
PIP_free(&pipRx);
PIP_put(&pipTx);
}
// Generate coefficient using the following equations
// b = [1, -2*rz*cos(w), rz*rz];
// a = [1, -2*rp*cos(w), rp*rp];
// w = 2*PI*freq/F: F = 8000Hz
static void coefGen(double (*gainTbl)[2], short gain, short *c, float freq)
{
double rz,rp,temp,omega;
rz = gainTbl[gain][0];
rp = gainTbl[gain][1];
omega = 2.0*3.1415926*freq/8000.0; // This example is for 8000 Hz samping rate
c[3] = 0x4000;
temp = -2.0*rz*cos(omega);
c[4] = (short)(temp*16384.0+0.5);
c[2] = (short)(rz*rz*16384.0+0.5);
temp = -2.0*rp*cos(omega);
c[0] = (short)(temp*16384.0+0.5);
c[1] = (short)(rp*rp*16384.0+0.5);;
}
// Set and switch equalizer band coefficients
// This function shows how to change the equalizer gain at run-time.
void switchBand()
{
short i;
// Initialize IIR filter delay line
for (i=0; i<SECTIONS*2;i++)
{
w[i] = 0;
}
if (bandFlag)
{
// Generate filter coefficients for high band
coefGen(gain1000, NEG_6dB, &C[0], 1000);
// Generate filter coefficients for low band
coefGen(gain200, POS_6dB, &C[5], 200);
bandFlag = 0;
}
else
{
// Generate filter coefficients for high band
coefGen(gain1000, POS_6dB, &C[0], 1000);
// Generate filter coefficients for low band
coefGen(gain200, NEG_6dB, &C[5], 200);
bandFlag = 1;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -