Qt播放PCM音频(裸流)文件的两种方法

来源:互联网 发布:matlab的gui编程实例 编辑:程序博客网 时间:2024/05/05 01:43

        这两种方法都需要在.pro文件中加入multimedia模块。方法一是通过QAudioOutput实现的,先用QFile打开PCM文件,然后进行音频参数设置,最后调用QAudioOutput的start函数进行播放;方法二也用到了QAudioOutput,先将PCM文件读取到内存,然后进行音频参数设置,最后从内存中定时读取部分数据,调用QIODevice的write函数将这部分数据写入到扬声器。与方法一相比,方法二虽然麻烦,但是这种方法是进行语音编解码和语音网络传输的基础。

方法一:

#include <QApplication>#include <QFile>#include <QAudioFormat>#include <QAudioOutput>int main(int argc, char *argv[]){    QApplication a(argc, argv);    QFile inputFile;    inputFile.setFileName("test.pcm");    inputFile.open(QIODevice::ReadOnly);    //设置采样格式    QAudioFormat audioFormat;    //设置采样率    audioFormat.setSampleRate(44100);    //设置通道数    audioFormat.setChannelCount(2);    //设置采样大小,一般为8位或16位    audioFormat.setSampleSize(16);    //设置编码方式    audioFormat.setCodec("audio/pcm");    //设置字节序    audioFormat.setByteOrder(QAudioFormat::LittleEndian);    //设置样本数据类型    audioFormat.setSampleType(QAudioFormat::UnSignedInt);    QAudioOutput *audio = new QAudioOutput( audioFormat, 0);    audio->start(&inputFile);    return a.exec();}
方法二:

Widget::Widget(QWidget *parent) :    QWidget(parent),    ui(new Ui::Widget){    ui->setupUi(this);    //获取文件的指针    FILE *file=fopen("test.pcm","rb");    if(!file)    {        qDebug()<<"Open Failed";        return;    }    //把指针移动到文件的结尾 ,获取文件长度    fseek(file,0,SEEK_END);    //获取文件长度    fileLength=ftell(file);    //定义数组长度    fileBuffer=new char[fileLength+1];    //把指针移动到文件开头 因为我们一开始把指针移动到结尾,如果不移动回来 会出错    rewind(file);    //读文件    fread(fileBuffer,1,fileLength,file);    //把读到的文件最后一位 写为0 要不然系统会一直寻找到0后才结束    fileBuffer[fileLength]=0;    //关闭文件    fclose(file);    qDebug()<<fileLength;    //设置采样格式    QAudioFormat audioFormat;    //设置采样率    audioFormat.setSampleRate(44100);    //设置通道数    audioFormat.setChannelCount(2);    //设置采样大小,一般为8位或16位    audioFormat.setSampleSize(16);    //设置编码方式    audioFormat.setCodec("audio/pcm");    //设置字节序    audioFormat.setByteOrder(QAudioFormat::LittleEndian);    //设置样本数据类型    audioFormat.setSampleType(QAudioFormat::UnSignedInt);    //音频设备信息    QAudioDeviceInfo info = QAudioDeviceInfo::defaultOutputDevice();    if (!info.isFormatSupported(audioFormat)) {        qDebug()<<"default format not supported try to use nearest";        audioFormat = info.nearestFormat(audioFormat);    }    audioOutput = new QAudioOutput(audioFormat, this);    streamOut = audioOutput->start();    //定时器    timer=new QTimer(this);    connect(timer, SIGNAL(timeout()), SLOT(slotTimeout()));  }
void Widget::slotTimeout(){    static int i=0;    if(i<fileLength/1764)    {        tempBuffer.append(fileBuffer+i*1764,1764);        if(audioOutput&&audioOutput->state()!=QAudio::StoppedState&&                audioOutput->state()!=QAudio::SuspendedState)        {            int chunks = audioOutput->bytesFree()/audioOutput->periodSize();            while (chunks)            {                if (tempBuffer.length() >= audioOutput->periodSize())                {                    //写入到扬声器                    streamOut->write(tempBuffer.data(),audioOutput->periodSize());                    tempBuffer = tempBuffer.mid(audioOutput->periodSize());                }                else                {                    //写入到扬声器                    streamOut->write(tempBuffer);                    tempBuffer.clear();                    break;                }                --chunks;            }        }    }    i++;}
PCM裸流1秒的数据量是44100×16×2/8=176400字节,那么10毫秒的数据量就是1764字节,所以定时器定时10毫秒,每隔10毫秒从数组中顺序读取1746个字节。


PCM音频文件的制作参考:http://blog.csdn.net/caoshangpa/article/details/51218994

音频参数解析参考:http://blog.csdn.net/caoshangpa/article/details/51218597

测试用PCM音频文件下载链接:http://download.csdn.net/detail/caoshangpa/9497751

方法二源码:见http://blog.csdn.net/caoshangpa/article/details/51224678的评论

12 0
原创粉丝点击