您的位置:首页 > 运维架构 > Linux

关于Linux下alsa录音程序移植出现的奇怪问题

2017-03-14 21:27 309 查看
以下程序是可以正常运行的:#include <alsa/asoundlib.h>#include <math.h>#include <pthread.h>#include <string.h>#define BUFFERSIZE 4096#define PERIOD_SIZE 1024#define PERIODS 2#define SAMPLE_RATE 16000#define CHANNELS 1#define FSIZE 2*CHANNELS/* Use the newer ALSA API */#define ALSA_PCM_NEW_HW_PARAMS_API
long loops; //define the record time.int rc;	//return code.int size;snd_pcm_t *handle;snd_pcm_hw_params_t *params;//定义参数变量unsigned int val;int dir;snd_pcm_uframes_t frames;char *buffer;int err;char *file;int fd_pcm;int read_flag1=0;
/*放音初始化*/int init_pcm_play_dri(void){/*snd_pcm_open (&pcm_handle, “default” , mode , 0)snd_pcm_open是Alsa库提供的打开设备调用函数,这里我们指定打开缺省的音频设备,并根据参数mode将设备置为录音或是播放状态,如果设备打开成功,pcm_handle便指向该设备句柄,我们用全局变量保存起来,方便以后使用。*/rc = snd_pcm_open(&handle, "default",SND_PCM_STREAM_PLAYBACK, 0);if (rc < 0) {fprintf(stderr,"unable to open pcm device: %s\n",snd_strerror(rc));exit(1);}/* Allocate a hardware parameters object. */snd_pcm_hw_params_alloca(¶ms);//为参数变量分配空间/* Fill it in with default values. */err=snd_pcm_hw_params_any(handle, params);//参数初始化if (err < 0) {fprintf(stderr, "Can not configure this PCM device: %s\n",snd_strerror(err));exit(1);}/* Set the desired hardware parameters. *//* Interleaved mode *///设置为交错模式err=snd_pcm_hw_params_set_access(handle, params,SND_PCM_ACCESS_RW_INTERLEAVED);if (err < 0) {fprintf(stderr,"Failed to set PCM device to interleaved: %s\n",snd_strerror(err));exit(1);}/* Signed 16-bit little-endian format *///使用用16位样本err=snd_pcm_hw_params_set_format(handle, params,SND_PCM_FORMAT_S16_LE);if (err < 0) {fprintf(stderr,"Failed to set PCM device to 16-bit signed PCM: %s\n",snd_strerror(err));exit(1);}/* One channels (mono) *///设置通道err=snd_pcm_hw_params_set_channels(handle, params, CHANNELS);if (err < 0) {fprintf(stderr, "Failed to set PCM device to mono: %s\n",snd_strerror(err));exit(1);}/* 16000 bits/second sampling rate (CD quality) */ //设置采样率为16KHzval = SAMPLE_RATE;err=snd_pcm_hw_params_set_rate_near(handle, params,&val, &dir);if (err < 0) {fprintf(stderr, "Failed to set PCM device to sample rate =%d: %s\n",val,snd_strerror(err));exit(1);}/*frames = PERIOD_SIZE;snd_pcm_hw_params_set_period_size_near(handle,params, &frames, &dir);*//*snd_pcm_hw_params_get_buffer_time_max(params, &buffer_time, 0);period_time = buffer_time / 4;err=snd_pcm_hw_params_set_period_time_near(handle, params,&period_time, 0);if (err < 0) {fprintf(stderr,"Failed to set PCM device to period time =%u: %s\n",period_time,snd_strerror(err));exit(1);}*/unsigned int buffer_time,period_time;snd_pcm_hw_params_get_buffer_time_max(params, &buffer_time, 0);if ( buffer_time >500000)buffer_time = 500000;period_time = buffer_time / 4;err = snd_pcm_hw_params_set_buffer_time_near(handle, params, &buffer_time, 0);if (err < 0){fprintf(stderr, "Failed to set PCM device to buffer time =%d: %s\n",buffer_time,snd_strerror(err));exit(1);}err = snd_pcm_hw_params_set_period_time_near(handle, params, &period_time, 0);if (err < 0) {fprintf(stderr, "Failed to set PCM device to period time =%d: %s\n",period_time,snd_strerror(err));exit(1);}rc = snd_pcm_hw_params(handle, params);//设置参数if (rc < 0) {fprintf(stderr,"unable to set hw parameters: %s\n",snd_strerror(rc));exit(1);}snd_pcm_hw_params_get_period_size(params, &frames,&dir);//获取周期长度size = frames * FSIZE;buffer = (char *) malloc(size);printf("period size = %d frames\n", (int)frames);printf("read buffer size = %d\n",size);snd_pcm_hw_params_get_period_time(params,&val, &dir);printf("period time is: %d\n",val);//loops = 100;snd_pcm_hw_params_get_buffer_time(params,&val, &dir);printf("buffer time = %d us\n", val);snd_pcm_hw_params_get_buffer_size(params,(snd_pcm_uframes_t *) &val);printf("buffer size = %d frames\n", val);snd_pcm_hw_params_get_periods(params, &val, &dir);printf("periods per buffer = %d frames\n", val);printf("start playing !\n");file = "output_test.wav";fd_pcm = open(file,O_RDONLY);do{read_flag1 = read(fd_pcm, buffer, size);if(read_flag1 == 0){fprintf(stderr, "end of file on input\n");break;}else if (read_flag1 != size){fprintf(stderr,"short read: read %d bytes\n", read_flag1);}rc = snd_pcm_writei(handle, buffer, frames);if (rc == -EPIPE){fprintf(stderr, "underrun occurred\n");err=snd_pcm_prepare(handle);if( err <0){fprintf(stderr, "can not recover from underrun: %s\n",snd_strerror(err));}}else if (rc < 0){fprintf(stderr,"error from writei: %s\n",snd_strerror(rc));}else if (rc != (int)frames){fprintf(stderr,"short write, write %d frames\n", rc);}printf("recording.......................................\n");}while(read_flag1);//close(fd_pcm);//snd_pcm_drain(handle);//snd_pcm_close(handle);//free(buffer);return 1;}
以上程序运行时没问题的,但是将所有的变量都放在函数init_pcm_play_dri()里面,就会出问题,在友善之臂210的开发板上运行的时候报错:在这里报错:rc = snd_pcm_hw_params(handle, params);//设置参数if (rc < 0) {fprintf(stderr,"unable to set hw parameters: %s\n",snd_strerror(rc));exit(1);}打印出rc的值为-22,报的错误是非法的参数。最后发现变量read_flag1必须在这个函数体的外面(即全局变量)或者在函数体内部声明成静态变量才不会报这个错误。暂时还没想清楚是为什么。。。。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: