c 언어 ALSA 녹음 실현
c 언어 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.
",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!
");
exit(1);
}
//
snd_pcm_hw_params_t *params;
//params
snd_pcm_hw_params_malloc(¶ms);
// pcm hwparams
ret=snd_pcm_hw_params_any(handle, params);
if (ret < 0)
{
printf("Can not configure this PCM device!
");
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!
");
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
");
exit(1);
}
//
ret=snd_pcm_hw_params_set_channels(handle, params, CHANNELS);
if (ret < 0)
{
printf("Failed to set PCM device CHANNELS
");
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
");
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
",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
");
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
");
exit(1);
}
// PCM
ret = snd_pcm_hw_params(handle, params);
if (ret < 0)
{
printf("unable to set hw parameters
");
exit(1);
}
snd_pcm_uframes_t frames;
snd_pcm_hw_params_get_period_size(params,&frames, &dir);
printf("period_size:%ld
",frames);
int size;
// 1 frame = channels * sample_size.
size = frames * FSIZE; /* 2 bytes/sample, 1 channels */
printf("size:%d
",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
");
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
",snd_strerror(ret));
exit(1);
}
else if (ret != (int)frames) {
fprintf(stderr, "short read, read %d frames
", ret);
}
ret = write(fd, buffer, size);
if (ret <0){
perror("fail to write to audio file
");
}
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