aboutsummaryrefslogtreecommitdiffstats
path: root/Project/RTDSP/enhance.c
diff options
context:
space:
mode:
Diffstat (limited to 'Project/RTDSP/enhance.c')
-rw-r--r--Project/RTDSP/enhance.c301
1 files changed, 301 insertions, 0 deletions
diff --git a/Project/RTDSP/enhance.c b/Project/RTDSP/enhance.c
new file mode 100644
index 0000000..9829c00
--- /dev/null
+++ b/Project/RTDSP/enhance.c
@@ -0,0 +1,301 @@
+/*************************************************************************************
+ 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 <stdlib.h>
+// 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 <math.h>
+
+/* 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 <helper_functions_ISR.h>
+
+#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 1000
+#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 */
+volatile int io_ptr=0; /* Input/ouput pointer for circular buffers */
+volatile int frame_ptr=0; /* Frame pointer */
+volatile int frame_ctr =0;
+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<FFTLEN;++k)
+ {
+ inwin[k] = sqrt((1.0-WINCONST*cos(PI*(2*k+1)/FFTLEN))/OVERSAMP);
+ outwin[k] = inwin[k];
+ }
+ ingain=INGAIN;
+ outgain=OUTGAIN;
+
+ for (k = 0; k < NUM_M; ++k)
+ {
+ int i;
+ M[k].spec = (complex *) calloc(FFTLEN, sizeof(complex));
+ M[k].mag_avg = MAX_FLOAT;
+ for(i = 0; i < FFTLEN; ++i) {
+ M[k].spec[i].r = MAX_FLOAT;
+ M[k].spec[i].i = MAX_FLOAT;
+ }
+ }
+
+
+ /* main loop, wait for interrupt */
+ while(1) process_frame();
+}
+
+/********************************** init_hardware() *********************************/
+void init_hardware()
+{
+ // Initialize the board support library, must be called first
+ DSK6713_init();
+
+ // Start the AIC23 codec using the settings defined above in config
+ H_Codec = DSK6713_AIC23_openCodec(0, &Config);
+
+ /* Function below sets the number of bits in word used by MSBSP (serial port) for
+ receives from AIC23 (audio port). We are using a 32 bit packet containing two
+ 16 bit numbers hence 32BIT is set for receive */
+ MCBSP_FSETS(RCR1, RWDLEN1, 32BIT);
+
+ /* Configures interrupt to activate on each consecutive available 32 bits
+ from Audio port hence an interrupt is generated for each L & R sample pair */
+ MCBSP_FSETS(SPCR1, RINTM, FRM);
+
+ /* These commands do the same thing as above but applied to data transfers to the
+ audio port */
+ MCBSP_FSETS(XCR1, XWDLEN1, 32BIT);
+ MCBSP_FSETS(SPCR1, XINTM, FRM);
+
+
+}
+/********************************** init_HWI() **************************************/
+void init_HWI(void)
+{
+ IRQ_globalDisable(); // Globally disables interrupts
+ IRQ_nmiEnable(); // Enables the NMI interrupt (used by the debugger)
+ IRQ_map(IRQ_EVT_RINT1,4); // Maps an event to a physical interrupt
+ IRQ_enable(IRQ_EVT_RINT1); // Enables the event
+ IRQ_globalEnable(); // Globally enables interrupts
+
+}
+
+/******************************** process_frame() ***********************************/
+void process_frame(void)
+{
+ int k, m;
+ int io_ptr0;
+ avg = 0;
+ /* work out fraction of available CPU time used by algorithm */
+ cpufrac = ((float) (io_ptr & (FRAMEINC - 1)))/FRAMEINC;
+
+ /* wait until io_ptr is at the start of the current frame */
+ while((io_ptr/FRAMEINC) != frame_ptr);
+
+ /* then increment the framecount (wrapping if required) */
+ if (++frame_ptr >= (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<FFTLEN;k++)
+ {
+ inframe[k] = inbuffer[m] * inwin[k];
+ if (++m >= 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 < FFTLEN; ++k) {
+ fft_out[k] = M[0].spec[k];
+ }
+
+ ifft(FFTLEN, fft_out);
+
+ if(frame_ctr > MAX_COUNT-1) {
+ int i;
+ frame_ctr = 0;
+ free(M[NUM_M-1].spec);
+ for(k = NUM_M-1; k > 0; ++k) {
+ M[k] = M[k-1];
+ }
+ M[0].spec = (complex *) malloc(FFTLEN * sizeof(complex));
+ 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<FFTLEN;k++)
+ {
+ outbuffer[m] = outframe[k]*outwin[k]; /* this loop over-writes outbuffer */
+ m++;
+ }
+}
+/*************************** INTERRUPT SERVICE ROUTINE *****************************/
+
+// Map this to the appropriate interrupt in the CDB file
+
+void ISR_AIC(void)
+{
+ short sample;
+ /* Read and write the ADC and DAC using inbuffer and outbuffer */
+ frame_ctr++;
+ sample = mono_read_16Bit();
+ inbuffer[io_ptr] = ((float)sample)*ingain;
+ /* write new output data */
+ mono_write_16Bit((int)(outbuffer[io_ptr]*outgain));
+
+ /* update io_ptr and check for buffer wraparound */
+
+ if (++io_ptr >= CIRCBUF) io_ptr=0;
+}
+
+/************************************************************************************/