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.

751 lines
22 KiB

  1. //===== Copyright 1996-2005, 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 "avi/ibik.h"
  10. // prevent some conflicts in SDL headers...
  11. #undef M_PI
  12. #include <stdint.h>
  13. #ifndef _STDINT_H_
  14. #define _STDINT_H_ 1
  15. #endif
  16. #include "SDL.h"
  17. // memdbgon must be the last include file in a .cpp file!!!
  18. #include "tier0/memdbgon.h"
  19. extern IVEngineClient* engineClient;
  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. ConVar snd_mute_losefocus("snd_mute_losefocus", "1", FCVAR_ARCHIVE);
  24. static ConVar sdl_speaker_channels( "sdl_speaker_channels", "-1", FCVAR_RELEASE|FCVAR_ARCHIVE );
  25. static void OnSDLSpeakerChannelsChanged( IConVar *pVar, const char *pOldString, float flOldValue )
  26. {
  27. if ( atoi( pOldString ) != sdl_speaker_channels.GetInt() )
  28. {
  29. g_pSoundServices->RestartSoundSystem();
  30. }
  31. }
  32. // 64K is about 1/3 second at 16-bit, stereo, 44100 Hz
  33. // 44k: UNDONE - need to double buffers now that we're playing back at 44100?
  34. #define WAV_BUFFERS 64
  35. #define WAV_MASK (WAV_BUFFERS - 1)
  36. #define WAV_BUFFER_SIZE 0x0400
  37. #if 0
  38. #define debugsdl printf
  39. #else
  40. static inline void debugsdl(const char *fmt, ...) {}
  41. #endif
  42. //-----------------------------------------------------------------------------
  43. //
  44. // NOTE: This only allows 16-bit, stereo wave out (!!! FIXME: but SDL supports 7.1, etc, too!)
  45. //
  46. //-----------------------------------------------------------------------------
  47. class CAudioDeviceSDLAudio : public CAudioDeviceBase
  48. {
  49. public:
  50. CAudioDeviceSDLAudio();
  51. virtual ~CAudioDeviceSDLAudio();
  52. bool IsActive( void );
  53. bool Init( void );
  54. void Shutdown( void );
  55. void PaintEnd( void );
  56. int GetOutputPosition( void );
  57. void ChannelReset( int entnum, int channelIndex, float distanceMod );
  58. void Pause( void );
  59. void UnPause( void );
  60. float MixDryVolume( void );
  61. bool Should3DMix( void );
  62. void StopAllSounds( void );
  63. int64 PaintBegin( float mixAheadTime, int64 soundtime, int64 paintedtime );
  64. void ClearBuffer( void );
  65. void MixBegin( int sampleCount );
  66. void MixUpsample( int sampleCount, int filtertype );
  67. void Mix8Mono( channel_t *pChannel, char *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress );
  68. void Mix8Stereo( channel_t *pChannel, char *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress );
  69. void Mix16Mono( channel_t *pChannel, short *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress );
  70. void Mix16Stereo( channel_t *pChannel, short *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress );
  71. void TransferSamples( int end );
  72. void SpatializeChannel( int nSlot, int volume[CCHANVOLUMES/2], int master_vol, const Vector& sourceDir, float gain, float mono);
  73. void ApplyDSPEffects( int idsp, portable_samplepair_t *pbuffront, portable_samplepair_t *pbufrear, portable_samplepair_t *pbufcenter, int samplecount );
  74. const char *DeviceName( void ) { return "SDL"; }
  75. int DeviceChannels( void ) { return m_numChannels; }
  76. int DeviceSampleBits( void ) { return 16; }
  77. int DeviceSampleBytes( void ) { return 2; }
  78. int DeviceDmaSpeed( void ) { return SOUND_DMA_SPEED; }
  79. int DeviceSampleCount( void ) { return m_deviceSampleCount; }
  80. private:
  81. SDL_AudioDeviceID m_devId;
  82. static void SDLCALL AudioCallbackEntry(void *userdata, Uint8 * stream, int len);
  83. void AudioCallback(Uint8 *stream, int len);
  84. void OpenWaveOut( void );
  85. void CloseWaveOut( void );
  86. void AllocateOutputBuffers();
  87. void FreeOutputBuffers();
  88. bool ValidWaveOut( void ) const;
  89. void TransferSurround16( void *pOutput, const portable_samplepair_t *pfront, const portable_samplepair_t *prear, const portable_samplepair_t *pcenter, int64 lpaintedtime, int64 endtime, int nChannels);
  90. int m_numChannels;
  91. int m_deviceSampleCount;
  92. int m_buffersSent;
  93. int m_pauseCount;
  94. int m_readPos;
  95. int m_partialWrite;
  96. // Memory for the wave data
  97. uint8_t *m_pBuffer;
  98. bool m_bSurround;
  99. bool m_bSurroundCenter;
  100. bool m_bHeadphone;
  101. };
  102. static CAudioDeviceSDLAudio *g_wave = NULL;
  103. //-----------------------------------------------------------------------------
  104. // Constructor (just lookup SDL entry points, real work happens in this->Init())
  105. //-----------------------------------------------------------------------------
  106. CAudioDeviceSDLAudio::CAudioDeviceSDLAudio()
  107. {
  108. m_devId = 0;
  109. m_numChannels = 2;
  110. }
  111. //-----------------------------------------------------------------------------
  112. // Destructor. Make sure our global pointer gets set to NULL.
  113. //-----------------------------------------------------------------------------
  114. CAudioDeviceSDLAudio::~CAudioDeviceSDLAudio()
  115. {
  116. g_wave = NULL;
  117. }
  118. //-----------------------------------------------------------------------------
  119. // Class factory
  120. //-----------------------------------------------------------------------------
  121. IAudioDevice *Audio_CreateSDLAudioDevice( void )
  122. {
  123. if ( !g_wave )
  124. {
  125. g_wave = new CAudioDeviceSDLAudio;
  126. Assert( g_wave );
  127. }
  128. if ( g_wave && !g_wave->Init() )
  129. {
  130. delete g_wave;
  131. g_wave = NULL;
  132. }
  133. return g_wave;
  134. }
  135. //-----------------------------------------------------------------------------
  136. // Init, shutdown
  137. //-----------------------------------------------------------------------------
  138. bool CAudioDeviceSDLAudio::Init( void )
  139. {
  140. // If we've already got a device open, then return. This allows folks to call
  141. // Audio_CreateSDLAudioDevice() multiple times. CloseWaveOut() will free the
  142. // device, and set m_devId to 0.
  143. if( m_devId )
  144. return true;
  145. m_bSurround = false;
  146. m_bSurroundCenter = false;
  147. m_bHeadphone = false;
  148. m_buffersSent = 0;
  149. m_pauseCount = 0;
  150. m_pBuffer = NULL;
  151. m_readPos = 0;
  152. m_partialWrite = 0;
  153. m_devId = 0;
  154. OpenWaveOut();
  155. if ( snd_firsttime )
  156. {
  157. DevMsg( "Wave sound initialized\n" );
  158. }
  159. return ValidWaveOut();
  160. }
  161. void CAudioDeviceSDLAudio::Shutdown( void )
  162. {
  163. CloseWaveOut();
  164. }
  165. //-----------------------------------------------------------------------------
  166. // WAV out device
  167. //-----------------------------------------------------------------------------
  168. inline bool CAudioDeviceSDLAudio::ValidWaveOut( void ) const
  169. {
  170. return m_devId != 0;
  171. }
  172. //-----------------------------------------------------------------------------
  173. // Opens the windows wave out device
  174. //-----------------------------------------------------------------------------
  175. void CAudioDeviceSDLAudio::OpenWaveOut( void )
  176. {
  177. debugsdl("SDLAUDIO: OpenWaveOut...\n");
  178. #ifndef WIN32
  179. // Set these environment variables, in case we're using PulseAudio.
  180. const char *appname = "Counter-Strike: Global Offensive"; // !!! FIXME: get this from elsewhere.
  181. setenv("PULSE_PROP_application.name", appname, 1);
  182. setenv("PULSE_PROP_media.role", "game", 1);
  183. #endif
  184. // !!! FIXME: specify channel map, etc
  185. // !!! FIXME: set properties (role, icon, etc).
  186. //#define SDLAUDIO_FAIL(fnstr) do { DevWarning(fnstr " failed"); CloseWaveOut(); return; } while (false)
  187. //#define SDLAUDIO_FAIL(fnstr) do { printf("SDLAUDIO: " fnstr " failed: %s\n", SDL_GetError ? SDL_GetError() : "???"); CloseWaveOut(); return; } while (false)
  188. #define SDLAUDIO_FAIL(fnstr) do { printf("SDLAUDIO: " fnstr " failed: %s\n", SDL_GetError() ); CloseWaveOut(); return; } while (false)
  189. if (!SDL_WasInit(SDL_INIT_AUDIO))
  190. {
  191. if (SDL_InitSubSystem(SDL_INIT_AUDIO))
  192. SDLAUDIO_FAIL("SDL_InitSubSystem(SDL_INIT_AUDIO)");
  193. }
  194. char target[128];
  195. debugsdl("SDLAUDIO: Using SDL audio target '%s'\n", SDL_GetCurrentAudioDriver());
  196. int nChannelsDesired = sdl_speaker_channels.GetInt();
  197. if ( nChannelsDesired == 1 )
  198. {
  199. //This really means 'headphones' which we want 2 channels for
  200. nChannelsDesired = 2;
  201. m_bHeadphone = true;
  202. }
  203. else if ( nChannelsDesired <= 0 )
  204. {
  205. nChannelsDesired = 6;
  206. }
  207. // Open an audio device...
  208. // !!! FIXME: let user specify a device?
  209. // !!! FIXME: we can handle quad, 5.1, 7.1, etc here.
  210. SDL_AudioSpec obtained;
  211. m_devId = 0;
  212. for ( m_devId = 0; m_devId == 0 && nChannelsDesired > 0; nChannelsDesired -= 2 )
  213. {
  214. SDL_AudioSpec desired;
  215. memset(&desired, '\0', sizeof (desired));
  216. desired.freq = SOUND_DMA_SPEED;
  217. desired.format = AUDIO_S16SYS;
  218. desired.samples = 2048;
  219. desired.channels = nChannelsDesired;
  220. desired.callback = &CAudioDeviceSDLAudio::AudioCallbackEntry;
  221. desired.userdata = this;
  222. m_devId = SDL_OpenAudioDevice(NULL, 0, &desired, &obtained, 0);
  223. }
  224. if (!m_devId)
  225. SDLAUDIO_FAIL("SDL_OpenAudioDevice()");
  226. m_bSurround = obtained.channels >= 4;
  227. m_bSurroundCenter = obtained.channels >= 6;
  228. m_numChannels = obtained.channels;
  229. if ( sdl_speaker_channels.GetInt() == 1 && m_numChannels == 2 )
  230. {
  231. //'headphones' setting.
  232. sdl_speaker_channels.SetValue( 1 );
  233. }
  234. else
  235. {
  236. sdl_speaker_channels.SetValue( m_numChannels );
  237. }
  238. #undef SDLAUDIO_FAIL
  239. // We're now ready to feed audio data to SDL!
  240. AllocateOutputBuffers();
  241. SDL_PauseAudioDevice(m_devId, 0);
  242. #if defined( BINK_VIDEO ) && defined( LINUX )
  243. // Tells Bink to use SDL for its audio decoding
  244. if ( g_pBIK && g_pBIK->SetSDLDevice( obtained.freq, obtained.format, obtained.channels ) == 0 )
  245. {
  246. Assert( 0 );
  247. }
  248. #endif
  249. static bool first_time = true;
  250. if ( first_time )
  251. {
  252. first_time = false;
  253. sdl_speaker_channels.InstallChangeCallback( &OnSDLSpeakerChannelsChanged );
  254. }
  255. }
  256. //-----------------------------------------------------------------------------
  257. // Closes the windows wave out device
  258. //-----------------------------------------------------------------------------
  259. void CAudioDeviceSDLAudio::CloseWaveOut( void )
  260. {
  261. // none of these SDL_* functions are available to call if this is false.
  262. if (m_devId)
  263. {
  264. SDL_CloseAudioDevice(m_devId);
  265. m_devId = 0;
  266. }
  267. SDL_QuitSubSystem(SDL_INIT_AUDIO);
  268. FreeOutputBuffers();
  269. }
  270. //-----------------------------------------------------------------------------
  271. // Allocate output buffers
  272. //-----------------------------------------------------------------------------
  273. void CAudioDeviceSDLAudio::AllocateOutputBuffers()
  274. {
  275. // Allocate and lock memory for the waveform data.
  276. const int nBufferSize = (WAV_BUFFER_SIZE * WAV_BUFFERS * DeviceChannels())/2;
  277. m_pBuffer = new uint8_t[nBufferSize];
  278. memset(m_pBuffer, '\0', nBufferSize);
  279. m_readPos = 0;
  280. m_partialWrite = 0;
  281. m_deviceSampleCount = nBufferSize / DeviceSampleBytes();
  282. }
  283. //-----------------------------------------------------------------------------
  284. // Free output buffers
  285. //-----------------------------------------------------------------------------
  286. void CAudioDeviceSDLAudio::FreeOutputBuffers()
  287. {
  288. delete[] m_pBuffer;
  289. m_pBuffer = NULL;
  290. }
  291. //-----------------------------------------------------------------------------
  292. // Mixing setup
  293. //-----------------------------------------------------------------------------
  294. int64 CAudioDeviceSDLAudio::PaintBegin( float mixAheadTime, int64 soundtime, int64 paintedtime )
  295. {
  296. // soundtime - total samples that have been played out to hardware at dmaspeed
  297. // paintedtime - total samples that have been mixed at speed
  298. // endtime - target for samples in mixahead buffer at speed
  299. unsigned int endtime = soundtime + mixAheadTime * DeviceDmaSpeed();
  300. int samps = DeviceSampleCount() / DeviceChannels();
  301. if ((int)(endtime - soundtime) > samps)
  302. endtime = soundtime + samps;
  303. if ((endtime - paintedtime) & 0x3)
  304. {
  305. // The difference between endtime and painted time should align on
  306. // boundaries of 4 samples. This is important when upsampling from 11khz -> 44khz.
  307. endtime -= (endtime - paintedtime) & 0x3;
  308. }
  309. return endtime;
  310. }
  311. void CAudioDeviceSDLAudio::AudioCallbackEntry(void *userdata, Uint8 *stream, int len)
  312. {
  313. ((CAudioDeviceSDLAudio *) userdata)->AudioCallback(stream, len);
  314. }
  315. void CAudioDeviceSDLAudio::AudioCallback(Uint8 *stream, int len)
  316. {
  317. if (!m_devId)
  318. {
  319. debugsdl("SDLAUDIO: uhoh, no audio device!\n");
  320. return; // can this even happen?
  321. }
  322. const int totalWriteable = len;
  323. Uint8 *stream_orig = stream;
  324. debugsdl("SDLAUDIO: writable size is %d.\n", totalWriteable);
  325. Assert(len <= (WAV_BUFFERS * WAV_BUFFER_SIZE));
  326. while (len > 0)
  327. {
  328. // spaceAvailable == bytes before we overrun the end of the ring buffer.
  329. const int spaceAvailable = ((WAV_BUFFERS * WAV_BUFFER_SIZE * DeviceChannels())/2 - m_readPos);
  330. const int writeLen = (len < spaceAvailable) ? len : spaceAvailable;
  331. if (writeLen > 0)
  332. {
  333. const uint8_t *buf = m_pBuffer + m_readPos;
  334. debugsdl("SDLAUDIO: Writing %d bytes...\n", writeLen);
  335. #if 0
  336. static FILE *io = NULL;
  337. if (io == NULL) io = fopen("dumpplayback.raw", "wb");
  338. if (io != NULL) { fwrite(buf, writeLen, 1, io); fflush(io); }
  339. #endif
  340. if ( engineClient->IsActiveApp() == false && snd_mute_losefocus.GetBool() )
  341. {
  342. // The game is in the background and we are set to mute
  343. // while in background so just play silence.
  344. memset(stream, 0, writeLen);
  345. }
  346. else
  347. {
  348. memcpy(stream, buf, writeLen);
  349. }
  350. stream += writeLen;
  351. len -= writeLen;
  352. Assert(len >= 0);
  353. }
  354. m_readPos = (m_readPos + writeLen) % ((WAV_BUFFERS * WAV_BUFFER_SIZE * DeviceChannels())/2); // if still bytes to write to stream, we're rolling around the ring buffer.
  355. }
  356. #if defined( BINK_VIDEO ) && defined( LINUX )
  357. // Mix in Bink movie audio if that stuff is playing.
  358. g_pBIK->SDLMixerAudioCallback( stream_orig, totalWriteable );
  359. #endif
  360. // Translate between bytes written and buffers written.
  361. m_partialWrite += totalWriteable;
  362. m_buffersSent += m_partialWrite / WAV_BUFFER_SIZE;
  363. m_partialWrite %= WAV_BUFFER_SIZE;
  364. }
  365. //-----------------------------------------------------------------------------
  366. // Actually performs the mixing
  367. //-----------------------------------------------------------------------------
  368. void CAudioDeviceSDLAudio::PaintEnd( void )
  369. {
  370. debugsdl("SDLAUDIO: PaintEnd...\n");
  371. #if 0 // !!! FIXME: this is the 1.3 headers, but not implemented yet in SDL.
  372. if (SDL_AudioDeviceConnected(m_devId) != 1)
  373. {
  374. debugsdl("SDLAUDIO: Audio device was disconnected!\n");
  375. Shutdown();
  376. }
  377. #endif
  378. }
  379. int CAudioDeviceSDLAudio::GetOutputPosition( void )
  380. {
  381. return (m_readPos >> SAMPLE_16BIT_SHIFT)/DeviceChannels();
  382. }
  383. //-----------------------------------------------------------------------------
  384. // Pausing
  385. //-----------------------------------------------------------------------------
  386. void CAudioDeviceSDLAudio::Pause( void )
  387. {
  388. m_pauseCount++;
  389. if (m_pauseCount == 1)
  390. {
  391. debugsdl("SDLAUDIO: PAUSE\n");
  392. SDL_PauseAudioDevice(m_devId, 1);
  393. }
  394. }
  395. void CAudioDeviceSDLAudio::UnPause( void )
  396. {
  397. if ( m_pauseCount > 0 )
  398. {
  399. m_pauseCount--;
  400. if (m_pauseCount == 0)
  401. {
  402. debugsdl("SDLAUDIO: UNPAUSE\n");
  403. SDL_PauseAudioDevice(m_devId, 0);
  404. }
  405. }
  406. }
  407. bool CAudioDeviceSDLAudio::IsActive( void )
  408. {
  409. return ( m_pauseCount == 0 );
  410. }
  411. float CAudioDeviceSDLAudio::MixDryVolume( void )
  412. {
  413. return 0;
  414. }
  415. bool CAudioDeviceSDLAudio::Should3DMix( void )
  416. {
  417. return false;
  418. }
  419. void CAudioDeviceSDLAudio::ClearBuffer( void )
  420. {
  421. int clear;
  422. if ( !m_pBuffer )
  423. return;
  424. clear = 0;
  425. Q_memset(m_pBuffer, clear, DeviceSampleCount() * DeviceSampleBytes() );
  426. }
  427. void CAudioDeviceSDLAudio::MixBegin( int sampleCount )
  428. {
  429. MIX_ClearAllPaintBuffers( sampleCount, false );
  430. }
  431. void CAudioDeviceSDLAudio::MixUpsample( int sampleCount, int filtertype )
  432. {
  433. paintbuffer_t *ppaint = MIX_GetCurrentPaintbufferPtr();
  434. int ifilter = ppaint->ifilter;
  435. Assert (ifilter < CPAINTFILTERS);
  436. S_MixBufferUpsample2x( sampleCount, ppaint->pbuf, &(ppaint->fltmem[ifilter][0]), CPAINTFILTERMEM, filtertype );
  437. if ( ppaint->fsurround )
  438. {
  439. Assert( ppaint->pbufrear );
  440. S_MixBufferUpsample2x( sampleCount, ppaint->pbufrear, &(ppaint->fltmemrear[ifilter][0]), CPAINTFILTERMEM, filtertype );
  441. if ( ppaint->fsurround_center )
  442. {
  443. Assert( ppaint->pbufcenter );
  444. S_MixBufferUpsample2x( sampleCount, ppaint->pbufcenter, &(ppaint->fltmemcenter[ifilter][0]), CPAINTFILTERMEM, filtertype );
  445. }
  446. }
  447. ppaint->ifilter++;
  448. }
  449. void CAudioDeviceSDLAudio::Mix8Mono( channel_t *pChannel, char *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress )
  450. {
  451. int volume[CCHANVOLUMES];
  452. paintbuffer_t *ppaint = MIX_GetCurrentPaintbufferPtr();
  453. if (!MIX_ScaleChannelVolume( ppaint, pChannel, volume, 1))
  454. return;
  455. Mix8MonoWavtype( pChannel, ppaint->pbuf + outputOffset, volume, (byte *)pData, inputOffset, rateScaleFix, outCount );
  456. if ( ppaint->fsurround )
  457. {
  458. Assert( ppaint->pbufrear );
  459. Mix8MonoWavtype( pChannel, ppaint->pbufrear + outputOffset, &volume[IREAR_LEFT], (byte *)pData, inputOffset, rateScaleFix, outCount );
  460. if ( ppaint->fsurround_center )
  461. {
  462. Assert( ppaint->pbufcenter );
  463. Mix8MonoWavtype( pChannel, ppaint->pbufcenter + outputOffset, &volume[IFRONT_CENTER], (byte *)pData, inputOffset, rateScaleFix, outCount );
  464. }
  465. }
  466. }
  467. void CAudioDeviceSDLAudio::Mix8Stereo( channel_t *pChannel, char *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress )
  468. {
  469. int volume[CCHANVOLUMES];
  470. paintbuffer_t *ppaint = MIX_GetCurrentPaintbufferPtr();
  471. if (!MIX_ScaleChannelVolume( ppaint, pChannel, volume, 2 ))
  472. return;
  473. Mix8StereoWavtype( pChannel, ppaint->pbuf + outputOffset, volume, (byte *)pData, inputOffset, rateScaleFix, outCount );
  474. if ( ppaint->fsurround )
  475. {
  476. Assert( ppaint->pbufrear );
  477. Mix8StereoWavtype( pChannel, ppaint->pbufrear + outputOffset, &volume[IREAR_LEFT], (byte *)pData, inputOffset, rateScaleFix, outCount );
  478. if ( ppaint->fsurround_center )
  479. {
  480. Assert( ppaint->pbufcenter );
  481. Mix8StereoWavtype( pChannel, ppaint->pbufcenter + outputOffset, &volume[IFRONT_CENTER], (byte *)pData, inputOffset, rateScaleFix, outCount );
  482. }
  483. }
  484. }
  485. void CAudioDeviceSDLAudio::Mix16Mono( channel_t *pChannel, short *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress )
  486. {
  487. int volume[CCHANVOLUMES];
  488. paintbuffer_t *ppaint = MIX_GetCurrentPaintbufferPtr();
  489. if (!MIX_ScaleChannelVolume( ppaint, pChannel, volume, 1 ))
  490. return;
  491. Mix16MonoWavtype( pChannel, ppaint->pbuf + outputOffset, volume, pData, inputOffset, rateScaleFix, outCount );
  492. if ( ppaint->fsurround )
  493. {
  494. Assert( ppaint->pbufrear );
  495. Mix16MonoWavtype( pChannel, ppaint->pbufrear + outputOffset, &volume[IREAR_LEFT], pData, inputOffset, rateScaleFix, outCount );
  496. if ( ppaint->fsurround_center )
  497. {
  498. Assert( ppaint->pbufcenter );
  499. Mix16MonoWavtype( pChannel, ppaint->pbufcenter + outputOffset, &volume[IFRONT_CENTER], pData, inputOffset, rateScaleFix, outCount );
  500. }
  501. }
  502. }
  503. void CAudioDeviceSDLAudio::Mix16Stereo( channel_t *pChannel, short *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress )
  504. {
  505. int volume[CCHANVOLUMES];
  506. paintbuffer_t *ppaint = MIX_GetCurrentPaintbufferPtr();
  507. if (!MIX_ScaleChannelVolume( ppaint, pChannel, volume, 2 ))
  508. return;
  509. Mix16StereoWavtype( pChannel, ppaint->pbuf + outputOffset, volume, pData, inputOffset, rateScaleFix, outCount );
  510. if ( ppaint->fsurround )
  511. {
  512. Assert( ppaint->pbufrear );
  513. Mix16StereoWavtype( pChannel, ppaint->pbufrear + outputOffset, &volume[IREAR_LEFT], pData, inputOffset, rateScaleFix, outCount );
  514. if ( ppaint->fsurround_center )
  515. {
  516. Assert( ppaint->pbufcenter );
  517. Mix16StereoWavtype( pChannel, ppaint->pbufcenter + outputOffset, &volume[IFRONT_CENTER], pData, inputOffset, rateScaleFix, outCount );
  518. }
  519. }
  520. }
  521. void CAudioDeviceSDLAudio::ChannelReset( int entnum, int channelIndex, float distanceMod )
  522. {
  523. }
  524. void CAudioDeviceSDLAudio::TransferSamples( int end )
  525. {
  526. int lpaintedtime = g_paintedtime;
  527. int endtime = end;
  528. // resumes playback...
  529. if ( m_pBuffer )
  530. {
  531. if ( m_bSurround )
  532. {
  533. TransferSurround16( m_pBuffer, PAINTBUFFER, REARPAINTBUFFER, CENTERPAINTBUFFER, lpaintedtime, endtime, DeviceChannels() );
  534. }
  535. else
  536. {
  537. S_TransferStereo16( m_pBuffer, PAINTBUFFER, lpaintedtime, endtime );
  538. }
  539. }
  540. }
  541. void CAudioDeviceSDLAudio::SpatializeChannel( int nSlot, int volume[CCHANVOLUMES/2], int master_vol, const Vector& sourceDir, float gain, float mono )
  542. {
  543. VPROF("CAudioDeviceSDLAudio::SpatializeChannel");
  544. S_SpatializeChannel( nSlot, volume, master_vol, &sourceDir, gain, mono );
  545. }
  546. void CAudioDeviceSDLAudio::StopAllSounds( void )
  547. {
  548. }
  549. void CAudioDeviceSDLAudio::ApplyDSPEffects( int idsp, portable_samplepair_t *pbuffront, portable_samplepair_t *pbufrear, portable_samplepair_t *pbufcenter, int samplecount )
  550. {
  551. //SX_RoomFX( endtime, filter, timefx );
  552. DSP_Process( idsp, pbuffront, pbufrear, pbufcenter, samplecount );
  553. }
  554. void CAudioDeviceSDLAudio::TransferSurround16( void *pOutput, const portable_samplepair_t *pfront, const portable_samplepair_t *prear, const portable_samplepair_t *pcenter, int64 lpaintedtime, int64 endtime, int nChannels)
  555. {
  556. const int volume = S_GetMasterVolume()*256;
  557. const int* snd_front = (const int*)pfront;
  558. const int* snd_rear = (const int*)prear;
  559. const int* snd_center = (const int*)pcenter;
  560. const int numSamples = (WAV_BUFFER_SIZE * WAV_BUFFERS)/4;
  561. while(lpaintedtime < endtime)
  562. {
  563. const int lpos = lpaintedtime % numSamples;
  564. int64 snd_linear_count = numSamples - lpos;
  565. if ( snd_linear_count > endtime - lpaintedtime )
  566. {
  567. snd_linear_count = endtime - lpaintedtime;
  568. }
  569. short *snd_out = (short *)pOutput + lpos*nChannels;
  570. for ( int i = 0; i < snd_linear_count; ++i )
  571. {
  572. const short* base = snd_out;
  573. *snd_out++ = (snd_front[i*2] * volume) >> 8;
  574. *snd_out++ = (snd_front[i*2+1] * volume) >> 8;
  575. if ( nChannels >= 6 )
  576. {
  577. *snd_out++ = (snd_center[i*2] * volume) >> 8;
  578. *snd_out++ = 0;
  579. }
  580. if ( nChannels >= 4 )
  581. {
  582. *snd_out++ = (snd_rear[i*2] * volume) >> 8;
  583. *snd_out++ = (snd_rear[i*2+1] * volume) >> 8;
  584. }
  585. while ( snd_out - base < nChannels )
  586. {
  587. *snd_out++ = 0;
  588. }
  589. }
  590. lpaintedtime += snd_linear_count;
  591. snd_front += snd_linear_count*2;
  592. snd_rear += snd_linear_count*2;
  593. snd_center += snd_linear_count*2;
  594. }
  595. }
  596. #endif // !DEDICATED