⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rt_2band_eq.c

📁 CHP 5 - Real-Time Digital Signal Processing: Implementations and Applications, Second Edition by Sen
💻 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 + -