QT-播放原始PCM音频流

这篇具有很好参考价值的文章主要介绍了QT-播放原始PCM音频流。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

QT +=  multimedia

audioplay.h

/*************************************************************************
接口描述:原始音频播放类
拟制:
接口版本:V1.0
时间:20220922
说明:
*************************************************************************/

#ifndef AUDIOPLAY_H
#define AUDIOPLAY_H

#include <QAudioFormat>
#include <QAudioOutput>
#include <QMutex>
#include <QThread>

class AudioThread;
class AudioPlay : public QObject
{
    Q_OBJECT
public:
    explicit AudioPlay(QObject *parent = nullptr);
    ~AudioPlay();

public:
    void inputVoice(char *pcVoice, int nLen);   //PCM数据输入
    void setSampleRate(int nSampleRate);        //设置采样率
    void stop();                                //停止播放

signals:
    void sendDataSignal(QByteArray qbaData);
    void inputVoiceSignal(QByteArray qbaData);
    void setSampleRateSignal(int nSampleRate);
    void stopAudio();

private slots:
    void audioStateChanged(QAudio::State state);

private:
    QAudioFormat m_audioFormat;

    int m_nSampleRate;
    bool m_bAudioOpen;

    QAudioOutput *m_pAudioOutput;
    AudioThread *m_pAudioThread;
    QThread *m_pThread;

private:
    void audioPlay();
    void setFormat();
    void releaseAudio();
};

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

public:
    void inputData(char *pcData, int nLen);
    void start();
    void stop();

    // QIODevice interface
protected:
    qint64 readData(char *data, qint64 maxlen);
    qint64 writeData(const char *data, qint64 len);
    qint64 bytesAvailable() const;

private:
    QByteArray m_qbaAudioBuffer;
};

class AudioThread : public QObject
{
    Q_OBJECT
public:
    explicit AudioThread(QAudioOutput *pAudioOutput, QObject *parent = nullptr);
    ~AudioThread();

public slots:
    void inputData(QByteArray qbaData);

private:
    QAudioOutput *m_pAudioOutput;
    AudioDevice *m_pAudioDevice;
};

#endif // AUDIOPLAY_H

audioplay.cpp文章来源地址https://www.toymoban.com/news/detail-664762.html

#include "audioplay.h"
#include <QDebug>

static QMutex m_mutex;

AudioPlay::AudioPlay(QObject *parent)
    : QObject(parent)
{
    m_nSampleRate = 8000;
    m_bAudioOpen = false;
    m_pAudioOutput = nullptr;
    m_pAudioThread = nullptr;
    setFormat();
    m_pThread = new QThread;
    m_pThread->start();
    connect(this,
            &AudioPlay::inputVoiceSignal,
            this,
            [&](QByteArray qbaData) {
        if (!m_bAudioOpen) {
            audioPlay();
        }
        emit sendDataSignal(qbaData);
    },
    Qt::QueuedConnection);

    connect(this,
            &AudioPlay::setSampleRateSignal,
            this,
            [&](int nSampleRate) {
        if (m_nSampleRate != nSampleRate) {
            m_nSampleRate = nSampleRate;
            setFormat();
        }
    },
    Qt::QueuedConnection);

    connect(this, &AudioPlay::stopAudio, this, [&] {
        m_bAudioOpen = false;
        releaseAudio();
    });
}

AudioPlay::~AudioPlay()
{
    releaseAudio();
    m_pThread->exit();
    if (m_pThread != nullptr) {
        m_pThread->deleteLater();
        m_pThread = nullptr;
    }
}

void AudioPlay::inputVoice(char *pcVoice, int nLen)
{
    emit inputVoiceSignal(QByteArray(pcVoice, nLen));
}

void AudioPlay::setSampleRate(int nSampleRate)
{
    emit setSampleRateSignal(nSampleRate);
}

void AudioPlay::stop()
{
    emit stopAudio();
}

void AudioPlay::audioStateChanged(QAudio::State state)
{
    switch (state) {
    case QAudio::IdleState:
        m_bAudioOpen = false;
        releaseAudio();
        setFormat();
        break;
    default:
        break;
    }
}

