依赖库
要完成该功能依赖libasound、libsndfile库,该命令在linux下可以通过命令行安装安装,安装命令如下:
bash
sudo apt-get install libasound2-dev
sudo apt-get install libsndfile1-dev
代码实现
本文的目的是在linux下利用libasound和libsndfile库基于C++实现读取麦克风数据,并保存为wav文件。具体实现代码如下所示:
cpp
#include <iostream>
#include <vector>
#include <complex>
#include <fftw3.h>
#include <alsa/asoundlib.h>
#include "math.h"
#include "stdio.h"
#include <vector>
#include <QDateTime>
#include <QDebug>
#include <fstream>
#include "sndfile.h"
using namespace std;
const int FRAME_SIZE = 1024;
// 定义采样率、通道数、采样格式等参数
#define SAMPLE_RATE 16000
#define CHANNELS 1
#define FORMAT SND_PCM_FORMAT_S16_LE // 16位,小端
int main() {
// 初始化 ALSA 音频采集
snd_pcm_t* capture_handle;
int rc;
rc = snd_pcm_open(&capture_handle, "default", SND_PCM_STREAM_CAPTURE, 0);
if (rc < 0)
{
std::cerr << "无法打开默认音频设备: " << snd_strerror(rc) << std::endl;
return 1;
}
// 设置音频采集参数
// 配置PCM参数
snd_pcm_hw_params_t *params;
snd_pcm_hw_params_alloca(¶ms);
snd_pcm_hw_params_any(capture_handle, params);
snd_pcm_hw_params_set_access(capture_handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); //设置该参数的目的是决定多通道时是否采用一块内存来存储音频数据,设置SND_PCM_ACCESS_RW_INTERLEAVED参数就是将多通道情况下的数据存储到一块内存中
snd_pcm_hw_params_set_format(capture_handle, params, FORMAT);
snd_pcm_hw_params_set_channels(capture_handle, params, CHANNELS);
unsigned int sampleRate = SAMPLE_RATE;
snd_pcm_hw_params_set_rate_near(capture_handle, params, &sampleRate, 0);
int err = snd_pcm_hw_params(capture_handle, params);
if(err < 0)
{
fprintf(stderr, "无法打开 PCM 设备: %s\n", snd_strerror(err));
return 1;
}
SNDFILE* sndfile;
SF_INFO sfinfo;
sfinfo.samplerate = 16000;
sfinfo.channels = 1;
sfinfo.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
sfinfo.frames = 0;
sndfile = sf_open("output1.wav", SFM_WRITE, &sfinfo);
if(!sndfile)
{
qDebug()<<"无法创建wav文件";
snd_pcm_close(capture_handle);
return 1;
}
int index = 0;
short* audioFrame = (short*)malloc(FRAME_SIZE*sizeof(short));
while (true)
{
rc = snd_pcm_readi(capture_handle, audioFrame, FRAME_SIZE);
//vector<int16_t> vData(audioFrame, audioFrame+FRAME_SIZE);
qDebug()<<"time :"<<QDateTime::currentMSecsSinceEpoch();
if (rc == FRAME_SIZE)
{
sf_count_t ret = sf_write_short(sndfile, audioFrame, FRAME_SIZE);
qDebug()<<"sf_write_short ret : "<<ret;
index++;
if(index == 50)
break;
}
else if (rc < 0)
{
std::cerr << "读取音频数据时出错: " << snd_strerror(rc) << std::endl;
break;
}
}
sf_close(sndfile);
snd_pcm_close(capture_handle);
return 0;
}
该程序编译通过后,运行该程序,可以实现录音。