From 7268979931db2015bb2126cb013f8f69d0f9ffa1 Mon Sep 17 00:00:00 2001 From: Hiroyuki Adachi Date: Sat, 15 Oct 2022 19:11:24 +0900 Subject: [PATCH] refactor: #1 keeping codes clean. --- Meowziq.Midi/Midi/Manager.cs | 2 +- Meowziq.View/FormMain.cs | 42 ++++++++++++++++++------------------ Meowziq/Core/Note.cs | 2 +- Meowziq/Env.cs | 2 ++ Meowziq/IO/IOUtils.cs | 35 ++++++++++++++++++++++++++++++ Meowziq/Value/Validater.cs | 2 +- 6 files changed, 61 insertions(+), 24 deletions(-) create mode 100644 Meowziq/IO/IOUtils.cs diff --git a/Meowziq.Midi/Midi/Manager.cs b/Meowziq.Midi/Midi/Manager.cs index b1b3c0b..66c0a95 100644 --- a/Meowziq.Midi/Midi/Manager.cs +++ b/Meowziq.Midi/Midi/Manager.cs @@ -17,7 +17,7 @@ namespace Meowziq.Midi { /// - /// midi class using Sanford.Multimedia.Midi + /// MIDI class using Sanford.Multimedia.Midi /// /// h.adachi (STUDIO MeowToon) public class Manager { diff --git a/Meowziq.View/FormMain.cs b/Meowziq.View/FormMain.cs index 61cd186..ca4eb4d 100644 --- a/Meowziq.View/FormMain.cs +++ b/Meowziq.View/FormMain.cs @@ -121,7 +121,7 @@ async void buttonLoad_Click(object sender, EventArgs e) { } /// - /// converts the song data to smf. + /// converts the song data to SMF. /// async void buttonConvert_Click(object sender, EventArgs e) { try { @@ -142,7 +142,7 @@ async void buttonConvert_Click(object sender, EventArgs e) { } /// - /// throws midi data to the device. + /// throws MIDI data to the device. /// /// /// + depends on the conductor.midi and is only called every 30 ticks.
@@ -150,14 +150,14 @@ async void buttonConvert_Click(object sender, EventArgs e) { /// + variable named tick defines to be always an absolute value.
///
/// - /// is it possible to independently implement the timing of message transmission to the midi device? + /// is it possible to independently implement the timing of message transmission to the MIDI device? /// void sequencer_ChannelMessagePlayed(object sender, ChannelMessageEventArgs e) { if (Sound.Stopping) { return; } if (Visible) { State.Tick = _sequencer.Position - 1; // NOTE: tick position comes with 1, 31, so subtract 1 in advance. if (State.SameTick) { return; }; - // midi message processing. + // MIDI message processing. Midi.Message.ApplyTick(tick: State.Repeat.Tick, load: loadSong); // switches every 2 beats. MEMO: considers syncopation. var list = Midi.Message.GetBy(tick: State.Repeat.Tick); // gets the list of midi messages. if (list is not null) { @@ -188,7 +188,7 @@ void sequencer_ChannelMessagePlayed(object sender, ChannelMessageEventArgs e) { /// loads a song data fully while stopped. /// /// - /// also called from smf output. + /// also called from SMF output. /// async Task buildSong(bool smf = false) { var name = "------------"; @@ -225,7 +225,7 @@ await Task.Run(action: () => { catch (Exception ex) { if (!_ex_message.Equals(ex.Message)) { // if the error message is different, _ = Task.Factory.StartNew(action: () => { // displays an error dialog. - _result = MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Stop); + _result = MessageBox.Show(text: ex.Message, caption: "Error", buttons: MessageBoxButtons.OK, icon: MessageBoxIcon.Stop); if (_result is DialogResult.OK) { // when closed with ok. _ex_message = string.Empty; // initializes the flag and show the dialog again if necessary. } @@ -250,12 +250,12 @@ void buildResourse(int tick, bool current = true, bool smf = false) { PlayerLoader.PhraseList = PhraseLoader.Build(target: current ? Cache.Current.PhraseStream : Cache.Valid.PhraseStream); PlayerLoader.Build(target: current ? Cache.Current.PlayerStream : Cache.Valid.PlayerStream).ForEach(x => { x.Song = song; // sets song data. - x.Build(tick: tick, smf: smf); // builds midi data. + x.Build(tick: tick, smf: smf); // builds MIDI data. }); } /// - /// converts the song to smf and output as a file. + /// converts the song to SMF and output as a file. /// /// /// stop playing the song. @@ -267,7 +267,7 @@ async Task convertSong() { /// var message = "PLEASE WAIT"; IObservable timer = Observable.Timer(dueTime: TimeSpan.FromSeconds(1), period: TimeSpan.FromSeconds(1)); - IDisposable disposer = timer.Subscribe(x => { + IDisposable disposer = timer.Subscribe(onNext: x => { Log.Info($"converting the song.. ({x})"); Invoke(method: (MethodInvoker) (() => { var dot = (x % 2) == 0 ? "*" : "-"; @@ -275,7 +275,7 @@ async Task convertSong() { })); }); /// - /// midi data generation. + /// MIDI data generation. /// Midi.Message.Clear(); var song_name = await buildSong(smf: true); @@ -288,29 +288,29 @@ async Task convertSong() { conductor_track.Insert(position: 0, new MetaMessage(MetaType.Tempo, Value.Converter.ToByteTempo(State.Tempo))); conductor_track.Insert(position: 0, new MetaMessage(MetaType.TrackName, Value.Converter.ToByteArray(State.Name))); conductor_track.Insert(position: 0, new MetaMessage(MetaType.Copyright, Value.Converter.ToByteArray(State.Copyright))); - State.TrackList.ForEach(x => { + State.TrackList.ForEach(action: x => { var ch_track = Multi.Get(index: x.MidiCh); ch_track.Insert(position: 0, new MetaMessage(MetaType.TrackName, Value.Converter.ToByteArray(x.Name))); ch_track.Insert(position: 0, new MetaMessage(MetaType.ProgramName, Value.Converter.ToByteArray(x.Instrument))); // FIXME: not reflected? }); /// - /// applies midi data. + /// applies MIDI data. /// for (var index = 0; Midi.Message.Has(tick: index * 30); index++) { // loops every 30 ticks. var tick = index * 30; // manually generates 30 ticks. var list = Midi.Message.GetBy(tick: tick); // gets list of messages. if (list is not null) { - list.ForEach(x => Multi.Get(index: x.MidiChannel).Insert(position: tick, message: x)); + list.ForEach(action: x => Multi.Get(index: x.MidiChannel).Insert(position: tick, message: x)); } } /// - /// smf file export. + /// SMF file export. /// _sequence.Load("./data/conductor.mid"); // TODO: need this? _sequence.Clear(); _sequence.Format = 1; _sequence.Add(item: conductor_track); // adds conductor track. - Multi.List.Where(x => x.Length > 1).ToList().ForEach(x => _sequence.Add(item: x)); // adds channel tracks. + Multi.List.Where(predicate: x => x.Length > 1).ToList().ForEach(action: x => _sequence.Add(item: x)); // adds channel tracks. _sequence.Save($"./data/{song_dir}/{song_name}.mid"); Invoke(method: (MethodInvoker) (() => _textbox_song_name.Text = song_name));// restores the song name. disposer.Dispose(); // discard timer. @@ -327,7 +327,7 @@ async Task startSound() { Midi.Message.Clear(); _textbox_song_name.Text = await buildSong(); Facade.CreateConductor(sequence: _sequence); - _sequence.Load("./data/conductor.mid"); // FIXME: to const value. + _sequence.Load(CONDUCTOR_MIDI); // FIXME: to const value. _sequencer.Position = 0; _sequencer.Start(); _label_play.ForeColor = Lime; @@ -345,7 +345,7 @@ async Task stopSound() { return await Task.Run(function: () => { Sound.Stopping = true; Enumerable.Range(start: MIDI_TRACK_BASE, count: MIDI_TRACK_COUNT).ToList().ForEach( - x => _midi.OutDevice.Send(new ChannelMessage(ChannelCommand.Controller, x, 120)) + action: x => _midi.OutDevice.Send(new ChannelMessage(ChannelCommand.Controller, x, 120)) ); Sound.Stopping = false; Sound.Playing = false; @@ -408,7 +408,7 @@ MethodInvoker updateDisplay(State.Item16beat item) { MethodInvoker resetDisplay() { return () => { Enumerable.Range(start: 0, count: 88).ToList().ForEach( - x => _piano_control.Send(message: new ChannelMessage(command: ChannelCommand.NoteOff, midiChannel: 1, data1: x, data2: 0)) + action: x => _piano_control.Send(message: new ChannelMessage(command: ChannelCommand.NoteOff, midiChannel: 1, data1: x, data2: 0)) ); _label_play.ForeColor = DimGray; _label_modulation.ForeColor = DimGray; @@ -434,7 +434,7 @@ static class Facade { // public static Methods [verb] /// - /// creates and outputs an smf file for tempo control. + /// creates and outputs an SMF file for tempo control. /// public static void CreateConductor(Sequence sequence) { MetaMessage tempo = new(type: MetaType.Tempo, data: Value.Converter.ToByteTempo(tempo: State.Tempo)); @@ -445,10 +445,10 @@ public static void CreateConductor(Sequence sequence) { track.Insert(position: tick, message: new ChannelMessage(command: ChannelCommand.NoteOn, midiChannel: 0, data1: 64, data2: 0)); track.Insert(position: tick + 30, message: new ChannelMessage(command: ChannelCommand.NoteOff, midiChannel: 0, data1: 64, data2: 0)); } - sequence.Load("./data/conductor.mid"); // TODO: need this? // FIXME: to const value. + sequence.Load(CONDUCTOR_MIDI); // FIXME: still need for tempo. sequence.Clear(); sequence.Add(item: track); - sequence.Save($"./data/conductor.mid"); // smf file export for tempo control. // FIXME: to const value. + sequence.Save(CONDUCTOR_MIDI); // SMF file export for tempo control. } } diff --git a/Meowziq/Core/Note.cs b/Meowziq/Core/Note.cs index e8ea082..aa89ef8 100644 --- a/Meowziq/Core/Note.cs +++ b/Meowziq/Core/Note.cs @@ -77,7 +77,7 @@ public int Gate { } /// - /// midi note strength. + /// MIDI note strength. /// /// /// + not provide modify operations. diff --git a/Meowziq/Env.cs b/Meowziq/Env.cs index 48c1f1d..0e9cfd7 100644 --- a/Meowziq/Env.cs +++ b/Meowziq/Env.cs @@ -34,5 +34,7 @@ public static class Env { public static readonly int NOTE_RESOLUTION = 480; public static readonly string COUNT_PATTERN = "count"; + + public static readonly string CONDUCTOR_MIDI = "./data/conductor.mid"; } } diff --git a/Meowziq/IO/IOUtils.cs b/Meowziq/IO/IOUtils.cs new file mode 100644 index 0000000..5d2c333 --- /dev/null +++ b/Meowziq/IO/IOUtils.cs @@ -0,0 +1,35 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +using System.IO; + +namespace Meowziq.IO { + /// + /// IO utils functions. + /// h.adachi (STUDIO MeowToon) + public static class IOUtils { + /// + /// creates a directory if necessary. + /// + public static DirectoryInfo MakeDirectoryIfNecessary(string target) { + string directory = Path.GetDirectoryName(target); + bool exists = Directory.Exists(directory); + if (!exists) { + return Directory.CreateDirectory(directory); + } + return null; + } + } +} diff --git a/Meowziq/Value/Validater.cs b/Meowziq/Value/Validater.cs index e4bf56e..38af9b5 100644 --- a/Meowziq/Value/Validater.cs +++ b/Meowziq/Value/Validater.cs @@ -63,7 +63,7 @@ internal static string Filter(string target) { /// public static class Converter { /// - /// converts numeric BPM to tempo information for smf. + /// converts numeric BPM to tempo information for SMF. /// /// /// BPM = 120 (1分あたり四分音符が120個) の場合、