|
楼主 |
发表于 2009-8-26 11:04:39
|
显示全部楼层
这是一个单件。接下来需要实现一个Sound的接口,因为Sound有普通的wav这样的声音文件,也有像mp3这样的流媒体。因此需要区别对待的,比如说wav的处理思路通常都是直接加载到内存中而mp3等是不会的。我们这里只实现wav的。接口类: #pragma once
#include <string> #include <boost/smart_ptr/shared_ptr.hpp>
namespace db { class ISound { public: typedef std::string string_type; public: virtual bool load() = 0; virtual void unLoad() = 0; virtual void play() = 0; virtual void changePauseState() = 0; virtual const string_type& getName() const = 0; virtual void release() = 0; };
typedef boost::shared_ptr<ISound> ISound_SP; }
然后实现我们的内存wav,这和普通的声音有所不同,因为我们需要直接从内存中播放而不是通过一个wav格式的文件的文件名或者路径来构造,因此其实现如下: #include "ISound.hpp" #include <fmod.hpp>
#if defined(_MSC_VER ) #pragma comment( lib, "fmodex_vc.lib" ) #endif
namespace db { class CFmodSoundManager; class CMemSound : public db::ISound { public: typedef db::ISound base_class; typedef base_class::string_type string_type;
friend class CFmodSoundManager; public: CMemSound( FMOD::System* pSystem, const string_type& strFile ); virtual ~CMemSound(); public: bool load(); void unLoad(); void play(); void changePauseState(); void release(); const string_type& getName() const;
protected: bool create( void* pBuf, unsigned uBytesCount ); protected: string_type m_strName; FMOD::System* m_pSystem; FMOD::Sound* m_pSound; FMOD::Channel* m_pChannel; }; }
现在再看管理单件的实现,其中需要提的就这两个函数: bool CFmodSoundManager::loadtomemory( void* pBuf, size_t uByteCounts, size_t uoffset ) { FILE* pData = NULL; if( 0 != fopen_s( &pData, m_strDataFile.c_str(), "rb") ) { return false; }
fseek( pData, uoffset, SEEK_SET ); fread_s( pBuf, uByteCounts, uByteCounts, 1, pData );
fclose(pData);
return true; }
ISound_SP CFmodSoundManager::createSound( const string_type& strFile ) { try { CFilePack::node_type node; #ifdef __DB_USE_SAFE_CRT_FUNC__ strcpy_s( node.szName, strFile.c_str() ); #else strcpy( node.szName, strFile.c_str() ); #endif container_type::const_iterator pos = m_nodes.find( node ); if( pos == m_nodes.end() ) { // 没找到哈 throw std::exception("没这个文件"); }
CMemSound* pSound = new CMemSound( m_pSystem, pos->szName ); char* pBuf = new char[pos->uSize]; if( !this->loadtomemory( pBuf, pos->uSize, pos->uOffset ) ) { delete pSound; delete[] pBuf;
throw std::exception( "加载失败!" ); }
pSound->create( pBuf, pos->uSize ); delete[] pBuf;
return ISound_SP( pSound, boost::mem_fn( &ISound::release ) ); // 这样就算是pSound由DLL创建也不会出错了 } catch( std::exception& /*e*/ ) { return ISound_SP(); } } 它从散列或者二叉树中查找我们需要的文件的信息,如果找到了则打开数据文件将那一块文件加载到内存中,然后创建内存Sound的智能指针。然后我们就可以使用这个对象进行声音的播放了。下面是主函数的实现: // Test #define _CRTDBG_MAP_ALLOC #include <crtdbg.h>
#include "FmodManager.hpp" #include <iostream> #include <conio.h> #include <Windows.h> using namespace std;
using namespace db;
void printDebug() { _CrtDumpMemoryLeaks(); // 它比Manager的析构先调用,因此内存泄露的提示是错误的。 }
int main() { _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); atexit( printDebug );
if( !CFmodSoundManager::GetSingletonPtr()->initialize( "music.data", "music.inx" ) ) { cout<< "系统初始化失败!"<< endl; return -1; }
CFmodSoundManager* pManager = CFmodSoundManager::GetSingletonPtr(); ISound_SP spSound1 = pManager->createSound( "jaguar.wav" );
if( !spSound1 ) { cout<<"jaguar.wav加载失败!"<< endl; return -1; }
ISound_SP spSound2 = pManager->createSound( "swish.wav" );
if( !spSound2 ) { cout<<"swish.wav加载失败!"<< endl; return -1; }
printf_s( "请按播放jaguar.wav\n请按播放swish.wav\n请按q退出\n"); spSound1->play(); spSound2->play();
bool bExit = false; do { if (_kbhit()) { int key = _getch(); switch( key ) { case '1': spSound1->play(); break; case '2': spSound2->play(); break; case 'q': bExit = true; break; default: break; } }
Sleep( 10 );
} while (!bExit);
system("pause");
return 0; }
总结 由于时间关系这里只列出了部分代码,详细的工程我会放在附件中。另外就是Bug问题,也是因为时间关系,我没做大量详细的测试,但是我觉得重要的思想而不是具体的操作,只要明白了思想要改也是很容易的。另外这个东东也只是我自己的一些简单的思想,工程中是怎么样的其实我也不知道,呵呵,因为我还没有看过别人是怎么做的;时间仓促也没有做什么详细的构思和设计,敬请原谅,O(∩_∩)O哈哈~ 欢迎各位朋友对文中的任何点提出您的意见和问题。 我的QQ是84638372,Email:dbdongbo@vip.qq.com 。 2009/6/10于东北大学秦皇岛分校。
PS: Demo工程的下载地址:http://ishare.iask.sina.com.cn/f/5263833.html 比较工整的版本在我的cppblog: http://www.cppblog.com/db123/archive/2009/06/10/87371.html
|
|