菜鸟也能学cocos2dx 3.3 AudioCache

菜鸟也能学cocos2dx 3.3 AudioCache,第1张

概述最新的3.3cocos将openal也进行了引入,作为一个引擎使用者,当然是相当的开心!~ 那么我们首先来看一看~ #include "platform/CCPlatformConfig.h"#if CC_TARGET_PLATFORM == CC_PLATFORM_WIN32#ifndef __AUDIO_CACHE_H_#define __AUDIO_CACHE_H_#inclu

最新的3.3cocos将openal也进行了引入,作为一个引擎使用者,当然是相当的开心!~ 那么我们首先来看一看~


#include "platform/CCPlatformConfig.h"#if CC_TARGET_PLATFORM == CC_PLATFORM_WIN32#ifndef __AUdio_CACHE_H_#define __AUdio_CACHE_H_#include <string>#include <mutex>#include <vector>#include "CCPlatformMacros.h"#include "AL/al.h"#define QUEUEBUFFER_NUM 3#define QUEUEBUFFER_TIME_STEP 0.1fNS_CC_BEGINnamespace experimental{//前向声明class AudioEngineImpl;class AudioPlayer;class CC_DLL AudioCache{public:	//文件类型枚举    enum class fileFormat    {        UNKNowN,//未知格式        OGG,// ogg格式音频,常用于androID平台        MP3 // mp3格式音频,ios,androID都较为常用    };    AudioCache();//构造函数    AudioCache(AudioCache&);//拷贝构造函数,值传递和用一个AudioCache去初始化另一个AudioCache的时候使用,尽量避免。    ~AudioCache();//析构函数    voID addCallbacks(const std::function<voID()> &callback);//添加回调,参数为函数指针(形如voID XXX())protected:    voID readDataTask();  //读数据任务    voID invokingCallbacks();//请求回调    std::string _fileFullPath;    fileFormat _fileFormat;    //pcm data related stuff    size_t _pcmDataSize;    ALenum _alBufferFormat;//等于int32_t    int _channels;    ALuint _sampleRate; //等于uint32_t    size_t _bytesPerFrame;    float _duration;        /*Cache related stuff;     * Cache pcm data when sizeInBytes less than PCMDATA_CACHEMAXSIZE     */    ALuint _alBufferID;//等于uint32_t    voID* _pcmData;    size_t _bytesOfRead;    /*Queue buffer related stuff     *  Streaming in OpenAL when sizeInBytes greater then PCMDATA_CACHEMAXSIZE     */    char* _queBuffers[QUEUEBUFFER_NUM];    ALsizei _queBufferSize[QUEUEBUFFER_NUM];    int _queBufferFrames;    int _queBufferBytes;    bool _alBufferReady;    std::mutex _callbackMutex; //c11的互斥锁    std::vector< std::function<voID()> > _callbacks;//vector存放函数指针    std::mutex _readDataTaskMutex;        int _mp3EnCoding;        frIEnd class AudioEngineImpl;//声明友元    frIEnd class AudioPlayer;} ;}NS_CC_END#endif // __AUdio_CACHE_H_#endif
#if CC_TARGET_PLATFORM == CC_PLATFORM_WIN32#include "AudioCache.h"#include <thread>#include <algorithm>#include "base/CCConsole.h"#include "mpg123.h"#include "vorbis/codec.h"#include "vorbis/vorbisfile.h"#include "base/ccUtils.h"#define PCMDATA_CACHEMAXSIZE 2621440using namespace cocos2d::experimental;//列表初始化AudioCache::AudioCache(): _pcmData(nullptr),_pcmDataSize(0),_bytesOfRead(0),_alBufferReady(false),_fileFormat(fileFormat::UNKNowN),_queBufferFrames(0),_queBufferBytes(0),_mp3EnCoding(0){    //在这里其实就属于赋值了,不是初始化}//拷贝构造AudioCache::AudioCache(AudioCache& cache){    _pcmData = cache._pcmData;    _pcmDataSize = cache._pcmDataSize;    _bytesOfRead = cache._bytesOfRead;    _alBufferReady = cache._alBufferReady;    _fileFormat = cache._fileFormat;    _queBufferFrames = cache._queBufferFrames;    _queBufferBytes = cache._queBufferBytes;    _mp3EnCoding = cache._mp3EnCoding;}AudioCache::~AudioCache(){    if(_pcmData){        if (_alBufferReady){            alDeleteBuffers(1,&_alBufferID);//释放缓存ID        }        //wait for the 'readDataTask' task to exit        _readDataTaskMutex.lock();//上锁,等待读取数据任务离开        _readDataTaskMutex.unlock();//解锁                free(_pcmData);//释放指针,free接受参数为voID*    }    if (_queBufferFrames > 0) {//有缓存帧数,则释放        for (int index = 0; index < QUEUEBUFFER_NUM; ++index) {            free(_queBuffers[index]);        }    }}voID AudioCache::readDataTask(){    _readDataTaskMutex.lock();//上任务锁     oggvorbis_file* vf = nullptr;//定义一个ogg数据结构体指针     mpg123_handle* mpg123handle = nullptr;//定义一个MP3数据的结构体指针     long totalFrames = 0;     switch (_fileFormat)     {     case fileFormat::OGG:         {             vf = new oggvorbis_file;//申请一块新的内存,并调用oggvorbis_file的构造,初始化,vf指向内存首地址             if (ov_fopen(_fileFullPath.c_str(),vf)){//类似于fopen,开始读取数据,将数据存放在vf所在的内存地址                 log("input does not appear to be an Ogg bitstream.\n");                 goto ExitThread;//不喜欢goto!除非跳多重循环!  这里表示直接跳到ExitThread所在代码段             }             auto vi = ov_info(vf,-1);////得到文件信息              totalFrames = (long)ov_pcm_total(vf,-1);//样本数               _bytesPerFrame =  vi->channels * 2;//声道数*2 =每个字节帧             _alBufferFormat = (vi->channels > 1) ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16;//缓存模式设置             _sampleRate = vi->rate;//采样率             _pcmDataSize = totalFrames * _bytesPerFrame; //扩展pcmdata的容量至指定大小             _duration = 1.0f * totalFrames / _sampleRate;//持续时间         }         break;     case fileFormat::MP3:         {             long rate = 0;             int error = MPG123_OK;             mpg123handle = mpg123_new(nullptr,&error);//初始化,并且因为传入引用,可从error,获取成功或者失败信息             if (!mpg123handle){                 log("Basic setup goes wrong: %s",mpg123_plain_strerror(error));                 goto ExitThread;//失败跳转,输出错误信息             }             if (mpg123_open(mpg123handle,_fileFullPath.c_str()) != MPG123_OK ||                  mpg123_getformat(mpg123handle,&rate,&_channels,&_mp3EnCoding) != MPG123_OK) {                 log("Trouble with mpg123: %s\n",mpg123_strerror(mpg123handle) );                 goto ExitThread;             }//开始读取,并设置信息,如果失败,则跳转             if (_mp3EnCoding == MPG123_ENC_SIGNED_16){                 _bytesPerFrame = 2 * _channels;             }             else if (_mp3EnCoding == MPG123_ENC_float_32){                 _bytesPerFrame = 4 * _channels;             }             else{                 log("Bad enCoding: 0x%x!\n",_mp3EnCoding);                 goto ExitThread;             }//设置声道数量,根据不同的格式                          _alBufferFormat = (_channels > 1) ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16;             _sampleRate = rate;//同上                          /* Ensure that this output format will not change (it Could,when we allow it). */             mpg123_format_none(mpg123handle);             mpg123_format(mpg123handle,rate,_channels,_mp3EnCoding);             /* Ensure that we can get accurate length by call mpg123_length */             mpg123_scan(mpg123handle);//各个参数设置             auto framesLength = mpg123_length(mpg123handle);//帧长度             totalFrames = framesLength;             _pcmDataSize = totalFrames * _bytesPerFrame;             _duration = 1.0f * totalFrames / _sampleRate;//同上         }         break;     case fileFormat::UNKNowN:     default:         break;     }        if (_pcmDataSize <= PCMDATA_CACHEMAXSIZE)    {        _pcmData = malloc(_pcmDataSize);//不超过限制内存长度下,申请内存        auto alError = alGetError();//获得错误信息        alGenBuffers(1,&_alBufferID);//申请一个al缓存        alError = alGetError();//得到错误信息        if (alError != AL_NO_ERROR) {            log("%s: attaching audio to buffer fail: %x\n",__FUNCTION__,alError);            goto ExitThread;        }        switch (_fileFormat)        {        case fileFormat::OGG:            {                int current_section;                unsigned int currPos = 0;                long readRet = 0;                do                 {                    readRet = ov_read(vf,(char*)_pcmData + _bytesOfRead,4096,2,1,¤t_section);//进行解码                      if (readRet > 0){//readRet可能小于等于0,表示文件流中发生不明错误                        _bytesOfRead += readRet;                    }                } while (_bytesOfRead < _pcmDataSize);//确保有读取到数据,有疑问!如果异常,陷入死循环?                _alBufferReady = true;                _bytesOfRead = _pcmDataSize;                break;            }        case fileFormat::MP3:            {                size_t done = 0;                auto err = mpg123_read(mpg123handle,(unsigned char*)_pcmData,_pcmDataSize,&done);//mp3解码                if (err == MPG123_ERR){                    log("Trouble with mpg123: %s\n",mpg123_strerror(mpg123handle) );                    goto ExitThread;                }                if (err == MPG123_DONE || err == MPG123_OK){//错误处理                    _alBufferReady = true;                    _pcmDataSize = done;                    _bytesOfRead = done;                }            }            break;             case fileFormat::UNKNowN:        default:            break;        }        alBufferData(_alBufferID,_alBufferFormat,_pcmData,_sampleRate);//将数据放入缓存    }     else{//数据量很大时        _queBufferFrames = _sampleRate * QUEUEBUFFER_TIME_STEP;        _queBufferBytes = _queBufferFrames * _bytesPerFrame;        for (int index = 0; index < QUEUEBUFFER_NUM; ++index) {            _queBuffers[index] = (char*)malloc(_queBufferBytes);//3段申请内存                        switch (_fileFormat){            case fileFormat::MP3:                {                    size_t done = 0;                    mpg123_read(mpg123handle,(unsigned char*)_queBuffers[index],_queBufferBytes,&done);//解码                    _queBufferSize[index] = done;                    _bytesOfRead += done;                }                break;            case fileFormat::OGG:                {                    int current_section;                    auto readRet = ov_read(vf,_queBuffers[index],¤t_section);//解码                    _queBufferSize[index] = readRet;                }                break;            }        }    } //goto的目的代码段   ExitThread:    switch (_fileFormat)    {    case fileFormat::OGG:        ov_clear(vf);//字节流清空,该函数中已调用了fclose函数          delete vf;        break;    case fileFormat::MP3:        mpg123_close(mpg123handle);        mpg123_delete(mpg123handle);//关闭释放内存,数据都已存放到缓存中        break;    case fileFormat::UNKNowN:    default:        break;    }        _readDataTaskMutex.unlock();//读取数据完毕,解锁    if (_queBufferFrames > 0)        _alBufferReady = true;        invokingCallbacks();}voID AudioCache::invokingCallbacks(){    _callbackMutex.lock();//回调处理上锁    auto count = _callbacks.size();    for (size_t index = 0; index < count; ++index) {        _callbacks[index]();//依次执行回调函数    }    _callbacks.clear();    _callbackMutex.unlock();//回调处理解锁}voID AudioCache::addCallbacks(const std::function<voID ()> &callback){    _callbackMutex.lock();//上锁    if (_alBufferReady) {//当数据已经在缓存中,直接执行回调        callback();    } else {        _callbacks.push_back(callback);//否则,等待执行    }    _callbackMutex.unlock();//解锁}#endif
鉴于时间,不便多说,求指点!~~ T T 总结

以上是内存溢出为你收集整理的菜鸟也能学cocos2dx 3.3 AudioCache全部内容,希望文章能够帮你解决菜鸟也能学cocos2dx 3.3 AudioCache所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1006431.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-22
下一篇 2022-05-22

发表评论

登录后才能评论

评论列表(0条)

保存