c语言实现ALSA录音

用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
  • 1
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
要在C语言中调用ALSA(Advanced Linux Sound Architecture)库来实现录音功能,你可以使用ALSA提供的API来控制音频输入设备并捕获音频数据。以下是一个简单的示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <alsa/asoundlib.h> #define SAMPLE_RATE 44100 #define NUM_SECONDS 5 #define OUTPUT_FILE "recorded_audio.wav" int main() { int err; int numSamples = NUM_SECONDS * SAMPLE_RATE; short *recordedSamples; recordedSamples = (short *)malloc(sizeof(short) * numSamples); if (recordedSamples == NULL) { printf("Failed to allocate memory.\n"); return 1; } snd_pcm_t *handle; snd_pcm_hw_params_t *params; err = snd_pcm_open(&handle, "default", SND_PCM_STREAM_CAPTURE, 0); if (err < 0) { printf("Failed to open PCM device: %s\n", snd_strerror(err)); return 1; } snd_pcm_hw_params_alloca(&params); err = snd_pcm_hw_params_any(handle, params); if (err < 0) { printf("Failed to initialize PCM device parameters: %s\n", snd_strerror(err)); return 1; } err = snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); if (err < 0) { printf("Failed to set PCM device access type: %s\n", snd_strerror(err)); return 1; } err = snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE); if (err < 0) { printf("Failed to set PCM device sample format: %s\n", snd_strerror(err)); return 1; } err = snd_pcm_hw_params_set_rate_near(handle, params, &SAMPLE_RATE, 0); if (err < 0) { printf("Failed to set PCM device sample rate: %s\n", snd_strerror(err)); return 1; } err = snd_pcm_hw_params_set_channels(handle, params, 1); if (err < 0) { printf("Failed to set PCM device channel count: %s\n", snd_strerror(err)); return 1; } err = snd_pcm_hw_params(handle, params); if (err < 0) { printf("Failed to set PCM device parameters: %s\n", snd_strerror(err)); return 1; } printf("Recording started. Press Ctrl+C to stop recording.\n"); while (numSamples > 0) { err = snd_pcm_readi(handle, recordedSamples, numSamples); if (err == -EPIPE) { printf("Overrun occurred.\n"); snd_pcm_prepare(handle); } else if (err < 0) { printf("Failed to read from PCM device: %s\n", snd_strerror(err)); return 1; } else { numSamples -= err; recordedSamples += err * snd_pcm_hw_params_get_channels(params); } } err = snd_pcm_close(handle); if (err < 0) { printf("Failed to close PCM device: %s\n", snd_strerror(err)); return 1; } FILE *file = fopen(OUTPUT_FILE, "wb"); if (file == NULL) { printf("Failed to open output file.\n"); return 1; } fwrite(recordedSamples, sizeof(short), numSamples, file); fclose(file); free(recordedSamples); printf("Recording finished. Saved as %s\n", OUTPUT_FILE); return 0; } ``` 这个示例程序使用ALSA库来打开默认的PCM设备,并读取音频数据。它将录制的音频数据存储在一个内存缓冲区中,并将其写入名为"recorded_audio.wav"的文件中。 请确保在编译时链接ALSA库,例如: ```shell gcc -o record_audio record_audio.c -lasound ``` 这只是一个简单的示例,你可以根据自己的需求进行修改和扩展。希望对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值