예제 #1
0
 void SendMidiMessage(SmfMessage m)
 {
     if ((m.Value & 0xFF) == 0xF0)
         WriteSysEx (0xF0, m.Data);
     else if ((m.Value & 0xFF) == 0xF7)
         WriteSysEx (0xF7, m.Data);
     else if ((m.Value & 0xFF) == 0xFF)
         return; // meta. Nothing to send.
     else
         output.Write (0, new MidiMessage (m.StatusByte, m.Msb, m.Lsb));
 }
예제 #2
0
        // Override it to customize track dispatcher. It would be
        // useful to split note messages out from non-note ones,
        // to ease data reading.
        public virtual int GetTrackID(SmfMessage e)
        {
            switch (e.Event.EventType)
            {
            case SmfEvent.Meta:
            case SmfEvent.SysEx1:
            case SmfEvent.SysEx2:
                return(-1);

            default:
                return(e.Event.Channel);
            }
        }
예제 #3
0
 public virtual void ProcessMessage(SmfMessage msg)
 {
     switch (msg.MessageType) {
     case SmfMessage.NoteOn:
         Channels [msg.Channel].NoteVelocity [msg.Msb] = msg.Lsb;
         break;
     case SmfMessage.NoteOff:
         Channels [msg.Channel].NoteVelocity [msg.Msb] = 0;
         break;
     case SmfMessage.PAf:
         Channels [msg.Channel].PAfVelocity [msg.Msb] = msg.Lsb;
         break;
     case SmfMessage.CC:
         // FIXME: handle RPNs and NRPNs by DTE
         switch (msg.Msb) {
         case SmfCC.NrpnMsb:
         case SmfCC.NrpnLsb:
             Channels [msg.Channel].DteTarget = DteTarget.Nrpn;
             break;
         case SmfCC.RpnMsb:
         case SmfCC.RpnLsb:
             Channels [msg.Channel].DteTarget = DteTarget.Rpn;
             break;
         case SmfCC.DteMsb:
             Channels [msg.Channel].ProcessDte (msg.Lsb, true);
             break;
         case SmfCC.DteLsb:
             Channels [msg.Channel].ProcessDte (msg.Lsb, false);
             break;
         case SmfCC.DteIncrement:
             Channels [msg.Channel].ProcessDteIncrement ();
             break;
         case SmfCC.DteDecrement:
             Channels [msg.Channel].ProcessDteDecrement ();
             break;
         }
         Channels [msg.Channel].Controls [msg.Msb] = msg.Lsb;
         break;
     case SmfMessage.Program:
         Channels [msg.Channel].Program = msg.Msb;
         break;
     case SmfMessage.CAf:
         Channels [msg.Channel].CAf = msg.Msb;
         break;
     case SmfMessage.Pitch:
         Channels [msg.Channel].PitchBend = (short) ((msg.Msb << 7) + msg.Lsb);
         break;
     }
     if (MessageReceived != null)
         MessageReceived (msg);
 }
예제 #4
0
 SmfTrack GenerateTrack(MmlResolvedTrack source)
 {
     var rtrk = new SmfTrack ();
     int cur = 0;
     foreach (var ev in source.Events) {
         SmfEvent evt;
         if (ev.Arguments.Count == 3)
             evt = new SmfEvent (ev.Arguments [0], ev.Arguments [1], ev.Arguments [2], null);
         else if (ev.Arguments [0] == 0xFF)
             evt = new SmfEvent (ev.Arguments [0], ev.Arguments [1], 0, ev.Arguments.Skip (2).ToArray ());
         else
             evt = new SmfEvent (ev.Arguments [0], 0, 0, ev.Arguments.Skip (1).ToArray ());
         var msg = new SmfMessage (ev.Tick - cur, evt);
         rtrk.Messages.Add (msg);
         cur = ev.Tick;
     }
     rtrk.Messages.Add (new SmfMessage (0, new SmfEvent (0xFF, 0x2F, 0, new byte [0])));
     return rtrk;
 }
예제 #5
0
        public virtual void HandleEvent(SmfMessage m)
        {
            if (m.DeltaTime != 0)
            {
                var ms = GetDeltaTimeInMilliseconds(m.DeltaTime);
                time_manager.AdvanceBy(ms);
            }
            if (m.Event.StatusByte == 0xFF)
            {
                if (m.Event.Msb == SmfMetaType.Tempo)
                {
                    current_tempo = SmfMetaType.GetTempo(m.Event.Data);
                }
                else if (m.Event.Msb == SmfMetaType.TimeSignature && m.Event.Data.Length == 4)
                {
                    Array.Copy(m.Event.Data, current_time_signature, 4);
                }
            }

            OnEvent(m.Event);
            PlayDeltaTime += m.DeltaTime;
        }
