本章需要用到的类如下:
- 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实现音频播放器