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.
 
 
 
 

370 lines
8.9 KiB

// Fill out your copyright notice in the Description page of Project Settings.
#include "BPFileIO.h"
#include "ModuleManager.h"
#include "FileHelper.h"
#include "ImageUtils.h"
#include "IImageWrapper.h"
#include "IImageWrapperModule.h"
bool UBPFileIO::VerifyOrCreateDirectory(const FString & TestDir)
{
IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile();
// Directory Exists?
if (!PlatformFile.DirectoryExists(*TestDir))
{
PlatformFile.CreateDirectory(*TestDir);
if (!PlatformFile.DirectoryExists(*TestDir))
{
return false;
}
}
return true;
}
bool UBPFileIO::VerifyDirectory(const FString & TestDir)
{
IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile();
// Directory Exists?
if (!PlatformFile.DirectoryExists(*TestDir))
{
return false;
}
return true;
}
uint8 getMpegVersion(uint8 num) {
/*
00 - MPEG Version 2.5 (unofficial)
01 - reserved
10 - MPEG Version 2 (ISO/IEC 13818-3)
11 - MPEG Version 1 (ISO/IEC 11172-3)
*/
if ((num & 0x03) == 0x03) {
return 1;
}
if ((num & 0x02) == 0x02) {
return 2;
}
return 0;
}
uint8 getMpegLayer(uint8 num) {
/**
00 - reserved
01 - Layer III
10 - Layer II
11 - Layer I
*/
if ((num & 0x03) == 0x03) {
return 1;
}
if ((num & 0x02) == 0x02) {
return 2;
}
if ((num & 0x01) == 0x01) {
return 3;
}
return 0;
}
int BITRATES[3][5][16] = { {},
{
{},
{0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0},
{0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 0},
{0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
},
{
{},
{0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 0},
{0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0},
{0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
}
};
int SAMPLE_RATES[3][4] = {
{0, 0, 0, 0},
{44100, 48000, 32000, 0},
{22050, 24000, 16000, 0}
};
int SAMPLES_PER_FRAME[3][4] = {
{0, 0, 0, 0},
{0, 384, 1152, 1152},
{0, 384, 1152, 576}
};
int getMpegFrameLength(bool has_padding, int sample_rate, uint8 layer, int bitrate, int num_samples) {
uint8 padding = has_padding ? 1 : 0;
if (sample_rate == 0) {
return 0;
}
if (layer == 1) {
return ((int) (12.0 * bitrate / sample_rate + padding)) * 4;
}
return ((int) (num_samples * (bitrate / 8) / sample_rate)) + padding;
}
uint8 getMpegChannels(uint8 num) {
/*
00 - Stereo
01 - Joint stereo (Stereo)
10 - Dual channel (2 mono channels)
11 - Single channel (Mono)
*/
if ((num & 0x03) == 0x03) {
return 1;
}
return 2;
}
int CheckFrameInfo(TArray<uint8> FileData, int i, int depth) {
bool isMP3 = (FileData[i] << 8 | (FileData[i + 1] & 0xF0)) == 0xFFF0;
if (!isMP3) return -1;
bool padding = (FileData[i + 2] & 0x02) >> 1 == 0x01;
uint8 mpegVersion = getMpegVersion(FileData[i + 1] >> 3);
uint8 mpegLayer = getMpegLayer(FileData[i + 1] >> 1);
int bitRate = BITRATES[mpegVersion][mpegLayer][(FileData[i + 2] >> 4) & 0x0F] * 1000;
int sampleRate = SAMPLE_RATES[mpegVersion][(FileData[i + 2] >> 2) & 0x03];
int sampleCount = SAMPLES_PER_FRAME[mpegVersion][mpegLayer];
uint8 channels = getMpegChannels(FileData[i + 3] >> 6);
int frameLength = getMpegFrameLength(padding, sampleRate, mpegLayer, bitRate, sampleCount);
if (frameLength == 0) return -1;
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);
if (depth < 2) {
int otherBitrate = CheckFrameInfo(FileData, i + frameLength, depth + 1);
if (otherBitrate != bitRate) {
return -1;
}
}
return bitRate;
}
FString UBPFileIO::CheckAudioFormatMatches(const FString & TestPath)
{
FString unknownProblem = "Error loading song file";
TArray<uint8> FileData;
if (!FFileHelper::LoadFileToArray(FileData, *TestPath))
{
UE_LOG(LogTemp, Error, TEXT("Failed to load file"));
return unknownProblem;
}
if (FileData.Num() < 1024) {
return unknownProblem;
}
for (int i = 0; i < 1024; i++) {
if ((FileData[i] << 8 | (FileData[i+1] & 0xF0)) == 0xFFF0) {
if (CheckFrameInfo(FileData, i, 0) != -1) {
if (TestPath.EndsWith(".ogg")) {
return "That looks like an MP3, you can't just rename files to change their type.\nGo get audacity and convert it properly.";
}
return "That looks like an MP3, but it needs to be an ogg.\nPlease use audacity to convert it.";
}
return unknownProblem;
}
}
return unknownProblem;
}
FString UBPFileIO::CheckImageFormatMatches(const FString & TestPath)
{
FString unknownProblem = "Something's weird with your cover image, and i don't know what it is.";
IImageWrapperModule& ImageWrapperModule = FModuleManager::LoadModuleChecked<IImageWrapperModule>(FName("ImageWrapper"));
TArray<uint8> FileData;
if (!FFileHelper::LoadFileToArray(FileData, *TestPath))
{
UE_LOG(LogTemp, Error, TEXT("Failed to load file"));
return unknownProblem;
}
EImageFormat fileFormat = ImageWrapperModule.DetectImageFormat(FileData.GetData(), FileData.Num());
if ((TestPath.EndsWith(".png") && fileFormat == EImageFormat::PNG) ||
((TestPath.EndsWith(".jpg") || TestPath.EndsWith(".jpeg")) && (fileFormat == EImageFormat::JPEG || fileFormat == EImageFormat::GrayscaleJPEG)))
{
return unknownProblem;
} else if (!TestPath.EndsWith(".png") && !TestPath.EndsWith(".jpg") && !TestPath.EndsWith(".jpeg")) {
return "Your cover image needs to be a jpg or png and end with .jpg, .jpeg or .png";
}
FString fileFormatStr;
switch (fileFormat) {
case EImageFormat::BMP:
fileFormatStr = "BMP";
break;
case EImageFormat::PNG:
fileFormatStr = "PNG";
break;
case EImageFormat::JPEG:
case EImageFormat::GrayscaleJPEG:
fileFormatStr = "JPG";
break;
case EImageFormat::ICO:
fileFormatStr = "ICO";
break;
case EImageFormat::EXR:
fileFormatStr = "EXR";
break;
case EImageFormat::ICNS:
fileFormatStr = "ICNS";
break;
case EImageFormat::Invalid:
default:
fileFormatStr = "Unknown";
}
return "Your cover image appears to be a " + fileFormatStr + " file, but the extension does not match";
}
TArray<FString> UBPFileIO::FindAllDirectories(const FString & TestDir)
{
TArray<FString> result;
IFileManager& FileManager = IFileManager::Get();
FString FinalPath = TestDir + "/*";
FileManager.FindFiles(result, *FinalPath, false, true);
return result;
}
TArray<FString> UBPFileIO::FindAllFiles(const FString & TestDir)
{
TArray<FString> result;
IFileManager& FileManager = IFileManager::Get();
FString FinalPath = TestDir + "/*";
FileManager.FindFiles(result, *FinalPath, true, false);
return result;
}
bool UBPFileIO::VerifyFile(const FString & TestFile)
{
if (FPlatformFileManager::Get().GetPlatformFile().FileExists(*TestFile))
{
return true;
}
return false;
}
bool UBPFileIO::RenameOrMoveFile(const FString & InputFile, const FString & OutputFile)
{
if (!FPlatformFileManager::Get().GetPlatformFile().FileExists(*InputFile))
{
return false;
}
if (!FPlatformFileManager::Get().GetPlatformFile().MoveFile(*OutputFile, *InputFile))
{
return false;
}
return true;
}
bool UBPFileIO::CopyFile(const FString & File, const FString& OutputDirectory, const FString& newName)
{
IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile();
if (PlatformFile.FileExists(*File))
{
if (PlatformFile.DirectoryExists(*OutputDirectory))
{
PlatformFile.CopyFile(*FString(OutputDirectory + "/" + newName), *File);
return true;
}
}
return false;
}
bool UBPFileIO::DeleteFile(const FString & File)
{
if (!FPlatformFileManager::Get().GetPlatformFile().DeleteFile(*File))
{
return false;
}
return true;
}
bool UBPFileIO::DeleteDirectory(const FString & Directory)
{
if (!FPlatformFileManager::Get().GetPlatformFile().DeleteDirectoryRecursively(*Directory))
{
return false;
}
return true;
}
int UBPFileIO::getFileSize(const FString & File)
{
return FPlatformFileManager::Get().GetPlatformFile().FileSize(*File);
}
int UBPFileIO::getTimestamp(const FString & File)
{
return FPlatformFileManager::Get().GetPlatformFile().GetTimeStamp(*File).ToUnixTimestamp();
}
bool UBPFileIO::SaveStringTextToFile(
FString SaveDirectory,
FString JoyfulFileName,
FString SaveText,
bool AllowOverWriting
) {
if (!FPlatformFileManager::Get().GetPlatformFile().CreateDirectoryTree(*SaveDirectory))
{
//Could not make the specified directory
return false;
//~~~~~~~~~~~~~~~~~~~~~~
}
//get complete file path
SaveDirectory += "\\";
SaveDirectory += JoyfulFileName;
//No over-writing?
if (!AllowOverWriting)
{
//Check if file exists already
if (FPlatformFileManager::Get().GetPlatformFile().FileExists(*SaveDirectory))
{
//no overwriting
return false;
}
}
return FFileHelper::SaveStringToFile(SaveText, *SaveDirectory, FFileHelper::EEncodingOptions::ForceUTF8WithoutBOM);
}