【实例简介】
基于alsa,linux音频采集实现
【实例截图】
【文件目录】
AudioSamplingApp
├── AudioSamplingApp.cpp
├── AudioSamplingApp.vcxproj
├── AudioSamplingApp.vcxproj.filters
├── ReadMe.txt
├── build
│ ├── CMakeLists.txt
│ ├── aconfig.h
│ ├── formats.h
│ ├── gettext.h
│ └── version.h
└── x64
└── Debug
├── AudioSamplingApp.Build.CppClean.log
├── AudioSamplingApp.log
├── AudioSamplingApp.obj
├── AudioSamplingApp.tlog
│ ├── AudioSamplingApp.lastbuildstate
│ ├── CL.command.1.tlog
│ ├── CL.read.1.tlog
│ ├── CL.write.1.tlog
│ ├── link.command.1.tlog
│ ├── link.read.1.tlog
│ └── link.write.1.tlog
├── audiosamplingapp.obj.enc
├── vc140.idb
└── vc140.pdb
4 directories, 22 files
【核心代码】
int InitAudioCodec()
{
snd_pcm_stream_t stream = SND_PCM_STREAM_CAPTURE;
snd_pcm_hw_params_t *hwparams;
snd_pcm_info_t *info;
snd_pcm_uframes_t* frames;
char* buffer;
int size;
//char *pcm_name = "default";
char *pcm_name = "hw:1,0";
snd_pcm_info_alloca(&info);
int err = snd_output_stdio_attach(&log, stderr, 0);
assert(err >= 0);
int ret, dir;
//打开设备
ret = snd_pcm_open(&pcm_handle, pcm_name, SND_PCM_STREAM_CAPTURE, 0);
if (ret < 0)
{
printf("unable to open device : %s\n", snd_strerror(ret));
exit(1);
}
snd_pcm_hw_params_alloca(&hwparams);
//使用默认参数
snd_pcm_hw_params_any(pcm_handle, hwparams);
//翻译
snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED);
//S16小端
snd_pcm_hw_params_set_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_LE);
//单通道
snd_pcm_hw_params_set_channels(pcm_handle, hwparams, 1);
//采样率
//int val = 44100;
int val = 16000;
snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &val, 0);
//frames = 32;
if (buffer_time == 0 && buffer_frames == 0)
{
int err = snd_pcm_hw_params_get_buffer_time_max(hwparams,
&buffer_time, 0);
assert(err >= 0);
if (buffer_time > 500000)
{
buffer_time = 500000;
}
}
if (period_time == 0 && period_frames == 0)
{
if (buffer_time > 0)
{
period_time = buffer_time / 4;
}
else
{
period_frames = buffer_frames / 4;
}
}
if (period_time > 0)
{
err = snd_pcm_hw_params_set_period_time_near(pcm_handle, hwparams,
&period_time, 0);
}
else
{
err = snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams,
&period_frames, 0);
}
//frames = 32;
//snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, frames, 0);
if (buffer_time > 0)
{
err = snd_pcm_hw_params_set_buffer_time_near(pcm_handle, hwparams,
&buffer_time, 0);
}
else
{
err = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams,
&buffer_frames);
}
//参数生效
ret = snd_pcm_hw_params(pcm_handle, hwparams);
if (ret < 0)
{
fprintf(stderr, "unable to set hw parameters:%s\n", snd_strerror(ret));
exit(1);
}
//得到一个周期的数据大小
snd_pcm_hw_params_get_period_size(hwparams, &chunk_size, 0);
snd_pcm_hw_params_get_buffer_size(hwparams, &buffer_size);
//设置一个周期的时间长度
//snd_pcm_hw_params_get_period_time(hwparams, &val,0);
snd_pcm_start(pcm_handle);
snd_pcm_state_t pcm_state = snd_pcm_state(pcm_handle);
printf("State: %s\n", print_pcm_state(pcm_state));
return 0;
}
int SamplingAudio(char** pbuf, int* nsize)
{
snd_pcm_state_t pcm_state = snd_pcm_state(pcm_handle);
if (pcm_state == SND_PCM_STATE_XRUN)
{
int nRet;
if ((nRet = snd_pcm_prepare(pcm_handle)) < 0)
{
printf("xrun(DRAINING): prepare error: %s", snd_strerror(nRet));
return -1;
}
}
else if (pcm_state == SND_PCM_STATE_PREPARED)
{
snd_pcm_start(pcm_handle);
return -1;
}
int count = *nsize;
while (count > 0)
{
int ret = snd_pcm_readi(pcm_handle, *pbuf, count);
if (ret == -EAGAIN || (ret >= 0 && (size_t)ret < count))
{
snd_pcm_wait(pcm_handle, 100);
}
else if (ret == -EPIPE)
{
fprintf(stderr, "overrun occurred\n");
snd_pcm_prepare(pcm_handle);
//return -3;
}
else if (ret == -ESTRPIPE)
{
while ((ret = snd_pcm_resume(pcm_handle)) == -EAGAIN)
{
sleep(1); /* wait until resume flag is released */
}
if (ret < 0)
{
snd_pcm_prepare(pcm_handle);
}
}
else if (ret < 0)
{
printf(" error from read: %s", snd_strerror(ret));
return -3;
}
if (ret > 0)
{
static FILE* g_enfp = NULL;
if (!g_enfp)
{
char file_name_264[256] = { 0 };
snprintf(file_name_264, 256, "./AudioSamplingApp.cm");
g_enfp = fopen(file_name_264, "wb");
}
if (g_enfp)
{
fwrite(*pbuf, 1, count, g_enfp);
}
count -= ret;
}
}
return 0;
}