diff options
Diffstat (limited to '')
-rw-r--r-- | src/audio/miles/sampman_mss.cpp | 2257 | ||||
-rw-r--r-- | src/audio/miles/sampman_mss.h | 339 |
2 files changed, 2596 insertions, 0 deletions
diff --git a/src/audio/miles/sampman_mss.cpp b/src/audio/miles/sampman_mss.cpp new file mode 100644 index 00000000..f3a6ba80 --- /dev/null +++ b/src/audio/miles/sampman_mss.cpp @@ -0,0 +1,2257 @@ +#include <windows.h> +#include <shobjidl.h> +#include <shlguid.h> + +#include <time.h> + +#include "eax.h" +#include "eax-util.h" +#include "mss.h" + +#include "sampman_mss.h" +#include "AudioManager.h" +#include "MusicManager.h" +#include "Frontend.h" +#include "Timer.h" + + +#pragma comment( lib, "mss32.lib" ) + +cSampleManager SampleManager; +int32 BankStartOffset[MAX_SAMPLEBANKS]; +/////////////////////////////////////////////////////////////// + +char SampleBankDescFilename[] = "AUDIO\\SFX.SDT"; +char SampleBankDataFilename[] = "AUDIO\\SFX.RAW"; + +FILE *fpSampleDescHandle; +FILE *fpSampleDataHandle; +bool bSampleBankLoaded [MAX_SAMPLEBANKS]; +int32 nSampleBankDiscStartOffset [MAX_SAMPLEBANKS]; +int32 nSampleBankSize [MAX_SAMPLEBANKS]; +int32 nSampleBankMemoryStartAddress[MAX_SAMPLEBANKS]; +int32 _nSampleDataEndOffset; + +int32 nPedSlotSfx [MAX_PEDSFX]; +int32 nPedSlotSfxAddr[MAX_PEDSFX]; +uint8 nCurrentPedSlot; + +uint8 nChannelVolume[MAXCHANNELS+MAX2DCHANNELS]; + +uint32 nStreamLength[TOTAL_STREAMED_SOUNDS]; + +/////////////////////////////////////////////////////////////// +struct tMP3Entry +{ + char aFilename[MAX_PATH]; + + uint32 nTrackLength; + uint32 nTrackStreamPos; + + tMP3Entry *pNext; + char *pLinkPath; +}; + +uint32 nNumMP3s; +tMP3Entry *_pMP3List; +char _mp3DirectoryPath[MAX_PATH]; +HSTREAM mp3Stream [MAX_MP3STREAMS]; +int8 nStreamPan [MAX_MP3STREAMS]; +int8 nStreamVolume[MAX_MP3STREAMS]; +uint32 _CurMP3Index; +int32 _CurMP3Pos; +bool _bIsMp3Active; + +#if defined(GTA3_1_1_PATCH) || defined(GTA3_STEAM_PATCH) || defined(NO_CDCHECK) +bool _bUseHDDAudio; +char _aHDDPath[MAX_PATH]; +#endif +/////////////////////////////////////////////////////////////// + + +bool _bSampmanInitialised = false; + +// +// Miscellaneous globals / defines + +// Env Size Diffus Room RoomHF RoomLF DecTm DcHF DcLF Refl RefDel Ref Pan Revb RevDel Rev Pan EchTm EchDp ModTm ModDp AirAbs HFRef LFRef RRlOff FLAGS + +EAXLISTENERPROPERTIES StartEAX3 = + {26, 1.7f, 0.8f, -1000, -1000, -100, 4.42f, 0.14f, 1.00f, 429, 0.014f, 0.00f,0.00f,0.00f, 1023, 0.021f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 2727.1f, 250.0f, 0.00f, 0x3f }; + +EAXLISTENERPROPERTIES FinishEAX3 = + {26, 100.0f, 1.0f, 0, -1000, -2200, 20.0f, 1.39f, 1.00f, 1000, 0.069f, 0.00f,0.00f,0.00f, 400, 0.100f, 0.00f,0.00f,0.00f, 0.250f, 1.000f, 3.982f, 0.000f, -18.0f, 3530.8f, 417.9f, 6.70f, 0x3f }; + +EAXLISTENERPROPERTIES EAX3Params; + +S32 prevprovider=-1; +S32 curprovider=-1; +S32 usingEAX=0; +S32 usingEAX3=0; +HPROVIDER opened_provider=0; +H3DSAMPLE opened_samples[MAXCHANNELS] = {0}; +HSAMPLE opened_2dsamples[MAX2DCHANNELS] = {0}; +HDIGDRIVER DIG; +S32 speaker_type=0; + +U32 _maxSamples; +float _fPrevEaxRatioDestination; +bool _usingMilesFast2D; +float _fEffectsLevel; + + +struct +{ + HPROVIDER id; + char name[80]; +}providers[MAXPROVIDERS]; + +typedef struct provider_stuff +{ + char* name; + HPROVIDER id; +} provider_stuff; + + +static int __cdecl comp(const provider_stuff*s1,const provider_stuff*s2) +{ + return( _stricmp(s1->name,s2->name) ); +} + +static void +add_providers() +{ + provider_stuff pi[MAXPROVIDERS]; + U32 n,i,j; + + SampleManager.SetNum3DProvidersAvailable(0); + + HPROENUM next = HPROENUM_FIRST; + + n=0; + while (AIL_enumerate_3D_providers(&next, &pi[n].id, &pi[n].name) && (n<MAXPROVIDERS)) + { + ++n; + } + + qsort(pi,n,sizeof(pi[0]), (int(__cdecl*)(void const*, void const*))comp); + + for(i=0;i<n;i++) + { + providers[i].id=pi[i].id; + strcpy(providers[i].name, pi[i].name); + SampleManager.Set3DProviderName(i, providers[i].name); + } + + SampleManager.SetNum3DProvidersAvailable(n); + + for(j=n;j<MAXPROVIDERS;j++) + SampleManager.Set3DProviderName(j, NULL); +} + +static void +release_existing() +{ + for ( U32 i = 0; i < _maxSamples; i++ ) + { + if ( opened_samples[i] ) + { + AIL_release_3D_sample_handle(opened_samples[i]); + opened_samples[i] = NULL; + } + } + + if ( opened_provider ) + { + AIL_close_3D_provider(opened_provider); + opened_provider = NULL; + } + + _fPrevEaxRatioDestination = 0.0f; + _usingMilesFast2D = false; + _fEffectsLevel = 0.0f; +} + +static bool +set_new_provider(S32 index) +{ + DWORD result; + + if ( curprovider == index ) + return true; + + //close the already opened provider + curprovider = index; + + release_existing(); + + if ( curprovider != -1 ) + { + if ( !strcmp(providers[index].name, "Dolby Surround") ) + _maxSamples = MAXCHANNELS_SURROUND; + else + _maxSamples = MAXCHANNELS; + + AIL_set_3D_provider_preference(providers[index].id, "Maximum supported samples", &_maxSamples); + + //load the new provider + result = AIL_open_3D_provider(providers[index].id); + + if (result != M3D_NOERR) + { + curprovider=-1; + + OutputDebugStringA(AIL_last_error()); + + release_existing(); + + return false; + } + else + { + opened_provider=providers[index].id; + + //see if we're running under an EAX compatible provider + + if ( !strcmp(providers[index].name, "Creative Labs EAX 3 (TM)") ) + { + usingEAX = 1; + usingEAX3 = 1; + } + else + { + usingEAX3 = 0; + + result=AIL_3D_room_type(opened_provider); + usingEAX=(((S32)result)!=-1)?1:0; // will be something other than -1 on EAX + } + + if ( usingEAX3 ) + { + OutputDebugString("DOING SPECIAL EAX 3 STUFF!"); + AIL_set_3D_provider_preference(opened_provider, "EAX all parameters", &FinishEAX3); + } + else if ( usingEAX ) + { + AIL_set_3D_room_type(opened_provider, ENVIRONMENT_CAVE); + + if ( !strcmp(providers[index].name, "Miles Fast 2D Positional Audio") ) + _usingMilesFast2D = true; + } + + AIL_3D_provider_attribute(opened_provider, "Maximum supported samples", &_maxSamples); + + if ( _maxSamples > MAXCHANNELS ) + _maxSamples = MAXCHANNELS; + + SampleManager.SetSpeakerConfig(speaker_type); + + //obtain a 3D sample handles + for ( U32 i = 0; i < _maxSamples; ++i ) + { + opened_samples[i] = AIL_allocate_3D_sample_handle(opened_provider); + if ( opened_samples[i] != NULL ) + AIL_set_3D_sample_effects_level(opened_samples[i], 0.0f); + } + + return true; + } + } + + return false; +} + +void +cSampleManager::SetSpeakerConfig(int32 which) +{ + switch ( which ) + { + case 1: + speaker_type=AIL_3D_2_SPEAKER; + break; + + case 2: + speaker_type=AIL_3D_HEADPHONE; + break; + + case 3: + speaker_type=AIL_3D_4_SPEAKER; + break; + + default: + return; + break; + } + + if (opened_provider) + AIL_set_3D_speaker_type(opened_provider, speaker_type); +} + +uint32 +cSampleManager::GetMaximumSupportedChannels(void) +{ + if ( _maxSamples > MAXCHANNELS ) + return MAXCHANNELS; + + return _maxSamples; +} + +int8 +cSampleManager::GetCurrent3DProviderIndex(void) +{ + return curprovider; +} + +int8 +cSampleManager::SetCurrent3DProvider(uint8 nProvider) +{ + S32 savedprovider = curprovider; + + if ( nProvider < m_nNumberOfProviders ) + { + if ( set_new_provider(nProvider) ) + return curprovider; + else if ( savedprovider != -1 && savedprovider < m_nNumberOfProviders && set_new_provider(savedprovider) ) + return curprovider; + else + return -1; + } + else + return curprovider; +} + +static bool +_ResolveLink(char const *path, char *out) +{ + IShellLink* psl; + WIN32_FIND_DATA fd; + char filepath[MAX_PATH]; + + CoInitialize(NULL); + + if (SUCCEEDED( CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl ) )) + { + IPersistFile *ppf; + + if (SUCCEEDED(psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf))) + { + WCHAR wpath[MAX_PATH]; + + MultiByteToWideChar(CP_ACP, 0, path, -1, wpath, MAX_PATH); + + if (SUCCEEDED(ppf->Load(wpath, STGM_READ))) + { + /* Resolve the link */ + if (SUCCEEDED(psl->Resolve(NULL, SLR_ANY_MATCH|SLR_NO_UI|SLR_NOSEARCH))) + { + strcpy(filepath, path); + + if (SUCCEEDED(psl->GetPath(filepath, MAX_PATH, &fd, SLGP_UNCPRIORITY))) + { + OutputDebugString(fd.cFileName); + + strcpy(out, filepath); + // FIX: Release the objects. Taken from SA. +#ifdef FIX_BUGS + ppf->Release(); + psl->Release(); +#endif + return true; + } + } + } + + ppf->Release(); + } + psl->Release(); + } + + return false; +} + +static void +_FindMP3s(void) +{ + tMP3Entry *pList; + bool bShortcut; + bool bInitFirstEntry; + HANDLE hFind; + char path[MAX_PATH]; + char filepath[MAX_PATH*2]; + S32 total_ms; + WIN32_FIND_DATA fd; + + + if ( GetCurrentDirectory(MAX_PATH, _mp3DirectoryPath) == 0 ) + { + GetLastError(); + return; + } + + OutputDebugString("Finding MP3s..."); + strcpy(path, _mp3DirectoryPath); + strcat(path, "\\MP3\\"); + + strcpy(_mp3DirectoryPath, path); + OutputDebugString(_mp3DirectoryPath); + + strcat(path, "*"); + + hFind = FindFirstFile(path, &fd); + + if ( hFind == INVALID_HANDLE_VALUE ) + { + GetLastError(); + return; + } + + strcpy(filepath, _mp3DirectoryPath); + strcat(filepath, fd.cFileName); + + int32 filepathlen = strlen(filepath); + + if ( filepathlen <= 0) + { + FindClose(hFind); + return; + } + + FILE *f = fopen("MP3\\MP3Report.txt", "w"); + + if ( f ) + { + fprintf(f, "MP3 Report File\n\n"); + fprintf(f, "\"%s\"", fd.cFileName); + } + + + if ( filepathlen > 4 ) + { + if ( !strcmp(&filepath[filepathlen - 4], ".lnk") ) + { + if ( _ResolveLink(filepath, filepath) ) + { + OutputDebugString("Resolving Link"); + OutputDebugString(filepath); + + if ( f ) fprintf(f, " - shortcut to \"%s\"", filepath); + } + else + { + if ( f ) fprintf(f, " - couldn't resolve shortcut"); + } + + bShortcut = true; + } + else + bShortcut = false; + } + + mp3Stream[0] = AIL_open_stream(DIG, filepath, 0); + if ( mp3Stream[0] ) + { + AIL_stream_ms_position(mp3Stream[0], &total_ms, NULL); + + AIL_close_stream(mp3Stream[0]); + mp3Stream[0] = NULL; + + OutputDebugString(fd.cFileName); + + _pMP3List = new tMP3Entry; + + if ( _pMP3List == NULL ) + { + FindClose(hFind); + + if ( f ) + fclose(f); + + return; + } + + nNumMP3s = 1; + + strcpy(_pMP3List->aFilename, fd.cFileName); + + _pMP3List->nTrackLength = total_ms; + + _pMP3List->pNext = NULL; + + pList = _pMP3List; + + if ( bShortcut ) + { + _pMP3List->pLinkPath = new char[MAX_PATH*2]; + strcpy(_pMP3List->pLinkPath, filepath); + } + else + { + _pMP3List->pLinkPath = NULL; + } + + if ( f ) fprintf(f, " - OK\n"); + + bInitFirstEntry = false; + } + else + { + strcat(filepath, " - NOT A VALID MP3"); + + OutputDebugString(filepath); + + if ( f ) fprintf(f, " - not an MP3 or supported MP3 type\n"); + + bInitFirstEntry = true; + } + + while ( true ) + { + if ( !FindNextFile(hFind, &fd) ) + break; + + if ( bInitFirstEntry ) + { + strcpy(filepath, _mp3DirectoryPath); + strcat(filepath, fd.cFileName); + + int32 filepathlen = strlen(filepath); + + if ( f ) fprintf(f, "\"%s\"", fd.cFileName); + + if ( filepathlen > 0 ) + { + if ( filepathlen > 4 ) + { + if ( !strcmp(&filepath[filepathlen - 4], ".lnk") ) + { + if ( _ResolveLink(filepath, filepath) ) + { + OutputDebugString("Resolving Link"); + OutputDebugString(filepath); + + if ( f ) fprintf(f, " - shortcut to \"%s\"", filepath); + } + else + { + if ( f ) fprintf(f, " - couldn't resolve shortcut"); + } + + bShortcut = true; + } + else + { + bShortcut = false; + + if ( filepathlen > MAX_PATH ) + { + if ( f ) fprintf(f, " - Filename and path too long - %s - IGNORED)\n", filepath); + + continue; + } + } + } + + mp3Stream[0] = AIL_open_stream(DIG, filepath, 0); + if ( mp3Stream[0] ) + { + AIL_stream_ms_position(mp3Stream[0], &total_ms, NULL); + + AIL_close_stream(mp3Stream[0]); + mp3Stream[0] = NULL; + + OutputDebugString(fd.cFileName); + + _pMP3List = new tMP3Entry; + + if ( _pMP3List == NULL) + break; + + nNumMP3s = 1; + + strcpy(_pMP3List->aFilename, fd.cFileName); + + _pMP3List->nTrackLength = total_ms; + _pMP3List->pNext = NULL; + + if ( bShortcut ) + { + _pMP3List->pLinkPath = new char [MAX_PATH*2]; + strcpy(_pMP3List->pLinkPath, filepath); + } + else + { + _pMP3List->pLinkPath = NULL; + } + + pList = _pMP3List; + + if ( f ) fprintf(f, " - OK\n"); + + bInitFirstEntry = false; + } + else + { + strcat(filepath, " - NOT A VALID MP3"); + OutputDebugString(filepath); + + if ( f ) fprintf(f, " - not an MP3 or supported MP3 type\n"); + } + } + } + else + { + strcpy(filepath, _mp3DirectoryPath); + strcat(filepath, fd.cFileName); + + int32 filepathlen = strlen(filepath); + + if ( filepathlen > 0 ) + { + if ( f ) fprintf(f, "\"%s\"", fd.cFileName); + + if ( filepathlen > 4 ) + { + if ( !strcmp(&filepath[filepathlen - 4], ".lnk") ) + { + if ( _ResolveLink(filepath, filepath) ) + { + OutputDebugString("Resolving Link"); + OutputDebugString(filepath); + + if ( f ) fprintf(f, " - shortcut to \"%s\"", filepath); + } + else + { + if ( f ) fprintf(f, " - couldn't resolve shortcut"); + } + + bShortcut = true; + } + else + { + bShortcut = false; + } + } + + mp3Stream[0] = AIL_open_stream(DIG, filepath, 0); + if ( mp3Stream[0] ) + { + AIL_stream_ms_position(mp3Stream[0], &total_ms, NULL); + + AIL_close_stream(mp3Stream[0]); + mp3Stream[0] = NULL; + + pList->pNext = new tMP3Entry; + + tMP3Entry *e = pList->pNext; + + if ( e == NULL ) + break; + + pList = pList->pNext; + + strcpy(e->aFilename, fd.cFileName); + e->nTrackLength = total_ms; + e->pNext = NULL; + + if ( bShortcut ) + { + e->pLinkPath = new char [MAX_PATH*2]; + strcpy(e->pLinkPath, filepath); + } + else + { + e->pLinkPath = NULL; + } + + nNumMP3s++; + + OutputDebugString(fd.cFileName); + + if ( f ) fprintf(f, " - OK\n"); + } + else + { + strcat(filepath, " - NOT A VALID MP3"); + OutputDebugString(filepath); + + if ( f ) fprintf(f, " - not an MP3 or supported MP3 type\n"); + } + } + } + } + + if ( f ) + { + fprintf(f, "\nTOTAL SUPPORTED MP3s: %d\n", nNumMP3s); + fclose(f); + } + + FindClose(hFind); +} + +static void +_DeleteMP3Entries(void) +{ + tMP3Entry *e = _pMP3List; + + while ( e != NULL ) + { + tMP3Entry *next = e->pNext; + + if ( next == NULL ) + next = NULL; + + if ( e->pLinkPath != NULL ) + { +#ifndef FIX_BUGS + delete e->pLinkPath; // BUG: should be delete [] +#else + delete[] e->pLinkPath; +#endif + e->pLinkPath = NULL; + } + + delete e; + + if ( next ) + e = next; + else + e = NULL; + + nNumMP3s--; + } + + + if ( nNumMP3s != 0 ) + { + OutputDebugString("Not all MP3 entries were deleted"); + nNumMP3s = 0; + } + + _pMP3List = NULL; +} + +static tMP3Entry * +_GetMP3EntryByIndex(uint32 idx) +{ + uint32 n = ( idx < nNumMP3s ) ? idx : 0; + + if ( _pMP3List != NULL ) + { + tMP3Entry *e = _pMP3List; + + for ( uint32 i = 0; i < n; i++ ) + e = e->pNext; + + return e; + + } + + return NULL; +} + +static inline bool +_GetMP3PosFromStreamPos(uint32 *pPosition, tMP3Entry **pEntry) +{ + _CurMP3Index = 0; + + for ( *pEntry = _pMP3List; *pEntry != NULL; *pEntry = (*pEntry)->pNext ) + { + if ( *pPosition >= (*pEntry)->nTrackStreamPos + && *pPosition < (*pEntry)->nTrackLength + (*pEntry)->nTrackStreamPos ) + { + *pPosition -= (*pEntry)->nTrackStreamPos; + _CurMP3Pos = *pPosition; + + return true; + } + + _CurMP3Index++; + } + + *pPosition = 0; + *pEntry = _pMP3List; + _CurMP3Pos = 0; + _CurMP3Index = 0; + + return false; +} + +bool +cSampleManager::IsMP3RadioChannelAvailable(void) +{ + return nNumMP3s != 0; +} + +void +cSampleManager::ReleaseDigitalHandle(void) +{ + if ( DIG ) + { + prevprovider = curprovider; + release_existing(); + curprovider = -1; + AIL_digital_handle_release(DIG); + } +} + +void +cSampleManager::ReacquireDigitalHandle(void) +{ + if ( DIG ) + { + AIL_digital_handle_reacquire(DIG); + if ( prevprovider != -1 ) + set_new_provider(prevprovider); + } +} + +bool +cSampleManager::Initialise(void) +{ + TRACE("start"); + + if ( _bSampmanInitialised ) + return true; + + { + for ( int32 i = 0; i < TOTAL_AUDIO_SAMPLES; i++ ) + { + m_aSamples[i].nOffset = 0; + m_aSamples[i].nSize = 0; + m_aSamples[i].nFrequency = 22050; + m_aSamples[i].nLoopStart = 0; + m_aSamples[i].nLoopEnd = -1; + } + + m_nEffectsVolume = MAX_VOLUME; + m_nMusicVolume = MAX_VOLUME; + m_nEffectsFadeVolume = MAX_VOLUME; + m_nMusicFadeVolume = MAX_VOLUME; + + m_nMonoMode = 0; + } + + // miles + TRACE("MILES"); + { + curprovider = -1; + prevprovider = -1; + + _usingMilesFast2D = false; + usingEAX=0; + usingEAX3=0; + + _fEffectsLevel = 0.0f; + + _maxSamples = 0; + + opened_provider = NULL; + DIG = NULL; + + for ( int32 i = 0; i < MAXCHANNELS; i++ ) + opened_samples[i] = NULL; + } + + // banks + TRACE("banks"); + { + fpSampleDescHandle = NULL; + fpSampleDataHandle = NULL; + + _nSampleDataEndOffset = 0; + + for ( int32 i = 0; i < MAX_SAMPLEBANKS; i++ ) + { + bSampleBankLoaded[i] = false; + nSampleBankDiscStartOffset[i] = 0; + nSampleBankSize[i] = 0; + nSampleBankMemoryStartAddress[i] = 0; + } + } + + // pedsfx + TRACE("pedsfx"); + { + for ( int32 i = 0; i < MAX_PEDSFX; i++ ) + { + nPedSlotSfx[i] = NO_SAMPLE; + nPedSlotSfxAddr[i] = 0; + } + + nCurrentPedSlot = 0; + } + + // channel volume + TRACE("vol"); + { + for ( int32 i = 0; i < MAXCHANNELS+MAX2DCHANNELS; i++ ) + nChannelVolume[i] = 0; + } + + TRACE("mss"); + { + AIL_set_redist_directory( "mss" ); + + AIL_startup(); + + AIL_set_preference(DIG_MIXER_CHANNELS, MAX_DIGITAL_MIXER_CHANNELS); + + DIG = AIL_open_digital_driver(DIGITALRATE, DIGITALBITS, DIGITALCHANNELS, 0); + if ( DIG == NULL ) + { + OutputDebugString(AIL_last_error()); + Terminate(); + return false; + } + + add_providers(); + + if ( !InitialiseSampleBanks() ) + { + Terminate(); + return false; + } + + nSampleBankMemoryStartAddress[SAMPLEBANK_MAIN] = (int32)AIL_mem_alloc_lock(nSampleBankSize[SAMPLEBANK_MAIN]); + if ( !nSampleBankMemoryStartAddress[SAMPLEBANK_MAIN] ) + { + Terminate(); + return false; + } + + nSampleBankMemoryStartAddress[SAMPLEBANK_PED] = (int32)AIL_mem_alloc_lock(PED_BLOCKSIZE*MAX_PEDSFX); + + } + + TRACE("cdrom"); + + S32 tatalms; + char filepath[MAX_PATH]; + + { + m_bInitialised = false; + + while (true) + { + int32 drive = 'C'; + + do + { + char latter[2]; + + latter[0] = drive; + latter[1] = '\0'; + + strcpy(m_szCDRomRootPath, latter); + strcat(m_szCDRomRootPath, ":\\"); + + if ( GetDriveType(m_szCDRomRootPath) == DRIVE_CDROM ) + { + strcpy(filepath, m_szCDRomRootPath); + strcat(filepath, StreamedNameTable[0]); + + FILE *f = fopen(filepath, "rb"); + + if ( f ) + { + fclose(f); + + bool bFileNotFound = false; + + for ( int32 i = 0; i < TOTAL_STREAMED_SOUNDS; i++ ) + { + strcpy(filepath, m_szCDRomRootPath); + strcat(filepath, StreamedNameTable[i]); + + mp3Stream[0] = AIL_open_stream(DIG, filepath, 0); + + if ( mp3Stream[0] ) + { + AIL_stream_ms_position(mp3Stream[0], &tatalms, NULL); + + AIL_close_stream(mp3Stream[0]); + mp3Stream[0] = NULL; + + nStreamLength[i] = tatalms; + } + else + { + bFileNotFound = true; + break; + } + } + + if ( !bFileNotFound ) + { + m_bInitialised = true; + break; + } + else + { + m_bInitialised = false; + continue; + } + } + } + + } while ( ++drive <= 'Z' ); + + if ( !m_bInitialised ) + { +#if !defined(GTA3_STEAM_PATCH) && !defined(NO_CDCHECK) + FrontEndMenuManager.WaitForUserCD(); + if ( FrontEndMenuManager.m_bQuitGameNoCD ) + { + Terminate(); + return false; + } + continue; +#else + m_bInitialised = true; +#endif + } + + break; + } + } + +#if defined(GTA3_1_1_PATCH) || defined(GTA3_STEAM_PATCH) || defined(NO_CDCHECK) + // hddaudio + /** + Option for user to play audio files directly from hard disk. + Copy the contents of the PLAY discs Audio directory into your installed Grand Theft Auto III Audio directory. + Grand Theft Auto III still requires the presence of the PLAY disc when started. + This may give better performance on some machines (though worse on others). + **/ + TRACE("hddaudio 1.1 patch"); + { + int32 streamLength[TOTAL_STREAMED_SOUNDS]; + + bool bFileNotFound = false; + char rootpath[MAX_PATH]; + + strcpy(_aHDDPath, m_szCDRomRootPath); + rootpath[0] = '\0'; + + FILE *f = fopen(StreamedNameTable[0], "rb"); + + if ( f ) + { + fclose(f); + + for ( int32 i = 0; i < TOTAL_STREAMED_SOUNDS; i++ ) + { + strcpy(filepath, rootpath); + strcat(filepath, StreamedNameTable[i]); + + mp3Stream[0] = AIL_open_stream(DIG, filepath, 0); + + if ( mp3Stream[0] ) + { + AIL_stream_ms_position(mp3Stream[0], &tatalms, NULL); + + AIL_close_stream(mp3Stream[0]); + mp3Stream[0] = NULL; + + streamLength[i] = tatalms; + } + else + { + bFileNotFound = true; + break; + } + } + + } + else + bFileNotFound = true; + + if ( !bFileNotFound ) + { + strcpy(m_szCDRomRootPath, rootpath); + + for ( int32 i = 0; i < TOTAL_STREAMED_SOUNDS; i++ ) + nStreamLength[i] = streamLength[i]; + + _bUseHDDAudio = true; + } + else + _bUseHDDAudio = false; + } +#endif + + TRACE("stream"); + { + for ( int32 i = 0; i < MAX_MP3STREAMS; i++ ) + { + mp3Stream [i] = NULL; + nStreamPan [i] = 63; + nStreamVolume[i] = 100; + } + } + + for ( int32 i = 0; i < MAX2DCHANNELS; i++ ) + { + opened_2dsamples[i] = AIL_allocate_sample_handle(DIG); + if ( opened_2dsamples[i] ) + { + AIL_init_sample(opened_2dsamples[i]); + AIL_set_sample_type(opened_2dsamples[i], DIG_F_MONO_16, DIG_PCM_SIGN); + } + } + + TRACE("providerset"); + { + _bSampmanInitialised = true; + + U32 n = 0; + + while ( n < m_nNumberOfProviders ) + { + if ( !strcmp(providers[n].name, "Miles Fast 2D Positional Audio") ) + { + set_new_provider(n); + break; + } + n++; + } + + if ( n == m_nNumberOfProviders ) + { + Terminate(); + return false; + } + } + + TRACE("bank"); + + LoadSampleBank(SAMPLEBANK_MAIN); + + // mp3 + TRACE("mp3"); + { + nNumMP3s = 0; + + _pMP3List = NULL; + + _FindMP3s(); + + if ( nNumMP3s != 0 ) + { + nStreamLength[STREAMED_SOUND_RADIO_MP3_PLAYER] = 0; + + for ( tMP3Entry *e = _pMP3List; e != NULL; e = e->pNext ) + { + e->nTrackStreamPos = nStreamLength[STREAMED_SOUND_RADIO_MP3_PLAYER]; + nStreamLength[STREAMED_SOUND_RADIO_MP3_PLAYER] += e->nTrackLength; + } + + time_t t = time(NULL); + tm *localtm; + bool bUseRandomTable; + + if ( t == -1 ) + bUseRandomTable = true; + else + { + bUseRandomTable = false; + localtm = localtime(&t); + } + + int32 randval; + if ( bUseRandomTable ) + randval = AudioManager.GetRandomNumber(1); + else + randval = localtm->tm_sec * localtm->tm_min; + + _CurMP3Index = randval % nNumMP3s; + + tMP3Entry *randmp3 = _pMP3List; + for ( int32 i = randval % nNumMP3s; i > 0; --i) + randmp3 = randmp3->pNext; + + if ( bUseRandomTable ) + _CurMP3Pos = AudioManager.GetRandomNumber(0) % randmp3->nTrackLength; + else + { + if ( localtm->tm_sec > 0 ) + { + int32 s = localtm->tm_sec; + _CurMP3Pos = s*s*s*s*s*s*s*s % randmp3->nTrackLength; + } + else + _CurMP3Pos = AudioManager.GetRandomNumber(0) % randmp3->nTrackLength; + } + } + else + _CurMP3Pos = 0; + + _bIsMp3Active = false; + } + + TRACE("end"); + + return true; +} + +void +cSampleManager::Terminate(void) +{ + for ( int32 i = 0; i < MAX_MP3STREAMS; i++ ) + { + if ( mp3Stream[i] ) + { + AIL_pause_stream(mp3Stream[i], 1); + AIL_close_stream(mp3Stream[i]); + mp3Stream[i] = NULL; + } + } + + for ( int32 i = 0; i < MAX2DCHANNELS; i++ ) + { + if ( opened_2dsamples[i] ) + { + AIL_release_sample_handle(opened_2dsamples[i]); + opened_2dsamples[i] = NULL; + } + } + + release_existing(); + + _DeleteMP3Entries(); + + if ( nSampleBankMemoryStartAddress[SAMPLEBANK_MAIN] != 0 ) + { + AIL_mem_free_lock((void *)nSampleBankMemoryStartAddress[SAMPLEBANK_MAIN]); + nSampleBankMemoryStartAddress[SAMPLEBANK_MAIN] = 0; + } + + if ( nSampleBankMemoryStartAddress[SAMPLEBANK_PED] != 0 ) + { + AIL_mem_free_lock((void *)nSampleBankMemoryStartAddress[SAMPLEBANK_PED]); + nSampleBankMemoryStartAddress[SAMPLEBANK_PED] = 0; + } + + if ( DIG ) + { + AIL_close_digital_driver(DIG); + DIG = NULL; + } + + AIL_shutdown(); + + _bSampmanInitialised = false; +} + +bool +cSampleManager::CheckForAnAudioFileOnCD(void) +{ +#if !defined(GTA3_STEAM_PATCH) && !defined(NO_CDCHECK) + char filepath[MAX_PATH]; + +#if defined(GTA3_1_1_PATCH) + if (_bUseHDDAudio) + strcpy(filepath, _aHDDPath); + else + strcpy(filepath, m_szCDRomRootPath); +#else + strcpy(filepath, m_szCDRomRootPath); +#endif // #if defined(GTA3_1_1_PATCH) + + strcat(filepath, StreamedNameTable[AudioManager.GetRandomNumber(1) % TOTAL_STREAMED_SOUNDS]); + + FILE *f = fopen(filepath, "rb"); + + if ( f ) + { + fclose(f); + + return true; + } + + return false; + +#else + return true; +#endif // #if !defined(GTA3_STEAM_PATCH) && !defined(NO_CDCHECK) +} + +char +cSampleManager::GetCDAudioDriveLetter(void) +{ +#if defined(GTA3_1_1_PATCH) || defined(GTA3_STEAM_PATCH) || defined(NO_CDCHECK) + if (_bUseHDDAudio) + { + if ( strlen(_aHDDPath) != 0 ) + return _aHDDPath[0]; + else + return '\0'; + } + else + { + if ( strlen(m_szCDRomRootPath) != 0 ) + return m_szCDRomRootPath[0]; + else + return '\0'; + } +#else + if ( strlen(m_szCDRomRootPath) != 0 ) + return m_szCDRomRootPath[0]; + else + return '\0'; +#endif +} + +void +cSampleManager::UpdateEffectsVolume(void) //[Y], cSampleManager::UpdateSoundBuffers ? +{ + if ( _bSampmanInitialised ) + { + for ( int32 i = 0; i < MAXCHANNELS+MAX2DCHANNELS; i++ ) + { + if ( i < MAXCHANNELS ) + { + if ( opened_samples[i] && GetChannelUsedFlag(i) ) + { + if ( nChannelVolume[i] ) + { + AIL_set_3D_sample_volume(opened_samples[i], + m_nEffectsFadeVolume * nChannelVolume[i] * m_nEffectsVolume >> 14); + } + } + } + else + { + if ( opened_2dsamples[i - MAXCHANNELS] ) + { + if ( GetChannelUsedFlag(i - MAXCHANNELS) ) + { + if ( nChannelVolume[i - MAXCHANNELS] ) + { + AIL_set_sample_volume(opened_2dsamples[i - MAXCHANNELS], + m_nEffectsFadeVolume * nChannelVolume[i - MAXCHANNELS] * m_nEffectsVolume >> 14); + } + } + } + } + } + } +} + +void +cSampleManager::SetEffectsMasterVolume(uint8 nVolume) +{ + m_nEffectsVolume = nVolume; + UpdateEffectsVolume(); +} + +void +cSampleManager::SetMusicMasterVolume(uint8 nVolume) +{ + m_nMusicVolume = nVolume; +} + +void +cSampleManager::SetEffectsFadeVolume(uint8 nVolume) +{ + m_nEffectsFadeVolume = nVolume; + UpdateEffectsVolume(); +} + +void +cSampleManager::SetMusicFadeVolume(uint8 nVolume) +{ + m_nMusicFadeVolume = nVolume; +} + +bool +cSampleManager::LoadSampleBank(uint8 nBank) +{ + if ( CTimer::GetIsCodePaused() ) + return false; + + if ( MusicManager.IsInitialised() + && MusicManager.GetMusicMode() == MUSICMODE_CUTSCENE + && nBank != SAMPLEBANK_MAIN ) + { + return false; + } + + if ( fseek(fpSampleDataHandle, nSampleBankDiscStartOffset[nBank], SEEK_SET) != 0 ) + return false; + + if ( fread((void *)nSampleBankMemoryStartAddress[nBank], 1, nSampleBankSize[nBank],fpSampleDataHandle) != nSampleBankSize[nBank] ) + return false; + + bSampleBankLoaded[nBank] = true; + + return true; +} + +void +cSampleManager::UnloadSampleBank(uint8 nBank) +{ + bSampleBankLoaded[nBank] = false; +} + +bool +cSampleManager::IsSampleBankLoaded(uint8 nBank) +{ + return bSampleBankLoaded[nBank]; +} + +bool +cSampleManager::IsPedCommentLoaded(uint32 nComment) +{ + uint8 slot; + + for ( int32 i = 0; i < _TODOCONST(3); i++ ) + { + slot = nCurrentPedSlot - i - 1; + if ( nComment == nPedSlotSfx[slot] ) + return true; + } + + return false; +} + +int32 +cSampleManager::_GetPedCommentSlot(uint32 nComment) +{ + uint8 slot; + + for ( int32 i = 0; i < _TODOCONST(3); i++ ) + { + slot = nCurrentPedSlot - i - 1; + if ( nComment == nPedSlotSfx[slot] ) + return slot; + } + + return -1; +} + +bool +cSampleManager::LoadPedComment(uint32 nComment) +{ + if ( CTimer::GetIsCodePaused() ) + return false; + + // no talking peds during cutsenes or the game end + if ( MusicManager.IsInitialised() ) + { + switch ( MusicManager.GetMusicMode() ) + { + case MUSICMODE_CUTSCENE: + { + return false; + + break; + } + + case MUSICMODE_FRONTEND: + { + if ( MusicManager.GetCurrentTrack() == STREAMED_SOUND_GAME_COMPLETED ) + return false; + + break; + } + } + } + + if ( fseek(fpSampleDataHandle, m_aSamples[nComment].nOffset, SEEK_SET) != 0 ) + return false; + + if ( fread((void *)(nSampleBankMemoryStartAddress[SAMPLEBANK_PED] + PED_BLOCKSIZE*nCurrentPedSlot), 1, m_aSamples[nComment].nSize, fpSampleDataHandle) != m_aSamples[nComment].nSize ) + return false; + + nPedSlotSfxAddr[nCurrentPedSlot] = nSampleBankMemoryStartAddress[SAMPLEBANK_PED] + PED_BLOCKSIZE*nCurrentPedSlot; + nPedSlotSfx [nCurrentPedSlot] = nComment; + + if ( ++nCurrentPedSlot >= MAX_PEDSFX ) + nCurrentPedSlot = 0; + + return true; +} + +int32 +cSampleManager::GetSampleBaseFrequency(uint32 nSample) +{ + return m_aSamples[nSample].nFrequency; +} + +int32 +cSampleManager::GetSampleLoopStartOffset(uint32 nSample) +{ + return m_aSamples[nSample].nLoopStart; +} + +int32 +cSampleManager::GetSampleLoopEndOffset(uint32 nSample) +{ + return m_aSamples[nSample].nLoopEnd; +} + +uint32 +cSampleManager::GetSampleLength(uint32 nSample) +{ + return m_aSamples[nSample].nSize >> 1; +} + +bool +cSampleManager::UpdateReverb(void) +{ + if ( !usingEAX ) + return false; + + if ( AudioManager.GetFrameCounter() & 15 ) + return false; + + float y = AudioManager.GetReflectionsDistance(REFLECTION_TOP) + AudioManager.GetReflectionsDistance(REFLECTION_BOTTOM); + float x = AudioManager.GetReflectionsDistance(REFLECTION_LEFT) + AudioManager.GetReflectionsDistance(REFLECTION_RIGHT); + float z = AudioManager.GetReflectionsDistance(REFLECTION_UP); + + float normy = norm(y, 5.0f, 40.0f); + float normx = norm(x, 5.0f, 40.0f); + float normz = norm(z, 5.0f, 40.0f); + + float fRatio; + + if ( normy == 0.0f ) + { + if ( normx == 0.0f ) + { + if ( normz == 0.0f ) + fRatio = 0.3f; + else + fRatio = 0.5f; + } + else + { + fRatio = 0.3f; + } + } + else + { + if ( normx == 0.0f ) + { + if ( normz == 0.0f ) + fRatio = 0.3f; + else + fRatio = 0.5f; + } + else + { + if ( normz == 0.0f ) + fRatio = 0.3f; + else + fRatio = (normy+normx+normz) / 3.0f; + } + } + + fRatio = clamp(fRatio, usingEAX3==1 ? 0.0f : 0.30f, 1.0f); + + if ( fRatio == _fPrevEaxRatioDestination ) + return false; + + if ( usingEAX3 ) + { + if ( EAX3ListenerInterpolate(&StartEAX3, &FinishEAX3, fRatio, &EAX3Params, false) ) + { + AIL_set_3D_provider_preference(opened_provider, "EAX all parameters", &EAX3Params); + _fEffectsLevel = 1.0f - fRatio * 0.5f; + } + } + else + { + if ( _usingMilesFast2D ) + _fEffectsLevel = (1.0f - fRatio) * 0.4f; + else + _fEffectsLevel = (1.0f - fRatio) * 0.7f; + } + + _fPrevEaxRatioDestination = fRatio; + + return true; +} + +void +cSampleManager::SetChannelReverbFlag(uint32 nChannel, uint8 nReverbFlag) +{ + bool b2d = false; + + switch ( nChannel ) + { + case CHANNEL2D: + { + b2d = true; + break; + } + } + + if ( usingEAX ) + { + if ( nReverbFlag != 0 ) + { + if ( !b2d ) + AIL_set_3D_sample_effects_level(opened_samples[nChannel], _fEffectsLevel); + } + else + { + if ( !b2d ) + AIL_set_3D_sample_effects_level(opened_samples[nChannel], 0.0f); + } + } +} + +bool +cSampleManager::InitialiseChannel(uint32 nChannel, uint32 nSfx, uint8 nBank) +{ + bool b2d = false; + + switch ( nChannel ) + { + case CHANNEL2D: + { + b2d = true; + break; + } + } + + int32 addr; + + if ( nSfx < SAMPLEBANK_MAX ) + { + if ( !IsSampleBankLoaded(nBank) ) + return false; + + addr = nSampleBankMemoryStartAddress[nBank] + m_aSamples[nSfx].nOffset - m_aSamples[BankStartOffset[nBank]].nOffset; + } + else + { + if ( !IsPedCommentLoaded(nSfx) ) + return false; + + int32 slot = _GetPedCommentSlot(nSfx); + + addr = nPedSlotSfxAddr[slot]; + } + + if ( b2d ) + { + if ( opened_2dsamples[nChannel - MAXCHANNELS] ) + { + AIL_set_sample_address(opened_2dsamples[nChannel - MAXCHANNELS], (void *)addr, m_aSamples[nSfx].nSize); + return true; + } + else + return false; + } + else + { + AILSOUNDINFO info; + + info.format = WAVE_FORMAT_PCM; + info.data_ptr = (void *)addr; + info.channels = 1; + info.data_len = m_aSamples[nSfx].nSize; + info.rate = m_aSamples[nSfx].nFrequency; + info.bits = 16; + + if ( AIL_set_3D_sample_info(opened_samples[nChannel], &info) == 0 ) + { + OutputDebugString(AIL_last_error()); + return false; + } + + return true; + } +} + +void +cSampleManager::SetChannelEmittingVolume(uint32 nChannel, uint32 nVolume) +{ + uint32 vol = nVolume; + if ( vol > MAX_VOLUME ) vol = MAX_VOLUME; + + nChannelVolume[nChannel] = vol; + + // increase the volume for JB.MP3 and S4_BDBD.MP3 + if ( MusicManager.GetMusicMode() == MUSICMODE_CUTSCENE + && MusicManager.GetCurrentTrack() != STREAMED_SOUND_NEWS_INTRO + && MusicManager.GetCurrentTrack() != STREAMED_SOUND_CUTSCENE_SAL4_BDBD ) + { + nChannelVolume[nChannel] >>= 2; + } + + if ( opened_samples[nChannel] ) + AIL_set_3D_sample_volume(opened_samples[nChannel], m_nEffectsFadeVolume*nChannelVolume[nChannel]*m_nEffectsVolume >> 14); + +} + +void +cSampleManager::SetChannel3DPosition(uint32 nChannel, float fX, float fY, float fZ) +{ + if ( opened_samples[nChannel] ) + AIL_set_3D_position(opened_samples[nChannel], -fX, fY, fZ); +} + +void +cSampleManager::SetChannel3DDistances(uint32 nChannel, float fMax, float fMin) +{ + if ( opened_samples[nChannel] ) + AIL_set_3D_sample_distances(opened_samples[nChannel], fMax, fMin); +} + +void +cSampleManager::SetChannelVolume(uint32 nChannel, uint32 nVolume) +{ + uint32 vol = nVolume; + if ( vol > MAX_VOLUME ) vol = MAX_VOLUME; + + switch ( nChannel ) + { + case CHANNEL2D: + { + nChannelVolume[nChannel] = vol; + + // increase the volume for JB.MP3 and S4_BDBD.MP3 + if ( MusicManager.GetMusicMode() == MUSICMODE_CUTSCENE + && MusicManager.GetCurrentTrack() != STREAMED_SOUND_NEWS_INTRO + && MusicManager.GetCurrentTrack() != STREAMED_SOUND_CUTSCENE_SAL4_BDBD ) + { + nChannelVolume[nChannel] >>= 2; + } + + if ( opened_2dsamples[nChannel - MAXCHANNELS] ) + { + AIL_set_sample_volume(opened_2dsamples[nChannel - MAXCHANNELS], + m_nEffectsFadeVolume*vol*m_nEffectsVolume >> 14); + } + + break; + } + } +} + +void +cSampleManager::SetChannelPan(uint32 nChannel, uint32 nPan) +{ + switch ( nChannel ) + { + case CHANNEL2D: + { +#ifndef FIX_BUGS + if ( opened_samples[nChannel - MAXCHANNELS] ) // BUG +#else + if ( opened_2dsamples[nChannel - MAXCHANNELS] ) +#endif + AIL_set_sample_pan(opened_2dsamples[nChannel - MAXCHANNELS], nPan); + + break; + } + } +} + +void +cSampleManager::SetChannelFrequency(uint32 nChannel, uint32 nFreq) +{ + bool b2d = false; + + switch ( nChannel ) + { + case CHANNEL2D: + { + b2d = true; + break; + } + } + + if ( b2d ) + { + if ( opened_2dsamples[nChannel - MAXCHANNELS] ) + AIL_set_sample_playback_rate(opened_2dsamples[nChannel - MAXCHANNELS], nFreq); + } + else + { + if ( opened_samples[nChannel] ) + AIL_set_3D_sample_playback_rate(opened_samples[nChannel], nFreq); + } +} + +void +cSampleManager::SetChannelLoopPoints(uint32 nChannel, uint32 nLoopStart, int32 nLoopEnd) +{ + bool b2d = false; + + switch ( nChannel ) + { + case CHANNEL2D: + { + b2d = true; + break; + } + } + + if ( b2d ) + { + if ( opened_2dsamples[nChannel - MAXCHANNELS] ) + AIL_set_sample_loop_block(opened_2dsamples[nChannel - MAXCHANNELS], nLoopStart, nLoopEnd); + } + else + { + if ( opened_samples[nChannel] ) + AIL_set_3D_sample_loop_block(opened_samples[nChannel], nLoopStart, nLoopEnd); + } +} + +void +cSampleManager::SetChannelLoopCount(uint32 nChannel, uint32 nLoopCount) +{ + bool b2d = false; + + switch ( nChannel ) + { + case CHANNEL2D: + { + b2d = true; + break; + } + } + + if ( b2d ) + { + if ( opened_2dsamples[nChannel - MAXCHANNELS] ) + AIL_set_sample_loop_count(opened_2dsamples[nChannel - MAXCHANNELS], nLoopCount); + } + else + { + if ( opened_samples[nChannel] ) + AIL_set_3D_sample_loop_count(opened_samples[nChannel], nLoopCount); + } +} + +bool +cSampleManager::GetChannelUsedFlag(uint32 nChannel) +{ + bool b2d = false; + + switch ( nChannel ) + { + case CHANNEL2D: + { + b2d = true; + break; + } + } + + if ( b2d ) + { + if ( opened_2dsamples[nChannel - MAXCHANNELS] ) + return AIL_sample_status(opened_2dsamples[nChannel - MAXCHANNELS]) == SMP_PLAYING; + else + return false; + } + else + { + if ( opened_samples[nChannel] ) + return AIL_3D_sample_status(opened_samples[nChannel]) == SMP_PLAYING; + else + return false; + } + +} + +void +cSampleManager::StartChannel(uint32 nChannel) +{ + bool b2d = false; + + switch ( nChannel ) + { + case CHANNEL2D: + { + b2d = true; + break; + } + } + + if ( b2d ) + { + if ( opened_2dsamples[nChannel - MAXCHANNELS] ) + AIL_start_sample(opened_2dsamples[nChannel - MAXCHANNELS]); + } + else + { + if ( opened_samples[nChannel] ) + AIL_start_3D_sample(opened_samples[nChannel]); + } +} + +void +cSampleManager::StopChannel(uint32 nChannel) +{ + bool b2d = false; + + switch ( nChannel ) + { + case CHANNEL2D: + { + b2d = true; + break; + } + } + + if ( b2d ) + { + if ( opened_2dsamples[nChannel - MAXCHANNELS] ) + AIL_end_sample(opened_2dsamples[nChannel - MAXCHANNELS]); + } + else + { + if ( opened_samples[nChannel] ) + { + if ( AIL_3D_sample_status(opened_samples[nChannel]) == SMP_PLAYING ) + AIL_end_3D_sample(opened_samples[nChannel]); + } + } +} + +void +cSampleManager::PreloadStreamedFile(uint8 nFile, uint8 nStream) +{ + if ( m_bInitialised ) + { + if ( nFile < TOTAL_STREAMED_SOUNDS ) + { + if ( mp3Stream[nStream] ) + { + AIL_pause_stream(mp3Stream[nStream], 1); + AIL_close_stream(mp3Stream[nStream]); + } + + char filepath[MAX_PATH]; + + strcpy(filepath, m_szCDRomRootPath); + strcat(filepath, StreamedNameTable[nFile]); + + mp3Stream[nStream] = AIL_open_stream(DIG, filepath, 0); + + if ( mp3Stream[nStream] ) + { + AIL_set_stream_loop_count(mp3Stream[nStream], 1); + AIL_service_stream(mp3Stream[nStream], 1); + } + else + OutputDebugString(AIL_last_error()); + } + } +} + +void +cSampleManager::PauseStream(uint8 nPauseFlag, uint8 nStream) +{ + if ( m_bInitialised ) + { + if ( mp3Stream[nStream] ) + AIL_pause_stream(mp3Stream[nStream], nPauseFlag != 0); + } +} + +void +cSampleManager::StartPreloadedStreamedFile(uint8 nStream) +{ + if ( m_bInitialised ) + { + if ( mp3Stream[nStream] ) + AIL_start_stream(mp3Stream[nStream]); + } +} + +bool +cSampleManager::StartStreamedFile(uint8 nFile, uint32 nPos, uint8 nStream) +{ + uint32 position = nPos; + char filename[MAX_PATH]; + + if ( m_bInitialised && nFile < TOTAL_STREAMED_SOUNDS ) + { + if ( mp3Stream[nStream] ) + { + AIL_pause_stream(mp3Stream[nStream], 1); + AIL_close_stream(mp3Stream[nStream]); + } + + if ( nFile == STREAMED_SOUND_RADIO_MP3_PLAYER ) + { + uint32 i = 0; + do { + if(i != 0 || _bIsMp3Active) { + if(++_CurMP3Index >= nNumMP3s) _CurMP3Index = 0; + + _CurMP3Pos = 0; + + tMP3Entry *mp3 = _GetMP3EntryByIndex(_CurMP3Index); + + if(mp3) { + mp3 = _pMP3List; + if(mp3 == NULL) { + _bIsMp3Active = false; + nFile = 0; + strcpy(filename, m_szCDRomRootPath); + strcat(filename, StreamedNameTable[nFile]); + + mp3Stream[nStream] = + AIL_open_stream(DIG, filename, 0); + if(mp3Stream[nStream]) { + AIL_set_stream_loop_count( + mp3Stream[nStream], 1); + AIL_set_stream_ms_position( + mp3Stream[nStream], position); + AIL_pause_stream(mp3Stream[nStream], + 0); + return true; + } + + return false; + } + } + + if(mp3->pLinkPath != NULL) + mp3Stream[nStream] = + AIL_open_stream(DIG, mp3->pLinkPath, 0); + else { + strcpy(filename, _mp3DirectoryPath); + strcat(filename, mp3->aFilename); + + mp3Stream[nStream] = + AIL_open_stream(DIG, filename, 0); + } + + if(mp3Stream[nStream]) { + AIL_set_stream_loop_count(mp3Stream[nStream], 1); + AIL_set_stream_ms_position(mp3Stream[nStream], 0); + AIL_pause_stream(mp3Stream[nStream], 0); + return true; + } + + _bIsMp3Active = false; + continue; + } + if ( nPos > nStreamLength[STREAMED_SOUND_RADIO_MP3_PLAYER] ) + position = 0; + + tMP3Entry *e; + if ( !_GetMP3PosFromStreamPos(&position, &e) ) + { + if ( e == NULL ) + { + nFile = 0; + strcpy(filename, m_szCDRomRootPath); + strcat(filename, StreamedNameTable[nFile]); + mp3Stream[nStream] = + AIL_open_stream(DIG, filename, 0); + if(mp3Stream[nStream]) { + AIL_set_stream_loop_count( + mp3Stream[nStream], 1); + AIL_set_stream_ms_position( + mp3Stream[nStream], position); + AIL_pause_stream(mp3Stream[nStream], 0); + return true; + } + + return false; + } + } + + if ( e->pLinkPath != NULL ) + mp3Stream[nStream] = AIL_open_stream(DIG, e->pLinkPath, 0); + else + { + strcpy(filename, _mp3DirectoryPath); + strcat(filename, e->aFilename); + + mp3Stream[nStream] = AIL_open_stream(DIG, filename, 0); + } + + if ( mp3Stream[nStream] ) + { + AIL_set_stream_loop_count(mp3Stream[nStream], 1); + AIL_set_stream_ms_position(mp3Stream[nStream], position); + AIL_pause_stream(mp3Stream[nStream], 0); + + _bIsMp3Active = true; + + return true; + } + + _bIsMp3Active = false; + + } while(++i < nNumMP3s); + + position = 0; + nFile = 0; + } + + strcpy(filename, m_szCDRomRootPath); + strcat(filename, StreamedNameTable[nFile]); + + mp3Stream[nStream] = AIL_open_stream(DIG, filename, 0); + if ( mp3Stream[nStream] ) + { + AIL_set_stream_loop_count(mp3Stream[nStream], 1); + AIL_set_stream_ms_position(mp3Stream[nStream], position); + AIL_pause_stream(mp3Stream[nStream], 0); + return true; + } + } + + return false; +} + +void +cSampleManager::StopStreamedFile(uint8 nStream) +{ + if ( m_bInitialised ) + { + if ( mp3Stream[nStream] ) + { + AIL_pause_stream(mp3Stream[nStream], 1); + + AIL_close_stream(mp3Stream[nStream]); + mp3Stream[nStream] = NULL; + + if ( nStream == 0 ) + _bIsMp3Active = false; + } + } +} + +int32 +cSampleManager::GetStreamedFilePosition(uint8 nStream) +{ + S32 currentms; + + if ( m_bInitialised ) + { + if ( mp3Stream[nStream] ) + { + if ( _bIsMp3Active ) + { + tMP3Entry *mp3 = _GetMP3EntryByIndex(_CurMP3Index); + + if ( mp3 != NULL ) + { + AIL_stream_ms_position(mp3Stream[nStream], NULL, ¤tms); + return currentms + mp3->nTrackStreamPos; + } + else + return 0; + } + else + { + AIL_stream_ms_position(mp3Stream[nStream], NULL, ¤tms); + return currentms; + } + } + } + + return 0; +} + +void +cSampleManager::SetStreamedVolumeAndPan(uint8 nVolume, uint8 nPan, uint8 nEffectFlag, uint8 nStream) +{ + uint8 vol = nVolume; + + if ( m_bInitialised ) + { + if ( vol > MAX_VOLUME ) vol = MAX_VOLUME; + if ( vol > MAX_VOLUME ) vol = MAX_VOLUME; + + nStreamVolume[nStream] = vol; + nStreamPan[nStream] = nPan; + + if ( mp3Stream[nStream] ) + { + if ( nEffectFlag ) + AIL_set_stream_volume(mp3Stream[nStream], m_nEffectsFadeVolume*vol*m_nEffectsVolume >> 14); + else + AIL_set_stream_volume(mp3Stream[nStream], m_nMusicFadeVolume*vol*m_nMusicVolume >> 14); + + AIL_set_stream_pan(mp3Stream[nStream], nPan); + } + } +} + +int32 +cSampleManager::GetStreamedFileLength(uint8 nStream) +{ + if ( m_bInitialised ) + return nStreamLength[nStream]; + + return 0; +} + +bool +cSampleManager::IsStreamPlaying(uint8 nStream) +{ + if ( m_bInitialised ) + { + if ( mp3Stream[nStream] ) + { + if ( AIL_stream_status(mp3Stream[nStream]) == SMP_PLAYING ) + return true; + else + return false; + } + } + + return false; +} + +bool +cSampleManager::InitialiseSampleBanks(void) +{ + int32 nBank = SAMPLEBANK_MAIN; + + fpSampleDescHandle = fopen(SampleBankDescFilename, "rb"); + if ( fpSampleDescHandle == NULL ) + return false; + + fpSampleDataHandle = fopen(SampleBankDataFilename, "rb"); + if ( fpSampleDataHandle == NULL ) + { + fclose(fpSampleDescHandle); + fpSampleDescHandle = NULL; + + return false; + } + + fseek(fpSampleDataHandle, 0, SEEK_END); + _nSampleDataEndOffset = ftell(fpSampleDataHandle); + rewind(fpSampleDataHandle); + + fread(m_aSamples, sizeof(tSample), TOTAL_AUDIO_SAMPLES, fpSampleDescHandle); + + fclose(fpSampleDescHandle); + fpSampleDescHandle = NULL; + + for ( int32 i = 0; i < TOTAL_AUDIO_SAMPLES; i++ ) + { +#ifdef FIX_BUGS + if (nBank >= MAX_SAMPLEBANKS) break; +#endif + if ( BankStartOffset[nBank] == BankStartOffset[SAMPLEBANK_MAIN] + i ) + { + nSampleBankDiscStartOffset[nBank] = m_aSamples[i].nOffset; + nBank++; + } + } + + nSampleBankSize[SAMPLEBANK_MAIN] = nSampleBankDiscStartOffset[SAMPLEBANK_PED] - nSampleBankDiscStartOffset[SAMPLEBANK_MAIN]; + nSampleBankSize[SAMPLEBANK_PED] = _nSampleDataEndOffset - nSampleBankDiscStartOffset[SAMPLEBANK_PED]; + + return true; +} diff --git a/src/audio/miles/sampman_mss.h b/src/audio/miles/sampman_mss.h new file mode 100644 index 00000000..ebedfb63 --- /dev/null +++ b/src/audio/miles/sampman_mss.h @@ -0,0 +1,339 @@ +#pragma once +#include "common.h" +#include "AudioSamples.h" + +#define MAX_VOLUME 127 + +struct tSample { + int32 nOffset; + uint32 nSize; + int32 nFrequency; + int32 nLoopStart; + int32 nLoopEnd; +}; + +enum +{ + SAMPLEBANK_MAIN, + SAMPLEBANK_PED, + MAX_SAMPLEBANKS, + SAMPLEBANK_INVALID +}; + +#define MAX_PEDSFX 7 +#define PED_BLOCKSIZE 79000 + +#define MAXPROVIDERS 64 + +#define MAXCHANNELS 28 +#define MAXCHANNELS_SURROUND 24 +#define MAX2DCHANNELS 1 +#define CHANNEL2D MAXCHANNELS + +#define MAX_MP3STREAMS 2 + +#define DIGITALRATE 32000 +#define DIGITALBITS 16 +#define DIGITALCHANNELS 2 + +#define MAX_DIGITAL_MIXER_CHANNELS 32 + +class cSampleManager +{ + uint8 m_nEffectsVolume; + uint8 m_nMusicVolume; + uint8 m_nEffectsFadeVolume; + uint8 m_nMusicFadeVolume; + uint8 m_nMonoMode; + char unk; + char m_szCDRomRootPath[80]; + bool m_bInitialised; + uint8 m_nNumberOfProviders; + char *m_aAudioProviders[MAXPROVIDERS]; + tSample m_aSamples[TOTAL_AUDIO_SAMPLES]; + +public: + + + + cSampleManager(void) : + m_nNumberOfProviders(0) + { } + + ~cSampleManager(void) + { } + + void SetSpeakerConfig(int32 nConfig); + uint32 GetMaximumSupportedChannels(void); + + uint32 GetNum3DProvidersAvailable() { return m_nNumberOfProviders; } + void SetNum3DProvidersAvailable(uint32 num) { m_nNumberOfProviders = num; } + + char *Get3DProviderName(uint8 id) { return m_aAudioProviders[id]; } + void Set3DProviderName(uint8 id, char *name) { m_aAudioProviders[id] = name; } + + int8 GetCurrent3DProviderIndex(void); + int8 SetCurrent3DProvider(uint8 which); + + bool IsMP3RadioChannelAvailable(void); + + void ReleaseDigitalHandle (void); + void ReacquireDigitalHandle(void); + + bool Initialise(void); + void Terminate (void); + + bool CheckForAnAudioFileOnCD(void); + char GetCDAudioDriveLetter (void); + + void UpdateEffectsVolume(void); + + void SetEffectsMasterVolume(uint8 nVolume); + void SetMusicMasterVolume (uint8 nVolume); + void SetEffectsFadeVolume (uint8 nVolume); + void SetMusicFadeVolume (uint8 nVolume); + + bool LoadSampleBank (uint8 nBank); + void UnloadSampleBank (uint8 nBank); + bool IsSampleBankLoaded(uint8 nBank); + + bool IsPedCommentLoaded(uint32 nComment); + bool LoadPedComment (uint32 nComment); + + int32 _GetPedCommentSlot(uint32 nComment); + + int32 GetSampleBaseFrequency (uint32 nSample); + int32 GetSampleLoopStartOffset(uint32 nSample); + int32 GetSampleLoopEndOffset (uint32 nSample); + uint32 GetSampleLength (uint32 nSample); + + bool UpdateReverb(void); + + void SetChannelReverbFlag (uint32 nChannel, uint8 nReverbFlag); + bool InitialiseChannel (uint32 nChannel, uint32 nSfx, uint8 nBank); + void SetChannelEmittingVolume(uint32 nChannel, uint32 nVolume); + void SetChannel3DPosition (uint32 nChannel, float fX, float fY, float fZ); + void SetChannel3DDistances (uint32 nChannel, float fMax, float fMin); + void SetChannelVolume (uint32 nChannel, uint32 nVolume); + void SetChannelPan (uint32 nChannel, uint32 nPan); + void SetChannelFrequency (uint32 nChannel, uint32 nFreq); + void SetChannelLoopPoints (uint32 nChannel, uint32 nLoopStart, int32 nLoopEnd); + void SetChannelLoopCount (uint32 nChannel, uint32 nLoopCount); + bool GetChannelUsedFlag (uint32 nChannel); + void StartChannel (uint32 nChannel); + void StopChannel (uint32 nChannel); + + void PreloadStreamedFile (uint8 nFile, uint8 nStream); + void PauseStream (uint8 nPauseFlag, uint8 nStream); + void StartPreloadedStreamedFile (uint8 nStream); + bool StartStreamedFile (uint8 nFile, uint32 nPos, uint8 nStream); + void StopStreamedFile (uint8 nStream); + int32 GetStreamedFilePosition (uint8 nStream); + void SetStreamedVolumeAndPan(uint8 nVolume, uint8 nPan, uint8 nEffectFlag, uint8 nStream); + int32 GetStreamedFileLength (uint8 nStream); + bool IsStreamPlaying (uint8 nStream); + bool InitialiseSampleBanks(void); +}; + +extern cSampleManager SampleManager; +extern int32 BankStartOffset[MAX_SAMPLEBANKS]; + +static char StreamedNameTable[][25]= +{ + "AUDIO\\HEAD.WAV", + "AUDIO\\CLASS.WAV", + "AUDIO\\KJAH.WAV", + "AUDIO\\RISE.WAV", + "AUDIO\\LIPS.WAV", + "AUDIO\\GAME.WAV", + "AUDIO\\MSX.WAV", + "AUDIO\\FLASH.WAV", + "AUDIO\\CHAT.WAV", + "AUDIO\\HEAD.WAV", + "AUDIO\\POLICE.WAV", + "AUDIO\\CITY.WAV", + "AUDIO\\WATER.WAV", + "AUDIO\\COMOPEN.WAV", + "AUDIO\\SUBOPEN.WAV", + "AUDIO\\JB.MP3", + "AUDIO\\BET.MP3", + "AUDIO\\L1_LG.MP3", + "AUDIO\\L2_DSB.MP3", + "AUDIO\\L3_DM.MP3", + "AUDIO\\L4_PAP.MP3", + "AUDIO\\L5_TFB.MP3", + "AUDIO\\J0_DM2.MP3", + "AUDIO\\J1_LFL.MP3", + "AUDIO\\J2_KCL.MP3", + "AUDIO\\J3_VH.MP3", + "AUDIO\\J4_ETH.MP3", + "AUDIO\\J5_DST.MP3", + "AUDIO\\J6_TBJ.MP3", + "AUDIO\\T1_TOL.MP3", + "AUDIO\\T2_TPU.MP3", + "AUDIO\\T3_MAS.MP3", + "AUDIO\\T4_TAT.MP3", + "AUDIO\\T5_BF.MP3", + "AUDIO\\S0_MAS.MP3", + "AUDIO\\S1_PF.MP3", + "AUDIO\\S2_CTG.MP3", + "AUDIO\\S3_RTC.MP3", + "AUDIO\\S5_LRQ.MP3", + "AUDIO\\S4_BDBA.MP3", + "AUDIO\\S4_BDBB.MP3", + "AUDIO\\S2_CTG2.MP3", + "AUDIO\\S4_BDBD.MP3", + "AUDIO\\S5_LRQB.MP3", + "AUDIO\\S5_LRQC.MP3", + "AUDIO\\A1_SSO.WAV", + "AUDIO\\A2_PP.WAV", + "AUDIO\\A3_SS.WAV", + "AUDIO\\A4_PDR.WAV", + "AUDIO\\A5_K2FT.WAV", + "AUDIO\\K1_KBO.MP3", + "AUDIO\\K2_GIS.MP3", + "AUDIO\\K3_DS.MP3", + "AUDIO\\K4_SHI.MP3", + "AUDIO\\K5_SD.MP3", + "AUDIO\\R0_PDR2.MP3", + "AUDIO\\R1_SW.MP3", + "AUDIO\\R2_AP.MP3", + "AUDIO\\R3_ED.MP3", + "AUDIO\\R4_GF.MP3", + "AUDIO\\R5_PB.MP3", + "AUDIO\\R6_MM.MP3", + "AUDIO\\D1_STOG.MP3", + "AUDIO\\D2_KK.MP3", + "AUDIO\\D3_ADO.MP3", + "AUDIO\\D5_ES.MP3", + "AUDIO\\D7_MLD.MP3", + "AUDIO\\D4_GTA.MP3", + "AUDIO\\D4_GTA2.MP3", + "AUDIO\\D6_STS.MP3", + "AUDIO\\A6_BAIT.WAV", + "AUDIO\\A7_ETG.WAV", + "AUDIO\\A8_PS.WAV", + "AUDIO\\A9_ASD.WAV", + "AUDIO\\K4_SHI2.MP3", + "AUDIO\\C1_TEX.MP3", + "AUDIO\\EL_PH1.MP3", + "AUDIO\\EL_PH2.MP3", + "AUDIO\\EL_PH3.MP3", + "AUDIO\\EL_PH4.MP3", + "AUDIO\\YD_PH1.MP3", + "AUDIO\\YD_PH2.MP3", + "AUDIO\\YD_PH3.MP3", + "AUDIO\\YD_PH4.MP3", + "AUDIO\\HD_PH1.MP3", + "AUDIO\\HD_PH2.MP3", + "AUDIO\\HD_PH3.MP3", + "AUDIO\\HD_PH4.MP3", + "AUDIO\\HD_PH5.MP3", + "AUDIO\\MT_PH1.MP3", + "AUDIO\\MT_PH2.MP3", + "AUDIO\\MT_PH3.MP3", + "AUDIO\\MT_PH4.MP3", + "AUDIO\\MISCOM.WAV", + "AUDIO\\END.MP3", + "AUDIO\\lib_a1.WAV", + "AUDIO\\lib_a2.WAV", + "AUDIO\\lib_a.WAV", + "AUDIO\\lib_b.WAV", + "AUDIO\\lib_c.WAV", + "AUDIO\\lib_d.WAV", + "AUDIO\\l2_a.WAV", + "AUDIO\\j4t_1.WAV", + "AUDIO\\j4t_2.WAV", + "AUDIO\\j4t_3.WAV", + "AUDIO\\j4t_4.WAV", + "AUDIO\\j4_a.WAV", + "AUDIO\\j4_b.WAV", + "AUDIO\\j4_c.WAV", + "AUDIO\\j4_d.WAV", + "AUDIO\\j4_e.WAV", + "AUDIO\\j4_f.WAV", + "AUDIO\\j6_1.WAV", + "AUDIO\\j6_a.WAV", + "AUDIO\\j6_b.WAV", + "AUDIO\\j6_c.WAV", + "AUDIO\\j6_d.WAV", + "AUDIO\\t4_a.WAV", + "AUDIO\\s1_a.WAV", + "AUDIO\\s1_a1.WAV", + "AUDIO\\s1_b.WAV", + "AUDIO\\s1_c.WAV", + "AUDIO\\s1_c1.WAV", + "AUDIO\\s1_d.WAV", + "AUDIO\\s1_e.WAV", + "AUDIO\\s1_f.WAV", + "AUDIO\\s1_g.WAV", + "AUDIO\\s1_h.WAV", + "AUDIO\\s1_i.WAV", + "AUDIO\\s1_j.WAV", + "AUDIO\\s1_k.WAV", + "AUDIO\\s1_l.WAV", + "AUDIO\\s3_a.WAV", + "AUDIO\\s3_b.WAV", + "AUDIO\\el3_a.WAV", + "AUDIO\\mf1_a.WAV", + "AUDIO\\mf2_a.WAV", + "AUDIO\\mf3_a.WAV", + "AUDIO\\mf3_b.WAV", + "AUDIO\\mf3_b1.WAV", + "AUDIO\\mf3_c.WAV", + "AUDIO\\mf4_a.WAV", + "AUDIO\\mf4_b.WAV", + "AUDIO\\mf4_c.WAV", + "AUDIO\\a1_a.WAV", + "AUDIO\\a3_a.WAV", + "AUDIO\\a5_a.WAV", + "AUDIO\\a4_a.WAV", + "AUDIO\\a4_b.WAV", + "AUDIO\\a4_c.WAV", + "AUDIO\\a4_d.WAV", + "AUDIO\\k1_a.WAV", + "AUDIO\\k3_a.WAV", + "AUDIO\\r1_a.WAV", + "AUDIO\\r2_a.WAV", + "AUDIO\\r2_b.WAV", + "AUDIO\\r2_c.WAV", + "AUDIO\\r2_d.WAV", + "AUDIO\\r2_e.WAV", + "AUDIO\\r2_f.WAV", + "AUDIO\\r2_g.WAV", + "AUDIO\\r2_h.WAV", + "AUDIO\\r5_a.WAV", + "AUDIO\\r6_a.WAV", + "AUDIO\\r6_a1.WAV", + "AUDIO\\r6_b.WAV", + "AUDIO\\lo2_a.WAV", + "AUDIO\\lo6_a.WAV", + "AUDIO\\yd2_a.WAV", + "AUDIO\\yd2_b.WAV", + "AUDIO\\yd2_c.WAV", + "AUDIO\\yd2_c1.WAV", + "AUDIO\\yd2_d.WAV", + "AUDIO\\yd2_e.WAV", + "AUDIO\\yd2_f.WAV", + "AUDIO\\yd2_g.WAV", + "AUDIO\\yd2_h.WAV", + "AUDIO\\yd2_ass.WAV", + "AUDIO\\yd2_ok.WAV", + "AUDIO\\h5_a.WAV", + "AUDIO\\h5_b.WAV", + "AUDIO\\h5_c.WAV", + "AUDIO\\ammu_a.WAV", + "AUDIO\\ammu_b.WAV", + "AUDIO\\ammu_c.WAV", + "AUDIO\\door_1.WAV", + "AUDIO\\door_2.WAV", + "AUDIO\\door_3.WAV", + "AUDIO\\door_4.WAV", + "AUDIO\\door_5.WAV", + "AUDIO\\door_6.WAV", + "AUDIO\\t3_a.WAV", + "AUDIO\\t3_b.WAV", + "AUDIO\\t3_c.WAV", + "AUDIO\\k1_b.WAV", + "AUDIO\\cat1.WAV" +}; |