先看看效果:
之前我使用了QFile将音频存储为.raw格式,用matlab可以处理和播放,音质也不错,但是如果想采集后直接听是不行的,因为那个格式是自己定义的,播放器不认。现在使用QAudioRecorder可以保存为主流音频格式。但是在多线程中采集时还是遇到了一些奇怪的问题。
主要步骤很简单:
1. 初始化
mpProbe = new QAudioProbe; //这里使用了一个探针,监听声音数据
mpAudioRecorder = new QAudioRecorder();
connect(mpProbe, &QAudioProbe::audioBufferProbed, // 把探针的信号与槽函数绑定
this, &audioSample::processBuffer);
mpProbe->setSource(mpAudioRecorder); // 指定声源
settings.setCodec("audio/PCM"); // 这些是QAudioRecorder是设置,见名思意
settings.setBitRate(96000);
settings.setChannelCount(1);
settings.setQuality(QMultimedia::EncodingQuality::HighQuality);
settings.setEncodingMode(QMultimedia::ConstantQualityEncoding);
mpAudioRecorder->setContainerFormat("audio/wav"); // 设置容器格式
【2022.03.26更新】
这里说明一下,在QT5.9版本以前,使用上面的设置,在5.9版本以后,删掉:settings.setCodec("audio/PCM"); ,然后mpAudioRecorder->setContainerFormat("audio/x-wav");
2. 开启设备
settings.setSampleRate(mSampleRate); //采样率在开启设备时确定
mpAudioRecorder->setAudioInput(audioDeviceInfo.deviceName());//打开指定设备,还是用的QAudioDeviceInfo类,可以正常打开
settings.setQuality(QMultimedia::EncodingQuality::HighQuality);
mpAudioRecorder->setOutputLocation(QUrl::fromLocalFile("./---test.avi")); // 此时还没有录音,随便指定一个文件,仅仅为了探针能够接收到数据,实验发现无法保存到相对路径。
mpAudioRecorder->setEncodingSettings(settings);
mpAudioRecorder->record(); //开始录音,这时候audioSample::processBuffer槽函数就可以被触发了,在这个槽函数中进行声音显示。
3. 开始录音
如果开始录音,把刚才的那个录音结束掉,然后重新设定保存文件,然后开启录音。
if ( mpAudioRecorder->state() == QMediaRecorder::RecordingState)
{
mpAudioRecorder->stop();
}
mpAudioRecorder->setOutputLocation(QUrl::fromLocalFile(path));
mpAudioRecorder->record();
4. 结束
if ( mpAudioRecorder->state() == QMediaRecorder::RecordingState)
{
mpAudioRecorder->stop();
}
本来是很简单的,但是存在1个问题:
mpAudioRecorder->stop(); mpAudioRecorder->record();这两句话是不能连续执行的,否则第二段录音无法打开;解决的办法是等待10ms左右。但是等待尽量在主线程中等待,然后再通过信号-槽调用mpAudioRecorder->record()
中途还尝试过更换探针声源,mpProbe->setSource(mpAudioRecorder_copy); 这是不可行的,系统会提示在 子线程中不能开辟新线程,不知道为什么,可能是因为每一个探针是一个独立的线程吧。
最后为了实现监听和录音两不误,又创建了一个录音对象,一个对象给探针显示,一个对象用来录音,探针的录音对象可以设置为非常低的质量和采样率,不会影响录音的质量。
【2022.03.26更新】
另外,强调一下,QAudioRecorder类和QAudioInput类不能同时使用,否则后面打开的那个就无法找到设备,显示被占用。
目前我在台式机上分别用QAudioRecorder和QAudioInput类实现了连续的声音采集。在树莓派上,两种方式也均实现了声音连续采集,但是前者的压缩率不太好整,压缩效率不高,后者是使用了ffmepg库进行的压缩,效果不错但是无法实时获取采集到的声音数据。折腾了一圈,又使用QAudioRecorder+QAudioProbe的方案了。