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.

532 lines
15 KiB

  1. //===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose:
  4. //
  5. // $Workfile: $
  6. // $Date: $
  7. // $NoKeywords: $
  8. //===========================================================================//
  9. #include <stdio.h>
  10. #include "snd_dev_wave.h"
  11. #include "snd_wave_source.h"
  12. #include "soundsystem/snd_audio_source.h"
  13. #include "snd_wave_mixer_private.h"
  14. #include "snd_wave_mixer_adpcm.h"
  15. #include "tier2/riff.h"
  16. // NOTE: This has to be the last file included!
  17. #include "tier0/memdbgon.h"
  18. //-----------------------------------------------------------------------------
  19. // These mixers provide an abstraction layer between the audio device and
  20. // mixing/decoding code. They allow data to be decoded and mixed using
  21. // optimized, format sensitive code by calling back into the device that
  22. // controls them.
  23. //-----------------------------------------------------------------------------
  24. //-----------------------------------------------------------------------------
  25. // Purpose: maps mixing to 8-bit mono mixer
  26. //-----------------------------------------------------------------------------
  27. class CAudioMixerWave8Mono : public CAudioMixerWave
  28. {
  29. public:
  30. CAudioMixerWave8Mono( CWaveData *data ) : CAudioMixerWave( data ) {}
  31. virtual void Mix( IAudioDevice *pDevice, channel_t *pChannel, void *pData, int outputOffset, int inputOffset, fixedint fracRate, int outCount, int timecompress, bool forward = true )
  32. {
  33. pDevice->Mix8Mono( pChannel, (char *)pData, outputOffset, inputOffset, fracRate, outCount, timecompress, forward );
  34. }
  35. };
  36. //-----------------------------------------------------------------------------
  37. // Purpose: maps mixing to 8-bit stereo mixer
  38. //-----------------------------------------------------------------------------
  39. class CAudioMixerWave8Stereo : public CAudioMixerWave
  40. {
  41. public:
  42. CAudioMixerWave8Stereo( CWaveData *data ) : CAudioMixerWave( data ) {}
  43. virtual void Mix( IAudioDevice *pDevice, channel_t *pChannel, void *pData, int outputOffset, int inputOffset, fixedint fracRate, int outCount, int timecompress, bool forward = true )
  44. {
  45. pDevice->Mix8Stereo( pChannel, (char *)pData, outputOffset, inputOffset, fracRate, outCount, timecompress, forward );
  46. }
  47. };
  48. //-----------------------------------------------------------------------------
  49. // Purpose: maps mixing to 16-bit mono mixer
  50. //-----------------------------------------------------------------------------
  51. class CAudioMixerWave16Mono : public CAudioMixerWave
  52. {
  53. public:
  54. CAudioMixerWave16Mono( CWaveData *data ) : CAudioMixerWave( data ) {}
  55. virtual void Mix( IAudioDevice *pDevice, channel_t *pChannel, void *pData, int outputOffset, int inputOffset, fixedint fracRate, int outCount, int timecompress, bool forward = true )
  56. {
  57. pDevice->Mix16Mono( pChannel, (short *)pData, outputOffset, inputOffset, fracRate, outCount, timecompress, forward );
  58. }
  59. };
  60. //-----------------------------------------------------------------------------
  61. // Purpose: maps mixing to 16-bit stereo mixer
  62. //-----------------------------------------------------------------------------
  63. class CAudioMixerWave16Stereo : public CAudioMixerWave
  64. {
  65. public:
  66. CAudioMixerWave16Stereo( CWaveData *data ) : CAudioMixerWave( data ) {}
  67. virtual void Mix( IAudioDevice *pDevice, channel_t *pChannel, void *pData, int outputOffset, int inputOffset, fixedint fracRate, int outCount, int timecompress, bool forward = true )
  68. {
  69. pDevice->Mix16Stereo( pChannel, (short *)pData, outputOffset, inputOffset, fracRate, outCount, timecompress, forward );
  70. }
  71. };
  72. //-----------------------------------------------------------------------------
  73. // Purpose: Create an approprite mixer type given the data format
  74. // Input : *data - data access abstraction
  75. // format - pcm or adpcm (1 or 2 -- RIFF format)
  76. // channels - number of audio channels (1 = mono, 2 = stereo)
  77. // bits - bits per sample
  78. // Output : CAudioMixer * abstract mixer type that maps mixing to appropriate code
  79. //-----------------------------------------------------------------------------
  80. CAudioMixer *CreateWaveMixer( CWaveData *data, int format, int channels, int bits )
  81. {
  82. if ( format == WAVE_FORMAT_PCM )
  83. {
  84. if ( channels > 1 )
  85. {
  86. if ( bits == 8 )
  87. return new CAudioMixerWave8Stereo( data );
  88. else
  89. return new CAudioMixerWave16Stereo( data );
  90. }
  91. else
  92. {
  93. if ( bits == 8 )
  94. return new CAudioMixerWave8Mono( data );
  95. else
  96. return new CAudioMixerWave16Mono( data );
  97. }
  98. }
  99. else if ( format == WAVE_FORMAT_ADPCM )
  100. {
  101. return CreateADPCMMixer( data );
  102. }
  103. return NULL;
  104. }
  105. //-----------------------------------------------------------------------------
  106. // Purpose: Init the base WAVE mixer.
  107. // Input : *data - data access object
  108. //-----------------------------------------------------------------------------
  109. CAudioMixerWave::CAudioMixerWave( CWaveData *data ) : m_pData(data), m_pChannel(NULL)
  110. {
  111. m_loop = 0;
  112. m_sample = 0;
  113. m_absoluteSample = 0;
  114. m_scubSample = -1;
  115. m_fracOffset = 0;
  116. m_bActive = false;
  117. m_nModelIndex = -1;
  118. m_bForward = true;
  119. m_bAutoDelete = true;
  120. m_pChannel = new channel_t;
  121. m_pChannel->leftvol = 127;
  122. m_pChannel->rightvol = 127;
  123. m_pChannel->pitch = 1.0;
  124. }
  125. //-----------------------------------------------------------------------------
  126. // Purpose: Frees the data access object (we own it after construction)
  127. //-----------------------------------------------------------------------------
  128. CAudioMixerWave::~CAudioMixerWave( void )
  129. {
  130. delete m_pData;
  131. delete m_pChannel;
  132. }
  133. //-----------------------------------------------------------------------------
  134. // Purpose: Decode and read the data
  135. // by default we just pass the request on to the data access object
  136. // other mixers may need to buffer or decode the data for some reason
  137. //
  138. // Input : **pData - dest pointer
  139. // sampleCount - number of samples needed
  140. // Output : number of samples available in this batch
  141. //-----------------------------------------------------------------------------
  142. int CAudioMixerWave::GetOutputData( void **pData, int samplePosition, int sampleCount, bool forward /*= true*/ )
  143. {
  144. if ( samplePosition != m_sample )
  145. {
  146. // Seek
  147. m_sample = samplePosition;
  148. m_absoluteSample = samplePosition;
  149. }
  150. return m_pData->ReadSourceData( pData, m_sample, sampleCount, forward );
  151. }
  152. //-----------------------------------------------------------------------------
  153. // Purpose: calls through the wavedata to get the audio source
  154. // Output : CAudioSource
  155. //-----------------------------------------------------------------------------
  156. CAudioSource *CAudioMixerWave::GetSource( void )
  157. {
  158. if ( m_pData )
  159. return &m_pData->Source();
  160. return NULL;
  161. }
  162. //-----------------------------------------------------------------------------
  163. // Purpose: Gets the current sample location in playback
  164. // Output : int (samples from start of wave)
  165. //-----------------------------------------------------------------------------
  166. int CAudioMixerWave::GetSamplePosition( void )
  167. {
  168. return m_sample;
  169. }
  170. //-----------------------------------------------------------------------------
  171. // Purpose: Gets the current sample location in playback
  172. // Output : int (samples from start of wave)
  173. //-----------------------------------------------------------------------------
  174. int CAudioMixerWave::GetScubPosition( void )
  175. {
  176. if (m_scubSample != -1)
  177. {
  178. return m_scubSample;
  179. }
  180. return m_sample;
  181. }
  182. //-----------------------------------------------------------------------------
  183. // Purpose:
  184. // Input : position -
  185. //-----------------------------------------------------------------------------
  186. bool CAudioMixerWave::SetSamplePosition( int position, bool scrubbing )
  187. {
  188. position = MAX( 0, position );
  189. m_sample = position;
  190. m_absoluteSample = position;
  191. m_startpos = m_sample;
  192. if (scrubbing)
  193. {
  194. m_scubSample = position;
  195. }
  196. else
  197. {
  198. m_scubSample = -1;
  199. }
  200. return true;
  201. }
  202. //-----------------------------------------------------------------------------
  203. // Purpose:
  204. // Input : position -
  205. //-----------------------------------------------------------------------------
  206. void CAudioMixerWave::SetLoopPosition( int position )
  207. {
  208. m_loop = position;
  209. }
  210. //-----------------------------------------------------------------------------
  211. // Purpose:
  212. // Output : int
  213. //-----------------------------------------------------------------------------
  214. int CAudioMixerWave::GetStartPosition( void )
  215. {
  216. return m_startpos;
  217. }
  218. bool CAudioMixerWave::GetActive( void )
  219. {
  220. return m_bActive;
  221. }
  222. void CAudioMixerWave::SetActive( bool active )
  223. {
  224. m_bActive = active;
  225. }
  226. void CAudioMixerWave::SetModelIndex( int index )
  227. {
  228. m_nModelIndex = index;
  229. }
  230. int CAudioMixerWave::GetModelIndex( void ) const
  231. {
  232. return m_nModelIndex;
  233. }
  234. void CAudioMixerWave::SetDirection( bool forward )
  235. {
  236. m_bForward = forward;
  237. }
  238. bool CAudioMixerWave::GetDirection( void ) const
  239. {
  240. return m_bForward;
  241. }
  242. void CAudioMixerWave::SetAutoDelete( bool autodelete )
  243. {
  244. m_bAutoDelete = autodelete;
  245. }
  246. bool CAudioMixerWave::GetAutoDelete( void ) const
  247. {
  248. return m_bAutoDelete;
  249. }
  250. void CAudioMixerWave::SetVolume( float volume )
  251. {
  252. int ivolume = (int)( clamp( volume, 0.0f, 1.0f ) * 127.0f );
  253. m_pChannel->leftvol = ivolume;
  254. m_pChannel->rightvol = ivolume;
  255. }
  256. channel_t *CAudioMixerWave::GetChannel()
  257. {
  258. Assert( m_pChannel );
  259. return m_pChannel;
  260. }
  261. //-----------------------------------------------------------------------------
  262. // Purpose:
  263. // Input : *pChannel -
  264. // sampleCount -
  265. // outputRate -
  266. //-----------------------------------------------------------------------------
  267. void CAudioMixerWave::IncrementSamples( channel_t *pChannel, int startSample, int sampleCount,int outputRate, bool forward /*= true*/ )
  268. {
  269. int inputSampleRate = (int)(pChannel->pitch * m_pData->Source().SampleRate());
  270. float rate = (float)inputSampleRate / outputRate;
  271. int startpos = startSample;
  272. if ( !forward )
  273. {
  274. int requestedstart = startSample - (int)( sampleCount * rate );
  275. if ( requestedstart < 0 )
  276. return;
  277. startpos = MAX( 0, requestedstart );
  278. SetSamplePosition( startpos );
  279. }
  280. while ( sampleCount > 0 )
  281. {
  282. int inputSampleCount;
  283. int outputSampleCount = sampleCount;
  284. if ( outputRate != inputSampleRate )
  285. {
  286. inputSampleCount = (int)(sampleCount * rate);
  287. }
  288. else
  289. {
  290. inputSampleCount = sampleCount;
  291. }
  292. sampleCount -= outputSampleCount;
  293. if ( forward )
  294. {
  295. m_sample += inputSampleCount;
  296. m_absoluteSample += inputSampleCount;
  297. }
  298. }
  299. }
  300. //-----------------------------------------------------------------------------
  301. // Purpose: The device calls this to request data. The mixer must provide the
  302. // full amount of samples or have silence in its output stream.
  303. // Input : *pDevice - requesting device
  304. // sampleCount - number of samples at the output rate
  305. // outputRate - sampling rate of the request
  306. // Output : Returns true to keep mixing, false to delete this mixer
  307. //-----------------------------------------------------------------------------
  308. bool CAudioMixerWave::SkipSamples( IAudioDevice *pDevice, channel_t *pChannel,
  309. int startSample, int sampleCount, int outputRate, bool forward /*= true*/ )
  310. {
  311. int offset = 0;
  312. int inputSampleRate = (int)(pChannel->pitch * m_pData->Source().SampleRate());
  313. float rate = (float)inputSampleRate / outputRate;
  314. sampleCount = MIN( sampleCount, pDevice->PaintBufferSampleCount() );
  315. int startpos = startSample;
  316. if ( !forward )
  317. {
  318. int requestedstart = startSample - (int)( sampleCount * rate );
  319. if ( requestedstart < 0 )
  320. return false;
  321. startpos = MAX( 0, requestedstart );
  322. SetSamplePosition( startpos );
  323. }
  324. while ( sampleCount > 0 )
  325. {
  326. int availableSamples;
  327. int inputSampleCount;
  328. char *pData = NULL;
  329. int outputSampleCount = sampleCount;
  330. if ( outputRate != inputSampleRate )
  331. {
  332. inputSampleCount = (int)(sampleCount * rate);
  333. if ( !forward )
  334. {
  335. startSample = MAX( 0, startSample - inputSampleCount );
  336. }
  337. int availableSamples = GetOutputData( (void **)&pData, startSample, inputSampleCount, forward );
  338. if ( !availableSamples )
  339. break;
  340. if ( availableSamples < inputSampleCount )
  341. {
  342. outputSampleCount = (int)(availableSamples / rate);
  343. inputSampleCount = availableSamples;
  344. }
  345. // compute new fraction part of sample index
  346. float offset = (m_fracOffset / FIX_SCALE) + (rate * outputSampleCount);
  347. offset = offset - (float)((int)offset);
  348. m_fracOffset = FIX_FLOAT(offset);
  349. }
  350. else
  351. {
  352. if ( !forward )
  353. {
  354. startSample = MAX( 0, startSample - sampleCount );
  355. }
  356. availableSamples = GetOutputData( (void **)&pData, startSample, sampleCount, forward );
  357. if ( !availableSamples )
  358. break;
  359. outputSampleCount = availableSamples;
  360. inputSampleCount = availableSamples;
  361. }
  362. offset += outputSampleCount;
  363. sampleCount -= outputSampleCount;
  364. if ( forward )
  365. {
  366. m_sample += inputSampleCount;
  367. m_absoluteSample += inputSampleCount;
  368. }
  369. if ( m_loop != 0 && m_sample >= m_loop )
  370. {
  371. SetSamplePosition( m_startpos );
  372. }
  373. }
  374. if ( sampleCount > 0 )
  375. return false;
  376. return true;
  377. }
  378. //-----------------------------------------------------------------------------
  379. // Purpose: The device calls this to request data. The mixer must provide the
  380. // full amount of samples or have silence in its output stream.
  381. // Input : *pDevice - requesting device
  382. // sampleCount - number of samples at the output rate
  383. // outputRate - sampling rate of the request
  384. // Output : Returns true to keep mixing, false to delete this mixer
  385. //-----------------------------------------------------------------------------
  386. bool CAudioMixerWave::MixDataToDevice( IAudioDevice *pDevice, channel_t *pChannel, int startSample, int sampleCount, int outputRate, bool forward /*= true*/ )
  387. {
  388. int offset = 0;
  389. int inputSampleRate = (int)(pChannel->pitch * m_pData->Source().SampleRate());
  390. float rate = (float)inputSampleRate / outputRate;
  391. fixedint fracstep = FIX_FLOAT( rate );
  392. sampleCount = MIN( sampleCount, pDevice->PaintBufferSampleCount() );
  393. int startpos = startSample;
  394. if ( !forward )
  395. {
  396. int requestedstart = startSample - (int)( sampleCount * rate );
  397. if ( requestedstart < 0 )
  398. return false;
  399. startpos = MAX( 0, requestedstart );
  400. SetSamplePosition( startpos );
  401. }
  402. while ( sampleCount > 0 )
  403. {
  404. int availableSamples;
  405. int inputSampleCount;
  406. char *pData = NULL;
  407. int outputSampleCount = sampleCount;
  408. if ( outputRate != inputSampleRate )
  409. {
  410. inputSampleCount = (int)(sampleCount * rate);
  411. int availableSamples = GetOutputData( (void **)&pData, startpos, inputSampleCount, forward );
  412. if ( !availableSamples )
  413. break;
  414. if ( availableSamples < inputSampleCount )
  415. {
  416. outputSampleCount = (int)(availableSamples / rate);
  417. inputSampleCount = availableSamples;
  418. }
  419. Mix( pDevice, pChannel, pData, offset, m_fracOffset, fracstep, outputSampleCount, 0, forward );
  420. // compute new fraction part of sample index
  421. float offset = (m_fracOffset / FIX_SCALE) + (rate * outputSampleCount);
  422. offset = offset - (float)((int)offset);
  423. m_fracOffset = FIX_FLOAT(offset);
  424. }
  425. else
  426. {
  427. availableSamples = GetOutputData( (void **)&pData, startpos, sampleCount, forward );
  428. if ( !availableSamples )
  429. break;
  430. outputSampleCount = availableSamples;
  431. inputSampleCount = availableSamples;
  432. Mix( pDevice, pChannel, pData, offset, m_fracOffset, FIX(1), outputSampleCount, 0, forward );
  433. }
  434. offset += outputSampleCount;
  435. sampleCount -= outputSampleCount;
  436. if ( forward )
  437. {
  438. m_sample += inputSampleCount;
  439. m_absoluteSample += inputSampleCount;
  440. }
  441. if ( m_loop != 0 && m_sample >= m_loop )
  442. {
  443. SetSamplePosition( m_startpos );
  444. }
  445. }
  446. if ( sampleCount > 0 )
  447. return false;
  448. return true;
  449. }