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.

537 lines
15 KiB

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