本章需要用到的類如下:
- 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來實現一個簡單的音頻播放器
未完待續,下章學習:11.QT-ffmpeg+QAudioOutput實現音頻播放器