From 948b22c78bcc8ac8c7b56d45666796d24d760e12 Mon Sep 17 00:00:00 2001 From: Kermalis <29823718+Kermalis@users.noreply.github.com> Date: Wed, 17 May 2023 01:37:23 -0400 Subject: [PATCH] Finish the CMD application FOINALLY --- .../MIDIProgramSplitter.CMD.csproj | 14 +- MIDIProgramSplitter.CMD/Program.cs | 434 +++++++++++++++--- MIDIProgramSplitter.CMD/WinUtils.cs | 40 -- MIDIProgramSplitter.sln | 10 +- 4 files changed, 394 insertions(+), 104 deletions(-) delete mode 100644 MIDIProgramSplitter.CMD/WinUtils.cs diff --git a/MIDIProgramSplitter.CMD/MIDIProgramSplitter.CMD.csproj b/MIDIProgramSplitter.CMD/MIDIProgramSplitter.CMD.csproj index 3280615..eea0a63 100644 --- a/MIDIProgramSplitter.CMD/MIDIProgramSplitter.CMD.csproj +++ b/MIDIProgramSplitter.CMD/MIDIProgramSplitter.CMD.csproj @@ -1,4 +1,4 @@ - + net7.0 @@ -8,6 +8,18 @@ true MIDIProgramSplitter.CMD + + Debug;Release;Release_Win64 + + + + false + true + false + win-x64 + true + false + None diff --git a/MIDIProgramSplitter.CMD/Program.cs b/MIDIProgramSplitter.CMD/Program.cs index 1d56b60..9480aed 100644 --- a/MIDIProgramSplitter.CMD/Program.cs +++ b/MIDIProgramSplitter.CMD/Program.cs @@ -9,99 +9,409 @@ internal static class Program { private static void Main(string[] args) { - const string OUTFLP = @"C:\Users\Kermalis\Documents\Development\GitHub\MIDIProgramSplitter\TestOUT.flp"; - //const byte DEFAULT_MIDI_VOL = 100; // MP2K, but the VGMS ripped ones scale back up to 127 - const byte DEFAULT_MIDI_VOL = 127; // SDAT/MIDI - - //Test_ReadFLP(); return; - -#if DEBUG - args = new string[] + if (args.Length < 3) { - //@"E:\Music\MIDIs\Pokemon B2W2\Music\Roaming Legendary Battle format1.mid", - - //@"E:\Music\MIDIs\Pokemon B2W2\Music\B2W2KantoChampion format1.mid", - //@"D:\Music\Samples, Presets, Soundfonts, VSTs, etc\Soundfonts\Game Rips\Gen5\BANK_MUS_SW_VS_RG_CHAMP.dls", + ShowUsage(); + return; + } - //@"E:\Music\MIDIs\Pokemon B2W2\Music\B2W2SinnohLeader format1.mid", - //@"E:\Music\MIDIs\Pokemon B2W2\Music\DEEEEEEENNIS format1.mid", - //@"E:\Music\MIDIs\Pokemon B2W2\Music\Elite4Battle format1.mid", - //@"E:\Music\MIDIs\Pokemon B2W2\Music\Iris Battle format1.mid", + try + { + string mode = args[0].ToLowerInvariant(); + switch (mode) + { + case "-midsplit": + { + Mode_MIDSplit(args.AsSpan(1)); + break; + } + case "-flpreport": + { + Mode_FLPReport(args.AsSpan(1)); + break; + } + case "-midtoflp": + { + Mode_MIDToFLP(args.AsSpan(1)); + break; + } + default: + { + ShowUsage(); + return; + } + } + } + catch (Exception ex) + { + Console.WriteLine("Error: " + ex); + } + } - @"E:\Music\MIDIs\Pokemon B2W2\Music\Colress Battle format1.mid", - @"D:\Music\Samples, Presets, Soundfonts, VSTs, etc\Soundfonts\Game Rips\Gen5\BANK_MUS_SW_VS_ACHROMA.dls", + private static void Mode_MIDSplit(ReadOnlySpan args) + { + string inMIDIPath = args[0]; - //@"E:\Music\MIDIs\DS Rips\HGSS\BATTLE1\SEQ_GS_VS_TRAINER format1.mid", - //@"E:\Music\MIDIs\DS Rips\HGSS\BATTLE2\SEQ_GS_VS_RIVAL format1.mid", - //@"E:\Music\MIDIs\DS Rips\HGSS\BATTLE6\SEQ_GS_VS_RAIKOU format1.mid", - //@"C:\Users\Kermalis\Documents\Development\GitHub\pokeemerald\sound\songs\midi\mus_vs_aqua_magma.mid", - //@"C:\Users\Kermalis\Documents\Development\GitHub\pokeemerald\sound\songs\midi\mus_surf.mid", + if (!File.Exists(inMIDIPath)) + { + Console.WriteLine("File not found: \"" + inMIDIPath + '\"'); + return; + } - @"E:\Music\MIDIs\Split Rips\BWB2W2" - //@"E:\Music\MIDIs\Split Rips\HGSS" - //@"E:\Music\MIDIs\Split Rips\RSE" - }; -#endif + string outMIDIPath = args[1]; + byte defaultVol = 127; - if (args.Length != 3) + try { - throw new Exception("Must have two arguments"); // TODO: Example usage + for (int i = 2; i < args.Length;) + { + string extraArg = args[i++].ToLowerInvariant(); + switch (extraArg) + { + case "-defaultvol": + { + HandleDefaultVol(args[i++], ref defaultVol); + break; + } + default: throw new Exception(); + } + } } - - string inMIDIFile = args[0]; - string dlsPath = args[1]; - string outDir = args[2]; - if (!File.Exists(inMIDIFile)) + catch { - throw new Exception("File not found: \"" + inMIDIFile + '\"'); + ShowUsage(); + return; } - Directory.CreateDirectory(outDir); - string outMIDIFile = Path.Combine(outDir, Path.GetFileName(inMIDIFile)); + + CreateOutputDir(outMIDIPath); MIDIFile inMIDI; - using (FileStream fs = File.OpenRead(inMIDIFile)) + using (FileStream fs = File.OpenRead(inMIDIPath)) { inMIDI = new MIDIFile(fs); } - var splitter = new Splitter(inMIDI, DEFAULT_MIDI_VOL); - using (FileStream fs = File.Create(outMIDIFile)) + var splitter = new Splitter(inMIDI, defaultVol); + using (FileStream fs = File.Create(outMIDIPath)) { splitter.SaveMIDI(fs); } - using (FileStream fs = File.Create(OUTFLP)) + Console.WriteLine(); + Console.WriteLine("Successfully saved \"" + outMIDIPath + '\"'); + } + private static void Mode_FLPReport(ReadOnlySpan args) + { + string inFLPPath = args[0]; + + if (!File.Exists(inFLPPath)) { - var options = new FLPSaveOptions + Console.WriteLine("File not found: \"" + inFLPPath + '\"'); + return; + } + + string outTXTPath = args[1]; + + CreateOutputDir(outTXTPath); + + FLProjectReader flp; + using (FileStream fs = File.OpenRead(inFLPPath)) + { + flp = new FLProjectReader(fs); + } + + File.WriteAllText(outTXTPath, flp.Log.ToString()); + } + private static void Mode_MIDToFLP(ReadOnlySpan args) + { + string inMIDIPath = args[0]; + + if (!File.Exists(inMIDIPath)) + { + Console.WriteLine("File not found: \"" + inMIDIPath + '\"'); + return; + } + + string outFLPPath = args[1]; + var options = new FLPSaveOptions + { + DefaultMIDIVolume = 127, + }; + + try + { + for (int i = 2; i < args.Length;) { - DLSPath = dlsPath, - DefaultMIDIVolume = DEFAULT_MIDI_VOL, - }; + string extraArg = args[i++].ToLowerInvariant(); + switch (extraArg) + { + case "-defaultvol": + { + HandleDefaultVol(args[i++], ref options.DefaultMIDIVolume); + break; + } + case "-flversioncompat": + { + switch (args[i++].ToLowerInvariant()) + { + case "v20_9_2": + { + options.FLVersionCompat = FLVersionCompat.V20_9_2__B2963; + break; + } + case "v21_0_3": + { + options.FLVersionCompat = FLVersionCompat.V21_0_3__B3517; + break; + } + default: throw new Exception(); + } + break; + } + case "-dlspath": + { + options.DLSPath = args[i++]; + break; + } + case "-pitchbendrange": + { + options.PitchBendRange = int.Parse(args[i++]); + if (options.PitchBendRange is < 1 or > 48) + { + throw new Exception(); + } + break; + } + case "-automationtracksize": + { + options.AutomationTrackSize = float.Parse(args[i++]); + if (options.AutomationTrackSize is < FLPlaylistTrack.SIZE_MIN or > FLPlaylistTrack.SIZE_MAX) + { + throw new Exception(); + } + break; + } + case "-automationgrouping": + { + switch (args[i++].ToLowerInvariant()) + { + case "groupbychannel": + { + options.AutomationGrouping = FLPSaveOptions.AutomationGroupMode.GroupByChannel; + break; + } + case "groupall": + { + options.AutomationGrouping = FLPSaveOptions.AutomationGroupMode.GroupAll; + break; + } + default: throw new Exception(); + } + break; + } + case "-collapseautomationgroups": + { + options.CollapseAutomationGroups = bool.Parse(args[i++]); + break; + } + case "-appendinstrumentnamestopatterns": + { + options.AppendInstrumentNamesToPatterns = bool.Parse(args[i++]); + break; + } + case "-instrumenttrackcoloring": + { + switch (args[i++].ToLowerInvariant()) + { + case "random": + { + options.InstrumentTrackColoring = FLPSaveOptions.InstrumentTrackColorMode.Random; + break; + } + default: throw new Exception(); + } + break; + } + case "-automationtrackcoloring": + { + switch (args[i++].ToLowerInvariant()) + { + case "random": + { + options.AutomationTrackColoring = FLPSaveOptions.AutomationTrackColorMode.Random; + break; + } + case "instrumenttrack": + { + options.AutomationTrackColoring = FLPSaveOptions.AutomationTrackColorMode.InstrumentTrack; + break; + } + default: throw new Exception(); + } + break; + } + case "-midioutcoloring": + { + switch (args[i++].ToLowerInvariant()) + { + case "random": + { + options.MIDIOutColoring = FLPSaveOptions.MIDIOutColorMode.Random; + break; + } + case "instrumenttrack": + { + options.MIDIOutColoring = FLPSaveOptions.MIDIOutColorMode.InstrumentTrack; + break; + } + case "instrument": + { + options.MIDIOutColoring = FLPSaveOptions.MIDIOutColorMode.Instrument; + break; + } + default: throw new Exception(); + } + break; + } + case "-patterncoloring": + { + switch (args[i++].ToLowerInvariant()) + { + case "random": + { + options.PatternColoring = FLPSaveOptions.PatternColorMode.Random; + break; + } + case "instrumenttrack": + { + options.PatternColoring = FLPSaveOptions.PatternColorMode.InstrumentTrack; + break; + } + case "instrument": + { + options.PatternColoring = FLPSaveOptions.PatternColorMode.Instrument; + break; + } + default: throw new Exception(); + } + break; + } + case "-insertcoloring": + { + switch (args[i++].ToLowerInvariant()) + { + case "random": + { + options.InsertColoring = FLPSaveOptions.InsertColorMode.Random; + break; + } + case "instrumenttrack": + { + options.InsertColoring = FLPSaveOptions.InsertColorMode.InstrumentTrack; + break; + } + default: throw new Exception(); + } + break; + } + case "-automationcoloring": + { + switch (args[i++].ToLowerInvariant()) + { + case "random": + { + options.AutomationColoring = FLPSaveOptions.AutomationColorMode.Random; + break; + } + case "automationtrack": + { + options.AutomationColoring = FLPSaveOptions.AutomationColorMode.AutomationTrack; + break; + } + default: throw new Exception(); + } + break; + } + default: throw new Exception(); + } + } + } + catch + { + ShowUsage(); + return; + } + + CreateOutputDir(outFLPPath); + + MIDIFile inMIDI; + using (FileStream fs = File.OpenRead(inMIDIPath)) + { + inMIDI = new MIDIFile(fs); + } + + var splitter = new Splitter(inMIDI, options.DefaultMIDIVolume); + using (FileStream fs = File.Create(outFLPPath)) + { splitter.SaveFLP(fs, options); } Console.WriteLine(); - Console.WriteLine("Successfully saved \"" + outMIDIFile + '\"'); + Console.WriteLine("Successfully saved \"" + outFLPPath + '\"'); + } -#if DEBUG - Console.ReadKey(); -#endif + private static void HandleDefaultVol(string s, ref byte defaultVol) + { + defaultVol = byte.Parse(s); + if (defaultVol is < 1 or > 127) + { + throw new Exception(); + } + } + private static void CreateOutputDir(string outFile) + { + string test = Path.GetDirectoryName(outFile)!; + Console.WriteLine(test); + Directory.CreateDirectory(test); } - private static void Test_ReadFLP() + private static void ShowUsage() { - const string IN = @"C:\Users\Kermalis\Documents\Development\GitHub\MIDIProgramSplitter\TestIn.flp"; - //const string IN = @"C:\Users\Kermalis\Documents\Development\GitHub\MIDIProgramSplitter\TestOUT.flp"; - //const string IN = @"D:\Music\Projects\Remix\Vs Colress.flp"; + Console.WriteLine("######################### MIDI Program Splitter by Kermalis #########################"); + Console.WriteLine("Example usage:"); - using (FileStream fs = File.OpenRead(IN)) - { - var flp = new FLProjectReader(fs); + Console.WriteLine(" MIDIProgramSplitter.exe -MIDSplit \"InputMIDIPath.mid\" \"OutputFLPPath.flp\" -DefaultVol 100"); + Console.WriteLine(" Optional args:"); + Console.WriteLine(" -DefaultVol [0,127]"); + Console.WriteLine(" Default args:"); + Console.WriteLine(" DefaultVol = 127"); + Console.WriteLine(); -#if DEBUG && WINDOWS - WinUtils.Win_SetClipboardString(flp.Log.ToString()); -#endif - ; - } + Console.WriteLine(" MIDIProgramSplitter.exe -FLPReport \"InputFLPPath.flp\" \"OutputTXTPath.txt\""); + Console.WriteLine(); + + Console.WriteLine(" MIDIProgramSplitter.exe -MIDToFLP \"InputMIDIPath.mid\" \"OutputFLPPath.flp\" -DefaultVol 100 -FLVersionCompat V21_0_3 -DLSPath \"PathToDLS.dls\""); + Console.WriteLine(" Optional args:"); + Console.WriteLine(" -DefaultVol [0,127]"); + Console.WriteLine(" -FLVersionCompat {V20_9_2 or V21_0_3}"); + Console.WriteLine(" -DLSPath \"PathToDLS.dls\""); + Console.WriteLine(" -PitchBendRange [1,48]"); + Console.WriteLine(" -AutomationTrackSize [0.0,25.9249992370605]"); + Console.WriteLine(" -AutomationGrouping {GroupByChannel or GroupAll}"); + Console.WriteLine(" -CollapseAutomationGroups {False}"); + Console.WriteLine(" -AppendInstrumentNamesToPatterns {False}"); + Console.WriteLine(" -InstrumentTrackColoring {Random}"); + Console.WriteLine(" -AutomationTrackColoring {Random or InstrumentTrack}"); + Console.WriteLine(" -MIDIOutColoring {None or Random or InstrumentTrack}"); + Console.WriteLine(" -PatternColoring {None or Random or InstrumentTrack}"); + Console.WriteLine(" -InsertColoring {Random or InstrumentTrack}"); + Console.WriteLine(" -AutomationColoring {Random or AutomationTrack}"); + Console.WriteLine(" Default args:"); + Console.WriteLine(" DefaultVol = 127"); + Console.WriteLine(" FLVersionCompat = V20_9_2"); + Console.WriteLine(" PitchBendRange = 12"); + Console.WriteLine(" AutomationTrackSize = 0.0"); + + Console.WriteLine("######################### #########################"); } } \ No newline at end of file diff --git a/MIDIProgramSplitter.CMD/WinUtils.cs b/MIDIProgramSplitter.CMD/WinUtils.cs deleted file mode 100644 index d7994a0..0000000 --- a/MIDIProgramSplitter.CMD/WinUtils.cs +++ /dev/null @@ -1,40 +0,0 @@ -#if DEBUG && WINDOWS -using System; -using System.Runtime.InteropServices; -using System.Text; - -namespace MIDIProgramSplitter.CMD; - -internal static partial class WinUtils -{ - private const int CF_UNICODETEXT = 13; - - [LibraryImport("user32.dll")] - private static partial IntPtr SetClipboardData(uint uFormat, IntPtr hMem); - - [LibraryImport("user32.dll", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - private static partial bool OpenClipboard(IntPtr hWndNewOwner); - - [LibraryImport("user32.dll")] - [return: MarshalAs(UnmanagedType.Bool)] - private static partial bool EmptyClipboard(); - - [LibraryImport("user32.dll", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - private static partial bool CloseClipboard(); - - public static void Win_SetClipboardString(string s) - { - string nullTerminatedStr = s + '\0'; - byte[] strBytes = Encoding.Unicode.GetBytes(nullTerminatedStr); - IntPtr hglobal = Marshal.AllocHGlobal(strBytes.Length); - Marshal.Copy(strBytes, 0, hglobal, strBytes.Length); - OpenClipboard(IntPtr.Zero); - EmptyClipboard(); - SetClipboardData(CF_UNICODETEXT, hglobal); - CloseClipboard(); - Marshal.FreeHGlobal(hglobal); - } -} -#endif \ No newline at end of file diff --git a/MIDIProgramSplitter.sln b/MIDIProgramSplitter.sln index 4112f1c..893c608 100644 --- a/MIDIProgramSplitter.sln +++ b/MIDIProgramSplitter.sln @@ -9,28 +9,36 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MIDIProgramSplitter.CMD", " EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MIDIProgramSplitter.GUI", "MIDIProgramSplitter.GUI\MIDIProgramSplitter.GUI.csproj", "{756C2E7D-3912-44CE-9BDA-0A474927FF54}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FLP", "FLP\FLP.csproj", "{4745F7C7-78D8-42B1-9BFC-03945B6D8551}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FLP", "FLP\FLP.csproj", "{4745F7C7-78D8-42B1-9BFC-03945B6D8551}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU + Release_Win64|Any CPU = Release_Win64|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {52E19FF8-853A-496B-8D70-AE18DF1E7878}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {52E19FF8-853A-496B-8D70-AE18DF1E7878}.Debug|Any CPU.Build.0 = Debug|Any CPU + {52E19FF8-853A-496B-8D70-AE18DF1E7878}.Release_Win64|Any CPU.ActiveCfg = Release|Any CPU + {52E19FF8-853A-496B-8D70-AE18DF1E7878}.Release_Win64|Any CPU.Build.0 = Release|Any CPU {52E19FF8-853A-496B-8D70-AE18DF1E7878}.Release|Any CPU.ActiveCfg = Release|Any CPU {52E19FF8-853A-496B-8D70-AE18DF1E7878}.Release|Any CPU.Build.0 = Release|Any CPU {6A5278D8-78A1-42E5-892F-BC5A763F65C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6A5278D8-78A1-42E5-892F-BC5A763F65C9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6A5278D8-78A1-42E5-892F-BC5A763F65C9}.Release_Win64|Any CPU.ActiveCfg = Release_Win64|Any CPU + {6A5278D8-78A1-42E5-892F-BC5A763F65C9}.Release_Win64|Any CPU.Build.0 = Release_Win64|Any CPU {6A5278D8-78A1-42E5-892F-BC5A763F65C9}.Release|Any CPU.ActiveCfg = Release|Any CPU {6A5278D8-78A1-42E5-892F-BC5A763F65C9}.Release|Any CPU.Build.0 = Release|Any CPU {756C2E7D-3912-44CE-9BDA-0A474927FF54}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {756C2E7D-3912-44CE-9BDA-0A474927FF54}.Debug|Any CPU.Build.0 = Debug|Any CPU + {756C2E7D-3912-44CE-9BDA-0A474927FF54}.Release_Win64|Any CPU.ActiveCfg = Release|Any CPU {756C2E7D-3912-44CE-9BDA-0A474927FF54}.Release|Any CPU.ActiveCfg = Release|Any CPU {756C2E7D-3912-44CE-9BDA-0A474927FF54}.Release|Any CPU.Build.0 = Release|Any CPU {4745F7C7-78D8-42B1-9BFC-03945B6D8551}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4745F7C7-78D8-42B1-9BFC-03945B6D8551}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4745F7C7-78D8-42B1-9BFC-03945B6D8551}.Release_Win64|Any CPU.ActiveCfg = Release|Any CPU + {4745F7C7-78D8-42B1-9BFC-03945B6D8551}.Release_Win64|Any CPU.Build.0 = Release|Any CPU {4745F7C7-78D8-42B1-9BFC-03945B6D8551}.Release|Any CPU.ActiveCfg = Release|Any CPU {4745F7C7-78D8-42B1-9BFC-03945B6D8551}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection