i_sound_win32.cpp 26 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085
  1. /*
  2. ===========================================================================
  3. Doom 3 BFG Edition GPL Source Code
  4. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
  6. Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #include "Precompiled.h"
  21. #include "globaldata.h"
  22. //
  23. // DESCRIPTION:
  24. // System interface for sound.
  25. //
  26. //-----------------------------------------------------------------------------
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <stdarg.h>
  30. #include <math.h>
  31. #include <sys/types.h>
  32. #include <fcntl.h>
  33. // Timer stuff. Experimental.
  34. #include <time.h>
  35. #include <signal.h>
  36. #include "z_zone.h"
  37. #include "i_system.h"
  38. #include "i_sound.h"
  39. #include "m_argv.h"
  40. #include "m_misc.h"
  41. #include "w_wad.h"
  42. #include "d_main.h"
  43. #include "doomdef.h"
  44. #include "../timidity/timidity.h"
  45. #include "../timidity/controls.h"
  46. #include "sound/snd_local.h"
  47. #include <xaudio2.h>
  48. #include <x3daudio.h>
  49. #pragma warning ( disable : 4244 )
  50. #define MIDI_CHANNELS 2
  51. #if 1
  52. #define MIDI_RATE 22050
  53. #define MIDI_SAMPLETYPE XAUDIOSAMPLETYPE_8BITPCM
  54. #define MIDI_FORMAT AUDIO_U8
  55. #define MIDI_FORMAT_BYTES 1
  56. #else
  57. #define MIDI_RATE 48000
  58. #define MIDI_SAMPLETYPE XAUDIOSAMPLETYPE_16BITPCM
  59. #define MIDI_FORMAT AUDIO_S16MSB
  60. #define MIDI_FORMAT_BYTES 2
  61. #endif
  62. IXAudio2SourceVoice* pMusicSourceVoice;
  63. MidiSong* doomMusic;
  64. byte* musicBuffer;
  65. int totalBufferSize;
  66. HANDLE hMusicThread;
  67. bool waitingForMusic;
  68. bool musicReady;
  69. typedef struct tagActiveSound_t {
  70. IXAudio2SourceVoice* m_pSourceVoice; // Source voice
  71. X3DAUDIO_DSP_SETTINGS m_DSPSettings;
  72. X3DAUDIO_EMITTER m_Emitter;
  73. X3DAUDIO_CONE m_Cone;
  74. int id;
  75. int valid;
  76. int start;
  77. int player;
  78. bool localSound;
  79. mobj_t *originator;
  80. } activeSound_t;
  81. // cheap little struct to hold a sound
  82. typedef struct {
  83. int vol;
  84. int player;
  85. int pitch;
  86. int priority;
  87. mobj_t *originator;
  88. mobj_t *listener;
  89. } soundEvent_t;
  90. // array of all the possible sounds
  91. // in split screen we only process the loudest sound of each type per frame
  92. soundEvent_t soundEvents[128];
  93. extern int PLAYERCOUNT;
  94. // Real volumes
  95. const float GLOBAL_VOLUME_MULTIPLIER = 0.5f;
  96. float x_SoundVolume = GLOBAL_VOLUME_MULTIPLIER;
  97. float x_MusicVolume = GLOBAL_VOLUME_MULTIPLIER;
  98. // The actual lengths of all sound effects.
  99. static int lengths[NUMSFX];
  100. activeSound_t activeSounds[NUM_SOUNDBUFFERS] = {0};
  101. int S_initialized = 0;
  102. bool Music_initialized = false;
  103. // XAUDIO
  104. float g_EmitterAzimuths [] = { 0.f };
  105. static int numOutputChannels = 0;
  106. static bool soundHardwareInitialized = false;
  107. X3DAUDIO_HANDLE X3DAudioInstance;
  108. X3DAUDIO_LISTENER doom_Listener;
  109. //float localSoundVolumeEntries[] = { 0.f, 0.f, 0.9f, 0.5f, 0.f, 0.f };
  110. float localSoundVolumeEntries[] = { 0.8f, 0.8f, 0.8f, 0.8f, 0.8f, 0.8f, 0.8f, 0.8f, 0.8f, 0.8f, 0.8f };
  111. void I_InitSoundChannel( int channel, int numOutputChannels_ );
  112. /*
  113. ======================
  114. getsfx
  115. ======================
  116. */
  117. // This function loads the sound data from the WAD lump,
  118. // for single sound.
  119. //
  120. void* getsfx ( char* sfxname, int* len )
  121. {
  122. unsigned char* sfx;
  123. unsigned char* sfxmem;
  124. int size;
  125. char name[20];
  126. int sfxlump;
  127. float scale = 1.0f;
  128. // Get the sound data from the WAD, allocate lump
  129. // in zone memory.
  130. sprintf(name, "ds%s", sfxname);
  131. // Scale down the plasma gun, it clips
  132. if ( strcmp( sfxname, "plasma" ) == 0 ) {
  133. scale = 0.75f;
  134. }
  135. if ( strcmp( sfxname, "itemup" ) == 0 ) {
  136. scale = 1.333f;
  137. }
  138. // If sound requested is not found in current WAD, use pistol as default
  139. if ( W_CheckNumForName(name) == -1 )
  140. sfxlump = W_GetNumForName("dspistol");
  141. else
  142. sfxlump = W_GetNumForName(name);
  143. // Sound lump headers are 8 bytes.
  144. const int SOUND_LUMP_HEADER_SIZE_IN_BYTES = 8;
  145. size = W_LumpLength( sfxlump ) - SOUND_LUMP_HEADER_SIZE_IN_BYTES;
  146. sfx = (unsigned char*)W_CacheLumpNum( sfxlump, PU_CACHE_SHARED );
  147. const unsigned char * sfxSampleStart = sfx + SOUND_LUMP_HEADER_SIZE_IN_BYTES;
  148. // Allocate from zone memory.
  149. //sfxmem = (float*)DoomLib::Z_Malloc( size*(sizeof(float)), PU_SOUND_SHARED, 0 );
  150. sfxmem = (unsigned char*)malloc( size * sizeof(unsigned char) );
  151. // Now copy, and convert to Xbox360 native float samples, do initial volume ramp, and scale
  152. for ( int i=0; i<size; i++ ) {
  153. sfxmem[i] = sfxSampleStart[i];// * scale;
  154. }
  155. // Remove the cached lump.
  156. Z_Free( sfx );
  157. // Set length.
  158. *len = size;
  159. // Return allocated padded data.
  160. return (void *) (sfxmem);
  161. }
  162. /*
  163. ======================
  164. I_SetChannels
  165. ======================
  166. */
  167. void I_SetChannels() {
  168. // Original Doom set up lookup tables here
  169. }
  170. /*
  171. ======================
  172. I_SetSfxVolume
  173. ======================
  174. */
  175. void I_SetSfxVolume(int volume) {
  176. x_SoundVolume = ((float)volume / 15.f) * GLOBAL_VOLUME_MULTIPLIER;
  177. }
  178. /*
  179. ======================
  180. I_GetSfxLumpNum
  181. ======================
  182. */
  183. //
  184. // Retrieve the raw data lump index
  185. // for a given SFX name.
  186. //
  187. int I_GetSfxLumpNum(sfxinfo_t* sfx)
  188. {
  189. char namebuf[9];
  190. sprintf(namebuf, "ds%s", sfx->name);
  191. return W_GetNumForName(namebuf);
  192. }
  193. /*
  194. ======================
  195. I_StartSound2
  196. ======================
  197. */
  198. // Starting a sound means adding it
  199. // to the current list of active sounds
  200. // in the internal channels.
  201. // As the SFX info struct contains
  202. // e.g. a pointer to the raw data,
  203. // it is ignored.
  204. // As our sound handling does not handle
  205. // priority, it is ignored.
  206. // Pitching (that is, increased speed of playback) is set
  207. //
  208. int I_StartSound2 ( int id, int player, mobj_t *origin, mobj_t *listener_origin, int pitch, int priority ) {
  209. if ( !soundHardwareInitialized ) {
  210. return id;
  211. }
  212. int i;
  213. XAUDIO2_VOICE_STATE state;
  214. activeSound_t* sound = 0;
  215. int oldest = 0, oldestnum = -1;
  216. // these id's should not overlap
  217. if ( id == sfx_sawup || id == sfx_sawidl || id == sfx_sawful || id == sfx_sawhit || id == sfx_stnmov ) {
  218. // Loop all channels, check.
  219. for (i=0 ; i < NUM_SOUNDBUFFERS ; i++)
  220. {
  221. sound = &activeSounds[i];
  222. if (sound->valid && ( sound->id == id && sound->player == player ) ) {
  223. I_StopSound( sound->id, player );
  224. break;
  225. }
  226. }
  227. }
  228. // find a valid channel, or one that has finished playing
  229. for (i = 0; i < NUM_SOUNDBUFFERS; ++i) {
  230. sound = &activeSounds[i];
  231. if (!sound->valid)
  232. break;
  233. if (!oldest || oldest > sound->start) {
  234. oldestnum = i;
  235. oldest = sound->start;
  236. }
  237. sound->m_pSourceVoice->GetState( &state );
  238. if ( state.BuffersQueued == 0 ) {
  239. break;
  240. }
  241. }
  242. // none found, so use the oldest one
  243. if (i == NUM_SOUNDBUFFERS)
  244. {
  245. i = oldestnum;
  246. sound = &activeSounds[i];
  247. }
  248. // stop the sound with a FlushPackets
  249. sound->m_pSourceVoice->Stop();
  250. sound->m_pSourceVoice->FlushSourceBuffers();
  251. // Set up packet
  252. XAUDIO2_BUFFER Packet = { 0 };
  253. Packet.Flags = XAUDIO2_END_OF_STREAM;
  254. Packet.AudioBytes = lengths[id];
  255. Packet.pAudioData = (BYTE*)S_sfx[id].data;
  256. Packet.PlayBegin = 0;
  257. Packet.PlayLength = 0;
  258. Packet.LoopBegin = XAUDIO2_NO_LOOP_REGION;
  259. Packet.LoopLength = 0;
  260. Packet.LoopCount = 0;
  261. Packet.pContext = NULL;
  262. // Set voice volumes
  263. sound->m_pSourceVoice->SetVolume( x_SoundVolume );
  264. // Set voice pitch
  265. sound->m_pSourceVoice->SetFrequencyRatio( 1 + ((float)pitch-128.f)/95.f );
  266. // Set initial spatialization
  267. if ( origin && origin != listener_origin ) {
  268. // Update Emitter Position
  269. sound->m_Emitter.Position.x = (float)(origin->x >> FRACBITS);
  270. sound->m_Emitter.Position.y = 0.f;
  271. sound->m_Emitter.Position.z = (float)(origin->y >> FRACBITS);
  272. // Calculate 3D positioned speaker volumes
  273. DWORD dwCalculateFlags = X3DAUDIO_CALCULATE_MATRIX;
  274. X3DAudioCalculate( X3DAudioInstance, &doom_Listener, &sound->m_Emitter, dwCalculateFlags, &sound->m_DSPSettings );
  275. // Pan the voice according to X3DAudio calculation
  276. sound->m_pSourceVoice->SetOutputMatrix( NULL, 1, numOutputChannels, sound->m_DSPSettings.pMatrixCoefficients );
  277. sound->localSound = false;
  278. } else {
  279. // Local(or Global) sound, fixed speaker volumes
  280. sound->m_pSourceVoice->SetOutputMatrix( NULL, 1, numOutputChannels, localSoundVolumeEntries );
  281. sound->localSound = true;
  282. }
  283. // Submit packet
  284. HRESULT hr;
  285. if( FAILED( hr = sound->m_pSourceVoice->SubmitSourceBuffer( &Packet ) ) ) {
  286. int fail = 1;
  287. }
  288. // Play the source voice
  289. if( FAILED( hr = sound->m_pSourceVoice->Start( 0 ) ) ) {
  290. int fail = 1;
  291. }
  292. // set id, and start time
  293. sound->id = id;
  294. sound->start = ::g->gametic;
  295. sound->valid = 1;
  296. sound->player = player;
  297. sound->originator = origin;
  298. return id;
  299. }
  300. /*
  301. ======================
  302. I_ProcessSoundEvents
  303. ======================
  304. */
  305. void I_ProcessSoundEvents( void ) {
  306. for( int i = 0; i < 128; i++ ) {
  307. if( soundEvents[i].pitch ) {
  308. I_StartSound2( i, soundEvents[i].player, soundEvents[i].originator, soundEvents[i].listener, soundEvents[i].pitch, soundEvents[i].priority );
  309. }
  310. }
  311. memset( soundEvents, 0, sizeof( soundEvents ) );
  312. }
  313. /*
  314. ======================
  315. I_StartSound
  316. ======================
  317. */
  318. int I_StartSound ( int id, mobj_t *origin, mobj_t *listener_origin, int vol, int pitch, int priority ) {
  319. // only allow player 0s sounds in intermission and finale screens
  320. if( ::g->gamestate != GS_LEVEL && DoomLib::GetPlayer() != 0 ) {
  321. return 0;
  322. }
  323. // if we're only one player or we're trying to play the chainsaw sound, do it normal
  324. // otherwise only allow one sound of each type per frame
  325. if( PLAYERCOUNT == 1 || id == sfx_sawup || id == sfx_sawidl || id == sfx_sawful || id == sfx_sawhit ) {
  326. return I_StartSound2( id, ::g->consoleplayer, origin, listener_origin, pitch, priority );
  327. }
  328. else {
  329. if( soundEvents[ id ].vol < vol ) {
  330. soundEvents[ id ].player = DoomLib::GetPlayer();
  331. soundEvents[ id ].pitch = pitch;
  332. soundEvents[ id ].priority = priority;
  333. soundEvents[ id ].vol = vol;
  334. soundEvents[ id ].originator = origin;
  335. soundEvents[ id ].listener = listener_origin;
  336. }
  337. return id;
  338. }
  339. }
  340. /*
  341. ======================
  342. I_StopSound
  343. ======================
  344. */
  345. void I_StopSound (int handle, int player)
  346. {
  347. // You need the handle returned by StartSound.
  348. // Would be looping all channels,
  349. // tracking down the handle,
  350. // an setting the channel to zero.
  351. int i;
  352. activeSound_t* sound = 0;
  353. for (i = 0; i < NUM_SOUNDBUFFERS; ++i)
  354. {
  355. sound = &activeSounds[i];
  356. if (!sound->valid || sound->id != handle || (player >= 0 && sound->player != player) )
  357. continue;
  358. break;
  359. }
  360. if (i == NUM_SOUNDBUFFERS)
  361. return;
  362. // stop the sound
  363. if ( sound->m_pSourceVoice != NULL ) {
  364. sound->m_pSourceVoice->Stop( 0 );
  365. }
  366. sound->valid = 0;
  367. sound->player = -1;
  368. }
  369. /*
  370. ======================
  371. I_SoundIsPlaying
  372. ======================
  373. */
  374. int I_SoundIsPlaying(int handle) {
  375. if ( !soundHardwareInitialized ) {
  376. return 0;
  377. }
  378. int i;
  379. XAUDIO2_VOICE_STATE state;
  380. activeSound_t* sound;
  381. for (i = 0; i < NUM_SOUNDBUFFERS; ++i)
  382. {
  383. sound = &activeSounds[i];
  384. if (!sound->valid || sound->id != handle)
  385. continue;
  386. sound->m_pSourceVoice->GetState( &state );
  387. if ( state.BuffersQueued > 0 ) {
  388. return 1;
  389. }
  390. }
  391. return 0;
  392. }
  393. /*
  394. ======================
  395. I_UpdateSound
  396. ======================
  397. */
  398. // Update Listener Position and go through all the
  399. // channels and update speaker volumes for 3D sound.
  400. void I_UpdateSound( void ) {
  401. if ( !soundHardwareInitialized ) {
  402. return;
  403. }
  404. int i;
  405. XAUDIO2_VOICE_STATE state;
  406. activeSound_t* sound;
  407. for ( i=0; i < NUM_SOUNDBUFFERS; i++ ) {
  408. sound = &activeSounds[i];
  409. if ( !sound->valid || sound->localSound ) {
  410. continue;
  411. }
  412. sound->m_pSourceVoice->GetState( &state );
  413. if ( state.BuffersQueued > 0 ) {
  414. mobj_t *playerObj = ::g->players[ sound->player ].mo;
  415. // Update Listener Orientation and Position
  416. angle_t pAngle = playerObj->angle;
  417. fixed_t fx, fz;
  418. pAngle >>= ANGLETOFINESHIFT;
  419. fx = finecosine[pAngle];
  420. fz = finesine[pAngle];
  421. doom_Listener.OrientFront.x = (float)(fx) / 65535.f;
  422. doom_Listener.OrientFront.y = 0.f;
  423. doom_Listener.OrientFront.z = (float)(fz) / 65535.f;
  424. doom_Listener.Position.x = (float)(playerObj->x >> FRACBITS);
  425. doom_Listener.Position.y = 0.f;
  426. doom_Listener.Position.z = (float)(playerObj->y >> FRACBITS);
  427. // Update Emitter Position
  428. sound->m_Emitter.Position.x = (float)(sound->originator->x >> FRACBITS);
  429. sound->m_Emitter.Position.y = 0.f;
  430. sound->m_Emitter.Position.z = (float)(sound->originator->y >> FRACBITS);
  431. // Calculate 3D positioned speaker volumes
  432. DWORD dwCalculateFlags = X3DAUDIO_CALCULATE_MATRIX;
  433. X3DAudioCalculate( X3DAudioInstance, &doom_Listener, &sound->m_Emitter, dwCalculateFlags, &sound->m_DSPSettings );
  434. // Pan the voice according to X3DAudio calculation
  435. sound->m_pSourceVoice->SetOutputMatrix( NULL, 1, numOutputChannels, sound->m_DSPSettings.pMatrixCoefficients );
  436. }
  437. }
  438. }
  439. /*
  440. ======================
  441. I_UpdateSoundParams
  442. ======================
  443. */
  444. void I_UpdateSoundParams( int handle, int vol, int sep, int pitch) {
  445. }
  446. /*
  447. ======================
  448. I_ShutdownSound
  449. ======================
  450. */
  451. void I_ShutdownSound(void) {
  452. int done = 0;
  453. int i;
  454. if ( S_initialized ) {
  455. // Stop all sounds, but don't destroy the XAudio2 buffers.
  456. for ( i = 0; i < NUM_SOUNDBUFFERS; ++i ) {
  457. activeSound_t * sound = &activeSounds[i];
  458. if ( sound == NULL ) {
  459. continue;
  460. }
  461. I_StopSound( sound->id, 0 );
  462. if ( sound->m_pSourceVoice ) {
  463. sound->m_pSourceVoice->FlushSourceBuffers();
  464. }
  465. }
  466. for (i=1 ; i<NUMSFX ; i++) {
  467. if ( S_sfx[i].data && !(S_sfx[i].link) ) {
  468. //Z_Free( S_sfx[i].data );
  469. free( S_sfx[i].data );
  470. }
  471. }
  472. }
  473. I_StopSong( 0 );
  474. S_initialized = 0;
  475. // Done.
  476. return;
  477. }
  478. /*
  479. ======================
  480. I_InitSoundHardware
  481. Called from the tech4x initialization code. Sets up Doom classic's
  482. sound channels.
  483. ======================
  484. */
  485. void I_InitSoundHardware( int numOutputChannels_, int channelMask ) {
  486. ::numOutputChannels = numOutputChannels_;
  487. // Initialize the X3DAudio
  488. // Speaker geometry configuration on the final mix, specifies assignment of channels
  489. // to speaker positions, defined as per WAVEFORMATEXTENSIBLE.dwChannelMask
  490. // SpeedOfSound - not used by doomclassic
  491. X3DAudioInitialize( channelMask, 340.29f, X3DAudioInstance );
  492. for ( int i = 0; i < NUM_SOUNDBUFFERS; ++i ) {
  493. // Initialize source voices
  494. I_InitSoundChannel( i, numOutputChannels );
  495. }
  496. I_InitMusic();
  497. soundHardwareInitialized = true;
  498. }
  499. /*
  500. ======================
  501. I_ShutdownitSoundHardware
  502. Called from the tech4x shutdown code. Tears down Doom classic's
  503. sound channels.
  504. ======================
  505. */
  506. void I_ShutdownSoundHardware() {
  507. soundHardwareInitialized = false;
  508. I_ShutdownMusic();
  509. for ( int i = 0; i < NUM_SOUNDBUFFERS; ++i ) {
  510. activeSound_t * sound = &activeSounds[i];
  511. if ( sound == NULL ) {
  512. continue;
  513. }
  514. if ( sound->m_pSourceVoice ) {
  515. sound->m_pSourceVoice->Stop();
  516. sound->m_pSourceVoice->FlushSourceBuffers();
  517. sound->m_pSourceVoice->DestroyVoice();
  518. sound->m_pSourceVoice = NULL;
  519. }
  520. if ( sound->m_DSPSettings.pMatrixCoefficients ) {
  521. delete [] sound->m_DSPSettings.pMatrixCoefficients;
  522. sound->m_DSPSettings.pMatrixCoefficients = NULL;
  523. }
  524. }
  525. }
  526. /*
  527. ======================
  528. I_InitSoundChannel
  529. ======================
  530. */
  531. void I_InitSoundChannel( int channel, int numOutputChannels_ ) {
  532. activeSound_t *soundchannel = &activeSounds[ channel ];
  533. X3DAUDIO_VECTOR ZeroVector = { 0.0f, 0.0f, 0.0f };
  534. // Set up emitter parameters
  535. soundchannel->m_Emitter.OrientFront.x = 0.0f;
  536. soundchannel->m_Emitter.OrientFront.y = 0.0f;
  537. soundchannel->m_Emitter.OrientFront.z = 1.0f;
  538. soundchannel->m_Emitter.OrientTop.x = 0.0f;
  539. soundchannel->m_Emitter.OrientTop.y = 1.0f;
  540. soundchannel->m_Emitter.OrientTop.z = 0.0f;
  541. soundchannel->m_Emitter.Position = ZeroVector;
  542. soundchannel->m_Emitter.Velocity = ZeroVector;
  543. soundchannel->m_Emitter.pCone = &(soundchannel->m_Cone);
  544. soundchannel->m_Emitter.pCone->InnerAngle = 0.0f; // Setting the inner cone angles to X3DAUDIO_2PI and
  545. // outer cone other than 0 causes
  546. // the emitter to act like a point emitter using the
  547. // INNER cone settings only.
  548. soundchannel->m_Emitter.pCone->OuterAngle = 0.0f; // Setting the outer cone angles to zero causes
  549. // the emitter to act like a point emitter using the
  550. // OUTER cone settings only.
  551. soundchannel->m_Emitter.pCone->InnerVolume = 0.0f;
  552. soundchannel->m_Emitter.pCone->OuterVolume = 1.0f;
  553. soundchannel->m_Emitter.pCone->InnerLPF = 0.0f;
  554. soundchannel->m_Emitter.pCone->OuterLPF = 1.0f;
  555. soundchannel->m_Emitter.pCone->InnerReverb = 0.0f;
  556. soundchannel->m_Emitter.pCone->OuterReverb = 1.0f;
  557. soundchannel->m_Emitter.ChannelCount = 1;
  558. soundchannel->m_Emitter.ChannelRadius = 0.0f;
  559. soundchannel->m_Emitter.pVolumeCurve = NULL;
  560. soundchannel->m_Emitter.pLFECurve = NULL;
  561. soundchannel->m_Emitter.pLPFDirectCurve = NULL;
  562. soundchannel->m_Emitter.pLPFReverbCurve = NULL;
  563. soundchannel->m_Emitter.pReverbCurve = NULL;
  564. soundchannel->m_Emitter.CurveDistanceScaler = 1200.0f;
  565. soundchannel->m_Emitter.DopplerScaler = 1.0f;
  566. soundchannel->m_Emitter.pChannelAzimuths = g_EmitterAzimuths;
  567. soundchannel->m_DSPSettings.SrcChannelCount = 1;
  568. soundchannel->m_DSPSettings.DstChannelCount = numOutputChannels_;
  569. soundchannel->m_DSPSettings.pMatrixCoefficients = new FLOAT[ numOutputChannels_ ];
  570. // Create Source voice
  571. WAVEFORMATEX voiceFormat = {0};
  572. voiceFormat.wFormatTag = WAVE_FORMAT_PCM;
  573. voiceFormat.nChannels = 1;
  574. voiceFormat.nSamplesPerSec = 11025;
  575. voiceFormat.nAvgBytesPerSec = 11025;
  576. voiceFormat.nBlockAlign = 1;
  577. voiceFormat.wBitsPerSample = 8;
  578. voiceFormat.cbSize = 0;
  579. soundSystemLocal.hardware.GetIXAudio2()->CreateSourceVoice( &soundchannel->m_pSourceVoice, (WAVEFORMATEX *)&voiceFormat );
  580. }
  581. /*
  582. ======================
  583. I_InitSound
  584. ======================
  585. */
  586. void I_InitSound() {
  587. if (S_initialized == 0) {
  588. int i;
  589. X3DAUDIO_VECTOR ZeroVector = { 0.0f, 0.0f, 0.0f };
  590. // Set up listener parameters
  591. doom_Listener.OrientFront.x = 0.0f;
  592. doom_Listener.OrientFront.y = 0.0f;
  593. doom_Listener.OrientFront.z = 1.0f;
  594. doom_Listener.OrientTop.x = 0.0f;
  595. doom_Listener.OrientTop.y = 1.0f;
  596. doom_Listener.OrientTop.z = 0.0f;
  597. doom_Listener.Position = ZeroVector;
  598. doom_Listener.Velocity = ZeroVector;
  599. for (i=1 ; i<NUMSFX ; i++)
  600. {
  601. // Alias? Example is the chaingun sound linked to pistol.
  602. if (!S_sfx[i].link)
  603. {
  604. // Load data from WAD file.
  605. S_sfx[i].data = getsfx( S_sfx[i].name, &lengths[i] );
  606. }
  607. else
  608. {
  609. // Previously loaded already?
  610. S_sfx[i].data = S_sfx[i].link->data;
  611. lengths[i] = lengths[(S_sfx[i].link - S_sfx)/sizeof(sfxinfo_t)];
  612. }
  613. }
  614. S_initialized = 1;
  615. }
  616. }
  617. /*
  618. ======================
  619. I_SubmitSound
  620. ======================
  621. */
  622. void I_SubmitSound(void)
  623. {
  624. // Only do this for player 0, it will still handle positioning
  625. // for other players, but it can't be outside the game
  626. // frame like the soundEvents are.
  627. if ( DoomLib::GetPlayer() == 0 ) {
  628. // Do 3D positioning of sounds
  629. I_UpdateSound();
  630. // Check for XMP notifications
  631. I_UpdateMusic();
  632. }
  633. }
  634. // =========================================================
  635. // =========================================================
  636. // Background Music
  637. // =========================================================
  638. // =========================================================
  639. /*
  640. ======================
  641. I_SetMusicVolume
  642. ======================
  643. */
  644. void I_SetMusicVolume(int volume)
  645. {
  646. x_MusicVolume = (float)volume / 15.f;
  647. }
  648. /*
  649. ======================
  650. I_InitMusic
  651. ======================
  652. */
  653. void I_InitMusic(void)
  654. {
  655. if ( !Music_initialized ) {
  656. // Initialize Timidity
  657. Timidity_Init( MIDI_RATE, MIDI_FORMAT, MIDI_CHANNELS, MIDI_RATE, "classicmusic/gravis.cfg" );
  658. hMusicThread = NULL;
  659. musicBuffer = NULL;
  660. totalBufferSize = 0;
  661. waitingForMusic = false;
  662. musicReady = false;
  663. // Create Source voice
  664. WAVEFORMATEX voiceFormat = {0};
  665. voiceFormat.wFormatTag = WAVE_FORMAT_PCM;
  666. voiceFormat.nChannels = 2;
  667. voiceFormat.nSamplesPerSec = MIDI_RATE;
  668. voiceFormat.nAvgBytesPerSec = MIDI_RATE * MIDI_FORMAT_BYTES * 2;
  669. voiceFormat.nBlockAlign = MIDI_FORMAT_BYTES * 2;
  670. voiceFormat.wBitsPerSample = MIDI_FORMAT_BYTES * 8;
  671. voiceFormat.cbSize = 0;
  672. soundSystemLocal.hardware.GetIXAudio2()->CreateSourceVoice( &pMusicSourceVoice, (WAVEFORMATEX *)&voiceFormat, XAUDIO2_VOICE_MUSIC );
  673. Music_initialized = true;
  674. }
  675. }
  676. /*
  677. ======================
  678. I_ShutdownMusic
  679. ======================
  680. */
  681. void I_ShutdownMusic(void)
  682. {
  683. I_StopSong( 0 );
  684. if ( Music_initialized ) {
  685. if ( pMusicSourceVoice ) {
  686. pMusicSourceVoice->Stop();
  687. pMusicSourceVoice->FlushSourceBuffers();
  688. pMusicSourceVoice->DestroyVoice();
  689. pMusicSourceVoice = NULL;
  690. }
  691. if ( hMusicThread ) {
  692. DWORD rc;
  693. do {
  694. GetExitCodeThread( hMusicThread, &rc );
  695. if ( rc == STILL_ACTIVE ) {
  696. Sleep( 1 );
  697. }
  698. } while( rc == STILL_ACTIVE );
  699. CloseHandle( hMusicThread );
  700. }
  701. if ( musicBuffer ) {
  702. free( musicBuffer );
  703. }
  704. Timidity_Shutdown();
  705. }
  706. pMusicSourceVoice = NULL;
  707. hMusicThread = NULL;
  708. musicBuffer = NULL;
  709. totalBufferSize = 0;
  710. waitingForMusic = false;
  711. musicReady = false;
  712. Music_initialized = false;
  713. }
  714. int Mus2Midi(unsigned char* bytes, unsigned char* out, int* len);
  715. namespace {
  716. const int MaxMidiConversionSize = 1024 * 1024;
  717. unsigned char midiConversionBuffer[MaxMidiConversionSize];
  718. }
  719. /*
  720. ======================
  721. I_LoadSong
  722. ======================
  723. */
  724. DWORD WINAPI I_LoadSong( LPVOID songname ) {
  725. idStr lumpName = "d_";
  726. lumpName += static_cast< const char * >( songname );
  727. unsigned char * musFile = static_cast< unsigned char * >( W_CacheLumpName( lumpName.c_str(), PU_STATIC_SHARED ) );
  728. int length = 0;
  729. Mus2Midi( musFile, midiConversionBuffer, &length );
  730. doomMusic = Timidity_LoadSongMem( midiConversionBuffer, length );
  731. if ( doomMusic ) {
  732. musicBuffer = (byte *)malloc( MIDI_CHANNELS * MIDI_FORMAT_BYTES * doomMusic->samples );
  733. totalBufferSize = doomMusic->samples * MIDI_CHANNELS * MIDI_FORMAT_BYTES;
  734. Timidity_Start( doomMusic );
  735. int rc = RC_NO_RETURN_VALUE;
  736. int num_bytes = 0;
  737. int offset = 0;
  738. do {
  739. rc = Timidity_PlaySome( musicBuffer + offset, MIDI_RATE, &num_bytes );
  740. offset += num_bytes;
  741. } while ( rc != RC_TUNE_END );
  742. Timidity_Stop();
  743. Timidity_FreeSong( doomMusic );
  744. }
  745. musicReady = true;
  746. return ERROR_SUCCESS;
  747. }
  748. /*
  749. ======================
  750. I_PlaySong
  751. ======================
  752. */
  753. void I_PlaySong( const char *songname, int looping)
  754. {
  755. if ( !Music_initialized ) {
  756. return;
  757. }
  758. if ( pMusicSourceVoice != NULL ) {
  759. // Stop the voice and flush packets before freeing the musicBuffer
  760. pMusicSourceVoice->Stop();
  761. pMusicSourceVoice->FlushSourceBuffers();
  762. }
  763. // Make sure voice is stopped before we free the buffer
  764. bool isStopped = false;
  765. int d = 0;
  766. while ( !isStopped ) {
  767. XAUDIO2_VOICE_STATE test;
  768. if ( pMusicSourceVoice != NULL ) {
  769. pMusicSourceVoice->GetState( &test );
  770. }
  771. if ( test.pCurrentBufferContext == NULL && test.BuffersQueued == 0 ) {
  772. isStopped = true;
  773. }
  774. //I_Printf( "waiting to stop (%d)\n", d++ );
  775. }
  776. // Clear old state
  777. if ( musicBuffer != NULL ) {
  778. free( musicBuffer );
  779. musicBuffer = NULL;
  780. }
  781. musicReady = false;
  782. I_LoadSong( (LPVOID)songname );
  783. waitingForMusic = true;
  784. if ( DoomLib::GetPlayer() >= 0 ) {
  785. ::g->mus_looping = looping;
  786. }
  787. }
  788. /*
  789. ======================
  790. I_UpdateMusic
  791. ======================
  792. */
  793. void I_UpdateMusic( void ) {
  794. if ( !Music_initialized ) {
  795. return;
  796. }
  797. if ( waitingForMusic ) {
  798. if ( musicReady && pMusicSourceVoice != NULL ) {
  799. if ( musicBuffer ) {
  800. // Set up packet
  801. XAUDIO2_BUFFER Packet = { 0 };
  802. Packet.Flags = XAUDIO2_END_OF_STREAM;
  803. Packet.AudioBytes = totalBufferSize;
  804. Packet.pAudioData = (BYTE*)musicBuffer;
  805. Packet.PlayBegin = 0;
  806. Packet.PlayLength = 0;
  807. Packet.LoopBegin = 0;
  808. Packet.LoopLength = 0;
  809. Packet.LoopCount = ::g->mus_looping ? XAUDIO2_LOOP_INFINITE : 0;
  810. Packet.pContext = NULL;
  811. // Submit packet
  812. HRESULT hr;
  813. if( FAILED( hr = pMusicSourceVoice->SubmitSourceBuffer( &Packet ) ) ) {
  814. int fail = 1;
  815. }
  816. // Play the source voice
  817. if( FAILED( hr = pMusicSourceVoice->Start( 0 ) ) ) {
  818. int fail = 1;
  819. }
  820. }
  821. waitingForMusic = false;
  822. }
  823. }
  824. if ( pMusicSourceVoice != NULL ) {
  825. // Set the volume
  826. pMusicSourceVoice->SetVolume( x_MusicVolume * GLOBAL_VOLUME_MULTIPLIER );
  827. }
  828. }
  829. /*
  830. ======================
  831. I_PauseSong
  832. ======================
  833. */
  834. void I_PauseSong (int handle)
  835. {
  836. if ( !Music_initialized ) {
  837. return;
  838. }
  839. if ( pMusicSourceVoice != NULL ) {
  840. // Stop the music source voice
  841. pMusicSourceVoice->Stop( 0 );
  842. }
  843. }
  844. /*
  845. ======================
  846. I_ResumeSong
  847. ======================
  848. */
  849. void I_ResumeSong (int handle)
  850. {
  851. if ( !Music_initialized ) {
  852. return;
  853. }
  854. // Stop the music source voice
  855. if ( pMusicSourceVoice != NULL ) {
  856. pMusicSourceVoice->Start( 0 );
  857. }
  858. }
  859. /*
  860. ======================
  861. I_StopSong
  862. ======================
  863. */
  864. void I_StopSong(int handle)
  865. {
  866. if ( !Music_initialized ) {
  867. return;
  868. }
  869. // Stop the music source voice
  870. if ( pMusicSourceVoice != NULL ) {
  871. pMusicSourceVoice->Stop( 0 );
  872. }
  873. }
  874. /*
  875. ======================
  876. I_UnRegisterSong
  877. ======================
  878. */
  879. void I_UnRegisterSong(int handle)
  880. {
  881. // does nothing
  882. }
  883. /*
  884. ======================
  885. I_RegisterSong
  886. ======================
  887. */
  888. int I_RegisterSong(void* data, int length)
  889. {
  890. // does nothing
  891. return 0;
  892. }