当前位置:网站首页>【音视频开发系列】QT 采集麦克风PCM并播放
【音视频开发系列】QT 采集麦克风PCM并播放
2022-08-04 05:34:00 【_杜竞宁_】
[注] 调试前请先戴耳机,作为测试使用,没有项目的严谨,需要自调,适合做回声消除类似的测试用例
项目地址:https://github.com/dujingning/PcmCaptureAndPlay
1.创建 QT 项目
2.pro文件添加
QT += multimedia
3添加类 .PcmCaptureAndPlay
①pcmcaptureandplay.h
/* * auth: dujingning * date: 2022.05.03 * licenst: MIT */
#ifndef PCMCAPTUREANDPLAY_H
#define PCMCAPTUREANDPLAY_H
#include <QThread>
#include <QDebug>
#include <QTimer>
#include <QFile>
#include <QAudio>
#include <QAudioFormat>
#include <QAudioInput>
#include <QAudioOutput>
#include <QIODevice>
class PcmCaptureAndPlay: public QThread
{
Q_OBJECT
public:
PcmCaptureAndPlay();
private: /* QT audio play */
QAudioFormat qAudioFormat;
QAudioOutput *out;
QIODevice *audioIO;
QTimer *audioPlayTimer;
QThread *timerTHread;
bool initQtAudioForPlay();
private: /* QT audio capture */
QAudioFormat format;
QAudioInput* audioInput;
QIODevice *qIODevice;
QFile file; // 可以输出到文件,咱不用,直接播
bool initQtAudioForCapture();
private: /* QT audio capture */
void audioCaptureAndPlay();
public slots:
void onReadyRead(); /*采集并填充*/
public:
void run();
};
#endif // PCMCAPTUREANDPLAY_H
② pcmcaptureandplay.cpp
#include "PcmCaptureAndPlay.h"
PcmCaptureAndPlay::PcmCaptureAndPlay()
{
}
bool PcmCaptureAndPlay::initQtAudioForPlay()
{
qAudioFormat.setSampleRate(16000);
qAudioFormat.setChannelCount(1);
qAudioFormat.setSampleSize(16);
qAudioFormat.setCodec("audio/pcm");
qAudioFormat.setByteOrder(QAudioFormat::LittleEndian);
qAudioFormat.setSampleType(QAudioFormat::SignedInt);
out = new QAudioOutput(qAudioFormat);
if (!out) {
return false;
}
audioIO = out->start();
return true;
}
bool PcmCaptureAndPlay::initQtAudioForCapture()
{
qIODevice = nullptr;
format.setSampleRate(16000);
format.setChannelCount(1); // 设定声道数目,mono(平声道)的声道数目是1;stero(立体声)的声道数目是2
format.setSampleSize(16); // 采样位深
format.setCodec("audio/pcm"); // 设置唯一支持的codec
format.setByteOrder(QAudioFormat::LittleEndian);
format.setSampleType(QAudioFormat::SignedInt);
QAudioDeviceInfo info = QAudioDeviceInfo::defaultInputDevice();
if (!info.isFormatSupported(format))
{
format = info.nearestFormat(format);
}
file.setFileName("test.raw");
file.open( QIODevice::WriteOnly | QIODevice::Truncate );
audioInput = new QAudioInput(format, nullptr);
qIODevice = audioInput->start(); // 这里可以直接写入到文件,咱不用直接就是播放 audioInput->start(file);
if (qIODevice) {
qDebug() << "device available";
return true;
}
return false;
}
void PcmCaptureAndPlay::onReadyRead()
{
qint64 len = 0, size = 4096;
char buffer[4096]{
0};
len = qIODevice->read(buffer, size); //读取音频
if (len <= 0) {
return;
}
qDebug() << "read pcm size" << len;
qint64 bufferPlay = out->periodSize();
if (out->bytesFree() < bufferPlay) {
//
qDebug() << "play buffer not enough";
return;
}
audioIO->write((const char*)(buffer),len);
}
void PcmCaptureAndPlay::audioCaptureAndPlay()
{
initQtAudioForPlay(); // for play
initQtAudioForCapture(); // for capture
connect(qIODevice, SIGNAL(readyRead()), this, SLOT(onReadyRead()));
}
void PcmCaptureAndPlay::run()
{
audioCaptureAndPlay();
exec();
}
3.使用
PcmCaptureAndPlay *PCAP = new PcmCaptureAndPlay;
PCAP->start();
边栏推荐
猜你喜欢
随机推荐
2020-03-27
IDEA中创建web项目实现步骤
Operating System Kernel
结构体传参-C语言
JVM intro
安全漏洞是如何被发现的?
An abstract class, internal classes and interfaces
淘宝分布式文件系统存储(二)
新冠病毒和网络安全的异同及思考
第九篇 ApplicationContext初始化
对渗透测试工程师来说,学历重要嘛?
罗斯50分
线程池原理
Flask request 返回网页中 checkbox 是否选中
跑跑飞弹室外跑步AR游戏代码方案设计
counting cycle
Uos统信系统控制台欢迎登陆后消息及所处区域配置
JDBC第一学之进行数据库连接时出现The server time zone.....解决办法
位段-C语言
Uos统信系统 DNS