예제 #6
0
파일: SMF.cs 프로젝트: atsushieno/mugene
        // FIXME: it should rather be implemented to iterate all
        // tracks with index to messages, pick the track which contains
        // the nearest event and push the events into the merged queue.
        // It's simpler, and costs less by removing sort operation
        // over thousands of events.
        SmfMusic GetMergedMessages()
        {
            IList<SmfMessage> l = new List<SmfMessage> ();

            foreach (var track in source.Tracks) {
                int delta = 0;
                foreach (var mev in track.Messages) {
                    delta += mev.DeltaTime;
                    l.Add (new SmfMessage (delta, mev.Event));
                }
            }

            if (l.Count == 0)
                return new SmfMusic () { DeltaTimeSpec = source.DeltaTimeSpec }; // empty (why did you need to sort your song file?)

            // Sort() does not always work as expected.
            // For example, it does not always preserve event
            // orders on the same channels when the delta time
            // of event B after event A is 0. It could be sorted
            // either as A->B or B->A.
            //
            // To resolve this ieeue, we have to sort "chunk"
            // of events, not all single events themselves, so
            // that order of events in the same chunk is preserved
            // i.e. [AB] at 48 and [CDE] at 0 should be sorted as
            // [CDE] [AB].

            var idxl = new List<int> (l.Count);
            idxl.Add (0);
            int prev = 0;
            for (int i = 0; i < l.Count; i++) {
                if (l [i].DeltaTime != prev) {
                    idxl.Add (i);
                    prev = l [i].DeltaTime;
                }
            }

            idxl.Sort (delegate (int i1, int i2) {
                return l [i1].DeltaTime - l [i2].DeltaTime;
                });

            // now build a new event list based on the sorted blocks.
            var l2 = new List<SmfMessage> (l.Count);
            int idx;
            for (int i = 0; i < idxl.Count; i++)
                for (idx = idxl [i], prev = l [idx].DeltaTime; idx < l.Count && l [idx].DeltaTime == prev; idx++)
                    l2.Add (l [idx]);
            //if (l.Count != l2.Count) throw new Exception (String.Format ("Internal eror: count mismatch: l1 {0} l2 {1}", l.Count, l2.Count));
            l = l2;

            // now messages should be sorted correctly.

            var waitToNext = l [0].DeltaTime;
            for (int i = 0; i < l.Count - 1; i++) {
                if (l [i].Event.Value != 0) { // if non-dummy
                    var tmp = l [i + 1].DeltaTime - l [i].DeltaTime;
                    l [i] = new SmfMessage (waitToNext, l [i].Event);
                    waitToNext = tmp;
                }
            }
            l [l.Count - 1] = new SmfMessage (waitToNext, l [l.Count - 1].Event);

            var m = new SmfMusic ();
            m.DeltaTimeSpec = source.DeltaTimeSpec;
            m.Format = 0;
            m.Tracks.Add (new SmfTrack (l));
            return m;
        }
예제 #7
0
파일: SMF.cs 프로젝트: atsushieno/mugene
 public void AddMessage(SmfMessage msg)
 {
     messages.Add (msg);
 }
