Something went wrong. Try again.
the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
Something went wrong. Try again.
49 kB · 1716 lines
C++
at master
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717#include "stdafx.h"
#include "SoundEngine.h"#include "..\Consoles_App.h"#include "..\..\MultiplayerLocalPlayer.h"#include "..\..\..\Minecraft.World\net.minecraft.world.level.h"#include "..\..\Minecraft.World\leveldata.h"#include "..\..\Minecraft.World\mth.h"#include "..\..\TexturePackRepository.h"#include "..\..\DLCTexturePack.h"#include "Common\DLC\DLCAudioFile.h"
#ifdef __PSVITA__#include <audioout.h>#endif
#ifdef _WINDOWS64#include "..\..\Minecraft.Client\Windows64\Windows64_App.h"#include "..\..\Minecraft.Client\Windows64\Miles\include\imssapi.h"#endif
#ifdef __ORBIS__#include <audioout.h>//#define __DISABLE_MILES__ // MGH disabled for now as it crashes if we call sceNpMatching2Initialize#endif
// take out Orbis until they are done#if defined _XBOX
SoundEngine::SoundEngine() {}void SoundEngine::init(Options *pOptions){}
void SoundEngine::tick(shared_ptr<Mob> *players, float a){}void SoundEngine::destroy() {}void SoundEngine::play(int iSound, float x, float y, float z, float volume, float pitch){ app.DebugPrintf("PlaySound - %d\n",iSound);}void SoundEngine::playStreaming(const wstring& name, float x, float y , float z, float volume, float pitch, bool bMusicDelay) {}void SoundEngine::playUI(int iSound, float volume, float pitch) {}
void SoundEngine::updateMusicVolume(float fVal) {}void SoundEngine::updateSoundEffectVolume(float fVal) {}
void SoundEngine::add(const wstring& name, File *file) {}void SoundEngine::addMusic(const wstring& name, File *file) {}void SoundEngine::addStreaming(const wstring& name, File *file) {}char *SoundEngine::ConvertSoundPathToName(const wstring& name, bool bConvertSpaces) { return NULL; }bool SoundEngine::isStreamingWavebankReady() { return true; }void SoundEngine::playMusicTick() {};
#else
#ifdef _WINDOWS64char SoundEngine::m_szSoundPath[]={"Windows64Media\\Sound\\"};char SoundEngine::m_szMusicPath[]={"music\\"};char SoundEngine::m_szRedistName[]={"redist64"};#elif defined _DURANGOchar SoundEngine::m_szSoundPath[]={"Sound\\"};char SoundEngine::m_szMusicPath[]={"music\\"};char SoundEngine::m_szRedistName[]={"redist64"};#elif defined __ORBIS__
#ifdef _CONTENT_PACKAGEchar SoundEngine::m_szSoundPath[]={"Sound/"};#elif defined _ART_BUILDchar SoundEngine::m_szSoundPath[]={"Sound/"};#else// just use the host Durango folder for the sound. In the content package, we'll have moved this in the .gp4 filechar SoundEngine::m_szSoundPath[]={"Durango/Sound/"};#endifchar SoundEngine::m_szMusicPath[]={"music/"};char SoundEngine::m_szRedistName[]={"redist64"};#elif defined __PSVITA__char SoundEngine::m_szSoundPath[]={"PSVita/Sound/"};char SoundEngine::m_szMusicPath[]={"music/"};char SoundEngine::m_szRedistName[]={"redist"};#elif defined __PS3__//extern const char* getPS3HomePath();char SoundEngine::m_szSoundPath[]={"PS3/Sound/"};char SoundEngine::m_szMusicPath[]={"music/"};char SoundEngine::m_szRedistName[]={"redist"};
#define USE_SPURS
#ifdef USE_SPURS#include <cell/spurs.h>#else#include <sys/spu_image.h>#endif
#endif
F32 AILCALLBACK custom_falloff_function (HSAMPLE S, F32 distance, F32 rolloff_factor, F32 min_dist, F32 max_dist);
char *SoundEngine::m_szStreamFileA[eStream_Max]={ "calm1", "calm2", "calm3", "hal1", "hal2", "hal3", "hal4", "nuance1", "nuance2",#ifndef _XBOX // add the new music tracks "creative1", "creative2", "creative3", "creative4", "creative5", "creative6", "menu1", "menu2", "menu3", "menu4",#endif "piano1", "piano2", "piano3",
// Nether "nether1", "nether2", "nether3", "nether4", // The End "the_end_dragon_alive", "the_end_end", // CDs "11", "13", "blocks", "cat", "chirp", "far", "mall", "mellohi", "stal", "strad", "ward", "where_are_we_now"};
///////////////////////////////////////////////// ErrorCallback///////////////////////////////////////////////void AILCALL ErrorCallback(S64 i_Id, char const* i_Details){ char *pchLastError=AIL_last_error();
if(pchLastError[0]!=0) { app.DebugPrintf("\rErrorCallback Error Category: %s\n", pchLastError); }
if (i_Details) { app.DebugPrintf("ErrorCallback - Details: %s\n", i_Details); }}
#ifdef __PSVITA__// AP - this is the callback when the driver is about to mix. At this point the mutex is locked by Miles so we can now call all Miles functions without// the possibility of incurring a stall.static bool SoundEngine_Change = false; // has tick been called?static CRITICAL_SECTION SoundEngine_MixerMutex;
void AILCALL MilesMixerCB(HDIGDRIVER dig){ // has the tick function been called since the last callback if( SoundEngine_Change ) { SoundEngine_Change = false;
EnterCriticalSection(&SoundEngine_MixerMutex);
Minecraft *pMinecraft = Minecraft::GetInstance(); pMinecraft->soundEngine->updateMiles(); pMinecraft->soundEngine->playMusicUpdate();
LeaveCriticalSection(&SoundEngine_MixerMutex); }}#endif
///////////////////////////////////////////////// init///////////////////////////////////////////////void SoundEngine::init(Options *pOptions){ app.DebugPrintf("---SoundEngine::init\n");#ifdef __DISABLE_MILES__ return;#endif#ifdef __ORBIS__ C4JThread::PushAffinityAllCores();#endif #if defined _DURANGO || defined __ORBIS__ || defined __PS3__ || defined __PSVITA__ Register_RIB(BinkADec);#endif
char *redistpath;
#if (defined _WINDOWS64 || defined __PSVITA__)// || defined _DURANGO || defined __ORBIS__ ) redistpath=AIL_set_redist_directory(m_szRedistName);#endif
app.DebugPrintf("---SoundEngine::init - AIL_startup\n"); S32 ret = AIL_startup();
int iNumberOfChannels=initAudioHardware(8);
// Create a driver to render our audio - 44khz, 16 bit,#ifdef __PS3__ // On the Sony PS3, the driver is always opened in 48 kHz, 32-bit floating point. The only meaningful configurations are MSS_MC_STEREO, MSS_MC_51_DISCRETE, and MSS_MC_71_DISCRETE. m_hDriver = AIL_open_digital_driver( 48000, 16, iNumberOfChannels, AIL_OPEN_DIGITAL_USE_SPU0 );#elif defined __PSVITA__
// maximum of 16 samples AIL_set_preference(DIG_MIXER_CHANNELS, 16);
m_hDriver = AIL_open_digital_driver( 48000, 16, MSS_MC_STEREO, 0 );
// AP - For some reason the submit thread defaults to a priority of zero (invalid). Make sure it has the highest priority to avoid audio breakup. SceUID threadID; AIL_platform_property( m_hDriver, PSP2_SUBMIT_THREAD, &threadID, 0, 0); S32 g_DefaultCPU = sceKernelGetThreadCpuAffinityMask(threadID); S32 Old = sceKernelChangeThreadPriority(threadID, 64);
// AP - register a callback when the mixer starts AILMIXERCB temp = AIL_register_mix_callback(m_hDriver, MilesMixerCB);
InitializeCriticalSection(&SoundEngine_MixerMutex);
#elif defined(__ORBIS__) m_hDriver = AIL_open_digital_driver( 48000, 16, 2, 0 ); app.DebugPrintf("---SoundEngine::init - AIL_open_digital_driver\n");
#else m_hDriver = AIL_open_digital_driver(44100, 16, MSS_MC_USE_SYSTEM_CONFIG, 0);#endif if (m_hDriver == 0) { app.DebugPrintf("Couldn't open digital sound driver. (%s)\n", AIL_last_error()); AIL_shutdown();#ifdef __ORBIS__ C4JThread::PopAffinity();#endif return; } app.DebugPrintf("---SoundEngine::init - driver opened\n");
#ifdef __PSVITA__
// set high falloff power for maximum spatial effect in software mode AIL_set_speaker_configuration( m_hDriver, 0, 0, 4.0F );
#endif
AIL_set_event_error_callback(ErrorCallback);
AIL_set_3D_rolloff_factor(m_hDriver,1.0);
// Create an event system tied to that driver - let Miles choose memory defaults. //if (AIL_startup_event_system(m_hDriver, 0, 0, 0) == 0) // 4J-PB - Durango complains that the default memory (64k)isn't enough // Error: MilesEvent: Out of event system memory (pool passed to event system startup exhausted). // AP - increased command buffer from the default 5K to 20K for Vita
if (AIL_startup_event_system(m_hDriver, 1024*20, 0, 1024*128) == 0) { app.DebugPrintf("Couldn't init event system (%s).\n", AIL_last_error()); AIL_close_digital_driver(m_hDriver); AIL_shutdown();#ifdef __ORBIS__ C4JThread::PopAffinity();#endif app.DebugPrintf("---SoundEngine::init - AIL_startup_event_system failed\n"); return; } char szBankName[255];#if defined __PS3__ if(app.GetBootedFromDiscPatch()) { char szTempSoundFilename[255]; sprintf(szTempSoundFilename,"%s%s",m_szSoundPath, "Minecraft.msscmp" );
app.DebugPrintf("SoundEngine::playMusicUpdate - (booted from disc patch) looking for %s\n",szTempSoundFilename); sprintf(szBankName,"%s/%s",app.GetBDUsrDirPath(szTempSoundFilename), m_szSoundPath ); app.DebugPrintf("SoundEngine::playMusicUpdate - (booted from disc patch) music path - %s\n",szBankName); } else { sprintf(szBankName,"%s/%s",getUsrDirPath(), m_szSoundPath ); } #elif defined __PSVITA__ sprintf(szBankName,"%s/%s",getUsrDirPath(), m_szSoundPath );#elif defined __ORBIS__ sprintf(szBankName,"%s/%s",getUsrDirPath(), m_szSoundPath );#else strcpy((char *)szBankName,m_szSoundPath);#endif
strcat((char *)szBankName,"Minecraft.msscmp");
m_hBank=AIL_add_soundbank(szBankName, 0);
if(m_hBank == NULL) { char *Error=AIL_last_error(); app.DebugPrintf("Couldn't open soundbank: %s (%s)\n", szBankName, Error); AIL_close_digital_driver(m_hDriver); AIL_shutdown();#ifdef __ORBIS__ C4JThread::PopAffinity();#endif return; }
//#ifdef _DEBUG HMSSENUM token = MSS_FIRST; char const* Events[1] = {0}; S32 EventCount = 0; while (AIL_enumerate_events(m_hBank, &token, 0, &Events[0])) { app.DebugPrintf(4,"%d - %s\n", EventCount, Events[0]);
EventCount++; } //#endif
U64 u64Result; u64Result=AIL_enqueue_event_by_name("Minecraft/CacheSounds");
m_MasterMusicVolume=1.0f; m_MasterEffectsVolume=1.0f;
//AIL_set_variable_float(0,"UserEffectVol",1);
m_bSystemMusicPlaying = false;
m_openStreamThread = NULL;
#ifdef __ORBIS__ C4JThread::PopAffinity();#endif
#ifdef __PSVITA__ // AP - By default the mixer won't start up and nothing will process. Kick off a blank sample to force the mixer to start up. HSAMPLE Sample = AIL_allocate_sample_handle(m_hDriver); AIL_init_sample(Sample, DIG_F_STEREO_16); static U64 silence = 0; AIL_set_sample_address(Sample, &silence, sizeof(U64)); AIL_start_sample(Sample);
// wait for 1 mix... AIL_release_sample_handle(Sample);#endif}
#ifdef __ORBIS__// void SoundEngine::SetHandle(int32_t hAudio)// {// //m_hAudio=hAudio;// }#endif
void SoundEngine::SetStreamingSounds(int iOverworldMin, int iOverWorldMax, int iNetherMin, int iNetherMax, int iEndMin, int iEndMax, int iCD1){ m_iStream_Overworld_Min=iOverworldMin; m_iStream_Overworld_Max=iOverWorldMax; m_iStream_Nether_Min=iNetherMin; m_iStream_Nether_Max=iNetherMax; m_iStream_End_Min=iEndMin; m_iStream_End_Max=iEndMax; m_iStream_CD_1=iCD1;
// array to monitor recently played tracks if(m_bHeardTrackA) { delete [] m_bHeardTrackA; } m_bHeardTrackA = new bool[iEndMax+1]; memset(m_bHeardTrackA,0,sizeof(bool)*iEndMax+1);}
// AP - moved to a separate function so it can be called from the mixer callback on Vitavoid SoundEngine::updateMiles(){#ifdef __PSVITA__ //CD - We must check for Background Music [BGM] at any point //If it's playing disable our audio, otherwise enable int NoBGMPlaying = sceAudioOutGetAdopt(SCE_AUDIO_OUT_PORT_TYPE_BGM); updateSystemMusicPlaying( !NoBGMPlaying );#elif defined __ORBIS__ // is the system playing background music? SceAudioOutPortState outPortState; sceAudioOutGetPortState(m_hBGMAudio,&outPortState); updateSystemMusicPlaying( outPortState.output==SCE_AUDIO_OUT_STATE_OUTPUT_UNKNOWN );#endif
if( m_validListenerCount == 1 ) { for( int i = 0; i < MAX_LOCAL_PLAYERS; i++ ) { // set the listener as the first player we find if( m_ListenerA[i].bValid ) { AIL_set_listener_3D_position(m_hDriver,m_ListenerA[i].vPosition.x,m_ListenerA[i].vPosition.y,-m_ListenerA[i].vPosition.z); // Flipped sign of z as Miles is expecting left handed coord system AIL_set_listener_3D_orientation(m_hDriver,-m_ListenerA[i].vOrientFront.x,m_ListenerA[i].vOrientFront.y,m_ListenerA[i].vOrientFront.z,0,1,0); // Flipped sign of z as Miles is expecting left handed coord system break; } } } else { // 4J-PB - special case for splitscreen // the shortest distance between any listener and a sound will be used to play a sound a set distance away down the z axis. // The listener position will be set to 0,0,0, and the orientation will be facing down the z axis
AIL_set_listener_3D_position(m_hDriver,0,0,0); AIL_set_listener_3D_orientation(m_hDriver,0,0,1,0,1,0); }
AIL_begin_event_queue_processing();
// Iterate over the sounds S32 StartedCount = 0, CompletedCount = 0, TotalCount = 0; HMSSENUM token = MSS_FIRST; MILESEVENTSOUNDINFO SoundInfo; int Playing = 0; while (AIL_enumerate_sound_instances(0, &token, 0, 0, 0, &SoundInfo)) { AUDIO_INFO* game_data= (AUDIO_INFO*)( SoundInfo.UserBuffer );
if( SoundInfo.Status == MILESEVENT_SOUND_STATUS_PLAYING ) { Playing += 1; }
if ( SoundInfo.Status != MILESEVENT_SOUND_STATUS_COMPLETE ) { // apply the master volume // watch for the 'special' volume levels bool isThunder = false; if( game_data->volume == 10000.0f ) { isThunder = true; } if(game_data->volume>1) { game_data->volume=1; } AIL_set_sample_volume_levels( SoundInfo.Sample, game_data->volume*m_MasterEffectsVolume, game_data->volume*m_MasterEffectsVolume);
float distanceScaler = 16.0f; switch(SoundInfo.Status) { case MILESEVENT_SOUND_STATUS_PENDING: // 4J-PB - causes the falloff to be calculated on the PPU instead of the SPU, and seems to resolve our distorted sound issue AIL_register_falloff_function_callback(SoundInfo.Sample,&custom_falloff_function);
if(game_data->bIs3D) { AIL_set_sample_is_3D( SoundInfo.Sample, 1 );
int iSound = game_data->iSound - eSFX_MAX; switch(iSound) { // Is this the Dragon? case eSoundType_MOB_ENDERDRAGON_GROWL: case eSoundType_MOB_ENDERDRAGON_MOVE: case eSoundType_MOB_ENDERDRAGON_END: case eSoundType_MOB_ENDERDRAGON_HIT: distanceScaler=100.0f; break; case eSoundType_FIREWORKS_BLAST: case eSoundType_FIREWORKS_BLAST_FAR: case eSoundType_FIREWORKS_LARGE_BLAST: case eSoundType_FIREWORKS_LARGE_BLAST_FAR: distanceScaler=100.0f; break; case eSoundType_MOB_GHAST_MOAN: case eSoundType_MOB_GHAST_SCREAM: case eSoundType_MOB_GHAST_DEATH: case eSoundType_MOB_GHAST_CHARGE: case eSoundType_MOB_GHAST_FIREBALL: distanceScaler=30.0f; break; }
// Set a special distance scaler for thunder, which we respond to by having no attenutation if( isThunder ) { distanceScaler = 10000.0f; } } else { AIL_set_sample_is_3D( SoundInfo.Sample, 0 ); }
AIL_set_sample_3D_distances(SoundInfo.Sample,distanceScaler,1,0); // set the pitch if(!game_data->bUseSoundsPitchVal) { AIL_set_sample_playback_rate_factor(SoundInfo.Sample,game_data->pitch); }
if(game_data->bIs3D) { if(m_validListenerCount>1) { float fClosest=10000.0f; int iClosestListener=0; float fClosestX=0.0f,fClosestY=0.0f,fClosestZ=0.0f,fDist; // need to calculate the distance from the sound to the nearest listener - use Manhattan Distance as the decision for( int i = 0; i < MAX_LOCAL_PLAYERS; i++ ) { if( m_ListenerA[i].bValid ) { float x,y,z;
x=fabs(m_ListenerA[i].vPosition.x-game_data->x); y=fabs(m_ListenerA[i].vPosition.y-game_data->y); z=fabs(m_ListenerA[i].vPosition.z-game_data->z); fDist=x+y+z;
if(fDist<fClosest) { fClosest=fDist; fClosestX=x; fClosestY=y; fClosestZ=z; iClosestListener=i; } } }
// our distances in the world aren't very big, so floats rather than casts to doubles should be fine fDist=sqrtf((fClosestX*fClosestX)+(fClosestY*fClosestY)+(fClosestZ*fClosestZ)); AIL_set_sample_3D_position( SoundInfo.Sample, 0, 0, fDist );
//app.DebugPrintf("Playing sound %d %f from nearest listener [%d]\n",SoundInfo.EventID,fDist,iClosestListener); } else { AIL_set_sample_3D_position( SoundInfo.Sample, game_data->x, game_data->y, -game_data->z ); // Flipped sign of z as Miles is expecting left handed coord system } } break;
default: if(game_data->bIs3D) { if(m_validListenerCount>1) { float fClosest=10000.0f; int iClosestListener=0; float fClosestX=0.0f,fClosestY=0.0f,fClosestZ=0.0f,fDist; // need to calculate the distance from the sound to the nearest listener - use Manhattan Distance as the decision for( int i = 0; i < MAX_LOCAL_PLAYERS; i++ ) { if( m_ListenerA[i].bValid ) { float x,y,z;
x=fabs(m_ListenerA[i].vPosition.x-game_data->x); y=fabs(m_ListenerA[i].vPosition.y-game_data->y); z=fabs(m_ListenerA[i].vPosition.z-game_data->z); fDist=x+y+z;
if(fDist<fClosest) { fClosest=fDist; fClosestX=x; fClosestY=y; fClosestZ=z; iClosestListener=i; } } } // our distances in the world aren't very big, so floats rather than casts to doubles should be fine fDist=sqrtf((fClosestX*fClosestX)+(fClosestY*fClosestY)+(fClosestZ*fClosestZ)); AIL_set_sample_3D_position( SoundInfo.Sample, 0, 0, fDist );
//app.DebugPrintf("Playing sound %d %f from nearest listener [%d]\n",SoundInfo.EventID,fDist,iClosestListener); } else { AIL_set_sample_3D_position( SoundInfo.Sample, game_data->x, game_data->y, -game_data->z ); // Flipped sign of z as Miles is expecting left handed coord system } } break; } } } AIL_complete_event_queue_processing();}
//#define DISTORTION_TEST#ifdef DISTORTION_TESTstatic float fVal=0.0f;#endif///////////////////////////////////////////////// tick///////////////////////////////////////////////
#ifdef __PSVITA__static S32 running = AIL_ms_count();#endif
void SoundEngine::tick(shared_ptr<Mob> *players, float a){ ConsoleSoundEngine::tick();#ifdef __DISABLE_MILES__ return;#endif
#ifdef __PSVITA__ EnterCriticalSection(&SoundEngine_MixerMutex);#endif
// update the listener positions int listenerCount = 0;#ifdef DISTORTION_TEST float fX,fY,fZ;#endif if( players ) { bool bListenerPostionSet=false; for( int i = 0; i < MAX_LOCAL_PLAYERS; i++ ) { if( players[i] != NULL ) { m_ListenerA[i].bValid=true; F32 x,y,z; x=players[i]->xo + (players[i]->x - players[i]->xo) * a; y=players[i]->yo + (players[i]->y - players[i]->yo) * a; z=players[i]->zo + (players[i]->z - players[i]->zo) * a;
float yRot = players[i]->yRotO + (players[i]->yRot - players[i]->yRotO) * a; float yCos = (float)cos(-yRot * Mth::RAD_TO_GRAD - PI); float ySin = (float)sin(-yRot * Mth::RAD_TO_GRAD - PI);
// store the listener positions for splitscreen m_ListenerA[i].vPosition.x = x; m_ListenerA[i].vPosition.y = y; m_ListenerA[i].vPosition.z = z;
m_ListenerA[i].vOrientFront.x = ySin; m_ListenerA[i].vOrientFront.y = 0; m_ListenerA[i].vOrientFront.z = yCos;
listenerCount++; } else { m_ListenerA[i].bValid=false; } } }
// If there were no valid players set, make up a default listener if( listenerCount == 0 ) { m_ListenerA[0].vPosition.x = 0; m_ListenerA[0].vPosition.y = 0; m_ListenerA[0].vPosition.z = 0; m_ListenerA[0].vOrientFront.x = 0; m_ListenerA[0].vOrientFront.y = 0; m_ListenerA[0].vOrientFront.z = 1.0f; listenerCount++; } m_validListenerCount = listenerCount;
#ifdef __PSVITA__ // AP - Show that a change has occurred so we know to update the values at the next Mixer callback SoundEngine_Change = true;
LeaveCriticalSection(&SoundEngine_MixerMutex);#else updateMiles();#endif}
///////////////////////////////////////////////// SoundEngine///////////////////////////////////////////////SoundEngine::SoundEngine(){ random = new Random(); m_hStream=0; m_StreamState=eMusicStreamState_Idle; m_iMusicDelay=0; m_validListenerCount=0;
m_bHeardTrackA=NULL;
// Start the streaming music playing some music from the overworld SetStreamingSounds(eStream_Overworld_Calm1,eStream_Overworld_piano3, eStream_Nether1,eStream_Nether4, eStream_end_dragon,eStream_end_end, eStream_CD_1);
m_musicID=getMusicID(LevelData::DIMENSION_OVERWORLD);
m_StreamingAudioInfo.bIs3D=false; m_StreamingAudioInfo.x=0; m_StreamingAudioInfo.y=0; m_StreamingAudioInfo.z=0; m_StreamingAudioInfo.volume=1; m_StreamingAudioInfo.pitch=1;
memset(CurrentSoundsPlaying,0,sizeof(int)*(eSoundType_MAX+eSFX_MAX)); memset(m_ListenerA,0,sizeof(AUDIO_LISTENER)*XUSER_MAX_COUNT);
#ifdef __ORBIS__ m_hBGMAudio=GetAudioBGMHandle();#endif}
void SoundEngine::destroy() {}
#ifdef _DEBUGvoid SoundEngine::GetSoundName(char *szSoundName,int iSound){ strcpy((char *)szSoundName,"Minecraft/"); wstring name = wchSoundNames[iSound]; char *SoundName = (char *)ConvertSoundPathToName(name); strcat((char *)szSoundName,SoundName);}#endif
///////////////////////////////////////////////// play///////////////////////////////////////////////void SoundEngine::play(int iSound, float x, float y, float z, float volume, float pitch){ U8 szSoundName[256];
if(iSound==-1) { app.DebugPrintf(6,"PlaySound with sound of -1 !!!!!!!!!!!!!!!\n"); return; }
// AP removed old counting system. Now relying on Miles' Play Count Limit /* // if we are already playing loads of this sounds ignore this one if(CurrentSoundsPlaying[iSound+eSFX_MAX]>MAX_SAME_SOUNDS_PLAYING) { // wstring name = wchSoundNames[iSound]; // char *SoundName = (char *)ConvertSoundPathToName(name); // app.DebugPrintf("Too many %s sounds playing!\n",SoundName); return; }*/
//if (iSound != eSoundType_MOB_IRONGOLEM_WALK) return;
// build the name strcpy((char *)szSoundName,"Minecraft/");
#ifdef DISTORTION_TEST wstring name = wchSoundNames[eSoundType_MOB_ENDERDRAGON_GROWL];#else wstring name = wchSoundNames[iSound];#endif
char *SoundName = (char *)ConvertSoundPathToName(name); strcat((char *)szSoundName,SoundName);
// app.DebugPrintf(6,"PlaySound - %d - %s - %s (%f %f %f, vol %f, pitch %f)\n",iSound, SoundName, szSoundName,x,y,z,volume,pitch);
AUDIO_INFO AudioInfo; AudioInfo.x=x; AudioInfo.y=y; AudioInfo.z=z; AudioInfo.volume=volume; AudioInfo.pitch=pitch; AudioInfo.bIs3D=true; AudioInfo.bUseSoundsPitchVal=false; AudioInfo.iSound=iSound+eSFX_MAX;#ifdef _DEBUG strncpy(AudioInfo.chName,(char *)szSoundName,64);#endif
S32 token = AIL_enqueue_event_start(); AIL_enqueue_event_buffer(&token, &AudioInfo, sizeof(AUDIO_INFO), 0); AIL_enqueue_event_end_named(token, (char *)szSoundName);}
///////////////////////////////////////////////// playUI///////////////////////////////////////////////void SoundEngine::playUI(int iSound, float volume, float pitch) { U8 szSoundName[256]; wstring name; // we have some game sounds played as UI sounds... // Not the best way to do this, but it seems to only be the portal sounds
if(iSound>=eSFX_MAX) { // AP removed old counting system. Now relying on Miles' Play Count Limit /* // if we are already playing loads of this sounds ignore this one if(CurrentSoundsPlaying[iSound+eSFX_MAX]>MAX_SAME_SOUNDS_PLAYING) return;*/
// build the name strcpy((char *)szSoundName,"Minecraft/"); name = wchSoundNames[iSound]; } else { // AP removed old counting system. Now relying on Miles' Play Count Limit /* // if we are already playing loads of this sounds ignore this one if(CurrentSoundsPlaying[iSound]>MAX_SAME_SOUNDS_PLAYING) return;*/
// build the name strcpy((char *)szSoundName,"Minecraft/UI/"); name = wchUISoundNames[iSound]; }
char *SoundName = (char *)ConvertSoundPathToName(name); strcat((char *)szSoundName,SoundName);// app.DebugPrintf("UI: Playing %s, volume %f, pitch %f\n",SoundName,volume,pitch);
//app.DebugPrintf("PlaySound - %d - %s\n",iSound, SoundName);
AUDIO_INFO AudioInfo; memset(&AudioInfo,0,sizeof(AUDIO_INFO)); AudioInfo.volume=volume; // will be multiplied by the master volume AudioInfo.pitch=pitch; AudioInfo.bUseSoundsPitchVal=true; if(iSound>=eSFX_MAX) { AudioInfo.iSound=iSound+eSFX_MAX; } else { AudioInfo.iSound=iSound; }#ifdef _DEBUG strncpy(AudioInfo.chName,(char *)szSoundName,64);#endif
// 4J-PB - not going to stop UI events happening based on the number of currently playing sounds S32 token = AIL_enqueue_event_start(); AIL_enqueue_event_buffer(&token, &AudioInfo, sizeof(AUDIO_INFO), 0); AIL_enqueue_event_end_named(token, (char *)szSoundName);}
///////////////////////////////////////////////// playStreaming///////////////////////////////////////////////void SoundEngine::playStreaming(const wstring& name, float x, float y , float z, float volume, float pitch, bool bMusicDelay){ // This function doesn't actually play a streaming sound, just sets states and an id for the music tick to play it // Level audio will be played when a play with an empty name comes in // CD audio will be played when a named stream comes in
m_StreamingAudioInfo.x=x; m_StreamingAudioInfo.y=y; m_StreamingAudioInfo.z=z; m_StreamingAudioInfo.volume=volume; m_StreamingAudioInfo.pitch=pitch;
if(m_StreamState==eMusicStreamState_Playing) { m_StreamState=eMusicStreamState_Stop; } else if(m_StreamState==eMusicStreamState_Opening) { m_StreamState=eMusicStreamState_OpeningCancel; }
if(name.empty()) { // music, or stop CD m_StreamingAudioInfo.bIs3D=false;
// we need a music id // random delay of up to 3 minutes for music m_iMusicDelay = random->nextInt(20 * 60 * 3);//random->nextInt(20 * 60 * 10) + 20 * 60 * 10;
#ifdef _DEBUG m_iMusicDelay=0;#endif Minecraft *pMinecraft=Minecraft::GetInstance();
bool playerInEnd=false; bool playerInNether=false;
for(unsigned int i=0;i<MAX_LOCAL_PLAYERS;i++) { if(pMinecraft->localplayers[i]!=NULL) { if(pMinecraft->localplayers[i]->dimension==LevelData::DIMENSION_END) { playerInEnd=true; } else if(pMinecraft->localplayers[i]->dimension==LevelData::DIMENSION_NETHER) { playerInNether=true; } } } if(playerInEnd) { m_musicID = getMusicID(LevelData::DIMENSION_END); } else if(playerInNether) { m_musicID = getMusicID(LevelData::DIMENSION_NETHER); } else { m_musicID = getMusicID(LevelData::DIMENSION_OVERWORLD); } } else { // jukebox m_StreamingAudioInfo.bIs3D=true; m_musicID=getMusicID(name); m_iMusicDelay=0; }}
int SoundEngine::GetRandomishTrack(int iStart,int iEnd){ // 4J-PB - make it more likely that we'll get a track we've not heard for a while, although repeating tracks sometimes is fine
// if all tracks have been heard, clear the flags bool bAllTracksHeard=true; int iVal=iStart; for(int i=iStart;i<=iEnd;i++) { if(m_bHeardTrackA[i]==false) { bAllTracksHeard=false; app.DebugPrintf("Not heard all tracks yet\n"); break; } }
if(bAllTracksHeard) { app.DebugPrintf("Heard all tracks - resetting the tracking array\n");
for(int i=iStart;i<=iEnd;i++) { m_bHeardTrackA[i]=false; } }
// trying to get a track we haven't heard, but not too hard for(int i=0;i<=((iEnd-iStart)/2);i++) { // random->nextInt(1) will always return 0 iVal=random->nextInt((iEnd-iStart)+1)+iStart; if(m_bHeardTrackA[iVal]==false) { // not heard this app.DebugPrintf("(%d) Not heard track %d yet, so playing it now\n",i,iVal); m_bHeardTrackA[iVal]=true; break; } else { app.DebugPrintf("(%d) Skipping track %d already heard it recently\n",i,iVal); } }
app.DebugPrintf("Select track %d\n",iVal); return iVal;}///////////////////////////////////////////////// getMusicID///////////////////////////////////////////////int SoundEngine::getMusicID(int iDomain){ int iRandomVal=0; Minecraft *pMinecraft=Minecraft::GetInstance();
// Before the game has started? if(pMinecraft==NULL) { // any track from the overworld return GetRandomishTrack(m_iStream_Overworld_Min,m_iStream_Overworld_Max); }
if(pMinecraft->skins->isUsingDefaultSkin()) { switch(iDomain) { case LevelData::DIMENSION_END: // the end isn't random - it has different music depending on whether the dragon is alive or not, but we've not added the dead dragon music yet return m_iStream_End_Min; case LevelData::DIMENSION_NETHER: return GetRandomishTrack(m_iStream_Nether_Min,m_iStream_Nether_Max); //return m_iStream_Nether_Min + random->nextInt(m_iStream_Nether_Max-m_iStream_Nether_Min); default: //overworld //return m_iStream_Overworld_Min + random->nextInt(m_iStream_Overworld_Max-m_iStream_Overworld_Min); return GetRandomishTrack(m_iStream_Overworld_Min,m_iStream_Overworld_Max); } } else { // using a texture pack - may have multiple End music tracks switch(iDomain) { case LevelData::DIMENSION_END: return GetRandomishTrack(m_iStream_End_Min,m_iStream_End_Max); case LevelData::DIMENSION_NETHER: //return m_iStream_Nether_Min + random->nextInt(m_iStream_Nether_Max-m_iStream_Nether_Min); return GetRandomishTrack(m_iStream_Nether_Min,m_iStream_Nether_Max); default: //overworld //return m_iStream_Overworld_Min + random->nextInt(m_iStream_Overworld_Max-m_iStream_Overworld_Min); return GetRandomishTrack(m_iStream_Overworld_Min,m_iStream_Overworld_Max); } }}
///////////////////////////////////////////////// getMusicID///////////////////////////////////////////////// check what the CD isint SoundEngine::getMusicID(const wstring& name){ int iCD=0; char *SoundName = (char *)ConvertSoundPathToName(name,true);
// 4J-PB - these will always be the game cds, so use the m_szStreamFileA for this for(int i=0;i<12;i++) { if(strcmp(SoundName,m_szStreamFileA[i+eStream_CD_1])==0) { iCD=i; break; } }
// adjust for cd start position on normal or mash-up pack return iCD+m_iStream_CD_1;}
///////////////////////////////////////////////// getMasterMusicVolume///////////////////////////////////////////////float SoundEngine::getMasterMusicVolume(){ if( m_bSystemMusicPlaying ) { return 0.0f; } else { return m_MasterMusicVolume; }}
///////////////////////////////////////////////// updateMusicVolume///////////////////////////////////////////////void SoundEngine::updateMusicVolume(float fVal){ m_MasterMusicVolume=fVal;}
///////////////////////////////////////////////// updateSystemMusicPlaying///////////////////////////////////////////////void SoundEngine::updateSystemMusicPlaying(bool isPlaying){ m_bSystemMusicPlaying = isPlaying;}
///////////////////////////////////////////////// updateSoundEffectVolume///////////////////////////////////////////////void SoundEngine::updateSoundEffectVolume(float fVal) { m_MasterEffectsVolume=fVal; //AIL_set_variable_float(0,"UserEffectVol",fVal);}
void SoundEngine::add(const wstring& name, File *file) {}void SoundEngine::addMusic(const wstring& name, File *file) {}void SoundEngine::addStreaming(const wstring& name, File *file) {}bool SoundEngine::isStreamingWavebankReady() { return true; }
int SoundEngine::OpenStreamThreadProc( void* lpParameter ){#ifdef __DISABLE_MILES__ return 0;#endif SoundEngine *soundEngine = (SoundEngine *)lpParameter; soundEngine->m_hStream = AIL_open_stream(soundEngine->m_hDriver,soundEngine->m_szStreamName,0);
if(soundEngine->m_hStream==0) { app.DebugPrintf("SoundEngine::OpenStreamThreadProc - Could not open - %s\n",soundEngine->m_szStreamName); } return 0;}
///////////////////////////////////////////////// playMusicTick///////////////////////////////////////////////void SoundEngine::playMusicTick() {// AP - vita will update the music during the mixer callback#ifndef __PSVITA__ playMusicUpdate();#endif}
// AP - moved to a separate function so it can be called from the mixer callback on Vitavoid SoundEngine::playMusicUpdate() { //return; static bool firstCall = true; static float fMusicVol = 0.0f; if( firstCall ) { fMusicVol = getMasterMusicVolume(); firstCall = false; }
switch(m_StreamState) { case eMusicStreamState_Idle:
// start a stream playing if (m_iMusicDelay > 0) { m_iMusicDelay--; return; }
if(m_musicID!=-1) { // start playing it
#if ( defined __PS3__ || defined __PSVITA__ || defined __ORBIS__ )
#ifdef __PS3__ // 4J-PB - Need to check if we are a patched BD build if(app.GetBootedFromDiscPatch()) { sprintf(m_szStreamName,"%s/%s",app.GetBDUsrDirPath(m_szMusicPath), m_szMusicPath ); app.DebugPrintf("SoundEngine::playMusicUpdate - (booted from disc patch) music path - %s",m_szStreamName); } else { sprintf(m_szStreamName,"%s/%s",getUsrDirPath(), m_szMusicPath ); }#else sprintf(m_szStreamName,"%s/%s",getUsrDirPath(), m_szMusicPath );#endif
#else strcpy((char *)m_szStreamName,m_szMusicPath);#endif // are we using a mash-up pack? //if(pMinecraft && !pMinecraft->skins->isUsingDefaultSkin() && pMinecraft->skins->getSelected()->hasAudio()) if(Minecraft::GetInstance()->skins->getSelected()->hasAudio()) { // It's a mash-up - need to use the DLC path for the music TexturePack *pTexPack=Minecraft::GetInstance()->skins->getSelected(); DLCTexturePack *pDLCTexPack=(DLCTexturePack *)pTexPack; DLCPack *pack = pDLCTexPack->getDLCInfoParentPack(); DLCAudioFile *dlcAudioFile = (DLCAudioFile *) pack->getFile(DLCManager::e_DLCType_Audio, 0);
app.DebugPrintf("Mashup pack \n");
// build the name
// if the music ID is beyond the end of the texture pack music files, then it's a CD if(m_musicID<m_iStream_CD_1) { SetIsPlayingStreamingGameMusic(true); SetIsPlayingStreamingCDMusic(false); m_MusicType=eMusicType_Game; m_StreamingAudioInfo.bIs3D=false; #ifdef _XBOX_ONE wstring &wstrSoundName=dlcAudioFile->GetSoundName(m_musicID); wstring wstrFile=L"TPACK:\\Data\\" + wstrSoundName +L".binka"; std::wstring mountedPath = StorageManager.GetMountedPath(wstrFile); wcstombs(m_szStreamName,mountedPath.c_str(),255);#else wstring &wstrSoundName=dlcAudioFile->GetSoundName(m_musicID); char szName[255]; wcstombs(szName,wstrSoundName.c_str(),255);
#if defined __PS3__ || defined __ORBIS__ || defined __PSVITA__ string strFile="TPACK:/Data/" + string(szName) + ".binka";#else string strFile="TPACK:\\Data\\" + string(szName) + ".binka";#endif std::string mountedPath = StorageManager.GetMountedPath(strFile); strcpy(m_szStreamName,mountedPath.c_str());#endif } else { SetIsPlayingStreamingGameMusic(false); SetIsPlayingStreamingCDMusic(true); m_MusicType=eMusicType_CD; m_StreamingAudioInfo.bIs3D=true;
// Need to adjust to index into the cds in the game's m_szStreamFileA strcat((char *)m_szStreamName,"cds/"); strcat((char *)m_szStreamName,m_szStreamFileA[m_musicID-m_iStream_CD_1+eStream_CD_1]); strcat((char *)m_szStreamName,".binka"); } } else { // 4J-PB - if this is a PS3 disc patch, we have to check if the music file is in the patch data#ifdef __PS3__ if(app.GetBootedFromDiscPatch() && (m_musicID<m_iStream_CD_1)) { // rebuild the path for the music strcpy((char *)m_szStreamName,m_szMusicPath); strcat((char *)m_szStreamName,"music/"); strcat((char *)m_szStreamName,m_szStreamFileA[m_musicID]); strcat((char *)m_szStreamName,".binka");
// check if this is in the patch data sprintf(m_szStreamName,"%s/%s",app.GetBDUsrDirPath(m_szStreamName), m_szMusicPath ); strcat((char *)m_szStreamName,"music/"); strcat((char *)m_szStreamName,m_szStreamFileA[m_musicID]); strcat((char *)m_szStreamName,".binka");
SetIsPlayingStreamingGameMusic(true); SetIsPlayingStreamingCDMusic(false); m_MusicType=eMusicType_Game; m_StreamingAudioInfo.bIs3D=false; } else if(m_musicID<m_iStream_CD_1) { SetIsPlayingStreamingGameMusic(true); SetIsPlayingStreamingCDMusic(false); m_MusicType=eMusicType_Game; m_StreamingAudioInfo.bIs3D=false; // build the name strcat((char *)m_szStreamName,"music/"); strcat((char *)m_szStreamName,m_szStreamFileA[m_musicID]); strcat((char *)m_szStreamName,".binka"); }
else { SetIsPlayingStreamingGameMusic(false); SetIsPlayingStreamingCDMusic(true); m_MusicType=eMusicType_CD; m_StreamingAudioInfo.bIs3D=true; // build the name strcat((char *)m_szStreamName,"cds/"); strcat((char *)m_szStreamName,m_szStreamFileA[m_musicID]); strcat((char *)m_szStreamName,".binka"); }#else if(m_musicID<m_iStream_CD_1) { SetIsPlayingStreamingGameMusic(true); SetIsPlayingStreamingCDMusic(false); m_MusicType=eMusicType_Game; m_StreamingAudioInfo.bIs3D=false; // build the name strcat((char *)m_szStreamName,"music/"); } else { SetIsPlayingStreamingGameMusic(false); SetIsPlayingStreamingCDMusic(true); m_MusicType=eMusicType_CD; m_StreamingAudioInfo.bIs3D=true; // build the name strcat((char *)m_szStreamName,"cds/"); } strcat((char *)m_szStreamName,m_szStreamFileA[m_musicID]); strcat((char *)m_szStreamName,".binka"); #endif }
// wstring name = m_szStreamFileA[m_musicID]; // char *SoundName = (char *)ConvertSoundPathToName(name); // strcat((char *)szStreamName,SoundName);
const bool isCD = (m_musicID >= m_iStream_CD_1); const char* folder = isCD ? "cds/" : "music/";
FILE* pFile = nullptr; if (fopen_s(&pFile, reinterpret_cast<char*>(m_szStreamName), "rb") == 0 && pFile) { fclose(pFile); } else { const char* extensions[] = { ".wav" }; // only wav works outside of binka files to my knowledge, i've only tested ogg, wav, mp3 and only wav worked out of the bunch size_t count = sizeof(extensions) / sizeof(extensions[0]); bool found = false;
for (size_t i = 0; i < count; i++) { int n = sprintf_s(reinterpret_cast<char*>(m_szStreamName), 512, "%s%s%s%s", m_szMusicPath, folder, m_szStreamFileA[m_musicID], extensions[i]); if (n < 0) continue;
if (fopen_s(&pFile, reinterpret_cast<char*>(m_szStreamName), "rb") == 0 && pFile) { fclose(pFile); found = true; break; } }
if (!found) { return; } }
app.DebugPrintf("Starting streaming - %s\n",m_szStreamName);
// Don't actually open in this thread, as it can block for ~300ms. m_openStreamThread = new C4JThread(OpenStreamThreadProc, this, "OpenStreamThreadProc"); m_openStreamThread->Run(); m_StreamState = eMusicStreamState_Opening; } break;
case eMusicStreamState_Opening: // If the open stream thread is complete, then we are ready to proceed to actually playing if( !m_openStreamThread->isRunning() ) { delete m_openStreamThread; m_openStreamThread = NULL;
HSAMPLE hSample = AIL_stream_sample_handle( m_hStream);
// 4J-PB - causes the falloff to be calculated on the PPU instead of the SPU, and seems to resolve our distorted sound issue AIL_register_falloff_function_callback(hSample,&custom_falloff_function);
if(m_StreamingAudioInfo.bIs3D) { AIL_set_sample_3D_distances(hSample,64.0f,1,0); // Larger distance scaler for music discs if(m_validListenerCount>1) { float fClosest=10000.0f; int iClosestListener=0; float fClosestX=0.0f,fClosestY=0.0f,fClosestZ=0.0f,fDist; // need to calculate the distance from the sound to the nearest listener - use Manhattan Distance as the decision for( int i = 0; i < MAX_LOCAL_PLAYERS; i++ ) { if( m_ListenerA[i].bValid ) { float x,y,z;
x=fabs(m_ListenerA[i].vPosition.x-m_StreamingAudioInfo.x); y=fabs(m_ListenerA[i].vPosition.y-m_StreamingAudioInfo.y); z=fabs(m_ListenerA[i].vPosition.z-m_StreamingAudioInfo.z); fDist=x+y+z;
if(fDist<fClosest) { fClosest=fDist; fClosestX=x; fClosestY=y; fClosestZ=z; iClosestListener=i; } } }
// our distances in the world aren't very big, so floats rather than casts to doubles should be fine fDist=sqrtf((fClosestX*fClosestX)+(fClosestY*fClosestY)+(fClosestZ*fClosestZ)); AIL_set_sample_3D_position( hSample, 0, 0, fDist ); } else { AIL_set_sample_3D_position( hSample, m_StreamingAudioInfo.x, m_StreamingAudioInfo.y, -m_StreamingAudioInfo.z ); // Flipped sign of z as Miles is expecting left handed coord system } } else { // clear the 3d flag on the stream after a jukebox finishes and streaming music starts AIL_set_sample_is_3D( hSample, 0 ); } // set the pitch app.DebugPrintf("Sample rate:%d\n", AIL_sample_playback_rate(hSample)); AIL_set_sample_playback_rate_factor(hSample,m_StreamingAudioInfo.pitch); // set the volume AIL_set_sample_volume_levels( hSample, m_StreamingAudioInfo.volume*getMasterMusicVolume(), m_StreamingAudioInfo.volume*getMasterMusicVolume());
AIL_start_stream( m_hStream );
m_StreamState=eMusicStreamState_Playing; } break; case eMusicStreamState_OpeningCancel: if( !m_openStreamThread->isRunning() ) { delete m_openStreamThread; m_openStreamThread = NULL; m_StreamState = eMusicStreamState_Stop; } break; case eMusicStreamState_Stop: // should gradually take the volume down in steps AIL_pause_stream(m_hStream,1); AIL_close_stream(m_hStream); m_hStream=0; SetIsPlayingStreamingCDMusic(false); SetIsPlayingStreamingGameMusic(false); m_StreamState=eMusicStreamState_Idle; break; case eMusicStreamState_Stopping: break; case eMusicStreamState_Play: break; case eMusicStreamState_Playing: if(GetIsPlayingStreamingGameMusic()) { //if(m_MusicInfo.pCue!=NULL) { bool playerInEnd = false; bool playerInNether=false; Minecraft *pMinecraft = Minecraft::GetInstance(); for(unsigned int i = 0; i < MAX_LOCAL_PLAYERS; ++i) { if(pMinecraft->localplayers[i]!=NULL) { if(pMinecraft->localplayers[i]->dimension==LevelData::DIMENSION_END) { playerInEnd=true; } else if(pMinecraft->localplayers[i]->dimension==LevelData::DIMENSION_NETHER) { playerInNether=true; } } }
if(playerInEnd && !GetIsPlayingEndMusic()) { m_StreamState=eMusicStreamState_Stop;
// Set the end track m_musicID = getMusicID(LevelData::DIMENSION_END); SetIsPlayingEndMusic(true); SetIsPlayingNetherMusic(false); } else if(!playerInEnd && GetIsPlayingEndMusic()) { if(playerInNether) { m_StreamState=eMusicStreamState_Stop;
// Set the end track m_musicID = getMusicID(LevelData::DIMENSION_NETHER); SetIsPlayingEndMusic(false); SetIsPlayingNetherMusic(true); } else { m_StreamState=eMusicStreamState_Stop;
// Set the end track m_musicID = getMusicID(LevelData::DIMENSION_OVERWORLD); SetIsPlayingEndMusic(false); SetIsPlayingNetherMusic(false); } } else if (playerInNether && !GetIsPlayingNetherMusic()) { m_StreamState=eMusicStreamState_Stop; // set the Nether track m_musicID = getMusicID(LevelData::DIMENSION_NETHER); SetIsPlayingNetherMusic(true); SetIsPlayingEndMusic(false); } else if(!playerInNether && GetIsPlayingNetherMusic()) { if(playerInEnd) { m_StreamState=eMusicStreamState_Stop; // set the Nether track m_musicID = getMusicID(LevelData::DIMENSION_END); SetIsPlayingNetherMusic(false); SetIsPlayingEndMusic(true); } else { m_StreamState=eMusicStreamState_Stop; // set the Nether track m_musicID = getMusicID(LevelData::DIMENSION_OVERWORLD); SetIsPlayingNetherMusic(false); SetIsPlayingEndMusic(false); } }
// volume change required? if(fMusicVol!=getMasterMusicVolume()) { fMusicVol=getMasterMusicVolume(); HSAMPLE hSample = AIL_stream_sample_handle( m_hStream); //AIL_set_sample_3D_position( hSample, m_StreamingAudioInfo.x, m_StreamingAudioInfo.y, m_StreamingAudioInfo.z ); AIL_set_sample_volume_levels( hSample, fMusicVol, fMusicVol); } } } else { // Music disc playing - if it's a 3D stream, then set the position - we don't have any streaming audio in the world that moves, so this isn't // required unless we have more than one listener, and are setting the listening position to the origin and setting a fake position // for the sound down the z axis if(m_StreamingAudioInfo.bIs3D) { if(m_validListenerCount>1) { float fClosest=10000.0f; int iClosestListener=0; float fClosestX=0.0f,fClosestY=0.0f,fClosestZ=0.0f,fDist;
// need to calculate the distance from the sound to the nearest listener - use Manhattan Distance as the decision for( int i = 0; i < MAX_LOCAL_PLAYERS; i++ ) { if( m_ListenerA[i].bValid ) { float x,y,z;
x=fabs(m_ListenerA[i].vPosition.x-m_StreamingAudioInfo.x); y=fabs(m_ListenerA[i].vPosition.y-m_StreamingAudioInfo.y); z=fabs(m_ListenerA[i].vPosition.z-m_StreamingAudioInfo.z); fDist=x+y+z;
if(fDist<fClosest) { fClosest=fDist; fClosestX=x; fClosestY=y; fClosestZ=z; iClosestListener=i; } } }
// our distances in the world aren't very big, so floats rather than casts to doubles should be fine HSAMPLE hSample = AIL_stream_sample_handle( m_hStream); fDist=sqrtf((fClosestX*fClosestX)+(fClosestY*fClosestY)+(fClosestZ*fClosestZ)); AIL_set_sample_3D_position( hSample, 0, 0, fDist ); } } }
break;
case eMusicStreamState_Completed: { // random delay of up to 3 minutes for music m_iMusicDelay = random->nextInt(20 * 60 * 3);//random->nextInt(20 * 60 * 10) + 20 * 60 * 10; // Check if we have a local player in The Nether or in The End, and play that music if they are Minecraft *pMinecraft=Minecraft::GetInstance(); bool playerInEnd=false; bool playerInNether=false;
for(unsigned int i=0;i<MAX_LOCAL_PLAYERS;i++) { if(pMinecraft->localplayers[i]!=NULL) { if(pMinecraft->localplayers[i]->dimension==LevelData::DIMENSION_END) { playerInEnd=true; } else if(pMinecraft->localplayers[i]->dimension==LevelData::DIMENSION_NETHER) { playerInNether=true; } } } if(playerInEnd) { m_musicID = getMusicID(LevelData::DIMENSION_END); SetIsPlayingEndMusic(true); SetIsPlayingNetherMusic(false); } else if(playerInNether) { m_musicID = getMusicID(LevelData::DIMENSION_NETHER); SetIsPlayingNetherMusic(true); SetIsPlayingEndMusic(false); } else { m_musicID = getMusicID(LevelData::DIMENSION_OVERWORLD); SetIsPlayingNetherMusic(false); SetIsPlayingEndMusic(false); }
m_StreamState=eMusicStreamState_Idle; } break; }
// check the status of the stream - this is for when a track completes rather than is stopped by the user action
if(m_hStream!=0) { if(AIL_stream_status(m_hStream)==SMP_DONE ) // SMP_DONE { AIL_close_stream(m_hStream); m_hStream=0; SetIsPlayingStreamingCDMusic(false); SetIsPlayingStreamingGameMusic(false);
m_StreamState=eMusicStreamState_Completed; } }}
///////////////////////////////////////////////// ConvertSoundPathToName///////////////////////////////////////////////char *SoundEngine::ConvertSoundPathToName(const wstring& name, bool bConvertSpaces){ static char buf[256]; assert(name.length()<256); for(unsigned int i = 0; i < name.length(); i++ ) { wchar_t c = name[i]; if(c=='.') c='/'; if(bConvertSpaces) { if(c==' ') c='_'; } buf[i] = (char)c; } buf[name.length()] = 0; return buf;}
#endif
F32 AILCALLBACK custom_falloff_function (HSAMPLE S, F32 distance, F32 rolloff_factor, F32 min_dist, F32 max_dist){ F32 result;
// This is now emulating the linear fall-off function that we used on the Xbox 360. The parameter which is passed as "max_dist" is the only one actually used, // and is generally used as CurveDistanceScaler is used on XACT on the Xbox. A special value of 10000.0f is passed for thunder, which has no attenuation
if( max_dist == 10000.0f ) { return 1.0f; }
result = 1.0f - ( distance / max_dist ); if( result < 0.0f ) result = 0.0f; if( result > 1.0f ) result = 1.0f;
return result;}