用c语言编写的录音程序,c语言实现ALSA录音

该博客介绍了如何在Linux系统中使用Alsa库进行音频捕获。主要内容包括打开默认音频设备、配置采样率、声道数、缓冲时间和周期时间,以及实时读取和写入音频数据到文件。程序还包括了错误处理和音量调节功能。

#include

#include

#include

#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;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值