예제 #8
0
 void HandleSmfMessage(SmfMessage m)
 {
     switch (m.MessageType) {
     case SmfMessage.NoteOn:
         if (m.Lsb == 0)
             goto case SmfMessage.NoteOff; // It is equivalent to note off
         int note = GetKeyIndexForNote (m.Msb);
         if (note < 0)
             break; // out of range
         key_rectangles [m.Channel, note].Fill = brush_keyon;
         keyon_meter_panel.ProcessKeyOn (m.Channel, m.Msb, m.Lsb);
         spectrum_analyzer_panel.ProcessKeyOn (m.Channel, m.Msb, m.Lsb);
         break;
     case SmfMessage.NoteOff:
         note = GetKeyIndexForNote (m.Msb);
         if (note < 0)
             break; // out of range
         Brush c = registers.Channels [m.Channel].Controls [0x40] > 63 ? brush_hold :
             IsWhiteKey (note) ? brush_white_key : brush_black_key;
         key_rectangles [m.Channel, note].Fill = c;
         break;
     case SmfMessage.Program:
         keyon_meter_panel.SetProgram (m.Channel, m.Msb);
         break;
     case SmfMessage.CC:
         switch (m.Msb) {
         case SmfCC.BankSelect:
             keyon_meter_panel.SetBank (m.Channel, m.Lsb, true);
             break;
         case SmfCC.BankSelectLsb:
             keyon_meter_panel.SetBank (m.Channel, m.Lsb, false);
             break;
         case SmfCC.Pan:
             keyon_meter_panel.SetPan (m.Channel, m.Lsb);
             break;
         case SmfCC.Volume:
             parameter_visualizers [m.Channel].Volume.SetValue (m.Lsb);
             break;
         case SmfCC.Expression:
             parameter_visualizers [m.Channel].Expression.SetValue (m.Lsb);
             break;
         case SmfCC.Rsd:
             parameter_visualizers [m.Channel].Rsd.SetValue (m.Lsb);
             break;
         case SmfCC.Csd:
             parameter_visualizers [m.Channel].Csd.SetValue (m.Lsb);
             break;
         case SmfCC.Hold:
             parameter_visualizers [m.Channel].Hold.Value = (m.Lsb > 63);
             if (m.Lsb < 64 && key_rectangles != null) { // reset held keys to nothing
                 for (int i = 0; i < 128; i++) {
                     note = GetKeyIndexForNote (i);
                     if (note < 0)
                         continue;
                     var rect = key_rectangles [m.Channel, note];
                     if (rect == null)
                         continue;
                     if (((SolidColorBrush) rect.Fill).Color == color_hold)
                         key_rectangles [m.Channel, note].Fill = IsWhiteKey (i) ? brush_white_key : brush_black_key;
                 }
             }
             break;
         case SmfCC.PortamentoSwitch:
             parameter_visualizers [m.Channel].PortamentoSwitch.Value = (m.Lsb > 63);
             break;
         case SmfCC.Sostenuto:
             parameter_visualizers [m.Channel].Sostenuto.Value = (m.Lsb > 63);
             break;
         case SmfCC.SoftPedal:
             parameter_visualizers [m.Channel].SoftPedal.Value = (m.Lsb > 63);
             break;
         }
         break;
     case SmfMessage.Meta:
         switch (m.MetaType) {
         case SmfMetaType.TimeSignature:
             play_time_status_panel.SetTimeMeterValues (m.Data);
             break;
         case SmfMetaType.Tempo:
             foreach (var view in player_status_views)
                 view.ProcessChangeTempo ((int) ((60.0 / SmfMetaType.GetTempo (m.Data)) * 1000000.0));
             break;
         }
         break;
     }
 }
예제 #9
0
        void DrawNoteOnOff(SmfMessage m)
        {
            int note = GetKeyIndexForNote (m.Msb);
            if (note < 0)
                return; // out of range
            int octave = note / 12;
            int key = note % 12;
            int channel = m.Channel;
            bool isKeyOn = m.MessageType == SmfMessage.NoteOn && m.Lsb != 0;

            float x = octave * key_width * 7;
            float y = GetChannelYPos (channel) + ch_height - key_height;
            int k = key_to_keyboard_idx [key];
            if (IsWhiteKey (key)) {
                paint.Color = (isKeyOn ? color_keyon : color_white_key);
                canvas.DrawCircle(x + k * key_width + 3, y + 12, 2, paint);
                //keyon_meter_panel.ProcessKeyOn (m.Channel, m.Msb, m.Lsb);
                //spectrum_analyzer_panel.ProcessKeyOn (m.Channel, m.Msb, m.Lsb);
            } else {
                paint.Color = (isKeyOn ? color_keyon : color_black_key);
                int blackKeyStartX = (int) (x + (k + 0.8) * key_width);
                canvas.DrawCircle(blackKeyStartX + 2, y + 1 + 5, 1, paint);
            }
            needs_redraw = true;
        }
예제 #10
0
 public SmfEvent(int deltaTime, SmfMessage msg)
 {
     DeltaTime = deltaTime;
     Message = msg;
 }
예제 #11
0
 protected virtual void OnMessage(SmfMessage m)
 {
     if (MessageReceived != null)
         MessageReceived (m);
 }
