当前位置:网站首页>QAudioOutput使用
QAudioOutput使用
2022-06-21 05:22:00 【柠檬野生菌】
QAudioOutput使用
模块和头文件
- 项目文件
.pro中加入
QT += multimedia
- 使用文件中加入头文件
#include <QAudioDeviceInfo>
#include <QAudioFormat>
#include <QAudioOutput>
第一步先获取默认设备
QAudioDeviceInfo audio_device_default = QAudioDeviceInfo::defaultOutputDevice();
qDebug()<<"audio:"<<audio_device_default.deviceName();
第二步初始化
void MainWindow::initAudio(QAudioDeviceInfo &deviceInfo)
{
qDebug()<<"deviceInfo:"<<deviceInfo.deviceName();
QAudioFormat format;
format.setSampleRate(380000); //采样率
format.setChannelCount(1); //通道
format.setSampleSize(32); //采样大小
format.setCodec("audio/pcm"); //解码模式
format.setByteOrder(QAudioFormat::LittleEndian); //小端格式
format.setSampleType(QAudioFormat::Float); //浮点型
if(!deviceInfo.isFormatSupported(format)) //音频设备是否支持该格式
{
qDebug()<<"deviceInfo format No Supported";
format = deviceInfo.nearestFormat(format); //使用最近设备
}
m_audioOutput.reset(new QAudioOutput(deviceInfo, format));
connect(m_audioOutput.get(),&QAudioOutput::stateChanged,this,&MainWindow::audioStateChanged);
device = m_audioOutput->start();
}
void MainWindow::audioStateChanged(QAudio::State state)
{
switch(state)
{
case QAudio::ActiveState:
qDebug()<<"Audio data is being processed...";
break;
case QAudio::IdleState:
qDebug()<<"Play Filish...";
break;
case QAudio::SuspendedState: //音频被暂停
qDebug()<<"SuspendedState";
break;
case QAudio::StoppedState: //设备已关闭
qDebug()<<"StoppedState";
break;
case QAudio::InterruptedState: //被挂起更高优先级在使用设备
qDebug()<<"InterruptedState";
break;
default: break;
}
}
第三步播放音频
- 使用
QAudioOutput::start()函数播放音频 这里start()函数两种实现 所以有两种方法
void QAudioOutput::start(QIODevice *device)
QIODevice *QAudioOutput::start()
第一种方法
- 第一种方式需要继承
QIODevice重写读写函数 具体操作看官方例子
qint64 readData(char *data, qint64 maxlen) override;
qint64 writeData(const char *data, qint64 len) override;
qint64 bytesAvailable() const override;
- 但是如果直接播放音频文件下面这个方式更好 因为文件的读写
IO都继承于QIODevice
void MainWindow::playFile()
{
QString file_name = QFileDialog::getOpenFileName(this,"选择播放文件","./");
if(file_name.isEmpty())
{
return;
}
file.setFileName((file_name)); //file 全局QFile变量
if(!file.open(QIODevice::ReadOnly))
{
qDebug()<<file.errorString();
return;
}
m_audioOutput->start(&file);
//说明:需要在播放结束时(QAudio::IdleState) 关掉文件(file.close())
}
第二种方法
start()返回一个QIODevice*指针 然后使用这个指针的Write()函数进行写入播放数据
void MainWindow::playFile2()
{
QString file_name = QFileDialog::getOpenFileName(this,"选择播放文件","./");
if(file_name.isEmpty())
{
return;
}
QFile in(file_name);
if(!in.open(QIODevice::ReadOnly))
{
qDebug()<<in.errorString();
return;
}
int64_t size = in.size();
qDebug()<<"size:"<<size;
int per_size = m_audioOutput->periodSize();
QByteArray per_buffer(per_size,0);
while (!in.atEnd())
{
if(m_audioOutput->bytesFree() == 0) continue;
if(in.read(per_buffer.data(),per_size) <= 0) break;
device->write(per_buffer.data(),per_size);
//device 是事先获取的 QIODevice指针 initAudio()函数的最后一行
}
in.close();
}
特别说明这里有一个坑
- 如果是自己把文件的数据一股脑的
write数据的size小于bytesFree()(缓冲区可用字节数)还好说, 如果大于bytesFree()就只能听一个响(也就1~2s)。 【别问为啥知道的】 - 所以需要通过
bytesFree()判断缓冲区的可用字节数 每次再往里面写一个周期periodSize()的数据
- 如果是自己把文件的数据一股脑的
播放这里的
while()循环最好写在多线程里面否则会阻塞窗口主线程
其他控制
void MainWindow::on_Button_SuspendResume_clicked()
{
if(m_audioOutput->state() == QAudio::SuspendedState || m_audioOutput->state() == QAudio::StoppedState)
{
m_audioOutput->resume(); //继续
ui->Button_SuspendResume->setText("暂停");
}
else if(m_audioOutput->state() == QAudio::ActiveState)
{
m_audioOutput->suspend(); //暂停
ui->Button_SuspendResume->setText("继续");
}
else if(m_audioOutput->state() == QAudio::IdleState)
{
}
}
//设置音量
void MainWindow::setVolume(int value)
{
qreal linear_volume = QAudio::convertVolume(value/qreal(100),QAudio::LogarithmicVolumeScale,QAudio::LinearVolumeScale);
m_audioOutput->setVolume(linear_volume);
}
参考
- 官方例子: Audio Output Example QtCreator示例 重点参考
- 参考
边栏推荐
- A7.ansible production practice case -- Chrony client roles
- How to remove the prohibition of copying and pasting set by teachers
- Dayjs get the last day of the first day of the current month the last day of the first day of the current year
- How to take anti extortion virus measures for enterprise servers
- 随机创建圆形、三角形或者矩形类的对象, 存放在数组中,并计算出每个形状的面积和周长
- C language: randomly input the scores of each subject in each student, and require each student to rank the average scores of all subjects from low to high to find out the average scores of each stude
- Abnova 11-脱氢-TXB2 ELISA 试剂盒说明书
- 蓝桥杯十三届国赛个人模板------又来一年
- launcher切页动画
- 一文全面解读CKA认证的含金量、详细介绍及考试攻略
猜你喜欢

