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.

622 lines
19 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Device Common Base Class.
  4. //
  5. //=====================================================================================//
  6. #include "audio_pch.h"
  7. #define ISPEAKER_RIGHT_FRONT 0
  8. #define ISPEAKER_LEFT_FRONT 1
  9. #define ISPEAKER_RIGHT_REAR 2
  10. #define ISPEAKER_LEFT_REAR 3
  11. #define ISPEAKER_CENTER_FRONT 4
  12. extern Vector listener_right;
  13. extern void DEBUG_StartSoundMeasure(int type, int samplecount );
  14. extern void DEBUG_StopSoundMeasure(int type, int samplecount );
  15. extern bool MIX_ScaleChannelVolume( paintbuffer_t *pPaint, channel_t *pChannel, int volume[CCHANVOLUMES], int mixchans );
  16. inline bool FVolumeFrontNonZero( int *pvol )
  17. {
  18. return (pvol[IFRONT_RIGHT] || pvol[IFRONT_LEFT]);
  19. }
  20. inline bool FVolumeRearNonZero( int *pvol )
  21. {
  22. return (pvol[IREAR_RIGHT] || pvol[IREAR_LEFT]);
  23. }
  24. inline bool FVolumeCenterNonZero( int *pvol )
  25. {
  26. return (pvol[IFRONT_CENTER] != 0);
  27. }
  28. // fade speaker volumes to mono, based on xfade value.
  29. // ie: xfade 1.0 is full mono.
  30. // ispeaker is speaker index, cspeaker is total # of speakers
  31. // fmix2channels causes mono mix for 4 channel mix to mix down to 2 channels
  32. // this is used for the 2 speaker outpu case, which uses recombined 4 channel front/rear mixing
  33. static float XfadeSpeakerVolToMono( float scale, float xfade, float ispeaker, float cspeaker, bool fmix2channels )
  34. {
  35. float scale_out;
  36. float scale_target;
  37. if (cspeaker == 4 )
  38. {
  39. // mono sound distribution:
  40. float scale_targets[] = {0.9, 0.9, 0.9, 0.9}; // RF, LF, RR, LR
  41. float scale_targets2ch[] = {0.9, 0.9, 0.0, 0.0}; // RF, LF, RR, LR
  42. if ( fmix2channels )
  43. scale_target = scale_targets2ch[clamp(FastFloatToSmallInt(ispeaker), 0, 3)];
  44. else
  45. scale_target = scale_targets[clamp(FastFloatToSmallInt(ispeaker), 0, 3)];
  46. goto XfadeExit;
  47. }
  48. if (cspeaker == 5 )
  49. {
  50. // mono sound distribution:
  51. float scale_targets[] = {0.9, 0.9, 0.5, 0.5, 0.9}; // RF, LF, RR, LR, FC
  52. scale_target = scale_targets[(int)clamp(FastFloatToSmallInt(ispeaker), 0, 4)];
  53. goto XfadeExit;
  54. }
  55. // if (cspeaker == 2 )
  56. scale_target = 0.9; // front 2 speakers in stereo each get 50% of total volume in mono case
  57. XfadeExit:
  58. scale_out = scale + (scale_target - scale) * xfade;
  59. return scale_out;
  60. }
  61. // given:
  62. // 2d yaw angle to sound source (0-360), where 0 is listener_right
  63. // pitch angle to source
  64. // angle to speaker position (0-360), where 0 is listener_right
  65. // speaker index
  66. // speaker total count,
  67. // return: scale from 0-1.0 for speaker volume.
  68. // NOTE: as pitch angle goes to +/- 90, sound goes to mono, all speakers.
  69. #define PITCH_ANGLE_THRESHOLD 45.0
  70. #define REAR_VOL_DROP 0.5
  71. #define VOLCURVEPOWER 1.5 // 1.0 is a linear crossfade of volume between speakers.
  72. // 1.5 provides a smoother, nonlinear volume transition - this is done
  73. // because a volume of 255 played in a single speaker is
  74. // percieved as louder than 128 + 128 in two speakers
  75. // separated by at least 45 degrees. The nonlinear curve
  76. // gives the volume boost needed.
  77. static float GetSpeakerVol( float yaw_source, float pitch_source, float mono, float yaw_speaker, int ispeaker, int cspeaker, bool fmix2channels )
  78. {
  79. float adif = fabs(yaw_source - yaw_speaker);
  80. float pitch_angle = pitch_source;
  81. float scale = 0.0;
  82. float xfade = 0.0;
  83. if ( adif > 180 )
  84. adif = 360 - adif;
  85. // mono goes from 0.0 to 1.0 as listener moves into 'mono' radius of sound source.
  86. // Also, as pitch_angle to sound source approaches 90 (sound above/below listener), sounds become mono.
  87. // convert pitch angle to 0-90 absolute pitch
  88. if ( pitch_angle < 0)
  89. pitch_angle += 360;
  90. if ( pitch_angle > 180)
  91. pitch_angle = 360 - pitch_angle;
  92. if ( pitch_angle > 90)
  93. pitch_angle = 90 - (pitch_angle - 90);
  94. // calculate additional mono crossfade due to pitch angle
  95. if ( pitch_angle > PITCH_ANGLE_THRESHOLD )
  96. {
  97. xfade = ( pitch_angle - PITCH_ANGLE_THRESHOLD ) / ( 90.0 - PITCH_ANGLE_THRESHOLD ); // 0.0 -> 1.0 as angle 45->90
  98. mono += xfade;
  99. mono = clamp(mono, 0.0f, 1.0f);
  100. }
  101. if ( cspeaker == 2 )
  102. {
  103. // 2 speaker (headphone) mix: speakers opposing, at 0 & 180 degrees
  104. scale = (1.0 - powf(adif/180.0, VOLCURVEPOWER));
  105. goto GetVolExit;
  106. }
  107. if ( adif >= 90.0 )
  108. goto GetVolExit; // 0.0 scale
  109. if ( cspeaker == 4 )
  110. {
  111. // 4 ch surround: all speakers on 90 degree angles,
  112. // scale ranges from 0.0 (at 90 degree difference between source and speaker)
  113. // to 1.0 (0 degree difference between source and speaker)
  114. scale = (1.0 - powf(adif/90.0, VOLCURVEPOWER));
  115. goto GetVolExit;
  116. }
  117. // 5 ch surround:
  118. // rear speakers are on 90 degree angles and return 0.0->1.0 range over +/- 90 degrees each
  119. // center speaker is on 45 degree angle to left/right front speaker
  120. // center speaker has 0.0->1.0 range over 45 degrees
  121. switch (ispeaker)
  122. {
  123. default:
  124. case ISPEAKER_RIGHT_REAR:
  125. case ISPEAKER_LEFT_REAR:
  126. {
  127. // rear speakers get +/- 90 degrees of linear scaling...
  128. scale = (1.0 - powf(adif/90.0, VOLCURVEPOWER));
  129. break;
  130. }
  131. case ISPEAKER_CENTER_FRONT:
  132. {
  133. // center speaker gets +/- 45 degrees of linear scaling...
  134. if (adif > 45.0)
  135. goto GetVolExit; // 0.0 scale
  136. scale = (1.0 - powf(adif/45.0, VOLCURVEPOWER));
  137. break;
  138. }
  139. case ISPEAKER_RIGHT_FRONT:
  140. {
  141. if (yaw_source > yaw_speaker)
  142. {
  143. // if sound source is between right front speaker and center speaker,
  144. // apply scaling over 75 degrees...
  145. if (adif > 75.0)
  146. goto GetVolExit; // 0.0 scale
  147. scale = (1.0 - powf(adif/75.0, VOLCURVEPOWER));
  148. }
  149. /*
  150. if (yaw_source > yaw_speaker && yaw_source < (yaw_speaker + 90.0))
  151. {
  152. // if sound source is between right front speaker and center speaker,
  153. // apply scaling over 45 degrees...
  154. if (adif > 45.0)
  155. goto GetVolExit; // 0.0 scale
  156. scale = (1.0 - powf(adif/45.0, VOLCURVEPOWER));
  157. }
  158. */
  159. else
  160. {
  161. // sound source is CW from right speaker, apply scaling over 90 degrees...
  162. scale = (1.0 - powf(adif/90.0, VOLCURVEPOWER));
  163. }
  164. break;
  165. }
  166. case ISPEAKER_LEFT_FRONT:
  167. {
  168. if (yaw_source < yaw_speaker )
  169. {
  170. // if sound source is between left front speaker and center speaker,
  171. // apply scaling over 75 degrees...
  172. if (adif > 75.0)
  173. goto GetVolExit; // 0.0 scale
  174. scale = (1.0 - powf(adif/75.0, VOLCURVEPOWER));
  175. }
  176. /*
  177. if (yaw_source < yaw_speaker && yaw_source > (yaw_speaker - 90.0))
  178. {
  179. // if sound source is between left front speaker and center speaker,
  180. // apply scaling over 45 degrees...
  181. if (adif > 45.0)
  182. goto GetVolExit; // 0.0 scale
  183. scale = (1.0 - powf(adif/45.0, VOLCURVEPOWER));
  184. }
  185. */
  186. else
  187. {
  188. // sound source is CW from right speaker, apply scaling over 90 degrees...
  189. scale = (1.0 - powf(adif/90.0, VOLCURVEPOWER));
  190. }
  191. break;
  192. }
  193. }
  194. GetVolExit:
  195. Assert(mono <= 1.0 && mono >= 0.0);
  196. Assert(scale <= 1.0 && scale >= 0.0);
  197. // crossfade speaker volumes towards mono with increased pitch angle of sound source
  198. scale = XfadeSpeakerVolToMono( scale, mono, ispeaker, cspeaker, fmix2channels );
  199. Assert(scale <= 1.0 && scale >= 0.0);
  200. return scale;
  201. }
  202. // given unit vector from listener to sound source,
  203. // determine proportion of volume for sound in FL, FC, FR, RL, RR quadrants
  204. // Scale this proportion by the distance scalar 'gain'
  205. // If sound has 'mono' radius, blend sound to mono over 50% of radius.
  206. void CAudioDeviceBase::SpatializeChannel( int volume[CCHANVOLUMES/2], int master_vol, const Vector& sourceDir, float gain, float mono )
  207. {
  208. VPROF("CAudioDeviceBase::SpatializeChannel");
  209. float rfscale, rrscale, lfscale, lrscale, fcscale;
  210. fcscale = rfscale = lfscale = rrscale = lrscale = 0.0;
  211. // clear volumes
  212. for (int i = 0; i < CCHANVOLUMES/2; i++)
  213. volume[i] = 0;
  214. // linear crossfader for 2, 4 or 5 speakers, using polar coord. separation angle as linear basis
  215. // get pitch & yaw angle from listener origin to sound source
  216. QAngle angles;
  217. float pitch;
  218. float source_yaw;
  219. float yaw;
  220. VectorAngles(sourceDir, angles);
  221. pitch = angles[PITCH];
  222. source_yaw = angles[YAW];
  223. // get 2d listener yaw angle from listener right
  224. QAngle angles2d;
  225. Vector source2d;
  226. float listener_yaw;
  227. source2d.x = listener_right.x;
  228. source2d.y = listener_right.y;
  229. source2d.z = 0.0;
  230. VectorNormalize(source2d);
  231. // convert right vector to euler angles (yaw & pitch)
  232. VectorAngles(source2d, angles2d);
  233. listener_yaw = angles2d[YAW];
  234. // get yaw of sound source, with listener_yaw as reference 0.
  235. yaw = source_yaw - listener_yaw;
  236. if (yaw < 0)
  237. yaw += 360;
  238. if ( !m_bSurround )
  239. {
  240. // 2 ch stereo mixing
  241. if ( m_bHeadphone )
  242. {
  243. // headphone mix: (NO HRTF)
  244. rfscale = GetSpeakerVol( yaw, pitch, mono, 0.0, ISPEAKER_RIGHT_FRONT, 2, false);
  245. lfscale = GetSpeakerVol( yaw, pitch, mono, 180.0, ISPEAKER_LEFT_FRONT, 2, false );
  246. }
  247. else
  248. {
  249. // stereo speakers at 45 & 135 degrees: (mono sounds mix down to 2 channels)
  250. rfscale = GetSpeakerVol( yaw, pitch, mono, 45.0, ISPEAKER_RIGHT_FRONT, 4, true );
  251. lfscale = GetSpeakerVol( yaw, pitch, mono, 135.0, ISPEAKER_LEFT_FRONT, 4, true );
  252. rrscale = GetSpeakerVol( yaw, pitch, mono, 315.0, ISPEAKER_RIGHT_REAR, 4, true );
  253. lrscale = GetSpeakerVol( yaw, pitch, mono, 225.0, ISPEAKER_LEFT_REAR, 4, true );
  254. // add sounds coming from rear (quieter)
  255. rfscale = clamp((rfscale + rrscale * 0.75), 0.0, 1.0);
  256. lfscale = clamp((lfscale + lrscale * 0.75), 0.0, 1.0);
  257. rrscale = 0;
  258. lrscale = 0;
  259. //DevMsg("lfscale=%f rfscale=%f lrscale=%f rrscale=%f\n",lfscale,rfscale,lrscale,rrscale);
  260. //DevMsg("pitch=%f yaw=%f \n",pitch, yaw);
  261. }
  262. goto SpatialExit;
  263. }
  264. if ( m_bSurround && !m_bSurroundCenter )
  265. {
  266. // 4 ch surround
  267. // linearly scale with radial distance from asource to FR, FL, RR, RL
  268. // where FR = 45 degrees, FL = 135, RR = 315 (-45), RL = 225 (-135)
  269. rfscale = GetSpeakerVol( yaw, pitch, mono, 45.0, ISPEAKER_RIGHT_FRONT, 4, false );
  270. lfscale = GetSpeakerVol( yaw, pitch, mono, 135.0, ISPEAKER_LEFT_FRONT, 4, false );
  271. rrscale = GetSpeakerVol( yaw, pitch, mono, 315.0, ISPEAKER_RIGHT_REAR, 4, false );
  272. lrscale = GetSpeakerVol( yaw, pitch, mono, 225.0, ISPEAKER_LEFT_REAR, 4, false );
  273. // DevMsg("lfscale=%f rfscale=%f lrscale=%f rrscale=%f\n",lfscale,rfscale,lrscale,rrscale);
  274. // DevMsg("pitch=%f yaw=%f \n",pitch, yaw);
  275. goto SpatialExit;
  276. }
  277. if ( m_bSurround && m_bSurroundCenter )
  278. {
  279. // 5 ch surround
  280. // linearly scale with radial distance from asource to FR, FC, FL, RR, RL
  281. // where FR = 45 degrees, FC = 90, FL = 135, RR = 315 (-45), RL = 225 (-135)
  282. rfscale = GetSpeakerVol( yaw, pitch, mono, 45.0, ISPEAKER_RIGHT_FRONT, 5, false );
  283. fcscale = GetSpeakerVol( yaw, pitch, mono, 90.0, ISPEAKER_CENTER_FRONT, 5, false );
  284. lfscale = GetSpeakerVol( yaw, pitch, mono, 135.0, ISPEAKER_LEFT_FRONT, 5, false );
  285. rrscale = GetSpeakerVol( yaw, pitch, mono, 315.0, ISPEAKER_RIGHT_REAR, 5, false );
  286. lrscale = GetSpeakerVol( yaw, pitch, mono, 225.0, ISPEAKER_LEFT_REAR, 5, false );
  287. //DevMsg("lfscale=%f center= %f rfscale=%f lrscale=%f rrscale=%f\n",lfscale,fcscale, rfscale,lrscale,rrscale);
  288. //DevMsg("pitch=%f yaw=%f \n",pitch, yaw);
  289. goto SpatialExit;
  290. }
  291. SpatialExit:
  292. // scale volumes in each quadrant by distance attenuation.
  293. // volumes are 0-255:
  294. // gain is 0.0->1.0, rscale is 0.0->1.0, so scale is 0.0->1.0
  295. // master_vol is 0->255, so rightvol is 0->255
  296. volume[IFRONT_RIGHT] = (int) (master_vol * gain * rfscale);
  297. volume[IFRONT_LEFT] = (int) (master_vol * gain * lfscale);
  298. volume[IFRONT_RIGHT] = clamp( volume[IFRONT_RIGHT], 0, 255 );
  299. volume[IFRONT_LEFT] = clamp( volume[IFRONT_LEFT], 0, 255 );
  300. if ( m_bSurround )
  301. {
  302. volume[IREAR_RIGHT] = (int) (master_vol * gain * rrscale);
  303. volume[IREAR_LEFT] = (int) (master_vol * gain * lrscale);
  304. volume[IREAR_RIGHT] = clamp( volume[IREAR_RIGHT], 0, 255 );
  305. volume[IREAR_LEFT] = clamp( volume[IREAR_LEFT], 0, 255 );
  306. if ( m_bSurroundCenter )
  307. {
  308. volume[IFRONT_CENTER] = (int) (master_vol * gain * fcscale);
  309. volume[IFRONT_CENTER0] = 0.0;
  310. volume[IFRONT_CENTER] = clamp( volume[IFRONT_CENTER], 0, 255);
  311. }
  312. }
  313. }
  314. void CAudioDeviceBase::ApplyDSPEffects( int idsp, portable_samplepair_t *pbuffront, portable_samplepair_t *pbufrear, portable_samplepair_t *pbufcenter, int samplecount)
  315. {
  316. VPROF("CAudioDeviceBase::ApplyDSPEffects");
  317. DEBUG_StartSoundMeasure( 1, samplecount );
  318. DSP_Process( idsp, pbuffront, pbufrear, pbufcenter, samplecount );
  319. DEBUG_StopSoundMeasure( 1, samplecount );
  320. }
  321. void CAudioDeviceBase::MixBegin( int sampleCount )
  322. {
  323. MIX_ClearAllPaintBuffers( sampleCount, false );
  324. }
  325. void CAudioDeviceBase::MixUpsample( int sampleCount, int filtertype )
  326. {
  327. paintbuffer_t *pPaint = MIX_GetCurrentPaintbufferPtr();
  328. int ifilter = pPaint->ifilter;
  329. Assert (ifilter < CPAINTFILTERS);
  330. S_MixBufferUpsample2x( sampleCount, pPaint->pbuf, &(pPaint->fltmem[ifilter][0]), CPAINTFILTERMEM, filtertype );
  331. if ( pPaint->fsurround )
  332. {
  333. Assert( pPaint->pbufrear );
  334. S_MixBufferUpsample2x( sampleCount, pPaint->pbufrear, &(pPaint->fltmemrear[ifilter][0]), CPAINTFILTERMEM, filtertype );
  335. if ( pPaint->fsurround_center )
  336. {
  337. Assert( pPaint->pbufcenter );
  338. S_MixBufferUpsample2x( sampleCount, pPaint->pbufcenter, &(pPaint->fltmemcenter[ifilter][0]), CPAINTFILTERMEM, filtertype );
  339. }
  340. }
  341. // make sure on next upsample pass for this paintbuffer, new filter memory is used
  342. pPaint->ifilter++;
  343. }
  344. void CAudioDeviceBase::Mix8Mono( channel_t *pChannel, char *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress )
  345. {
  346. int volume[CCHANVOLUMES];
  347. paintbuffer_t *pPaint = MIX_GetCurrentPaintbufferPtr();
  348. if ( !MIX_ScaleChannelVolume( pPaint, pChannel, volume, 1) )
  349. return;
  350. if ( FVolumeFrontNonZero(volume) )
  351. {
  352. Mix8MonoWavtype( pChannel, pPaint->pbuf + outputOffset, volume, (byte *)pData, inputOffset, rateScaleFix, outCount);
  353. }
  354. if ( pPaint->fsurround )
  355. {
  356. if ( FVolumeRearNonZero(volume) )
  357. {
  358. Assert( pPaint->pbufrear );
  359. Mix8MonoWavtype( pChannel, pPaint->pbufrear + outputOffset, &volume[IREAR_LEFT], (byte *)pData, inputOffset, rateScaleFix, outCount );
  360. }
  361. if ( pPaint->fsurround_center && FVolumeCenterNonZero(volume) )
  362. {
  363. Assert( pPaint->pbufcenter );
  364. Mix8MonoWavtype( pChannel, pPaint->pbufcenter + outputOffset, &volume[IFRONT_CENTER], (byte *)pData, inputOffset, rateScaleFix, outCount );
  365. }
  366. }
  367. }
  368. void CAudioDeviceBase::Mix8Stereo( channel_t *pChannel, char *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress )
  369. {
  370. int volume[CCHANVOLUMES];
  371. paintbuffer_t *pPaint = MIX_GetCurrentPaintbufferPtr();
  372. if ( !MIX_ScaleChannelVolume( pPaint, pChannel, volume, 2 ) )
  373. return;
  374. if ( FVolumeFrontNonZero(volume) )
  375. {
  376. Mix8StereoWavtype( pChannel, pPaint->pbuf + outputOffset, volume, (byte *)pData, inputOffset, rateScaleFix, outCount );
  377. }
  378. if ( pPaint->fsurround )
  379. {
  380. if ( FVolumeRearNonZero(volume) )
  381. {
  382. Assert( pPaint->pbufrear );
  383. Mix8StereoWavtype( pChannel, pPaint->pbufrear + outputOffset, &volume[IREAR_LEFT], (byte *)pData, inputOffset, rateScaleFix, outCount );
  384. }
  385. if ( pPaint->fsurround_center && FVolumeCenterNonZero(volume) )
  386. {
  387. Assert( pPaint->pbufcenter );
  388. Mix8StereoWavtype( pChannel, pPaint->pbufcenter + outputOffset, &volume[IFRONT_CENTER], (byte *)pData, inputOffset, rateScaleFix, outCount );
  389. }
  390. }
  391. }
  392. void CAudioDeviceBase::Mix16Mono( channel_t *pChannel, short *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress )
  393. {
  394. int volume[CCHANVOLUMES];
  395. paintbuffer_t *pPaint = MIX_GetCurrentPaintbufferPtr();
  396. if ( !MIX_ScaleChannelVolume( pPaint, pChannel, volume, 1 ) )
  397. return;
  398. if ( FVolumeFrontNonZero(volume) )
  399. {
  400. Mix16MonoWavtype( pChannel, pPaint->pbuf + outputOffset, volume, pData, inputOffset, rateScaleFix, outCount );
  401. }
  402. if ( pPaint->fsurround )
  403. {
  404. if ( FVolumeRearNonZero(volume) )
  405. {
  406. Assert( pPaint->pbufrear );
  407. Mix16MonoWavtype( pChannel, pPaint->pbufrear + outputOffset, &volume[IREAR_LEFT], pData, inputOffset, rateScaleFix, outCount );
  408. }
  409. if ( pPaint->fsurround_center && FVolumeCenterNonZero(volume) )
  410. {
  411. Assert( pPaint->pbufcenter );
  412. Mix16MonoWavtype( pChannel, pPaint->pbufcenter + outputOffset, &volume[IFRONT_CENTER], pData, inputOffset, rateScaleFix, outCount );
  413. }
  414. }
  415. }
  416. void CAudioDeviceBase::Mix16Stereo( channel_t *pChannel, short *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress )
  417. {
  418. int volume[CCHANVOLUMES];
  419. paintbuffer_t *pPaint = MIX_GetCurrentPaintbufferPtr();
  420. if ( !MIX_ScaleChannelVolume( pPaint, pChannel, volume, 2 ) )
  421. return;
  422. if ( FVolumeFrontNonZero(volume) )
  423. {
  424. Mix16StereoWavtype( pChannel, pPaint->pbuf + outputOffset, volume, pData, inputOffset, rateScaleFix, outCount );
  425. }
  426. if ( pPaint->fsurround )
  427. {
  428. if ( FVolumeRearNonZero(volume) )
  429. {
  430. Assert( pPaint->pbufrear );
  431. Mix16StereoWavtype( pChannel, pPaint->pbufrear + outputOffset, &volume[IREAR_LEFT], pData, inputOffset, rateScaleFix, outCount );
  432. }
  433. if ( pPaint->fsurround_center && FVolumeCenterNonZero(volume) )
  434. {
  435. Assert( pPaint->pbufcenter );
  436. Mix16StereoWavtype( pChannel, pPaint->pbufcenter + outputOffset, &volume[IFRONT_CENTER], pData, inputOffset, rateScaleFix, outCount );
  437. }
  438. }
  439. }
  440. // Null Audio Device
  441. class CAudioDeviceNull : public CAudioDeviceBase
  442. {
  443. public:
  444. bool IsActive( void ) { return false; }
  445. bool Init( void ) { return true; }
  446. void Shutdown( void ) {}
  447. void Pause( void ) {}
  448. void UnPause( void ) {}
  449. float MixDryVolume( void ) { return 0; }
  450. bool Should3DMix( void ) { return false; }
  451. void StopAllSounds( void ) {}
  452. int PaintBegin( float, int, int ) { return 0; }
  453. void PaintEnd( void ) {}
  454. void SpatializeChannel( int volume[CCHANVOLUMES/2], int master_vol, const Vector& sourceDir, float gain, float mono ) {}
  455. void ApplyDSPEffects( int idsp, portable_samplepair_t *pbuffront, portable_samplepair_t *pbufrear, portable_samplepair_t *pbufcenter, int samplecount ) {}
  456. int GetOutputPosition( void ) { return 0; }
  457. void ClearBuffer( void ) {}
  458. void UpdateListener( const Vector&, const Vector&, const Vector&, const Vector& ) {}
  459. void MixBegin( int ) {}
  460. void MixUpsample( int sampleCount, int filtertype ) {}
  461. void Mix8Mono( channel_t *pChannel, char *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress ) {}
  462. void Mix8Stereo( channel_t *pChannel, char *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress ) {}
  463. void Mix16Mono( channel_t *pChannel, short *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress ) {}
  464. void Mix16Stereo( channel_t *pChannel, short *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress ) {}
  465. void ChannelReset( int, int, float ) {}
  466. void TransferSamples( int end ) {}
  467. const char *DeviceName( void ) { return "Audio Disabled"; }
  468. int DeviceChannels( void ) { return 2; }
  469. int DeviceSampleBits( void ) { return 16; }
  470. int DeviceSampleBytes( void ) { return 2; }
  471. int DeviceDmaSpeed( void ) { return SOUND_DMA_SPEED; }
  472. int DeviceSampleCount( void ) { return 0; }
  473. bool IsSurround( void ) { return false; }
  474. bool IsSurroundCenter( void ) { return false; }
  475. bool IsHeadphone( void ) { return false; }
  476. };
  477. IAudioDevice *Audio_GetNullDevice( void )
  478. {
  479. // singeton device here
  480. static CAudioDeviceNull nullDevice;
  481. return &nullDevice;
  482. }