├── .gitattributes ├── .gitignore ├── FM-SoundConvertor.sln ├── FM-SoundConvertor ├── App.config ├── Console.cs ├── Dat.cs ├── Directory.cs ├── FM-SoundConvertor.csproj ├── FMtrial.cs ├── File.cs ├── Fmp.cs ├── Main.cs ├── Muc.cs ├── Option.cs ├── Path.cs ├── Pmd.cs ├── Properties │ └── AssemblyInfo.cs ├── Tone.cs ├── VOPM.cs └── bin │ └── Release │ └── FM-SoundConvertor.exe ├── LICENSE └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | .vs/FM-SoundConvertor/v16/.suo 3 | FM-SoundConvertor/bin/Debug/FM-SoundConvertor.exe 4 | FM-SoundConvertor/bin/Debug/FM-SoundConvertor.exe.config 5 | FM-SoundConvertor/bin/Debug/FM-SoundConvertor.pdb 6 | FM-SoundConvertor/bin/Release/FM-SoundConvertor.exe.config 7 | FM-SoundConvertor/bin/Release/FM-SoundConvertor.pdb 8 | FM-SoundConvertor/obj/Debug/FM-SoundConvertor.csproj.CoreCompileInputs.cache 9 | FM-SoundConvertor/obj/Debug/FM-SoundConvertor.csproj.FileListAbsolute.txt 10 | FM-SoundConvertor/obj/Debug/FM-SoundConvertor.csprojAssemblyReference.cache 11 | FM-SoundConvertor/obj/Debug/FM-SoundConvertor.exe 12 | FM-SoundConvertor/obj/Debug/FM-SoundConvertor.pdb 13 | FM-SoundConvertor/obj/Release/FM-SoundConvertor.csproj.CoreCompileInputs.cache 14 | FM-SoundConvertor/obj/Release/FM-SoundConvertor.csproj.FileListAbsolute.txt 15 | FM-SoundConvertor/obj/Release/FM-SoundConvertor.exe 16 | FM-SoundConvertor/obj/Release/FM-SoundConvertor.pdb 17 | FM-SoundConvertor/obj/Release/FM-SoundConvertor.csprojAssemblyReference.cache 18 | FM-SoundConvertor/obj/Release/DesignTimeResolveAssemblyReferencesInput.cache 19 | -------------------------------------------------------------------------------- /FM-SoundConvertor.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29905.134 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FM-SoundConvertor", "FM-SoundConvertor\FM-SoundConvertor.csproj", "{A3DA1746-8229-471A-8029-3322CCFB15AB}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {A3DA1746-8229-471A-8029-3322CCFB15AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {A3DA1746-8229-471A-8029-3322CCFB15AB}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {A3DA1746-8229-471A-8029-3322CCFB15AB}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {A3DA1746-8229-471A-8029-3322CCFB15AB}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {8AE8F879-C449-4863-9888-D78245A3EED5} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /FM-SoundConvertor/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /FM-SoundConvertor/Console.cs: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | using System.Linq; 5 | using System.Collections.Generic; 6 | 7 | using static System.Console; 8 | 9 | 10 | 11 | namespace FM_SoundConvertor 12 | { 13 | public class Console 14 | { 15 | public static void Log(int Val) 16 | { 17 | WriteLine("{0}", Val.ToString()); 18 | } 19 | 20 | 21 | 22 | public static void Log(string Str) 23 | { 24 | WriteLine("{0}", Str); 25 | } 26 | 27 | 28 | 29 | public static void Log(string Pref, string Str) 30 | { 31 | WriteLine("{0} : {1}", Pref, Str); 32 | } 33 | 34 | 35 | 36 | public static void Log(IEnumerable aStr) 37 | { 38 | aStr.ToList().ForEach(Str => Log(Str)); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /FM-SoundConvertor/Dat.cs: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | using System; 5 | 6 | using static FM_SoundConvertor.Path; 7 | using static FM_SoundConvertor.File; 8 | using static FM_SoundConvertor.Console; 9 | 10 | 11 | 12 | namespace FM_SoundConvertor 13 | { 14 | class Dat 15 | { 16 | enum ePut 17 | { 18 | Void, 19 | DTML0, DTML2, DTML1, DTML3, 20 | TL0, TL2, TL1, TL3, 21 | KSAR0, KSAR2, KSAR1, KSAR3, 22 | DR0, DR2, DR1, DR3, 23 | SR0, SR2, SR1, SR3, 24 | SLRR0, SLRR2, SLRR1, SLRR3, 25 | FBAL, 26 | Name0, Name1, Name2, Name3, Name4, Name5, 27 | } 28 | 29 | 30 | 31 | static int ToneLength() 32 | { 33 | return 0x100; 34 | } 35 | 36 | static int PutLength() 37 | { 38 | return System.Enum.GetNames(typeof(ePut)).Length; 39 | } 40 | 41 | static int DatLength() 42 | { 43 | return ToneLength() * PutLength(); 44 | } 45 | 46 | 47 | 48 | public static byte[] New() 49 | { 50 | return new byte[DatLength()]; 51 | } 52 | 53 | 54 | 55 | static void Get(ref Tone @Tone, byte[] Buffer, int i) 56 | { 57 | var o = i * PutLength(); 58 | Tone.aOp[0].AR = Buffer[o + (int)ePut.KSAR0] & 0x1f; 59 | Tone.aOp[1].AR = Buffer[o + (int)ePut.KSAR1] & 0x1f; 60 | Tone.aOp[2].AR = Buffer[o + (int)ePut.KSAR2] & 0x1f; 61 | Tone.aOp[3].AR = Buffer[o + (int)ePut.KSAR3] & 0x1f; 62 | Tone.aOp[0].DR = Buffer[o + (int)ePut.DR0]; 63 | Tone.aOp[1].DR = Buffer[o + (int)ePut.DR1]; 64 | Tone.aOp[2].DR = Buffer[o + (int)ePut.DR2]; 65 | Tone.aOp[3].DR = Buffer[o + (int)ePut.DR3]; 66 | Tone.aOp[0].SR = Buffer[o + (int)ePut.SR0]; 67 | Tone.aOp[1].SR = Buffer[o + (int)ePut.SR1]; 68 | Tone.aOp[2].SR = Buffer[o + (int)ePut.SR2]; 69 | Tone.aOp[3].SR = Buffer[o + (int)ePut.SR3]; 70 | Tone.aOp[0].RR = Buffer[o + (int)ePut.SLRR0] & 0xf; 71 | Tone.aOp[1].RR = Buffer[o + (int)ePut.SLRR1] & 0xf; 72 | Tone.aOp[2].RR = Buffer[o + (int)ePut.SLRR2] & 0xf; 73 | Tone.aOp[3].RR = Buffer[o + (int)ePut.SLRR3] & 0xf; 74 | Tone.aOp[0].SL = Buffer[o + (int)ePut.SLRR0] >> 4; 75 | Tone.aOp[1].SL = Buffer[o + (int)ePut.SLRR1] >> 4; 76 | Tone.aOp[2].SL = Buffer[o + (int)ePut.SLRR2] >> 4; 77 | Tone.aOp[3].SL = Buffer[o + (int)ePut.SLRR3] >> 4; 78 | Tone.aOp[0].TL = Buffer[o + (int)ePut.TL0]; 79 | Tone.aOp[1].TL = Buffer[o + (int)ePut.TL1]; 80 | Tone.aOp[2].TL = Buffer[o + (int)ePut.TL2]; 81 | Tone.aOp[3].TL = Buffer[o + (int)ePut.TL3]; 82 | Tone.aOp[0].KS = Buffer[o + (int)ePut.KSAR0] >> 6; 83 | Tone.aOp[1].KS = Buffer[o + (int)ePut.KSAR1] >> 6; 84 | Tone.aOp[2].KS = Buffer[o + (int)ePut.KSAR2] >> 6; 85 | Tone.aOp[3].KS = Buffer[o + (int)ePut.KSAR3] >> 6; 86 | Tone.aOp[0].ML = Buffer[o + (int)ePut.DTML0] & 0xf; 87 | Tone.aOp[1].ML = Buffer[o + (int)ePut.DTML1] & 0xf; 88 | Tone.aOp[2].ML = Buffer[o + (int)ePut.DTML2] & 0xf; 89 | Tone.aOp[3].ML = Buffer[o + (int)ePut.DTML3] & 0xf; 90 | Tone.aOp[0].DT = Buffer[o + (int)ePut.DTML0] >> 4; 91 | Tone.aOp[1].DT = Buffer[o + (int)ePut.DTML1] >> 4; 92 | Tone.aOp[2].DT = Buffer[o + (int)ePut.DTML2] >> 4; 93 | Tone.aOp[3].DT = Buffer[o + (int)ePut.DTML3] >> 4; 94 | Tone.aOp[0].DT2 = 0; 95 | Tone.aOp[1].DT2 = 0; 96 | Tone.aOp[2].DT2 = 0; 97 | Tone.aOp[3].DT2 = 0; 98 | Tone.aOp[0].AM = 0; 99 | Tone.aOp[1].AM = 0; 100 | Tone.aOp[2].AM = 0; 101 | Tone.aOp[3].AM = 0; 102 | Tone.AL = Buffer[o + (int)ePut.FBAL] & 0x7; 103 | Tone.FB = Buffer[o + (int)ePut.FBAL] >> 3; 104 | 105 | var aChar = new char[] 106 | { 107 | (char)Buffer[o + (int)ePut.Name0], 108 | (char)Buffer[o + (int)ePut.Name1], 109 | (char)Buffer[o + (int)ePut.Name2], 110 | (char)Buffer[o + (int)ePut.Name3], 111 | (char)Buffer[o + (int)ePut.Name4], 112 | (char)Buffer[o + (int)ePut.Name5], 113 | }; 114 | Tone.Name = ""; 115 | foreach (var Char in aChar) if (Char != 0) Tone.Name += Char.ToString(); 116 | 117 | Tone.Number = i; 118 | } 119 | 120 | 121 | 122 | public static void Put(Tone @Tone, ref byte[] Buffer) 123 | { 124 | if (Tone.IsValid()) 125 | { 126 | int o = Tone.Number * PutLength(); 127 | Buffer[o + (int)ePut.Void] = 0; 128 | Buffer[o + (int)ePut.DTML0] = (byte)((Tone.aOp[0].DT << 4) | Tone.aOp[0].ML); 129 | Buffer[o + (int)ePut.DTML1] = (byte)((Tone.aOp[1].DT << 4) | Tone.aOp[1].ML); 130 | Buffer[o + (int)ePut.DTML2] = (byte)((Tone.aOp[2].DT << 4) | Tone.aOp[2].ML); 131 | Buffer[o + (int)ePut.DTML3] = (byte)((Tone.aOp[3].DT << 4) | Tone.aOp[3].ML); 132 | Buffer[o + (int)ePut.TL0] = (byte)Tone.aOp[0].TL; 133 | Buffer[o + (int)ePut.TL1] = (byte)Tone.aOp[1].TL; 134 | Buffer[o + (int)ePut.TL2] = (byte)Tone.aOp[2].TL; 135 | Buffer[o + (int)ePut.TL3] = (byte)Tone.aOp[3].TL; 136 | Buffer[o + (int)ePut.KSAR0] = (byte)((Tone.aOp[0].KS << 6) | Tone.aOp[0].AR); 137 | Buffer[o + (int)ePut.KSAR1] = (byte)((Tone.aOp[1].KS << 6) | Tone.aOp[1].AR); 138 | Buffer[o + (int)ePut.KSAR2] = (byte)((Tone.aOp[2].KS << 6) | Tone.aOp[2].AR); 139 | Buffer[o + (int)ePut.KSAR3] = (byte)((Tone.aOp[3].KS << 6) | Tone.aOp[3].AR); 140 | Buffer[o + (int)ePut.DR0] = (byte)Tone.aOp[0].DR; 141 | Buffer[o + (int)ePut.DR1] = (byte)Tone.aOp[1].DR; 142 | Buffer[o + (int)ePut.DR2] = (byte)Tone.aOp[2].DR; 143 | Buffer[o + (int)ePut.DR3] = (byte)Tone.aOp[3].DR; 144 | Buffer[o + (int)ePut.SR0] = (byte)Tone.aOp[0].SR; 145 | Buffer[o + (int)ePut.SR1] = (byte)Tone.aOp[1].SR; 146 | Buffer[o + (int)ePut.SR2] = (byte)Tone.aOp[2].SR; 147 | Buffer[o + (int)ePut.SR3] = (byte)Tone.aOp[3].SR; 148 | Buffer[o + (int)ePut.SLRR0] = (byte)((Tone.aOp[0].SL << 4) | Tone.aOp[0].RR); 149 | Buffer[o + (int)ePut.SLRR1] = (byte)((Tone.aOp[1].SL << 4) | Tone.aOp[1].RR); 150 | Buffer[o + (int)ePut.SLRR2] = (byte)((Tone.aOp[2].SL << 4) | Tone.aOp[2].RR); 151 | Buffer[o + (int)ePut.SLRR3] = (byte)((Tone.aOp[3].SL << 4) | Tone.aOp[3].RR); 152 | Buffer[o + (int)ePut.FBAL] = (byte)((Tone.FB << 3) | Tone.AL); 153 | Buffer[o + (int)ePut.Name0] = (byte)((Tone.Name.Length > 0) ? Tone.Name[0] : 0); 154 | Buffer[o + (int)ePut.Name1] = (byte)((Tone.Name.Length > 1) ? Tone.Name[1] : 0); 155 | Buffer[o + (int)ePut.Name2] = (byte)((Tone.Name.Length > 2) ? Tone.Name[2] : 0); 156 | Buffer[o + (int)ePut.Name3] = (byte)((Tone.Name.Length > 3) ? Tone.Name[3] : 0); 157 | Buffer[o + (int)ePut.Name4] = (byte)((Tone.Name.Length > 4) ? Tone.Name[4] : 0); 158 | Buffer[o + (int)ePut.Name5] = (byte)((Tone.Name.Length > 5) ? Tone.Name[5] : 0); 159 | } 160 | } 161 | 162 | 163 | 164 | public static void Reader(string Path, Option @Option) 165 | { 166 | var Buffer = ReadByte(Path); 167 | if (Buffer.Length == DatLength()) 168 | { 169 | Tone vTone = new Tone(); 170 | 171 | var BufferMuc = ""; 172 | var BufferFmp = ""; 173 | var BufferPmd = ""; 174 | var BufferVopm = Vopm.New(); 175 | var BufferFMtrial = FMtrial.New(); 176 | 177 | for (int i = 0; i < ToneLength(); ++i) 178 | { 179 | Get(ref vTone, Buffer, i); 180 | 181 | if (Option.bMuc) Muc.Put(vTone, ref BufferMuc); 182 | if (Option.bFmp) Fmp.Put(vTone, ref BufferFmp); 183 | if (Option.bPmd) Pmd.Put(vTone, ref BufferPmd); 184 | if (Option.bVopm) Vopm.Put(vTone, ref BufferVopm); 185 | if (Option.bFMtrial) FMtrial.Put(vTone, ref BufferFMtrial); 186 | } 187 | 188 | if (Option.bMuc) Muc.Writer(Path, BufferMuc); 189 | if (Option.bFmp) Fmp.Writer(Path, BufferFmp); 190 | if (Option.bPmd) Pmd.Writer(Path, BufferPmd); 191 | if (Option.bVopm) Vopm.Writer(Path, BufferVopm); 192 | if (Option.bFMtrial) FMtrial.Writer(Path, BufferFMtrial); 193 | } 194 | } 195 | 196 | 197 | 198 | public static void Reader(string[] aPath, Option @Option) 199 | { 200 | foreach (var Path in aPath) 201 | { 202 | if (!String.IsNullOrWhiteSpace(Path) && Extension(Path) == ".dat") Reader(Path, Option); 203 | } 204 | } 205 | 206 | 207 | 208 | public static void Writer(string Path, byte[] Buffer) 209 | { 210 | WriteByte(ChangeExtension(Path, ".dat"), Buffer); 211 | } 212 | } 213 | } 214 | -------------------------------------------------------------------------------- /FM-SoundConvertor/Directory.cs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | using System; 5 | using System.Linq; 6 | using System.Collections.Generic; 7 | 8 | using static FM_SoundConvertor.Path; 9 | 10 | 11 | 12 | namespace FM_SoundConvertor { 13 | public class Directory { 14 | public static string[] Enum(string Path){ 15 | Path = UnCloak(Path); 16 | if (System.IO.Directory.Exists(Path)){ 17 | return System.IO.Directory.EnumerateDirectories(Path, "*", System.IO.SearchOption.AllDirectories) 18 | .Select(Entry => Entry.Replace('\\','/')) 19 | .Where(Entry => (Entry.IndexOf("/.") == -1)) 20 | .OrderBy(Entry => Entry) 21 | .ToArray(); 22 | } 23 | return System.Array.Empty(); 24 | } 25 | 26 | 27 | 28 | public static string[] Enum(string[] aPath){ 29 | var aEnum = new List(); 30 | Array.ForEach(aPath, Path => aEnum.AddRange(Enum(Path))); 31 | return aEnum.ToArray(); 32 | } 33 | 34 | 35 | 36 | public static bool Exist(string Path){ 37 | Path = UnCloak(Path); 38 | return System.IO.Directory.Exists(Path); 39 | } 40 | 41 | 42 | 43 | public static void Delete(string Path){ 44 | try { 45 | Path = UnCloak(Path); 46 | System.IO.Directory.Delete(Path, true); 47 | } 48 | catch (System.IO.DirectoryNotFoundException){} 49 | } 50 | 51 | 52 | 53 | public static System.DateTime Date(string Path){ 54 | Path = UnCloak(Path); 55 | if (Exist(Path)) return System.IO.Directory.GetLastWriteTime(Path); 56 | return new System.DateTime(0); 57 | } 58 | 59 | 60 | 61 | public static System.DateTime Newer(IEnumerable aPath){ 62 | var aDate = aPath.Select(Path => Date(Path)); 63 | return new System.DateTime(aDate.Max().Ticks); 64 | } 65 | 66 | 67 | 68 | public static string Parent(string Path){ 69 | Path = UnCloak(Path); 70 | return System.IO.Directory.GetParent(Path).FullName; 71 | } 72 | 73 | 74 | 75 | public static void Create(string Path){ 76 | Path = UnCloak(Path); 77 | System.IO.Directory.CreateDirectory(Path); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /FM-SoundConvertor/FM-SoundConvertor.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {A3DA1746-8229-471A-8029-3322CCFB15AB} 8 | Exe 9 | FM_SoundConvertor 10 | FM-SoundConvertor 11 | v4.7.2 12 | 512 13 | true 14 | true 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | AnyCPU 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /FM-SoundConvertor/FMtrial.cs: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | using System; 5 | 6 | using static FM_SoundConvertor.Path; 7 | using static FM_SoundConvertor.File; 8 | using static FM_SoundConvertor.Console; 9 | 10 | 11 | 12 | namespace FM_SoundConvertor 13 | { 14 | class FMtrial 15 | { 16 | enum eName 17 | { 18 | Name0, Name1, Name2, Name3, Name4, Name5, Name6, Name7, Name8, Name9, Name10, Name11, Name12, Name13, Name14, Name15, 19 | Name16, Name17, Name18, Name19, Name20, _0, _1, _2, 20 | } 21 | 22 | enum ePut 23 | { 24 | _0, 25 | AL, FB, 26 | _1, _2, _3, _4, _5, _6, _7, _8, _9, 27 | AR0, DR0, SR0, RR0, SL0, TL0, KS0, ML0, DT1_0, DT2_0, WF0, 28 | AR1, DR1, SR1, RR1, SL1, TL1, KS1, ML1, DT1_1, DT2_1, WF1, 29 | AR2, DR2, SR2, RR2, SL2, TL2, KS2, ML2, DT1_2, DT2_2, WF2, 30 | AR3, DR3, SR3, RR3, SL3, TL3, KS3, ML3, DT1_3, DT2_3, WF3, 31 | _10, _11, MX, _13, _14, _15, _16, _17, _18, _19, 32 | _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, 33 | _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, 34 | _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, 35 | OS, PB, 36 | } 37 | 38 | 39 | 40 | 41 | static int ToneLength() 42 | { 43 | return 0x124; 44 | } 45 | 46 | static int HeadLength() 47 | { 48 | return 0xa0; 49 | } 50 | 51 | static int NameLength() 52 | { 53 | return System.Enum.GetNames(typeof(eName)).Length; 54 | } 55 | 56 | static int PutLength() 57 | { 58 | return NameLength() + (System.Enum.GetNames(typeof(ePut)).Length * sizeof(float)); 59 | } 60 | 61 | static int FxbLength() 62 | { 63 | return HeadLength() + (ToneLength() * PutLength()); 64 | } 65 | 66 | 67 | 68 | public static byte[] New() 69 | { 70 | return new byte[FxbLength()]; 71 | } 72 | 73 | 74 | 75 | static int Get(byte[] Buffer, int O, int e, int Max) 76 | { 77 | return (int)Math.Round(BitConverter.ToSingle(Buffer, O + (e * sizeof(float))) * Max); 78 | } 79 | 80 | 81 | 82 | static void Get(ref Tone @Tone, byte[] Buffer, int i) 83 | { 84 | int o = HeadLength() + (i * PutLength()); 85 | int O = o + NameLength(); 86 | Tone.aOp[0].AR = Get(Buffer, O, (int)ePut.AR0, 31); 87 | Tone.aOp[1].AR = Get(Buffer, O, (int)ePut.AR1, 31); 88 | Tone.aOp[2].AR = Get(Buffer, O, (int)ePut.AR2, 31); 89 | Tone.aOp[3].AR = Get(Buffer, O, (int)ePut.AR3, 31); 90 | Tone.aOp[0].DR = Get(Buffer, O, (int)ePut.DR0, 31); 91 | Tone.aOp[1].DR = Get(Buffer, O, (int)ePut.DR1, 31); 92 | Tone.aOp[2].DR = Get(Buffer, O, (int)ePut.DR2, 31); 93 | Tone.aOp[3].DR = Get(Buffer, O, (int)ePut.DR3, 31); 94 | Tone.aOp[0].SR = Get(Buffer, O, (int)ePut.SR0, 31); 95 | Tone.aOp[1].SR = Get(Buffer, O, (int)ePut.SR1, 31); 96 | Tone.aOp[2].SR = Get(Buffer, O, (int)ePut.SR2, 31); 97 | Tone.aOp[3].SR = Get(Buffer, O, (int)ePut.SR3, 31); 98 | Tone.aOp[0].RR = Get(Buffer, O, (int)ePut.RR0, 15); 99 | Tone.aOp[1].RR = Get(Buffer, O, (int)ePut.RR1, 15); 100 | Tone.aOp[2].RR = Get(Buffer, O, (int)ePut.RR2, 15); 101 | Tone.aOp[3].RR = Get(Buffer, O, (int)ePut.RR3, 15); 102 | Tone.aOp[0].SL = Get(Buffer, O, (int)ePut.SL0, 15); 103 | Tone.aOp[1].SL = Get(Buffer, O, (int)ePut.SL1, 15); 104 | Tone.aOp[2].SL = Get(Buffer, O, (int)ePut.SL2, 15); 105 | Tone.aOp[3].SL = Get(Buffer, O, (int)ePut.SL3, 15); 106 | Tone.aOp[0].TL = Get(Buffer, O, (int)ePut.TL0, 127); 107 | Tone.aOp[1].TL = Get(Buffer, O, (int)ePut.TL1, 127); 108 | Tone.aOp[2].TL = Get(Buffer, O, (int)ePut.TL2, 127); 109 | Tone.aOp[3].TL = Get(Buffer, O, (int)ePut.TL3, 127); 110 | Tone.aOp[0].KS = Get(Buffer, O, (int)ePut.KS0, 3); 111 | Tone.aOp[1].KS = Get(Buffer, O, (int)ePut.KS1, 3); 112 | Tone.aOp[2].KS = Get(Buffer, O, (int)ePut.KS2, 3); 113 | Tone.aOp[3].KS = Get(Buffer, O, (int)ePut.KS3, 3); 114 | Tone.aOp[0].ML = Get(Buffer, O, (int)ePut.ML0, 15); 115 | Tone.aOp[1].ML = Get(Buffer, O, (int)ePut.ML1, 15); 116 | Tone.aOp[2].ML = Get(Buffer, O, (int)ePut.ML2, 15); 117 | Tone.aOp[3].ML = Get(Buffer, O, (int)ePut.ML3, 15); 118 | Tone.aOp[0].DT = Get(Buffer, O, (int)ePut.DT1_0, 99); 119 | Tone.aOp[1].DT = Get(Buffer, O, (int)ePut.DT1_1, 99); 120 | Tone.aOp[2].DT = Get(Buffer, O, (int)ePut.DT1_2, 99); 121 | Tone.aOp[3].DT = Get(Buffer, O, (int)ePut.DT1_3, 99); 122 | Tone.aOp[0].DT2 = Get(Buffer, O, (int)ePut.DT2_0, 3); 123 | Tone.aOp[1].DT2 = Get(Buffer, O, (int)ePut.DT2_1, 3); 124 | Tone.aOp[2].DT2 = Get(Buffer, O, (int)ePut.DT2_2, 3); 125 | Tone.aOp[3].DT2 = Get(Buffer, O, (int)ePut.DT2_3, 3); 126 | Tone.AL = Get(Buffer, O, (int)ePut.AL, 7); 127 | Tone.FB = Get(Buffer, O, (int)ePut.FB, 7); 128 | 129 | var aChar = new char[] 130 | { 131 | (char)Buffer[o + (int)eName.Name0], 132 | (char)Buffer[o + (int)eName.Name1], 133 | (char)Buffer[o + (int)eName.Name2], 134 | (char)Buffer[o + (int)eName.Name3], 135 | (char)Buffer[o + (int)eName.Name4], 136 | (char)Buffer[o + (int)eName.Name5], 137 | (char)Buffer[o + (int)eName.Name6], 138 | (char)Buffer[o + (int)eName.Name7], 139 | (char)Buffer[o + (int)eName.Name8], 140 | (char)Buffer[o + (int)eName.Name9], 141 | (char)Buffer[o + (int)eName.Name10], 142 | (char)Buffer[o + (int)eName.Name11], 143 | (char)Buffer[o + (int)eName.Name12], 144 | (char)Buffer[o + (int)eName.Name13], 145 | (char)Buffer[o + (int)eName.Name14], 146 | (char)Buffer[o + (int)eName.Name15], 147 | (char)Buffer[o + (int)eName.Name16], 148 | (char)Buffer[o + (int)eName.Name17], 149 | (char)Buffer[o + (int)eName.Name18], 150 | (char)Buffer[o + (int)eName.Name19], 151 | (char)Buffer[o + (int)eName.Name20], 152 | }; 153 | Tone.Name = ""; 154 | foreach (var Char in aChar) if (Char != 0) Tone.Name += Char.ToString(); 155 | 156 | Tone.Number = i; 157 | } 158 | 159 | 160 | 161 | static void Put(byte[] Buffer, int O, int e, int Max, int v) 162 | { 163 | var aPut = BitConverter.GetBytes((float)v / (float)Max); 164 | Array.Copy(aPut, 0, Buffer, O + (e * sizeof(float)), aPut.Length); 165 | } 166 | 167 | 168 | 169 | public static void Put(Tone @Tone, ref byte[] Buffer) 170 | { 171 | if (Tone.IsValid() && Tone.Number < ToneLength()) 172 | { 173 | int o = HeadLength() + (Tone.Number * PutLength()); 174 | int O = o + NameLength(); 175 | Put(Buffer, O, (int)ePut.AR0, 31, Tone.aOp[0].AR); 176 | Put(Buffer, O, (int)ePut.AR1, 31, Tone.aOp[1].AR); 177 | Put(Buffer, O, (int)ePut.AR2, 31, Tone.aOp[2].AR); 178 | Put(Buffer, O, (int)ePut.AR3, 31, Tone.aOp[3].AR); 179 | Put(Buffer, O, (int)ePut.DR0, 31, Tone.aOp[0].DR); 180 | Put(Buffer, O, (int)ePut.DR1, 31, Tone.aOp[1].DR); 181 | Put(Buffer, O, (int)ePut.DR2, 31, Tone.aOp[2].DR); 182 | Put(Buffer, O, (int)ePut.DR3, 31, Tone.aOp[3].DR); 183 | Put(Buffer, O, (int)ePut.SR0, 31, Tone.aOp[0].SR); 184 | Put(Buffer, O, (int)ePut.SR1, 31, Tone.aOp[1].SR); 185 | Put(Buffer, O, (int)ePut.SR2, 31, Tone.aOp[2].SR); 186 | Put(Buffer, O, (int)ePut.SR3, 31, Tone.aOp[3].SR); 187 | Put(Buffer, O, (int)ePut.RR0, 15, Tone.aOp[0].RR); 188 | Put(Buffer, O, (int)ePut.RR1, 15, Tone.aOp[1].RR); 189 | Put(Buffer, O, (int)ePut.RR2, 15, Tone.aOp[2].RR); 190 | Put(Buffer, O, (int)ePut.RR3, 15, Tone.aOp[3].RR); 191 | Put(Buffer, O, (int)ePut.SL0, 15, Tone.aOp[0].SL); 192 | Put(Buffer, O, (int)ePut.SL1, 15, Tone.aOp[1].SL); 193 | Put(Buffer, O, (int)ePut.SL2, 15, Tone.aOp[2].SL); 194 | Put(Buffer, O, (int)ePut.SL3, 15, Tone.aOp[3].SL); 195 | Put(Buffer, O, (int)ePut.TL0, 127, Tone.aOp[0].TL); 196 | Put(Buffer, O, (int)ePut.TL1, 127, Tone.aOp[1].TL); 197 | Put(Buffer, O, (int)ePut.TL2, 127, Tone.aOp[2].TL); 198 | Put(Buffer, O, (int)ePut.TL3, 127, Tone.aOp[3].TL); 199 | Put(Buffer, O, (int)ePut.KS0, 3, Tone.aOp[0].KS); 200 | Put(Buffer, O, (int)ePut.KS1, 3, Tone.aOp[1].KS); 201 | Put(Buffer, O, (int)ePut.KS2, 3, Tone.aOp[2].KS); 202 | Put(Buffer, O, (int)ePut.KS3, 3, Tone.aOp[3].KS); 203 | Put(Buffer, O, (int)ePut.ML0, 15, Tone.aOp[0].ML); 204 | Put(Buffer, O, (int)ePut.ML1, 15, Tone.aOp[1].ML); 205 | Put(Buffer, O, (int)ePut.ML2, 15, Tone.aOp[2].ML); 206 | Put(Buffer, O, (int)ePut.ML3, 15, Tone.aOp[3].ML); 207 | Put(Buffer, O, (int)ePut.DT1_0, 99, Tone.aOp[0].DT); 208 | Put(Buffer, O, (int)ePut.DT1_1, 99, Tone.aOp[1].DT); 209 | Put(Buffer, O, (int)ePut.DT1_2, 99, Tone.aOp[2].DT); 210 | Put(Buffer, O, (int)ePut.DT1_3, 99, Tone.aOp[3].DT); 211 | Put(Buffer, O, (int)ePut.DT2_0, 3, Tone.aOp[0].DT2); 212 | Put(Buffer, O, (int)ePut.DT2_1, 3, Tone.aOp[1].DT2); 213 | Put(Buffer, O, (int)ePut.DT2_2, 3, Tone.aOp[2].DT2); 214 | Put(Buffer, O, (int)ePut.DT2_3, 3, Tone.aOp[3].DT2); 215 | Put(Buffer, O, (int)ePut.AL, 7, Tone.AL); 216 | Put(Buffer, O, (int)ePut.FB, 7, Tone.FB); 217 | Put(Buffer, O, (int)ePut.MX, 7, 7); 218 | Put(Buffer, O, (int)ePut.OS, 1, 1); 219 | Put(Buffer, O, (int)ePut.PB, 127, 2); 220 | 221 | if (String.IsNullOrWhiteSpace(Tone.Name)) 222 | { 223 | Tone.Name = Tone.Number.ToString(); 224 | } 225 | Buffer[o + (int)eName.Name0] = (byte)((Tone.Name.Length > 0) ? Tone.Name[0] : 0); 226 | Buffer[o + (int)eName.Name1] = (byte)((Tone.Name.Length > 1) ? Tone.Name[1] : 0); 227 | Buffer[o + (int)eName.Name2] = (byte)((Tone.Name.Length > 2) ? Tone.Name[2] : 0); 228 | Buffer[o + (int)eName.Name3] = (byte)((Tone.Name.Length > 3) ? Tone.Name[3] : 0); 229 | Buffer[o + (int)eName.Name4] = (byte)((Tone.Name.Length > 4) ? Tone.Name[4] : 0); 230 | Buffer[o + (int)eName.Name5] = (byte)((Tone.Name.Length > 5) ? Tone.Name[5] : 0); 231 | Buffer[o + (int)eName.Name6] = (byte)((Tone.Name.Length > 6) ? Tone.Name[6] : 0); 232 | Buffer[o + (int)eName.Name7] = (byte)((Tone.Name.Length > 7) ? Tone.Name[7] : 0); 233 | Buffer[o + (int)eName.Name8] = (byte)((Tone.Name.Length > 8) ? Tone.Name[8] : 0); 234 | Buffer[o + (int)eName.Name9] = (byte)((Tone.Name.Length > 9) ? Tone.Name[9] : 0); 235 | Buffer[o + (int)eName.Name10] = (byte)((Tone.Name.Length > 10) ? Tone.Name[10] : 0); 236 | Buffer[o + (int)eName.Name11] = (byte)((Tone.Name.Length > 11) ? Tone.Name[11] : 0); 237 | Buffer[o + (int)eName.Name12] = (byte)((Tone.Name.Length > 12) ? Tone.Name[12] : 0); 238 | Buffer[o + (int)eName.Name13] = (byte)((Tone.Name.Length > 13) ? Tone.Name[13] : 0); 239 | Buffer[o + (int)eName.Name14] = (byte)((Tone.Name.Length > 14) ? Tone.Name[14] : 0); 240 | Buffer[o + (int)eName.Name15] = (byte)((Tone.Name.Length > 15) ? Tone.Name[15] : 0); 241 | Buffer[o + (int)eName.Name16] = (byte)((Tone.Name.Length > 16) ? Tone.Name[16] : 0); 242 | Buffer[o + (int)eName.Name17] = (byte)((Tone.Name.Length > 17) ? Tone.Name[17] : 0); 243 | Buffer[o + (int)eName.Name18] = (byte)((Tone.Name.Length > 18) ? Tone.Name[18] : 0); 244 | Buffer[o + (int)eName.Name19] = (byte)((Tone.Name.Length > 19) ? Tone.Name[19] : 0); 245 | Buffer[o + (int)eName.Name20] = (byte)((Tone.Name.Length > 20) ? Tone.Name[20] : 0); 246 | } 247 | } 248 | 249 | 250 | 251 | public static bool IsValid(byte[] Buffer) 252 | { 253 | return (Buffer[0x00] == (byte)'C' 254 | && Buffer[0x01] == (byte)'c' 255 | && Buffer[0x02] == (byte)'n' 256 | && Buffer[0x03] == (byte)'K' 257 | && Buffer[0x05] == 0x01 258 | && Buffer[0x06] == 0xdb 259 | && Buffer[0x07] == 0x18 260 | && Buffer[0x08] == (byte)'F' 261 | && Buffer[0x09] == (byte)'B' 262 | && Buffer[0x0a] == (byte)'C' 263 | && Buffer[0x0b] == (byte)'h' 264 | && Buffer[0x0f] == 0x01 265 | && Buffer[0x10] == (byte)'J' 266 | && Buffer[0x11] == (byte)'K' 267 | && Buffer[0x12] == (byte)'J' 268 | && Buffer[0x13] == (byte)'M' 269 | && Buffer[0x17] == 0x01 270 | && Buffer[0x1a] == 0x01 271 | && Buffer[0x1b] == 0x24 272 | && Buffer[0x9d] == 0x01 273 | && Buffer[0x9e] == 0xda 274 | && Buffer[0x9f] == 0x80 275 | ); 276 | } 277 | 278 | 279 | 280 | public static void Reader(string Path, Option @Option) 281 | { 282 | var Buffer = ReadByte(Path); 283 | if (Buffer.Length == FxbLength() && IsValid(Buffer)) 284 | { 285 | Tone vTone = new Tone(); 286 | 287 | var BufferMuc = ""; 288 | var BufferDat = Dat.New(); 289 | var BufferFmp = ""; 290 | var BufferPmd = ""; 291 | var BufferVopm = Vopm.New(); 292 | 293 | for (int i = 0; i < ToneLength(); ++i) 294 | { 295 | Get(ref vTone, Buffer, i); 296 | 297 | if (Option.bMuc) Muc.Put(vTone, ref BufferMuc); 298 | if (Option.bDat) Dat.Put(vTone, ref BufferDat); 299 | if (Option.bFmp) Fmp.Put(vTone, ref BufferFmp); 300 | if (Option.bPmd) Pmd.Put(vTone, ref BufferPmd); 301 | if (Option.bVopm) Vopm.Put(vTone, ref BufferVopm); 302 | } 303 | 304 | if (Option.bMuc) Muc.Writer(Path, BufferMuc); 305 | if (Option.bDat) Dat.Writer(Path, BufferDat); 306 | if (Option.bFmp) Fmp.Writer(Path, BufferFmp); 307 | if (Option.bPmd) Pmd.Writer(Path, BufferPmd); 308 | if (Option.bVopm) Vopm.Writer(Path, BufferVopm); 309 | } 310 | } 311 | 312 | 313 | 314 | public static void Reader(string[] aPath, Option @Option) 315 | { 316 | foreach (var Path in aPath) 317 | { 318 | if (!String.IsNullOrWhiteSpace(Path) && Extension(Path) == ".fxb") Reader(Path, Option); 319 | } 320 | } 321 | 322 | 323 | 324 | public static void Writer(string Path, byte[] Buffer) 325 | { 326 | Buffer[0x00] = (byte)'C'; 327 | Buffer[0x01] = (byte)'c'; 328 | Buffer[0x02] = (byte)'n'; 329 | Buffer[0x03] = (byte)'K'; 330 | Buffer[0x05] = 0x01; 331 | Buffer[0x06] = 0xdb; 332 | Buffer[0x07] = 0x18; 333 | Buffer[0x08] = (byte)'F'; 334 | Buffer[0x09] = (byte)'B'; 335 | Buffer[0x0a] = (byte)'C'; 336 | Buffer[0x0b] = (byte)'h'; 337 | Buffer[0x0f] = 0x01; 338 | Buffer[0x10] = (byte)'J'; 339 | Buffer[0x11] = (byte)'K'; 340 | Buffer[0x12] = (byte)'J'; 341 | Buffer[0x13] = (byte)'M'; 342 | Buffer[0x17] = 0x01; 343 | Buffer[0x1a] = 0x01; 344 | Buffer[0x1b] = 0x24; 345 | Buffer[0x9d] = 0x01; 346 | Buffer[0x9e] = 0xda; 347 | Buffer[0x9f] = 0x80; 348 | 349 | WriteByte(ChangeExtension(Path, ".fxb"), Buffer); 350 | } 351 | } 352 | } 353 | -------------------------------------------------------------------------------- /FM-SoundConvertor/File.cs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | using System; 5 | using System.Linq; 6 | using System.Collections.Generic; 7 | 8 | using static FM_SoundConvertor.Path; 9 | 10 | 11 | 12 | namespace FM_SoundConvertor { 13 | public class File { 14 | public static string[] Enum(string Path){ 15 | Path = UnCloak(Path); 16 | if (System.IO.Directory.Exists(Path)){ 17 | return System.IO.Directory.EnumerateFiles(Path) 18 | .Select(Entry => Entry.Replace('\\','/')) 19 | .Where(Entry => (Entry.IndexOf("/.") == -1)) 20 | .OrderBy(Entry => Entry) 21 | .ToArray(); 22 | } 23 | return System.Array.Empty(); 24 | } 25 | 26 | 27 | 28 | public static string[] Enum(string[] aPath){ 29 | var aEnum = new List(); 30 | Array.ForEach(aPath, Path => aEnum.AddRange(Enum(Path))); 31 | return aEnum.ToArray(); 32 | } 33 | 34 | 35 | 36 | public static bool Exist(string Path){ 37 | Path = UnCloak(Path); 38 | return System.IO.File.Exists(Path); 39 | } 40 | 41 | 42 | 43 | public static void Delete(string Path){ 44 | try { 45 | Path = UnCloak(Path); 46 | System.IO.File.Delete(Path); 47 | } 48 | catch (System.IO.DirectoryNotFoundException){} 49 | } 50 | 51 | 52 | 53 | public static System.DateTime Date(string Path){ 54 | Path = UnCloak(Path); 55 | if (Exist(Path)) return System.IO.File.GetLastWriteTime(Path); 56 | return new System.DateTime(0); 57 | } 58 | 59 | 60 | 61 | public static System.DateTime Newer(IEnumerable aPath){ 62 | var aDate = aPath.Select(Path => Date(Path)); 63 | return new System.DateTime(aDate.Max().Ticks); 64 | } 65 | 66 | 67 | 68 | public static string[] ReadLine(string Path){ 69 | Path = UnCloak(Path); 70 | if (Exist(Path)) return System.IO.File.ReadAllLines(Path, System.Text.Encoding.ASCII); 71 | return System.Array.Empty(); 72 | } 73 | 74 | 75 | 76 | public static string ReadText(string Path){ 77 | Path = UnCloak(Path); 78 | if (Exist(Path)) return System.IO.File.ReadAllText(Path, System.Text.Encoding.ASCII); 79 | return System.String.Empty; 80 | } 81 | 82 | 83 | 84 | public static byte[] ReadByte(string Path){ 85 | Path = UnCloak(Path); 86 | if (Exist(Path)) return System.IO.File.ReadAllBytes(Path); 87 | return System.Array.Empty(); 88 | } 89 | 90 | 91 | 92 | public static void WriteLine(string Path, string[] aLine){ 93 | Path = UnCloak(Path); 94 | System.IO.File.WriteAllLines(Path, aLine, System.Text.Encoding.ASCII); 95 | } 96 | 97 | 98 | 99 | public static void WriteText(string Path, string Text){ 100 | Path = UnCloak(Path); 101 | System.IO.File.WriteAllText(Path, Text, System.Text.Encoding.ASCII); 102 | } 103 | 104 | 105 | 106 | public static void WriteByte(string Path, byte[] aByte){ 107 | Path = UnCloak(Path); 108 | System.IO.File.WriteAllBytes(Path, aByte); 109 | } 110 | 111 | 112 | 113 | public static long Size(string Path){ 114 | Path = UnCloak(Path); 115 | if (Exist(Path)) return (new System.IO.FileInfo(Path)).Length; 116 | return 0; 117 | } 118 | 119 | 120 | 121 | public static void Touch(string Path){ 122 | Path = UnCloak(Path); 123 | System.IO.File.OpenWrite(Path).Close(); 124 | System.IO.File.SetLastWriteTime(Path, System.DateTime.Now); 125 | } 126 | 127 | 128 | 129 | public static void Copy(string Src, string Dst){ 130 | Src = UnCloak(Src); 131 | Dst = UnCloak(Dst); 132 | if (Exist(Src)) System.IO.File.Copy(Src, Dst, true); 133 | } 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /FM-SoundConvertor/Fmp.cs: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | using System; 5 | 6 | using static FM_SoundConvertor.Path; 7 | using static FM_SoundConvertor.File; 8 | using static FM_SoundConvertor.Console; 9 | 10 | 11 | 12 | namespace FM_SoundConvertor 13 | { 14 | class Fmp 15 | { 16 | enum eState 17 | { 18 | Entry, 19 | Op0, 20 | Op1, 21 | Op2, 22 | Op3, 23 | Header, 24 | } 25 | 26 | 27 | 28 | static void GetOp(string[] aTok, ref Op @Op, int nTok) 29 | { 30 | int.TryParse(aTok[0], out Op.AR); 31 | int.TryParse(aTok[1], out Op.DR); 32 | int.TryParse(aTok[2], out Op.SR); 33 | int.TryParse(aTok[3], out Op.RR); 34 | int.TryParse(aTok[4], out Op.SL); 35 | int.TryParse(aTok[5], out Op.TL); 36 | int.TryParse(aTok[6], out Op.KS); 37 | int.TryParse(aTok[7], out Op.ML); 38 | int.TryParse(aTok[8], out Op.DT); 39 | 40 | switch (nTok) 41 | { 42 | case 9: 43 | { 44 | Op.DT2 = 0; 45 | Op.AM = 0; 46 | break; 47 | } 48 | case 10: 49 | { 50 | Op.DT2 = 0; 51 | int.TryParse(aTok[9], out Op.AM); 52 | break; 53 | } 54 | case 11: 55 | { 56 | int.TryParse(aTok[9], out Op.DT2); 57 | int.TryParse(aTok[10], out Op.AM); 58 | break; 59 | } 60 | } 61 | } 62 | 63 | 64 | 65 | static string Put(int Value) 66 | { 67 | return String.Format("{0,3},", Value); 68 | } 69 | 70 | static string Put(Op @Op) 71 | { 72 | return Put(Op.AR) + Put(Op.DR) + Put(Op.SR) + Put(Op.RR) + Put(Op.SL) + Put(Op.TL) + Put(Op.KS) + Put(Op.ML) + Put(Op.DT) + Put(Op.AM).TrimEnd(','); 73 | } 74 | 75 | public static void Put(Tone @Tone, ref string Buffer) 76 | { 77 | if (Tone.IsValid()) 78 | { 79 | var Name = String.Format("({0})", Tone.Name) + "\n"; 80 | var Header = "'@ " + String.Format("FA {0}", Tone.Number) + "\n"; 81 | var Op0 = "'@ " + Put(Tone.aOp[0]) + "\n"; 82 | var Op1 = "'@ " + Put(Tone.aOp[1]) + "\n"; 83 | var Op2 = "'@ " + Put(Tone.aOp[2]) + "\n"; 84 | var Op3 = "'@ " + Put(Tone.aOp[3]) + "\n"; 85 | var Footer = "'@ " + Put(Tone.AL) + Put(Tone.FB).TrimEnd(',') + "\n"; 86 | Buffer += Name + Header + Op0 + Op1 + Op2 + Op3 + Footer + "\n"; 87 | } 88 | } 89 | 90 | 91 | 92 | public static void Reader(string Path, Option @Option) 93 | { 94 | var vTone = new Tone(); 95 | int nTok = 0; 96 | 97 | var BufferMuc = ""; 98 | var BufferDat = Dat.New(); 99 | var BufferPmd = ""; 100 | var BufferVopm = Vopm.New(); 101 | var BufferFMtrial = FMtrial.New(); 102 | 103 | var State = eState.Entry; 104 | var aLine = ReadLine(Path); 105 | foreach (var Line in aLine) 106 | { 107 | if (String.IsNullOrWhiteSpace(Line)) continue; 108 | if (Line[0] != '\'') continue; 109 | 110 | var bPartCommnet = false; 111 | var aChar = Line.ToCharArray(); 112 | var oChar = 0; 113 | foreach (var Char in aChar) 114 | { 115 | var bPart = (Char == ';'); 116 | if (bPartCommnet) aChar[oChar] = ' '; 117 | if (bPart) bPartCommnet = !bPartCommnet; 118 | if (bPartCommnet) aChar[oChar] = ' '; 119 | ++oChar; 120 | } 121 | var Text = new string(aChar); 122 | 123 | switch (State) 124 | { 125 | case eState.Entry: 126 | { 127 | var bHead = Text.StartsWith("'@"); 128 | if (bHead) 129 | { 130 | nTok = 9; 131 | var oSub = 0; 132 | Text = Text.Substring(2).Trim(); 133 | if (Text.StartsWith("F")) { nTok = 9; oSub = 1; } 134 | if (Text.StartsWith("FA")) { nTok = 10; oSub = 2; } 135 | if (Text.StartsWith("FC")) { nTok = 11; oSub = 2; } 136 | Text = Text.Substring(oSub); 137 | 138 | var aTok = Text.Split(new char[] { ' ', '\t', }, StringSplitOptions.RemoveEmptyEntries); 139 | if (aTok.Length >= 1) 140 | { 141 | int.TryParse(aTok[0], out vTone.Number); 142 | State = eState.Op0; 143 | break; 144 | } 145 | } 146 | break; 147 | } 148 | case eState.Op0: 149 | { 150 | var bHead = Text.StartsWith("'@"); 151 | if (bHead) 152 | { 153 | Text = Text.Substring(2); 154 | var aTok = Text.Split(new char[] { ' ', '\t', ',' }, StringSplitOptions.RemoveEmptyEntries); 155 | if (aTok.Length >= nTok) 156 | { 157 | GetOp(aTok, ref vTone.aOp[0], nTok); 158 | State = eState.Op1; 159 | break; 160 | } 161 | } 162 | State = eState.Entry; 163 | break; 164 | } 165 | case eState.Op1: 166 | { 167 | var bHead = Text.StartsWith("'@"); 168 | if (bHead) 169 | { 170 | Text = Text.Substring(2); 171 | var aTok = Text.Split(new char[] { ' ', '\t', ',' }, StringSplitOptions.RemoveEmptyEntries); 172 | if (aTok.Length >= nTok) 173 | { 174 | GetOp(aTok, ref vTone.aOp[1], nTok); 175 | State = eState.Op2; 176 | break; 177 | } 178 | } 179 | State = eState.Entry; 180 | break; 181 | } 182 | case eState.Op2: 183 | { 184 | var bHead = Text.StartsWith("'@"); 185 | if (bHead) 186 | { 187 | Text = Text.Substring(2); 188 | var aTok = Text.Split(new char[] { ' ', '\t', ',' }, StringSplitOptions.RemoveEmptyEntries); 189 | if (aTok.Length >= nTok) 190 | { 191 | GetOp(aTok, ref vTone.aOp[2], nTok); 192 | State = eState.Op3; 193 | break; 194 | } 195 | } 196 | State = eState.Entry; 197 | break; 198 | } 199 | case eState.Op3: 200 | { 201 | var bHead = Text.StartsWith("'@"); 202 | if (bHead) 203 | { 204 | Text = Text.Substring(2); 205 | var aTok = Text.Split(new char[] { ' ', '\t', ',' }, StringSplitOptions.RemoveEmptyEntries); 206 | if (aTok.Length >= nTok) 207 | { 208 | GetOp(aTok, ref vTone.aOp[3], nTok); 209 | State = eState.Header; 210 | break; 211 | } 212 | } 213 | State = eState.Entry; 214 | break; 215 | } 216 | case eState.Header: 217 | { 218 | var bHead = Text.StartsWith("'@"); 219 | if (bHead) 220 | { 221 | Text = Text.Substring(2); 222 | var aTok = Text.Split(new char[] { ' ', '\t', ',' }, StringSplitOptions.RemoveEmptyEntries); 223 | if (aTok.Length >= 2) 224 | { 225 | int.TryParse(aTok[0], out vTone.AL); 226 | int.TryParse(aTok[1], out vTone.FB); 227 | vTone.Name = ""; 228 | 229 | if (Option.bMuc) Muc.Put(vTone, ref BufferMuc); 230 | if (Option.bDat) Dat.Put(vTone, ref BufferDat); 231 | if (Option.bPmd) Pmd.Put(vTone, ref BufferPmd); 232 | if (Option.bVopm) Vopm.Put(vTone, ref BufferVopm); 233 | if (Option.bFMtrial) FMtrial.Put(vTone, ref BufferFMtrial); 234 | } 235 | } 236 | State = eState.Entry; 237 | break; 238 | } 239 | } 240 | } 241 | 242 | if (Option.bMuc) Muc.Writer(Path, BufferMuc); 243 | if (Option.bDat) Dat.Writer(Path, BufferDat); 244 | if (Option.bPmd) Pmd.Writer(Path, BufferPmd); 245 | if (Option.bVopm) Vopm.Writer(Path, BufferVopm); 246 | if (Option.bFMtrial) FMtrial.Writer(Path, BufferFMtrial); 247 | } 248 | 249 | 250 | 251 | public static void Reader(string[] aPath, Option @Option) 252 | { 253 | foreach (var Path in aPath) 254 | { 255 | if (!String.IsNullOrWhiteSpace(Path) && Extension(Path) == ".mwi") Reader(Path, Option); 256 | } 257 | } 258 | 259 | 260 | 261 | public static void Writer(string Path, string Buffer) 262 | { 263 | WriteText(ChangeExtension(Path, ".mwi"), Buffer); 264 | } 265 | } 266 | } 267 | 268 | -------------------------------------------------------------------------------- /FM-SoundConvertor/Main.cs: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | using System; 5 | 6 | 7 | 8 | namespace FM_SoundConvertor 9 | { 10 | class Program 11 | { 12 | static int Main(string[] aArg) 13 | { 14 | var Option = new Option(); 15 | 16 | int oArg = 0; 17 | foreach (var Arg in aArg) 18 | { 19 | if (Arg[0] == '-') 20 | { 21 | switch (Arg) 22 | { 23 | case "-muc": 24 | { 25 | Option.bMuc = true; 26 | break; 27 | } 28 | case "-dat": 29 | { 30 | Option.bDat = true; 31 | break; 32 | } 33 | case "-fmp": 34 | { 35 | Option.bFmp = true; 36 | break; 37 | } 38 | case "-pmd": 39 | { 40 | Option.bPmd = true; 41 | break; 42 | } 43 | case "-vopm": 44 | { 45 | Option.bVopm = true; 46 | break; 47 | } 48 | case "-fmtrial": 49 | { 50 | Option.bFMtrial = true; 51 | break; 52 | } 53 | } 54 | aArg[oArg] = String.Empty; 55 | } 56 | ++oArg; 57 | } 58 | 59 | Muc.Reader(aArg, Option); 60 | Dat.Reader(aArg, Option); 61 | Fmp.Reader(aArg, Option); 62 | Pmd.Reader(aArg, Option); 63 | Vopm.Reader(aArg, Option); 64 | FMtrial.Reader(aArg, Option); 65 | return 0; 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /FM-SoundConvertor/Muc.cs: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | using System; 5 | 6 | using static FM_SoundConvertor.Path; 7 | using static FM_SoundConvertor.File; 8 | using static FM_SoundConvertor.Console; 9 | 10 | 11 | 12 | namespace FM_SoundConvertor 13 | { 14 | class Muc 15 | { 16 | enum eState 17 | { 18 | Entry, 19 | Header, 20 | Op0, 21 | Op1, 22 | Op2, 23 | Op3, 24 | } 25 | 26 | enum eType 27 | { 28 | Mucom, 29 | Mmldrv, 30 | } 31 | 32 | 33 | 34 | static void GetOp(string[] aTok, ref Op @Op, eType Type) 35 | { 36 | switch (Type) 37 | { 38 | case eType.Mucom: 39 | { 40 | int.TryParse(aTok[0], out Op.AR); 41 | int.TryParse(aTok[1], out Op.DR); 42 | int.TryParse(aTok[2], out Op.SR); 43 | int.TryParse(aTok[3], out Op.RR); 44 | int.TryParse(aTok[4], out Op.SL); 45 | int.TryParse(aTok[5], out Op.TL); 46 | int.TryParse(aTok[6], out Op.KS); 47 | int.TryParse(aTok[7], out Op.ML); 48 | int.TryParse(aTok[8], out Op.DT); 49 | Op.DT2 = 0; 50 | Op.AM = 0; 51 | break; 52 | } 53 | case eType.Mmldrv: 54 | { 55 | int.TryParse(aTok[0], out Op.AR); 56 | int.TryParse(aTok[1], out Op.DR); 57 | int.TryParse(aTok[2], out Op.SR); 58 | int.TryParse(aTok[3], out Op.RR); 59 | int.TryParse(aTok[4], out Op.SL); 60 | int.TryParse(aTok[5], out Op.TL); 61 | int.TryParse(aTok[6], out Op.KS); 62 | int.TryParse(aTok[7], out Op.ML); 63 | int.TryParse(aTok[8], out Op.DT); 64 | int.TryParse(aTok[9], out Op.DT2); 65 | int.TryParse(aTok[10], out Op.AM); 66 | break; 67 | } 68 | } 69 | } 70 | 71 | 72 | 73 | static string Put(int Value) 74 | { 75 | return String.Format("{0,3},", Value); 76 | } 77 | 78 | static string Put(Op @Op) 79 | { 80 | return Put(Op.AR) + Put(Op.DR) + Put(Op.SR) + Put(Op.RR) + Put(Op.SL) + Put(Op.TL) + Put(Op.KS) + Put(Op.ML) + Put(Op.DT).TrimEnd(','); 81 | } 82 | 83 | public static void Put(Tone @Tone, ref string Buffer) 84 | { 85 | if (Tone.IsValid()) 86 | { 87 | var Entry = " " + String.Format("@{0}:{{", Tone.Number) + "\n"; 88 | var Header = " " + Put(Tone.FB) + Put(Tone.AL).TrimEnd(',') + "\n"; 89 | var Op0 = " " + Put(Tone.aOp[0]) + "\n"; 90 | var Op1 = " " + Put(Tone.aOp[1]) + "\n"; 91 | var Op2 = " " + Put(Tone.aOp[2]) + "\n"; 92 | var Op3 = " " + Put(Tone.aOp[3]) + String.Format(",\"{0}\"}}", Tone.Name) + "\n"; 93 | Buffer += Entry + Header + Op0 + Op1 + Op2 + Op3 + "\n"; 94 | } 95 | } 96 | 97 | 98 | 99 | static void Reader(string Path, Option @Option) 100 | { 101 | var vTone = new Tone(); 102 | var Type = eType.Mucom; 103 | var nTok = 0; 104 | 105 | var BufferDat = Dat.New(); 106 | var BufferFmp = ""; 107 | var BufferPmd = ""; 108 | var BufferVopm = Vopm.New(); 109 | var BufferFMtrial = FMtrial.New(); 110 | 111 | var State = eState.Entry; 112 | var aLine = ReadLine(Path); 113 | foreach (var Line in aLine) 114 | { 115 | if (String.IsNullOrWhiteSpace(Line)) continue; 116 | if (Line[0] == '\'') continue; 117 | 118 | var oMark = Line.IndexOf(';'); 119 | var Text = (oMark >= 0)? Line.Remove(oMark): Line; 120 | 121 | switch (State) 122 | { 123 | case eState.Entry: 124 | { 125 | Text = Text.Trim(); 126 | 127 | var bHead = Text.StartsWith("@"); 128 | var bTail = Text.EndsWith(":{"); 129 | if (bHead) 130 | { 131 | vTone.Number++; 132 | 133 | Type = (bTail) ? eType.Mucom : eType.Mmldrv; 134 | nTok = (bTail) ? 9 : 11; 135 | 136 | var aTok = Text.Split(new char[] { ' ', '\t', '@', ':', '{', }, StringSplitOptions.RemoveEmptyEntries); 137 | if (aTok.Length >= 1) 138 | { 139 | int Number; 140 | if (int.TryParse(aTok[0], out Number)) vTone.Number = Number; 141 | } 142 | State = eState.Header; 143 | break; 144 | } 145 | break; 146 | } 147 | case eState.Header: 148 | { 149 | var aTok = Text.Split(new char[] { ' ', '\t', ',', }, StringSplitOptions.RemoveEmptyEntries); 150 | if (aTok.Length >= 2) 151 | { 152 | switch (Type) 153 | { 154 | case eType.Mucom: 155 | { 156 | int.TryParse(aTok[0], out vTone.FB); 157 | int.TryParse(aTok[1], out vTone.AL); 158 | break; 159 | } 160 | case eType.Mmldrv: 161 | { 162 | int.TryParse(aTok[0], out vTone.AL); 163 | int.TryParse(aTok[1], out vTone.FB); 164 | break; 165 | } 166 | } 167 | State = eState.Op0; 168 | break; 169 | } 170 | State = eState.Entry; 171 | break; 172 | } 173 | case eState.Op0: 174 | { 175 | var aTok = Text.Split(new char[] { ' ', '\t', ',', }, StringSplitOptions.RemoveEmptyEntries); 176 | if (aTok.Length >= nTok) 177 | { 178 | GetOp(aTok, ref vTone.aOp[0], Type); 179 | State = eState.Op1; 180 | break; 181 | } 182 | State = eState.Entry; 183 | break; 184 | } 185 | case eState.Op1: 186 | { 187 | var aTok = Text.Split(new char[] { ' ', '\t', ',', }, StringSplitOptions.RemoveEmptyEntries); 188 | if (aTok.Length >= nTok) 189 | { 190 | GetOp(aTok, ref vTone.aOp[1], Type); 191 | State = eState.Op2; 192 | break; 193 | } 194 | State = eState.Entry; 195 | break; 196 | } 197 | case eState.Op2: 198 | { 199 | var aTok = Text.Split(new char[] { ' ', '\t', ',', }, StringSplitOptions.RemoveEmptyEntries); 200 | if (aTok.Length >= nTok) 201 | { 202 | GetOp(aTok, ref vTone.aOp[2], Type); 203 | State = eState.Op3; 204 | break; 205 | } 206 | State = eState.Entry; 207 | break; 208 | } 209 | case eState.Op3: 210 | { 211 | var aTok = Text.Split(new char[] { ' ', '\t', ',', }, StringSplitOptions.RemoveEmptyEntries); 212 | switch (Type) 213 | { 214 | case eType.Mucom: 215 | { 216 | if (aTok.Length >= (nTok+1)) 217 | { 218 | GetOp(aTok, ref vTone.aOp[3], Type); 219 | 220 | var Tok = ""; 221 | for (int o = nTok; o < aTok.Length; ++o) Tok += aTok[o]; 222 | 223 | var oHead = Tok.IndexOf('\"'); 224 | var oTail = Tok.IndexOf('\"', oHead+1); 225 | var bTerm = Tok.EndsWith("}"); 226 | if (oHead >= 0 && oTail >= 0 && bTerm) 227 | { 228 | vTone.Name = Tok.Substring(oHead+1, oTail-oHead-1); 229 | 230 | if (Option.bDat) Dat.Put(vTone, ref BufferDat); 231 | if (Option.bFmp) Fmp.Put(vTone, ref BufferFmp); 232 | if (Option.bPmd) Pmd.Put(vTone, ref BufferPmd); 233 | if (Option.bVopm) Vopm.Put(vTone, ref BufferVopm); 234 | if (Option.bFMtrial) FMtrial.Put(vTone, ref BufferFMtrial); 235 | } 236 | } 237 | break; 238 | } 239 | case eType.Mmldrv: 240 | { 241 | if (aTok.Length >= nTok) 242 | { 243 | GetOp(aTok, ref vTone.aOp[3], Type); 244 | 245 | vTone.Name = ""; 246 | 247 | if (Option.bDat) Dat.Put(vTone, ref BufferDat); 248 | if (Option.bFmp) Fmp.Put(vTone, ref BufferFmp); 249 | if (Option.bPmd) Pmd.Put(vTone, ref BufferPmd); 250 | if (Option.bVopm) Vopm.Put(vTone, ref BufferVopm); 251 | if (Option.bFMtrial) FMtrial.Put(vTone, ref BufferFMtrial); 252 | } 253 | break; 254 | } 255 | } 256 | State = eState.Entry; 257 | break; 258 | } 259 | } 260 | } 261 | 262 | if (Option.bDat) Dat.Writer(Path, BufferDat); 263 | if (Option.bFmp) Fmp.Writer(Path, BufferFmp); 264 | if (Option.bPmd) Pmd.Writer(Path, BufferPmd); 265 | if (Option.bVopm) Vopm.Writer(Path, BufferVopm); 266 | if (Option.bFMtrial) FMtrial.Writer(Path, BufferFMtrial); 267 | } 268 | 269 | 270 | 271 | public static void Reader(string[] aPath, Option @Option) 272 | { 273 | foreach (var Path in aPath) 274 | { 275 | if (!String.IsNullOrWhiteSpace(Path) && Extension(Path) == ".muc") Reader(Path, Option); 276 | } 277 | } 278 | 279 | 280 | 281 | public static void Writer(string Path, string Buffer) 282 | { 283 | WriteText(ChangeExtension(Path, ".muc"), Buffer); 284 | } 285 | } 286 | } 287 | -------------------------------------------------------------------------------- /FM-SoundConvertor/Option.cs: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | namespace FM_SoundConvertor 5 | { 6 | class Option 7 | { 8 | public bool bMuc; 9 | public bool bDat; 10 | public bool bPmd; 11 | public bool bFmp; 12 | public bool bVopm; 13 | public bool bFMtrial; 14 | 15 | 16 | 17 | public Option() 18 | { 19 | bMuc = false; 20 | bDat = false; 21 | bPmd = false; 22 | bFmp = false; 23 | bVopm = false; 24 | bFMtrial = false; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /FM-SoundConvertor/Path.cs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | using System; 5 | using System.Linq; 6 | using System.Collections.Generic; 7 | 8 | 9 | 10 | namespace FM_SoundConvertor { 11 | public class Path { 12 | public static string[] Full(string[] aPath){ 13 | return aPath.Select(Path => Full(Path)).ToArray(); 14 | } 15 | 16 | 17 | 18 | public static string Full(string Path){ 19 | return System.IO.Path.GetFullPath(Path).Replace('\\','/'); 20 | } 21 | 22 | 23 | 24 | public static string Directory(string Path){ 25 | return System.IO.Path.GetDirectoryName(Path).Replace('\\','/'); 26 | } 27 | 28 | 29 | 30 | public static string Base(string Path){ 31 | return System.IO.Path.GetFileNameWithoutExtension(Path); 32 | } 33 | 34 | 35 | 36 | public static string Name(string Path){ 37 | return System.IO.Path.GetFileName(Path); 38 | } 39 | 40 | 41 | 42 | public static string Extension(string Path){ 43 | return System.IO.Path.GetExtension(Path); 44 | } 45 | 46 | 47 | 48 | public static string TrimStart(string Path){ 49 | return Path.TrimStart(':','\\','/'); 50 | } 51 | 52 | 53 | 54 | public static string TrimEnd(string Path){ 55 | return Path.TrimEnd(':','\\','/'); 56 | } 57 | 58 | 59 | 60 | public static string Trim(string Path){ 61 | return TrimStart(TrimEnd(Path)); 62 | } 63 | 64 | 65 | 66 | public static string Combine(string Base, string Path){ 67 | return Full(System.IO.Path.Combine(Base, TrimStart(Path))); 68 | } 69 | 70 | 71 | 72 | public static string Combine(string Base, string Path, string Extension){ 73 | return string.Concat(Combine(Base, Path), Extension); 74 | } 75 | 76 | 77 | 78 | public static string ChangeDirectory(string From, string To, string Path){ 79 | return Combine(To, Path.Substring(From.Length)); 80 | } 81 | 82 | 83 | 84 | public static string ChangeExtension(string Path, string Extension){ 85 | return Combine(Directory(Path), Base(Path), Extension); 86 | } 87 | 88 | 89 | 90 | public static string Cloak(string Path){ 91 | return "\"" + Trim(Path) + "\""; 92 | } 93 | 94 | 95 | 96 | public static string UnCloak(string Path){ 97 | return Path.Trim('\"'); 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /FM-SoundConvertor/Pmd.cs: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | using System; 5 | 6 | using static FM_SoundConvertor.Path; 7 | using static FM_SoundConvertor.File; 8 | using static FM_SoundConvertor.Console; 9 | 10 | 11 | 12 | namespace FM_SoundConvertor 13 | { 14 | class Pmd 15 | { 16 | enum eState 17 | { 18 | Entry, 19 | Op0, 20 | Op1, 21 | Op2, 22 | Op3, 23 | } 24 | 25 | 26 | 27 | static void GetOp(string[] aTok, ref Op @Op) 28 | { 29 | int.TryParse(aTok[0], out Op.AR); 30 | int.TryParse(aTok[1], out Op.DR); 31 | int.TryParse(aTok[2], out Op.SR); 32 | int.TryParse(aTok[3], out Op.RR); 33 | int.TryParse(aTok[4], out Op.SL); 34 | int.TryParse(aTok[5], out Op.TL); 35 | int.TryParse(aTok[6], out Op.KS); 36 | int.TryParse(aTok[7], out Op.ML); 37 | int.TryParse(aTok[8], out Op.DT); 38 | Op.DT2 = 0; 39 | int.TryParse(aTok[9], out Op.AM); 40 | } 41 | 42 | 43 | 44 | static string Put(int Value) 45 | { 46 | return String.Format("{0,4}", Value); 47 | } 48 | 49 | static string Put(Op @Op) 50 | { 51 | return Put(Op.AR) + Put(Op.DR) + Put(Op.SR) + Put(Op.RR) + Put(Op.SL) + Put(Op.TL) + Put(Op.KS) + Put(Op.ML) + Put(Op.DT) + Put(Op.AM); 52 | } 53 | 54 | public static void Put(Tone @Tone, ref string Buffer) 55 | { 56 | if (Tone.IsValid()) 57 | { 58 | var Header = String.Format("@{0}", Tone.Number) + Put(Tone.AL) + Put(Tone.FB) + String.Format(" = {0}", Tone.Name) + "\n"; 59 | var Op0 = Put(Tone.aOp[0]) + "\n"; 60 | var Op1 = Put(Tone.aOp[1]) + "\n"; 61 | var Op2 = Put(Tone.aOp[2]) + "\n"; 62 | var Op3 = Put(Tone.aOp[3]) + "\n"; 63 | Buffer += Header + Op0 + Op1 + Op2 + Op3 + "\n"; 64 | } 65 | } 66 | 67 | 68 | 69 | public static void Reader(string Path, Option @Option) 70 | { 71 | var vTone = new Tone(); 72 | bool bLineComment = false; 73 | 74 | var BufferMuc = ""; 75 | var BufferDat = Dat.New(); 76 | var BufferFmp = ""; 77 | var BufferVopm = Vopm.New(); 78 | var BufferFMtrial = FMtrial.New(); 79 | 80 | var State = eState.Entry; 81 | var aLine = ReadLine(Path); 82 | foreach (var Line in aLine) 83 | { 84 | if (String.IsNullOrWhiteSpace(Line)) continue; 85 | 86 | var bLine = (Line[0] == '`'); 87 | if (bLine) 88 | { 89 | bLineComment = !bLineComment; 90 | continue; 91 | } 92 | if (bLineComment) continue; 93 | 94 | var bPartCommnet = false; 95 | var bTailCommnet = false; 96 | var aChar = Line.ToCharArray(); 97 | var oChar = 0; 98 | foreach (var Char in aChar) 99 | { 100 | if (bTailCommnet) aChar[oChar] = ' '; 101 | 102 | var bPart = (Char == '`'); 103 | if (bPartCommnet) aChar[oChar] = ' '; 104 | if (bPart) bPartCommnet = !bPartCommnet; 105 | if (bPartCommnet) aChar[oChar] = ' '; 106 | 107 | if (Char == ';') bTailCommnet = true; 108 | if (bTailCommnet) aChar[oChar] = ' '; 109 | ++oChar; 110 | } 111 | var Text = new string(aChar); 112 | 113 | switch (State) 114 | { 115 | case eState.Entry: 116 | { 117 | if (Text[0] == ' ' || Text[0] == '\t') continue; 118 | 119 | var bHead = Text.StartsWith("@"); 120 | var oName = Text.IndexOf('='); 121 | if (bHead) 122 | { 123 | var aTok = Text.Split(new char[] { ' ', '\t', '=', }, StringSplitOptions.RemoveEmptyEntries); 124 | if (aTok.Length >= 3) 125 | { 126 | aTok[0] = aTok[0].Substring(1); 127 | 128 | int.TryParse(aTok[0], out vTone.Number); 129 | int.TryParse(aTok[1], out vTone.AL); 130 | int.TryParse(aTok[2], out vTone.FB); 131 | vTone.Name = (aTok.Length >= 4 && oName > 0) ? aTok[3] : ""; 132 | State = eState.Op0; 133 | break; 134 | } 135 | } 136 | break; 137 | } 138 | case eState.Op0: 139 | { 140 | var aTok = Text.Split(new char[] { ' ', '\t', }, StringSplitOptions.RemoveEmptyEntries); 141 | if (aTok.Length >= 10) 142 | { 143 | GetOp(aTok, ref vTone.aOp[0]); 144 | State = eState.Op1; 145 | break; 146 | } 147 | State = eState.Entry; 148 | break; 149 | } 150 | case eState.Op1: 151 | { 152 | var aTok = Text.Split(new char[] { ' ', '\t', }, StringSplitOptions.RemoveEmptyEntries); 153 | if (aTok.Length >= 10) 154 | { 155 | GetOp(aTok, ref vTone.aOp[1]); 156 | State = eState.Op2; 157 | break; 158 | } 159 | State = eState.Entry; 160 | break; 161 | } 162 | case eState.Op2: 163 | { 164 | var aTok = Text.Split(new char[] { ' ', '\t', }, StringSplitOptions.RemoveEmptyEntries); 165 | if (aTok.Length >= 10) 166 | { 167 | GetOp(aTok, ref vTone.aOp[2]); 168 | State = eState.Op3; 169 | break; 170 | } 171 | State = eState.Entry; 172 | break; 173 | } 174 | case eState.Op3: 175 | { 176 | var aTok = Text.Split(new char[] { ' ', '\t', }, StringSplitOptions.RemoveEmptyEntries); 177 | if (aTok.Length >= 10) 178 | { 179 | GetOp(aTok, ref vTone.aOp[3]); 180 | 181 | if (Option.bMuc) Muc.Put(vTone, ref BufferMuc); 182 | if (Option.bDat) Dat.Put(vTone, ref BufferDat); 183 | if (Option.bFmp) Fmp.Put(vTone, ref BufferFmp); 184 | if (Option.bVopm) Vopm.Put(vTone, ref BufferVopm); 185 | if (Option.bFMtrial) FMtrial.Put(vTone, ref BufferFMtrial); 186 | } 187 | State = eState.Entry; 188 | break; 189 | } 190 | } 191 | } 192 | 193 | if (Option.bMuc) Muc.Writer(Path, BufferMuc); 194 | if (Option.bDat) Dat.Writer(Path, BufferDat); 195 | if (Option.bFmp) Fmp.Writer(Path, BufferFmp); 196 | if (Option.bVopm) Vopm.Writer(Path, BufferVopm); 197 | if (Option.bFMtrial) FMtrial.Writer(Path, BufferFMtrial); 198 | } 199 | 200 | 201 | 202 | public static void Reader(string[] aPath, Option @Option) 203 | { 204 | foreach (var Path in aPath) 205 | { 206 | if (!String.IsNullOrWhiteSpace(Path) && Extension(Path) == ".mml") Reader(Path, Option); 207 | } 208 | } 209 | 210 | 211 | 212 | public static void Writer(string Path, string Buffer) 213 | { 214 | WriteText(ChangeExtension(Path, ".mml"), Buffer); 215 | } 216 | } 217 | } 218 | -------------------------------------------------------------------------------- /FM-SoundConvertor/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // アセンブリに関する一般情報は以下の属性セットをとおして制御されます。 6 | // 制御されます。アセンブリに関連付けられている情報を変更するには、 7 | // これらの属性値を変更します。 8 | [assembly: AssemblyTitle("FM-SoundConvertor")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("FM-SoundConvertor")] 13 | [assembly: AssemblyCopyright("Copyright ©D.M.88 2020")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // ComVisible を false に設定すると、このアセンブリ内の型は COM コンポーネントから 18 | // 参照できなくなります。COM からこのアセンブリ内の型にアクセスする必要がある場合は、 19 | // その型の ComVisible 属性を true に設定します。 20 | [assembly: ComVisible(false)] 21 | 22 | // このプロジェクトが COM に公開される場合、次の GUID が typelib の ID になります 23 | [assembly: Guid("a3da1746-8229-471a-8029-3322ccfb15ab")] 24 | 25 | // アセンブリのバージョン情報は次の 4 つの値で構成されています: 26 | // 27 | // メジャー バージョン 28 | // マイナー バージョン 29 | // ビルド番号 30 | // リビジョン 31 | // 32 | // すべての値を指定するか、次を使用してビルド番号とリビジョン番号を既定に設定できます 33 | // 既定値にすることができます: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /FM-SoundConvertor/Tone.cs: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | namespace FM_SoundConvertor 5 | { 6 | class Op 7 | { 8 | public int AR; 9 | public int DR; 10 | public int SR; 11 | public int RR; 12 | public int SL; 13 | public int TL; 14 | public int KS; 15 | public int ML; 16 | public int DT; 17 | public int DT2; 18 | public int AM; 19 | 20 | 21 | 22 | public Op() 23 | { 24 | AR = 0; 25 | DR = 0; 26 | SR = 0; 27 | RR = 0; 28 | SL = 0; 29 | TL = 0; 30 | KS = 0; 31 | ML = 0; 32 | DT = 0; 33 | DT2 = 0; 34 | AM = 0; 35 | } 36 | } 37 | 38 | 39 | 40 | class Tone 41 | { 42 | public string Name; 43 | public int Number; 44 | public int FB; 45 | public int AL; 46 | public Op[] aOp; 47 | 48 | 49 | 50 | public Tone() 51 | { 52 | Name = ""; 53 | Number = -1; 54 | FB = 0; 55 | AL = 0; 56 | aOp = new Op[4]; 57 | aOp[0] = new Op(); 58 | aOp[1] = new Op(); 59 | aOp[2] = new Op(); 60 | aOp[3] = new Op(); 61 | } 62 | 63 | 64 | 65 | public bool IsValid() 66 | { 67 | return (Number >= 0x00 && Number <= 0xff && aOp[0].AR > 0 && aOp[1].AR > 0 && aOp[2].AR > 0 && aOp[3].AR > 0); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /FM-SoundConvertor/VOPM.cs: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | using System; 5 | 6 | using static FM_SoundConvertor.Path; 7 | using static FM_SoundConvertor.File; 8 | using static FM_SoundConvertor.Console; 9 | 10 | 11 | 12 | namespace FM_SoundConvertor 13 | { 14 | class Vopm 15 | { 16 | enum ePut 17 | { 18 | AL, FB, 19 | _0, _1, _2, _3, _4, _5, _6, _7, 20 | Mask, 21 | TL0, AR0, DR0, SL0, SR0, RR0, KS0, ML0, DT1_0, DT2_0, AM0, 22 | TL1, AR1, DR1, SL1, SR1, RR1, KS1, ML1, DT1_1, DT2_1, AM1, 23 | TL2, AR2, DR2, SL2, SR2, RR2, KS2, ML2, DT1_2, DT2_2, AM2, 24 | TL3, AR3, DR3, SL3, SR3, RR3, KS3, ML3, DT1_3, DT2_3, AM3, 25 | Name0, Name1, Name2, Name3, Name4, Name5, Name6, Name7, Name8, Name9, Name10, Name11, Name12, Name13, Name14, Name15, 26 | } 27 | 28 | 29 | 30 | static int ToneLength() 31 | { 32 | return 0x80; 33 | } 34 | 35 | static int HeadLength() 36 | { 37 | return 0xa0; 38 | } 39 | 40 | static int PutLength() 41 | { 42 | return System.Enum.GetNames(typeof(ePut)).Length; 43 | } 44 | 45 | static int FxbLength() 46 | { 47 | return HeadLength() + (ToneLength() * PutLength()); 48 | } 49 | 50 | 51 | 52 | public static byte[] New() 53 | { 54 | return new byte[FxbLength()]; 55 | } 56 | 57 | 58 | 59 | static void Get(ref Tone @Tone, byte[] Buffer, int i) 60 | { 61 | int o = HeadLength() + (i * PutLength()); 62 | Tone.aOp[0].AR = Buffer[o + (int)ePut.AR0]; 63 | Tone.aOp[1].AR = Buffer[o + (int)ePut.AR1]; 64 | Tone.aOp[2].AR = Buffer[o + (int)ePut.AR2]; 65 | Tone.aOp[3].AR = Buffer[o + (int)ePut.AR3]; 66 | Tone.aOp[0].DR = Buffer[o + (int)ePut.DR0]; 67 | Tone.aOp[1].DR = Buffer[o + (int)ePut.DR1]; 68 | Tone.aOp[2].DR = Buffer[o + (int)ePut.DR2]; 69 | Tone.aOp[3].DR = Buffer[o + (int)ePut.DR3]; 70 | Tone.aOp[0].SR = Buffer[o + (int)ePut.SR0]; 71 | Tone.aOp[1].SR = Buffer[o + (int)ePut.SR1]; 72 | Tone.aOp[2].SR = Buffer[o + (int)ePut.SR2]; 73 | Tone.aOp[3].SR = Buffer[o + (int)ePut.SR3]; 74 | Tone.aOp[0].RR = Buffer[o + (int)ePut.RR0]; 75 | Tone.aOp[1].RR = Buffer[o + (int)ePut.RR1]; 76 | Tone.aOp[2].RR = Buffer[o + (int)ePut.RR2]; 77 | Tone.aOp[3].RR = Buffer[o + (int)ePut.RR3]; 78 | Tone.aOp[0].SL = Buffer[o + (int)ePut.SL0]; 79 | Tone.aOp[1].SL = Buffer[o + (int)ePut.SL1]; 80 | Tone.aOp[2].SL = Buffer[o + (int)ePut.SL2]; 81 | Tone.aOp[3].SL = Buffer[o + (int)ePut.SL3]; 82 | Tone.aOp[0].TL = Buffer[o + (int)ePut.TL0]; 83 | Tone.aOp[1].TL = Buffer[o + (int)ePut.TL1]; 84 | Tone.aOp[2].TL = Buffer[o + (int)ePut.TL2]; 85 | Tone.aOp[3].TL = Buffer[o + (int)ePut.TL3]; 86 | Tone.aOp[0].KS = Buffer[o + (int)ePut.KS0]; 87 | Tone.aOp[1].KS = Buffer[o + (int)ePut.KS1]; 88 | Tone.aOp[2].KS = Buffer[o + (int)ePut.KS2]; 89 | Tone.aOp[3].KS = Buffer[o + (int)ePut.KS3]; 90 | Tone.aOp[0].ML = Buffer[o + (int)ePut.ML0]; 91 | Tone.aOp[1].ML = Buffer[o + (int)ePut.ML1]; 92 | Tone.aOp[2].ML = Buffer[o + (int)ePut.ML2]; 93 | Tone.aOp[3].ML = Buffer[o + (int)ePut.ML3]; 94 | Tone.aOp[0].DT = Buffer[o + (int)ePut.DT1_0]; 95 | Tone.aOp[1].DT = Buffer[o + (int)ePut.DT1_1]; 96 | Tone.aOp[2].DT = Buffer[o + (int)ePut.DT1_2]; 97 | Tone.aOp[3].DT = Buffer[o + (int)ePut.DT1_3]; 98 | Tone.aOp[0].DT2 = Buffer[o + (int)ePut.DT2_0]; 99 | Tone.aOp[1].DT2 = Buffer[o + (int)ePut.DT2_1]; 100 | Tone.aOp[2].DT2 = Buffer[o + (int)ePut.DT2_2]; 101 | Tone.aOp[3].DT2 = Buffer[o + (int)ePut.DT2_3]; 102 | Tone.aOp[0].AM = Buffer[o + (int)ePut.AM0]; 103 | Tone.aOp[1].AM = Buffer[o + (int)ePut.AM1]; 104 | Tone.aOp[2].AM = Buffer[o + (int)ePut.AM2]; 105 | Tone.aOp[3].AM = Buffer[o + (int)ePut.AM3]; 106 | Tone.AL = Buffer[o + (int)ePut.AL]; 107 | Tone.FB = Buffer[o + (int)ePut.FB]; 108 | 109 | var aChar = new char[] 110 | { 111 | (char)Buffer[o + (int)ePut.Name0], 112 | (char)Buffer[o + (int)ePut.Name1], 113 | (char)Buffer[o + (int)ePut.Name2], 114 | (char)Buffer[o + (int)ePut.Name3], 115 | (char)Buffer[o + (int)ePut.Name4], 116 | (char)Buffer[o + (int)ePut.Name5], 117 | (char)Buffer[o + (int)ePut.Name6], 118 | (char)Buffer[o + (int)ePut.Name7], 119 | (char)Buffer[o + (int)ePut.Name8], 120 | (char)Buffer[o + (int)ePut.Name9], 121 | (char)Buffer[o + (int)ePut.Name10], 122 | (char)Buffer[o + (int)ePut.Name11], 123 | (char)Buffer[o + (int)ePut.Name12], 124 | (char)Buffer[o + (int)ePut.Name13], 125 | (char)Buffer[o + (int)ePut.Name14], 126 | (char)Buffer[o + (int)ePut.Name15], 127 | }; 128 | Tone.Name = ""; 129 | foreach (var Char in aChar) if (Char != 0) Tone.Name += Char.ToString(); 130 | 131 | Tone.Number = i; 132 | } 133 | 134 | 135 | 136 | public static void Put(Tone @Tone, ref byte[] Buffer) 137 | { 138 | if (Tone.IsValid() && Tone.Number < ToneLength()) 139 | { 140 | int o = HeadLength() + (Tone.Number * PutLength()); 141 | Buffer[o + (int)ePut.AR0] = (byte)Tone.aOp[0].AR; 142 | Buffer[o + (int)ePut.AR1] = (byte)Tone.aOp[1].AR; 143 | Buffer[o + (int)ePut.AR2] = (byte)Tone.aOp[2].AR; 144 | Buffer[o + (int)ePut.AR3] = (byte)Tone.aOp[3].AR; 145 | Buffer[o + (int)ePut.DR0] = (byte)Tone.aOp[0].DR; 146 | Buffer[o + (int)ePut.DR1] = (byte)Tone.aOp[1].DR; 147 | Buffer[o + (int)ePut.DR2] = (byte)Tone.aOp[2].DR; 148 | Buffer[o + (int)ePut.DR3] = (byte)Tone.aOp[3].DR; 149 | Buffer[o + (int)ePut.SR0] = (byte)Tone.aOp[0].SR; 150 | Buffer[o + (int)ePut.SR1] = (byte)Tone.aOp[1].SR; 151 | Buffer[o + (int)ePut.SR2] = (byte)Tone.aOp[2].SR; 152 | Buffer[o + (int)ePut.SR3] = (byte)Tone.aOp[3].SR; 153 | Buffer[o + (int)ePut.RR0] = (byte)Tone.aOp[0].RR; 154 | Buffer[o + (int)ePut.RR1] = (byte)Tone.aOp[1].RR; 155 | Buffer[o + (int)ePut.RR2] = (byte)Tone.aOp[2].RR; 156 | Buffer[o + (int)ePut.RR3] = (byte)Tone.aOp[3].RR; 157 | Buffer[o + (int)ePut.SL0] = (byte)Tone.aOp[0].SL; 158 | Buffer[o + (int)ePut.SL1] = (byte)Tone.aOp[1].SL; 159 | Buffer[o + (int)ePut.SL2] = (byte)Tone.aOp[2].SL; 160 | Buffer[o + (int)ePut.SL3] = (byte)Tone.aOp[3].SL; 161 | Buffer[o + (int)ePut.TL0] = (byte)Tone.aOp[0].TL; 162 | Buffer[o + (int)ePut.TL1] = (byte)Tone.aOp[1].TL; 163 | Buffer[o + (int)ePut.TL2] = (byte)Tone.aOp[2].TL; 164 | Buffer[o + (int)ePut.TL3] = (byte)Tone.aOp[3].TL; 165 | Buffer[o + (int)ePut.KS0] = (byte)Tone.aOp[0].KS; 166 | Buffer[o + (int)ePut.KS1] = (byte)Tone.aOp[1].KS; 167 | Buffer[o + (int)ePut.KS2] = (byte)Tone.aOp[2].KS; 168 | Buffer[o + (int)ePut.KS3] = (byte)Tone.aOp[3].KS; 169 | Buffer[o + (int)ePut.ML0] = (byte)Tone.aOp[0].ML; 170 | Buffer[o + (int)ePut.ML1] = (byte)Tone.aOp[1].ML; 171 | Buffer[o + (int)ePut.ML2] = (byte)Tone.aOp[2].ML; 172 | Buffer[o + (int)ePut.ML3] = (byte)Tone.aOp[3].ML; 173 | Buffer[o + (int)ePut.DT1_0] = (byte)Tone.aOp[0].DT; 174 | Buffer[o + (int)ePut.DT1_1] = (byte)Tone.aOp[1].DT; 175 | Buffer[o + (int)ePut.DT1_2] = (byte)Tone.aOp[2].DT; 176 | Buffer[o + (int)ePut.DT1_3] = (byte)Tone.aOp[3].DT; 177 | Buffer[o + (int)ePut.DT2_0] = (byte)Tone.aOp[0].DT2; 178 | Buffer[o + (int)ePut.DT2_1] = (byte)Tone.aOp[1].DT2; 179 | Buffer[o + (int)ePut.DT2_2] = (byte)Tone.aOp[2].DT2; 180 | Buffer[o + (int)ePut.DT2_3] = (byte)Tone.aOp[3].DT2; 181 | Buffer[o + (int)ePut.AM0] = (byte)Tone.aOp[0].AM; 182 | Buffer[o + (int)ePut.AM1] = (byte)Tone.aOp[1].AM; 183 | Buffer[o + (int)ePut.AM2] = (byte)Tone.aOp[2].AM; 184 | Buffer[o + (int)ePut.AM3] = (byte)Tone.aOp[3].AM; 185 | Buffer[o + (int)ePut.AL] = (byte)Tone.AL; 186 | Buffer[o + (int)ePut.FB] = (byte)Tone.FB; 187 | Buffer[o + (int)ePut.Mask] = 0xf << 3; 188 | 189 | if (String.IsNullOrWhiteSpace(Tone.Name)) 190 | { 191 | Tone.Name = Tone.Number.ToString(); 192 | } 193 | Buffer[o + (int)ePut.Name0] = (byte)((Tone.Name.Length > 0) ? Tone.Name[0] : 0); 194 | Buffer[o + (int)ePut.Name1] = (byte)((Tone.Name.Length > 1) ? Tone.Name[1] : 0); 195 | Buffer[o + (int)ePut.Name2] = (byte)((Tone.Name.Length > 2) ? Tone.Name[2] : 0); 196 | Buffer[o + (int)ePut.Name3] = (byte)((Tone.Name.Length > 3) ? Tone.Name[3] : 0); 197 | Buffer[o + (int)ePut.Name4] = (byte)((Tone.Name.Length > 4) ? Tone.Name[4] : 0); 198 | Buffer[o + (int)ePut.Name5] = (byte)((Tone.Name.Length > 5) ? Tone.Name[5] : 0); 199 | Buffer[o + (int)ePut.Name6] = (byte)((Tone.Name.Length > 6) ? Tone.Name[6] : 0); 200 | Buffer[o + (int)ePut.Name7] = (byte)((Tone.Name.Length > 7) ? Tone.Name[7] : 0); 201 | Buffer[o + (int)ePut.Name8] = (byte)((Tone.Name.Length > 8) ? Tone.Name[8] : 0); 202 | Buffer[o + (int)ePut.Name9] = (byte)((Tone.Name.Length > 9) ? Tone.Name[9] : 0); 203 | Buffer[o + (int)ePut.Name10] = (byte)((Tone.Name.Length > 10) ? Tone.Name[10] : 0); 204 | Buffer[o + (int)ePut.Name11] = (byte)((Tone.Name.Length > 11) ? Tone.Name[11] : 0); 205 | Buffer[o + (int)ePut.Name12] = (byte)((Tone.Name.Length > 12) ? Tone.Name[12] : 0); 206 | Buffer[o + (int)ePut.Name13] = (byte)((Tone.Name.Length > 13) ? Tone.Name[13] : 0); 207 | Buffer[o + (int)ePut.Name14] = (byte)((Tone.Name.Length > 14) ? Tone.Name[14] : 0); 208 | Buffer[o + (int)ePut.Name15] = (byte)((Tone.Name.Length > 15) ? Tone.Name[15] : 0); 209 | } 210 | } 211 | 212 | 213 | 214 | public static bool IsValid(byte[] Buffer) 215 | { 216 | return (Buffer[0x00] == (byte)'C' 217 | && Buffer[0x01] == (byte)'c' 218 | && Buffer[0x02] == (byte)'n' 219 | && Buffer[0x03] == (byte)'K' 220 | && Buffer[0x08] == (byte)'F' 221 | && Buffer[0x09] == (byte)'B' 222 | && Buffer[0x0a] == (byte)'C' 223 | && Buffer[0x0b] == (byte)'h' 224 | && Buffer[0x0f] == 1 225 | && Buffer[0x10] == (byte)'V' 226 | && Buffer[0x11] == (byte)'O' 227 | && Buffer[0x12] == (byte)'P' 228 | && Buffer[0x13] == (byte)'M' 229 | && Buffer[0x17] == 1 230 | && Buffer[0x1b] == 0x80 231 | && Buffer[0x9e] == 0x23 232 | && Buffer[0x9f] == 0x80 233 | ); 234 | } 235 | 236 | 237 | 238 | public static void Reader(string Path, Option @Option) 239 | { 240 | var Buffer = ReadByte(Path); 241 | if (Buffer.Length == FxbLength() && IsValid(Buffer)) 242 | { 243 | Tone vTone = new Tone(); 244 | 245 | var BufferMuc = ""; 246 | var BufferDat = Dat.New(); 247 | var BufferFmp = ""; 248 | var BufferPmd = ""; 249 | var BufferFMtrial = FMtrial.New(); 250 | 251 | for (int i = 0; i < ToneLength(); ++i) 252 | { 253 | Get(ref vTone, Buffer, i); 254 | 255 | if (Option.bMuc) Muc.Put(vTone, ref BufferMuc); 256 | if (Option.bDat) Dat.Put(vTone, ref BufferDat); 257 | if (Option.bFmp) Fmp.Put(vTone, ref BufferFmp); 258 | if (Option.bPmd) Pmd.Put(vTone, ref BufferPmd); 259 | if (Option.bFMtrial) FMtrial.Put(vTone, ref BufferFMtrial); 260 | } 261 | 262 | if (Option.bMuc) Muc.Writer(Path, BufferMuc); 263 | if (Option.bDat) Dat.Writer(Path, BufferDat); 264 | if (Option.bFmp) Fmp.Writer(Path, BufferFmp); 265 | if (Option.bPmd) Pmd.Writer(Path, BufferPmd); 266 | if (Option.bFMtrial) FMtrial.Writer(Path, BufferFMtrial); 267 | } 268 | } 269 | 270 | 271 | 272 | public static void Reader(string[] aPath, Option @Option) 273 | { 274 | foreach (var Path in aPath) 275 | { 276 | if (!String.IsNullOrWhiteSpace(Path) && Extension(Path) == ".fxb") Reader(Path, Option); 277 | } 278 | } 279 | 280 | 281 | 282 | public static void Writer(string Path, byte[] Buffer) 283 | { 284 | Buffer[0x00] = (byte)'C'; 285 | Buffer[0x01] = (byte)'c'; 286 | Buffer[0x02] = (byte)'n'; 287 | Buffer[0x03] = (byte)'K'; 288 | Buffer[0x08] = (byte)'F'; 289 | Buffer[0x09] = (byte)'B'; 290 | Buffer[0x0a] = (byte)'C'; 291 | Buffer[0x0b] = (byte)'h'; 292 | Buffer[0x0f] = 1; 293 | Buffer[0x10] = (byte)'V'; 294 | Buffer[0x11] = (byte)'O'; 295 | Buffer[0x12] = (byte)'P'; 296 | Buffer[0x13] = (byte)'M'; 297 | Buffer[0x17] = 1; 298 | Buffer[0x1b] = 0x80; 299 | Buffer[0x9e] = 0x23; 300 | Buffer[0x9f] = 0x80; 301 | 302 | WriteByte(ChangeExtension(Path, ".fxb"), Buffer); 303 | } 304 | } 305 | } 306 | -------------------------------------------------------------------------------- /FM-SoundConvertor/bin/Release/FM-SoundConvertor.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DM-88/FM-SoundConvertor/ddd0da726279b60a9f0832edd9dbed335bc2540f/FM-SoundConvertor/bin/Release/FM-SoundConvertor.exe -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 D.M.88 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FM-SoundConvertor 2 | [MUCOM88](https://onitama.tv/mucom88/) に付属している、FmToneEditor で作成した音色を活用する為の、Windows用コマンドラインツールです。 3 | 4 | 以下の音色定義を相互変換します。 5 | ||入出力拡張子|入力定義|出力定義| 6 | |:-:|:-:|:-:|:-:| 7 | |MUCOM88|.muc|MUCOM形式
mmldrv形式|MUCOM形式| 8 | |MUCOM88音色ファイル|.dat|dat形式|dat形式| 9 | |FMP|.mwi|旧式
F形式
FA形式
FC形式|FA形式| 10 | |PMD|.mml|PMD形式|PMD形式| 11 | |VOPM|.fxb|fxb形式|fxb形式| 12 | |FM trial v4.3|.fxb|fxb形式|fxb形式| 13 | 14 | 実行ファイルのダウンロードは[こちら](https://github.com/DM-88/FM-SoundConvertor/blob/master/FM-SoundConvertor/bin/Release/FM-SoundConvertor.exe) 15 | 16 |
17 | 18 | # 使い方 19 | ~~~ 20 | FM-SoundConvertor.exe 変換オプション 入力ファイル 21 | 22 | 変換オプション 23 | -muc 拡張子が .muc ではない入力ファイルの音色定義を、MUCOM形式に変換し .muc ファイルを出力します。 24 | -dat 拡張子が .dat ではない入力ファイルの音色定義を、dat形式に変換し .dat ファイルを出力します。 25 | -fmp 拡張子が .mwi ではない入力ファイルの音色定義を、FA形式に変換し .mwi ファイルを出力します。 26 | -pmd 拡張子が .mml ではない入力ファイルの音色定義を、PMD形式に変換し .mml ファイルを出力します。 27 | -vopm 拡張子が .fxb ではない入力ファイルの音色定義を、fxb形式に変換し .fxb ファイルを出力します。 28 | -fmtrial 拡張子が .fxb ではない入力ファイルの音色定義を、fxb形式に変換し .fxb ファイルを出力します。 29 | 30 | 変換オプションと入力ファイルは、複数個の指定が可能です。 31 | 注意:-vopm と -fmtrial は、同じ拡張子のファイルを出力してしまうので、併用できません。 32 | ~~~ 33 | 34 |
35 | 36 | # 共通仕様 37 | 以下の条件の音色定義は無効と解釈し、出力しません。 38 | * 音色番号が 0 ~ 255 の範囲外 39 | * VOPM の場合は、0 ~ 127 の範囲外 40 | * 全オペレーターの AR が 0 41 | 42 |
43 | 44 | # MUCOM88 音色番号解釈の独自仕様 45 | 音色番号を無記入にすると、直前の音色番号+1 として解釈します。 46 | ~~~ 47 | ;初回は音色番号0 と解釈する 48 | @:{ 49 | 6, 2 50 | 22, 22, 0, 14, 7, 16, 1, 1, 0 51 | 17, 11, 0, 14, 3, 57, 1, 15, 7 52 | 21, 10, 4, 14, 2, 20, 1, 0, 2 53 | 31, 0, 4, 15, 0, 0, 1, 1, 5,"Bass"} 54 | 55 | ;指定された音色番号10 と解釈する 56 | @10:{ 57 | 7, 3 58 | 26, 25, 0, 14, 2, 15, 3, 0, 1 59 | 25, 16, 10, 14, 6, 15, 3, 0, 7 60 | 23, 23, 10, 14, 10, 0, 3, 1, 4 61 | 31, 12, 20, 15, 1, 0, 0, 2, 5,"Kick"};o2c 62 | 63 | ;連続した音色番号11 と解釈する 64 | @:{ 65 | 7, 5 66 | 24, 21, 0, 14, 3, 3, 0, 15, 0 67 | 31, 14, 16, 15, 1, 0, 0, 5, 3 68 | 31, 11, 15, 15, 1, 0, 0, 7, 7 69 | 31, 16, 20, 15, 1, 0, 0, 9, 4,"Snare"};o1g 70 | ~~~ 71 | 独自の音色ライブラリの編集や、楽曲用の音色セットが作りやすくなるかなと。 72 | 73 |
74 | 75 | # その他 76 | Windows環境での不要なファイルを嫌い、.NET Framework で作成しましたが、.NET Core への転用は容易かと思います。 77 | 78 | 音色定義に特化した簡易パーサーの為、ユースケースによっては正常に変換できない場合があるかもしれません。 79 | 80 | 自分用に作ったので、気の利いたものではありませんが、何かのお役に立てば幸いです。 81 | --------------------------------------------------------------------------------