void AudioPlay::audioPlay()
{
    QList<QAudioDeviceInfo> outputDevices = QAudioDeviceInfo::availableDevices(QAudio::AudioOutput);
    if (outputDevices.size() <= 0) {
        return;
    }
    if (m_pAudioOutput == nullptr) {
        m_pAudioOutput = new QAudioOutput(m_audioFormat);
        connect(m_pAudioOutput, &QAudioOutput::stateChanged, this, &AudioPlay::audioStateChanged);
        if (m_pAudioThread) {
            m_pAudioThread->deleteLater();
            m_pAudioThread = nullptr;
        }

        m_pAudioThread = new AudioThread(m_pAudioOutput);
        m_pAudioThread->moveToThread(m_pThread);

        connect(this,
                &AudioPlay::sendDataSignal,
                m_pAudioThread,
                &AudioThread::inputData,
                Qt::QueuedConnection);
    }
    m_bAudioOpen = true;
}

void AudioPlay::setFormat()
{
    if (m_pAudioOutput != nullptr) {
        m_pAudioOutput->reset();
        m_pAudioOutput->start();
    }
    //设置采样率
    m_audioFormat.setSampleRate(m_nSampleRate);
    //设置通道数
    m_audioFormat.setChannelCount(1);
    //设置采样大小,一般为8位或16位
    m_audioFormat.setSampleSize(16);
    //设置编码方式
    m_audioFormat.setCodec("audio/pcm");
    //设置字节序
    m_audioFormat.setByteOrder(QAudioFormat::LittleEndian);
    //设置样本数据类型
    m_audioFormat.setSampleType(QAudioFormat::SignedInt);
}

void AudioPlay::releaseAudio()
{
    if (m_pAudioThread != nullptr) {
        m_pAudioThread->deleteLater();
        m_pAudioThread = nullptr;
    }
    if (m_pAudioOutput != nullptr) {
        m_pAudioOutput->stop();
        m_pAudioOutput->deleteLater();
        m_pAudioOutput = nullptr;
    }
}

AudioDevice::AudioDevice(QObject *parent)
    : QIODevice(parent)
{
    QMutexLocker locker(&m_mutex);
    m_qbaAudioBuffer.clear();
}

void AudioDevice::inputData(char *pcData, int nLen)
{
    QMutexLocker locker(&m_mutex);
    m_qbaAudioBuffer.append(pcData, nLen);
}

void AudioDevice::start()
{
    if (!this->isOpen()) {
        open(QIODevice::ReadOnly);
    }
}

void AudioDevice::stop()
{
    QMutexLocker locker(&m_mutex);
    m_qbaAudioBuffer.clear();
    this->close();
}

qint64 AudioDevice::bytesAvailable() const
{
    QMutexLocker locker(&m_mutex);
    qint64 llReturn = m_qbaAudioBuffer.size() + QIODevice::bytesAvailable();
    return llReturn;
}

qint64 AudioDevice::readData(char *data, qint64 maxlen)
{
    QMutexLocker locker(&m_mutex);
    memset(data, 0, maxlen);
    if (m_qbaAudioBuffer.size() < maxlen) {
        maxlen = m_qbaAudioBuffer.size();
    }
    if (maxlen > 0) {
        memcpy(data, m_qbaAudioBuffer.left(maxlen).data(), maxlen);
        m_qbaAudioBuffer.remove(0, maxlen);
    }

    return maxlen;
}

qint64 AudioDevice::writeData(const char *data, qint64 len)
{
    Q_UNUSED(data);
    Q_UNUSED(len);
    return 0;
}

AudioThread::AudioThread(QAudioOutput *pAudioOutput, QObject *parent)
    : QObject(parent)
{
    m_pAudioOutput = nullptr;
    m_pAudioDevice = nullptr;

    m_pAudioDevice = new AudioDevice(this);
    m_pAudioDevice->start();
    m_pAudioOutput = pAudioOutput;
    m_pAudioOutput->start(m_pAudioDevice);
}

AudioThread::~AudioThread()
{
    if (m_pAudioDevice != nullptr) {
        m_pAudioDevice->stop();
        m_pAudioDevice->deleteLater();
        m_pAudioDevice = nullptr;
    }
}

void AudioThread::inputData(QByteArray qbaData)
{
    if (m_pAudioDevice != nullptr) {
        m_pAudioDevice->inputData(qbaData.data(), qbaData.size());
    }
}

