DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

i_sound_win32.cpp (26837B)


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