mirror of
https://github.com/TombEngine/TombEngine.git
synced 2025-04-30 00:37:58 +03:00
Refactor and fix sound code
This commit is contained in:
parent
feae212cef
commit
d470cdcf01
11 changed files with 240 additions and 238 deletions
|
@ -1249,9 +1249,9 @@ void AnimateLara(ITEM_INFO* item)
|
||||||
}
|
}
|
||||||
|
|
||||||
flags = cmd[1] & 0xC000;
|
flags = cmd[1] & 0xC000;
|
||||||
if (flags == SFX_LANDANDWATER ||
|
if ( flags == (int)SOUND_PLAYCONDITION::LandAndWater ||
|
||||||
(flags == SFX_LANDONLY && (Lara.waterSurfaceDist >= 0 || Lara.waterSurfaceDist == NO_HEIGHT)) ||
|
(flags == (int)SOUND_PLAYCONDITION::Land && (Lara.waterSurfaceDist >= 0 || Lara.waterSurfaceDist == NO_HEIGHT)) ||
|
||||||
(flags == SFX_WATERONLY && Lara.waterSurfaceDist < 0 && Lara.waterSurfaceDist != NO_HEIGHT && !(g_Level.Rooms[LaraItem->roomNumber].flags & ENV_FLAG_SWAMP)))
|
(flags == (int)SOUND_PLAYCONDITION::Water && Lara.waterSurfaceDist < 0 && Lara.waterSurfaceDist != NO_HEIGHT && !(g_Level.Rooms[LaraItem->roomNumber].flags & ENV_FLAG_SWAMP)))
|
||||||
{
|
{
|
||||||
SoundEffect(cmd[1] & 0x3FFF, &item->pos, 2);
|
SoundEffect(cmd[1] & 0x3FFF, &item->pos, 2);
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,12 +121,12 @@ void AnimateItem(ITEM_INFO* item)
|
||||||
}
|
}
|
||||||
else if (g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_WATER)
|
else if (g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_WATER)
|
||||||
{
|
{
|
||||||
if (!flags || flags == SFX_WATERONLY && (g_Level.Rooms[Camera.pos.roomNumber].flags & ENV_FLAG_WATER || Objects[item->objectNumber].intelligent))
|
if (!flags || flags == (int)SOUND_PLAYCONDITION::Water && (g_Level.Rooms[Camera.pos.roomNumber].flags & ENV_FLAG_WATER || Objects[item->objectNumber].intelligent))
|
||||||
{
|
{
|
||||||
SoundEffect(cmd[1] & 0x3FFF, &item->pos, 2);
|
SoundEffect(cmd[1] & 0x3FFF, &item->pos, 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!flags || flags == SFX_LANDONLY && !(g_Level.Rooms[Camera.pos.roomNumber].flags & ENV_FLAG_WATER))
|
else if (!flags || flags == (int)SOUND_PLAYCONDITION::Land && !(g_Level.Rooms[Camera.pos.roomNumber].flags & ENV_FLAG_WATER))
|
||||||
{
|
{
|
||||||
SoundEffect(cmd[1] & 0x3FFF, &item->pos, 2);
|
SoundEffect(cmd[1] & 0x3FFF, &item->pos, 2);
|
||||||
}
|
}
|
||||||
|
|
|
@ -143,7 +143,7 @@ GAME_STATUS ControlPhase(int numFrames, int demoMode)
|
||||||
{
|
{
|
||||||
if (TrInput & IN_SAVE && LaraItem->hitPoints > 0 && g_Inventory.Get_invMode() != IM_SAVE)
|
if (TrInput & IN_SAVE && LaraItem->hitPoints > 0 && g_Inventory.Get_invMode() != IM_SAVE)
|
||||||
{
|
{
|
||||||
Sound_Stop();
|
StopAllSounds();
|
||||||
|
|
||||||
g_Inventory.Set_invMode(IM_SAVE);
|
g_Inventory.Set_invMode(IM_SAVE);
|
||||||
|
|
||||||
|
@ -152,7 +152,7 @@ GAME_STATUS ControlPhase(int numFrames, int demoMode)
|
||||||
}
|
}
|
||||||
else if (TrInput & IN_LOAD && g_Inventory.Get_invMode() != IM_LOAD)
|
else if (TrInput & IN_LOAD && g_Inventory.Get_invMode() != IM_LOAD)
|
||||||
{
|
{
|
||||||
Sound_Stop();
|
StopAllSounds();
|
||||||
|
|
||||||
g_Inventory.Set_invMode(IM_LOAD);
|
g_Inventory.Set_invMode(IM_LOAD);
|
||||||
|
|
||||||
|
@ -161,7 +161,7 @@ GAME_STATUS ControlPhase(int numFrames, int demoMode)
|
||||||
}
|
}
|
||||||
else if (TrInput & IN_PAUSE && g_Inventory.Get_invMode() != IM_PAUSE && LaraItem->hitPoints > 0)
|
else if (TrInput & IN_PAUSE && g_Inventory.Get_invMode() != IM_PAUSE && LaraItem->hitPoints > 0)
|
||||||
{
|
{
|
||||||
Sound_Stop();
|
StopAllSounds();
|
||||||
g_Renderer.DumpGameScene();
|
g_Renderer.DumpGameScene();
|
||||||
g_Inventory.Set_invMode(IM_PAUSE);
|
g_Inventory.Set_invMode(IM_PAUSE);
|
||||||
g_Inventory.Set_pause_menu_to_display(pause_main_menu);
|
g_Inventory.Set_pause_menu_to_display(pause_main_menu);
|
||||||
|
@ -170,7 +170,7 @@ GAME_STATUS ControlPhase(int numFrames, int demoMode)
|
||||||
else if ((DbInput & IN_DESELECT || g_Inventory.Get_enterInventory() != NO_ITEM) && LaraItem->hitPoints > 0)
|
else if ((DbInput & IN_DESELECT || g_Inventory.Get_enterInventory() != NO_ITEM) && LaraItem->hitPoints > 0)
|
||||||
{
|
{
|
||||||
// Stop all sounds
|
// Stop all sounds
|
||||||
Sound_Stop();
|
StopAllSounds();
|
||||||
|
|
||||||
if (g_Inventory.S_CallInventory2(1))
|
if (g_Inventory.S_CallInventory2(1))
|
||||||
return GAME_STATUS::GAME_STATUS_LOAD_GAME;
|
return GAME_STATUS::GAME_STATUS_LOAD_GAME;
|
||||||
|
@ -473,7 +473,7 @@ GAME_STATUS DoTitle(int index)
|
||||||
InitialiseFXArray(true);
|
InitialiseFXArray(true);
|
||||||
InitialisePickupDisplay();
|
InitialisePickupDisplay();
|
||||||
InitialiseCamera();
|
InitialiseCamera();
|
||||||
Sound_Stop();
|
StopAllSounds();
|
||||||
|
|
||||||
// Run the level script
|
// Run the level script
|
||||||
GameScriptLevel* level = g_GameFlow->Levels[index];
|
GameScriptLevel* level = g_GameFlow->Levels[index];
|
||||||
|
@ -506,7 +506,7 @@ GAME_STATUS DoTitle(int index)
|
||||||
UseSpotCam = true;
|
UseSpotCam = true;
|
||||||
|
|
||||||
// Play background music
|
// Play background music
|
||||||
PlaySoundTrack("083_horus", SOUND_TRACK_BGM);
|
PlaySoundTrack(83);
|
||||||
|
|
||||||
// Initialise ponytails
|
// Initialise ponytails
|
||||||
InitialiseHair();
|
InitialiseHair();
|
||||||
|
@ -581,7 +581,7 @@ GAME_STATUS DoLevel(int index, std::string ambient, bool loadFromSavegame)
|
||||||
InitialiseFXArray(true);
|
InitialiseFXArray(true);
|
||||||
InitialisePickupDisplay();
|
InitialisePickupDisplay();
|
||||||
InitialiseCamera();
|
InitialiseCamera();
|
||||||
Sound_Stop();
|
StopAllSounds();
|
||||||
|
|
||||||
// Run the level script
|
// Run the level script
|
||||||
GameScriptLevel* level = g_GameFlow->Levels[index];
|
GameScriptLevel* level = g_GameFlow->Levels[index];
|
||||||
|
@ -637,7 +637,7 @@ GAME_STATUS DoLevel(int index, std::string ambient, bool loadFromSavegame)
|
||||||
InitSpotCamSequences();
|
InitSpotCamSequences();
|
||||||
|
|
||||||
// Play background music
|
// Play background music
|
||||||
PlaySoundTrack(ambient, SOUND_TRACK_BGM);
|
PlaySoundTrack(ambient, SOUNDTRACK_PLAYTYPE::BGM);
|
||||||
|
|
||||||
// Initialise ponytails
|
// Initialise ponytails
|
||||||
InitialiseHair();
|
InitialiseHair();
|
||||||
|
@ -673,7 +673,7 @@ GAME_STATUS DoLevel(int index, std::string ambient, bool loadFromSavegame)
|
||||||
g_GameScript->OnEnd();
|
g_GameScript->OnEnd();
|
||||||
g_GameScript->FreeLevelScripts();
|
g_GameScript->FreeLevelScripts();
|
||||||
// Here is the only way for exiting from the loop
|
// Here is the only way for exiting from the loop
|
||||||
Sound_Stop();
|
StopAllSounds();
|
||||||
StopSoundTracks();
|
StopSoundTracks();
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -980,4 +980,7 @@ void CleanUp()
|
||||||
DisableDripParticles();
|
DisableDripParticles();
|
||||||
DisableBubbles();
|
DisableBubbles();
|
||||||
DisableDebris();
|
DisableDebris();
|
||||||
|
|
||||||
|
// Clear soundtrack masks
|
||||||
|
ClearSoundTrackMasks();
|
||||||
}
|
}
|
|
@ -116,7 +116,7 @@ void AddFootprint(ITEM_INFO* item)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
PHD_VECTOR position;
|
PHD_VECTOR position;
|
||||||
if (FXType == SFX_LANDONLY)
|
if (FXType == (int)SOUND_PLAYCONDITION::Land)
|
||||||
GetLaraJointPosition(&position, LM_LFOOT);
|
GetLaraJointPosition(&position, LM_LFOOT);
|
||||||
else
|
else
|
||||||
GetLaraJointPosition(&position, LM_RFOOT);
|
GetLaraJointPosition(&position, LM_RFOOT);
|
||||||
|
|
|
@ -177,11 +177,7 @@ void ControlTeleporter(short itemNumber)
|
||||||
|
|
||||||
if (item->triggerFlags == 666)
|
if (item->triggerFlags == 666)
|
||||||
{
|
{
|
||||||
if (item->itemFlags[0] == 15)
|
if (item->itemFlags[0] == 70)
|
||||||
{
|
|
||||||
//PlaySoundTrack("xa12_z_10", SOUND_TRACK_ONESHOT);
|
|
||||||
}
|
|
||||||
else if (item->itemFlags[0] == 70)
|
|
||||||
{
|
{
|
||||||
SoundEffect(SFX_TR5_LIFT_HIT_FLOOR1, 0, 0);
|
SoundEffect(SFX_TR5_LIFT_HIT_FLOOR1, 0, 0);
|
||||||
SoundEffect(SFX_TR5_LIFT_HIT_FLOOR2, 0, 0);
|
SoundEffect(SFX_TR5_LIFT_HIT_FLOOR2, 0, 0);
|
||||||
|
|
|
@ -172,12 +172,14 @@ void GameFlow::SetGameFarView(byte val)
|
||||||
void GameFlow::SetAudioTracks(sol::as_table_t<std::vector<GameScriptAudioTrack>>&& src)
|
void GameFlow::SetAudioTracks(sol::as_table_t<std::vector<GameScriptAudioTrack>>&& src)
|
||||||
{
|
{
|
||||||
std::vector<GameScriptAudioTrack> tracks = std::move(src);
|
std::vector<GameScriptAudioTrack> tracks = std::move(src);
|
||||||
|
SoundTracks.clear();
|
||||||
|
|
||||||
for (auto t : tracks) {
|
for (auto t : tracks) {
|
||||||
AudioTrack track;
|
SoundTrackInfo track;
|
||||||
track.Name = t.trackName;
|
track.Name = t.trackName;
|
||||||
track.Mask = 0;
|
track.Mask = 0;
|
||||||
track.looped = t.looped;
|
track.Mode = t.looped ? SOUNDTRACK_PLAYTYPE::BGM : SOUNDTRACK_PLAYTYPE::OneShot;
|
||||||
SoundTracks.insert_or_assign(track.Name, track);
|
SoundTracks.push_back(track);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,8 @@ Functions and callbacks for level-specific logic scripts.
|
||||||
|
|
||||||
static void PlayAudioTrack(std::string const & trackName, sol::optional<bool> looped)
|
static void PlayAudioTrack(std::string const & trackName, sol::optional<bool> looped)
|
||||||
{
|
{
|
||||||
PlaySoundTrack(trackName, looped.value_or(SOUND_TRACK_ONESHOT));
|
auto mode = looped.value_or(false) ? SOUNDTRACK_PLAYTYPE::OneShot : SOUNDTRACK_PLAYTYPE::BGM;
|
||||||
|
PlaySoundTrack(trackName, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PlaySoundEffect(int id, GameScriptPosition p, int flags)
|
static void PlaySoundEffect(int id, GameScriptPosition p, int flags)
|
||||||
|
@ -54,7 +55,7 @@ static void PlaySoundEffect(int id, int flags)
|
||||||
|
|
||||||
static void SetAmbientTrack(std::string const & trackName)
|
static void SetAmbientTrack(std::string const & trackName)
|
||||||
{
|
{
|
||||||
PlaySoundTrack(trackName, SOUND_TRACK_BGM);
|
PlaySoundTrack(trackName, SOUNDTRACK_PLAYTYPE::BGM);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int FindRoomNumber(GameScriptPosition pos)
|
static int FindRoomNumber(GameScriptPosition pos)
|
||||||
|
@ -516,8 +517,8 @@ void AddOneSecret()
|
||||||
{
|
{
|
||||||
if (Savegame.Level.Secrets >= 255)
|
if (Savegame.Level.Secrets >= 255)
|
||||||
return;
|
return;
|
||||||
Savegame.Level.Secrets++;
|
Savegame.Level.Secrets++;
|
||||||
PlaySoundTrack(TRACK_FOUND_SECRET, SOUND_TRACK_ONESHOT);
|
PlaySecretTrack();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -9,17 +9,13 @@
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include "level.h"
|
#include "level.h"
|
||||||
|
|
||||||
using std::vector;
|
|
||||||
using std::unordered_map;
|
|
||||||
using std::string;
|
|
||||||
|
|
||||||
HSTREAM BASS_3D_Mixdown;
|
HSTREAM BASS_3D_Mixdown;
|
||||||
HFX BASS_FXHandler[NUM_SOUND_FILTERS];
|
HFX BASS_FXHandler[(int)SOUND_FILTER::Count];
|
||||||
SoundTrackSlot BASS_Soundtrack[NUM_SOUND_TRACK_TYPES];
|
SoundTrackSlot BASS_Soundtrack[(int)SOUNDTRACK_PLAYTYPE::Count];
|
||||||
HSAMPLE SamplePointer[SOUND_MAX_SAMPLES];
|
HSAMPLE SamplePointer[SOUND_MAX_SAMPLES];
|
||||||
SoundEffectSlot SoundSlot[SOUND_MAX_CHANNELS];
|
SoundEffectSlot SoundSlot[SOUND_MAX_CHANNELS];
|
||||||
|
|
||||||
const BASS_BFX_FREEVERB BASS_ReverbTypes[NUM_REVERB_TYPES] = // Reverb presets
|
const BASS_BFX_FREEVERB BASS_ReverbTypes[(int)REVERB_TYPE::Count] = // Reverb presets
|
||||||
|
|
||||||
{ // Dry Mix | Wet Mix | Size | Damp | Width | Mode | Channel
|
{ // Dry Mix | Wet Mix | Size | Damp | Width | Mode | Channel
|
||||||
{ 1.0f, 0.20f, 0.05f, 0.90f, 0.7f, 0, -1 }, // 0 = Outside
|
{ 1.0f, 0.20f, 0.05f, 0.90f, 0.7f, 0, -1 }, // 0 = Outside
|
||||||
|
@ -29,7 +25,8 @@ const BASS_BFX_FREEVERB BASS_ReverbTypes[NUM_REVERB_TYPES] = // Reverb preset
|
||||||
{ 1.0f, 0.25f, 0.90f, 1.00f, 1.0f, 0, -1 } // 4 = Pipe
|
{ 1.0f, 0.25f, 0.90f, 1.00f, 1.0f, 0, -1 } // 4 = Pipe
|
||||||
};
|
};
|
||||||
|
|
||||||
unordered_map<string, AudioTrack> SoundTracks;
|
std::map<std::string, int> SoundTrackMap;
|
||||||
|
std::vector<SoundTrackInfo> SoundTracks;
|
||||||
std::string CurrentLoopedSoundTrack;
|
std::string CurrentLoopedSoundTrack;
|
||||||
|
|
||||||
static int GlobalMusicVolume;
|
static int GlobalMusicVolume;
|
||||||
|
@ -40,13 +37,13 @@ void SetVolumeMusic(int vol)
|
||||||
GlobalMusicVolume = vol;
|
GlobalMusicVolume = vol;
|
||||||
|
|
||||||
float fVol = static_cast<float>(vol) / 100.0f;
|
float fVol = static_cast<float>(vol) / 100.0f;
|
||||||
if (BASS_ChannelIsActive(BASS_Soundtrack[SOUND_TRACK_BGM].channel))
|
if (BASS_ChannelIsActive(BASS_Soundtrack[(int)SOUNDTRACK_PLAYTYPE::BGM].Channel))
|
||||||
{
|
{
|
||||||
BASS_ChannelSetAttribute(BASS_Soundtrack[SOUND_TRACK_BGM].channel, BASS_ATTRIB_VOL, fVol);
|
BASS_ChannelSetAttribute(BASS_Soundtrack[(int)SOUNDTRACK_PLAYTYPE::BGM].Channel, BASS_ATTRIB_VOL, fVol);
|
||||||
}
|
}
|
||||||
if (BASS_ChannelIsActive(BASS_Soundtrack[SOUND_TRACK_ONESHOT].channel))
|
if (BASS_ChannelIsActive(BASS_Soundtrack[(int)SOUNDTRACK_PLAYTYPE::OneShot].Channel))
|
||||||
{
|
{
|
||||||
BASS_ChannelSetAttribute(BASS_Soundtrack[SOUND_TRACK_ONESHOT].channel, BASS_ATTRIB_VOL, fVol);
|
BASS_ChannelSetAttribute(BASS_Soundtrack[(int)SOUNDTRACK_PLAYTYPE::OneShot].Channel, BASS_ATTRIB_VOL, fVol);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,7 +52,7 @@ void SetVolumeFX(int vol)
|
||||||
GlobalFXVolume = vol;
|
GlobalFXVolume = vol;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Sound_LoadSample(char *pointer, int compSize, int uncompSize, int index)
|
bool LoadSample(char *pointer, int compSize, int uncompSize, int index)
|
||||||
{
|
{
|
||||||
if (index >= SOUND_MAX_SAMPLES)
|
if (index >= SOUND_MAX_SAMPLES)
|
||||||
{
|
{
|
||||||
|
@ -163,9 +160,9 @@ long SoundEffect(int effectID, PHD_3DPOS* position, int env_flags, float pitchMu
|
||||||
else if (sampleIndex == -2)
|
else if (sampleIndex == -2)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
SAMPLE_INFO *sampleInfo = &g_Level.SoundDetails[sampleIndex];
|
SampleInfo* sampleInfo = &g_Level.SoundDetails[sampleIndex];
|
||||||
|
|
||||||
if (sampleInfo->number < 0)
|
if (sampleInfo->Number < 0)
|
||||||
{
|
{
|
||||||
logD("No valid samples count for effect %d", sampleIndex);
|
logD("No valid samples count for effect %d", sampleIndex);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -175,7 +172,7 @@ long SoundEffect(int effectID, PHD_3DPOS* position, int env_flags, float pitchMu
|
||||||
DWORD sampleFlags = SOUND_SAMPLE_FLAGS;
|
DWORD sampleFlags = SOUND_SAMPLE_FLAGS;
|
||||||
|
|
||||||
// Effect's chance to play.
|
// Effect's chance to play.
|
||||||
if ((sampleInfo->randomness) && ((GetRandomControl() & 127) > sampleInfo->randomness))
|
if ((sampleInfo->Randomness) && ((GetRandomControl() & 127) > sampleInfo->Randomness))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// Apply 3D attrib only to sound with position property
|
// Apply 3D attrib only to sound with position property
|
||||||
|
@ -183,19 +180,19 @@ long SoundEffect(int effectID, PHD_3DPOS* position, int env_flags, float pitchMu
|
||||||
sampleFlags |= BASS_SAMPLE_3D;
|
sampleFlags |= BASS_SAMPLE_3D;
|
||||||
|
|
||||||
// Set & randomize volume (if needed)
|
// Set & randomize volume (if needed)
|
||||||
float gain = (static_cast<float>(sampleInfo->volume) / 255.0f) * gainMultiplier;
|
float gain = (static_cast<float>(sampleInfo->Volume) / 255.0f) * gainMultiplier;
|
||||||
if ((sampleInfo->flags & SOUND_FLAG_RND_GAIN))
|
if ((sampleInfo->Flags & SOUND_FLAG_RND_GAIN))
|
||||||
gain -= (static_cast<float>(GetRandomControl()) / static_cast<float>(RAND_MAX))* SOUND_MAX_GAIN_CHANGE;
|
gain -= (static_cast<float>(GetRandomControl()) / static_cast<float>(RAND_MAX))* SOUND_MAX_GAIN_CHANGE;
|
||||||
|
|
||||||
// Set and randomize pitch and additionally multiply by provided value (for vehicles etc)
|
// Set and randomize pitch and additionally multiply by provided value (for vehicles etc)
|
||||||
float pitch = (1.0f + static_cast<float>(sampleInfo->pitch) / 127.0f) * pitchMultiplier;
|
float pitch = (1.0f + static_cast<float>(sampleInfo->Pitch) / 127.0f) * pitchMultiplier;
|
||||||
|
|
||||||
// Randomize pitch (if needed)
|
// Randomize pitch (if needed)
|
||||||
if ((sampleInfo->flags & SOUND_FLAG_RND_PITCH))
|
if ((sampleInfo->Flags & SOUND_FLAG_RND_PITCH))
|
||||||
pitch += ((static_cast<float>(GetRandomControl()) / static_cast<float>(RAND_MAX)) - 0.5f)* SOUND_MAX_PITCH_CHANGE * 2.0f;
|
pitch += ((static_cast<float>(GetRandomControl()) / static_cast<float>(RAND_MAX)) - 0.5f)* SOUND_MAX_PITCH_CHANGE * 2.0f;
|
||||||
|
|
||||||
// Calculate sound radius and distance to sound
|
// Calculate sound radius and distance to sound
|
||||||
float radius = (float)(sampleInfo->radius) * 1024.0f;
|
float radius = (float)(sampleInfo->Radius) * 1024.0f;
|
||||||
float distance = Sound_DistanceToListener(position);
|
float distance = Sound_DistanceToListener(position);
|
||||||
|
|
||||||
// Don't play sound if it's too far from listener's position.
|
// Don't play sound if it's too far from listener's position.
|
||||||
|
@ -209,23 +206,23 @@ long SoundEffect(int effectID, PHD_3DPOS* position, int env_flags, float pitchMu
|
||||||
int existingChannel = Sound_EffectIsPlaying(effectID, position);
|
int existingChannel = Sound_EffectIsPlaying(effectID, position);
|
||||||
|
|
||||||
// Select behaviour based on effect playback type (bytes 0-1 of flags field)
|
// Select behaviour based on effect playback type (bytes 0-1 of flags field)
|
||||||
int playType = sampleInfo->flags & 3;
|
auto playType = (SOUND_PLAYTYPE)(sampleInfo->Flags & 3);
|
||||||
switch (playType)
|
switch (playType)
|
||||||
{
|
{
|
||||||
case SOUND_NORMAL:
|
case SOUND_PLAYTYPE::Normal:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SOUND_WAIT:
|
case SOUND_PLAYTYPE::Wait:
|
||||||
if (existingChannel != -1) // Don't play until stopped
|
if (existingChannel != -1) // Don't play until stopped
|
||||||
return 0;
|
return 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SOUND_RESTART:
|
case SOUND_PLAYTYPE::Restart:
|
||||||
if (existingChannel != -1) // Stop existing and continue
|
if (existingChannel != -1) // Stop existing and continue
|
||||||
Sound_FreeSlot(existingChannel, SOUND_XFADETIME_CUTSOUND);
|
Sound_FreeSlot(existingChannel, SOUND_XFADETIME_CUTSOUND);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SOUND_LOOPED:
|
case SOUND_PLAYTYPE::Looped:
|
||||||
if (existingChannel != -1) // Just update parameters and return, if already playing
|
if (existingChannel != -1) // Just update parameters and return, if already playing
|
||||||
{
|
{
|
||||||
Sound_UpdateEffectPosition(existingChannel, position);
|
Sound_UpdateEffectPosition(existingChannel, position);
|
||||||
|
@ -238,11 +235,11 @@ long SoundEffect(int effectID, PHD_3DPOS* position, int env_flags, float pitchMu
|
||||||
|
|
||||||
// Randomly select arbitrary sample from the list, if more than one is present
|
// Randomly select arbitrary sample from the list, if more than one is present
|
||||||
int sampleToPlay = 0;
|
int sampleToPlay = 0;
|
||||||
int numSamples = (sampleInfo->flags >> 2) & 15;
|
int numSamples = (sampleInfo->Flags >> 2) & 15;
|
||||||
if (numSamples == 1)
|
if (numSamples == 1)
|
||||||
sampleToPlay = sampleInfo->number;
|
sampleToPlay = sampleInfo->Number;
|
||||||
else
|
else
|
||||||
sampleToPlay = sampleInfo->number + (int)((GetRandomControl() * numSamples) >> 15);
|
sampleToPlay = sampleInfo->Number + (int)((GetRandomControl() * numSamples) >> 15);
|
||||||
|
|
||||||
// Get free channel to play sample
|
// Get free channel to play sample
|
||||||
int freeSlot = Sound_GetFreeSlot();
|
int freeSlot = Sound_GetFreeSlot();
|
||||||
|
@ -259,17 +256,17 @@ long SoundEffect(int effectID, PHD_3DPOS* position, int env_flags, float pitchMu
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// Finally ready to play sound, assign it to sound slot.
|
// Finally ready to play sound, assign it to sound slot.
|
||||||
SoundSlot[freeSlot].state = SOUND_STATE_IDLE;
|
SoundSlot[freeSlot].State = SOUND_STATE::Idle;
|
||||||
SoundSlot[freeSlot].effectID = effectID;
|
SoundSlot[freeSlot].EffectID = effectID;
|
||||||
SoundSlot[freeSlot].channel = channel;
|
SoundSlot[freeSlot].Channel = channel;
|
||||||
SoundSlot[freeSlot].gain = gain;
|
SoundSlot[freeSlot].Gain = gain;
|
||||||
SoundSlot[freeSlot].origin = position ? Vector3(position->xPos, position->yPos, position->zPos) : SOUND_OMNIPRESENT_ORIGIN;
|
SoundSlot[freeSlot].Origin = position ? Vector3(position->xPos, position->yPos, position->zPos) : SOUND_OMNIPRESENT_ORIGIN;
|
||||||
|
|
||||||
if (Sound_CheckBASSError("Applying pitch/gain attribs on channel %x, sample %d", false, channel, sampleToPlay))
|
if (Sound_CheckBASSError("Applying pitch/gain attribs on channel %x, sample %d", false, channel, sampleToPlay))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// Set looped flag, if necessary
|
// Set looped flag, if necessary
|
||||||
if (playType == SOUND_LOOPED)
|
if (playType == SOUND_PLAYTYPE::Looped)
|
||||||
BASS_ChannelFlags(channel, BASS_SAMPLE_LOOP, BASS_SAMPLE_LOOP);
|
BASS_ChannelFlags(channel, BASS_SAMPLE_LOOP, BASS_SAMPLE_LOOP);
|
||||||
|
|
||||||
// Play channel
|
// Play channel
|
||||||
|
@ -292,58 +289,51 @@ long SoundEffect(int effectID, PHD_3DPOS* position, int env_flags, float pitchMu
|
||||||
void StopSoundEffect(short effectID)
|
void StopSoundEffect(short effectID)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < SOUND_MAX_CHANNELS; i++)
|
for (int i = 0; i < SOUND_MAX_CHANNELS; i++)
|
||||||
if (SoundSlot[i].effectID == effectID && SoundSlot[i].channel != NULL && BASS_ChannelIsActive(SoundSlot[i].channel) == BASS_ACTIVE_PLAYING)
|
if (SoundSlot[i].EffectID == effectID && SoundSlot[i].Channel != NULL && BASS_ChannelIsActive(SoundSlot[i].Channel) == BASS_ACTIVE_PLAYING)
|
||||||
Sound_FreeSlot(i, SOUND_XFADETIME_CUTSOUND);
|
Sound_FreeSlot(i, SOUND_XFADETIME_CUTSOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sound_Stop()
|
void StopAllSounds()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < SOUND_MAX_CHANNELS; i++)
|
for (int i = 0; i < SOUND_MAX_CHANNELS; i++)
|
||||||
if (SoundSlot[i].channel != NULL && BASS_ChannelIsActive(SoundSlot[i].channel))
|
if (SoundSlot[i].Channel != NULL && BASS_ChannelIsActive(SoundSlot[i].Channel))
|
||||||
BASS_ChannelStop(SoundSlot[i].channel);
|
BASS_ChannelStop(SoundSlot[i].Channel);
|
||||||
ZeroMemory(SoundSlot, (sizeof(SoundEffectSlot) * SOUND_MAX_CHANNELS));
|
ZeroMemory(SoundSlot, (sizeof(SoundEffectSlot) * SOUND_MAX_CHANNELS));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sound_FreeSamples()
|
void FreeSamples()
|
||||||
{
|
{
|
||||||
Sound_Stop();
|
StopAllSounds();
|
||||||
for (int i = 0; i < SOUND_MAX_SAMPLES; i++)
|
for (int i = 0; i < SOUND_MAX_SAMPLES; i++)
|
||||||
Sound_FreeSample(i);
|
Sound_FreeSample(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlaySoundTrack(short track, short flags)
|
void PlaySoundTrack(std::string track, SOUNDTRACK_PLAYTYPE mode)
|
||||||
{
|
|
||||||
PlaySoundTrack(track, flags, SOUND_TRACK_ONESHOT);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PlaySoundTrack(std::string track, unsigned int mode)
|
|
||||||
{
|
{
|
||||||
bool crossfade = false;
|
bool crossfade = false;
|
||||||
DWORD crossfadeTime;
|
DWORD crossfadeTime = 0;
|
||||||
DWORD flags = BASS_STREAM_AUTOFREE | BASS_SAMPLE_FLOAT | BASS_ASYNCFILE;
|
DWORD flags = BASS_STREAM_AUTOFREE | BASS_SAMPLE_FLOAT | BASS_ASYNCFILE;
|
||||||
|
|
||||||
mode = (mode >= NUM_SOUND_TRACK_TYPES) ? SOUND_TRACK_BGM : mode;
|
bool channelActive = BASS_ChannelIsActive(BASS_Soundtrack[(int)mode].Channel);
|
||||||
|
if (channelActive && BASS_Soundtrack[(int)mode].Track.compare(track) == 0)
|
||||||
bool channelActive = BASS_ChannelIsActive(BASS_Soundtrack[mode].channel);
|
|
||||||
if (channelActive && BASS_Soundtrack[mode].track.compare(track) == 0)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
switch (mode)
|
switch (mode)
|
||||||
{
|
{
|
||||||
case SOUND_TRACK_ONESHOT:
|
case SOUNDTRACK_PLAYTYPE::OneShot:
|
||||||
crossfadeTime = SOUND_XFADETIME_ONESHOT;
|
crossfadeTime = SOUND_XFADETIME_ONESHOT;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SOUND_TRACK_BGM:
|
case SOUNDTRACK_PLAYTYPE::BGM:
|
||||||
crossfade = true;
|
crossfade = true;
|
||||||
crossfadeTime = channelActive ? SOUND_XFADETIME_BGM : SOUND_XFADETIME_BGM_START;
|
crossfadeTime = channelActive ? SOUND_XFADETIME_BGM : SOUND_XFADETIME_BGM_START;
|
||||||
flags |= BASS_SAMPLE_LOOP;
|
flags |= BASS_SAMPLE_LOOP;
|
||||||
CurrentLoopedSoundTrack = track;
|
CurrentLoopedSoundTrack = track;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(channelActive)
|
if (channelActive)
|
||||||
BASS_ChannelSlideAttribute(BASS_Soundtrack[mode].channel, BASS_ATTRIB_VOL, -1.0f, crossfadeTime);
|
BASS_ChannelSlideAttribute(BASS_Soundtrack[(int)mode].Channel, BASS_ATTRIB_VOL, -1.0f, crossfadeTime);
|
||||||
|
|
||||||
static char fullTrackName[1024];
|
static char fullTrackName[1024];
|
||||||
char const* name = track.c_str();
|
char const* name = track.c_str();
|
||||||
|
@ -371,10 +361,10 @@ void PlaySoundTrack(std::string track, unsigned int mode)
|
||||||
|
|
||||||
// Damp BGM track in case one-shot track is about to play.
|
// Damp BGM track in case one-shot track is about to play.
|
||||||
|
|
||||||
if (mode == SOUND_TRACK_ONESHOT)
|
if (mode == SOUNDTRACK_PLAYTYPE::OneShot)
|
||||||
{
|
{
|
||||||
if (BASS_ChannelIsActive(BASS_Soundtrack[SOUND_TRACK_BGM].channel))
|
if (BASS_ChannelIsActive(BASS_Soundtrack[(int)SOUNDTRACK_PLAYTYPE::BGM].Channel))
|
||||||
BASS_ChannelSlideAttribute(BASS_Soundtrack[SOUND_TRACK_BGM].channel, BASS_ATTRIB_VOL, masterVolume * SOUND_BGM_DAMP_COEFFICIENT, SOUND_XFADETIME_BGM_START);
|
BASS_ChannelSlideAttribute(BASS_Soundtrack[(int)SOUNDTRACK_PLAYTYPE::BGM].Channel, BASS_ATTRIB_VOL, masterVolume * SOUND_BGM_DAMP_COEFFICIENT, SOUND_XFADETIME_BGM_START);
|
||||||
BASS_ChannelSetSync(stream, BASS_SYNC_FREE | BASS_SYNC_ONETIME | BASS_SYNC_MIXTIME, 0, Sound_FinishOneshotTrack, NULL);
|
BASS_ChannelSetSync(stream, BASS_SYNC_FREE | BASS_SYNC_ONETIME | BASS_SYNC_MIXTIME, 0, Sound_FinishOneshotTrack, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -399,51 +389,56 @@ void PlaySoundTrack(std::string track, unsigned int mode)
|
||||||
if (Sound_CheckBASSError("Playing soundtrack %s", false, fullTrackName))
|
if (Sound_CheckBASSError("Playing soundtrack %s", false, fullTrackName))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
BASS_Soundtrack[mode].channel = stream;
|
BASS_Soundtrack[(int)mode].Channel = stream;
|
||||||
BASS_Soundtrack[mode].track = track;
|
BASS_Soundtrack[(int)mode].Track = track;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlaySoundTrack(std::string track, DWORD mask, DWORD unknown)
|
void PlaySoundTrack(std::string track, short mask)
|
||||||
|
{
|
||||||
|
PlaySoundTrack(SoundTrackMap[track], mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlaySoundTrack(int index, short mask)
|
||||||
{
|
{
|
||||||
// Check and modify soundtrack map mask, if needed.
|
// Check and modify soundtrack map mask, if needed.
|
||||||
// If existing mask is unmodified (same activation mask setup), track won't play.
|
// If existing mask is unmodified (same activation mask setup), track won't play.
|
||||||
if (!SoundTracks[track].looped)
|
|
||||||
|
if (!(SoundTracks[index].Mode == SOUNDTRACK_PLAYTYPE::BGM))
|
||||||
{
|
{
|
||||||
byte filteredMask = (mask >> 8) & 0x3F;
|
short filteredMask = (mask >> 8) & 0x3F;
|
||||||
if ((SoundTracks[track].Mask & filteredMask) == filteredMask)
|
if ((SoundTracks[index].Mask & filteredMask) == filteredMask)
|
||||||
return; // Mask is the same, don't play it.
|
return; // Mask is the same, don't play it.
|
||||||
|
|
||||||
SoundTracks[track].Mask |= filteredMask;
|
SoundTracks[index].Mask |= filteredMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
PlaySoundTrack(track, SoundTracks[track].looped);
|
PlaySoundTrack(SoundTracks[index].Name, SoundTracks[index].Mode);
|
||||||
}
|
|
||||||
|
|
||||||
void PlaySoundTrack(int index, DWORD mask, DWORD unknown)
|
|
||||||
{
|
|
||||||
std::pair<const std::string, AudioTrack>& track = *std::next(SoundTracks.begin(), index);
|
|
||||||
PlaySoundTrack(track.first, mask, unknown);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void StopSoundTracks()
|
void StopSoundTracks()
|
||||||
{
|
{
|
||||||
// Do quick fadeouts.
|
// Do quick fadeouts.
|
||||||
BASS_ChannelSlideAttribute(BASS_Soundtrack[SOUND_TRACK_ONESHOT].channel, BASS_ATTRIB_VOL | BASS_SLIDE_LOG, -1.0f, SOUND_XFADETIME_ONESHOT);
|
BASS_ChannelSlideAttribute(BASS_Soundtrack[(int)SOUNDTRACK_PLAYTYPE::OneShot].Channel, BASS_ATTRIB_VOL | BASS_SLIDE_LOG, -1.0f, SOUND_XFADETIME_ONESHOT);
|
||||||
BASS_ChannelSlideAttribute(BASS_Soundtrack[SOUND_TRACK_BGM].channel, BASS_ATTRIB_VOL | BASS_SLIDE_LOG, -1.0f, SOUND_XFADETIME_ONESHOT);
|
BASS_ChannelSlideAttribute(BASS_Soundtrack[(int)SOUNDTRACK_PLAYTYPE::BGM].Channel, BASS_ATTRIB_VOL | BASS_SLIDE_LOG, -1.0f, SOUND_XFADETIME_ONESHOT);
|
||||||
|
|
||||||
BASS_Soundtrack[SOUND_TRACK_ONESHOT].track = "";
|
BASS_Soundtrack[(int)SOUNDTRACK_PLAYTYPE::OneShot].Track = "";
|
||||||
BASS_Soundtrack[SOUND_TRACK_ONESHOT].channel = NULL;
|
BASS_Soundtrack[(int)SOUNDTRACK_PLAYTYPE::OneShot].Channel = NULL;
|
||||||
BASS_Soundtrack[SOUND_TRACK_BGM].track = "";
|
BASS_Soundtrack[(int)SOUNDTRACK_PLAYTYPE::BGM].Track = "";
|
||||||
BASS_Soundtrack[SOUND_TRACK_BGM].channel = NULL;
|
BASS_Soundtrack[(int)SOUNDTRACK_PLAYTYPE::BGM].Channel = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClearSoundTrackMasks()
|
||||||
|
{
|
||||||
|
for (auto& track : SoundTracks) { track.Mask = 0; }
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CALLBACK Sound_FinishOneshotTrack(HSYNC handle, DWORD channel, DWORD data, void* userData)
|
static void CALLBACK Sound_FinishOneshotTrack(HSYNC handle, DWORD channel, DWORD data, void* userData)
|
||||||
{
|
{
|
||||||
if (BASS_ChannelIsActive(BASS_Soundtrack[SOUND_TRACK_BGM].channel))
|
if (BASS_ChannelIsActive(BASS_Soundtrack[(int)SOUNDTRACK_PLAYTYPE::BGM].Channel))
|
||||||
BASS_ChannelSlideAttribute(BASS_Soundtrack[SOUND_TRACK_BGM].channel, BASS_ATTRIB_VOL, (float)GlobalMusicVolume / 100.0f, SOUND_XFADETIME_BGM_START);
|
BASS_ChannelSlideAttribute(BASS_Soundtrack[(int)SOUNDTRACK_PLAYTYPE::BGM].Channel, BASS_ATTRIB_VOL, (float)GlobalMusicVolume / 100.0f, SOUND_XFADETIME_BGM_START);
|
||||||
|
|
||||||
BASS_Soundtrack[SOUND_TRACK_ONESHOT].track = "";
|
BASS_Soundtrack[(int)SOUNDTRACK_PLAYTYPE::OneShot].Track = "";
|
||||||
BASS_Soundtrack[SOUND_TRACK_ONESHOT].channel = NULL;
|
BASS_Soundtrack[(int)SOUNDTRACK_PLAYTYPE::OneShot].Channel = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sound_FreeSample(int index)
|
void Sound_FreeSample(int index)
|
||||||
|
@ -462,7 +457,7 @@ int Sound_GetFreeSlot()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < SOUND_MAX_CHANNELS; i++)
|
for (int i = 0; i < SOUND_MAX_CHANNELS; i++)
|
||||||
{
|
{
|
||||||
if (SoundSlot[i].channel == NULL || !BASS_ChannelIsActive(SoundSlot[i].channel))
|
if (SoundSlot[i].Channel == NULL || !BASS_ChannelIsActive(SoundSlot[i].Channel))
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -473,7 +468,7 @@ int Sound_GetFreeSlot()
|
||||||
|
|
||||||
for (int i = 0; i < SOUND_MAX_CHANNELS; i++)
|
for (int i = 0; i < SOUND_MAX_CHANNELS; i++)
|
||||||
{
|
{
|
||||||
float distance = Vector3(SoundSlot[i].origin - Vector3(Camera.mikePos.x, Camera.mikePos.y, Camera.mikePos.z)).Length();
|
float distance = Vector3(SoundSlot[i].Origin - Vector3(Camera.mikePos.x, Camera.mikePos.y, Camera.mikePos.z)).Length();
|
||||||
if (distance > minDistance)
|
if (distance > minDistance)
|
||||||
{
|
{
|
||||||
minDistance = distance;
|
minDistance = distance;
|
||||||
|
@ -494,28 +489,28 @@ int Sound_EffectIsPlaying(int effectID, PHD_3DPOS *position)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < SOUND_MAX_CHANNELS; i++)
|
for (int i = 0; i < SOUND_MAX_CHANNELS; i++)
|
||||||
{
|
{
|
||||||
if (SoundSlot[i].effectID == effectID)
|
if (SoundSlot[i].EffectID == effectID)
|
||||||
{
|
{
|
||||||
if (SoundSlot[i].channel == NULL) // Free channel
|
if (SoundSlot[i].Channel == NULL) // Free channel
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (BASS_ChannelIsActive(SoundSlot[i].channel))
|
if (BASS_ChannelIsActive(SoundSlot[i].Channel))
|
||||||
{
|
{
|
||||||
// Only check position on 3D samples. 2D samples stop immediately.
|
// Only check position on 3D samples. 2D samples stop immediately.
|
||||||
|
|
||||||
BASS_CHANNELINFO info;
|
BASS_CHANNELINFO info;
|
||||||
BASS_ChannelGetInfo(SoundSlot[i].channel, &info);
|
BASS_ChannelGetInfo(SoundSlot[i].Channel, &info);
|
||||||
if (!(info.flags & BASS_SAMPLE_3D) || !position)
|
if (!(info.flags & BASS_SAMPLE_3D) || !position)
|
||||||
return i;
|
return i;
|
||||||
|
|
||||||
// Check if effect origin is equal OR in nearest possible hearing range.
|
// Check if effect origin is equal OR in nearest possible hearing range.
|
||||||
|
|
||||||
Vector3 origin = Vector3(position->xPos, position->yPos, position->zPos);
|
Vector3 origin = Vector3(position->xPos, position->yPos, position->zPos);
|
||||||
if (Vector3::Distance(origin, SoundSlot[i].origin) < SOUND_MAXVOL_RADIUS)
|
if (Vector3::Distance(origin, SoundSlot[i].Origin) < SOUND_MAXVOL_RADIUS)
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
SoundSlot[i].channel = NULL; // WTF, let's clean this up
|
SoundSlot[i].Channel = NULL; // WTF, let's clean this up
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -550,13 +545,13 @@ void Sound_FreeSlot(int index, unsigned int fadeout)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (fadeout > 0)
|
if (fadeout > 0)
|
||||||
BASS_ChannelSlideAttribute(SoundSlot[index].channel, BASS_ATTRIB_VOL, -1.0f, fadeout);
|
BASS_ChannelSlideAttribute(SoundSlot[index].Channel, BASS_ATTRIB_VOL, -1.0f, fadeout);
|
||||||
else
|
else
|
||||||
BASS_ChannelStop(SoundSlot[index].channel);
|
BASS_ChannelStop(SoundSlot[index].Channel);
|
||||||
|
|
||||||
SoundSlot[index].channel = NULL;
|
SoundSlot[index].Channel = NULL;
|
||||||
SoundSlot[index].state = SOUND_STATE_IDLE;
|
SoundSlot[index].State = SOUND_STATE::Idle;
|
||||||
SoundSlot[index].effectID = -1;
|
SoundSlot[index].EffectID = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update sound position in a level.
|
// Update sound position in a level.
|
||||||
|
@ -569,23 +564,23 @@ bool Sound_UpdateEffectPosition(int index, PHD_3DPOS *position, bool force)
|
||||||
if (position)
|
if (position)
|
||||||
{
|
{
|
||||||
BASS_CHANNELINFO info;
|
BASS_CHANNELINFO info;
|
||||||
BASS_ChannelGetInfo(SoundSlot[index].channel, &info);
|
BASS_ChannelGetInfo(SoundSlot[index].Channel, &info);
|
||||||
if (info.flags & BASS_SAMPLE_3D)
|
if (info.flags & BASS_SAMPLE_3D)
|
||||||
{
|
{
|
||||||
SoundSlot[index].origin.x = position->xPos;
|
SoundSlot[index].Origin.x = position->xPos;
|
||||||
SoundSlot[index].origin.y = position->yPos;
|
SoundSlot[index].Origin.y = position->yPos;
|
||||||
SoundSlot[index].origin.z = position->zPos;
|
SoundSlot[index].Origin.z = position->zPos;
|
||||||
|
|
||||||
auto pos = BASS_3DVECTOR(position->xPos, position->yPos, position->zPos);
|
auto pos = BASS_3DVECTOR(position->xPos, position->yPos, position->zPos);
|
||||||
auto rot = BASS_3DVECTOR(position->xRot, position->yRot, position->zRot);
|
auto rot = BASS_3DVECTOR(position->xRot, position->yRot, position->zRot);
|
||||||
BASS_ChannelSet3DPosition(SoundSlot[index].channel, &pos, &rot, NULL);
|
BASS_ChannelSet3DPosition(SoundSlot[index].Channel, &pos, &rot, NULL);
|
||||||
BASS_Apply3D();
|
BASS_Apply3D();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset activity flag, important for looped samples
|
// Reset activity flag, important for looped samples
|
||||||
if (BASS_ChannelIsActive(SoundSlot[index].channel))
|
if (BASS_ChannelIsActive(SoundSlot[index].Channel))
|
||||||
SoundSlot[index].state = SOUND_STATE_IDLE;
|
SoundSlot[index].State = SOUND_STATE::Idle;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -596,8 +591,8 @@ bool Sound_UpdateEffectAttributes(int index, float pitch, float gain)
|
||||||
if (index > SOUND_MAX_CHANNELS || index < 0)
|
if (index > SOUND_MAX_CHANNELS || index < 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
BASS_ChannelSetAttribute(SoundSlot[index].channel, BASS_ATTRIB_FREQ, 22050.0f * pitch);
|
BASS_ChannelSetAttribute(SoundSlot[index].Channel, BASS_ATTRIB_FREQ, 22050.0f * pitch);
|
||||||
BASS_ChannelSetAttribute(SoundSlot[index].channel, BASS_ATTRIB_VOL, gain);
|
BASS_ChannelSetAttribute(SoundSlot[index].Channel, BASS_ATTRIB_VOL, gain);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -614,34 +609,34 @@ void Sound_UpdateScene()
|
||||||
if (currentReverb == -1 || g_Level.Rooms[Camera.pos.roomNumber].reverbType != currentReverb)
|
if (currentReverb == -1 || g_Level.Rooms[Camera.pos.roomNumber].reverbType != currentReverb)
|
||||||
{
|
{
|
||||||
currentReverb = g_Level.Rooms[Camera.pos.roomNumber].reverbType;
|
currentReverb = g_Level.Rooms[Camera.pos.roomNumber].reverbType;
|
||||||
if (currentReverb < NUM_REVERB_TYPES)
|
if (currentReverb < (int)REVERB_TYPE::Count)
|
||||||
BASS_FXSetParameters(BASS_FXHandler[SOUND_FILTER_REVERB], &BASS_ReverbTypes[currentReverb]);
|
BASS_FXSetParameters(BASS_FXHandler[(int)SOUND_FILTER::Reverb], &BASS_ReverbTypes[currentReverb]);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < SOUND_MAX_CHANNELS; i++)
|
for (int i = 0; i < SOUND_MAX_CHANNELS; i++)
|
||||||
{
|
{
|
||||||
if ((SoundSlot[i].channel != NULL) && (BASS_ChannelIsActive(SoundSlot[i].channel) == BASS_ACTIVE_PLAYING))
|
if ((SoundSlot[i].Channel != NULL) && (BASS_ChannelIsActive(SoundSlot[i].Channel) == BASS_ACTIVE_PLAYING))
|
||||||
{
|
{
|
||||||
SAMPLE_INFO *sampleInfo = &g_Level.SoundDetails[g_Level.SoundMap[SoundSlot[i].effectID]];
|
SampleInfo* sampleInfo = &g_Level.SoundDetails[g_Level.SoundMap[SoundSlot[i].EffectID]];
|
||||||
|
|
||||||
// Stop and clean up sounds which were in ending state in previous frame.
|
// Stop and clean up sounds which were in ending state in previous frame.
|
||||||
// In case sound is looping, make it ending unless they are re-fired in next frame.
|
// In case sound is looping, make it ending unless they are re-fired in next frame.
|
||||||
|
|
||||||
if (SoundSlot[i].state == SOUND_STATE_ENDING)
|
if (SoundSlot[i].State == SOUND_STATE::Ending)
|
||||||
{
|
{
|
||||||
SoundSlot[i].state = SOUND_STATE_ENDED;
|
SoundSlot[i].State = SOUND_STATE::Ended;
|
||||||
Sound_FreeSlot(i, SOUND_XFADETIME_CUTSOUND);
|
Sound_FreeSlot(i, SOUND_XFADETIME_CUTSOUND);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (sampleInfo->flags & 3 == SOUND_LOOPED)
|
else if ((SOUND_PLAYTYPE)(sampleInfo->Flags & 3) == SOUND_PLAYTYPE::Looped)
|
||||||
SoundSlot[i].state = SOUND_STATE_ENDING;
|
SoundSlot[i].State = SOUND_STATE::Ending;
|
||||||
|
|
||||||
// Calculate attenuation and clean up sounds which are out of listener range (only for 3D sounds).
|
// Calculate attenuation and clean up sounds which are out of listener range (only for 3D sounds).
|
||||||
|
|
||||||
if (SoundSlot[i].origin != SOUND_OMNIPRESENT_ORIGIN)
|
if (SoundSlot[i].Origin != SOUND_OMNIPRESENT_ORIGIN)
|
||||||
{
|
{
|
||||||
float radius = (float)(sampleInfo->radius) * 1024.0f;
|
float radius = (float)(sampleInfo->Radius) * 1024.0f;
|
||||||
float distance = Sound_DistanceToListener(SoundSlot[i].origin);
|
float distance = Sound_DistanceToListener(SoundSlot[i].Origin);
|
||||||
|
|
||||||
if (distance > radius)
|
if (distance > radius)
|
||||||
{
|
{
|
||||||
|
@ -649,7 +644,7 @@ void Sound_UpdateScene()
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
BASS_ChannelSetAttribute(SoundSlot[i].channel, BASS_ATTRIB_VOL, Sound_Attenuate(SoundSlot[i].gain, distance, radius));
|
BASS_ChannelSetAttribute(SoundSlot[i].Channel, BASS_ATTRIB_VOL, Sound_Attenuate(SoundSlot[i].Gain, distance, radius));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -711,20 +706,20 @@ void Sound_Init()
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Initialize channels and tracks array
|
// Initialize channels and tracks array
|
||||||
ZeroMemory(BASS_Soundtrack, (sizeof(HSTREAM) * NUM_SOUND_TRACK_TYPES));
|
ZeroMemory(BASS_Soundtrack, (sizeof(HSTREAM) * (int)SOUNDTRACK_PLAYTYPE::Count));
|
||||||
ZeroMemory(SoundSlot, (sizeof(SoundEffectSlot) * SOUND_MAX_CHANNELS));
|
ZeroMemory(SoundSlot, (sizeof(SoundEffectSlot) * SOUND_MAX_CHANNELS));
|
||||||
|
|
||||||
// Attach reverb effect to 3D channel
|
// Attach reverb effect to 3D channel
|
||||||
BASS_FXHandler[SOUND_FILTER_REVERB] = BASS_ChannelSetFX(BASS_3D_Mixdown, BASS_FX_BFX_FREEVERB, 0);
|
BASS_FXHandler[(int)SOUND_FILTER::Reverb] = BASS_ChannelSetFX(BASS_3D_Mixdown, BASS_FX_BFX_FREEVERB, 0);
|
||||||
BASS_FXSetParameters(BASS_FXHandler[SOUND_FILTER_REVERB], &BASS_ReverbTypes[RVB_OUTSIDE]);
|
BASS_FXSetParameters(BASS_FXHandler[(int)SOUND_FILTER::Reverb], &BASS_ReverbTypes[(int)REVERB_TYPE::Outside]);
|
||||||
|
|
||||||
if (Sound_CheckBASSError("Attaching environmental FX", true))
|
if (Sound_CheckBASSError("Attaching environmental FX", true))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Apply slight compression to 3D channel
|
// Apply slight compression to 3D channel
|
||||||
BASS_FXHandler[SOUND_FILTER_COMPRESSOR] = BASS_ChannelSetFX(BASS_3D_Mixdown, BASS_FX_BFX_COMPRESSOR2, 1);
|
BASS_FXHandler[(int)SOUND_FILTER::Compressor] = BASS_ChannelSetFX(BASS_3D_Mixdown, BASS_FX_BFX_COMPRESSOR2, 1);
|
||||||
auto comp = BASS_BFX_COMPRESSOR2{ 4.0f, -18.0f, 1.5f, 10.0f, 100.0f, -1 };
|
auto comp = BASS_BFX_COMPRESSOR2{ 4.0f, -18.0f, 1.5f, 10.0f, 100.0f, -1 };
|
||||||
BASS_FXSetParameters(BASS_FXHandler[SOUND_FILTER_COMPRESSOR], &comp);
|
BASS_FXSetParameters(BASS_FXHandler[(int)SOUND_FILTER::Compressor], &comp);
|
||||||
|
|
||||||
if (Sound_CheckBASSError("Attaching compressor", true))
|
if (Sound_CheckBASSError("Attaching compressor", true))
|
||||||
return;
|
return;
|
||||||
|
@ -762,6 +757,11 @@ void SayNo()
|
||||||
SoundEffect(SFX_TR4_LARA_NO, NULL, SFX_ALWAYS);
|
SoundEffect(SFX_TR4_LARA_NO, NULL, SFX_ALWAYS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PlaySecretTrack()
|
||||||
|
{
|
||||||
|
PlaySoundTrack(SoundTracks.size());
|
||||||
|
}
|
||||||
|
|
||||||
int GetShatterSound(int shatterID)
|
int GetShatterSound(int shatterID)
|
||||||
{
|
{
|
||||||
auto fxID = StaticObjects[shatterID].shatterSound;
|
auto fxID = StaticObjects[shatterID].shatterSound;
|
||||||
|
|
|
@ -1,16 +1,10 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <bass.h>
|
#include <bass.h>
|
||||||
#include <bass_fx.h>
|
#include <bass_fx.h>
|
||||||
#include "control/control.h"
|
#include "control/control.h"
|
||||||
#include "sound_effects.h"
|
#include "sound_effects.h"
|
||||||
|
|
||||||
enum SFX_TYPES
|
|
||||||
{
|
|
||||||
SFX_LANDANDWATER = 0,
|
|
||||||
SFX_LANDONLY = (1 << 14),
|
|
||||||
SFX_WATERONLY = (2 << 14)
|
|
||||||
};
|
|
||||||
|
|
||||||
#define SFX_ALWAYS 2
|
#define SFX_ALWAYS 2
|
||||||
|
|
||||||
#define SOUND_BASS_UNITS 1.0f / 1024.0f // TR->BASS distance unit coefficient
|
#define SOUND_BASS_UNITS 1.0f / 1024.0f // TR->BASS distance unit coefficient
|
||||||
|
@ -35,98 +29,104 @@ enum SFX_TYPES
|
||||||
#define SOUND_XFADETIME_HIJACKSOUND 50
|
#define SOUND_XFADETIME_HIJACKSOUND 50
|
||||||
#define SOUND_BGM_DAMP_COEFFICIENT 0.6f
|
#define SOUND_BGM_DAMP_COEFFICIENT 0.6f
|
||||||
|
|
||||||
#define TRACK_FOUND_SECRET "073_Secret"
|
|
||||||
#define TRACKS_PREFIX "Audio\\%s.%s"
|
#define TRACKS_PREFIX "Audio\\%s.%s"
|
||||||
|
|
||||||
|
enum class SOUNDTRACK_PLAYTYPE
|
||||||
|
{
|
||||||
|
OneShot,
|
||||||
|
BGM,
|
||||||
|
Count
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class SOUND_PLAYCONDITION
|
||||||
|
{
|
||||||
|
LandAndWater = 0,
|
||||||
|
Land = (1 << 14),
|
||||||
|
Water = (2 << 14)
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class SOUND_PLAYTYPE
|
||||||
|
{
|
||||||
|
Normal,
|
||||||
|
Wait,
|
||||||
|
Restart,
|
||||||
|
Looped
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class REVERB_TYPE
|
||||||
|
{
|
||||||
|
Outside, // 0x00 no reverberation
|
||||||
|
Small, // 0x01 little reverberation
|
||||||
|
Medium, // 0x02
|
||||||
|
Large, // 0x03
|
||||||
|
Pipe, // 0x04 highest reverberation, almost never used
|
||||||
|
Count
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class SOUND_STATE
|
||||||
|
{
|
||||||
|
Idle,
|
||||||
|
Ending,
|
||||||
|
Ended
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class SOUND_FILTER
|
||||||
|
{
|
||||||
|
Reverb,
|
||||||
|
Compressor,
|
||||||
|
Lowpass,
|
||||||
|
Count
|
||||||
|
};
|
||||||
|
|
||||||
struct SoundEffectSlot
|
struct SoundEffectSlot
|
||||||
{
|
{
|
||||||
short state;
|
SOUND_STATE State;
|
||||||
short effectID;
|
short EffectID;
|
||||||
float gain;
|
float Gain;
|
||||||
HCHANNEL channel;
|
HCHANNEL Channel;
|
||||||
Vector3 origin;
|
Vector3 Origin;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SoundTrackSlot
|
struct SoundTrackSlot
|
||||||
{
|
{
|
||||||
HSTREAM channel;
|
HSTREAM Channel;
|
||||||
std::string track;
|
std::string Track;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum sound_track_types
|
struct SampleInfo
|
||||||
{
|
{
|
||||||
SOUND_TRACK_ONESHOT,
|
short Number;
|
||||||
SOUND_TRACK_BGM,
|
byte Volume;
|
||||||
|
byte Radius;
|
||||||
NUM_SOUND_TRACK_TYPES
|
byte Randomness;
|
||||||
|
signed char Pitch;
|
||||||
|
short Flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum sound_filters
|
struct SoundTrackInfo
|
||||||
{
|
|
||||||
SOUND_FILTER_REVERB,
|
|
||||||
SOUND_FILTER_COMPRESSOR,
|
|
||||||
SOUND_FILTER_LOWPASS,
|
|
||||||
|
|
||||||
NUM_SOUND_FILTERS
|
|
||||||
};
|
|
||||||
|
|
||||||
enum sound_states
|
|
||||||
{
|
|
||||||
SOUND_STATE_IDLE,
|
|
||||||
SOUND_STATE_ENDING,
|
|
||||||
SOUND_STATE_ENDED
|
|
||||||
};
|
|
||||||
|
|
||||||
enum sound_flags
|
|
||||||
{
|
|
||||||
SOUND_NORMAL,
|
|
||||||
SOUND_WAIT,
|
|
||||||
SOUND_RESTART,
|
|
||||||
SOUND_LOOPED
|
|
||||||
};
|
|
||||||
|
|
||||||
enum reverb_type
|
|
||||||
{
|
|
||||||
RVB_OUTSIDE, // 0x00 no reverberation
|
|
||||||
RVB_SMALL_ROOM, // 0x01 little reverberation
|
|
||||||
RVB_MEDIUM_ROOM, // 0x02
|
|
||||||
RVB_LARGE_ROOM, // 0x03
|
|
||||||
RVB_PIPE, // 0x04 highest reverberation, almost never used
|
|
||||||
|
|
||||||
NUM_REVERB_TYPES
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SAMPLE_INFO
|
|
||||||
{
|
|
||||||
short number;
|
|
||||||
byte volume;
|
|
||||||
byte radius;
|
|
||||||
byte randomness;
|
|
||||||
signed char pitch;
|
|
||||||
short flags;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct AudioTrack
|
|
||||||
{
|
{
|
||||||
std::string Name;
|
std::string Name;
|
||||||
byte Mask;
|
SOUNDTRACK_PLAYTYPE Mode;
|
||||||
bool looped;
|
short Mask;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern std::unordered_map<std::string, AudioTrack> SoundTracks;
|
extern std::map<std::string, int> SoundTrackMap;
|
||||||
|
extern std::vector<SoundTrackInfo> SoundTracks;
|
||||||
|
|
||||||
extern std::string CurrentLoopedSoundTrack;
|
extern std::string CurrentLoopedSoundTrack;
|
||||||
|
|
||||||
long SoundEffect(int effectID, PHD_3DPOS* position, int env_flags, float pitchMultiplier = 1.0f, float gainMultiplier = 1.0f);
|
long SoundEffect(int effectID, PHD_3DPOS* position, int env_flags, float pitchMultiplier = 1.0f, float gainMultiplier = 1.0f);
|
||||||
void StopSoundEffect(short effectID);
|
void StopSoundEffect(short effectID);
|
||||||
bool Sound_LoadSample(char *buffer, int compSize, int uncompSize, int currentIndex);
|
bool LoadSample(char *buffer, int compSize, int uncompSize, int currentIndex);
|
||||||
void Sound_FreeSamples();
|
void FreeSamples();
|
||||||
void Sound_Stop();
|
void StopAllSounds();
|
||||||
|
|
||||||
void PlaySoundTrack(short track, short flags);
|
void PlaySoundTrack(std::string trackName, SOUNDTRACK_PLAYTYPE mode);
|
||||||
void PlaySoundTrack(std::string trackName, unsigned int mode);
|
void PlaySoundTrack(std::string trackName, short mask = 0);
|
||||||
void PlaySoundTrack(std::string trackName, DWORD mask, DWORD unknown);
|
void PlaySoundTrack(int index, short mask = 0);
|
||||||
void PlaySoundTrack(int index, DWORD mask, DWORD unknown);
|
|
||||||
void StopSoundTracks();
|
void StopSoundTracks();
|
||||||
|
void ClearSoundTrackMasks();
|
||||||
|
void PlaySecretTrack();
|
||||||
void SayNo();
|
void SayNo();
|
||||||
void PlaySoundSources();
|
void PlaySoundSources();
|
||||||
int GetShatterSound(int shatterID);
|
int GetShatterSound(int shatterID);
|
||||||
|
|
|
@ -1112,7 +1112,7 @@ void LoadSamples()
|
||||||
if (numSamplesInfos)
|
if (numSamplesInfos)
|
||||||
{
|
{
|
||||||
g_Level.SoundDetails.resize(numSamplesInfos);
|
g_Level.SoundDetails.resize(numSamplesInfos);
|
||||||
ReadBytes(g_Level.SoundDetails.data(), numSamplesInfos * sizeof(SAMPLE_INFO));
|
ReadBytes(g_Level.SoundDetails.data(), numSamplesInfos * sizeof(SampleInfo));
|
||||||
|
|
||||||
int numSamples = ReadInt32();
|
int numSamples = ReadInt32();
|
||||||
if (numSamples <= 0)
|
if (numSamples <= 0)
|
||||||
|
@ -1127,7 +1127,7 @@ void LoadSamples()
|
||||||
uncompressedSize = ReadInt32();
|
uncompressedSize = ReadInt32();
|
||||||
compressedSize = ReadInt32();
|
compressedSize = ReadInt32();
|
||||||
ReadBytes(buffer, compressedSize);
|
ReadBytes(buffer, compressedSize);
|
||||||
Sound_LoadSample(buffer, compressedSize, uncompressedSize, i);
|
LoadSample(buffer, compressedSize, uncompressedSize, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(buffer);
|
free(buffer);
|
||||||
|
@ -1179,8 +1179,8 @@ int LoadLevelFile(int levelIndex)
|
||||||
{
|
{
|
||||||
logD("Loading level file...");
|
logD("Loading level file...");
|
||||||
|
|
||||||
Sound_Stop();
|
StopAllSounds();
|
||||||
Sound_FreeSamples();
|
FreeSamples();
|
||||||
if (!g_FirstLevel)
|
if (!g_FirstLevel)
|
||||||
FreeLevel();
|
FreeLevel();
|
||||||
g_FirstLevel = false;
|
g_FirstLevel = false;
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
|
|
||||||
struct ChunkId;
|
struct ChunkId;
|
||||||
struct LEB128;
|
struct LEB128;
|
||||||
struct SAMPLE_INFO;
|
struct SampleInfo;
|
||||||
struct BOX_INFO;
|
struct BOX_INFO;
|
||||||
struct OVERLAP;
|
struct OVERLAP;
|
||||||
|
|
||||||
|
@ -142,7 +142,7 @@ struct LEVEL
|
||||||
std::vector<OVERLAP> Overlaps;
|
std::vector<OVERLAP> Overlaps;
|
||||||
std::vector<int> Zones[MAX_ZONES][2];
|
std::vector<int> Zones[MAX_ZONES][2];
|
||||||
std::vector<short> SoundMap;
|
std::vector<short> SoundMap;
|
||||||
std::vector<SAMPLE_INFO> SoundDetails;
|
std::vector<SampleInfo> SoundDetails;
|
||||||
std::vector<ANIMATED_TEXTURES_SEQUENCE> AnimatedTexturesSequences;
|
std::vector<ANIMATED_TEXTURES_SEQUENCE> AnimatedTexturesSequences;
|
||||||
int NumItems;
|
int NumItems;
|
||||||
int NumSpritesSequences;
|
int NumSpritesSequences;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue