public MainPage() { this.InitializeComponent(); App.Current.Suspending += Current_Suspending; mArduino = new ArduinoManager(); mGPIO = new GPIOManager(); mGameNoteIndexs = new int[5] { 0, 0, 0, 0, 0 }; mCurrentGameNote = new MidiGameNote[5]; mIsInited = false; mIsPlaying = false; Task.Run(async() => { SMFReader r = new SMFReader(); mSMF = await r.Read(@"Assets\out.mid"); var w = new MidiDeviceWatcher(MidiOutPort.GetDeviceSelector(), Dispatcher); w.Start(); var col = w.GetDeviceInformationCollection(); var l = await DeviceInformation.FindAllAsync(MidiOutPort.GetDeviceSelector()); MIDIPort = await MidiOutPort.FromIdAsync(l[0].Id); await mArduino.Init(); await mGPIO.Init(GpioController.GetDefault()); mGPIO.MidiButtonChanged += MGPIO_MidiButtonChanged; mGPIO.JoyButtonChanged += MGPIO_JoyButtonChanged; mPlayer = new SMFPlayer(mSMF, MIDIPort); mPlayer.OnLED += Player_OnLED; mPlayer.OnBarBeatChanged += Player_BarBeatChanged; mPlayer.OnTempoChanged += Player_OnTempoChanged; mGPIO.Ack(); mIsInited = true; }); mVolTimer = new DispatcherTimer(); mVolTimer.Interval = new TimeSpan(0, 0, 0, 0, 100); mVolTimer.Tick += MVolTimer_Tick; mVolTimer.Start(); }
public SMFPlayer(SMF smf, IMidiOutPort p) { mSMF = smf; mMidi = p; }
public async Task <SMF> Read(String path) { SMF smf = new SMF(); ulong cursol = 0; var sf = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync(path); using (Stream fs = await sf.OpenStreamForReadAsync()) { SMFByte = new byte[fs.Length]; fs.Read(SMFByte, 0, SMFByte.Length); } byte[] head = ReadAsBytes(cursol, 4); cursol += 4; ulong head_len = ReadAsInt64(cursol); cursol += 4; smf.FormatType = ReadAsInt(cursol); cursol += 2; smf.TrackNum = ReadAsInt(cursol); cursol += 2; smf.TimeMode = ReadAsInt(cursol); cursol += 2; for (int i = 0; i < smf.TrackNum; i++) { byte[] track = ReadAsBytes(cursol, 4); cursol += 4; ulong track_len = ReadAsInt64(cursol); cursol += 4; ulong time = 0; for (ulong c = cursol; c < track_len + cursol;) { var dt = ReadVlen(c); c += dt.Item2; time += dt.Item1; //小節へ変換 byte dat = SMFByte[c]; if ((dat & 0xF0) == 0xF0) { byte type = SMFByte[c + 1]; c += 2; var len = ReadVlen(c); c += len.Item2; byte[] exdat = ReadAsBytes(c, len.Item1); c += len.Item1; ulong beat = time / smf.TimeMode; uint tick = (uint)(time % smf.TimeMode); switch (type) { case 0x51: smf.SystemEvents.Add(new TempoEvent(beat, tick, exdat[0], exdat[1], exdat[2])); break; case 0x58: smf.SystemEvents.Add(new MeterEvent(beat, tick, exdat[0], exdat[1], exdat[2], exdat[3])); break; case 0x59: smf.SystemEvents.Add(new KeyEvent(beat, tick, exdat[0], exdat[1])); break; } /* * * FF type len dats * FF 01-05 len text * FF 2F 00 End of Track * FF 51 03 tempo(3byte) Set Tempo テンポ。 4分音符の長さをマイクロ秒単位で表現。 * FF 58 04 nn dd cc bb Time Signature 拍子nn=分子 dd=分子(2の負のべき乗で表す) cc=メトロノーム間隔(四分音符間隔なら18H) bb=四分音符あたりの三十二分音符の数 * FFH 59H 02H sf ml Key Signature キー(調)を表す sf=正・・シャープの数 負・・フラットの数 ml=0・・・長調 1・・・短調 */ } else { byte ch = (byte)(dat & 0x0F); switch (dat & 0xF0) { case 0x80: if (ch == 0 && SMFByte[c + 2] <= 5 && smf.GameNotes[SMFByte[c + 2]].Count > 0) { foreach (var mg in smf.GameNotes[SMFByte[c + 2]]) { if (mg.Note == SMFByte[c + 1] && !mg.IsSetEnd) { mg.IsSetEnd = true; mg.EndTick = time; break; } } } else { smf.CHData[ch].Add(new NoteOFF(ch, time, SMFByte[c + 1], SMFByte[c + 2])); } c += 3; break; case 0x90: if (ch == 0 && SMFByte[c + 2] <= 5) { smf.GameNotes[SMFByte[c + 2]].Add( new MidiGameNote(time, SMFByte[c + 1])); } else { smf.CHData[ch].Add(new NoteON(ch, time, SMFByte[c + 1], SMFByte[c + 2])); } c += 3; break; case 0xB0: if (SMFByte[c + 1] == 12) { smf.SystemEvents.Add(new LEDEvent(time / smf.TimeMode, (uint)(time % smf.TimeMode), SMFByte[c + 2])); } else { smf.CHData[ch].Add(new ControleChange(ch, time, SMFByte[c + 1], SMFByte[c + 2])); } c += 3; break; case 0xC0: smf.CHData[ch].Add(new ProgramChange(ch, time, SMFByte[c + 1])); c += 2; break; case 0xE0: smf.CHData[ch].Add(new PitchBend(ch, time, SMFByte[c + 1], SMFByte[c + 2])); c += 3; break; } } } cursol += track_len; } smf.InitMidiMessage(); return(smf); }