先看看效果:

之前我使用了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的方案了。

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