到了这里,关于QT-播放原始PCM音频流的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【音视频|PCM】PCM格式详解

    😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀 🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C++、数据结构、音视频🍭 🤣本文内容🤣:🍭介绍数字音频的PCM格式🍭 😎金句分享😎:🍭子曰:君子不器。 ——《论语·为政篇》。意思是,君子不应像器具那样,只有一种用

    2024年02月08日
    浏览(28)
  • 音视频 ffmpeg命令提取PCM数据

    提取PCM 推荐一个零声学院项目课,个人觉得老师讲得不错,分享给大家: 零声白金学习卡(含基础架构/高性能存储/golang云原生/音视频/Linux内核) https://xxetb.xet.tech/s/VsFMs

    2024年02月09日
    浏览(45)
  • 浏览器网页内嵌Qt-C++音视频播放器的实现,支持软硬解码,支持音频,支持录像截图,支持多路播放等,提供源码工程下载

        在浏览器中实现播放RTSP实时视频流,⼤体上有如下⼏个⽅案: ⽅案一:浏览器插件⽅案 ActiveX、NPAPI、PPAPI     ActiveX插件适用于IE浏览器,NPAPI与PPAPI插件适用于谷歌浏览器,不过这些插件都已经不被浏览器所支持。 ⽅案二:先转码再转流⽅案     ⼯作原理是架设一

    2024年01月17日
    浏览(66)
  • 音视频编码实战-------pcm+yuv数据转成MP4

    avcodec_find_encoder: 根据编码器ID查找编码器 avcodec_alloc_context3:创建编码器上下文 avcodec_open2:打开编码器 avformat_alloc_output_context2:为输出格式创建复用器上下文 avformat_new_stream:创建音视频流 avcodec_parameters_from_context:将编码器上下文中的参数拷贝到音视频流中的编码器参数中AVCodec

    2024年02月15日
    浏览(47)
  • 使用Qt进行音视频播放

      Qt对音视频的播放和控制,相机拍照,收音机等多媒体应用提供了强大的支持。Qt5使用了全新的Qt Multimedia模块来实现多媒体应用,而原来Qt4中用于实现多媒体功能的Phonon模块已经被移除。   新的Qt Multimedia模块提供了丰富的接口,使读者可以轻松地使用平台的多媒体功

    2024年02月03日
    浏览(30)
  • Qt之基于QMediaPlayer的音视频播放器(支持常见音视频格式)

    Qt自带了一个Media Player的例子,如下图所示: 但是运行这个例子机会发现,连最基本的MP4格式视频都播放不了。因为QMediaPlayer是个壳(也可以叫框架),依赖本地解码器,视频这块默认基本上就播放个MP4,甚至连MP4都不能播放,如果要支持其他格式需要下载k-lite或者LAVFilter

    2024年02月02日
    浏览(48)
  • 音视频开发系列(10):基于qt的音频推流

    今天分享一下利用qt录制音频,然后再利用ffmpeg推流到nginx服务器,最后再利用vlc进行拉流的demo。 首先介绍一下如何利用qt来进行音频的录制,qt的音频录制主要利用qt的QAudioFormat先进行音频信息的配置。主要需要配置以下的信息: 然后使用QAudioDeviceInfo来获取是否支持改设置

    2024年02月02日
    浏览(43)
  • Qt 多媒体音频模拟按钮发音(音视频启动)

    ## 项目演示 平台 :windows或者ubuntu  要求 :平台需要支持音频播放功能 文件格式 :.wav 可以使用剪映生成,音频部分,我这里是简短的音乐 # Qt 多媒体简介 Qt QSound是Qt框架中的一个类,用于播放音频文件。它可以在Qt应用程序中实现简单的音频播放功能,包括播放、暂停和停

    2024年02月03日
    浏览(39)
  • FFMpeg-3、基于QT实现音视频播放显示

    1、音视频播放的基础知识 内容来自雷神博客 1、在Windows平台下的视频播放技术主要有以下三种:GDI,Direct3D和OpenGL;音频播放技术主要是DirectSound。 SDL本身并不具有播放显示的功能,它只是封装了底层播放显示的代码 记录三种视频显示技术:GDI,Direct3D,OpenGL。其中Direct3D包

    2024年02月03日
    浏览(47)
  • 原始PCM录制与播放

    来源:https://blog.csdn.net/liupin2008/article/details/124347278 arecord和aplay是alsa-utils一部分,我们在Linux系统下进行音频开发时经常使用,非常方便。 先简单介绍一下。 arecord 采集原始音频 arecord -r 8000 -t raw -c 1 -f S16_BE ./test aplay 播放原始音频 aplay -t raw -r 8000 -f S16_BE -c 1 ./test 参数说明:

    2023年04月26日
    浏览(23)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包