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.

403 lines
9.3 KiB

  1. //===== Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose:
  4. //
  5. //===========================================================================//
  6. #include "audio_pch.h"
  7. #include <OpenAL/al.h>
  8. #include <OpenAL/alc.h>
  9. // memdbgon must be the last include file in a .cpp file!!!
  10. #include "tier0/memdbgon.h"
  11. extern bool snd_firsttime;
  12. #define NUM_BUFFERS_SOURCES 128
  13. #define BUFF_MASK (NUM_BUFFERS_SOURCES - 1 )
  14. #define BUFFER_SIZE 0x0400
  15. //-----------------------------------------------------------------------------
  16. //
  17. // NOTE: This only allows 16-bit, stereo wave out
  18. //
  19. //-----------------------------------------------------------------------------
  20. class CAudioDeviceOpenAL : public CAudioDeviceBase
  21. {
  22. public:
  23. CAudioDeviceOpenAL()
  24. {
  25. m_pName = "OpenAL Audio";
  26. m_nChannels = 2;
  27. m_nSampleBits = 16;
  28. m_nSampleRate = 44100;
  29. m_bIsActive = true;
  30. }
  31. bool IsActive( void );
  32. bool Init( void );
  33. void Shutdown( void );
  34. int GetOutputPosition( void );
  35. void Pause( void );
  36. void UnPause( void );
  37. int64 PaintBegin( float mixAheadTime, int64 soundtime, int64 paintedtime );
  38. void PaintEnd( void );
  39. void ClearBuffer( void );
  40. void UpdateListener( const Vector& position, const Vector& forward, const Vector& right, const Vector& up );
  41. void TransferSamples( int end );
  42. int DeviceSampleCount( void ) { return m_deviceSampleCount; }
  43. private:
  44. void OpenWaveOut( void );
  45. void CloseWaveOut( void );
  46. bool ValidWaveOut( void ) const;
  47. ALuint m_Buffer[NUM_BUFFERS_SOURCES];
  48. ALuint m_Source[1];
  49. int m_SndBufSize;
  50. void *m_sndBuffers;
  51. int m_deviceSampleCount;
  52. int m_buffersSent;
  53. int m_buffersCompleted;
  54. int m_pauseCount;
  55. bool m_bHeadphone;
  56. bool m_bSurround;
  57. bool m_bSurroundCenter;
  58. };
  59. IAudioDevice *Audio_CreateOpenALDevice( void )
  60. {
  61. static CAudioDeviceOpenAL *wave = NULL;
  62. if ( !wave )
  63. {
  64. wave = new CAudioDeviceOpenAL;
  65. }
  66. if ( wave->Init() )
  67. return wave;
  68. delete wave;
  69. wave = NULL;
  70. return NULL;
  71. }
  72. //-----------------------------------------------------------------------------
  73. // Init, shutdown
  74. //-----------------------------------------------------------------------------
  75. bool CAudioDeviceOpenAL::Init( void )
  76. {
  77. m_SndBufSize = 0;
  78. m_sndBuffers = NULL;
  79. m_pauseCount = 0;
  80. m_bIsHeadphone = false;
  81. m_buffersSent = 0;
  82. m_buffersCompleted = 0;
  83. m_pauseCount = 0;
  84. OpenWaveOut();
  85. if ( snd_firsttime )
  86. {
  87. DevMsg( "Wave sound initialized\n" );
  88. }
  89. return ValidWaveOut();
  90. }
  91. void CAudioDeviceOpenAL::Shutdown( void )
  92. {
  93. CloseWaveOut();
  94. }
  95. //-----------------------------------------------------------------------------
  96. // WAV out device
  97. //-----------------------------------------------------------------------------
  98. inline bool CAudioDeviceOpenAL::ValidWaveOut( void ) const
  99. {
  100. return m_sndBuffers != 0;
  101. }
  102. //-----------------------------------------------------------------------------
  103. // Opens the windows wave out device
  104. //-----------------------------------------------------------------------------
  105. void CAudioDeviceOpenAL::OpenWaveOut( void )
  106. {
  107. m_buffersSent = 0;
  108. m_buffersCompleted = 0;
  109. ALenum error;
  110. ALCcontext *newContext = NULL;
  111. ALCdevice *newDevice = NULL;
  112. // Create a new OpenAL Device
  113. // Pass NULL to specify the system‚use default output device
  114. const ALCchar *initStr = (const ALCchar *)"\'( (sampling-rate 44100 ))";
  115. newDevice = alcOpenDevice(initStr);
  116. if (newDevice != NULL)
  117. {
  118. // Create a new OpenAL Context
  119. // The new context will render to the OpenAL Device just created
  120. ALCint attr[] = { ALC_FREQUENCY, SampleRate(), ALC_SYNC, AL_FALSE, 0 };
  121. newContext = alcCreateContext(newDevice, attr );
  122. if (newContext != NULL)
  123. {
  124. // Make the new context the Current OpenAL Context
  125. alcMakeContextCurrent(newContext);
  126. // Create some OpenAL Buffer Objects
  127. alGenBuffers( NUM_BUFFERS_SOURCES, m_Buffer);
  128. if((error = alGetError()) != AL_NO_ERROR)
  129. {
  130. DevMsg("Error Generating Buffers: ");
  131. return;
  132. }
  133. // Create some OpenAL Source Objects
  134. alGenSources(1, m_Source);
  135. if(alGetError() != AL_NO_ERROR)
  136. {
  137. DevMsg("Error generating sources! \n");
  138. return;
  139. }
  140. alListener3f( AL_POSITION,0.0f,0.0f,0.0f);
  141. int i;
  142. for ( i = 0; i < 1; i++ )
  143. {
  144. alSource3f( m_Source[i],AL_POSITION,0.0f,0.0f,0.0f );
  145. alSourcef( m_Source[i], AL_PITCH, 1.0f );
  146. alSourcef( m_Source[i], AL_GAIN, 1.0f );
  147. }
  148. }
  149. }
  150. m_SndBufSize = NUM_BUFFERS_SOURCES*BUFFER_SIZE;
  151. m_deviceSampleCount = m_SndBufSize / DeviceSampleBytes();
  152. if ( !m_sndBuffers )
  153. {
  154. m_sndBuffers = malloc( m_SndBufSize );
  155. memset( m_sndBuffers, 0x0, m_SndBufSize );
  156. }
  157. }
  158. //-----------------------------------------------------------------------------
  159. // Closes the windows wave out device
  160. //-----------------------------------------------------------------------------
  161. void CAudioDeviceOpenAL::CloseWaveOut( void )
  162. {
  163. if ( ValidWaveOut() )
  164. {
  165. ALCcontext *context = NULL;
  166. ALCdevice *device = NULL;
  167. alSourceStop( m_Source[0] );
  168. // Delete the Sources
  169. alDeleteSources(1, m_Source);
  170. // Delete the Buffers
  171. alDeleteBuffers(NUM_BUFFERS_SOURCES, m_Buffer);
  172. //Get active context
  173. context = alcGetCurrentContext();
  174. //Get device for active context
  175. device = alcGetContextsDevice(context);
  176. alcMakeContextCurrent( NULL );
  177. alcSuspendContext(context);
  178. //Release context
  179. alcDestroyContext(context);
  180. //Close device
  181. alcCloseDevice(device);
  182. }
  183. if ( m_sndBuffers )
  184. {
  185. free( m_sndBuffers );
  186. m_sndBuffers = NULL;
  187. }
  188. }
  189. //-----------------------------------------------------------------------------
  190. // Mixing setup
  191. //-----------------------------------------------------------------------------
  192. int64 CAudioDeviceOpenAL::PaintBegin( float mixAheadTime, int64 soundtime, int64 paintedtime )
  193. {
  194. // soundtime - total samples that have been played out to hardware at dmaspeed
  195. // paintedtime - total samples that have been mixed at speed
  196. // endtime - target for samples in mixahead buffer at speed
  197. int64 endtime = soundtime + mixAheadTime * SampleRate();
  198. int samps = DeviceSampleCount() >> (ChannelCount()-1);
  199. if ((int)(endtime - soundtime) > samps)
  200. endtime = soundtime + samps;
  201. if ((endtime - paintedtime) & 0x3)
  202. {
  203. // The difference between endtime and painted time should align on
  204. // boundaries of 4 samples. This is important when upsampling from 11khz -> 44khz.
  205. endtime -= (endtime - paintedtime) & 0x3;
  206. }
  207. return endtime;
  208. }
  209. //-----------------------------------------------------------------------------
  210. // Actually performs the mixing
  211. //-----------------------------------------------------------------------------
  212. void CAudioDeviceOpenAL::PaintEnd( void )
  213. {
  214. if ( !m_sndBuffers )
  215. return;
  216. ALint state;
  217. ALenum error;
  218. int iloop;
  219. int cblocks = 4 << 1;
  220. ALint processed = 1;
  221. while ( processed > 0 )
  222. {
  223. alGetSourcei( m_Source[ 0 ], AL_BUFFERS_PROCESSED, &processed);
  224. if ( processed > 0 )
  225. {
  226. ALuint tempVal = 0;
  227. alSourceUnqueueBuffers( m_Source[ 0 ], 1, &tempVal );
  228. error = alGetError();
  229. if ( error != AL_NO_ERROR && error != AL_INVALID_NAME )
  230. {
  231. DevMsg( "Error alSourceUnqueueBuffers %d\n", error );
  232. }
  233. else
  234. {
  235. m_buffersCompleted++; // this buffer has been played
  236. }
  237. }
  238. }
  239. //
  240. // submit a few new sound blocks
  241. //
  242. // 44K sound support
  243. while (((m_buffersSent - m_buffersCompleted) >> SAMPLE_16BIT_SHIFT) < cblocks)
  244. {
  245. int iBuf = m_buffersSent&BUFF_MASK;
  246. alBufferData( m_Buffer[iBuf], AL_FORMAT_STEREO16, (char *)m_sndBuffers + iBuf*BUFFER_SIZE, BUFFER_SIZE, SampleRate() );
  247. if ( (error = alGetError()) != AL_NO_ERROR )
  248. {
  249. DevMsg( "Error alBufferData %d %d\n", iBuf, error );
  250. }
  251. alSourceQueueBuffers( m_Source[0], 1, &m_Buffer[iBuf] );
  252. if ( (error = alGetError() ) != AL_NO_ERROR )
  253. {
  254. DevMsg( "Error alSourceQueueBuffers %d %d\n", iBuf, error );
  255. }
  256. m_buffersSent++;
  257. }
  258. // make sure the stream is playing
  259. alGetSourcei( m_Source[ 0 ], AL_SOURCE_STATE, &state);
  260. if ( state != AL_PLAYING )
  261. {
  262. Warning( "Restarting sound playback\n" );
  263. alSourcePlay( m_Source[0] );
  264. if((error = alGetError()) != AL_NO_ERROR)
  265. {
  266. DevMsg( "Error alSourcePlay %d\n", error );
  267. }
  268. }
  269. }
  270. int CAudioDeviceOpenAL::GetOutputPosition( void )
  271. {
  272. int s = m_buffersSent * BUFFER_SIZE;
  273. s >>= SAMPLE_16BIT_SHIFT;
  274. s &= (DeviceSampleCount()-1);
  275. return s / ChannelCount();
  276. }
  277. //-----------------------------------------------------------------------------
  278. // Pausing
  279. //-----------------------------------------------------------------------------
  280. void CAudioDeviceOpenAL::Pause( void )
  281. {
  282. m_pauseCount++;
  283. if (m_pauseCount == 1)
  284. {
  285. alSourceStop( m_Source[0] );
  286. }
  287. }
  288. void CAudioDeviceOpenAL::UnPause( void )
  289. {
  290. if ( m_pauseCount > 0 )
  291. {
  292. m_pauseCount--;
  293. }
  294. if ( m_pauseCount == 0 )
  295. alSourcePlay( m_Source[0] );
  296. }
  297. bool CAudioDeviceOpenAL::IsActive( void )
  298. {
  299. return ( m_pauseCount == 0 );
  300. }
  301. void CAudioDeviceOpenAL::ClearBuffer( void )
  302. {
  303. if ( !m_sndBuffers )
  304. return;
  305. Q_memset( m_sndBuffers, 0x0, DeviceSampleCount() * DeviceSampleBytes() );
  306. }
  307. void CAudioDeviceOpenAL::UpdateListener( const Vector& position, const Vector& forward, const Vector& right, const Vector& up )
  308. {
  309. }
  310. void CAudioDeviceOpenAL::TransferSamples( int end )
  311. {
  312. int64 lpaintedtime = g_paintedtime;
  313. int64 endtime = end;
  314. // resumes playback...
  315. if ( m_sndBuffers )
  316. {
  317. S_TransferStereo16( m_sndBuffers, PAINTBUFFER, lpaintedtime, endtime );
  318. }
  319. }