1. 程式人生 > 實用技巧 >5.QT-QAudioOutput類使用

5.QT-QAudioOutput類使用

本章需要用到的類如下:

  • QAudioDeviceInfo類提供音訊輸出裝置
  • QAudioFormat類提供音訊引數設定
  • QAudioOutput類提供了用於將PCM原始音訊資料傳送到音訊輸出裝置的介面。
1.QAudioDeviceInfo類 用來提供音訊輸出裝置,並且包含該裝置支援的格式,排序,通道,編碼器,頻率,取樣率等, 使用者可以通過bool isFormatSupported(const QAudioFormat &settings) 來判斷是否支援該格式.使用者一般通過defaultOutputDevice()來獲取當前預設播放裝置. 如果想獲取所有音訊輸出裝置可以通過availableDevices()成員函式,比如:
foreach
(const QAudioDeviceInfo &deviceInfo, QAudioDeviceInfo::availableDevices(QAudio::AudioOutput)) { qDebug() << "Device name: " << deviceInfo.deviceName(); }

2.QAudioOutput類

常用函式如下所示:
QAudio::Error QAudioOutput::error(); //獲取當前錯誤資訊
void QAudioOutput::suspend(); //暫停
void QAudioOutput::resume(); //
恢復 void QAudioOutput::start(QIODevice *device) //啟動播放,引數是QIODevice(需要通過write成員寫入pcm資料陣列)
QIODevice *QAudioOutput::start(); //開啟裝置並返回一個指向內部QIODevice的指標,通過write()便可以直接向其寫入pcm資料進行播放. QAudio::State QAudioOutput::state(); //獲取當前QAudioOutput狀態,狀態如下所示: //QAudio::ActiveState:正在播放中 //QAudio::SuspendedState:正在暫停中 //QAudio::StoppedState:已被停止,可能是被異常終止了
//QAudio::IdleState:處於空閒中,什麼都沒幹

void QAudioOutput::setVolume(qreal volume); //設定音量 (0.0~1.0之間,預設音量為1.0)
void QAudioOutput::setBufferSize(int value); //重新設定緩衝區大小,需要在start()之前設定
int QAudioOutput::bufferSize() const//獲取緩衝區大小,預設為35280,需要start()後,才分配buff
int QAudioOutput::bytesFree() //返回音訊緩衝區中可用的空閒位元組數。 //注意:返回值僅在QAudio::ActiveState或QAudio::IdleState狀態下有效,否則返回零。

int QAudioOutput::periodSize(); //週期大小(以位元組為單位),每播放一次音訊資料所需多少個數據量
                    //periodSize用來防止緩衝區欠執行和確保不間斷回放所需的資料量

3.初始化QAudioOutput 開始播放音訊流只需使用QIODevice呼叫start()即可。然後QAudioOutput將從io裝置中獲取所需的資料。所以播放音訊檔案是簡單的如下:
QFile sourceFile;  
QAudioOutput* audio; 
sourceFile.setFileName("/tmp/test.raw");
sourceFile.open(QIODevice::ReadOnly);
 
QAudioFormat format;
// Set up the format, eg.
format.setSampleRate(44100); //設定取樣率
format.setChannelCount(1); //設定通道數
format.setSampleSize(16); //樣本資料16位
format.setCodec("audio/pcm"); //播出格式為pcm格式
format.setByteOrder(QAudioFormat::LittleEndian); //預設小端模式
format.setSampleType(QAudioFormat::UnSignedInt); //無符號整形數
 
QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice()); //選擇預設輸出裝置
 
if (!info.isFormatSupported(format))
{
qDebug()<<"輸出裝置不支援該格式,不能播放音訊";
return;
}
 
audio = new QAudioOutput(format, this);
connect(audio, SIGNAL(stateChanged(QAudio::State)),this,SLOT(handleStateChanged(QAudio::State)));
 
audio->start(&sourceFile);
}

檔案在播放過程中, 當遇到錯誤時,狀態更改為QAudio::StoppedState,併發送stateChanged()訊號函式,這時可以通過error()函式獲取錯誤資訊,注意:檔案播放結束(QAudio::IdleState)後,需要停止裝置:

void AudioOutputExample::handleStateChanged(QAudio::State newState)
{
    switch (newState) {
        case QAudio::IdleState:
            // 資料已經沒有了,播放完畢
            audio->stop();
            sourceFile.close();
            delete audio;
            break;
         
        case QAudio::StoppedState:
                // 音訊裝置已關閉,檢查error是否異常關閉
                if (audio->error() != QAudio::NoError) {
                // Error handling
                }
                break;
         
        case QAudio::SuspendedState:
            // 音訊被暫停
            break;
            
            
        case QAudio::ActiveState:
            // 啟動音訊播放,正在解析中
            break;
    }
}

4.補充說明

由於QAudioOutput支援的輸入資料必須是原始資料,所以播放mp3,WAV,AAC等格式檔案,需要解封裝後才能支援播放.

而在QT中,提供了QMediaPlayer類可以支援解封裝,但是該類的解碼協議都是基於平臺的,如果平臺自身無法播放,那麼QMediaPlayer也無法播放.有興趣的朋友可以去試試.

所以接下來,我們使用ffmpeg+QAudioOutput來實現一個簡單的音訊播放器

未完待續~