the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at main 1078 lines 30 kB view raw
1#include "stdafx.h" 2#include "..\..\..\Minecraft.World\net.minecraft.world.entity.h" 3#include "..\..\..\Minecraft.World\Mth.h" 4#include "..\..\..\Minecraft.World\Random.h" 5#include "..\..\..\Minecraft.World\LevelData.h" 6#include "..\..\Minecraft.h" 7#include "..\..\MultiplayerLocalPlayer.h" 8#include "SoundEngine.h" 9#include "..\..\TexturePackRepository.h" 10#include "..\..\TexturePack.h" 11#include "..\..\Common\DLC\DLCAudioFile.h" 12#include "..\..\DLCTexturePack.h" 13 14 15IXAudio2* g_pXAudio2 = NULL; // pointer to XAudio2 instance used by QNet and XACT 16IXAudio2MasteringVoice* g_pXAudio2MasteringVoice = NULL; // pointer to XAudio2 mastering voice 17 18IXACT3Engine *SoundEngine::m_pXACT3Engine = NULL; 19IXACT3WaveBank *SoundEngine::m_pWaveBank = NULL; 20IXACT3WaveBank *SoundEngine::m_pWaveBank2 = NULL; 21IXACT3WaveBank *SoundEngine::m_pStreamedWaveBank = NULL; 22IXACT3WaveBank *SoundEngine::m_pStreamedWaveBankAdditional = NULL; 23IXACT3SoundBank *SoundEngine::m_pSoundBank = NULL; 24IXACT3SoundBank *SoundEngine::m_pSoundBank2 = NULL; 25CRITICAL_SECTION SoundEngine::m_CS; 26 27X3DAUDIO_HANDLE SoundEngine::m_xact3dInstance; 28vector<SoundEngine::soundInfo *> SoundEngine::currentSounds; 29X3DAUDIO_DSP_SETTINGS SoundEngine::m_DSPSettings; 30X3DAUDIO_EMITTER SoundEngine::m_emitter; 31X3DAUDIO_LISTENER SoundEngine::m_listeners[4]; 32int SoundEngine::m_validListenerCount = 0; 33 34X3DAUDIO_DISTANCE_CURVE_POINT SoundEngine::m_VolumeCurvePoints[2] = { 35 {0.0f, 1.0f}, 36 {1.0f, 0.0f}, 37}; 38 39X3DAUDIO_DISTANCE_CURVE_POINT SoundEngine::m_DragonVolumeCurvePoints[2] = { 40 {0.0f, 1.0f}, 41 {1.0f, 0.5f}, 42}; 43X3DAUDIO_DISTANCE_CURVE_POINT SoundEngine::m_VolumeCurvePointsNoDecay[2] = { 44 {0.0f, 1.0f}, 45 {1.0f, 1.0f}, 46}; 47 48X3DAUDIO_DISTANCE_CURVE SoundEngine::m_VolumeCurve; 49X3DAUDIO_DISTANCE_CURVE SoundEngine::m_DragonVolumeCurve; 50X3DAUDIO_DISTANCE_CURVE SoundEngine::m_VolumeCurveNoDecay; 51 52void SoundEngine::setXACTEngine( IXACT3Engine *pXACT3Engine) 53{ 54 m_pXACT3Engine = pXACT3Engine; 55} 56 57void SoundEngine::destroy() 58{ 59} 60 61SoundEngine::SoundEngine() 62{ 63 random = new Random(); 64 noMusicDelay = random->nextInt(20 * 60 * 10); 65 66 ZeroMemory(&m_MusicInfo,sizeof(soundInfo)); 67 //bIsPlayingStreamingCDMusic=false; 68 //m_bIsPlayingStreamingGameMusic=false; 69 SetIsPlayingEndMusic(false); 70 SetIsPlayingNetherMusic(false); 71 m_VolumeCurve.PointCount = 2; 72 m_VolumeCurve.pPoints = m_VolumeCurvePoints; 73 m_DragonVolumeCurve.PointCount = 2; 74 m_DragonVolumeCurve.pPoints = m_DragonVolumeCurvePoints; 75 m_VolumeCurveNoDecay.PointCount = 2; 76 m_VolumeCurveNoDecay.pPoints = m_VolumeCurvePointsNoDecay; 77 78 m_bStreamingMusicReady=false; 79 m_bStreamingWaveBank1Ready=false; 80 m_bStreamingWaveBank2Ready=false; 81} 82 83void SoundEngine::init(Options *pOptions) 84{ 85 InitializeCriticalSection(&m_CS); 86 87 // Iniatialise XACT itself 88 HRESULT hr; 89 if ( FAILED ( hr = XACT3CreateEngine( 0, &m_pXACT3Engine ) ) ) 90 { 91 app.FatalLoadError(); 92 assert( false ); 93 return; 94 } 95 96 // Load global settings file 97 // 4J-PB - move this to the title update, since we've corrected it to allow sounds to be pitch varied when they weren't before 98 HANDLE file; 99#ifdef _TU_BUILD 100 file = CreateFile("UPDATE:\\res\\audio\\Minecraft.xgs", GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 101#else 102 file = CreateFile("GAME:\\res\\TitleUpdate\\audio\\Minecraft.xgs", GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 103#endif 104 if( file == INVALID_HANDLE_VALUE ) 105 { 106 app.FatalLoadError(); 107 assert(false); 108 return; 109 } 110 DWORD dwFileSize = GetFileSize(file,NULL); 111 DWORD bytesRead = 0; 112 DWORD memFlags = MAKE_XALLOC_ATTRIBUTES(0,FALSE,TRUE,FALSE,0,XALLOC_PHYSICAL_ALIGNMENT_DEFAULT,XALLOC_MEMPROTECT_READWRITE,FALSE,XALLOC_MEMTYPE_PHYSICAL); 113 void *pvGlobalSettings = XMemAlloc(dwFileSize, memFlags); 114 ReadFile(file,pvGlobalSettings,dwFileSize,&bytesRead,NULL); 115 CloseHandle(file); 116 117 XACT_RUNTIME_PARAMETERS EngineParameters = {0}; 118 EngineParameters.lookAheadTime = XACT_ENGINE_LOOKAHEAD_DEFAULT; 119 EngineParameters.fnNotificationCallback = &this->XACTNotificationCallback; 120 EngineParameters.pGlobalSettingsBuffer = pvGlobalSettings; 121 EngineParameters.globalSettingsBufferSize = dwFileSize; 122 EngineParameters.globalSettingsFlags = XACT_FLAG_GLOBAL_SETTINGS_MANAGEDATA; 123 EngineParameters.pXAudio2 = g_pXAudio2; 124 EngineParameters.pMasteringVoice = g_pXAudio2MasteringVoice; 125 126 if ( FAILED ( hr = m_pXACT3Engine->Initialize( &EngineParameters ) ) ) 127 { 128 app.FatalLoadError(); 129 assert( false ); 130 return; 131 } 132 133 // printf("XACT initialisation complete\n"); 134 135 // Initialise X3D 136 XACT3DInitialize(m_pXACT3Engine,m_xact3dInstance); 137 138 // Set up common structures that can be re-used between sounds & just have required bits updated 139 memset(&m_DSPSettings,0,sizeof(X3DAUDIO_DSP_SETTINGS)); 140 WAVEFORMATEXTENSIBLE format; 141 m_pXACT3Engine->GetFinalMixFormat(&format); 142 m_DSPSettings.SrcChannelCount = 1; 143 m_DSPSettings.DstChannelCount = format.Format.nChannels; 144 // printf("%d channels\n", format.Format.nChannels); 145 m_DSPSettings.pMatrixCoefficients = new FLOAT32[m_DSPSettings.SrcChannelCount * m_DSPSettings.DstChannelCount]; 146 147 for( int i = 0; i < 4; i++ ) 148 { 149 memset(&m_listeners[i],0,sizeof(X3DAUDIO_LISTENER)); 150 m_listeners[i].OrientFront.z = 1.0f; 151 m_listeners[i].OrientTop.y = 1.0f; 152 } 153 m_validListenerCount = 1; 154 memset(&m_emitter,0,sizeof(X3DAUDIO_EMITTER)); 155 m_emitter.ChannelCount = 1; 156 m_emitter.pVolumeCurve = &m_VolumeCurve; 157 m_emitter.pLFECurve = &m_VolumeCurve; 158 m_emitter.CurveDistanceScaler = 16.0f; 159 m_emitter.OrientFront.z = 1.0f; 160 m_emitter.OrientTop.y = 1.0f; 161 162 // Create resident wave bank - leave memory for this managed by xact so it can free it 163 164 file = CreateFile("GAME:\\res\\audio\\resident.xwb", GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 165 if( file == INVALID_HANDLE_VALUE ) 166 { 167 app.FatalLoadError(); 168 assert(false); 169 return; 170 } 171 172 dwFileSize = GetFileSize(file,NULL); 173 void *pvWaveBank = XMemAlloc(dwFileSize, memFlags); 174 ReadFile(file,pvWaveBank,dwFileSize,&bytesRead,NULL); 175 CloseHandle(file); 176 177 if ( FAILED( hr = m_pXACT3Engine->CreateInMemoryWaveBank( pvWaveBank, dwFileSize, XACT_FLAG_ENGINE_CREATE_MANAGEDATA, memFlags, &m_pWaveBank ) ) ) 178 { 179 app.FatalLoadError(); 180 assert(false); 181 return; 182 } 183 184 // 4J-PB - add new sounds wavebank 185#ifdef _TU_BUILD 186 file = CreateFile("UPDATE:\\res\\audio\\additional.xwb", GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 187#else 188 file = CreateFile("GAME:\\res\\TitleUpdate\\audio\\additional.xwb", GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 189#endif 190 if( file == INVALID_HANDLE_VALUE ) 191 { 192 app.FatalLoadError(); 193 assert(false); 194 return; 195 } 196 197 dwFileSize = GetFileSize(file,NULL); 198 void *pvWaveBank2 = XMemAlloc(dwFileSize, memFlags); 199 ReadFile(file,pvWaveBank2,dwFileSize,&bytesRead,NULL); 200 CloseHandle(file); 201 202 if ( FAILED( hr = m_pXACT3Engine->CreateInMemoryWaveBank( pvWaveBank2, dwFileSize, XACT_FLAG_ENGINE_CREATE_MANAGEDATA, memFlags, &m_pWaveBank2 ) ) ) 203 { 204 app.FatalLoadError(); 205 assert(false); 206 return; 207 } 208 209 // Create streamed sound bank 210 211 file = CreateFile("GAME:\\res\\audio\\streamed.xwb", GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING, NULL); 212 213 if( file == INVALID_HANDLE_VALUE ) 214 { 215 app.FatalLoadError(); 216 assert(false); 217 return; 218 } 219 220 XACT_WAVEBANK_STREAMING_PARAMETERS streamParams; 221 streamParams.file = file; 222 streamParams.offset = 0; 223 streamParams.flags = 0; 224 streamParams.packetSize = 16; // Not sure what to pick for this - suggests a "multiple of 16" for DVD playback 225 226 if ( FAILED( hr = m_pXACT3Engine->CreateStreamingWaveBank( &streamParams, &m_pStreamedWaveBank ) ) ) 227 { 228 app.FatalLoadError(); 229 assert(false); 230 return; 231 } 232 233 // Create streamed sound bank 234 235 //file = CreateFile("GAME:\\res\\audio\\AdditionalMusic.xwb", GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING, NULL); 236#ifdef _TU_BUILD 237 file = CreateFile("UPDATE:\\res\\audio\\AdditionalMusic.xwb", GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 238#else 239 file = CreateFile("GAME:\\res\\TitleUpdate\\audio\\AdditionalMusic.xwb", GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 240#endif 241 if( file == INVALID_HANDLE_VALUE ) 242 { 243 app.FatalLoadError(); 244 assert(false); 245 return; 246 } 247 248 streamParams.file = file; 249 streamParams.offset = 0; 250 streamParams.flags = 0; 251 streamParams.packetSize = 16; // Not sure what to pick for this - suggests a "multiple of 16" for DVD playback 252 253 if ( FAILED( hr = m_pXACT3Engine->CreateStreamingWaveBank( &streamParams, &m_pStreamedWaveBankAdditional ) ) ) 254 { 255 app.FatalLoadError(); 256 assert(false); 257 return; 258 } 259 260 // Create sound bank - leave memory for this managed by xact so it can free it 261 // 4J-PB - updated for the TU 262 //file = CreateFile("GAME:\\res\\audio\\minecraft.xsb", GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 263#ifdef _TU_BUILD 264 file = CreateFile("UPDATE:\\res\\audio\\minecraft.xsb", GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 265#else 266 file = CreateFile("GAME:\\res\\TitleUpdate\\audio\\minecraft.xsb", GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 267#endif 268 if( file == INVALID_HANDLE_VALUE ) 269 { 270 app.FatalLoadError(); 271 assert(false); 272 return; 273 } 274 dwFileSize = GetFileSize(file,NULL); 275 void *pvSoundBank = XMemAlloc(dwFileSize, memFlags); 276 ReadFile(file,pvSoundBank,dwFileSize,&bytesRead,NULL); 277 CloseHandle(file); 278 279 if ( FAILED( hr = m_pXACT3Engine->CreateSoundBank( pvSoundBank, dwFileSize, XACT_FLAG_ENGINE_CREATE_MANAGEDATA, memFlags, &m_pSoundBank ) ) ) 280 { 281 app.FatalLoadError(); 282 assert(false); 283 return; 284 } 285 286 // Create sound bank2 - leave memory for this managed by xact so it can free it 287 288#ifdef _TU_BUILD 289 file = CreateFile("UPDATE:\\res\\audio\\additional.xsb", GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 290#else 291 file = CreateFile("GAME:\\res\\TitleUpdate\\audio\\additional.xsb", GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 292#endif 293 if( file == INVALID_HANDLE_VALUE ) 294 { 295 app.FatalLoadError(); 296 assert(false); 297 return; 298 } 299 dwFileSize = GetFileSize(file,NULL); 300 void *pvSoundBank2 = XMemAlloc(dwFileSize, memFlags); 301 ReadFile(file,pvSoundBank2,dwFileSize,&bytesRead,NULL); 302 CloseHandle(file); 303 304 if ( FAILED( hr = m_pXACT3Engine->CreateSoundBank( pvSoundBank2, dwFileSize, XACT_FLAG_ENGINE_CREATE_MANAGEDATA, memFlags, &m_pSoundBank2 ) ) ) 305 { 306 app.FatalLoadError(); 307 assert(false); 308 return; 309 } 310 311 XACT_NOTIFICATION_DESCRIPTION desc = {0}; 312 desc.flags = XACT_FLAG_NOTIFICATION_PERSIST; 313 desc.type = XACTNOTIFICATIONTYPE_WAVEBANKPREPARED; 314 desc.pvContext=this; 315 m_pXACT3Engine->RegisterNotification(&desc); 316 317 // get the category to manage the sfx (Default) 318 m_xactSFX = m_pXACT3Engine->GetCategory("Default"); 319 m_xactMusic = m_pXACT3Engine->GetCategory("Music"); 320} 321 322void SoundEngine::CreateStreamingWavebank(const char *pchName, IXACT3WaveBank **ppStreamedWaveBank) 323{ 324 // Create streamed sound bank 325 HRESULT hr; 326 327 HANDLE file = CreateFile(pchName, GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING, NULL); 328 329 if( file == INVALID_HANDLE_VALUE ) 330 { 331 app.FatalLoadError(); 332 assert(false); 333 return; 334 } 335 336 XACT_WAVEBANK_STREAMING_PARAMETERS streamParams; 337 streamParams.file = file; 338 streamParams.offset = 0; 339 streamParams.flags = 0; 340 streamParams.packetSize = 16; // Not sure what to pick for this - suggests a "multiple of 16" for DVD playback 341 342 if ( FAILED( hr = m_pXACT3Engine->CreateStreamingWaveBank( &streamParams, ppStreamedWaveBank ) ) ) 343 { 344 app.FatalLoadError(); 345 assert(false); 346 return; 347 } 348} 349 350void SoundEngine::CreateSoundbank(const char *pchName, IXACT3SoundBank **ppSoundBank) 351{ 352 HRESULT hr; 353 HANDLE file = CreateFile(pchName, GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 354 355 if( file == INVALID_HANDLE_VALUE ) 356 { 357 app.FatalLoadError(); 358 assert(false); 359 return; 360 } 361 DWORD dwFileSize = GetFileSize(file,NULL); 362 DWORD bytesRead = 0; 363 DWORD memFlags = MAKE_XALLOC_ATTRIBUTES(0,FALSE,TRUE,FALSE,0,XALLOC_PHYSICAL_ALIGNMENT_DEFAULT,XALLOC_MEMPROTECT_READWRITE,FALSE,XALLOC_MEMTYPE_PHYSICAL); 364 void *pvSoundBank = XMemAlloc(dwFileSize, memFlags); 365 ReadFile(file,pvSoundBank,dwFileSize,&bytesRead,NULL); 366 CloseHandle(file); 367 368 if ( FAILED( hr = m_pXACT3Engine->CreateSoundBank( pvSoundBank, dwFileSize, XACT_FLAG_ENGINE_CREATE_MANAGEDATA, memFlags, ppSoundBank ) ) ) 369 { 370 app.FatalLoadError(); 371 assert(false); 372 return; 373 } 374} 375 376bool SoundEngine::isStreamingWavebankReady() 377{ 378 if(m_bStreamingMusicReady==false) 379 { 380 DWORD dwState; 381 m_pSoundBank->GetState(&dwState); 382 if(dwState&XACT_WAVEBANKSTATE_PREPARED) 383 { 384 m_bStreamingWaveBank1Ready=true; 385 } 386 m_pSoundBank2->GetState(&dwState); 387 if(dwState&XACT_WAVEBANKSTATE_PREPARED) 388 { 389 m_bStreamingWaveBank2Ready=true; 390 } 391 392 if(m_bStreamingWaveBank1Ready && m_bStreamingWaveBank2Ready) 393 { 394 m_bStreamingMusicReady=true; 395 } 396 } 397 398 return m_bStreamingMusicReady; 399} 400 401#ifdef _XBOX 402bool SoundEngine::isStreamingWavebankReady(IXACT3WaveBank *pWaveBank) 403{ 404 DWORD dwState; 405 pWaveBank->GetState(&dwState); 406 if(dwState&XACT_WAVEBANKSTATE_PREPARED) 407 { 408 return true; 409 } 410 else 411 { 412 return false; 413 } 414} 415#endif 416 417void SoundEngine::XACTNotificationCallback( const XACT_NOTIFICATION* pNotification ) 418{ 419 if(pNotification->pvContext!= NULL) 420 { 421 if(pNotification->type==XACTNOTIFICATIONTYPE_WAVEBANKPREPARED) 422 { 423 SoundEngine *pSoundEngine=(SoundEngine *)pNotification->pvContext; 424 if(pNotification->waveBank.pWaveBank==pSoundEngine->m_pStreamedWaveBank) 425 { 426 pSoundEngine->m_bStreamingWaveBank1Ready=true; 427 } 428 if(pNotification->waveBank.pWaveBank==pSoundEngine->m_pStreamedWaveBankAdditional) 429 { 430 pSoundEngine->m_bStreamingWaveBank2Ready=true; 431 } 432 433 if(pSoundEngine->m_bStreamingWaveBank1Ready && pSoundEngine->m_bStreamingWaveBank2Ready) 434 { 435 pSoundEngine->m_bStreamingMusicReady=true; 436 } 437 } 438 } 439} 440 441char *SoundEngine::ConvertSoundPathToName(const wstring& name, bool bConvertSpaces) 442{ 443 static char buf[256]; 444 assert(name.length()<256); 445 for(unsigned int i = 0; i < name.length(); i++ ) 446 { 447 wchar_t c = name[i]; 448 if(c=='.') c='_'; 449 buf[i] = (char)c; 450 } 451 buf[name.length()] = 0; 452 return buf; 453} 454 455void SoundEngine::play(int iSound, float x, float y, float z, float volume, float pitch) 456{ 457 if(iSound==-1) 458 { 459 app.DebugPrintf(6,"PlaySound with sound of -1 !!!!!!!!!!!!!!!\n"); 460 return; 461 } 462 463 bool bSoundbank1=(iSound<=eSoundType_STEP_SAND); 464 465 if( (m_pSoundBank == NULL ) || (m_pSoundBank2 == NULL))return; 466 467 if( currentSounds.size() > MAX_POLYPHONY ) 468 { 469 return; 470 } 471 wstring name = wchSoundNames[iSound]; 472 //const unsigned char *name=ucSoundNames[iSound]; 473 474 char *xboxName = ConvertSoundPathToName(name); 475 XACTINDEX idx; 476 477 if(bSoundbank1) 478 { 479 idx = m_pSoundBank->GetCueIndex(xboxName); 480 } 481 else 482 { 483 idx = m_pSoundBank2->GetCueIndex(xboxName); 484 } 485 486 if( idx == XACTINDEX_INVALID ) 487 { 488#ifndef _CONTENT_PACKAGE 489#ifdef _DEBUG 490 __debugbreak(); 491#endif 492 //wprintf(L"WARNING: Sound cue not found - %ls\n", name.c_str() ); 493 app.DebugPrintf("Not found: %s\n",xboxName); 494#endif 495 return; 496 } 497 498 // 4J-PB - check how many of this cue are already playing and ignore if there are loads 499 int iSameSoundC=0; 500 for( unsigned int i = 0; i < currentSounds.size(); i++ ) 501 { 502 SoundEngine::soundInfo *info = currentSounds[i]; 503 504 if((info->idx==idx) && (info->iSoundBank==(bSoundbank1?0:1))) 505 { 506 iSameSoundC++; 507 } 508 } 509 510 if(iSameSoundC>MAX_SAME_SOUNDS_PLAYING) 511 { 512 return; 513 } 514 515 IXACT3Cue *cueInstance; 516 HRESULT hr; 517 MemSect(31); 518 519 if(bSoundbank1) 520 { 521 if( FAILED( hr = m_pSoundBank->Prepare(idx, 0, 0, &cueInstance ) ) ) 522 { 523 MemSect(0); 524 // printf("Sound prep failed\n"); 525 return; 526 } 527 } 528 else 529 { 530 if( FAILED( hr = m_pSoundBank2->Prepare(idx, 0, 0, &cueInstance ) ) ) 531 { 532 MemSect(0); 533 // printf("Sound prep failed\n"); 534 return; 535 } 536 } 537 538 MemSect(0); 539 540 // Register to receive callbacks for cues stopping so we can keep a track of active sounds 541 542 soundInfo *info = new soundInfo(); 543 info->idx = idx; 544 info->eSoundID = (eSOUND_TYPE)iSound; 545 info->iSoundBank = bSoundbank1?0:1; 546 info->x = x; 547 info->y = y; 548 info->z = z; 549 info->volume = volume;//*m_fSoundEffectsVolume; 550 info->pitch = pitch; 551 info->pCue = cueInstance; 552 info->updatePos = true; 553 EnterCriticalSection(&m_CS); 554 currentSounds.push_back(info); 555 LeaveCriticalSection(&m_CS); 556 557 XACTVARIABLEINDEX vidx = cueInstance->GetVariableIndex("Pitch"); 558 if( vidx != XACTVARIABLEINDEX_INVALID ) 559 { 560 // Convert pitch multiplier to semitones 561 float semiTones = (log(pitch)/log(2.0f)) * 12.0f; 562 cueInstance->SetVariable( vidx, semiTones ); 563 } 564 565 update3DPosition(info); 566 cueInstance->Play(); 567} 568 569void SoundEngine::playUI(int iSound, float, float) 570{ 571 bool bSoundBank1=(iSound<=eSoundType_STEP_SAND); 572 573 if( (m_pSoundBank == NULL ) || (m_pSoundBank2 == NULL)) return; 574 575 if( currentSounds.size() > MAX_POLYPHONY ) 576 { 577 return; 578 } 579 wstring name = wchSoundNames[iSound]; 580 581 char *xboxName = (char *)ConvertSoundPathToName(name); 582 583 XACTINDEX idx = m_pSoundBank->GetCueIndex(xboxName); 584 585 if( idx == XACTINDEX_INVALID ) 586 { 587 // check soundbank 2 588 idx = m_pSoundBank2->GetCueIndex(xboxName); 589 if( idx == XACTINDEX_INVALID ) 590 { 591#ifndef _CONTENT_PACKAGE 592 printf("Not found UI: %s\n",xboxName); 593#endif 594 return; 595 } 596 bSoundBank1=false; 597 } 598 599 IXACT3Cue *cueInstance; 600 HRESULT hr; 601 602 if(bSoundBank1) 603 { 604 if( FAILED( hr = m_pSoundBank->Prepare(idx, 0, 0, &cueInstance ) ) ) 605 { 606 // printf("Sound prep failed\n"); 607 return; 608 } 609 } 610 else 611 { 612 if( FAILED( hr = m_pSoundBank2->Prepare(idx, 0, 0, &cueInstance ) ) ) 613 { 614 // printf("Sound prep failed\n"); 615 return; 616 } 617 } 618 619 // Add sound info just so we can detect end of this sound 620 soundInfo *info = new soundInfo(); 621 info->eSoundID = (eSOUND_TYPE)0; 622 info->iSoundBank = bSoundBank1?0:1; 623 info->idx =idx; 624 info->x = 0.0f; 625 info->y = 0.0f; 626 info->z = 0.0f; 627 info->volume = 0.0f; 628 info->pitch = 0.0f; 629 info->pCue = cueInstance; 630 info->updatePos = false; 631 EnterCriticalSection(&m_CS); 632 currentSounds.push_back(info); 633 LeaveCriticalSection(&m_CS); 634 635 cueInstance->Play(); 636} 637 638void SoundEngine::playStreaming(const wstring& name, float x, float y, float z, float vol, float pitch, bool bMusicDelay) 639{ 640 IXACT3SoundBank *pSoundBank=NULL; 641 642 bool bSoundBank2=false; 643 MemSect(34); 644 if(m_MusicInfo.pCue!=NULL) 645 { 646 m_MusicInfo.pCue->Stop(0); 647 m_MusicInfo.pCue->Destroy(); 648 m_MusicInfo.pCue = NULL; 649 } 650 651 m_MusicInfo.volume = 1.0f;//m_fMusicVolume; 652 m_MusicInfo.pitch = 1.0f; 653 654 SetIsPlayingEndMusic(false); 655 SetIsPlayingNetherMusic(false); 656 657 if(name.empty()) 658 { 659 SetIsPlayingStreamingCDMusic(false); 660 SetIsPlayingStreamingGameMusic(false);// will be set to true when the sound is started in the tick 661 if(bMusicDelay) 662 { 663 noMusicDelay = random->nextInt(20 * 60 * 10) + 20 * 60 * 10; 664 } 665 else 666 { 667 noMusicDelay=0; 668 } 669 // Check if we have a local player in The Nether or in The End, and play that music if they are 670 Minecraft *pMinecraft=Minecraft::GetInstance(); 671 bool playerInEnd=false; 672 bool playerInNether=false; 673 674 for(unsigned int i=0;i<XUSER_MAX_COUNT;i++) 675 { 676 if(pMinecraft->localplayers[i]!=NULL) 677 { 678 if(pMinecraft->localplayers[i]->dimension==LevelData::DIMENSION_END) 679 { 680 playerInEnd=true; 681 } 682 else if(pMinecraft->localplayers[i]->dimension==LevelData::DIMENSION_NETHER) 683 { 684 playerInNether=true; 685 } 686 } 687 } 688 TexturePack *pTexPack=Minecraft::GetInstance()->skins->getSelected(); 689 690 if(Minecraft::GetInstance()->skins->isUsingDefaultSkin() || pTexPack->hasAudio()==false) 691 { 692 if(playerInEnd || playerInNether) 693 { 694 pSoundBank=m_pSoundBank2; 695 } 696 else 697 { 698 pSoundBank=m_pSoundBank; 699 } 700 } 701 else 702 { 703 // get the dlc texture pack 704 DLCTexturePack *pDLCTexPack=(DLCTexturePack *)pTexPack; 705 pSoundBank=pDLCTexPack->m_pSoundBank; 706 707 // check we can play the sound 708 if(isStreamingWavebankReady(pDLCTexPack->m_pStreamedWaveBank)==false) 709 { 710 return; 711 } 712 } 713 714 if(playerInEnd) 715 { 716 m_musicIDX = pSoundBank->GetCueIndex("the_end_dragon"); 717 SetIsPlayingEndMusic(true); 718 bSoundBank2=true; 719 } 720 else if(playerInNether) 721 { 722 m_musicIDX = pSoundBank->GetCueIndex("nether"); 723 SetIsPlayingNetherMusic(true); 724 bSoundBank2=true; 725 } 726 else 727 { 728 m_musicIDX = pSoundBank->GetCueIndex("music"); 729 } 730 } 731 else 732 { 733 pSoundBank=m_pSoundBank; 734 SetIsPlayingStreamingCDMusic(true); 735 SetIsPlayingStreamingGameMusic(false); 736 737 m_musicIDX = pSoundBank->GetCueIndex(ConvertSoundPathToName(name)); 738 } 739 740 HRESULT hr; 741 742 if( FAILED( hr = pSoundBank->Prepare(m_musicIDX, 0, 0, &m_MusicInfo.pCue ) ) ) 743 { 744 // printf("Sound prep failed\n"); 745 m_musicIDX = XACTINDEX_INVALID; // don't do anything in the tick 746 m_MusicInfo.pCue=NULL; 747 MemSect(0); 748 return; 749 } 750 751 752 if(GetIsPlayingStreamingCDMusic()) 753 { 754 m_MusicInfo.x = x; 755 m_MusicInfo.y = y; 756 m_MusicInfo.z = z; 757 m_MusicInfo.updatePos = true; 758 update3DPosition(&m_MusicInfo, false); 759 m_MusicInfo.pCue->Play(); 760 } 761 else 762 { 763 // don't play the game music - it will start playing in the tick when noMusicDelay is 0 764 765 m_MusicInfo.x = 0.0f; // will be overridden by the bPlaceEmitterAtListener 766 m_MusicInfo.y = 0.0f; // will be overridden by the bPlaceEmitterAtListener 767 m_MusicInfo.z = 0.0f; // will be overridden by the bPlaceEmitterAtListener 768 m_MusicInfo.updatePos = false; 769 770 update3DPosition(&m_MusicInfo, true); 771 } 772 773 MemSect(0); 774} 775void SoundEngine::playMusicTick() 776{ 777 if( (m_pSoundBank == NULL ) || (m_pSoundBank2 == NULL)) return; 778 779 if( m_musicIDX == XACTINDEX_INVALID ) 780 { 781 // printf("Not found music\n"); 782 return; 783 } 784 785 // check to see if the sound has stopped playing 786 DWORD state; 787 HRESULT hr; 788 if(m_MusicInfo.pCue!=NULL) 789 { 790 if( FAILED( hr = m_MusicInfo.pCue->GetState(&state) ) ) 791 { 792 assert(false); 793 } 794 else 795 { 796 if( state == XACT_CUESTATE_STOPPED ) 797 { 798 // remove the sound and reset the music 799 playStreaming(L"", 0, 0, 0, 0, 0); 800 return; 801 } 802 } 803 } 804 805 if(GetIsPlayingStreamingGameMusic()) 806 { 807 if(m_MusicInfo.pCue!=NULL) 808 { 809 bool playerInEnd = false; 810 bool playerInNether=false; 811 Minecraft *pMinecraft = Minecraft::GetInstance(); 812 for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) 813 { 814 if(pMinecraft->localplayers[i]!=NULL) 815 { 816 if(pMinecraft->localplayers[i]->dimension==LevelData::DIMENSION_END) 817 { 818 playerInEnd=true; 819 } 820 else if(pMinecraft->localplayers[i]->dimension==LevelData::DIMENSION_NETHER) 821 { 822 playerInNether=true; 823 } 824 } 825 } 826 827 if((playerInEnd && !GetIsPlayingEndMusic()) ||(!playerInEnd && GetIsPlayingEndMusic())) 828 { 829 // remove the sound and reset the music 830 playStreaming(L"", 0, 0, 0, 0, 0); 831 } 832 else if ((playerInNether && !GetIsPlayingNetherMusic()) ||(!playerInNether && GetIsPlayingNetherMusic())) 833 { 834 // remove the sound and reset the music 835 playStreaming(L"", 0, 0, 0, 0, 0); 836 } 837 } 838 // not positional so doesn't need ticked 839 return; 840 } 841 842 // is this cd music? If so, we need to tick it 843 if(GetIsPlayingStreamingCDMusic()) 844 { 845 update3DPosition(&m_MusicInfo, false, true); 846 } 847 else 848 { 849 if (noMusicDelay > 0) 850 { 851 noMusicDelay--; 852 return; 853 } 854 855 if(m_MusicInfo.pCue!=NULL) 856 { 857 update3DPosition(&m_MusicInfo, true); 858 SetIsPlayingStreamingGameMusic(true); 859 // and play the game music here 860 m_MusicInfo.pCue->Play(); 861 } 862 } 863} 864 865void SoundEngine::updateMusicVolume(float fVal) 866{ 867 XACTVOLUME xactVol=fVal; 868 HRESULT hr=m_pXACT3Engine->SetVolume(m_xactMusic,fVal); 869} 870 871void SoundEngine::updateSystemMusicPlaying(bool isPlaying) 872{ 873} 874 875void SoundEngine::updateSoundEffectVolume(float fVal) 876{ 877 XACTVOLUME xactVol=fVal; 878 HRESULT hr=m_pXACT3Engine->SetVolume(m_xactSFX,fVal); 879} 880 881void SoundEngine::update3DPosition(SoundEngine::soundInfo *pInfo, bool bPlaceEmitterAtListener,bool bIsCDMusic) 882{ 883 X3DAUDIO_LISTENER *listener = &m_listeners[0]; // Default case for single listener 884 885 if( ( m_validListenerCount > 1 ) && !bPlaceEmitterAtListener ) 886 { 887 // More than one listener. Find out which one is closest 888 float nearDistSq = ( listener->Position.x - pInfo->x ) * ( listener->Position.x - pInfo->x ) + 889 ( listener->Position.y - pInfo->y ) * ( listener->Position.y - pInfo->y ) + 890 ( listener->Position.z + pInfo->z ) * ( listener->Position.z + pInfo->z ); 891 892 for( int i = 1; i < m_validListenerCount; i++ ) 893 { 894 float distSq = ( m_listeners[i].Position.x - pInfo->x ) * ( m_listeners[i].Position.x - pInfo->x ) + 895 ( m_listeners[i].Position.y - pInfo->y ) * ( m_listeners[i].Position.y - pInfo->y ) + 896 ( m_listeners[i].Position.z + pInfo->z ) * ( m_listeners[i].Position.z + pInfo->z ); 897 if( distSq < nearDistSq ) 898 { 899 listener = &m_listeners[i]; 900 nearDistSq = distSq; 901 } 902 } 903 904 // More than one listener, don't do directional sounds - point our listener towards the sound 905 float xzDist = sqrtf( ( listener->Position.x - pInfo->x ) * ( listener->Position.x - pInfo->x ) + 906 ( listener->Position.z + pInfo->z ) * ( listener->Position.z + pInfo->z ) ); 907 // Don't orientate if its too near to work out a distance 908 if( xzDist > 0.001f) 909 { 910 listener->OrientFront.x = ( pInfo->x - listener->Position.x ) / xzDist; 911 listener->OrientFront.y = 0.0f; 912 listener->OrientFront.z = ( - pInfo->z - listener->Position.z ) / xzDist; 913 } 914 } 915 916 if(bPlaceEmitterAtListener) 917 { 918 m_emitter.Position.x = listener->Position.x; 919 m_emitter.Position.y = listener->Position.y; 920 m_emitter.Position.z = listener->Position.z; 921 } 922 else 923 { 924 // Update the position of the emitter - we aren't dynamically changing anything else 925 m_emitter.Position.x = pInfo->x; 926 m_emitter.Position.y = pInfo->y; 927 m_emitter.Position.z = -pInfo->z; // Flipped sign of z as x3daudio is expecting left handed coord system 928 } 929 930 // If this is the CD music, then make the distance scaler 4 x normal 931 if(bIsCDMusic) 932 { 933 m_emitter.CurveDistanceScaler=64.0f; 934 } 935 else 936 { 937 switch(pInfo->eSoundID) 938 { 939 // Is this the Dragon? 940 case eSoundType_MOB_ENDERDRAGON_GROWL: 941 case eSoundType_MOB_ENDERDRAGON_MOVE: 942 case eSoundType_MOB_ENDERDRAGON_END: 943 case eSoundType_MOB_ENDERDRAGON_HIT: 944 m_emitter.CurveDistanceScaler=100.0f; 945 break; 946 case eSoundType_MOB_GHAST_MOAN: 947 case eSoundType_MOB_GHAST_SCREAM: 948 case eSoundType_MOB_GHAST_DEATH: 949 case eSoundType_MOB_GHAST_CHARGE: 950 case eSoundType_MOB_GHAST_FIREBALL: 951 m_emitter.CurveDistanceScaler=30.0f; 952 break; 953 } 954 } 955 956 // 10000.0f is passed as the volume for thunder... treat this as a special case, and use a volume curve that doesn't decay with distance 957 // rather than just trying to guess at making something really really loud... 958 if( pInfo->volume == 10000.0f ) 959 { 960 m_emitter.pVolumeCurve = &m_VolumeCurveNoDecay; 961 } 962 else 963 { 964 m_emitter.pVolumeCurve = &m_VolumeCurve; 965 } 966 967 // Calculate all the 3D things 968 XACT3DCalculate( m_xact3dInstance, listener, &m_emitter, &m_DSPSettings ); 969 970 // Put volume curve back to default in case something else is depending on this 971 m_emitter.pVolumeCurve = &m_VolumeCurve; 972 //m_emitter.pLFECurve = &m_VolumeCurve; 973 m_emitter.CurveDistanceScaler=16.0f; 974 // Apply our general volume too by scaling the calculated coefficients - so long as this isn't our special case of 10000.0f (see comment above) 975 if( pInfo->volume != 10000.0f ) 976 { 977 for(unsigned int i = 0; i < m_DSPSettings.DstChannelCount; i++ ) 978 { 979 m_DSPSettings.pMatrixCoefficients[i] *= pInfo->volume; 980 } 981 } 982 983 // Finally apply to the cue 984 XACT3DApply( &m_DSPSettings, pInfo->pCue); 985} 986 987void SoundEngine::tick(shared_ptr<Mob> *players, float a) 988{ 989 if( m_pXACT3Engine == NULL ) return; 990 991 // Creater listener array from the local players 992 int listenerCount = 0; 993 bool doPosUpdate = true; 994 if( players ) 995 { 996 for( int i = 0; i < 4; i++ ) 997 { 998 if( players[i] != NULL ) 999 { 1000 float yRot = players[i]->yRotO + (players[i]->yRot - players[i]->yRotO) * a; 1001 1002 m_listeners[listenerCount].Position.x = (float) (players[i]->xo + (players[i]->x - players[i]->xo) * a); 1003 m_listeners[listenerCount].Position.y = (float) (players[i]->yo + (players[i]->y - players[i]->yo) * a); 1004 m_listeners[listenerCount].Position.z = -(float) (players[i]->zo + (players[i]->z - players[i]->zo) * a); // Flipped sign of z as x3daudio is expecting left handed coord system 1005 1006 float yCos = (float)cos(-yRot * Mth::RAD_TO_GRAD - PI); 1007 float ySin = (float)sin(-yRot * Mth::RAD_TO_GRAD - PI); 1008 1009 m_listeners[listenerCount].OrientFront.x = -ySin; 1010 m_listeners[listenerCount].OrientFront.y = 0; 1011 m_listeners[listenerCount].OrientFront.z = yCos; // Flipped sign of z as x3daudio is expecting left handed coord system 1012 1013 listenerCount++; 1014 } 1015 } 1016 } 1017 // If there were no valid players set, make up a default listener 1018 if( listenerCount == 0 ) 1019 { 1020 doPosUpdate = false; // Don't bother updating positions of sounds already placed 1021 m_listeners[listenerCount].Position.x = 0; 1022 m_listeners[listenerCount].Position.y = 0; 1023 m_listeners[listenerCount].Position.z = 0; 1024 m_listeners[listenerCount].OrientFront.x = 0; 1025 m_listeners[listenerCount].OrientFront.y = 0; 1026 m_listeners[listenerCount].OrientFront.z = 1.0f; 1027 listenerCount++; 1028 } 1029 m_validListenerCount = listenerCount; 1030 1031 EnterCriticalSection(&m_CS); 1032 for( unsigned int i = 0; i < currentSounds.size(); i++ ) 1033 { 1034 SoundEngine::soundInfo *info = currentSounds[i]; 1035 1036 DWORD state; 1037 HRESULT hr; 1038 if( FAILED( hr = info->pCue->GetState(&state) ) ) 1039 { 1040 assert(false); 1041 } 1042 else 1043 { 1044 if( state == XACT_CUESTATE_STOPPED ) 1045 { 1046 info->pCue->Destroy(); 1047 delete currentSounds[i]; 1048 currentSounds[i] = currentSounds.back(); 1049 currentSounds.pop_back(); 1050 } 1051 else 1052 { 1053 if( info->updatePos ) 1054 { 1055 if( doPosUpdate ) 1056 { 1057 update3DPosition(info); 1058 } 1059 } 1060 } 1061 } 1062 } 1063 1064 LeaveCriticalSection(&m_CS); 1065 m_pXACT3Engine->DoWork(); 1066} 1067 1068void SoundEngine::add(const wstring& name, File *file) 1069{ 1070} 1071 1072void SoundEngine::addMusic(const wstring& name, File *file) 1073{ 1074} 1075 1076void SoundEngine::addStreaming(const wstring& name, File *file) 1077{ 1078}