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.

574 lines
17 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //===========================================================================//
  6. #include "audio_pch.h"
  7. #if !DEDICATED
  8. #include "tier0/dynfunction.h"
  9. #include "video//ivideoservices.h"
  10. #include "../../sys_dll.h"
  11. // prevent some conflicts in SDL headers...
  12. #undef M_PI
  13. #include <stdint.h>
  14. #ifndef _STDINT_H_
  15. #define _STDINT_H_ 1
  16. #endif
  17. #include "SDL.h"
  18. // memdbgon must be the last include file in a .cpp file!!!
  19. #include "tier0/memdbgon.h"
  20. extern bool snd_firsttime;
  21. extern bool MIX_ScaleChannelVolume( paintbuffer_t *ppaint, channel_t *pChannel, int volume[CCHANVOLUMES], int mixchans );
  22. extern void S_SpatializeChannel( /*int nSlot,*/ int volume[6], int master_vol, const Vector *psourceDir, float gain, float mono );
  23. // 64K is about 1/3 second at 16-bit, stereo, 44100 Hz
  24. // 44k: UNDONE - need to double buffers now that we're playing back at 44100?
  25. #define WAV_BUFFERS 64
  26. #define WAV_MASK (WAV_BUFFERS - 1)
  27. #define WAV_BUFFER_SIZE 0x0400
  28. #if 0
  29. #define debugsdl printf
  30. #else
  31. static inline void debugsdl(const char *fmt, ...) {}
  32. #endif
  33. //-----------------------------------------------------------------------------
  34. //
  35. // NOTE: This only allows 16-bit, stereo wave out (!!! FIXME: but SDL supports 7.1, etc, too!)
  36. //
  37. //-----------------------------------------------------------------------------
  38. class CAudioDeviceSDLAudio : public CAudioDeviceBase
  39. {
  40. public:
  41. CAudioDeviceSDLAudio();
  42. virtual ~CAudioDeviceSDLAudio();
  43. bool IsActive( void );
  44. bool Init( void );
  45. void Shutdown( void );
  46. void PaintEnd( void );
  47. int GetOutputPosition( void );
  48. void ChannelReset( int entnum, int channelIndex, float distanceMod );
  49. void Pause( void );
  50. void UnPause( void );
  51. float MixDryVolume( void );
  52. bool Should3DMix( void );
  53. void StopAllSounds( void );
  54. int PaintBegin( float mixAheadTime, int soundtime, int paintedtime );
  55. void ClearBuffer( void );
  56. void MixBegin( int sampleCount );
  57. void MixUpsample( int sampleCount, int filtertype );
  58. void Mix8Mono( channel_t *pChannel, char *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress );
  59. void Mix8Stereo( channel_t *pChannel, char *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress );
  60. void Mix16Mono( channel_t *pChannel, short *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress );
  61. void Mix16Stereo( channel_t *pChannel, short *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress );
  62. void TransferSamples( int end );
  63. void SpatializeChannel( int nSlot, int volume[CCHANVOLUMES/2], int master_vol, const Vector& sourceDir, float gain, float mono);
  64. void ApplyDSPEffects( int idsp, portable_samplepair_t *pbuffront, portable_samplepair_t *pbufrear, portable_samplepair_t *pbufcenter, int samplecount );
  65. const char *DeviceName( void ) { return "SDL"; }
  66. int DeviceChannels( void ) { return 2; }
  67. int DeviceSampleBits( void ) { return 16; }
  68. int DeviceSampleBytes( void ) { return 2; }
  69. int DeviceDmaSpeed( void ) { return SOUND_DMA_SPEED; }
  70. int DeviceSampleCount( void ) { return m_deviceSampleCount; }
  71. private:
  72. SDL_AudioDeviceID m_devId;
  73. static void SDLCALL AudioCallbackEntry(void *userdata, Uint8 * stream, int len);
  74. void AudioCallback(Uint8 *stream, int len);
  75. void OpenWaveOut( void );
  76. void CloseWaveOut( void );
  77. void AllocateOutputBuffers();
  78. void FreeOutputBuffers();
  79. bool ValidWaveOut( void ) const;
  80. int m_deviceSampleCount;
  81. int m_buffersSent;
  82. int m_pauseCount;
  83. int m_readPos;
  84. int m_partialWrite;
  85. // Memory for the wave data
  86. uint8_t *m_pBuffer;
  87. };
  88. static CAudioDeviceSDLAudio *g_wave = NULL;
  89. //-----------------------------------------------------------------------------
  90. // Constructor (just lookup SDL entry points, real work happens in this->Init())
  91. //-----------------------------------------------------------------------------
  92. CAudioDeviceSDLAudio::CAudioDeviceSDLAudio()
  93. {
  94. m_devId = 0;
  95. }
  96. //-----------------------------------------------------------------------------
  97. // Destructor. Make sure our global pointer gets set to NULL.
  98. //-----------------------------------------------------------------------------
  99. CAudioDeviceSDLAudio::~CAudioDeviceSDLAudio()
  100. {
  101. g_wave = NULL;
  102. }
  103. //-----------------------------------------------------------------------------
  104. // Class factory
  105. //-----------------------------------------------------------------------------
  106. IAudioDevice *Audio_CreateSDLAudioDevice( void )
  107. {
  108. if ( !g_wave )
  109. {
  110. g_wave = new CAudioDeviceSDLAudio;
  111. Assert( g_wave );
  112. }
  113. if ( g_wave && !g_wave->Init() )
  114. {
  115. delete g_wave;
  116. g_wave = NULL;
  117. }
  118. return g_wave;
  119. }
  120. //-----------------------------------------------------------------------------
  121. // Init, shutdown
  122. //-----------------------------------------------------------------------------
  123. bool CAudioDeviceSDLAudio::Init( void )
  124. {
  125. // If we've already got a device open, then return. This allows folks to call
  126. // Audio_CreateSDLAudioDevice() multiple times. CloseWaveOut() will free the
  127. // device, and set m_devId to 0.
  128. if( m_devId )
  129. return true;
  130. m_bSurround = false;
  131. m_bSurroundCenter = false;
  132. m_bHeadphone = false;
  133. m_buffersSent = 0;
  134. m_pauseCount = 0;
  135. m_pBuffer = NULL;
  136. m_readPos = 0;
  137. m_partialWrite = 0;
  138. m_devId = 0;
  139. OpenWaveOut();
  140. if ( snd_firsttime )
  141. {
  142. DevMsg( "Wave sound initialized\n" );
  143. }
  144. return ValidWaveOut();
  145. }
  146. void CAudioDeviceSDLAudio::Shutdown( void )
  147. {
  148. CloseWaveOut();
  149. }
  150. //-----------------------------------------------------------------------------
  151. // WAV out device
  152. //-----------------------------------------------------------------------------
  153. inline bool CAudioDeviceSDLAudio::ValidWaveOut( void ) const
  154. {
  155. return m_devId != 0;
  156. }
  157. //-----------------------------------------------------------------------------
  158. // Opens the windows wave out device
  159. //-----------------------------------------------------------------------------
  160. void CAudioDeviceSDLAudio::OpenWaveOut( void )
  161. {
  162. debugsdl("SDLAUDIO: OpenWaveOut...\n");
  163. #ifndef WIN32
  164. char appname[ 256 ];
  165. KeyValues *modinfo = new KeyValues( "ModInfo" );
  166. if ( modinfo->LoadFromFile( g_pFileSystem, "gameinfo.txt" ) )
  167. Q_strncpy( appname, modinfo->GetString( "game" ), sizeof( appname ) );
  168. else
  169. Q_strncpy( appname, "Source1 Game", sizeof( appname ) );
  170. modinfo->deleteThis();
  171. modinfo = NULL;
  172. // Set these environment variables, in case we're using PulseAudio.
  173. setenv("PULSE_PROP_application.name", appname, 1);
  174. setenv("PULSE_PROP_media.role", "game", 1);
  175. #endif
  176. // !!! FIXME: specify channel map, etc
  177. // !!! FIXME: set properties (role, icon, etc).
  178. //#define SDLAUDIO_FAIL(fnstr) do { DevWarning(fnstr " failed"); CloseWaveOut(); return; } while (false)
  179. //#define SDLAUDIO_FAIL(fnstr) do { printf("SDLAUDIO: " fnstr " failed: %s\n", SDL_GetError ? SDL_GetError() : "???"); CloseWaveOut(); return; } while (false)
  180. #define SDLAUDIO_FAIL(fnstr) do { const char *err = SDL_GetError(); printf("SDLAUDIO: " fnstr " failed: %s\n", err ? err : "???"); CloseWaveOut(); return; } while (false)
  181. if (!SDL_WasInit(SDL_INIT_AUDIO))
  182. {
  183. if (SDL_InitSubSystem(SDL_INIT_AUDIO))
  184. SDLAUDIO_FAIL("SDL_InitSubSystem(SDL_INIT_AUDIO)");
  185. }
  186. debugsdl("SDLAUDIO: Using SDL audio target '%s'\n", SDL_GetCurrentAudioDriver());
  187. // Open an audio device...
  188. // !!! FIXME: let user specify a device?
  189. // !!! FIXME: we can handle quad, 5.1, 7.1, etc here.
  190. SDL_AudioSpec desired, obtained;
  191. memset(&desired, '\0', sizeof (desired));
  192. desired.freq = SOUND_DMA_SPEED;
  193. desired.format = AUDIO_S16SYS;
  194. desired.channels = 2;
  195. desired.samples = 2048;
  196. desired.callback = &CAudioDeviceSDLAudio::AudioCallbackEntry;
  197. desired.userdata = this;
  198. m_devId = SDL_OpenAudioDevice(NULL, 0, &desired, &obtained, SDL_AUDIO_ALLOW_ANY_CHANGE);
  199. if (!m_devId)
  200. SDLAUDIO_FAIL("SDL_OpenAudioDevice()");
  201. #undef SDLAUDIO_FAIL
  202. // We're now ready to feed audio data to SDL!
  203. AllocateOutputBuffers();
  204. SDL_PauseAudioDevice(m_devId, 0);
  205. #if defined( BINK_VIDEO ) && defined( LINUX )
  206. // Tells Bink to use SDL for its audio decoding
  207. if ( g_pVideo != NULL)
  208. {
  209. g_pVideo->SoundDeviceCommand( VideoSoundDeviceOperation::SET_SDL_PARAMS, NULL, (void *)&obtained );
  210. }
  211. #endif
  212. }
  213. //-----------------------------------------------------------------------------
  214. // Closes the windows wave out device
  215. //-----------------------------------------------------------------------------
  216. void CAudioDeviceSDLAudio::CloseWaveOut( void )
  217. {
  218. // none of these SDL_* functions are available to call if this is false.
  219. if (m_devId)
  220. {
  221. SDL_CloseAudioDevice(m_devId);
  222. m_devId = 0;
  223. }
  224. SDL_QuitSubSystem(SDL_INIT_AUDIO);
  225. FreeOutputBuffers();
  226. }
  227. //-----------------------------------------------------------------------------
  228. // Allocate output buffers
  229. //-----------------------------------------------------------------------------
  230. void CAudioDeviceSDLAudio::AllocateOutputBuffers()
  231. {
  232. // Allocate and lock memory for the waveform data.
  233. const int nBufferSize = WAV_BUFFER_SIZE * WAV_BUFFERS;
  234. m_pBuffer = new uint8_t[nBufferSize];
  235. memset(m_pBuffer, '\0', nBufferSize);
  236. m_readPos = 0;
  237. m_partialWrite = 0;
  238. m_deviceSampleCount = nBufferSize / DeviceSampleBytes();
  239. }
  240. //-----------------------------------------------------------------------------
  241. // Free output buffers
  242. //-----------------------------------------------------------------------------
  243. void CAudioDeviceSDLAudio::FreeOutputBuffers()
  244. {
  245. delete[] m_pBuffer;
  246. m_pBuffer = NULL;
  247. }
  248. //-----------------------------------------------------------------------------
  249. // Mixing setup
  250. //-----------------------------------------------------------------------------
  251. int CAudioDeviceSDLAudio::PaintBegin( float mixAheadTime, int soundtime, int paintedtime )
  252. {
  253. // soundtime - total samples that have been played out to hardware at dmaspeed
  254. // paintedtime - total samples that have been mixed at speed
  255. // endtime - target for samples in mixahead buffer at speed
  256. unsigned int endtime = soundtime + mixAheadTime * DeviceDmaSpeed();
  257. int samps = DeviceSampleCount() >> (DeviceChannels()-1);
  258. if ((int)(endtime - soundtime) > samps)
  259. endtime = soundtime + samps;
  260. if ((endtime - paintedtime) & 0x3)
  261. {
  262. // The difference between endtime and painted time should align on
  263. // boundaries of 4 samples. This is important when upsampling from 11khz -> 44khz.
  264. endtime -= (endtime - paintedtime) & 0x3;
  265. }
  266. return endtime;
  267. }
  268. void CAudioDeviceSDLAudio::AudioCallbackEntry(void *userdata, Uint8 *stream, int len)
  269. {
  270. ((CAudioDeviceSDLAudio *) userdata)->AudioCallback(stream, len);
  271. }
  272. void CAudioDeviceSDLAudio::AudioCallback(Uint8 *stream, int len)
  273. {
  274. if (!m_devId)
  275. {
  276. debugsdl("SDLAUDIO: uhoh, no audio device!\n");
  277. return; // can this even happen?
  278. }
  279. const int totalWriteable = len;
  280. #if defined( BINK_VIDEO ) && defined( LINUX )
  281. Uint8 *stream_orig = stream;
  282. #endif
  283. debugsdl("SDLAUDIO: writable size is %d.\n", totalWriteable);
  284. Assert(len <= (WAV_BUFFERS * WAV_BUFFER_SIZE));
  285. while (len > 0)
  286. {
  287. // spaceAvailable == bytes before we overrun the end of the ring buffer.
  288. const int spaceAvailable = ((WAV_BUFFERS * WAV_BUFFER_SIZE) - m_readPos);
  289. const int writeLen = (len < spaceAvailable) ? len : spaceAvailable;
  290. if (writeLen > 0)
  291. {
  292. const uint8_t *buf = m_pBuffer + m_readPos;
  293. debugsdl("SDLAUDIO: Writing %d bytes...\n", writeLen);
  294. #if 0
  295. static FILE *io = NULL;
  296. if (io == NULL) io = fopen("dumpplayback.raw", "wb");
  297. if (io != NULL) { fwrite(buf, writeLen, 1, io); fflush(io); }
  298. #endif
  299. memcpy(stream, buf, writeLen);
  300. stream += writeLen;
  301. len -= writeLen;
  302. Assert(len >= 0);
  303. }
  304. m_readPos = len ? 0 : (m_readPos + writeLen); // if still bytes to write to stream, we're rolling around the ring buffer.
  305. }
  306. #if defined( BINK_VIDEO ) && defined( LINUX )
  307. // Mix in Bink movie audio if that stuff is playing.
  308. if ( g_pVideo != NULL)
  309. {
  310. g_pVideo->SoundDeviceCommand( VideoSoundDeviceOperation::SDLMIXER_CALLBACK, (void *)stream_orig, (void *)&totalWriteable );
  311. }
  312. #endif
  313. // Translate between bytes written and buffers written.
  314. m_partialWrite += totalWriteable;
  315. m_buffersSent += m_partialWrite / WAV_BUFFER_SIZE;
  316. m_partialWrite %= WAV_BUFFER_SIZE;
  317. }
  318. //-----------------------------------------------------------------------------
  319. // Actually performs the mixing
  320. //-----------------------------------------------------------------------------
  321. void CAudioDeviceSDLAudio::PaintEnd( void )
  322. {
  323. debugsdl("SDLAUDIO: PaintEnd...\n");
  324. #if 0 // !!! FIXME: this is the 1.3 headers, but not implemented yet in SDL.
  325. if (SDL_AudioDeviceConnected(m_devId) != 1)
  326. {
  327. debugsdl("SDLAUDIO: Audio device was disconnected!\n");
  328. Shutdown();
  329. }
  330. #endif
  331. }
  332. int CAudioDeviceSDLAudio::GetOutputPosition( void )
  333. {
  334. return (m_readPos >> SAMPLE_16BIT_SHIFT)/DeviceChannels();
  335. }
  336. //-----------------------------------------------------------------------------
  337. // Pausing
  338. //-----------------------------------------------------------------------------
  339. void CAudioDeviceSDLAudio::Pause( void )
  340. {
  341. m_pauseCount++;
  342. if (m_pauseCount == 1)
  343. {
  344. debugsdl("SDLAUDIO: PAUSE\n");
  345. SDL_PauseAudioDevice(m_devId, 1);
  346. }
  347. }
  348. void CAudioDeviceSDLAudio::UnPause( void )
  349. {
  350. if ( m_pauseCount > 0 )
  351. {
  352. m_pauseCount--;
  353. if (m_pauseCount == 0)
  354. {
  355. debugsdl("SDLAUDIO: UNPAUSE\n");
  356. SDL_PauseAudioDevice(m_devId, 0);
  357. }
  358. }
  359. }
  360. bool CAudioDeviceSDLAudio::IsActive( void )
  361. {
  362. return ( m_pauseCount == 0 );
  363. }
  364. float CAudioDeviceSDLAudio::MixDryVolume( void )
  365. {
  366. return 0;
  367. }
  368. bool CAudioDeviceSDLAudio::Should3DMix( void )
  369. {
  370. return false;
  371. }
  372. void CAudioDeviceSDLAudio::ClearBuffer( void )
  373. {
  374. int clear;
  375. if ( !m_pBuffer )
  376. return;
  377. clear = 0;
  378. Q_memset(m_pBuffer, clear, DeviceSampleCount() * DeviceSampleBytes() );
  379. }
  380. void CAudioDeviceSDLAudio::MixBegin( int sampleCount )
  381. {
  382. MIX_ClearAllPaintBuffers( sampleCount, false );
  383. }
  384. void CAudioDeviceSDLAudio::MixUpsample( int sampleCount, int filtertype )
  385. {
  386. paintbuffer_t *ppaint = MIX_GetCurrentPaintbufferPtr();
  387. int ifilter = ppaint->ifilter;
  388. Assert (ifilter < CPAINTFILTERS);
  389. S_MixBufferUpsample2x( sampleCount, ppaint->pbuf, &(ppaint->fltmem[ifilter][0]), CPAINTFILTERMEM, filtertype );
  390. ppaint->ifilter++;
  391. }
  392. void CAudioDeviceSDLAudio::Mix8Mono( channel_t *pChannel, char *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress )
  393. {
  394. int volume[CCHANVOLUMES];
  395. paintbuffer_t *ppaint = MIX_GetCurrentPaintbufferPtr();
  396. if (!MIX_ScaleChannelVolume( ppaint, pChannel, volume, 1))
  397. return;
  398. Mix8MonoWavtype( pChannel, ppaint->pbuf + outputOffset, volume, (byte *)pData, inputOffset, rateScaleFix, outCount );
  399. }
  400. void CAudioDeviceSDLAudio::Mix8Stereo( channel_t *pChannel, char *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress )
  401. {
  402. int volume[CCHANVOLUMES];
  403. paintbuffer_t *ppaint = MIX_GetCurrentPaintbufferPtr();
  404. if (!MIX_ScaleChannelVolume( ppaint, pChannel, volume, 2 ))
  405. return;
  406. Mix8StereoWavtype( pChannel, ppaint->pbuf + outputOffset, volume, (byte *)pData, inputOffset, rateScaleFix, outCount );
  407. }
  408. void CAudioDeviceSDLAudio::Mix16Mono( channel_t *pChannel, short *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress )
  409. {
  410. int volume[CCHANVOLUMES];
  411. paintbuffer_t *ppaint = MIX_GetCurrentPaintbufferPtr();
  412. if (!MIX_ScaleChannelVolume( ppaint, pChannel, volume, 1 ))
  413. return;
  414. Mix16MonoWavtype( pChannel, ppaint->pbuf + outputOffset, volume, pData, inputOffset, rateScaleFix, outCount );
  415. }
  416. void CAudioDeviceSDLAudio::Mix16Stereo( channel_t *pChannel, short *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress )
  417. {
  418. int volume[CCHANVOLUMES];
  419. paintbuffer_t *ppaint = MIX_GetCurrentPaintbufferPtr();
  420. if (!MIX_ScaleChannelVolume( ppaint, pChannel, volume, 2 ))
  421. return;
  422. Mix16StereoWavtype( pChannel, ppaint->pbuf + outputOffset, volume, pData, inputOffset, rateScaleFix, outCount );
  423. }
  424. void CAudioDeviceSDLAudio::ChannelReset( int entnum, int channelIndex, float distanceMod )
  425. {
  426. }
  427. void CAudioDeviceSDLAudio::TransferSamples( int end )
  428. {
  429. int lpaintedtime = g_paintedtime;
  430. int endtime = end;
  431. // resumes playback...
  432. if ( m_pBuffer )
  433. {
  434. S_TransferStereo16( m_pBuffer, PAINTBUFFER, lpaintedtime, endtime );
  435. }
  436. }
  437. void CAudioDeviceSDLAudio::SpatializeChannel( int nSlot, int volume[CCHANVOLUMES/2], int master_vol, const Vector& sourceDir, float gain, float mono )
  438. {
  439. VPROF("CAudioDeviceSDLAudio::SpatializeChannel");
  440. S_SpatializeChannel( /*nSlot,*/ volume, master_vol, &sourceDir, gain, mono );
  441. }
  442. void CAudioDeviceSDLAudio::StopAllSounds( void )
  443. {
  444. }
  445. void CAudioDeviceSDLAudio::ApplyDSPEffects( int idsp, portable_samplepair_t *pbuffront, portable_samplepair_t *pbufrear, portable_samplepair_t *pbufcenter, int samplecount )
  446. {
  447. //SX_RoomFX( endtime, filter, timefx );
  448. DSP_Process( idsp, pbuffront, pbufrear, pbufcenter, samplecount );
  449. }
  450. #endif // !DEDICATED