예제 #12
0
        // FIXME: it should rather be implemented to iterate all
        // tracks with index to messages, pick the track which contains
        // the nearest event and push the events into the merged queue.
        // It's simpler, and costs less by removing sort operation
        // over thousands of events.
        SmfMusic GetMergedMessages()
        {
            IList <SmfMessage> l = new List <SmfMessage> ();

            foreach (var track in source.Tracks)
            {
                int delta = 0;
                foreach (var mev in track.Messages)
                {
                    delta += mev.DeltaTime;
                    l.Add(new SmfMessage(delta, mev.Event));
                }
            }

            if (l.Count == 0)
            {
                return new SmfMusic()
                       {
                           DeltaTimeSpec = source.DeltaTimeSpec
                       }
            }
            ;                                                                                    // empty (why did you need to sort your song file?)

            // Sort() does not always work as expected.
            // For example, it does not always preserve event
            // orders on the same channels when the delta time
            // of event B after event A is 0. It could be sorted
            // either as A->B or B->A.
            //
            // To resolve this ieeue, we have to sort "chunk"
            // of events, not all single events themselves, so
            // that order of events in the same chunk is preserved
            // i.e. [AB] at 48 and [CDE] at 0 should be sorted as
            // [CDE] [AB].

            var idxl = new List <int> (l.Count);

            idxl.Add(0);
            int prev = 0;

            for (int i = 0; i < l.Count; i++)
            {
                if (l [i].DeltaTime != prev)
                {
                    idxl.Add(i);
                    prev = l [i].DeltaTime;
                }
            }

            idxl.Sort(delegate(int i1, int i2) {
                return(l [i1].DeltaTime - l [i2].DeltaTime);
            });

            // now build a new event list based on the sorted blocks.
            var l2 = new List <SmfMessage> (l.Count);
            int idx;

            for (int i = 0; i < idxl.Count; i++)
            {
                for (idx = idxl [i], prev = l [idx].DeltaTime; idx < l.Count && l [idx].DeltaTime == prev; idx++)
                {
                    l2.Add(l [idx]);
                }
            }
//if (l.Count != l2.Count) throw new Exception (String.Format ("Internal eror: count mismatch: l1 {0} l2 {1}", l.Count, l2.Count));
            l = l2;

            // now messages should be sorted correctly.

            var waitToNext = l [0].DeltaTime;

            for (int i = 0; i < l.Count - 1; i++)
            {
                if (l [i].Event.Value != 0)                   // if non-dummy
                {
                    var tmp = l [i + 1].DeltaTime - l [i].DeltaTime;
                    l [i]      = new SmfMessage(waitToNext, l [i].Event);
                    waitToNext = tmp;
                }
            }
            l [l.Count - 1] = new SmfMessage(waitToNext, l [l.Count - 1].Event);

            var m = new SmfMusic();

            m.DeltaTimeSpec = source.DeltaTimeSpec;
            m.Format        = 0;
            m.Tracks.Add(new SmfTrack(l));
            return(m);
        }
    }
예제 #13
0
 public void AddMessage(SmfMessage msg)
 {
     messages.Add(msg);
 }
예제 #14
0
파일: SMF.cs 프로젝트: atsushieno/mugene
 // Override it to customize track dispatcher. It would be
 // useful to split note messages out from non-note ones,
 // to ease data reading.
 public virtual int GetTrackID(SmfMessage e)
 {
     switch (e.Event.EventType) {
     case SmfEvent.Meta:
     case SmfEvent.SysEx1:
     case SmfEvent.SysEx2:
         return -1;
     default:
         return e.Event.Channel;
     }
 }
예제 #15
0
 public void AddMessage(int deltaInsertAt, SmfMessage e)
 {
     e = new SmfMessage(deltaInsertAt - TotalDeltaTime, e.Event);
     Track.Messages.Add(e);
     TotalDeltaTime = deltaInsertAt;
 }
예제 #16
0
파일: SMF.cs 프로젝트: atsushieno/mugene
 public void AddMessage(int deltaInsertAt, SmfMessage e)
 {
     e = new SmfMessage (deltaInsertAt - TotalDeltaTime, e.Event);
     Track.Messages.Add (e);
     TotalDeltaTime = deltaInsertAt;
 }
예제 #17
0
        public virtual void HandleEvent(SmfMessage m)
        {
            if (m.DeltaTime != 0) {
                var ms = GetDeltaTimeInMilliseconds (m.DeltaTime);
                time_manager.AdvanceBy (ms);
            }
            if (m.Event.StatusByte == 0xFF) {
                if (m.Event.Msb == SmfMetaType.Tempo)
                    current_tempo = SmfMetaType.GetTempo (m.Event.Data);
                else if (m.Event.Msb == SmfMetaType.TimeSignature && m.Event.Data.Length == 4)
                    Array.Copy (m.Event.Data, current_time_signature, 4);
            }

            OnEvent (m.Event);
            PlayDeltaTime += m.DeltaTime;
        }