Qt 之 qt 实时采集麦克风数据并云端请求

背景

项目中用到了图灵的语音翻译功能,实现了实时采集麦克风数据并asr以及翻译

解决方案

QT中有一个强大的音频处理的库,可以设置采集的参数,指定采集的设备等,这个强大的类就是QAudioInput,下面介绍如何通过这个类实现音频的设置,采集和保存

QAudioInput属于multimedia模块,故我们在pro文件需要 QT += multimedia
采集音频的参数设置通过QAudioFormat 来设置,告诉计算机应该以什么样的方式进行数据采集,如采样率、声道数量、编码方式等;采用QAudioInput获取声卡输出,即采集麦克风数据,重写iodevcie的 qint64 writeData(const char * data, qint64 maxSize)函数即可实现此功能

QIODevice类是Qt中所有I/O设备的抽象基类,为支持读写数据块的设备提供了通用实现和其他接口。由于是抽象类,因此使用时不能直接实例化,要使用其派生类,如QFile、QBuffer和QTcpSocket。

.h

class VoiceDataSource : public QIODevice
{
    Q_OBJECT
public:
    explicit VoiceDataSource(QObject *parent = nullptr);

    static VoiceDataSource *GetInstance();

    Q_INVOKABLE void startRecord();
    Q_INVOKABLE void stopRecord();
    Q_INVOKABLE void saveAsWavFile();
    Q_INVOKABLE QByteArray getVoiceData();
    Q_INVOKABLE QByteArray convertUlrData();
    Q_INVOKABLE void setResJsonData(QJsonValue resultObj);
    Q_INVOKABLE bool isStart();
    Q_INVOKABLE QByteArray getSrcString();
    Q_INVOKABLE QByteArray getDesString();
    void addVoipData(const QByteArray &data)
    {
        emit sig_getVoipData(data);
    }

signals:
    void sig_getVoipData(const QByteArray &data);
protected:
    qint64 readData(char * data, qint64 maxSize);
    qint64 writeData(const char * data, qint64 maxSize);
private:

    void startHrsc();

    QScopedPointer<QAudioInput> m_audioInput;
    WavFileHead  m_wavFileHead;
    QByteArray   m_audioData;
    QByteArray   m_src;
    QByteArray   m_des;

};

.cpp 核心函数实现

qint64 VoiceDataSource::writeData(const char * data, qint64 maxSize)
{
#ifdef Q_OS_WINDOWS
    m_audioData.append(data, maxSize);
    if(TransWebSocket::GetInstance()->isReady())
    {
        TransWebSocket::GetInstance()->sendApiSpeechData(QByteArray(data,maxSize));
        qDebug() << "write size =" << maxSize << m_audioData.size();
    }
#endif
    return maxSize;
}

void VoiceDataSource::startRecord()
{

#ifdef Q_OS_WINDOWS
    m_audioData.clear();
#endif

    bool b = open(QIODevice::WriteOnly);
    qDebug() << "startRecord open res=" << b;

    int sampleRate = 16000;
#ifdef Q_OS_LINUX
    int channels = 3;
#endif

#ifdef Q_OS_WINDOWS
    int channels = 1;
#endif

    int sampleSize = 16;

    QAudioFormat formatAudio;
    formatAudio.setSampleRate(sampleRate);
    formatAudio.setChannelCount(channels);
    formatAudio.setSampleSize(sampleSize);
    formatAudio.setCodec("audio/pcm");
    formatAudio.setByteOrder(QAudioFormat::LittleEndian);
    //formatAudio.setSampleType(QAudioFormat::UnSignedInt);
    formatAudio.setSampleType(QAudioFormat::SignedInt);

    QAudioDeviceInfo inputDevices = QAudioDeviceInfo::defaultInputDevice();
    if (!inputDevices.isFormatSupported(formatAudio)) {
        qWarning() << "Default format not supported - trying to use nearest";
        formatAudio = inputDevices.nearestFormat(formatAudio);
    }

    m_audioInput.reset(new QAudioInput(inputDevices, formatAudio));
    m_audioInput->start(this);
}

void VoiceDataSource::stopRecord()
{
    if(m_audioInput->state() == QAudio::StoppedState)
    {
        return;
    }
    qDebug() << "VoiceDataSource::stopRecord()";
    m_audioInput->stop();
}

void VoiceDataSource::saveAsWavFile()
{
    QFile f("voice.pcm");

    bool bisOk = f.open(QIODevice::WriteOnly);
    if(bisOk == true)
    {
#ifdef Q_OS_WINDOWS
        f.write(m_audioData.data(), m_audioData.size());
#endif
        f.close();

    }else{
        qDebug() << "voice file open failed";
    }

#ifdef Q_OS_WINDOWS
        m_audioData.clear();
#endif
}

扩展

由于采集的是pcm数据,所以发送的数据比较大,如果想进一步优化的话,可以对采集的到pcm数据进行编码,常用的编码opus 等

什么是PCM?
PCM(Pulse Code Modulation,脉冲编码调制)音频数据是未经压缩的音频采样数据裸流,它是由模拟信号经过采样、量化、编码转换成的标准数字音频数据。

描述PCM数据的6个参数:

Sample Rate : 采样频率。8kHz(电话)44.1kHz(CD)48kHz(DVD)
Sample Size : 量化位数。通常该值为16-bit。
Number of Channels : 通道个数。常见的音频有立体声(stereo)和单声道(mono)两种类型,立体声包含左声道和右声道。另外还有环绕立体声等其它不太常用的类型。
Sign : 表示样本数据是否是有符号位,比如用一字节表示的样本数据,有符号的话表示范围为-128 ~ 127,无符号是0 ~ 255
Byte Ordering : 字节序。字节序是little-endian还是big-endian。通常均为little-endian。字节序说明见第4节。
Integer Or Floating Point : 整形或浮点型。大多数格式的PCM样本数据使用整形表示,而在一些对精度要求高的应用方面,使用浮点类型表示PCM样本数据。
什么是WAV
WAV:wav是一种无损的音频文件格式,WAV符合 PIFF(Resource Interchange File Format)规范。所有的WAV都有一个文件头,这个文件头音频流的编码参数。WAV对音频流的编码没有硬性规定,除了PCM之外,还有几乎所有支持ACM规范的编码都可以为WAV的音频流进行编码。

WAV和PCM的关系
WAV可以使用多种音频编码来压缩其音频流,不过我们常见的都是音频流被PCM编码处理的WAV,但这不表示WAV只能使用PCM编码,MP3编码同样也可以运用在WAV中,和AVI一样,只要安装好了相应的Decode,就可以欣赏这些WAV了。在Windows平台下,基于PCM编码的WAV是被支持得最好的音频格式,所有音频软件都能完美支持,由于本身可以达到较高的音质的要求,因此,WAV也是音乐编辑创作的首选格式,适合保存音乐素材。因此,基于PCM编码的WAV被作为了一种中介的格式,常常使用在其他编码的相互转换之中,例如MP3转换成WMA。

简单来说:pcm是无损wav文件中音频数据的一种编码方式,但wav还可以用其它方式编码。
  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值