Team Fortress 2 Source Code as on 22/4/2020
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.

611 lines
16 KiB

  1. //========= Copyright 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. #ifdef OSX
  10. #include <OpenAL/MacOSX_OALExtensions.h>
  11. #endif
  12. // memdbgon must be the last include file in a .cpp file!!!
  13. #include "tier0/memdbgon.h"
  14. #ifndef DEDICATED // have to test this because VPC is forcing us to compile this file.
  15. extern bool snd_firsttime;
  16. extern bool MIX_ScaleChannelVolume( paintbuffer_t *ppaint, channel_t *pChannel, int volume[CCHANVOLUMES], int mixchans );
  17. extern void S_SpatializeChannel( int volume[6], int master_vol, const Vector *psourceDir, float gain, float mono );
  18. #define NUM_BUFFERS_SOURCES 128
  19. #define BUFF_MASK (NUM_BUFFERS_SOURCES - 1 )
  20. #define BUFFER_SIZE 0x0400
  21. //-----------------------------------------------------------------------------
  22. //
  23. // NOTE: This only allows 16-bit, stereo wave out
  24. //
  25. //-----------------------------------------------------------------------------
  26. class CAudioDeviceOpenAL : public CAudioDeviceBase
  27. {
  28. public:
  29. bool IsActive( void );
  30. bool Init( void );
  31. void Shutdown( void );
  32. void PaintEnd( void );
  33. int GetOutputPosition( void );
  34. void ChannelReset( int entnum, int channelIndex, float distanceMod );
  35. void Pause( void );
  36. void UnPause( void );
  37. float MixDryVolume( void );
  38. bool Should3DMix( void );
  39. void StopAllSounds( void );
  40. int PaintBegin( float mixAheadTime, int soundtime, int paintedtime );
  41. void ClearBuffer( void );
  42. void UpdateListener( const Vector& position, const Vector& forward, const Vector& right, const Vector& up );
  43. void MixBegin( int sampleCount );
  44. void MixUpsample( int sampleCount, int filtertype );
  45. void Mix8Mono( channel_t *pChannel, char *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress );
  46. void Mix8Stereo( channel_t *pChannel, char *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress );
  47. void Mix16Mono( channel_t *pChannel, short *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress );
  48. void Mix16Stereo( channel_t *pChannel, short *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress );
  49. void TransferSamples( int end );
  50. void SpatializeChannel( int volume[CCHANVOLUMES/2], int master_vol, const Vector& sourceDir, float gain, float mono);
  51. void ApplyDSPEffects( int idsp, portable_samplepair_t *pbuffront, portable_samplepair_t *pbufrear, portable_samplepair_t *pbufcenter, int samplecount );
  52. const char *DeviceName( void ) { return "OpenAL"; }
  53. int DeviceChannels( void ) { return 2; }
  54. int DeviceSampleBits( void ) { return 16; }
  55. int DeviceSampleBytes( void ) { return 2; }
  56. int DeviceDmaSpeed( void ) { return SOUND_DMA_SPEED; }
  57. int DeviceSampleCount( void ) { return m_deviceSampleCount; }
  58. private:
  59. void OpenWaveOut( void );
  60. void CloseWaveOut( void );
  61. bool ValidWaveOut( void ) const;
  62. ALuint m_Buffer[NUM_BUFFERS_SOURCES];
  63. ALuint m_Source[1];
  64. int m_SndBufSize;
  65. void *m_sndBuffers;
  66. int m_deviceSampleCount;
  67. int m_buffersSent;
  68. int m_buffersCompleted;
  69. int m_pauseCount;
  70. bool m_bSoundsShutdown;
  71. };
  72. IAudioDevice *Audio_CreateOpenALDevice( void )
  73. {
  74. CAudioDeviceOpenAL *wave = NULL;
  75. if ( !wave )
  76. {
  77. wave = new CAudioDeviceOpenAL;
  78. }
  79. if ( wave->Init() )
  80. return wave;
  81. delete wave;
  82. wave = NULL;
  83. return NULL;
  84. }
  85. void OnSndSurroundCvarChanged( IConVar *pVar, const char *pOldString, float flOldValue );
  86. void OnSndSurroundLegacyChanged( IConVar *pVar, const char *pOldString, float flOldValue );
  87. //-----------------------------------------------------------------------------
  88. // Init, shutdown
  89. //-----------------------------------------------------------------------------
  90. bool CAudioDeviceOpenAL::Init( void )
  91. {
  92. m_SndBufSize = 0;
  93. m_sndBuffers = NULL;
  94. m_pauseCount = 0;
  95. m_bSurround = false;
  96. m_bSurroundCenter = false;
  97. m_bHeadphone = false;
  98. m_buffersSent = 0;
  99. m_buffersCompleted = 0;
  100. m_pauseCount = 0;
  101. m_bSoundsShutdown = false;
  102. static bool first = true;
  103. if ( first )
  104. {
  105. snd_surround.SetValue( 2 );
  106. snd_surround.InstallChangeCallback( &OnSndSurroundCvarChanged );
  107. snd_legacy_surround.InstallChangeCallback( &OnSndSurroundLegacyChanged );
  108. first = false;
  109. }
  110. OpenWaveOut();
  111. if ( snd_firsttime )
  112. {
  113. DevMsg( "Wave sound initialized\n" );
  114. }
  115. return ValidWaveOut();
  116. }
  117. void CAudioDeviceOpenAL::Shutdown( void )
  118. {
  119. CloseWaveOut();
  120. }
  121. //-----------------------------------------------------------------------------
  122. // WAV out device
  123. //-----------------------------------------------------------------------------
  124. inline bool CAudioDeviceOpenAL::ValidWaveOut( void ) const
  125. {
  126. return m_sndBuffers != 0;
  127. }
  128. //-----------------------------------------------------------------------------
  129. // Opens the windows wave out device
  130. //-----------------------------------------------------------------------------
  131. void CAudioDeviceOpenAL::OpenWaveOut( void )
  132. {
  133. m_buffersSent = 0;
  134. m_buffersCompleted = 0;
  135. ALenum error;
  136. ALCcontext *newContext = NULL;
  137. ALCdevice *newDevice = NULL;
  138. // Create a new OpenAL Device
  139. // Pass NULL to specify the system‚use default output device
  140. const ALCchar *initStr = (const ALCchar *)"\'( (sampling-rate 44100 ))";
  141. newDevice = alcOpenDevice(initStr);
  142. if (newDevice != NULL)
  143. {
  144. // Create a new OpenAL Context
  145. // The new context will render to the OpenAL Device just created
  146. ALCint attr[] = { ALC_FREQUENCY, DeviceDmaSpeed(), ALC_SYNC, AL_FALSE, 0 };
  147. newContext = alcCreateContext(newDevice, attr );
  148. if (newContext != NULL)
  149. {
  150. // Make the new context the Current OpenAL Context
  151. alcMakeContextCurrent(newContext);
  152. // Create some OpenAL Buffer Objects
  153. alGenBuffers( NUM_BUFFERS_SOURCES, m_Buffer);
  154. if((error = alGetError()) != AL_NO_ERROR)
  155. {
  156. DevMsg("Error Generating Buffers: ");
  157. return;
  158. }
  159. // Create some OpenAL Source Objects
  160. alGenSources(1, m_Source);
  161. if(alGetError() != AL_NO_ERROR)
  162. {
  163. DevMsg("Error generating sources! \n");
  164. return;
  165. }
  166. alListener3f( AL_POSITION,0.0f,0.0f,0.0f);
  167. int i;
  168. for ( i = 0; i < 1; i++ )
  169. {
  170. alSource3f( m_Source[i],AL_POSITION,0.0f,0.0f,0.0f );
  171. alSourcef( m_Source[i], AL_PITCH, 1.0f );
  172. alSourcef( m_Source[i], AL_GAIN, 1.0f );
  173. }
  174. }
  175. }
  176. m_SndBufSize = NUM_BUFFERS_SOURCES*BUFFER_SIZE;
  177. m_deviceSampleCount = m_SndBufSize / DeviceSampleBytes();
  178. if ( !m_sndBuffers )
  179. {
  180. m_sndBuffers = malloc( m_SndBufSize );
  181. memset( m_sndBuffers, 0x0, m_SndBufSize );
  182. }
  183. }
  184. //-----------------------------------------------------------------------------
  185. // Closes the windows wave out device
  186. //-----------------------------------------------------------------------------
  187. void CAudioDeviceOpenAL::CloseWaveOut( void )
  188. {
  189. if ( ValidWaveOut() )
  190. {
  191. ALCcontext *context = NULL;
  192. ALCdevice *device = NULL;
  193. m_bSoundsShutdown = true;
  194. alSourceStop( m_Source[0] );
  195. // Delete the Sources
  196. alDeleteSources(1, m_Source);
  197. // Delete the Buffers
  198. alDeleteBuffers(NUM_BUFFERS_SOURCES, m_Buffer);
  199. //Get active context
  200. context = alcGetCurrentContext();
  201. //Get device for active context
  202. device = alcGetContextsDevice(context);
  203. alcMakeContextCurrent( NULL );
  204. alcSuspendContext(context);
  205. //Release context
  206. alcDestroyContext(context);
  207. //Close device
  208. alcCloseDevice(device);
  209. }
  210. if ( m_sndBuffers )
  211. {
  212. free( m_sndBuffers );
  213. m_sndBuffers = NULL;
  214. }
  215. }
  216. //-----------------------------------------------------------------------------
  217. // Mixing setup
  218. //-----------------------------------------------------------------------------
  219. int CAudioDeviceOpenAL::PaintBegin( float mixAheadTime, int soundtime, int paintedtime )
  220. {
  221. // soundtime - total samples that have been played out to hardware at dmaspeed
  222. // paintedtime - total samples that have been mixed at speed
  223. // endtime - target for samples in mixahead buffer at speed
  224. unsigned int endtime = soundtime + mixAheadTime * DeviceDmaSpeed();
  225. int samps = DeviceSampleCount() >> (DeviceChannels()-1);
  226. if ((int)(endtime - soundtime) > samps)
  227. endtime = soundtime + samps;
  228. if ((endtime - paintedtime) & 0x3)
  229. {
  230. // The difference between endtime and painted time should align on
  231. // boundaries of 4 samples. This is important when upsampling from 11khz -> 44khz.
  232. endtime -= (endtime - paintedtime) & 0x3;
  233. }
  234. return endtime;
  235. }
  236. #ifdef OSX
  237. ALvoid alBufferDataStaticProc(const ALint bid, ALenum format, ALvoid* data, ALsizei size, ALsizei freq)
  238. {
  239. static alBufferDataStaticProcPtr proc = NULL;
  240. if (proc == NULL) {
  241. proc = (alBufferDataStaticProcPtr) alGetProcAddress((const ALCchar*) "alBufferDataStatic");
  242. }
  243. if (proc)
  244. proc(bid, format, data, size, freq);
  245. }
  246. #endif
  247. //-----------------------------------------------------------------------------
  248. // Actually performs the mixing
  249. //-----------------------------------------------------------------------------
  250. void CAudioDeviceOpenAL::PaintEnd( void )
  251. {
  252. if ( !m_sndBuffers /*|| m_bSoundsShutdown*/ )
  253. return;
  254. ALint state;
  255. ALenum error;
  256. int iloop;
  257. int cblocks = 4 << 1;
  258. ALint processed = 1;
  259. ALuint lastUnqueuedBuffer = 0;
  260. ALuint unqueuedBuffer = -1;
  261. int nProcessedLoop = 200; // spin for a max of 200 times de-queing buffers, fixes a hang on exit
  262. while ( processed > 0 && --nProcessedLoop > 0 )
  263. {
  264. alGetSourcei( m_Source[ 0 ], AL_BUFFERS_PROCESSED, &processed);
  265. error = alGetError();
  266. if (error != AL_NO_ERROR)
  267. break;
  268. if ( processed > 0 )
  269. {
  270. lastUnqueuedBuffer = unqueuedBuffer;
  271. alSourceUnqueueBuffers( m_Source[ 0 ], 1, &unqueuedBuffer );
  272. error = alGetError();
  273. if ( error != AL_NO_ERROR && error != AL_INVALID_NAME )
  274. {
  275. DevMsg( "Error alSourceUnqueueBuffers %d\n", error );
  276. break;
  277. }
  278. else
  279. {
  280. m_buffersCompleted++; // this buffer has been played
  281. }
  282. }
  283. }
  284. //
  285. // submit a few new sound blocks
  286. //
  287. // 44K sound support
  288. while (((m_buffersSent - m_buffersCompleted) >> SAMPLE_16BIT_SHIFT) < cblocks)
  289. {
  290. int iBuf = m_buffersSent&BUFF_MASK;
  291. #ifdef OSX
  292. alBufferDataStaticProc( m_Buffer[iBuf], AL_FORMAT_STEREO16, (char *)m_sndBuffers + iBuf*BUFFER_SIZE, BUFFER_SIZE, DeviceDmaSpeed() );
  293. #else
  294. alBufferData( m_Buffer[iBuf], AL_FORMAT_STEREO16, (char *)m_sndBuffers + iBuf*BUFFER_SIZE, BUFFER_SIZE, DeviceDmaSpeed() );
  295. #endif
  296. if ( (error = alGetError()) != AL_NO_ERROR )
  297. {
  298. DevMsg( "Error alBufferData %d %d\n", iBuf, error );
  299. }
  300. alSourceQueueBuffers( m_Source[0], 1, &m_Buffer[iBuf] );
  301. if ( (error = alGetError() ) != AL_NO_ERROR )
  302. {
  303. DevMsg( "Error alSourceQueueBuffers %d %d\n", iBuf, error );
  304. }
  305. m_buffersSent++;
  306. }
  307. // make sure the stream is playing
  308. alGetSourcei( m_Source[ 0 ], AL_SOURCE_STATE, &state);
  309. if ( state != AL_PLAYING )
  310. {
  311. DevMsg( "Restarting sound playback\n" );
  312. alSourcePlay( m_Source[0] );
  313. if((error = alGetError()) != AL_NO_ERROR)
  314. {
  315. DevMsg( "Error alSourcePlay %d\n", error );
  316. }
  317. }
  318. }
  319. int CAudioDeviceOpenAL::GetOutputPosition( void )
  320. {
  321. int s = m_buffersSent * BUFFER_SIZE;
  322. s >>= SAMPLE_16BIT_SHIFT;
  323. s &= (DeviceSampleCount()-1);
  324. return s / DeviceChannels();
  325. }
  326. //-----------------------------------------------------------------------------
  327. // Pausing
  328. //-----------------------------------------------------------------------------
  329. void CAudioDeviceOpenAL::Pause( void )
  330. {
  331. m_pauseCount++;
  332. if (m_pauseCount == 1)
  333. {
  334. alSourceStop( m_Source[0] );
  335. }
  336. }
  337. void CAudioDeviceOpenAL::UnPause( void )
  338. {
  339. if ( m_pauseCount > 0 )
  340. {
  341. m_pauseCount--;
  342. }
  343. if ( m_pauseCount == 0 )
  344. {
  345. alSourcePlay( m_Source[0] );
  346. }
  347. }
  348. bool CAudioDeviceOpenAL::IsActive( void )
  349. {
  350. return ( m_pauseCount == 0 );
  351. }
  352. float CAudioDeviceOpenAL::MixDryVolume( void )
  353. {
  354. return 0;
  355. }
  356. bool CAudioDeviceOpenAL::Should3DMix( void )
  357. {
  358. return false;
  359. }
  360. void CAudioDeviceOpenAL::ClearBuffer( void )
  361. {
  362. if ( !m_sndBuffers )
  363. return;
  364. Q_memset( m_sndBuffers, 0x0, DeviceSampleCount() * DeviceSampleBytes() );
  365. }
  366. void CAudioDeviceOpenAL::UpdateListener( const Vector& position, const Vector& forward, const Vector& right, const Vector& up )
  367. {
  368. }
  369. void CAudioDeviceOpenAL::MixBegin( int sampleCount )
  370. {
  371. MIX_ClearAllPaintBuffers( sampleCount, false );
  372. }
  373. void CAudioDeviceOpenAL::MixUpsample( int sampleCount, int filtertype )
  374. {
  375. paintbuffer_t *ppaint = MIX_GetCurrentPaintbufferPtr();
  376. int ifilter = ppaint->ifilter;
  377. Assert (ifilter < CPAINTFILTERS);
  378. S_MixBufferUpsample2x( sampleCount, ppaint->pbuf, &(ppaint->fltmem[ifilter][0]), CPAINTFILTERMEM, filtertype );
  379. ppaint->ifilter++;
  380. }
  381. void CAudioDeviceOpenAL::Mix8Mono( channel_t *pChannel, char *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress )
  382. {
  383. int volume[CCHANVOLUMES];
  384. paintbuffer_t *ppaint = MIX_GetCurrentPaintbufferPtr();
  385. if (!MIX_ScaleChannelVolume( ppaint, pChannel, volume, 1))
  386. return;
  387. Mix8MonoWavtype( pChannel, ppaint->pbuf + outputOffset, volume, (byte *)pData, inputOffset, rateScaleFix, outCount );
  388. }
  389. void CAudioDeviceOpenAL::Mix8Stereo( channel_t *pChannel, char *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress )
  390. {
  391. int volume[CCHANVOLUMES];
  392. paintbuffer_t *ppaint = MIX_GetCurrentPaintbufferPtr();
  393. if (!MIX_ScaleChannelVolume( ppaint, pChannel, volume, 2 ))
  394. return;
  395. Mix8StereoWavtype( pChannel, ppaint->pbuf + outputOffset, volume, (byte *)pData, inputOffset, rateScaleFix, outCount );
  396. }
  397. void CAudioDeviceOpenAL::Mix16Mono( channel_t *pChannel, short *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress )
  398. {
  399. int volume[CCHANVOLUMES];
  400. paintbuffer_t *ppaint = MIX_GetCurrentPaintbufferPtr();
  401. if (!MIX_ScaleChannelVolume( ppaint, pChannel, volume, 1 ))
  402. return;
  403. Mix16MonoWavtype( pChannel, ppaint->pbuf + outputOffset, volume, pData, inputOffset, rateScaleFix, outCount );
  404. }
  405. void CAudioDeviceOpenAL::Mix16Stereo( channel_t *pChannel, short *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress )
  406. {
  407. int volume[CCHANVOLUMES];
  408. paintbuffer_t *ppaint = MIX_GetCurrentPaintbufferPtr();
  409. if (!MIX_ScaleChannelVolume( ppaint, pChannel, volume, 2 ))
  410. return;
  411. Mix16StereoWavtype( pChannel, ppaint->pbuf + outputOffset, volume, pData, inputOffset, rateScaleFix, outCount );
  412. }
  413. void CAudioDeviceOpenAL::ChannelReset( int entnum, int channelIndex, float distanceMod )
  414. {
  415. }
  416. void CAudioDeviceOpenAL::TransferSamples( int end )
  417. {
  418. int lpaintedtime = g_paintedtime;
  419. int endtime = end;
  420. // resumes playback...
  421. if ( m_sndBuffers )
  422. {
  423. S_TransferStereo16( m_sndBuffers, PAINTBUFFER, lpaintedtime, endtime );
  424. }
  425. }
  426. void CAudioDeviceOpenAL::SpatializeChannel( int volume[CCHANVOLUMES/2], int master_vol, const Vector& sourceDir, float gain, float mono )
  427. {
  428. VPROF("CAudioDeviceOpenAL::SpatializeChannel");
  429. S_SpatializeChannel( volume, master_vol, &sourceDir, gain, mono );
  430. }
  431. void CAudioDeviceOpenAL::StopAllSounds( void )
  432. {
  433. m_bSoundsShutdown = true;
  434. alSourceStop( m_Source[0] );
  435. }
  436. void CAudioDeviceOpenAL::ApplyDSPEffects( int idsp, portable_samplepair_t *pbuffront, portable_samplepair_t *pbufrear, portable_samplepair_t *pbufcenter, int samplecount )
  437. {
  438. //SX_RoomFX( endtime, filter, timefx );
  439. DSP_Process( idsp, pbuffront, pbufrear, pbufcenter, samplecount );
  440. }
  441. static uint32 GetOSXSpeakerConfig()
  442. {
  443. return 2;
  444. }
  445. static uint32 GetSpeakerConfigForSurroundMode( int surroundMode, const char **pConfigDesc )
  446. {
  447. uint32 newSpeakerConfig = 2;
  448. *pConfigDesc = "stereo speaker";
  449. return newSpeakerConfig;
  450. }
  451. void OnSndSurroundCvarChanged( IConVar *pVar, const char *pOldString, float flOldValue )
  452. {
  453. // if the old value is -1, we're setting this from the detect routine for the first time
  454. // no need to reset the device
  455. if ( flOldValue == -1 )
  456. return;
  457. // get the user's previous speaker config
  458. uint32 speaker_config = GetOSXSpeakerConfig();
  459. // get the new config
  460. uint32 newSpeakerConfig = 0;
  461. const char *speakerConfigDesc = "";
  462. ConVarRef var( pVar );
  463. newSpeakerConfig = GetSpeakerConfigForSurroundMode( var.GetInt(), &speakerConfigDesc );
  464. // make sure the config has changed
  465. if (newSpeakerConfig == speaker_config)
  466. return;
  467. // set new configuration
  468. //SetWindowsSpeakerConfig(newSpeakerConfig);
  469. Msg("Speaker configuration has been changed to %s.\n", speakerConfigDesc);
  470. // restart sound system so it takes effect
  471. //g_pSoundServices->RestartSoundSystem();
  472. }
  473. void OnSndSurroundLegacyChanged( IConVar *pVar, const char *pOldString, float flOldValue )
  474. {
  475. }
  476. #endif // !DEDICATED