Definition in file CONCEPTION/AEC/main.c.
#include <stdio.h>
#include <string.h>
Go to the source code of this file.
Defines | |
#define | BLOCK_SIZE 64 |
#define | NUM_TAPS 256 |
#define | ROUND_DIV(a, b) (((a) + ((b)/2))/(b)) |
#define | SQ(x) ((x)*(x)) |
Functions | |
void | echo_cancel (const short *out_buf, const short *in, size_t block_size, int *filter_q16, size_t num_taps, short *echo_cancelled_in) |
int | main (int argc, char *_argv[]) |
#define BLOCK_SIZE 64 |
#define NUM_TAPS 256 |
#define ROUND_DIV | ( | a, | |||
b | ) | (((a) + ((b)/2))/(b)) |
#define SQ | ( | x | ) | ((x)*(x)) |
void echo_cancel | ( | const short * | out_buf, | |
const short * | in, | |||
size_t | block_size, | |||
int * | filter_q16, | |||
size_t | num_taps, | |||
short * | echo_cancelled_in | |||
) |
Definition at line 55 of file CONCEPTION/AEC/main.c.
Referenced by main().
00056 { 00057 const short *cur_out = &out_buf[block_size-1]; 00058 const short *cur_in = &in[block_size-1]; 00059 short *cur_in_ec = &echo_cancelled_in[block_size-1]; 00060 00061 const short *out_p; 00062 int out_norm_sq_p16; /* The value is * 2^16 */ 00063 00064 /* Calculate initial norm squared of output vector */ 00065 out_norm_sq_p16 = 0; 00066 for (out_p = &out_buf[block_size+num_taps-1]; out_p != &out_buf[block_size-1]; --out_p) 00067 out_norm_sq_p16 += SQ(ROUND_DIV((int) *out_p, 1 << 8)); 00068 00069 do 00070 { 00071 int *filter_q16_p; 00072 int echo_est_q16; 00073 short echo_est; 00074 00075 /* Caculate echo estimate for this sample using output data */ 00076 echo_est_q16 = 0; 00077 for (out_p = &cur_out[num_taps-1], filter_q16_p = &filter_q16[num_taps-1]; out_p != cur_out; --out_p, --filter_q16_p) 00078 echo_est_q16 += (int) (*out_p)*(*filter_q16_p); 00079 00080 echo_est = ROUND_DIV(echo_est_q16, 1 << 16); 00081 00082 /* Echo cancelled input is simply input minus echo estimate 00083 * Round echo_est_q16 to nearest int when convering to short 00084 * This can also be interpreted as the error term, which 00085 * is used for the NLMS correction below 00086 */ 00087 *cur_in_ec = *cur_in - echo_est; 00088 00089 /* Update norm squared of output vector */ 00090 out_norm_sq_p16 += SQ(ROUND_DIV((int) cur_out[0], 1<<8)) - SQ(ROUND_DIV((int) cur_out[num_taps], 1<<8)); 00091 00092 /* Update filter tap weights using NLMS correction */ 00093 if (out_norm_sq_p16 != 0) 00094 { 00095 for (out_p = &cur_out[num_taps-1], filter_q16_p = &filter_q16[num_taps-1]; out_p != cur_out; --out_p, --filter_q16_p) 00096 *filter_q16_p += ROUND_DIV((int) *cur_in_ec * (int) *out_p, out_norm_sq_p16); 00097 } 00098 } while (cur_out--, cur_in_ec--, cur_in-- != in); 00099 }
int main | ( | int | argc, | |
char * | _argv[] | |||
) |
Definition at line 102 of file CONCEPTION/AEC/main.c.
References BLOCK_SIZE, echo_cancel(), and NUM_TAPS.
00103 { 00104 short out_buf[BLOCK_SIZE+NUM_TAPS]; 00105 int filter_q16[NUM_TAPS]; 00106 00107 memset(out_buf, 0, sizeof (out_buf)); 00108 memset(filter_q16, 0, sizeof (filter_q16)); // The filter tap weights must 00109 // initially be zero!! 00110 00111 while (!kbhit()) 00112 { 00113 short in[BLOCK_SIZE]; 00114 short echo_cancelled_in[BLOCK_SIZE]; 00115 00116 // Output BLOCK_SIZE samples to the speaker from outBuf and input 00117 // BLOCK_SIZE samples into inBuf from the microphone. 00118 play_record_local(outBuf, in, BLOCK_SIZE); 00119 00120 // Cancel the echo of out present on in using the outBuf buffered 00121 // samples. Adaptively updates the filter tap weights as it goes. 00122 echo_cancel(out_buf, in, BLOCK_SIZE, filter_q16, NUM_TAPS, echo_cancelled_in); 00123 00124 // Shift samples in preparation to get more data... 00125 memmove (& out_buf[BLOCK_SIZE], &out_buf[0], sizeof (out_buf) - sizeof (in)); 00126 00127 // Send the echo cancelled input and receive to/from remote source 00128 play_record_remote(echo_cancelled_in, out, BLOCK_SIZE); 00129 } 00130 }