| 
 | 
 
 
 楼主 |
发表于 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 
 
  |   
 
 
 
 |