c语言实现alsa录音
这个比较简单直接上代码
#include <alsa/asoundlib.h> #include <math.h> #define SAMPLE_RATE 48000 #define CHANNELS 2 #define FSIZE 2*CHANNELS int main(int argc, char *argv[]) { int rc; int size; unsigned int val; int dir; snd_pcm_uframes_t frames; char *buffer; char *inFile; int fd; int err; inFile = "output.raw"; fd = open(inFile,O_RDONLY); snd_pcm_t *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); } //配置硬件参数结构体 snd_pcm_hw_params_t *params; //params申请内存 snd_pcm_hw_params_malloc(¶ms); //使用pcm设备初始化hwparams 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); } //设置多路数据在buffer中的存储方式 //SND_PCM_ACCESS_RW_INTERLEAVED每个周期(period)左右声道的数据交叉存放 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); } //设置16位采样格式,S16为有符号16位,LE是小端模式 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); } //设置声道数,双声道 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); } //采样率48000 val = 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); } unsigned int buffer_time,period_time; //获取最大的缓冲时间,buffer_time单位为us,500000us=0.5s snd_pcm_hw_params_get_buffer_time_max(params, &buffer_time, 0); if ( buffer_time >500000) buffer_time = 500000; //设置缓冲时间 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); } period_time = 26315; //设置周期时间 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); } //让这些参数作用于PCM设备 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); // 1 frame = channels * sample_size. size = frames * FSIZE; /* 2 bytes/sample, 1 channels */ buffer = (char *) malloc(size); while (1) { rc = read(fd, buffer, size); if (rc == 0) { fprintf(stderr, "end of file on input\n"); break; } else if (rc != size) { fprintf(stderr,"short read: read %d bytes\n", rc); } 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); } } snd_pcm_drain(handle); snd_pcm_close(handle); free(buffer); close(fd); return 0; }编译
gcc alsa_play.c -o alsa_play -lasound