using System; using System.IO; using System.Text; using System.Text.RegularExpressions; using System.Diagnostics; namespace CircuitBank2Patch { class Program { static void Main(string[] args) { string startPath =""; string startfolderPath = ""; string startfileName = ""; string startfileExtension = ""; Console.OutputEncoding = System.Text.Encoding.GetEncoding(28591); Console.Title = "Novation Circuit - Synth Bank Sysex Patch Dump"; string title = @" _________ .__ .__ __ \_ ___ \|__|______ ____ __ __|__|/ |_ / \ \/| \_ __ \_/ ___\| | \ \ __\ \ \___| || | \/\ \___| | / || | \______ /__||__| \___ >____/|__||__| \/ \/ -------------------------------------------- Novation Circuit Synth Bank SYSEX Patch Dump Utility v1.0 This program will dump all patches from a Cicruit Sysex (.syx) bank to a subdirectory named BankName_Extracted located wherever your bank file originates. .----------------------------------------------------------------------. | Notes: | | This for Novation Circuit >>SYNTH bank .syx files ONLY<<. | | The original bank file is NOT modified in any way. | | If your bank contains patches with duplicate names, the file names | | for those patches will have a number appended to the filename. | | If the destination directory already contains patches, any new files | | created will have a number appended to them. No files are deleted. | `-----------------------------------------------------------------------' Usage: Drag & Drop your Circuit Patch Bank .syx file onto this EXE. ---------------------------------------------------------------------- "; Console.WriteLine(title); Console.WriteLine("Press any key to continue or press ESC to abort"); ConsoleKeyInfo info = Console.ReadKey(); if (info.Key == ConsoleKey.Escape) { Console.WriteLine("ESC pressed. Program Aborted, nothing will be processed."); System.Threading.Thread.Sleep(5000); System.Environment.Exit(0); } if (args.Length > 0 && File.Exists(args[0])) { startPath = args[0]; startfolderPath = Path.GetDirectoryName(startPath); startfileName = Path.GetFileNameWithoutExtension(startPath); startfileExtension = Path.GetExtension(startPath); //Console.WriteLine("{0}, {1}, {2}, {3}", startfileName, startPath, startfileExtension, startfolderPath); Console.WriteLine("\n" + " Bank name: {0}\n" + " Bank Directory: {1}\n" + " Patches Destination Directory: {2}\n\n", startfileName, startfolderPath, startfolderPath + @"\" + startfileName + @"_Extracted\", "-------------------------------------"); System.Threading.Thread.Sleep(5000); } if (args.Length <= 0) { Console.WriteLine("\nNo file detected: To use this program, Drag and Drop your Bank directly onto the exe. \n\n Exiting..."); System.Threading.Thread.Sleep(5000); System.Environment.Exit(0); } string filePath = startfolderPath; string outputPath = filePath + @"\" + startfileName + @"_Extracted\"; System.IO.Directory.CreateDirectory(outputPath); FileStream filename; filename = new FileStream(startPath, FileMode.Open); var buffer = new byte[350]; //int bytesRead = 0; //replaced by _ discard int filecount = 0; int initialpatch = 0; int renamecount = 1; while ((_ = filename.Read(buffer, 0, buffer.Length)) > 0) { filecount++; FileStream singlePatch; singlePatch = new FileStream(outputPath + @"patch" + filecount + ".syx", FileMode.Append); singlePatch.Write(buffer, 0, buffer.Length); singlePatch.Close(); } while (filecount > 0) //fix bytes for compatibility { FileStream renamePatch; string fileforRename = outputPath + @"patch" + renamecount + ".syx"; renamePatch = new FileStream(fileforRename, FileMode.Open, FileAccess.ReadWrite); renamePatch.Seek(0x07, SeekOrigin.Begin); //replace by 0x07 with value 0x00 for librarian compatibility ..in bank it increase by patch # renamePatch.WriteByte(0x00); renamePatch.Seek(0x06, SeekOrigin.Begin); //replace by 0x06 with value 0x00 for librarian compatibility ..in bank it increase by patch # renamePatch.WriteByte(0x00); renamePatch.Seek(0x09, SeekOrigin.Begin); //start byte location of patch name var data = new byte[16]; //patch name can be up to 16 chars long renamePatch.Read(data, 0, 16); //read all 16 bytes as new byte[] string convertbytes = Encoding.UTF8.GetString(data, 0, data.Length).Trim(); //convert byte[] (data) containing patch name to string string converted = convertbytes.Replace(" ", "_"); //replace whitespace with underscore for potential program, path, compatibility import issues if (converted.Contains("Initial_Patch")) { converted += "_" + initialpatch; initialpatch++; } //handle initial patches seperately //Console.WriteLine("{0}", converted.Trim()); renamePatch.Close(); //HAVE PATCH NAME NOW CHECK FOR FILE AND RENAME/MOVE TO PATCHNAME.SYX //HANDLE OUTPUT HERE //Console.WriteLine("{0}", GetUniqueFilePath(fullfilePath)); string fullfilePath = outputPath + converted.Trim() + ".syx"; string uniquePath = GetUniqueFilePath(fullfilePath); File.Move(fileforRename, uniquePath); //output file with dupecheck and rename string outFile = Path.GetFileNameWithoutExtension(uniquePath); if (outFile.Contains(@"(")) { outFile = outFile + " - Possible Dupilcate"; } Console.WriteLine(" Written: {0}", @".\" + startfileName + @"_Extracted\" + outFile ); System.Threading.Thread.Sleep(50); renamecount++; filecount--; } filename.Close(); Console.WriteLine("Dump completed. Press SPACE to open folder or any other key to Exit."); ConsoleKeyInfo info2 = Console.ReadKey(); if (info2.Key == ConsoleKey.Spacebar) { Process.Start("explorer.exe", outputPath); System.Environment.Exit(0); } } public static string GetUniqueFilePath(string filePath) { if (File.Exists(filePath)) { string folderPath = Path.GetDirectoryName(filePath); string fileName = Path.GetFileNameWithoutExtension(filePath); string fileExtension = Path.GetExtension(filePath); int number = 1; Match regex = Regex.Match(fileName, @"^(.+) \((\d+)\)$"); if (regex.Success) { fileName = regex.Groups[1].Value; number = int.Parse(regex.Groups[2].Value); } do { number++; string newFileName = $"{fileName} ({number}){fileExtension}"; filePath = Path.Combine(folderPath, newFileName); } while (File.Exists(filePath)); } return filePath; } } }