当前位置:网站首页>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);
}

参考

原网站

版权声明
本文为[柠檬野生菌]所创,转载请带上原文链接,感谢
https://blog.csdn.net/weixin_49500446/article/details/125339438