WwiseExternalSourceFileState.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. /*******************************************************************************
  2. The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
  3. Technology released in source code form as part of the game integration package.
  4. The content of this file may not be used without valid licenses to the
  5. AUDIOKINETIC Wwise Technology.
  6. Note that the use of the game engine is subject to the Unreal(R) Engine End User
  7. License Agreement at https://www.unrealengine.com/en-US/eula/unreal
  8. License Usage
  9. Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
  10. this file in accordance with the end user license agreement provided with the
  11. software or, alternatively, in accordance with the terms contained
  12. in a written agreement between you and Audiokinetic Inc.
  13. Copyright (c) 2023 Audiokinetic Inc.
  14. *******************************************************************************/
  15. #include "Wwise/WwiseExternalSourceFileState.h"
  16. #include "Wwise/WwiseExternalSourceManager.h"
  17. #include "Wwise/WwiseFileCache.h"
  18. #include "Wwise/WwiseStreamingManagerHooks.h"
  19. #include "Wwise/WwiseTask.h"
  20. #include "Wwise/API/WwiseSoundEngineAPI.h"
  21. #include "Wwise/Stats/FileHandlerMemory.h"
  22. #include "Async/MappedFileHandle.h"
  23. #include <inttypes.h>
  24. FWwiseExternalSourceFileState::FWwiseExternalSourceFileState(uint32 InMemoryAlignment, bool bInDeviceMemory,
  25. uint32 InMediaId, const FName& InMediaPathName, const FName& InRootPath, int32 InCodecId) :
  26. AkExternalSourceInfo(),
  27. MemoryAlignment(InMemoryAlignment),
  28. bDeviceMemory(bInDeviceMemory),
  29. MediaId(InMediaId),
  30. MediaPathName(InMediaPathName),
  31. RootPath(InRootPath),
  32. PlayCount(0)
  33. {
  34. idCodec = InCodecId;
  35. INC_DWORD_STAT(STAT_WwiseFileHandlerKnownExternalSourceMedia);
  36. }
  37. FWwiseExternalSourceFileState::~FWwiseExternalSourceFileState()
  38. {
  39. DEC_DWORD_STAT(STAT_WwiseFileHandlerKnownExternalSourceMedia);
  40. }
  41. bool FWwiseExternalSourceFileState::GetExternalSourceInfo(AkExternalSourceInfo& OutInfo)
  42. {
  43. OutInfo = static_cast<AkExternalSourceInfo>(*this);
  44. return szFile != nullptr || pInMemory != nullptr || idFile != 0;
  45. }
  46. void FWwiseExternalSourceFileState::IncrementPlayCount()
  47. {
  48. ++PlayCount;
  49. }
  50. bool FWwiseExternalSourceFileState::DecrementPlayCount()
  51. {
  52. const auto NewPlayCount = PlayCount.DecrementExchange() - 1;
  53. if (PlayCount < 0)
  54. {
  55. PlayCount.Store(0);
  56. UE_LOG(LogWwiseFileHandler, Warning, TEXT("FWwiseExternalSourceFileState: Play count went below zero for media %" PRIu32 " (%s)"),
  57. MediaId, *MediaPathName.ToString());
  58. }
  59. return NewPlayCount == 0;
  60. }
  61. FWwiseInMemoryExternalSourceFileState::FWwiseInMemoryExternalSourceFileState(uint32 InMemoryAlignment, bool bInDeviceMemory,
  62. uint32 InMediaId, const FName& InMediaPathName, const FName& InRootPath, int32 InCodecId) :
  63. FWwiseExternalSourceFileState(InMemoryAlignment, bInDeviceMemory, InMediaId, InMediaPathName, InRootPath, InCodecId),
  64. Ptr(nullptr),
  65. MappedHandle(nullptr),
  66. MappedRegion(nullptr)
  67. {
  68. #if WITH_EDITOR
  69. if (bDeviceMemory)
  70. {
  71. UE_LOG(LogWwiseFileHandler, Warning, TEXT("FWwiseExternalSourceFileState: Loading External Source Media with DeviceMemory=true while in in editor. Expect to see \"No Device Memory\" errors in the log."));
  72. }
  73. #endif
  74. }
  75. void FWwiseInMemoryExternalSourceFileState::OpenFile(FOpenFileCallback&& InCallback)
  76. {
  77. SCOPED_WWISEFILEHANDLER_EVENT_3(TEXT("FWwiseInMemoryExternalSourceFileState::OpenFile"));
  78. if (UNLIKELY(uiMemorySize || pInMemory))
  79. {
  80. UE_LOG(LogWwiseFileHandler, Error, TEXT("FWwiseInMemoryExternalSourceFileState::OpenFile %" PRIu32 " (%s): Seems to be already opened."), MediaId, *MediaPathName.ToString());
  81. return OpenFileFailed(MoveTemp(InCallback));
  82. }
  83. const auto FullPathName = RootPath.ToString() / MediaPathName.ToString();
  84. int64 FileSize = 0;
  85. if (LIKELY(GetFileToPtr(const_cast<const uint8*&>(reinterpret_cast<uint8*&>(pInMemory)), FileSize,
  86. FullPathName, bDeviceMemory, MemoryAlignment, true,
  87. STAT_WwiseMemoryExtSrc_FName, STAT_WwiseMemoryExtSrcDevice_FName)))
  88. {
  89. UE_LOG(LogWwiseFileHandler, Verbose, TEXT("FWwiseInMemoryExternalSourceFileState::OpenFile %" PRIu32 " (%s)"), MediaId, *MediaPathName.ToString());
  90. uiMemorySize = FileSize;
  91. return OpenFileSucceeded(MoveTemp(InCallback));
  92. }
  93. else
  94. {
  95. UE_LOG(LogWwiseFileHandler, Error, TEXT("FWwiseInMemoryExternalSourceFileState::OpenFile %" PRIu32 ": Failed to open In-Memory External Source (%s)."), MediaId, *FullPathName);
  96. pInMemory = nullptr;
  97. FileSize = 0;
  98. return OpenFileFailed(MoveTemp(InCallback));
  99. }
  100. }
  101. void FWwiseInMemoryExternalSourceFileState::LoadInSoundEngine(FLoadInSoundEngineCallback&& InCallback)
  102. {
  103. SCOPED_WWISEFILEHANDLER_EVENT_3(TEXT("FWwiseInMemoryExternalSourceFileState::LoadInSoundEngine"));
  104. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseInMemoryExternalSourceFileState::LoadInSoundEngine %" PRIu32 " (%s)"), MediaId, *MediaPathName.ToString());
  105. INC_DWORD_STAT(STAT_WwiseFileHandlerLoadedExternalSourceMedia);
  106. LoadInSoundEngineSucceeded(MoveTemp(InCallback));
  107. }
  108. void FWwiseInMemoryExternalSourceFileState::UnloadFromSoundEngine(FUnloadFromSoundEngineCallback&& InCallback)
  109. {
  110. SCOPED_WWISEFILEHANDLER_EVENT_3(TEXT("FWwiseInMemoryExternalSourceFileState::UnloadFromSoundEngine"));
  111. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseInMemoryExternalSourceFileState::UnloadFromSoundEngine %" PRIu32 " (%s)"), MediaId, *MediaPathName.ToString());
  112. DEC_DWORD_STAT(STAT_WwiseFileHandlerLoadedExternalSourceMedia);
  113. UnloadFromSoundEngineDone(MoveTemp(InCallback));
  114. }
  115. void FWwiseInMemoryExternalSourceFileState::CloseFile(FCloseFileCallback&& InCallback)
  116. {
  117. SCOPED_WWISEFILEHANDLER_EVENT_3(TEXT("FWwiseInMemoryExternalSourceFileState::CloseFile"));
  118. UE_LOG(LogWwiseFileHandler, Verbose, TEXT("FWwiseInMemoryExternalSourceFileState::CloseFile %" PRIu32 " (%s)"), MediaId, *MediaPathName.ToString());
  119. DeallocateMemory(const_cast<const uint8*&>(reinterpret_cast<uint8*&>(pInMemory)), uiMemorySize, bDeviceMemory, MemoryAlignment, true, STAT_WwiseMemoryExtSrc_FName, STAT_WwiseMemoryExtSrcDevice_FName);
  120. pInMemory = nullptr;
  121. uiMemorySize = 0;
  122. CloseFileDone(MoveTemp(InCallback));
  123. }
  124. FWwiseStreamedExternalSourceFileState::FWwiseStreamedExternalSourceFileState(uint32 InMemoryAlignment, bool bInDeviceMemory,
  125. uint32 InPrefetchSize, uint32 InStreamingGranularity,
  126. uint32 InMediaId, const FName& InMediaPathName, const FName& InRootPath, int32 InCodecId) :
  127. FWwiseExternalSourceFileState(InMemoryAlignment, bInDeviceMemory, InMediaId, InMediaPathName, InRootPath, InCodecId),
  128. PrefetchSize(InPrefetchSize),
  129. StreamingGranularity(InStreamingGranularity),
  130. StreamedFile(nullptr)
  131. {
  132. sourceID = InMediaId;
  133. pMediaMemory = nullptr;
  134. uMediaSize = 0;
  135. idFile = InMediaId;
  136. }
  137. void FWwiseStreamedExternalSourceFileState::CloseStreaming()
  138. {
  139. auto* ExternalSourceManager = IWwiseExternalSourceManager::Get();
  140. if (UNLIKELY(!ExternalSourceManager))
  141. {
  142. UE_LOG(LogWwiseFileHandler, Log, TEXT("FWwiseStreamedExternalSourceFileState::CloseStreaming %" PRIu32 " (%s): Closing without an ExternalSourceManager."), MediaId, *MediaPathName.ToString());
  143. return;
  144. }
  145. ExternalSourceManager->GetStreamingHooks().CloseStreaming(MediaId, *this);
  146. }
  147. void FWwiseStreamedExternalSourceFileState::OpenFile(FOpenFileCallback&& InCallback)
  148. {
  149. SCOPED_WWISEFILEHANDLER_EVENT_3(TEXT("FWwiseStreamedExternalSourceFileState::OpenFile"));
  150. if (UNLIKELY(iFileSize != 0 || StreamedFile))
  151. {
  152. UE_LOG(LogWwiseFileHandler, Error, TEXT("FWwiseStreamedExternalSourceFileState::OpenFile %" PRIu32 " (%s): Stream seems to be already opened."), MediaId, *MediaPathName.ToString());
  153. return OpenFileFailed(MoveTemp(InCallback));
  154. }
  155. if (PrefetchSize == 0)
  156. {
  157. UE_LOG(LogWwiseFileHandler, Verbose, TEXT("FWwiseStreamedExternalSourceFileState::OpenFile %" PRIu32 " (%s)"), MediaId, *MediaPathName.ToString());
  158. return OpenFileSucceeded(MoveTemp(InCallback));
  159. }
  160. // Process PrefetchSize and send as SetMedia
  161. const auto FullPathName = RootPath.ToString() / MediaPathName.ToString();
  162. auto PrefetchWithGranularity = PrefetchSize;
  163. if (StreamingGranularity > 1)
  164. {
  165. auto PrefetchChunks = PrefetchSize / StreamingGranularity;
  166. if (PrefetchSize % StreamingGranularity > 0)
  167. {
  168. PrefetchChunks += 1;
  169. }
  170. PrefetchWithGranularity = PrefetchChunks * StreamingGranularity;
  171. }
  172. int64 FileSize = 0;
  173. if (UNLIKELY(!GetFileToPtr(const_cast<const uint8*&>(pMediaMemory), FileSize,
  174. FullPathName, false, 0, false,
  175. STAT_WwiseMemoryExtSrcPrefetch_FName, STAT_WwiseMemoryExtSrcPrefetchDevice_FName,
  176. PrefetchWithGranularity
  177. )))
  178. {
  179. UE_LOG(LogWwiseFileHandler, Error, TEXT("FWwiseStreamedExternalSourceFileState::OpenFile %" PRIu32 " (%s): Failed to Read prefetch ExternalSource (%s)."), MediaId, *MediaPathName.ToString(), *FullPathName);
  180. pMediaMemory = nullptr;
  181. return OpenFileFailed(MoveTemp(InCallback));
  182. }
  183. INC_DWORD_STAT(STAT_WwiseFileHandlerPrefetchedExternalSourceMedia);
  184. uMediaSize = FileSize;
  185. UE_CLOG(FileSize == PrefetchSize, LogWwiseFileHandler, Verbose, TEXT("FWwiseStreamedExternalSourceFileState::OpenFile %" PRIu32 " (%s): Prefetched %" PRIu32 " bytes."), MediaId, *MediaPathName.ToString(), uMediaSize);
  186. UE_CLOG(PrefetchSize != PrefetchWithGranularity && PrefetchWithGranularity == FileSize, LogWwiseFileHandler, Verbose, TEXT("FWwiseStreamedExternalSourceFileState::OpenFile %" PRIu32 " (%s): Prefetched (%" PRIu32 ") -> %" PRIu32 " bytes."), MediaId, *MediaPathName.ToString(), PrefetchSize, PrefetchWithGranularity);
  187. UE_CLOG(PrefetchWithGranularity != FileSize, LogWwiseFileHandler, Verbose, TEXT("FWwiseStreamedExternalSourceFileState::OpenFile %" PRIu32 " (%s): Prefetched (%" PRIu32 " -> %" PRIu32 ") -> %" PRIu32 " bytes."), MediaId, *MediaPathName.ToString(), PrefetchSize, PrefetchWithGranularity, uMediaSize);
  188. return OpenFileSucceeded(MoveTemp(InCallback));
  189. }
  190. void FWwiseStreamedExternalSourceFileState::LoadInSoundEngine(FLoadInSoundEngineCallback&& InCallback)
  191. {
  192. SCOPED_WWISEFILEHANDLER_EVENT_3(TEXT("FWwiseStreamedExternalSourceFileState::LoadInSoundEngine"));
  193. if (UNLIKELY(iFileSize != 0 || StreamedFile))
  194. {
  195. UE_LOG(LogWwiseFileHandler, Error, TEXT("FWwiseStreamedExternalSourceFileState::LoadInSoundEngine %" PRIu32 " (%s): Stream seems to be already loaded."), MediaId, *MediaPathName.ToString());
  196. return LoadInSoundEngineFailed(MoveTemp(InCallback));
  197. }
  198. FWwiseFileCache* FileCache = FWwiseFileCache::Get();
  199. if (UNLIKELY(!FileCache))
  200. {
  201. UE_LOG(LogWwiseFileHandler, Error, TEXT("FWwiseStreamedExternalSourceFileState::LoadInSoundEngine %" PRIu32 " (%s): WwiseFileCache not available."), MediaId, *MediaPathName.ToString());
  202. return LoadInSoundEngineFailed(MoveTemp(InCallback));
  203. }
  204. const auto FullPathName = RootPath.ToString() / MediaPathName.ToString();
  205. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseStreamedExternalSourceFileState::LoadInSoundEngine %" PRIu32 " (%s): Opening file"), MediaId, *MediaPathName.ToString());
  206. FileCache->CreateFileCacheHandle(StreamedFile, FullPathName, [this, Callback = MoveTemp(InCallback)](bool bResult) mutable
  207. {
  208. if (UNLIKELY(!bResult))
  209. {
  210. UE_LOG(LogWwiseFileHandler, Error, TEXT("FWwiseStreamedExternalSourceFileState::LoadInSoundEngine %" PRIu32 ": Failed to load Streaming ExternalSource (%s)."), MediaId, *MediaPathName.ToString());
  211. LaunchWwiseTask(WWISEFILEHANDLER_ASYNC_NAME("FWwiseStreamedExternalSourceFileState::LoadInSoundEngine delete"), [StreamedFile = StreamedFile]
  212. {
  213. delete StreamedFile;
  214. });
  215. StreamedFile = nullptr;
  216. return LoadInSoundEngineFailed(MoveTemp(Callback));
  217. }
  218. iFileSize = StreamedFile->GetFileSize();
  219. UE_LOG(LogWwiseFileHandler, Verbose, TEXT("FWwiseStreamedExternalSourceFileState::LoadInSoundEngine %" PRIu32 " (%s)"), MediaId, *MediaPathName.ToString());
  220. INC_DWORD_STAT(STAT_WwiseFileHandlerLoadedExternalSourceMedia);
  221. return LoadInSoundEngineSucceeded(MoveTemp(Callback));
  222. });
  223. }
  224. void FWwiseStreamedExternalSourceFileState::UnloadFromSoundEngine(FUnloadFromSoundEngineCallback&& InCallback)
  225. {
  226. SCOPED_WWISEFILEHANDLER_EVENT_3(TEXT("FWwiseStreamedExternalSourceFileState::UnloadFromSoundEngine"));
  227. UE_LOG(LogWwiseFileHandler, Verbose, TEXT("FWwiseStreamedExternalSourceFileState::UnloadFromSoundEngine %" PRIu32 " (%s)"), MediaId, *MediaPathName.ToString());
  228. const auto* StreamedFileToDelete = StreamedFile;
  229. StreamedFile = nullptr;
  230. iFileSize = 0;
  231. delete StreamedFileToDelete;
  232. DEC_DWORD_STAT(STAT_WwiseFileHandlerLoadedExternalSourceMedia);
  233. UnloadFromSoundEngineDone(MoveTemp(InCallback));
  234. }
  235. void FWwiseStreamedExternalSourceFileState::CloseFile(FCloseFileCallback&& InCallback)
  236. {
  237. SCOPED_WWISEFILEHANDLER_EVENT_3(TEXT("FWwiseStreamedExternalSourceFileState::CloseFile"));
  238. if (pMediaMemory == nullptr)
  239. {
  240. UE_LOG(LogWwiseFileHandler, Verbose, TEXT("FWwiseStreamedExternalSourceFileState::CloseFile %" PRIu32 " (%s)"), MediaId, *MediaPathName.ToString());
  241. return CloseFileDone(MoveTemp(InCallback));
  242. }
  243. UE_LOG(LogWwiseFileHandler, Verbose, TEXT("FWwiseStreamedExternalSourceFileState::CloseFile %" PRIu32 " (%s): Unloaded prefetch."), MediaId, *MediaPathName.ToString());
  244. DeallocateMemory(pMediaMemory, uMediaSize, bDeviceMemory, MemoryAlignment, true, STAT_WwiseMemoryExtSrcPrefetch_FName, STAT_WwiseMemoryExtSrcPrefetchDevice_FName);
  245. pMediaMemory = nullptr;
  246. uMediaSize = 0;
  247. DEC_DWORD_STAT(STAT_WwiseFileHandlerPrefetchedExternalSourceMedia);
  248. return CloseFileDone(MoveTemp(InCallback));
  249. }
  250. bool FWwiseStreamedExternalSourceFileState::CanProcessFileOp() const
  251. {
  252. if (UNLIKELY(State != EState::Loaded))
  253. {
  254. UE_LOG(LogWwiseFileHandler, Error, TEXT("FWwiseStreamedExternalSourceFileState::CanProcessFileOp %" PRIu32 " (%s): IO Hook asked for a file operation, but state is not ready."), MediaId, *MediaPathName.ToString());
  255. return false;
  256. }
  257. return true;
  258. }
  259. AKRESULT FWwiseStreamedExternalSourceFileState::ProcessRead(AkFileDesc& InFileDesc, const AkIoHeuristics& InHeuristics, AkAsyncIOTransferInfo& OutTransferInfo, FWwiseAkFileOperationDone&& InFileOpDoneCallback)
  260. {
  261. if (pMediaMemory && OutTransferInfo.uFilePosition + OutTransferInfo.uRequestedSize <= uMediaSize)
  262. {
  263. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseStreamedExternalSourceFileState::ProcessRead: Reading prefetch %" PRIu32 " bytes @ %" PRIu64 " in file %" PRIu32 " (%s)"),
  264. OutTransferInfo.uRequestedSize, OutTransferInfo.uFilePosition, MediaId, *MediaPathName.ToString());
  265. FMemory::Memcpy(OutTransferInfo.pBuffer, pMediaMemory + OutTransferInfo.uFilePosition, OutTransferInfo.uRequestedSize);
  266. SCOPED_WWISEFILEHANDLER_EVENT_4(TEXT("FWwiseStreamedExternalSourceFileState::ProcessRead Callback"));
  267. InFileOpDoneCallback(&OutTransferInfo, AK_Success);
  268. return AK_Success;
  269. }
  270. UE_LOG(LogWwiseFileHandler, VeryVerbose, TEXT("FWwiseStreamedExternalSourceFileState::ProcessRead: Reading %" PRIu32 " bytes @ %" PRIu64 " in file %" PRIu32 " (%s)"),
  271. OutTransferInfo.uRequestedSize, OutTransferInfo.uFilePosition, MediaId, *MediaPathName.ToString());
  272. StreamedFile->ReadAkData(InHeuristics, OutTransferInfo, MoveTemp(InFileOpDoneCallback));
  273. return AK_Success;
  274. }