c语言实现ALSA录音

    技术2022-07-10  139

    用c实现ALSA录音和播放

    c语言实现ALSA播放

    由于这个比较简单,直接上代码

    #include <alsa/asoundlib.h> #include <stdio.h> #include <sys/time.h> #define CHANNELS 2 #define FSIZE 2*CHANNELS int main() { int fd; char *out_filename="output.raw"; char *file=out_filename; fd = open(file,O_WRONLY|O_CREAT,0777); if( fd ==-1) { printf("open file:%s fail.\n",out_filename); exit(1); } int ret=0; snd_pcm_t *handle; //以录音模式打开设备 ret = snd_pcm_open(&handle, "default",SND_PCM_STREAM_CAPTURE, 0); if (ret < 0) { printf("unable to open pcm device!\n"); exit(1); } //配置硬件参数结构体 snd_pcm_hw_params_t *params; //params申请内存 snd_pcm_hw_params_malloc(&params); //使用pcm设备初始化hwparams ret=snd_pcm_hw_params_any(handle, params); if (ret < 0) { printf("Can not configure this PCM device!\n"); exit(1); } //设置多路数据在buffer中的存储方式 //SND_PCM_ACCESS_RW_INTERLEAVED每个周期(period)左右声道的数据交叉存放 ret=snd_pcm_hw_params_set_access(handle, params,SND_PCM_ACCESS_RW_INTERLEAVED); if (ret < 0) { printf("Failed to set PCM device to interleaved!\n"); exit(1); } //设置16位采样格式 ret=snd_pcm_hw_params_set_format(handle, params,SND_PCM_FORMAT_S16_LE); if (ret < 0) { printf("Failed to set PCM device to 16-bit signed PCM\n"); exit(1); } //设置声道数 ret=snd_pcm_hw_params_set_channels(handle, params, CHANNELS); if (ret < 0) { printf("Failed to set PCM device CHANNELS\n"); exit(1); } unsigned int val=48000; int dir; //设置采样率,如果采样率不支持,会用硬件支持最接近的采样率 ret=snd_pcm_hw_params_set_rate_near(handle, params,&val, &dir); if (ret < 0) { printf("Failed to set PCM device to sample rate\n"); exit(1); } unsigned int buffer_time,period_time; //获取最大的缓冲时间,buffer_time单位为us,500000us=0.5s snd_pcm_hw_params_get_buffer_time_max(params, &buffer_time, 0); //printf("buffer_time:%d\n",buffer_time); if ( buffer_time >500000) buffer_time = 500000; //设置缓冲时间 ret = snd_pcm_hw_params_set_buffer_time_near(handle, params, &buffer_time, 0); if (ret < 0) { printf("Failed to set PCM device to sample rate\n"); exit(1); } //设置周期时间 period_time = 26315; ret = snd_pcm_hw_params_set_period_time_near(handle, params, &period_time, 0); if (ret < 0) { printf("Failed to set PCM device to period time\n"); exit(1); } //让这些参数作用于PCM设备 ret = snd_pcm_hw_params(handle, params); if (ret < 0) { printf("unable to set hw parameters\n"); exit(1); } snd_pcm_uframes_t frames; snd_pcm_hw_params_get_period_size(params,&frames, &dir); printf("period_size:%ld\n",frames); int size; // 1 frame = channels * sample_size. size = frames * FSIZE; /* 2 bytes/sample, 1 channels */ printf("size:%d\n",size); char *buffer; buffer = (char *) malloc(size); struct timeval start, end; gettimeofday( &start, NULL ); while (1) { ret = snd_pcm_readi(handle, buffer, frames); if (ret == -EPIPE) { // EPIPE means overrun fprintf(stderr, "overrun occurred\n"); ret=snd_pcm_prepare(handle); if(ret <0){ printf("Failed to recover form overrun"); exit(1); } } else if (ret < 0) { fprintf(stderr,"error from read: %s\n",snd_strerror(ret)); exit(1); } else if (ret != (int)frames) { fprintf(stderr, "short read, read %d frames\n", ret); } ret = write(fd, buffer, size); if (ret <0){ perror("fail to write to audio file\n"); } gettimeofday( &end, NULL ); printf("%ld",end.tv_sec-start.tv_sec); printf("\r\033[k"); fflush(stdout); } close(fd); snd_pcm_drain(handle); snd_pcm_close(handle); free(buffer); return 0; } //音量调节 int volume_adjust(char *in_buf,float vol) { short buf=0; buf=*in_buf+(*(in_buf+1)<<8); if(buf>=-1&&buf<=1) { buf=0; } buf=buf*vol; if(buf>=32767) { buf=0; *in_buf=(char)buf; *(in_buf+1)=buf>>8; } else if(buf<=-32768) { buf=0; *in_buf=(char)buf; *(in_buf+1)=buf>>8; } else { *in_buf=(char)buf; *(in_buf+1)=buf>>8; } return 0; }

    编译

    gcc alsa_record.c -o alsa_record -lasound
    Processed: 0.012, SQL: 9