home *** CD-ROM | disk | FTP | other *** search
/ Game Audio Programming / GameAudioProgramming.iso / Game_Audio / audio_sdk / src / AudioLib / Vorbis.cpp < prev    next >
C/C++ Source or Header  |  2002-07-14  |  10KB  |  378 lines

  1. /***********************************************************\
  2. Copyright (C) James Boer, 2002. 
  3. All rights reserved worldwide.
  4.  
  5. This software is provided "as is" without express or implied
  6. warranties. You may freely copy and compile this source into
  7. applications you distribute provided that the copyright text
  8. below is included in the resulting source code, for example:
  9. "Portions Copyright (C) James Boer, 2002"
  10. \***********************************************************/
  11.  
  12. #include "Vorbis.h"
  13.  
  14. #ifdef USE_VORBIS
  15. using namespace std;
  16. using namespace Audio;
  17.  
  18. // Memory callback function declarations
  19. size_t read_func_mem(void *ptr, size_t size, size_t nmemb, void *datasource);
  20. int    seek_func_mem(void *datasource, ogg_int64_t offset, int whence);
  21. int    close_func_mem(void *datasource);
  22. long   tell_func_mem(void *datasource);
  23.  
  24. // Stream callback function declarations
  25. size_t read_func_stream(void *ptr, size_t size, size_t nmemb, void *datasource);
  26. int    seek_func_stream(void *datasource, ogg_int64_t offset, int whence);
  27. int    close_func_stream(void *datasource);
  28. long   tell_func_stream(void *datasource);
  29.  
  30.  
  31. IMPLEMENT_POOL(Vorbis);
  32.  
  33.  
  34. //------------------------------------------------------------------------//
  35. Vorbis::Vorbis()
  36. {
  37.     FN("Vorbis::Vorbis()");
  38.     Clear();
  39. }
  40.  
  41. //------------------------------------------------------------------------//
  42. Vorbis::~Vorbis()
  43. {
  44.     Close();
  45.     FN("Vorbis::~Vorbis()");
  46. }
  47.  
  48. //------------------------------------------------------------------------//
  49. void Vorbis::Clear()
  50. {
  51.     FN("Vorbis::Clear()");
  52.     m_pBufferPtr = 0;
  53.     m_pBuffer = 0;
  54.     m_nBufferSize = 0;
  55.     m_nNumSamples = 0;
  56.     m_pVorbisInfo = 0;
  57.     memset(&m_WaveFormatEx, 0, sizeof(WAVEFORMATEX));
  58.     memset(&m_VorbisFile, 0, sizeof(OggVorbis_File));
  59.     m_bEOF = false;
  60.     m_MemSrc.Clear();
  61.     m_pStreamSrc = 0;
  62.     m_bOpen = false;
  63. }
  64.  
  65.  
  66. //------------------------------------------------------------------------//
  67. // Use for IAudioStream-based source
  68. bool Vorbis::Open( std::string sFileName)
  69. {
  70.     FN("Vorbis::Open()");
  71.     int iStartTime = timeGetTime();
  72.  
  73.     if(m_bOpen)
  74.         return false;
  75.  
  76.     // Open the file
  77.     if(!AudioMgr()->CreateAudioStream(m_pStreamSrc))
  78.         return false;
  79.     
  80.     if(FAILED(m_pStreamSrc->Open(sFileName)))
  81.         return false;
  82.  
  83.     // Set the proper callback functions
  84.     ov_callbacks cb;
  85.     cb.read_func = &read_func_stream;
  86.     cb.seek_func = &seek_func_stream;
  87.     cb.close_func = &close_func_stream;
  88.     cb.tell_func = &tell_func_stream;
  89.  
  90.     // Open the ogg bitstream
  91.     if(ov_open_callbacks(m_pStreamSrc, &m_VorbisFile, NULL, 0, cb) < 0) 
  92.         return false;
  93.  
  94.     m_bOpen = true;
  95.     if(!GetStreamInfo())
  96.         return false;
  97.  
  98.     DebugOut(1, "Open() time: %dms", timeGetTime() - iStartTime);
  99.  
  100.  
  101.     return true;
  102. }
  103.  
  104. //------------------------------------------------------------------------//
  105. // Used for loading direct from memory
  106. bool Vorbis::Open( BYTE* pbData, uint32 dwDataSize)
  107. {
  108.     FN("Vorbis::Open()");
  109.  
  110.     if(m_bOpen)
  111.         return false;
  112.  
  113.     m_MemSrc.m_pData = (char*)pbData;
  114.     m_MemSrc.m_nDataSize = dwDataSize;
  115.     m_MemSrc.m_pReadPtr = (char*)pbData;
  116.  
  117.     // Set the proper callback functions
  118.     ov_callbacks cb;
  119.     cb.read_func = &read_func_mem;
  120.     cb.seek_func = &seek_func_mem;
  121.     cb.close_func = &close_func_mem;
  122.     cb.tell_func = &tell_func_mem;
  123.  
  124.     if(ov_open_callbacks(&m_MemSrc, &m_VorbisFile, NULL, dwDataSize, cb) < 0)
  125.         return false;
  126.  
  127.     if(!GetStreamInfo())
  128.         return false;
  129.  
  130.     m_bOpen = true;
  131.     return true;
  132. }
  133.  
  134. //------------------------------------------------------------------------//
  135. bool Vorbis::GetStreamInfo()
  136. {
  137.     // Display comment information when loading the file
  138.     char **ptr=ov_comment(&m_VorbisFile,-1)->user_comments;
  139.     while(*ptr)
  140.     {
  141.       DebugOut(4, "%s",*ptr);
  142.       ++ptr;
  143.     }
  144.  
  145.     // Get vorbis file information
  146.     m_pVorbisInfo = ov_info(&m_VorbisFile,-1);
  147.     DebugOut(4, "Bitstream is %d channel, %ldHz", m_pVorbisInfo->channels,m_pVorbisInfo->rate);
  148.  
  149.     // Get the number of PCM samples in this file
  150.     m_nNumSamples = (long)ov_pcm_total(&m_VorbisFile,-1);
  151.     DebugOut(4, "Decoded length: %ld samples", m_nNumSamples);
  152.  
  153.     // Display other info
  154.     DebugOut(4, "Encoded by: %s", ov_comment(&m_VorbisFile,-1)->vendor);
  155.  
  156.     // set up the WaveFormatEx structure
  157.     m_WaveFormatEx.wFormatTag = WAVE_FORMAT_PCM;
  158.     m_WaveFormatEx.nChannels = m_pVorbisInfo->channels;
  159.     m_WaveFormatEx.nSamplesPerSec = m_pVorbisInfo->rate;
  160.     m_WaveFormatEx.wBitsPerSample = 16;
  161.     m_WaveFormatEx.nBlockAlign = m_WaveFormatEx.nChannels * m_WaveFormatEx.wBitsPerSample / 8;
  162.     m_WaveFormatEx.nAvgBytesPerSec = m_WaveFormatEx.nSamplesPerSec * m_WaveFormatEx.nBlockAlign;
  163.     m_WaveFormatEx.cbSize = 0;
  164.  
  165.     return true;
  166. }
  167.  
  168. //------------------------------------------------------------------------//
  169. bool Vorbis::Close()
  170. {
  171.     FN("Vorbis::Close()");
  172.  
  173.     if(!m_bOpen)
  174.         return false;
  175.  
  176.     // close out the vorbis file bitstream
  177.     ov_clear(&m_VorbisFile);
  178.  
  179.     Clear();
  180.  
  181.     return true;
  182. }
  183.  
  184.  
  185. //------------------------------------------------------------------------//
  186. bool Vorbis::Read( BYTE* pBuffer, uint32 dwSizeToRead, uint32* pdwSizeRead )
  187. {
  188.     FN("Vorbis::Read()");
  189.  
  190.     int iStartTime = timeGetTime();
  191.  
  192.     if(!m_bOpen)
  193.         return false;
  194.  
  195.     char* pCurBuffer = (char*)pBuffer;
  196.     uint32 nBytesRead = 0;
  197.     int iSection = 0;
  198.     while((nBytesRead < dwSizeToRead) && !m_bEOF)
  199.     {
  200.         int32 iRet = ov_read(&m_VorbisFile, pCurBuffer, dwSizeToRead - nBytesRead, 0, 2, 1, &iSection);
  201.         if (iRet == 0 || iSection != 0) 
  202.         {
  203.             m_bEOF = true;
  204.         } 
  205.         else if (iRet < 0) 
  206.         {
  207.             return Error::Handle("Error in vorbis data stream!");;
  208.         }
  209.         nBytesRead += iRet;
  210.         pCurBuffer += iRet;
  211.     }
  212.  
  213.     *pdwSizeRead = nBytesRead;
  214.     DebugOut(5, "Read() time: %dms", timeGetTime() - iStartTime);
  215.     return true;
  216. }
  217.  
  218. //------------------------------------------------------------------------//
  219. uint32 Vorbis::GetSize()
  220. {
  221.     FN("Vorbis::GetSize()");
  222.  
  223.     return m_nNumSamples * m_WaveFormatEx.nChannels * m_WaveFormatEx.wBitsPerSample / 8;
  224. }
  225.  
  226. //------------------------------------------------------------------------//
  227. bool Vorbis::Reset()
  228. {
  229.     FN("Vorbis::Reset()");
  230.  
  231.     if(!m_bOpen)
  232.         return false;
  233.  
  234.     // Seek to beginning of file to begin reading it again
  235.     m_bEOF = false;
  236.     ov_pcm_seek(&m_VorbisFile, 0);
  237.  
  238.     return true;
  239. }
  240.  
  241.  
  242. //------------------------------------------------------------------------//
  243. void Vorbis::Destroy()
  244. {
  245.     Close();
  246.     Vorbis::DestroyObject(this);
  247. }
  248.  
  249.  
  250. //------------------------------------------------------------------------//
  251. WAVEFORMATEX* Vorbis::GetFormat()
  252. {
  253.     FN("Vorbis::GetFormat()");
  254.     return &m_WaveFormatEx;
  255. }
  256.  
  257. //------------------------------------------------------------------------//
  258. bool Vorbis::IsEOF()
  259. {
  260.     FN("Vorbis::IsEOF()");
  261.     return m_bEOF;
  262. }
  263.  
  264.  
  265. //-----------------------------------------------------------------
  266. // Vorbis file library callback functions for reading out of memory
  267. //-----------------------------------------------------------------
  268. size_t read_func_mem(void *ptr, size_t size, size_t nmemb, void *datasource)
  269. {
  270.     MemorySource* pSrc = (MemorySource*)datasource;
  271.     uint32 nBytesToCopy = size * nmemb;
  272.     uint32 nBytesRemaining = (pSrc->m_pData + pSrc->m_nDataSize) - pSrc->m_pReadPtr;
  273.     if(nBytesToCopy > nBytesRemaining)
  274.         nBytesToCopy = nBytesRemaining;
  275.     memcpy(ptr, pSrc->m_pReadPtr, nBytesToCopy);
  276.     pSrc->m_pReadPtr += nBytesToCopy;
  277.     return nBytesToCopy;
  278. }
  279.  
  280. //------------------------------------------------------------------------//
  281. int seek_func_mem(void *datasource, ogg_int64_t offset, int whence)
  282. {
  283.     MemorySource* pSrc = (MemorySource*)datasource;
  284.     switch(whence)
  285.     {
  286.         case SEEK_SET:
  287.             pSrc->m_pReadPtr = pSrc->m_pData + offset;
  288.             break;
  289.         case SEEK_CUR:
  290.             pSrc->m_pReadPtr += offset;
  291.             break;
  292.         case SEEK_END:
  293.             pSrc->m_pReadPtr = (pSrc->m_pData + pSrc->m_nDataSize) - offset;
  294.             break;
  295.     };
  296.  
  297.     // check for out of bounds seek pointer
  298.     if(pSrc->m_pReadPtr < pSrc->m_pData)
  299.     {
  300.         pSrc->m_pReadPtr = pSrc->m_pData;
  301.         return -1;
  302.     }
  303.     else if(pSrc->m_pReadPtr > (pSrc->m_pData + pSrc->m_nDataSize))
  304.     {
  305.         pSrc->m_pReadPtr = pSrc->m_pData + pSrc->m_nDataSize;
  306.         return -1;
  307.     }
  308.  
  309.     return 0;
  310. }
  311.  
  312. //------------------------------------------------------------------------//
  313. int close_func_mem(void *datasource)
  314. {
  315.     MemorySource* pSrc = (MemorySource*)datasource;
  316.     return 0;
  317. }
  318.  
  319. //------------------------------------------------------------------------//
  320. long tell_func_mem(void *datasource)
  321. {
  322.     MemorySource* pSrc = (MemorySource*)datasource;
  323.     return pSrc->m_pReadPtr - pSrc->m_pData;
  324. }
  325.  
  326.  
  327. //-----------------------------------------------------------------
  328. // Vorbis file library callback functions for reading from a file
  329. //-----------------------------------------------------------------
  330. size_t read_func_stream(void *ptr, size_t size, size_t nmemb, void *datasource)
  331. {
  332.     if(!size || !nmemb)
  333.         return 0;
  334.  
  335.     IAudioStream* pSrc = (IAudioStream*)datasource;
  336.     uint32 nBytesToRead = size * nmemb;
  337.  
  338.     uint32 nRead;
  339.     if(FAILED(pSrc->Read(ptr, nBytesToRead, &nRead)))
  340.         return 0;
  341.  
  342.     return nRead;
  343. }
  344.  
  345. //------------------------------------------------------------------------//
  346. int seek_func_stream(void *datasource, ogg_int64_t offset, int whence)
  347. {
  348.     IAudioStream* pSrc = (IAudioStream*)datasource;
  349.     LARGE_INTEGER liOffset;
  350.     ULARGE_INTEGER lnNewPos;
  351.     liOffset.QuadPart = offset;
  352.     if(FAILED(pSrc->Seek(liOffset, whence, &lnNewPos)))
  353.         return -1;
  354.     return 0;
  355. }
  356.  
  357. //------------------------------------------------------------------------//
  358. int close_func_stream(void *datasource)
  359. {
  360.     IAudioStream* pSrc = (IAudioStream*)datasource;
  361.     SAFE_RELEASE(pSrc);
  362.     return 0;
  363. }
  364.  
  365. //------------------------------------------------------------------------//
  366. long tell_func_stream(void *datasource)
  367. {
  368.     IAudioStream* pSrc = (IAudioStream*)datasource;
  369.     LARGE_INTEGER dlibMove;
  370.     dlibMove.QuadPart = 0;
  371.     ULARGE_INTEGER nNewPos;
  372.     pSrc->Seek(dlibMove, SEEK_CUR, &nNewPos);
  373.     return nNewPos.QuadPart;
  374. }
  375.  
  376. #endif // USE_VORBIS
  377.  
  378.