/************************************************************************************* DEPARTMENT OF ELECTRICAL AND ELECTRONIC ENGINEERING IMPERIAL COLLEGE LONDON EE 3.19: Real Time Digital Signal Processing Dr Paul Mitcheson and Daniel Harvey PROJECT: Frame Processing ********* ENHANCE. C ********** Shell for speech enhancement Demonstrates overlap-add frame processing (interrupt driven) on the DSK. ************************************************************************************* By Danny Harvey: 21 July 2006 Updated for use on CCS v4 Sept 2010 ************************************************************************************/ /* * You should modify the code so that a speech enhancement project is built * on top of this template. */ /**************************** Pre-processor statements ******************************/ // library required when using calloc #include // Included so program can make use of DSP/BIOS configuration tool. #include "dsp_bios_cfg.h" /* The file dsk6713.h must be included in every program that uses the BSL. This example also includes dsk6713_aic23.h because it uses the AIC23 codec module (audio interface). */ #include "dsk6713.h" #include "dsk6713_aic23.h" // math library (trig functions) #include /* Some functions to help with Complex algebra and FFT. */ #include "cmplx.h" #include "fft_functions.h" // Some functions to help with writing/reading the audio ports when using interrupts. #include #define WINCONST 0.85185 /* 0.46/0.54 for Hamming window */ #define FSAMP 8000.0 /* sample frequency, ensure this matches Config for AIC */ #define FFTLEN 256 /* fft length = frame length 256/8000 = 32 ms*/ #define NFREQ (1+FFTLEN/2) /* number of frequency bins from a real FFT */ #define OVERSAMP 4 /* oversampling ratio (2 or 4) */ #define FRAMEINC (FFTLEN/OVERSAMP) /* Frame increment */ #define CIRCBUF (FFTLEN+FRAMEINC) /* length of I/O buffers */ #define FRAME_TIME 2.5 #define MAX_COUNT 20000 #define MAX_FLOAT 3.4E+38 #define OUTGAIN 16000.0 /* Output gain for DAC */ #define INGAIN (1.0/16000.0) /* Input gain for ADC */ #define NUM_M 4 // PI defined here for use in your code #define PI 3.141592653589793 #define TFRAME FRAMEINC/FSAMP /* time between calculation of each frame */ /******************************* Global declarations ********************************/ /* Audio port configuration settings: these values set registers in the AIC23 audio interface to configure it. See TI doc SLWS106D 3-3 to 3-10 for more info. */ DSK6713_AIC23_Config Config = { \ /**********************************************************************/ /* REGISTER FUNCTION SETTINGS */ /**********************************************************************/\ 0x0017, /* 0 LEFTINVOL Left line input channel volume 0dB */\ 0x0017, /* 1 RIGHTINVOL Right line input channel volume 0dB */\ 0x01f9, /* 2 LEFTHPVOL Left channel headphone volume 0dB */\ 0x01f9, /* 3 RIGHTHPVOL Right channel headphone volume 0dB */\ 0x0011, /* 4 ANAPATH Analog audio path control DAC on, Mic boost 20dB*/\ 0x0000, /* 5 DIGPATH Digital audio path control All Filters off */\ 0x0000, /* 6 DPOWERDOWN Power down control All Hardware on */\ 0x0043, /* 7 DIGIF Digital audio interface format 16 bit */\ 0x008d, /* 8 SAMPLERATE Sample rate control 8 KHZ-ensure matches FSAMP */\ 0x0001 /* 9 DIGACT Digital interface activation On */\ /**********************************************************************/ }; typedef struct { complex *spec; float mag_avg; } Spectrum; // Codec handle:- a variable used to identify audio interface DSK6713_AIC23_CodecHandle H_Codec; float *inbuffer, *outbuffer; /* Input/output circular buffers */ float *inframe, *outframe; /* Input and output frames */ float *inwin, *outwin; /* Input and output windows */ float ingain, outgain; /* ADC and DAC gains */ float cpufrac; /* Fraction of CPU time used */ complex *fft_out; /* FFT output */ complex* noise; volatile int io_ptr=0; /* Input/ouput pointer for circular buffers */ volatile int frame_ptr=0; /* Frame pointer */ volatile int frame_ctr =0; volatile float lambda = 0.05; volatile float alpha = 20; double avg = 0; Spectrum M[NUM_M]; /******************************* Function prototypes *******************************/ void init_hardware(void); /* Initialize codec */ void init_HWI(void); /* Initialize hardware interrupts */ void ISR_AIC(void); /* Interrupt service routine for codec */ void process_frame(void); /* Frame processing routine */ /********************************** Main routine ************************************/ void main() { int k; // used in various for loops /* Initialize and zero fill arrays */ inbuffer = (float *) calloc(CIRCBUF, sizeof(float)); /* Input array */ outbuffer = (float *) calloc(CIRCBUF, sizeof(float)); /* Output array */ inframe = (float *) calloc(FFTLEN, sizeof(float)); /* Array for processing*/ outframe = (float *) calloc(FFTLEN, sizeof(float)); /* Array for processing*/ inwin = (float *) calloc(FFTLEN, sizeof(float)); /* Input window */ outwin = (float *) calloc(FFTLEN, sizeof(float)); /* Output window */ fft_out = (complex *) calloc(FFTLEN, sizeof(complex)); /* FFT Output */ /* initialize board and the audio port */ init_hardware(); /* initialize hardware interrupts */ init_HWI(); /* initialize algorithm constants */ for (k=0;k= (CIRCBUF/FRAMEINC)) frame_ptr=0; /* save a pointer to the position in the I/O buffers (inbuffer/outbuffer) where the data should be read (inbuffer) and saved (outbuffer) for the purpose of processing */ io_ptr0=frame_ptr * FRAMEINC; /* copy input data from inbuffer into inframe (starting from the pointer position) */ m=io_ptr0; for (k=0;k= CIRCBUF) m=0; /* wrap if required */ } /************************* DO PROCESSING OF FRAME HERE **************************/ for (k = 0; k < FFTLEN; ++k) { fft_out[k].i = 0.0; fft_out[k].r = inframe[k]; } fft(FFTLEN, fft_out); for(k = 0; k < FFTLEN; ++k) { avg += cabs(fft_out[k]); } avg /= FFTLEN; if(avg < M[0].mag_avg) { M[0].mag_avg = avg; for(k = 0; k < FFTLEN; ++k) { M[0].spec[k] = fft_out[k]; } } for(k = 0; k < NUM_M; ++k) { if (M[k].mag_avg < min_avg) { min_avg = M[k].mag_avg; min_index = k; } } noise = M[min_index].spec; for (k = 0; k < FFTLEN; ++k) { float g; mag_N_X = 1 - cabs(noise[k])/cabs(fft_out[k]); g = mag_N_X > lambda ? mag_N_X : lambda; fft_out[k].r *= g; fft_out[k].i *= g; } ifft(FFTLEN, fft_out); if(frame_ctr > MAX_COUNT-1) { int i; frame_ctr = 0; M[0].spec = M[NUM_M-1].spec; for(k = NUM_M-1; k > 0; --k) { M[k] = M[k-1]; } M[0].mag_avg = MAX_FLOAT; for(i = 0; i < FFTLEN; ++i) { M[0].spec[i].r = MAX_FLOAT; M[0].spec[i].i = MAX_FLOAT; } } for (k = 0; k < FFTLEN; ++k) { outframe[k] = fft_out[k].r; } /********************************************************************************/ /* multiply outframe by output window and overlap-add into output buffer */ m=io_ptr0; for (k=0;k<(FFTLEN-FRAMEINC);k++) { /* this loop adds into outbuffer */ outbuffer[m] = outbuffer[m]+outframe[k]*outwin[k]; if (++m >= CIRCBUF) m=0; /* wrap if required */ } for (;k= CIRCBUF) io_ptr=0; frame_ctr++; } /************************************************************************************/