Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

318 lines
7.4 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #ifdef _WIN32
  9. #define WIN32_LEAN_AND_MEAN
  10. #include <windows.h>
  11. #endif
  12. #include "quakedef.h"
  13. #include "iframeencoder.h"
  14. #include "interface.h"
  15. #include "milesbase.h"
  16. #include "tier0/dbg.h"
  17. // memdbgon must be the last include file in a .cpp file!!!
  18. #include "tier0/memdbgon.h"
  19. void Con_Printf( const char *pMsg, ... )
  20. {
  21. }
  22. class FrameEncoder_Miles : public IFrameEncoder
  23. {
  24. protected:
  25. virtual ~FrameEncoder_Miles();
  26. public:
  27. FrameEncoder_Miles();
  28. virtual bool Init(int quality, int &rawFrameSize, int &encodedFrameSize);
  29. virtual void Release();
  30. virtual void EncodeFrame(const char *pUncompressed, char *pCompressed);
  31. virtual void DecodeFrame(const char *pCompressed, char *pDecompressed);
  32. virtual bool ResetState();
  33. public:
  34. void Shutdown();
  35. static S32 AILCALLBACK EncodeStreamCB(
  36. UINTa user, // User value passed to ASI_open_stream()
  37. void *dest, // Location to which stream data should be copied by app
  38. S32 bytes_requested, // # of bytes requested by ASI codec
  39. S32 offset // If not -1, application should seek to this point in stream
  40. );
  41. static S32 AILCALLBACK DecodeStreamCB(
  42. UINTa user, // User value passed to ASI_open_stream()
  43. void *dest, // Location to which stream data should be copied by app
  44. S32 bytes_requested, // # of bytes requested by ASI codec
  45. S32 offset // If not -1, application should seek to this point in stream
  46. );
  47. void FigureOutFrameSizes();
  48. private:
  49. // Encoder stuff.
  50. ASISTRUCT m_Encoder;
  51. // Decoder stuff.
  52. ASISTRUCT m_Decoder;
  53. // Destination for encoding and decoding.
  54. const char *m_pSrc;
  55. int m_SrcLen;
  56. int m_CurSrcPos;
  57. // Frame sizes..
  58. int m_nRawBytes;
  59. int m_nEncodedBytes;
  60. };
  61. // ------------------------------------------------------------------------ //
  62. // Helper functions.
  63. // ------------------------------------------------------------------------ //
  64. void Convert16UnsignedToSigned(short *pDest, int nSamples)
  65. {
  66. for(int i=0; i < nSamples; i++)
  67. {
  68. int val = *((unsigned short*)&pDest[i]) - (1 << 15);
  69. pDest[i] = (short)val;
  70. }
  71. }
  72. void Convert16SignedToUnsigned(short *pDest, int nSamples)
  73. {
  74. for(int i=0; i < nSamples; i++)
  75. {
  76. int val = *((short*)&pDest[i]) + (1 << 15);
  77. *((unsigned short*)&pDest[i]) = (unsigned short)val;
  78. }
  79. }
  80. // ------------------------------------------------------------------------ //
  81. // FrameEncoder_Miles functions.
  82. // ------------------------------------------------------------------------ //
  83. FrameEncoder_Miles::FrameEncoder_Miles()
  84. {
  85. }
  86. FrameEncoder_Miles::~FrameEncoder_Miles()
  87. {
  88. Shutdown();
  89. }
  90. bool FrameEncoder_Miles::Init(int quality, int &rawFrameSize, int &encodedFrameSize)
  91. {
  92. Shutdown();
  93. // This tells what protocol we're using.
  94. C8 suffix[128] = ".v12"; // (.v12, .v24, .v29, or .raw)
  95. // encoder converts from RAW to v12
  96. if ( !m_Encoder.Init( (void *)this, ".RAW", suffix, &FrameEncoder_Miles::EncodeStreamCB ) )
  97. {
  98. Con_Printf("(FrameEncoder_Miles): Can't initialize ASI encoder.\n");
  99. Shutdown();
  100. return false;
  101. }
  102. // decoder converts from v12 to RAW
  103. if ( !m_Decoder.Init( (void *)this, suffix, ".RAW", &FrameEncoder_Miles::DecodeStreamCB ) )
  104. {
  105. Con_Printf("(FrameEncoder_Miles): Can't initialize ASI decoder.\n");
  106. Shutdown();
  107. return false;
  108. }
  109. FigureOutFrameSizes();
  110. // Output..
  111. rawFrameSize = m_nRawBytes * 2; // They'll be using 16-bit samples and we're quantizing to 8-bit.
  112. encodedFrameSize = m_nEncodedBytes;
  113. return true;
  114. }
  115. void FrameEncoder_Miles::Release()
  116. {
  117. delete this;
  118. }
  119. void FrameEncoder_Miles::EncodeFrame(const char *pUncompressedBytes, char *pCompressed)
  120. {
  121. char samples[1024];
  122. if(!m_Encoder.IsActive() || m_nRawBytes > sizeof(samples))
  123. return;
  124. const short *pUncompressed = (const short*)pUncompressedBytes;
  125. for(int i=0; i < m_nRawBytes; i++)
  126. samples[i] = (char)(pUncompressed[i] >> 8);
  127. m_pSrc = samples;
  128. m_SrcLen = m_nRawBytes;
  129. m_CurSrcPos = 0;
  130. U32 len = m_Encoder.Process( pCompressed, m_nEncodedBytes );
  131. if ( len != (U32)m_nEncodedBytes )
  132. {
  133. Assert(0);
  134. }
  135. }
  136. void FrameEncoder_Miles::DecodeFrame(const char *pCompressed, char *pDecompressed)
  137. {
  138. if(!m_Decoder.IsActive())
  139. return;
  140. m_pSrc = pCompressed;
  141. m_SrcLen = m_nEncodedBytes;
  142. m_CurSrcPos = 0;
  143. U32 outputSize = m_nRawBytes*2;
  144. U32 len = m_Decoder.Process( pDecompressed, outputSize );
  145. if (len != outputSize)
  146. {
  147. Assert(0);
  148. }
  149. }
  150. void FrameEncoder_Miles::Shutdown()
  151. {
  152. m_Decoder.Shutdown();
  153. m_Encoder.Shutdown();
  154. }
  155. bool FrameEncoder_Miles::ResetState()
  156. {
  157. if(!m_Decoder.IsActive() || !m_Encoder.IsActive())
  158. return true;
  159. for(int i=0; i < 2; i++)
  160. {
  161. char data[2048], compressed[2048];
  162. memset(data, 0, sizeof(data));
  163. m_pSrc = data;
  164. m_SrcLen = m_nRawBytes;
  165. m_CurSrcPos = 0;
  166. U32 len = m_Encoder.Process( compressed, m_nEncodedBytes );
  167. if ( len != (U32)m_nEncodedBytes )
  168. {
  169. Assert(0);
  170. }
  171. m_pSrc = compressed;
  172. m_SrcLen = m_nEncodedBytes;
  173. m_CurSrcPos = 0;
  174. m_Decoder.Process( data, m_nRawBytes * 2 );
  175. }
  176. // Encode and decode a couple frames of zeros.
  177. return true;
  178. }
  179. S32 AILCALLBACK FrameEncoder_Miles::EncodeStreamCB(
  180. UINTa user, // User value passed to ASI_open_stream()
  181. void *dest, // Location to which stream data should be copied by app
  182. S32 bytes_requested, // # of bytes requested by ASI codec
  183. S32 offset // If not -1, application should seek to this point in stream
  184. )
  185. {
  186. FrameEncoder_Miles *pThis = (FrameEncoder_Miles*)user;
  187. Assert(pThis && offset == -1);
  188. // Figure out how many samples we can safely give it.
  189. int maxSamples = pThis->m_SrcLen - pThis->m_CurSrcPos;
  190. int samplesToGive = MIN(maxSamples, bytes_requested/2);
  191. // Convert to 16-bit signed mono.
  192. short *pOut = (short*)dest;
  193. for(int i=0; i < samplesToGive; i++)
  194. {
  195. pOut[i] = pThis->m_pSrc[pThis->m_CurSrcPos+i] << 8;
  196. }
  197. pThis->m_CurSrcPos += samplesToGive;
  198. return samplesToGive * 2;
  199. }
  200. S32 AILCALLBACK FrameEncoder_Miles::DecodeStreamCB(
  201. UINTa user, // User value passed to ASI_open_stream()
  202. void *dest, // Location to which stream data should be copied by app
  203. S32 bytes_requested, // # of bytes requested by ASI codec
  204. S32 offset // If not -1, application should seek to this point in stream
  205. )
  206. {
  207. FrameEncoder_Miles *pThis = (FrameEncoder_Miles*)user;
  208. Assert(pThis && offset == -1);
  209. int maxBytes = pThis->m_SrcLen - pThis->m_CurSrcPos;
  210. int bytesToGive = MIN(maxBytes, bytes_requested);
  211. memcpy(dest, &pThis->m_pSrc[pThis->m_CurSrcPos], bytesToGive);
  212. pThis->m_CurSrcPos += bytesToGive;
  213. return bytesToGive;
  214. }
  215. void FrameEncoder_Miles::FigureOutFrameSizes()
  216. {
  217. // Figure out the frame sizes. It is probably not prudent in general to assume fixed frame sizes with Miles codecs
  218. // but it works with the voxware codec right now and simplifies things a lot.
  219. m_nRawBytes = (int)m_Encoder.GetProperty( m_Encoder.INPUT_BLOCK_SIZE );
  220. char uncompressed[1024];
  221. char compressed[1024];
  222. Assert(m_nRawBytes <= sizeof(uncompressed));
  223. m_pSrc = uncompressed;
  224. m_SrcLen = m_nRawBytes;
  225. m_CurSrcPos = 0;
  226. m_nEncodedBytes = (int)m_Encoder.Process( compressed, sizeof(compressed) );
  227. }
  228. class IVoiceCodec;
  229. extern IVoiceCodec* CreateVoiceCodec_Frame(IFrameEncoder *pEncoder);
  230. void* CreateVoiceCodec_Miles()
  231. {
  232. IFrameEncoder *pEncoder = new FrameEncoder_Miles;
  233. if(!pEncoder)
  234. return NULL;
  235. return CreateVoiceCodec_Frame(pEncoder);
  236. }
  237. EXPOSE_INTERFACE_FN(CreateVoiceCodec_Miles, IVoiceCodec, "vaudio_miles")