A modded EditSaber for making beat saber maps.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

331 lines
8.0 KiB

3 years ago
  1. // Fill out your copyright notice in the Description page of Project Settings.
  2. #include "BPFileIO.h"
  3. #include "ModuleManager.h"
  4. #include "FileHelper.h"
  5. #include "ImageUtils.h"
  6. #include "IImageWrapper.h"
  7. #include "IImageWrapperModule.h"
  8. bool UBPFileIO::VerifyOrCreateDirectory(const FString & TestDir)
  9. {
  10. IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile();
  11. // Directory Exists?
  12. if (!PlatformFile.DirectoryExists(*TestDir))
  13. {
  14. PlatformFile.CreateDirectory(*TestDir);
  15. if (!PlatformFile.DirectoryExists(*TestDir))
  16. {
  17. return false;
  18. }
  19. }
  20. return true;
  21. }
  22. bool UBPFileIO::VerifyDirectory(const FString & TestDir)
  23. {
  24. IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile();
  25. // Directory Exists?
  26. if (!PlatformFile.DirectoryExists(*TestDir))
  27. {
  28. return false;
  29. }
  30. return true;
  31. }
  32. uint8 getMpegVersion(uint8 num) {
  33. /*
  34. 00 - MPEG Version 2.5 (unofficial)
  35. 01 - reserved
  36. 10 - MPEG Version 2 (ISO/IEC 13818-3)
  37. 11 - MPEG Version 1 (ISO/IEC 11172-3)
  38. */
  39. if ((num & 0x03) == 0x03) {
  40. return 1;
  41. }
  42. if ((num & 0x02) == 0x02) {
  43. return 2;
  44. }
  45. return 0;
  46. }
  47. uint8 getMpegLayer(uint8 num) {
  48. /**
  49. 00 - reserved
  50. 01 - Layer III
  51. 10 - Layer II
  52. 11 - Layer I
  53. */
  54. if ((num & 0x03) == 0x03) {
  55. return 1;
  56. }
  57. if ((num & 0x02) == 0x02) {
  58. return 2;
  59. }
  60. if ((num & 0x01) == 0x01) {
  61. return 3;
  62. }
  63. return 0;
  64. }
  65. int BITRATES[3][5][16] = { {},
  66. {
  67. {},
  68. {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0},
  69. {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 0},
  70. {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0},
  71. {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
  72. },
  73. {
  74. {},
  75. {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 0},
  76. {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0},
  77. {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0},
  78. {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
  79. }
  80. };
  81. int SAMPLE_RATES[3][4] = {
  82. {0, 0, 0, 0},
  83. {44100, 48000, 32000, 0},
  84. {22050, 24000, 16000, 0}
  85. };
  86. int SAMPLES_PER_FRAME[3][4] = {
  87. {0, 0, 0, 0},
  88. {0, 384, 1152, 1152},
  89. {0, 384, 1152, 576}
  90. };
  91. int getMpegFrameLength(bool has_padding, int sample_rate, uint8 layer, int bitrate, int num_samples) {
  92. uint8 padding = has_padding ? 1 : 0;
  93. if (sample_rate == 0) {
  94. return 0;
  95. }
  96. if (layer == 1) {
  97. return ((int) (12.0 * bitrate / sample_rate + padding)) * 4;
  98. }
  99. return ((int) (num_samples * (bitrate / 8) / sample_rate)) + padding;
  100. }
  101. uint8 getMpegChannels(uint8 num) {
  102. /*
  103. 00 - Stereo
  104. 01 - Joint stereo (Stereo)
  105. 10 - Dual channel (2 mono channels)
  106. 11 - Single channel (Mono)
  107. */
  108. if ((num & 0x03) == 0x03) {
  109. return 1;
  110. }
  111. return 2;
  112. }
  113. int CheckFrameInfo(TArray<uint8> FileData, int i, int depth) {
  114. bool isMP3 = (FileData[i] << 8 | (FileData[i + 1] & 0xF0)) == 0xFFF0;
  115. if (!isMP3) return -1;
  116. bool padding = (FileData[i + 2] & 0x02) >> 1 == 0x01;
  117. uint8 mpegVersion = getMpegVersion(FileData[i + 1] >> 3);
  118. uint8 mpegLayer = getMpegLayer(FileData[i + 1] >> 1);
  119. int bitRate = BITRATES[mpegVersion][mpegLayer][(FileData[i + 2] >> 4) & 0x0F] * 1000;
  120. int sampleRate = SAMPLE_RATES[mpegVersion][(FileData[i + 2] >> 2) & 0x03];
  121. int sampleCount = SAMPLES_PER_FRAME[mpegVersion][mpegLayer];
  122. uint8 channels = getMpegChannels(FileData[i + 3] >> 6);
  123. int frameLength = getMpegFrameLength(padding, sampleRate, mpegLayer, bitRate, sampleCount);
  124. if (frameLength == 0) return -1;
  125. UE_LOG(LogTemp, Error, TEXT("Possible mp3 V: %d, L: %d, P: %d, Bitrate: %d, Channels: %d, Sample rate: %d, Sample count: %d, Frame len: %d"), mpegVersion, mpegLayer, padding, bitRate, channels, sampleRate, sampleCount, frameLength);
  126. if (depth < 2) {
  127. int otherBitrate = CheckFrameInfo(FileData, i + frameLength, depth + 1);
  128. if (otherBitrate != bitRate) {
  129. return -1;
  130. }
  131. }
  132. return bitRate;
  133. }
  134. FString UBPFileIO::CheckAudioFormatMatches(const FString & TestPath)
  135. {
  136. FString unknownProblem = "Error loading song file";
  137. TArray<uint8> FileData;
  138. if (!FFileHelper::LoadFileToArray(FileData, *TestPath))
  139. {
  140. UE_LOG(LogTemp, Error, TEXT("Failed to load file"));
  141. return unknownProblem;
  142. }
  143. for (int i = 0; i < 1024; i++) {
  144. if ((FileData[i] << 8 | (FileData[i+1] & 0xF0)) == 0xFFF0) {
  145. if (CheckFrameInfo(FileData, i, 0) != -1) {
  146. return "That looks like an MP3, you can't just rename files to change their type.\nGo get audacity and convert it properly.";
  147. }
  148. return unknownProblem;
  149. }
  150. }
  151. return unknownProblem;
  152. }
  153. FString UBPFileIO::CheckImageFormatMatches(const FString & TestPath)
  154. {
  155. FString unknownProblem = "Something's weird with your cover image, and i don't know what it is.";
  156. IImageWrapperModule& ImageWrapperModule = FModuleManager::LoadModuleChecked<IImageWrapperModule>(FName("ImageWrapper"));
  157. TArray<uint8> FileData;
  158. if (!FFileHelper::LoadFileToArray(FileData, *TestPath))
  159. {
  160. UE_LOG(LogTemp, Error, TEXT("Failed to load file"));
  161. return unknownProblem;
  162. }
  163. EImageFormat fileFormat = ImageWrapperModule.DetectImageFormat(FileData.GetData(), FileData.Num());
  164. if ((TestPath.EndsWith(".png") && fileFormat == EImageFormat::PNG) ||
  165. ((TestPath.EndsWith(".jpg") || TestPath.EndsWith(".jpeg")) && (fileFormat == EImageFormat::JPEG || fileFormat == EImageFormat::GrayscaleJPEG)))
  166. {
  167. return unknownProblem;
  168. } else if (!TestPath.EndsWith(".png") && !TestPath.EndsWith(".jpg") && !TestPath.EndsWith(".jpeg")) {
  169. return "Your cover image needs to be a jpg or png and end with .jpg, .jpeg or .png";
  170. }
  171. FString fileFormatStr;
  172. switch (fileFormat) {
  173. case EImageFormat::BMP:
  174. fileFormatStr = "BMP";
  175. break;
  176. case EImageFormat::PNG:
  177. fileFormatStr = "PNG";
  178. break;
  179. case EImageFormat::JPEG:
  180. case EImageFormat::GrayscaleJPEG:
  181. fileFormatStr = "JPG";
  182. break;
  183. case EImageFormat::ICO:
  184. fileFormatStr = "ICO";
  185. break;
  186. case EImageFormat::EXR:
  187. fileFormatStr = "EXR";
  188. break;
  189. case EImageFormat::ICNS:
  190. fileFormatStr = "ICNS";
  191. break;
  192. case EImageFormat::Invalid:
  193. default:
  194. fileFormatStr = "Unknown";
  195. }
  196. return "Your cover image appears to be a " + fileFormatStr + " file, but the extension does not match";
  197. }
  198. TArray<FString> UBPFileIO::FindAllDirectories(const FString & TestDir)
  199. {
  200. TArray<FString> result;
  201. IFileManager& FileManager = IFileManager::Get();
  202. FString FinalPath = TestDir + "/*";
  203. FileManager.FindFiles(result, *FinalPath, false, true);
  204. return result;
  205. }
  206. TArray<FString> UBPFileIO::FindAllFiles(const FString & TestDir)
  207. {
  208. TArray<FString> result;
  209. IFileManager& FileManager = IFileManager::Get();
  210. FString FinalPath = TestDir + "/*";
  211. FileManager.FindFiles(result, *FinalPath, true, false);
  212. return result;
  213. }
  214. bool UBPFileIO::VerifyFile(const FString & TestFile)
  215. {
  216. if (FPlatformFileManager::Get().GetPlatformFile().FileExists(*TestFile))
  217. {
  218. return true;
  219. }
  220. return false;
  221. }
  222. bool UBPFileIO::RenameOrMoveFile(const FString & InputFile, const FString & OutputFile)
  223. {
  224. if (!FPlatformFileManager::Get().GetPlatformFile().FileExists(*InputFile))
  225. {
  226. return false;
  227. }
  228. if (!FPlatformFileManager::Get().GetPlatformFile().MoveFile(*OutputFile, *InputFile))
  229. {
  230. return false;
  231. }
  232. return true;
  233. }
  234. bool UBPFileIO::CopyFile(const FString & File, const FString& OutputDirectory, const FString& newName)
  235. {
  236. IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile();
  237. if (PlatformFile.FileExists(*File))
  238. {
  239. if (PlatformFile.DirectoryExists(*OutputDirectory))
  240. {
  241. PlatformFile.CopyFile(*FString(OutputDirectory + "/" + newName), *File);
  242. return true;
  243. }
  244. }
  245. return false;
  246. }
  247. bool UBPFileIO::DeleteFile(const FString & File)
  248. {
  249. if (!FPlatformFileManager::Get().GetPlatformFile().DeleteFile(*File))
  250. {
  251. return false;
  252. }
  253. return true;
  254. }
  255. bool UBPFileIO::DeleteDirectory(const FString & Directory)
  256. {
  257. if (!FPlatformFileManager::Get().GetPlatformFile().DeleteDirectoryRecursively(*Directory))
  258. {
  259. return false;
  260. }
  261. return true;
  262. }
  263. int UBPFileIO::getFileSize(const FString & File)
  264. {
  265. return FPlatformFileManager::Get().GetPlatformFile().FileSize(*File);
  266. }
  267. int UBPFileIO::getTimestamp(const FString & File)
  268. {
  269. return FPlatformFileManager::Get().GetPlatformFile().GetTimeStamp(*File).ToUnixTimestamp();
  270. }