Qt游戏开发必备!用QtMultimedia播放Ogg格式音乐

来源:互联网 发布:麦当劳四川辣酱 知乎 编辑:程序博客网 时间:2024/05/22 06:18

Qt游戏开发必备!用QtMultimedia播放Ogg格式音乐


QtMultimediaQt4.6提出来的一个音频和视频的新底层。目的是针对开发者提供更加完全的视频和音频控制,同时不损失平台无关性的优点。而Ogg是一个优秀的开源多媒体容器,可以容纳多种编码格式的内容,而大家最为熟知的是Vorbis这个编码格式。这回我将亲自尝试QtMultimedia下播放OggVorbis音乐,而在游戏中播放音乐必不可少。

源代码和演示程序下载地址:这里

我的开发环境:

Ubuntu+ gcc4.4 + QtSDK 4.8.1 + QtCreator2.6

Windows8+ minGW4.4 + QtSDK 4.8.3 + QtCreator2.6

由于OggVorbis开源的性质,导致我们必须亲自解码。网上关于Ogg解码的内容非常少,我也是结合《游戏音频程序设计-Beginning.Game.Audio.Programming》和Ogg的文档才对OggVorbis格式有着一些理解。首先需要下载“libogg-1.3.0”和“libvorbis-1.3.2”这两个软件开发包。可以在xiph.org上(http://www.xiph.org/)得到这两个软件开发包(也可以下载我的源代码,那里面附带了oggvorbis的源代码和项目文件)。然后解压,软件开发包中附带了VisualStudio的项目文件,而我使用的是QtCreator2.6,所以我在阅读了VisualStudio的项目文件之后自己写了一个.pro文件来生成OggVorbis的静态库。大家可以到我的资源中下载相关的项目文件。(原创博客,反对未引用的转载。http://blog.csdn.net/jiangcaiyang123)

构建后获得了libOgglibVorbislibVorbisFile三个静态库,我们就可以使用现有的库函数构建我们的实验了。

下面是我定义的QOggVorbis类的声明:

#ifndef_QOGGVORBIS_H_

#define_QOGGVORBIS_H_


#include<QObject>

#include<QString>

#include<QStringList>


#defineDECLRARE_PROPERTY_WITH_GETTERS(aType,aProperty)private:\

aTypem_##aProperty;public:\

aTypeaProperty(void){returnm_##aProperty;}


structOggVorbis_File;//前向声明


classQOggVorbis:publicQObject

{

Q_OBJECT

Q_PROPERTY(quint16audioFormatREADaudioFormat)

Q_PROPERTY(quint16channelsREADchannels)

Q_PROPERTY(quint32sampleRateREADsampleRate)

Q_PROPERTY(quint32byteRateREADbyteRate)

Q_PROPERTY(quint16blockAlignREADblockAlign)

Q_PROPERTY(quint16bitsPerSampleREADbitsPerSample)

Q_PROPERTY(QStringListuserCommentsREADuserComments)

Q_PROPERTY(QStringvendorREAD vendor)

Q_PROPERTY(qint8*dataREAD data )

Q_PROPERTY(quint32dataSizeREADdataSize)

public:

QOggVorbis(void);

QOggVorbis(constQString&fileName);

~QOggVorbis(void);

boolload(constQString&fileName);

voidclear(void);

private:

boolgetComment(OggVorbis_File*vf);

booldecode(OggVorbis_File*vf);

DECLRARE_PROPERTY_WITH_GETTERS(quint16,audioFormat)

DECLRARE_PROPERTY_WITH_GETTERS(quint16,channels)

DECLRARE_PROPERTY_WITH_GETTERS(quint32,sampleRate) //也就是频率Frequency

DECLRARE_PROPERTY_WITH_GETTERS(quint32,byteRate)

DECLRARE_PROPERTY_WITH_GETTERS(quint16,blockAlign)

DECLRARE_PROPERTY_WITH_GETTERS(quint16,bitsPerSample) //也就是SampleRate

DECLRARE_PROPERTY_WITH_GETTERS(QStringList,userComments)

DECLRARE_PROPERTY_WITH_GETTERS(QString,vendor)

DECLRARE_PROPERTY_WITH_GETTERS(qint8*,data)

DECLRARE_PROPERTY_WITH_GETTERS(quint32,dataSize)

};


#endif// _QOGGVORBIS_H_


这里使用Q_PROPERTY宏来对这个类进行moc,可以通过setProperty()函数和getProperty()函数来获得成员的值,而DECLRARE_PROPERTY_WITH_GETTERS是一个自定义的宏,用来定义一个数据成员和一个Getter。由于Qt中有些类(如QString)是隐式共享(implicitsharing)的,返回变量还是它的引用都没有关系。一些私有的成员函数由于传值需要用到OggVorbis_File结构,而又不想破坏它的封装性,只有先前向声明OggVorbis_File结构,再将结构的指针作为参数进行传递。

进行QtMultimedia的编程,需要使用QAudioFormatQAudioDeviceInfoQAudioOutput这三个类。首先用QAudioFormat设置音频的格式,然后用这种格式来匹配QaudioDeviceInfo,随后利用QAudioFormatQAudioDeviceInfo的信息来创建QAudioOutput的对象。最后利用QAudioOutput的对象(或对象指针)进行播放。下面是相关的代码:

//main.cpp主函数所在的空间

//201312119:33:17By jiangcaiyang


#include<QCoreApplication>

#include<QBuffer>

#include<QtMultimedia>

#include<QtDebug>

#include"QOggVorbis.h"


classTestAudio

{

public:

TestAudio(void)

{

}

~TestAudio(void)

{

Release();

}

boolLoadOggFile(constQString&fileName)

{

if(!m_OggVorbis.load(fileName))returnfalse;


quint32sampleRate=m_OggVorbis.sampleRate();

quint16channels=m_OggVorbis.channels();

quint16sampleSize=m_OggVorbis.bitsPerSample();

QStringListcomments=m_OggVorbis.userComments();

QListIterator<QString>iterCmts(comments);


qDebug()<<"Ogg file information: "<<

"[sampleRate:"<<sampleRate<<

"][channels:"<<channels<<

"][sampleSize:"<<sampleSize<<

']';


//显示Ogg文件额外信息

qDebug()<<"Ogg comments: ";

while(iterCmts.hasNext())

{

qDebug()<<iterCmts.next();

}


//设置音频格式

m_Format.setSampleRate(sampleRate);

m_Format.setChannelCount(channels);

m_Format.setSampleSize(sampleSize);

m_Format.setCodec("audio/pcm");

m_Format.setByteOrder(QAudioFormat::LittleEndian);

m_Format.setSampleType(QAudioFormat::SignedInt);


//初始化音频设备

m_DeviceInfo=QAudioDeviceInfo::defaultOutputDevice();

if(!m_DeviceInfo.isFormatSupported(m_Format))

{

qDebug()<<"Cannot support this format, try acorresponding format.\n";

m_Format=m_DeviceInfo.nearestFormat(m_Format);

}


m_Buffer.setData((constchar*)m_OggVorbis.data(),m_OggVorbis.dataSize());

m_pOutput=newQAudioOutput(m_DeviceInfo,m_Format,0);

returntrue;

}

voidPlay(void)

{

m_Buffer.open(QIODevice::ReadOnly);

m_pOutput->start(&m_Buffer);

}

voidRelease(void)

{

m_Buffer.close();

deletem_pOutput;

m_pOutput=0;

}

private:

QAudioFormatm_Format;

QAudioDeviceInfom_DeviceInfo;

QOggVorbism_OggVorbis;

QAudioOutput*m_pOutput;

QBufferm_Buffer;

};


intmain(intargc,char*argv[])

{

QCoreApplicationa(argc,argv);


//读取并且播放

TestAudiotestAudio;

if(!testAudio.LoadOggFile("../TestSound.ogg"))return1;

qDebug()<<"Read test sound successful!\n";

testAudio.Play();

qDebug()<<"Now Playing audio!\n";

returna.exec();

}


原创粉丝点击