Qt各种采样率录音 录音到内存

近段时间了解了Qt的录音模块,Qt的录音模块分为QAudioInput输入,QAudioOutput输出。输入用来录音,输出用于播放。当然还用其它的QMediaPlayer、QAudioRecorder,这类控件封装的比较上层了;QAudioRecorder只能将数据录入到文件,QMediaPlayer是用于根据文件格式播放,一般用于音乐播放器中。

由于项目需要的是16k采样率的wav音频文件,首先使用QAudioRecorder进行录音,该类接口确实很方便,直接设置输出路径,但是通过Qt官方示例可以看出,

虽然可以设置采样率,但是录音出来的文件采样率并不是设置的参数,采样出来的文件只与setQuality设置的参数有关。

Qt各种采样率录音 录音到内存_第1张图片


上图桌面的文件便是通过官方示例录制的采样率为16k的wav文件,当我有coolEdit打开时,可以看到采样率并不是16k

Qt各种采样率录音 录音到内存_第2张图片

截图中红框部分便是实际采样率,于是最终我使用的QAudioInput来录音。

先介绍一下几个重要的类和函数,QAudioDeviceInfo检测本地可用设备;QAudioFormat,设置录音或播放参数;QAudioInput录音。

QAudioInput录音之后的数据是音频原始数据,要想转成wav文件,必需加入44字节的wav文件头。wav文件头的相关知识就请大家网上搜了

,开始录音时要传入一个QIODevice设备,如果想把数据录入到文件还是内存就要在这里入手了,如果是文件就是QFile,是内存就是QBufferr。

以下为一个固定采样率的小程序

#ifndef WIDGET_H
#define WIDGET_H

#include 
#include 
#include 
#include 
#include 

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = 0);
    ~Widget();

private:
    QPushButton *_startBtn,*_endBtn;//开始和结束按钮
    QAudioInput *_audioInput; //录音对象
    QFile outFile;
    QByteArray voiceData;
    QBuffer bufDevice;
};

#endif // WIDGET_H

cpp文件如下

#include "widget.h"
#include 
#include 
#include 
 
  
struct WAVHEADER
{
    // RIFF 
    char RiffName[4];
    unsigned long nRiffLength;
 
  
    // 数据类型标识符
    char WavName[4];
 
  
    // 格式块中的块头
    char FmtName[4];
    unsigned long nFmtLength;
 
  
    // 格式块中的块数据
    unsigned short nAudioFormat;
    unsigned short nChannleNumber;
    unsigned long nSampleRate;
    unsigned long nBytesPerSecond;
    unsigned short nBytesPerSample;
    unsigned short nBitsPerSample;
 
  
    // 数据块中的块头
    char    DATANAME[4];
    unsigned long   nDataLength;
};
 
  
Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    _startBtn = new QPushButton(QStringLiteral("开始录音"),this);
    _endBtn = new QPushButton(QStringLiteral("结束录音"),this);
 
  
    QHBoxLayout *_hBoxLayout = new QHBoxLayout(this);
    _hBoxLayout->addWidget(_startBtn);
    _hBoxLayout->addWidget(_endBtn);
    //设置格式
 
  
 
  
    QAudioFormat audioFormat;
    audioFormat.setByteOrder(QAudioFormat::LittleEndian);
    audioFormat.setChannelCount(1);
    audioFormat.setCodec("audio/pcm");
    audioFormat.setSampleRate(16000);
    audioFormat.setSampleSize(16);
    audioFormat.setSampleType(QAudioFormat::SignedInt);
    //判断设备,查看是否存在
 
  
    QAudioDeviceInfo devInfo = QAudioDeviceInfo::defaultInputDevice();
    if(devInfo.isNull()){
        qDebug() << "未找到录音设备";
    }
    //不支持格式,使用最接近格式
    if(!devInfo.isFormatSupported(audioFormat)){ //当前使用设备是否支持
        audioFormat = devInfo.nearestFormat(audioFormat); //转换为最接近格式
    }
    _audioInput = new QAudioInput(devInfo,audioFormat,this);
    //内存的IO对象
 
  
    bufDevice.setBuffer(&voiceData);
    connect(_startBtn,&QPushButton::clicked,[&]()->void{
             #ifdef TOFILE //存到文件
                outFile.setFileName(qApp->applicationDirPath() + "/test.wav"); //语音原始文件
                outFile.open(QIODevice::WriteOnly | QIODevice::Truncate);
                _audioInput->start(&outFile);
            #else //存到内存
                bufDevice.open(QIODevice::WriteOnly | QIODevice::Truncate);
                _audioInput->start(&bufDevice);
            #endif
    });
 
  
    connect(_endBtn,&QPushButton::clicked,[&]()->void{
                QIODevice *device{nullptr};
                #ifdef TOFILE //存到文件
                    device = &outFile;
                #else //存到内存
                    device = &bufDevice;
                #endif
		//添加wav文件头
                static WAVHEADER wavHeader;
                qstrcpy(wavHeader.RiffName,"RIFF");
                qstrcpy(wavHeader.WavName,"WAVE");
                qstrcpy(wavHeader.FmtName,"fmt ");
                qstrcpy(wavHeader.DATANAME,"data");
 
  
                wavHeader.nFmtLength = 16;
                int nAudioFormat = 1;
                wavHeader.nAudioFormat = nAudioFormat;
                wavHeader.nBitsPerSample = 16;
                wavHeader.nChannleNumber = 1;
                wavHeader.nSampleRate = 16000;
                wavHeader.nBytesPerSample = wavHeader.nChannleNumber * wavHeader.nBitsPerSample / 8;
                wavHeader.nBytesPerSecond = wavHeader.nSampleRate * wavHeader.nChannleNumber *  wavHeader.nBitsPerSample / 8;
                wavHeader.nRiffLength = device->size() - 8 + sizeof(WAVHEADER);
                wavHeader.nDataLength = device->size();
		//写到IO设备头
 
  
                device->seek(0);
                device->write(reinterpret_cast<char*>(&wavHeader),sizeof WAVHEADER);
            });
}
 
  
Widget::~Widget()
{
#ifdef TOFILE
     outFile.close();
#else
     bufDevice.close();
#endif
 
  
}
以上程序定义了一个宏,通过宏来决定存到哪里。在QtCreator中加入编译参数即可输出到文件

Qt各种采样率录音 录音到内存_第3张图片

看清楚添加参数的格式了哦,没有空格。

Qt各种采样率录音 录音到内存_第4张图片

Qt各种采样率录音 录音到内存_第5张图片

可以看到文件的采样率已经变到16000k了。如果要存到内存中去掉编译参数就可以了,项目可到此下载祝大家工作愉快。





你可能感兴趣的:(Qt)