Practice Linux, Alsa Speex Echo Elimination __linux

Source: Internet
Author: User
Tags assert save file sin win32 htons

A few days ago Win32 under the Speex AEC (http://blog.csdn.net/sunkwei/archive/2011/05/18/6429096.aspx), very complex, today to try to make alsa under, found very simple AH!!! First of all, put on the Audacity effect chart:

The code is simple, and the effect seems to be better than Win32.

Because the code is simple, just stick it in here.

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <alloca.h> #include < math.h> #include <alsa/asoundlib.h> #include <sys/socket.h> #include <sys/types.h> #include < netinet/in.h> #include <arpa/inet.h> #include <pthread.h> #include <assert.h> #include <speex/ speex_echo.h> #include <speex/speex_preprocess.h> #include "util_cirbuf.h" #define SAVEFILE 1 #define Listen_ PORT 7777 #define PERIOD_NUM 3 #define FRAMESIZE 160 static snd_pcm_uframes_t _period_size = 160; static unsigned int _period_bytes = 320; sock static int _sock_listen =-1, _sock_sender =-1; static struct sockaddr_in _target; static char *_target_ip; ARGV[1]//Speex obj static speexechostate *_speex_aec = 0; static Speexpreprocessstate *_speex_preprocess = 0; snd obj static snd_pcm_t *_snd_capture = 0, *_snd_playback = 0; FIFO, receive buffer, recording buffer, playback buffer static struct tea_cirbuf_t *_cbuf_recv = 0, *_cbuf_capture = 0, *_CBUF_playback = 0; recv thread static void *_thread_recv (void *p) {/** recv UDP data. And save into _CBUF_RECV/assert (_sock_listen!= -1); ASSERT (_CBUF_RECV); while (1) {char buf[4096];//each PCM packet cannot exceed struct sockaddr_in from; socklen_t fromlen = sizeof (from); int rc = Recvfrom (_s Ock_listen, buf, sizeof (BUF), 0, (struct sockaddr*), &from); if (RC < 0) {fprintf (stderr, "%s:recvfrom err/n", __func__); exit ( -1);}//Chk _cbuf_recv if (util_cbuf_space RECV) < RC) {//Todo:overflow, ERR, can actually empty the processing fprintf (stderr,%S:RECV overflow!!!!!! /n ", __func__); Exit (-1); } util_cbuf_save (_cbuf_recv, buf, RC); fprintf (stderr, "."); return 0; The static int Start_listener () {_sock_listen = socket (af_inet, SOCK_DGRAM, 0); if (_sock_listen = = 1) {fprintf (stderr, " %s:open Listen sock err/n ", __func__); Exit (-1); return-1; } struct sockaddr_in sin; sin.sin_family = af_inet; Sin.sin_port = htons (Listen_port); SIN.SIN_ADDR.S_ADDR = Inaddr_any; if (Bind (_sock_listen, (struct sockaddr*) &sin, sizeof (SIN)) < 0) {fprintf (stderr, "%s:bind Listen port%d err/n", __func__, Listen_port ); Exit (-1); return-1; }//start recv thread pthread_t th; if (pthread_create (&th, 0, _THREAD_RECV, 0)) {fprintf (stderr, "%s:create recv thread err/n", __func__); exit ( -1); re turn-1; return 1; static int Start_sender () {_sock_sender = socket (af_inet, SOCK_DGRAM, 0); if (_sock_sender = = 1) {fprintf (stderr, "% S:create Sender sock err/n ", __func__); Exit (-1); return-1; } _target.sin_family = Af_inet; _target.sin_port = htons (Listen_port); _TARGET.SIN_ADDR.S_ADDR = inet_addr (_TARGET_IP); return 1; static int sendpcm (void *pcm, size_t len) {return sendto (_sock_sender, PCM, Len, 0, (struct sockaddr*) &_target, siz EOF (_target)); } static void Pop_data (struct tea_cirbuf_t *cbuf, char *buf, size_t bufsize) {assert (Util_cbuf_data (cbuf) >= bufsize) ; Char *p; size_t cs = util_cbuf_get_cdata (cbuf, &p); if (CS >= bufsize) {memcpy (buf, p, Bufsize); Util_cbuf_consume (Cbuf, bufsize); else {memcpy (buf, p, CS); Util_cbuf_consume (Cbuf, cs); buf = cs; bufsize-= CS; Util_cbuf_get_cdata (CBUF, &p); mem CPY (BUF, p, bufsize); Util_cbuf_consume (Cbuf, bufsize); } static double Now () {struct timeval TV; Gettimeofday (&AMP;TV, 0); return tv.tv_sec + 0.000001*tv.tv_usec;} #define PI 3.1415927/** makes 1khz sine wave for 8k mono, each sample changes to PI/4 */static void Make_sine (short *sample_buf, int samples) {Double RA Dian = 0; for (int i = 0; i < samples; i++) {Sample_buf[i] = 65535 * 0.7 * sin (radian); Radian + = Pi/4;}} /** worker thread, use blocking mode, write (), read () .... */static void *_thread_run (void *p) {assert (_snd_capture && _snd_playbac k); unsigned char *silence = (unsigned char *) malloc (_period_bytes); memset (Silence, 0, _period_bytes); Make_sine (Silence, _period_size); unsigned char *playback_data = (unsigned char *) malloc (_period_bytes); unsigned char *capture_data = (unsigned char *) malloc (_period_bytes); unsigned char *outbuf= (unsigned char*) malloc (_period_bytes); AEC output BUF//Start if (Snd_pcm_start (_snd_capture) < 0) {fprintf (stderr, "%s:snd_pcm_start for capture err/n" , __func__); Exit (-1); } if (Snd_pcm_start (_snd_playback) < 0) {fprintf (stderr, "%s:snd_pcm_start for playback err/n", __func__); exit (-1); } snd_pcm_prepare (_snd_playback); Snd_pcm_prepare (_snd_capture); Double Curr = Now (); while (1) {//p unsigned char *p = silence for data that needs to be written to the sound card (Util_cbuf_data (_CBUF_RECV) >= _period_bytes) {pop_data (_CB UF_RECV, Playback_data, _period_bytes); p = playback_data; else {fprintf (stderr, "S");} int rc = Snd_pcm_writei (_snd_playback, p, _period_size); if (rc = = _period_size) {} else if (rc = =-epipe) {fprintf (stderr,%s:snd_pcm_writei xrun!/n, __func__); exit (-1);} else {fprintf (stderr, "%s:snd_pcm_writei ret%d/n", __func__, RC); exit ( -1);}/read from capture rc = Snd_pcm_readi ( _snd_capture, Capture_data, _period_size); if (rc = = _period_size) {} else if (rc =-epipe{fprintf (stderr, "%s:snd_pcm_readi xrun/n", __func__); exit ( -1);} else {fprintf (stderr, "%s:snd_pcm_readi ERR, code =%d/n ", __func__, RC); Exit (-1); }//AEC speex_echo_cancellation (_SPEEX_AEC, (short*) Capture_data, (short*) Playback_data, (short*) outbuf); Speex_preprocess_run (_speex_preprocess, outbuf); Send to target SENDPCM (Outbuf, _period_size); #if savefile FILE *fp_c = fopen ("CAPTURE.PCM", "AB"); FILE *fp_p = fopen ("PLAYBACK.PCM", "AB"); FILE *fp_o = fopen ("AECD.PCM", "AB"); Fwrite (Capture_data, 1, _period_bytes, Fp_c); Fwrite (Playback_data, 1, _period_bytes, fp_p); Fwrite (Outbuf, 1, _period_bytes, fp_o); Fclose (Fp_c); Fclose (fp_p); Fclose (Fp_o); #endif//Save File}}/** set parameters, Mono, 16bits, 8k */static int set_params (snd_pcm_t *snd) {int err; snd_pcm_hw_params_ T *hwparams; Snd_pcm_hw_params_alloca (&hwparams); if (Snd_pcm_hw_params_any (SND, Hwparams) < 0) {fprintf (stderr,%s:snd_pcm_hw_params_any err/n, __func__); exit (-1) ; return-1; } if (Snd_pcm_hw_paraMs_set_access (snd, Hwparams, snd_pcm_access_rw_interleaved) < 0) {fprintf (stderr, "%s:set_access err/n", __func__); Exit (-1); } if (Snd_pcm_hw_params_set_channels (SND, Hwparams, 1)) {fprintf (stderr,%s:set_channels err/n, __func__); exit (-1);} if (Snd_pcm_hw_params_set_format (snd, Hwparams, Snd_pcm_format_s16_le)) {fprintf (stderr, "%s:set_format err/n", __ FUNC__); Exit (-1); } if (Snd_pcm_hw_params_set_rate (SND, Hwparams, 8000, 1)) {fprintf (stderr, "%s:set_rate err/n", __func__); exit (-1);}/ /Set period size int dir; if (Snd_pcm_hw_params_set_period_size_near (snd, Hwparams, &_period_size, &dir) < 0) {fprintf (stderr, "%s: Snd_pcm_hw_params_set_period_size_near err/n ", __func__); Exit (-1); } fprintf (stderr, "set Period size=%u/n", _period_size); _period_bytes = _period_size*2; Set buffer size if (snd_pcm_hw_params_set_buffer_size (snd, Hwparams, period_num*_period_bytes) < 0) {fprintf (Stder R, "%s:snd_pcm_hw_params_set_buffer_size err/n", __func__); Exit-1); } if (Snd_pcm_hw_params (SND, Hwparams) < 0) {fprintf (stderr,%s:snd_pcm_hw_params err/n, __func__); exit (-1);}// Set software params snd_pcm_sw_params_t *swparams; Snd_pcm_sw_params_alloca (&swparams); return 1; /** Open Alsa plughw:0,0 for capture */static int open_snd_capture () {int err = Snd_pcm_open (&_snd_capture, "Defau LT ", snd_pcm_stream_capture, 0); if (Err < 0) {fprintf (stderr, "%s:snd_pcm_open err/n", __func__); exit ( -1); return-1;} set_params (_snd_capture); return 1; }//Open plughw:0,0 for playback static int open_snd_playback () {int err = Snd_pcm_open (&_snd_playback, "Default", Snd_pcm_stream_playback, 0); if (Err < 0) {fprintf (stderr, "%s:snd_pcm_open err/n", __func__); exit ( -1); return-1;} set_params (_snd_playback); return 1; int main (int argc, char **argv) {if (argc!= 2) {fprintf (stderr, "Usage:%s <target ip>/n", argv[0]); return-1 ; } _target_ip = StrDup (argv[1]); Speex state int sample_rate = 8000; _speex_aec = Speex_echo_state_init (framesize, 2500); _speex_preprocess = Speex_preprocess_state_init (framesize, 8000); Speex_echo_ctl (_SPEEX_AEC, Speex_echo_set_sampling_rate, &sample_rate); Speex_preprocess_ctl (_speex_preprocess, Speex_preprocess_set_echo_state, _SPEEX_AEC); int DN = 1; Speex_preprocess_ctl (_speex_preprocess, Speex_preprocess_set_denoise, &AMP;DN); Prepare Cbufs _cbuf_recv = util_cbuf_create (64*1024); _cbuf_capture = Util_cbuf_create (4*1024); _cbuf_playback = Util_cbuf_create (4*1024); Start local listener start_listener (); Start Sender sock start_sender (); Open playback open_snd_playback (); Open_snd_capture (); Work thread pthread_t th; Pthread_create (&th, 0, _thread_run, 0); while (1) {if (GetChar () = = ' Q ') {break;}} return 0; }  

Also need that UTIL_CIRBUF.C util_cirbuf.h, here download http://download.csdn.net/source/3290182

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.