1. 简介
QAudioInput
是Qt Multimedia模块中用于音频采集的核心类,能够从麦克风等输入设备实时获取原始音频数据(PCM格式)。本文将通过原理讲解和代码示例,帮助开发者快速掌握音频采集的核心技术。
2. 核心功能
-
支持多种音频格式(采样率/声道/位深)
-
提供实时音频流访问
-
自动管理音频设备资源
-
支持多平台(Windows/Linux/macOS/移动端)
3. 开发准备
3.1 环境要求
# .pro文件添加 QT += multimedia
3.2 头文件
#include <QAudioInput> #include <QAudioDeviceInfo>
4. 核心类说明
4.1 QAudioInput
-
核心方法:
-
start()
: 开始采集 -
stop()
: 停止采集 -
setBufferSize()
: 设置缓冲区大小
-
4.2 QAudioFormat
-
常用配置:
format.setSampleRate(16000); // 16kHz采样率 format.setChannelCount(1); // 单声道 format.setSampleSize(16); // 16位采样 format.setCodec("audio/pcm"); // PCM编码 format.setByteOrder(QAudioFormat::LittleEndian); format.setSampleType(QAudioFormat::SignedInt);
5. 基础使用流程
5.1 初始化设备
// 创建音频格式
QAudioFormat format;
// ...(设置格式参数)
// 获取输入设备
QAudioDeviceInfo inputDevice = QAudioDeviceInfo::defaultInputDevice();
if (!inputDevice.isFormatSupported(format)) {
format = inputDevice.nearestFormat(format);
}
// 创建音频输入对象
QAudioInput* audioInput = new QAudioInput(inputDevice, format, this);
5.2 数据采集与保存
// 创建文件保存原始数据
QFile outputFile("raw.pcm");
outputFile.open(QIODevice::WriteOnly);
// 开始采集
audioInput->start(&outputFile);
6. 完整示例代码
示例1:保存为WAV文件(含文件头)
#include <QCoreApplication>
#include <QAudioInput>
#include <QFile>
#include <QDataStream>
// WAV文件头结构(44字节)
struct WavHeader {
// ...(完整文件头结构定义,此处省略)
};
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
// 配置音频格式
QAudioFormat format;
format.setSampleRate(16000);
format.setChannelCount(1);
format.setSampleSize(16);
format.setCodec("audio/pcm");
format.setByteOrder(QAudioFormat::LittleEndian);
format.setSampleType(QAudioFormat::SignedInt);
// 初始化设备
QAudioInput audioInput(QAudioDeviceInfo::defaultInputDevice(), format);
// 创建WAV文件
QFile file("recording.wav");
file.open(QIODevice::WriteOnly);
// 写入空文件头
WavHeader header = createWavHeader(format);
file.write((const char*)&header, sizeof(header));
// 开始录音
audioInput.start(&file);
// 录音5秒后停止
QTimer::singleShot(5000, [&]() {
audioInput.stop();
file.close();
qApp->quit();
});
return a.exec();
}
示例2:实时音量监测
class AudioMonitor : public QIODevice {
public:
explicit AudioMonitor(QObject* parent = nullptr) : QIODevice(parent) {}
protected:
qint64 readData(char*, qint64) override { return 0; } // 不需要实现
qint64 writeData(const char* data, qint64 len) override {
// 计算音量(16位样本)
const qint16* samples = reinterpret_cast<const qint16*>(data);
int sampleCount = len / 2; // 每个样本占2字节
qreal peak = 0;
for (int i=0; i<sampleCount; ++i) {
peak = qMax(peak, qAbs(samples[i]/32768.0));
}
emit volumeChanged(peak * 100); // 百分比
return len;
}
signals:
void volumeChanged(qreal percent);
};
// 使用方式:
AudioMonitor* monitor = new AudioMonitor;
audioInput->start(monitor);
QObject::connect(monitor, &AudioMonitor::volumeChanged, [](qreal vol){
qDebug() << "当前音量:" << vol << "%";
});
7. 常见问题解决方案
7.1 无输入数据
-
检查项:
-
系统麦克风权限
-
音频格式与设备兼容性
-
缓冲区大小设置(
setBufferSize(2048)
)
-
7.2 录音文件杂音
-
解决方法:
-
添加静音检测逻辑
-
使用噪声抑制算法
-
调整麦克风增益
-
7.3 延迟过高
-
优化方法:
audioInput->setBufferSize(512); // 减小缓冲区 QThread::highPriority(); // 提升线程优先级
8. 关键知识点总结
要点 | 说明 |
---|---|
格式匹配 | 必须与硬件支持格式一致 |
实时性处理 | 避免在回调中进行耗时操作 |
资源释放 | stop()后及时释放设备 |
跨平台差异 | 特别注意移动端权限问题 |