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.

527 lines
15 KiB

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