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.

492 lines
14 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include <stdio.h>
  8. #include <windows.h>
  9. #include "snd_audio_source.h"
  10. #include "snd_wave_source.h"
  11. #include "snd_wave_mixer_private.h"
  12. #include "snd_wave_mixer_adpcm.h"
  13. #include "iscenemanagersound.h"
  14. #include "AudioWaveOutput.h"
  15. #include "tier2/riff.h"
  16. typedef struct channel_s
  17. {
  18. int leftvol;
  19. int rightvol;
  20. int rleftvol;
  21. int rrightvol;
  22. float pitch;
  23. } channel_t;
  24. //-----------------------------------------------------------------------------
  25. // These mixers provide an abstraction layer between the audio device and
  26. // mixing/decoding code. They allow data to be decoded and mixed using
  27. // optimized, format sensitive code by calling back into the device that
  28. // controls them.
  29. //-----------------------------------------------------------------------------
  30. //-----------------------------------------------------------------------------
  31. // Purpose: maps mixing to 8-bit mono mixer
  32. //-----------------------------------------------------------------------------
  33. class CAudioMixerWave8Mono : public CAudioMixerWave
  34. {
  35. public:
  36. CAudioMixerWave8Mono( CWaveData *data ) : CAudioMixerWave( data ) {}
  37. virtual void Mix( IAudioDevice *pDevice, channel_t *pChannel, void *pData, int outputOffset, int inputOffset, fixedint fracRate, int outCount, int timecompress, bool forward = true )
  38. {
  39. pDevice->Mix8Mono( pChannel, (char *)pData, outputOffset, inputOffset, fracRate, outCount, timecompress, forward );
  40. }
  41. };
  42. //-----------------------------------------------------------------------------
  43. // Purpose: maps mixing to 8-bit stereo mixer
  44. //-----------------------------------------------------------------------------
  45. class CAudioMixerWave8Stereo : public CAudioMixerWave
  46. {
  47. public:
  48. CAudioMixerWave8Stereo( CWaveData *data ) : CAudioMixerWave( data ) {}
  49. virtual void Mix( IAudioDevice *pDevice, channel_t *pChannel, void *pData, int outputOffset, int inputOffset, fixedint fracRate, int outCount, int timecompress, bool forward = true )
  50. {
  51. pDevice->Mix8Stereo( pChannel, (char *)pData, outputOffset, inputOffset, fracRate, outCount, timecompress, forward );
  52. }
  53. };
  54. //-----------------------------------------------------------------------------
  55. // Purpose: maps mixing to 16-bit mono mixer
  56. //-----------------------------------------------------------------------------
  57. class CAudioMixerWave16Mono : public CAudioMixerWave
  58. {
  59. public:
  60. CAudioMixerWave16Mono( CWaveData *data ) : CAudioMixerWave( data ) {}
  61. virtual void Mix( IAudioDevice *pDevice, channel_t *pChannel, void *pData, int outputOffset, int inputOffset, fixedint fracRate, int outCount, int timecompress, bool forward = true )
  62. {
  63. pDevice->Mix16Mono( pChannel, (short *)pData, outputOffset, inputOffset, fracRate, outCount, timecompress, forward );
  64. }
  65. };
  66. //-----------------------------------------------------------------------------
  67. // Purpose: maps mixing to 16-bit stereo mixer
  68. //-----------------------------------------------------------------------------
  69. class CAudioMixerWave16Stereo : public CAudioMixerWave
  70. {
  71. public:
  72. CAudioMixerWave16Stereo( CWaveData *data ) : CAudioMixerWave( data ) {}
  73. virtual void Mix( IAudioDevice *pDevice, channel_t *pChannel, void *pData, int outputOffset, int inputOffset, fixedint fracRate, int outCount, int timecompress, bool forward = true )
  74. {
  75. pDevice->Mix16Stereo( pChannel, (short *)pData, outputOffset, inputOffset, fracRate, outCount, timecompress, forward );
  76. }
  77. };
  78. //-----------------------------------------------------------------------------
  79. // Purpose: Create an approprite mixer type given the data format
  80. // Input : *data - data access abstraction
  81. // format - pcm or adpcm (1 or 2 -- RIFF format)
  82. // channels - number of audio channels (1 = mono, 2 = stereo)
  83. // bits - bits per sample
  84. // Output : CAudioMixer * abstract mixer type that maps mixing to appropriate code
  85. //-----------------------------------------------------------------------------
  86. CAudioMixer *CreateWaveMixer( CWaveData *data, int format, int channels, int bits )
  87. {
  88. if ( format == WAVE_FORMAT_PCM )
  89. {
  90. if ( channels > 1 )
  91. {
  92. if ( bits == 8 )
  93. return new CAudioMixerWave8Stereo( data );
  94. else
  95. return new CAudioMixerWave16Stereo( data );
  96. }
  97. else
  98. {
  99. if ( bits == 8 )
  100. return new CAudioMixerWave8Mono( data );
  101. else
  102. return new CAudioMixerWave16Mono( data );
  103. }
  104. }
  105. else if ( format == WAVE_FORMAT_ADPCM )
  106. {
  107. return CreateADPCMMixer( data );
  108. }
  109. return NULL;
  110. }
  111. //-----------------------------------------------------------------------------
  112. // Purpose: Init the base WAVE mixer.
  113. // Input : *data - data access object
  114. //-----------------------------------------------------------------------------
  115. CAudioMixerWave::CAudioMixerWave( CWaveData *data ) : m_pData(data)
  116. {
  117. m_loop = 0;
  118. m_sample = 0;
  119. m_absoluteSample = 0;
  120. m_fracOffset = 0;
  121. m_bActive = false;
  122. m_nModelIndex = -1;
  123. m_bForward = true;
  124. m_bAutoDelete = true;
  125. }
  126. //-----------------------------------------------------------------------------
  127. // Purpose: Frees the data access object (we own it after construction)
  128. //-----------------------------------------------------------------------------
  129. CAudioMixerWave::~CAudioMixerWave( void )
  130. {
  131. delete m_pData;
  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:
  172. // Input : position -
  173. //-----------------------------------------------------------------------------
  174. bool CAudioMixerWave::SetSamplePosition( int position )
  175. {
  176. position = max( 0, position );
  177. m_sample = position;
  178. m_absoluteSample = position;
  179. m_startpos = m_sample;
  180. return true;
  181. }
  182. //-----------------------------------------------------------------------------
  183. // Purpose:
  184. // Input : position -
  185. //-----------------------------------------------------------------------------
  186. void CAudioMixerWave::SetLoopPosition( int position )
  187. {
  188. m_loop = position;
  189. }
  190. //-----------------------------------------------------------------------------
  191. // Purpose:
  192. // Output : int
  193. //-----------------------------------------------------------------------------
  194. int CAudioMixerWave::GetStartPosition( void )
  195. {
  196. return m_startpos;
  197. }
  198. bool CAudioMixerWave::GetActive( void )
  199. {
  200. return m_bActive;
  201. }
  202. void CAudioMixerWave::SetActive( bool active )
  203. {
  204. m_bActive = active;
  205. }
  206. void CAudioMixerWave::SetModelIndex( int index )
  207. {
  208. m_nModelIndex = index;
  209. }
  210. int CAudioMixerWave::GetModelIndex( void ) const
  211. {
  212. return m_nModelIndex;
  213. }
  214. void CAudioMixerWave::SetDirection( bool forward )
  215. {
  216. m_bForward = forward;
  217. }
  218. bool CAudioMixerWave::GetDirection( void ) const
  219. {
  220. return m_bForward;
  221. }
  222. void CAudioMixerWave::SetAutoDelete( bool autodelete )
  223. {
  224. m_bAutoDelete = autodelete;
  225. }
  226. bool CAudioMixerWave::GetAutoDelete( void ) const
  227. {
  228. return m_bAutoDelete;
  229. }
  230. //-----------------------------------------------------------------------------
  231. // Purpose:
  232. // Input : *pChannel -
  233. // sampleCount -
  234. // outputRate -
  235. //-----------------------------------------------------------------------------
  236. void CAudioMixerWave::IncrementSamples( channel_t *pChannel, int startSample, int sampleCount,int outputRate, bool forward /*= true*/ )
  237. {
  238. int inputSampleRate = (int)(pChannel->pitch * m_pData->Source().SampleRate());
  239. float rate = (float)inputSampleRate / outputRate;
  240. int startpos = startSample;
  241. if ( !forward )
  242. {
  243. int requestedstart = startSample - (int)( sampleCount * rate );
  244. if ( requestedstart < 0 )
  245. return;
  246. startpos = max( 0, requestedstart );
  247. SetSamplePosition( startpos );
  248. }
  249. while ( sampleCount > 0 )
  250. {
  251. int inputSampleCount;
  252. int outputSampleCount = sampleCount;
  253. if ( outputRate != inputSampleRate )
  254. {
  255. inputSampleCount = (int)(sampleCount * rate);
  256. }
  257. else
  258. {
  259. inputSampleCount = sampleCount;
  260. }
  261. sampleCount -= outputSampleCount;
  262. if ( forward )
  263. {
  264. m_sample += inputSampleCount;
  265. m_absoluteSample += inputSampleCount;
  266. }
  267. }
  268. }
  269. //-----------------------------------------------------------------------------
  270. // Purpose: The device calls this to request data. The mixer must provide the
  271. // full amount of samples or have silence in its output stream.
  272. // Input : *pDevice - requesting device
  273. // sampleCount - number of samples at the output rate
  274. // outputRate - sampling rate of the request
  275. // Output : Returns true to keep mixing, false to delete this mixer
  276. //-----------------------------------------------------------------------------
  277. bool CAudioMixerWave::SkipSamples( channel_t *pChannel, int startSample, int sampleCount, int outputRate, bool forward /*= true*/ )
  278. {
  279. int offset = 0;
  280. int inputSampleRate = (int)(pChannel->pitch * m_pData->Source().SampleRate());
  281. float rate = (float)inputSampleRate / outputRate;
  282. // fixedint fracstep = FIX_FLOAT( rate );
  283. sampleCount = min( sampleCount, PAINTBUFFER_SIZE );
  284. int startpos = startSample;
  285. if ( !forward )
  286. {
  287. int requestedstart = startSample - (int)( sampleCount * rate );
  288. if ( requestedstart < 0 )
  289. return false;
  290. startpos = max( 0, requestedstart );
  291. SetSamplePosition( startpos );
  292. }
  293. while ( sampleCount > 0 )
  294. {
  295. int availableSamples;
  296. int inputSampleCount;
  297. char *pData = NULL;
  298. int outputSampleCount = sampleCount;
  299. if ( outputRate != inputSampleRate )
  300. {
  301. inputSampleCount = (int)(sampleCount * rate);
  302. if ( !forward )
  303. {
  304. startSample = max( 0, startSample - inputSampleCount );
  305. }
  306. int availableSamples = GetOutputData( (void **)&pData, startSample, inputSampleCount, forward );
  307. if ( !availableSamples )
  308. break;
  309. if ( availableSamples < inputSampleCount )
  310. {
  311. outputSampleCount = (int)(availableSamples / rate);
  312. inputSampleCount = availableSamples;
  313. }
  314. // compute new fraction part of sample index
  315. float offset = (m_fracOffset / FIX_SCALE) + (rate * outputSampleCount);
  316. offset = offset - (float)((int)offset);
  317. m_fracOffset = FIX_FLOAT(offset);
  318. }
  319. else
  320. {
  321. if ( !forward )
  322. {
  323. startSample = max( 0, startSample - sampleCount );
  324. }
  325. availableSamples = GetOutputData( (void **)&pData, startSample, sampleCount, forward );
  326. if ( !availableSamples )
  327. break;
  328. outputSampleCount = availableSamples;
  329. inputSampleCount = availableSamples;
  330. }
  331. offset += outputSampleCount;
  332. sampleCount -= outputSampleCount;
  333. if ( forward )
  334. {
  335. m_sample += inputSampleCount;
  336. m_absoluteSample += inputSampleCount;
  337. }
  338. if ( m_loop != 0 && m_sample >= m_loop )
  339. {
  340. SetSamplePosition( m_startpos );
  341. }
  342. }
  343. if ( sampleCount > 0 )
  344. return false;
  345. return true;
  346. }
  347. //-----------------------------------------------------------------------------
  348. // Purpose: The device calls this to request data. The mixer must provide the
  349. // full amount of samples or have silence in its output stream.
  350. // Input : *pDevice - requesting device
  351. // sampleCount - number of samples at the output rate
  352. // outputRate - sampling rate of the request
  353. // Output : Returns true to keep mixing, false to delete this mixer
  354. //-----------------------------------------------------------------------------
  355. bool CAudioMixerWave::MixDataToDevice( IAudioDevice *pDevice, channel_t *pChannel, int startSample, int sampleCount, int outputRate, bool forward /*= true*/ )
  356. {
  357. int offset = 0;
  358. int inputSampleRate = (int)(pChannel->pitch * m_pData->Source().SampleRate());
  359. float rate = (float)inputSampleRate / outputRate;
  360. fixedint fracstep = FIX_FLOAT( rate );
  361. sampleCount = min( sampleCount, PAINTBUFFER_SIZE );
  362. int startpos = startSample;
  363. if ( !forward )
  364. {
  365. int requestedstart = startSample - (int)( sampleCount * rate );
  366. if ( requestedstart < 0 )
  367. return false;
  368. startpos = max( 0, requestedstart );
  369. SetSamplePosition( startpos );
  370. }
  371. while ( sampleCount > 0 )
  372. {
  373. int availableSamples;
  374. int inputSampleCount;
  375. char *pData = NULL;
  376. int outputSampleCount = sampleCount;
  377. if ( outputRate != inputSampleRate )
  378. {
  379. inputSampleCount = (int)(sampleCount * rate);
  380. int availableSamples = GetOutputData( (void **)&pData, startpos, inputSampleCount, forward );
  381. if ( !availableSamples )
  382. break;
  383. if ( availableSamples < inputSampleCount )
  384. {
  385. outputSampleCount = (int)(availableSamples / rate);
  386. inputSampleCount = availableSamples;
  387. }
  388. Mix( pDevice, pChannel, pData, offset, m_fracOffset, fracstep, outputSampleCount, 0, forward );
  389. // compute new fraction part of sample index
  390. float offset = (m_fracOffset / FIX_SCALE) + (rate * outputSampleCount);
  391. offset = offset - (float)((int)offset);
  392. m_fracOffset = FIX_FLOAT(offset);
  393. }
  394. else
  395. {
  396. availableSamples = GetOutputData( (void **)&pData, startpos, sampleCount, forward );
  397. if ( !availableSamples )
  398. break;
  399. outputSampleCount = availableSamples;
  400. inputSampleCount = availableSamples;
  401. Mix( pDevice, pChannel, pData, offset, m_fracOffset, FIX(1), outputSampleCount, 0, forward );
  402. }
  403. offset += outputSampleCount;
  404. sampleCount -= outputSampleCount;
  405. if ( forward )
  406. {
  407. m_sample += inputSampleCount;
  408. m_absoluteSample += inputSampleCount;
  409. }
  410. if ( m_loop != 0 && m_sample >= m_loop )
  411. {
  412. SetSamplePosition( m_startpos );
  413. }
  414. }
  415. if ( sampleCount > 0 )
  416. return false;
  417. return true;
  418. }