├── .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 |
--------------------------------------------------------------------------------