Files
GTASource/game/audio/radioaudioentity.h
expvintl 419f2e4752 init
2025-02-23 17:40:52 +08:00

522 lines
14 KiB
C++

//
// audio/radioaudioentity.h
//
// Copyright (C) 1999-2006 Rockstar Games. All Rights Reserved.
//
#ifndef AUD_RADIOAUDIOENTITY_H
#define AUD_RADIOAUDIOENTITY_H
#include "audiodefines.h"
#if NA_RADIO_ENABLED
#include "radiostation.h"
#include "radioemitter.h"
#include "gameobjects.h"
#include "audioengine/tracker.h"
#include "audioengine/requestedsettings.h"
#include "audioengine/categorymanager.h"
#include "audioengine/engineutil.h"
#include "audioengine/soundset.h"
#include "audiohardware/driverutil.h"
#include "audiohardware/streamingwaveslot.h"
#include "audiosoundtypes/soundcontrol.h"
#include "audioentity.h"
#include "bank/bkmgr.h"
#include "vehicles/vehicle.h"
#include "system/param.h"
#if GTA_REPLAY
#define REPLAY_PREVIEW_MIN_LENGTH 20000
#define REPLAY_PREVIEW_MAX_LENGTH 50000
#define REPLAY_PREVIEW_DEFAULT_LENGTH 30000
#define REPLAY_PREVIEW_FADE_LENGTH 1000
#define REPLAY_PREVIEW_MUSIC_VOLUME 0.8f
#endif
class audRadioAudioEntity : public naAudioEntity
{
public:
AUDIO_ENTITY_NAME(audRadioAudioEntity);
enum audPlayerRadioStates
{
PLAYER_RADIO_OFF,
PLAYER_RADIO_STARTING,
PLAYER_RADIO_PLAYING,
PLAYER_RADIO_FROZEN,
PLAYER_RADIO_STOPPING,
PLAYER_RADIO_RETUNING
};
audRadioAudioEntity();
static void InitClass(void);
static void DLCInitClass(void);
static void ShutdownClass(void);
void Init(void);
virtual void Shutdown(void);
virtual void PreUpdateService(u32 timeInMs);
void GameUpdate(void);
#if GTA_REPLAY
void RequestUpdateReplayMusic() { m_ShouldUpdateReplayMusic = true; }
void RequestUpdateMusicPreview() { m_ShouldUpdateReplayPreview = true; }
u32 GetReplayMusicPlaybackTimeMs();
void RequestReplayMusicTrack(u32 soundHash, s32 musicTrackID, u32 startOffsetMS, u32 durationMs, float fadeOutScalar);
bool IsReplayMusicTrackPrepared();
void StartReplayTrackPreview(u32 soundHash, u32 startOffSetMS = 0, u32 trackDuration = REPLAY_PREVIEW_DEFAULT_LENGTH, bool jumpToRockout = true, bool fadeIn = true);
void StopReplayTrackPreview();
bool IsReplayMusicPreviewPlaying() { return (m_ReplayMusicStartTime > 0); }
void ParseMarkers();
f32 GetNextReplayBeat(u32 soundHash, f32 startOffsetMS);
f32 GetPrevReplayBeat(u32 soundHash, f32 startOffsetMS);
f32 GetReplayBeat(u32 soundHash, s32 direction, f32 startOffsetMS);
bool HasBeatMarkers(u32 soundHash);
bool HasBeatMarkersInRange(u32 soundHash, u32 startMS, u32 endMS);
#endif // GTA_REPLAY
const audRadioStation *RequestVehicleRadio(CVehicle *vehicle);
void StopVehicleRadio(CVehicle *vehicle, bool clearStation = true);
bool RequestStaticRadio(audStaticRadioEmitter *emitter, u32 stationNameHash, s32 requestedPCMChannel = -1);
void StopStaticRadio(audStaticRadioEmitter *emitter);
bool IsStaticRadioEmitterActive(audStaticRadioEmitter *emitter);
bool ShouldBlockPauseMenuRetunes() const;
static void SkipStationsForward(void);
bool IsTimeToRetune(u32 timeInMs);
u8 GetPendingPlayerRadioStationRetunes(void)
{
return sm_PendingPlayerRadioStationRetunes;
}
void ClearPendingPlayerRadioStationRetunes(void)
{
sm_PendingPlayerRadioStationRetunes = 0;
sm_ForceVehicleExplicitRetune = false;
}
void OnRetuneActioned(void);
bool IsPlayerInVehicle(void)
{
return m_IsPlayerInVehicleForRadio;
}
f32 GetPlayerVehicleInsideFactor(void)
{
return m_PlayerVehicleInsideFactor;
}
CVehicle *GetLastPlayerVehicle(void)
{
return m_LastPlayerVehicle;
}
CVehicle *GetPlayerVehicle(void)
{
return m_PlayerVehicle;
}
const audRadioStation *GetPlayerRadioStation()
{
return m_PlayerRadioStation;
}
u8 IsPlayerRadioActive() const
{
return (m_PlayerVehicleRadioState == PLAYER_RADIO_PLAYING || m_MobilePhoneRadioState == PLAYER_RADIO_PLAYING);
}
void SetPlayerRadioStation(const audRadioStation *station)
{
m_PlayerRadioStation = station;
}
bool StopEmittersForPlayerVehicle() const;
const char *GetPlayerRadioStationNamePendingRetune() const;
const audRadioStation *GetPlayerRadioStationPendingRetune() const;
const audRadioStation *GetLastPlayerRadioStation()
{
return m_LastPlayerRadioStation;
}
bool IsMobilePhoneRadioActive(void)
{
return sm_IsMobilePhoneRadioActive;
}
bool IsRetuning(void)
{
return ((m_PlayerVehicleRadioState == PLAYER_RADIO_RETUNING) ||
(m_MobilePhoneRadioState == PLAYER_RADIO_RETUNING));
}
bool IsStarting() const
{
return ((m_PlayerVehicleRadioState == PLAYER_RADIO_STARTING) ||
(m_MobilePhoneRadioState == PLAYER_RADIO_STARTING));
}
bool IsVehicleRadioOn(void)
{
return ((m_PlayerVehicleRadioState == PLAYER_RADIO_PLAYING) ||
(m_PlayerVehicleRadioState == PLAYER_RADIO_RETUNING));
}
bool WasPlayerInAVehicleForRadioLastFrame() const
{
return m_WasPlayerInVehicleForRadioLastFrame;
}
void SwitchOffRadio();
void PlayRadioOnOffSound(bool bModulateVolume = true );
void PlayStationSelectSound(bool bModulateVolume = true );
void PlayWheelShowSound();
void PlayWheelHideSound();
bool IsInFrontendMode() const
{
return m_InFrontendMode;
}
bool IsRetuningVehicleRadio(void)
{
return (m_PlayerVehicleRadioState == PLAYER_RADIO_RETUNING);
}
f32 GetVolumeOffset(void)
{
return m_VolumeOffset;
}
bool WasMobileRadioActiveOnEnteringFrontend(void)
{
return m_WasMobileRadioActiveOnEnteringFrontend;
}
void ForcePlayerRadioStation(const u32 stationId)
{
m_ForcePlayerStation = audRadioStation::GetStation(stationId);
}
void ForcePlayerRadioStation(const audRadioStation *station)
{
m_ForcePlayerStation = station;
}
u32 GetLastTimeVehicleRadioWasRetuned()
{
return m_LastTimeVehicleRadioWasRetuned;
}
bool WasVehicleRadioJustRetuned()
{
return m_VehicleRadioJustRetuned;
}
void FindFavouriteStations(u32 &mostFavourite, u32 &leastFavourite) const;
void StartFadeIn(const float delayTime, const float fadeTime);
void StartFadeOut(const float delayTime, const float fadeTime);
void MuteNextOnOffSound() { m_SkipOnOffSound = true; }
// PURPOSE
// Picks the most audible track and returns its text id; 0 for unknown
u32 GetAudibleTrackTextId() const;
// Gets the currently playing track id, as above, except only for the player's car/phone - to be used for tune-away info, not Zit!
u32 GetCurrentlyPlayingTrackTextId() const;
u32 GetPlayingTrackTextIdByStationIndex(const u32 index, bool &isUserTrack) const;
u32 GetPlayingTrackPlayTimeByStationIndex(const u32 index, bool &isUserTrack) const;
// PURPOSE
// Returns info on the next audible music beat, if available
// SEE ALSO
// audRadioTrack::GetNextBeat
bool GetCachedNextAudibleBeat(float &timeS, float &bpm, s32 &beatNum) const;
bool IsInControlOfRadio(void) const;
static void UpdateDLCBattleUnlockableTracks(bool allowReprioritization);
BANK_ONLY(static void RAGUpdateDLCBattleUnlockableTracks();)
void RetuneToStation(const char *stationName);
void RetuneToStation(const u32 stationNameHash);
void RetuneToStation(const audRadioStation *station);
void SetMobilePhoneRadioState(bool isActive);
bool IsMobileRadioNormallyPermitted() const;
static void RetuneRadioUp(void);
static void RetuneRadioDown(void);
static void ToggleMobilePhoneRadioState(void);
BANK_ONLY(static void DebugLockStation(void);)
BANK_ONLY(static void DebugUnlockStation(void);)
BANK_ONLY(static void DebugHideStation(void);)
BANK_ONLY(static void DebugUnHideStation(void);)
#if HEIST3_HIDDEN_RADIO_ENABLED
static u32* GetEncryptionKeyForBank(u32 bankId);
#endif
void FrontendUpdate(const bool shouldPreviewRadio);
void Pause();
void Unpause();
virtual bool IsUnpausable() const
{
return true;
}
void StartEndCredits();
void StopEndCredits();
void SetIgnorePlayerRadioShudown(bool ignore)
{
m_IgnorePlayerVehicleRadioShutdown = ignore;
}
void MuteRetunes()
{
m_AreRetunesMuted = true;
}
void UnmuteRetunes()
{
m_AreRetunesMuted = false;
}
void SetAutoUnfreezeForPlayer(const bool shouldUnfreeze)
{
m_AutoUnfreezeForPlayer = shouldUnfreeze;
// Disable any active timer
m_AutoUnfreezeForPlayerTimer = 0.f;
}
void SetAutoUnfreezeForPlayer(const float delayTime)
{
if(delayTime == 0.f)
{
m_AutoUnfreezeForPlayer = true;
}
m_AutoUnfreezeForPlayerTimer = delayTime;
}
void SetFrontendFadeTime(const float fadeTimeSeconds);
#if __BANK
void DrawDebug();
void DebugDrawStations();
void PrintRadioDebug();
static void PopulateRetuneWidgetStationNames();
static void DebugAllocateAllStreamSlots();
static void DebugFreeStreamSlots();
static void RetuneToRequestedStation(void);
static void RetuneClubEmittersToRequestedStation(void);
static void DebugPrintTrackListInfo();
static void AddWidgets(bkBank &bank);
static void DebugShutdownTracks();
#if __WIN32PC
static bool sm_DebugUserMusic;
#endif
#endif // __BANK
#if !__FINAL
static void SkipForward(void);
static void SkipForwardToTransition(void);
static bool sm_ShouldMuteRadio;
#endif // !__FINAL
bool IsRadioFadedOut() const
{
return m_FadeVolumeLinear <= g_SilenceVolumeLin;
}
const audSoundSet &GetRadioSounds() const { return m_RadioSounds; }
bool IsPlayerInAVehicleWithARadio() const { return m_IsPlayerInAVehicleWithARadio; }
void SetForcePlayerCharacterStation(const bool force) { m_ForcePlayerCharacterStations = force; }
bool MPDriverHasTriggeredRadioChange() const { return m_bMPDriverHasTriggeredRadioChange; }
void SetMPDriverTriggeredRadioChange() { m_bMPDriverHasTriggeredRadioChange = true; }
#if GTA_REPLAY
void PreUpdateReplayMusic(bool play = false);
void StopReplayMusic(bool isPreview = false, bool noRelease = false);
bool IsStartingReplayPreview() { return m_ShouldPlayReplayPreview; }
#endif // GTA_REPLAY
const audRadioStation* FindAudibleStation(const float searchRadius) const;
const audRadioStation* FindAudibleStation(CInteriorInst* pIntInst, s32 roomIdx) const;
private:
// PURPOSE
// Returns info on the next audible music beat, if available
// SEE ALSO
// audRadioTrack::GetNextBeat
bool GetNextAudibleBeat(float &timeS, float &bpm, s32 &beatNum) const;
#if GTA_REPLAY
void UpdateReplayMusic();
void UpdateReplayMusicVolume(bool instant = false);
void UpdateReplayTrackPreview();
#endif
static u32 GetCurrentTimeMs();
void UpdateFade();
void CancelFade();
void StartMobileRadio();
void SetPlayerVehicleRadioState(u8 newState);
void SetMobileRadioState(u8 newState);
const audRadioTrack *FindAudibleTrack(const float searchRadius) const;
u32 ChooseRandomRadioStationForGenre(const RadioGenre genre) const;
void UpdatePlayerVehicleRadio(u32 timeInMs);
void UpdateMobilePhoneRadio(u32 timeInMs);
void ComputeVolumeOffset(void);
void UpdateUserControl(u32 timeInMs);
void TriggerRetuneBurst();
void UpdateRetuneSounds();
static u32 sm_LastRetuneTime;
static u8 sm_PendingPlayerRadioStationRetunes;
static bool sm_ForceVehicleExplicitRetune;
static bool sm_IsMobilePhoneRadioActive;
audEntityRadioEmitter m_MobilePhoneRadioEmitter;
const audRadioStation *m_PlayerRadioStation;
const audRadioStation *m_PlayerRadioStationPendingRetune;
const audRadioStation *m_LastPlayerRadioStation;
const audRadioStation *m_RequestedRadioStation;
const audRadioStation *m_ForcePlayerStation;
audSoundSet m_RadioSounds;
#if GTA_REPLAY
audSound* m_ReplayMusicSound;
u32 m_PreviouslyRequestedReplayTrack;
s32 m_PreviouslyRequestedReplayTrackID;
float m_ReplayMusicFadeOutScalar;
bool m_ShouldStopReplayMusic;
bool m_StopReplayMusicPreview;
bool m_StopReplayMusicNoRelease;
bool m_ShouldPrepareReplayMusic;
bool m_ShouldPlayReplayMusic;
bool m_ShouldUpdateReplayPreview;
bool m_ShouldPlayReplayPreview;
bool m_ShouldFadeReplayPreview;
bool m_ShouldUpdateReplayMusic;
u32 m_ReplayMusicStartOffset;
u32 m_ReplayMusicStartTime;
u32 m_PreviewReplayTrack;
bool m_HasParsedMarkers;
u32 m_RockoutStartOffset;
u32 m_RockoutEndOffset;
u32 m_PreviewReplayTrackTime;
bool m_WasDuckingMusicForSFX;
u32 m_SFXMusicDuckEndTime;
f32 m_SFXFullMusicDuckVolume;
#endif
u32 m_RetuneLastReleaseTime;
u32 m_VolumeLastReleaseTime;
u32 m_CurrentStationIndex;
u32 m_LastActiveRadioTimeMs;
f32 m_PlayerVehicleInsideFactor;
f32 m_VolumeOffset;
RegdVeh m_PlayerVehicle;
RegdVeh m_LastPlayerVehicle;
audSmoother m_PositionedToStereoVolumeSmoother;
f32 m_CachedTimeTillNextAudibleBeat;
f32 m_CachedAudibleBeatBPM;
s32 m_CachedAudibleBeatNum;
bool m_CachedAudibleBeatValid;
u32 m_TimeEnteringStartingState;
u32 m_LastPlayerModelId;
u8 m_PlayerVehicleRadioState;
u8 m_MobilePhoneRadioState;
bool m_IsPlayerInAVehicleWithARadio;
bool m_IsPlayerInVehicleForRadio;
bool m_WasPlayerInVehicleForRadioLastFrame;
bool m_WasMobilePhoneRadioActiveLastFrame;
bool m_WasMobileRadioActiveOnEnteringFrontend;
bool m_IsPlayerRadioSwitchedOff;
bool m_InFrontendMode;
bool m_AreRetunesMuted;
u32 m_LastTimeVehicleRadioWasRetuned;
bool m_VehicleRadioJustRetuned;
bool m_VehicleRadioRetuneAlreadyFlagged;
bool m_IgnorePlayerVehicleRadioShutdown;
float m_AutoUnfreezeForPlayerTimer;
bool m_AutoUnfreezeForPlayer;
bool m_ForcePlayerCharacterStations;
bool m_SkipOnOffSound;
bool m_bMPDriverHasTriggeredRadioChange;
enum FadeState
{
kFadingIn = 0,
kFadingOut,
kWaitingToFadeIn,
kWaitingToFadeOut,
kNotFading
};
FadeState m_FadeState;
float m_InvFadeTime;
float m_FadeWaitTime;
float m_FadeVolumeLinear;
float m_FrontendFadeTime;
float m_FrontendFadeTimeResetTimer;
bool m_StopEmittersForPlayerVehicle;
static bool sm_IsMobilePhoneRadioAvailable;
#if __BANK
static bool sm_ShouldPerformRadioRetuneTest;
static u8 sm_RequestedRadioStationIndex;
static u32 sm_RetunePeriodMs;
static const char *sm_RadioStationNames[g_MaxRadioStations];
u32 m_LastTestRetuneTimeMs;
#endif // __BANK
#if !__FINAL
static bool sm_ShouldSkipForward;
static bool sm_ShouldQuickSkipForward;
#endif // !__FINAL
};
extern audRadioAudioEntity g_RadioAudioEntity;
#endif // NA_RADIO_ENABLED
#endif // AUD_RADIOAUDIOENTITY_H