At mode explanation and code implementation of Seata's four modes

Abnova 6-ketone-pgf1- α ELISA Kit instructions

Abbexa HSD11B2 antibody solution

Use of TestNG framework (I): idea installation TestNG environment

Automobile maintenance management system based on ssm+bootstrap+mysql+thymeleaf

Abbexa HSD11B2 抗体解决方案

七大设计原则

Super classic MySQL common functions, collect them quickly

Idea debug occurs: skipped breakpoint at because it happened inside debugger evaluation

基于SSM+Bootstrap+MySQL+Thymeleaf的汽车维修管理系统
随机推荐
Excel dynamic chart
Steam education subject integrates the intelligent scene of AR
软件研发团队效能提升从点滴做起
Volley 的是使用以及接口
适配器模式Adapter
基于SSM+Bootstrap+MySQL+Thymeleaf的汽车维修管理系统
基于SSM+Hui+MySQL的高校大学生信息管理系统
House sales and leasing system based on ssh+mysql
518. change II
Abnova 11 dehydrogenation TXB2 ELISA Kit instructions
Z-shaped deformation [one of the forms of the law - > periodic investigation]
IDEA Debug出现:Skipped breakpoint at because it happened inside debugger evaluation
Abnova β- Galactosidase recombinant monoclonal antibody protocol
De duplication according to an attribute in the class
Flower sales system based on jsp+servlet+mysql
进程间通信-----aidl
Abbexa GM130 antibody solution
Abnova chicken anti cotton mouse IgG (H & L) secondary antibody (HRP) protocol
批改网如何解除老师设置的禁止复制粘贴
Shell script iterates through the values in the log file to sum and calculate the average, maximum and minimum values