Пример #1
0
        public void Save(Stream stream)
        {
            EndianReader writer = new EndianReader(stream, Endianness.BigEndian);

            writer.Write(0x4D546864);
            writer.Write((uint)6);

            writer.Write((ushort)Type);
            writer.Write((ushort)Tracks.Count);
            if (Division is TicksPerBeatDivision)
            {
                writer.Write((Division as TicksPerBeatDivision).TicksPerBeat);
            }
            else
            {
                writer.Write((ushort)(0x8000 | ((Division as FramesPerSecondDivision).FramesPerSecond << 8) | (Division as FramesPerSecondDivision).TicksPerFrame));
            }
            foreach (Track track in Tracks)
            {
                writer.Write(0x4D54726B);

                MemoryStream memory  = new MemoryStream();
                EndianReader mwriter = new EndianReader(memory, Endianness.BigEndian);

                foreach (Event e in track.Events)
                {
                    Mid.WriteVariable(memory, (int)e.DeltaTime);
                    if (e is MetaEvent)
                    {
                        mwriter.Write((byte)0xFF);
                        mwriter.Write(e.Type);
                        Mid.WriteVariable(memory, (int)(e as MetaEvent).Data.Length);
                        mwriter.Write((e as MetaEvent).Data);
                    }
                    else
                    {
                        ChannelEvent c = e as ChannelEvent;
                        mwriter.Write((byte)((c.Type << 4) | c.Channel));
                        mwriter.Write(c.Parameter1);
                        if (e.Type != 0xC && e.Type != 0xD)
                        {
                            mwriter.Write(c.Parameter2);
                        }
                    }
                }

                writer.Write((uint)memory.Length);
                memory.Position = 0;
                Util.StreamCopy(stream, memory);
            }
        }
Пример #2
0
        public Mid ToMid()
        {
            Mid mid = new Mid();

            mid.Type     = Mid.MidiType.Uniform;
            mid.Division = Division;

            Mid.Track beat = new Mid.Track();
            beat.Events.Add(new Mid.MetaEvent()
            {
                DeltaTime = 0,
                Type      = 0x03,
                Data      = (Name == null || Name.Length == 0) ? Util.Encoding.GetBytes("rawksd") : Util.Encoding.GetBytes(Name)
            });

            List <Event> events = new List <Event>();

            events.AddRange(BPM.ToArray());
            events.AddRange(Signature.ToArray());
            events.Sort(new EventComparer());
            ulong delta = 0;

            foreach (Event e in events)
            {
                if (e is TimeSignatureEvent)
                {
                    TimeSignatureEvent sig = e as TimeSignatureEvent;
                    beat.Events.Add(new Mid.MetaEvent()
                    {
                        DeltaTime = (uint)(sig.Time - delta), Type = 0x58, Data = new byte[] { sig.Numerator, sig.Denominator, sig.Metronome, sig.NumberOf32ndNotes }
                    });
                }
                else if (e is TempoEvent)
                {
                    TempoEvent bpm  = e as TempoEvent;
                    byte[]     mpqn = new byte[3];
                    Array.Copy(BigEndianConverter.GetBytes(bpm.MicrosecondsPerBeat), 1, mpqn, 0, 3);
                    beat.Events.Add(new Mid.MetaEvent()
                    {
                        DeltaTime = (uint)(bpm.Time - delta), Type = 0x51, Data = mpqn
                    });
                }
                delta = e.Time;
            }
            beat.Events.Add(new Mid.MetaEvent()
            {
                DeltaTime = 0, Type = 0x2F, Data = new byte[0]
            });
            mid.Tracks.Add(beat);
            foreach (Track t in Tracks)
            {
                events.Clear();
                t.Comments.ForEach(e => { if (e.Type == TextEvent.TextEventType.Unknown)
                                          {
                                              e.Type = TextEvent.TextEventType.Comment;
                                          }
                                   });
                t.Lyrics.ForEach(e => { if (e.Type == TextEvent.TextEventType.Unknown)
                                        {
                                            e.Type = TextEvent.TextEventType.Lyric;
                                        }
                                 });
                t.Markers.ForEach(e => { if (e.Type == TextEvent.TextEventType.Unknown)
                                         {
                                             e.Type = TextEvent.TextEventType.Marker;
                                         }
                                  });
                events.AddRange(t.Notes.ToArray());
                events.AddRange(t.Comments.ToArray());
                events.AddRange(t.Markers.ToArray());
                events.AddRange(t.Lyrics.ToArray());
                events.Sort(new EventComparer());
                delta = 0;
                Mid.Track track = new Mid.Track();
                track.Events.Add(new Mid.MetaEvent()
                {
                    DeltaTime = 0, Type = 0x03, Data = Util.Encoding.GetBytes(t.Name)
                });

                List <NoteEvent> OpenNotes = new List <NoteEvent>();
                foreach (Event e in events)
                {
__fuck_labels_opennotesagain:
                    foreach (NoteEvent n in OpenNotes)
                    {
                        if (n.Time + n.Duration <= e.Time)
                        {
                            track.Events.Add(new Mid.ChannelEvent()
                            {
                                DeltaTime = (uint)(n.Time + n.Duration - delta), Channel = n.Channel, Type = 0x8, Parameter1 = n.Note, Parameter2 = n.ReleaseVelocity
                            });
                            delta = n.Time + n.Duration;
                            OpenNotes.Remove(n);
                            goto __fuck_labels_opennotesagain;                             // Yeah, too lazy to make a ToRemove list
                        }
                    }
                    if (e is NoteEvent)
                    {
                        NoteEvent n = e as NoteEvent;

                        NoteEvent overlap = OpenNotes.Find(n2 => n2.Note == n.Note);
                        if (overlap != null)                           // Stretch the open note over the colliding note
                        {
                            overlap.Duration = Math.Max(overlap.Duration, n.Time + n.Duration - overlap.Time);
                            OpenNotes.Sort(new NoteEventComparer());
                            continue;
                        }
                        else
                        {
                            OpenNotes.Insert(0, n);
                            OpenNotes.Sort(new NoteEventComparer());
                            track.Events.Add(new Mid.ChannelEvent()
                            {
                                DeltaTime = (uint)(n.Time - delta), Channel = n.Channel, Type = 0x9, Parameter1 = n.Note, Parameter2 = n.Velocity
                            });
                        }
                    }
                    else if (e is TextEvent)
                    {
                        TextEvent l = e as TextEvent;
                        track.Events.Add(new Mid.MetaEvent()
                        {
                            DeltaTime = (uint)(l.Time - delta), Type = (byte)l.Type, Data = Util.Encoding.GetBytes(l.Text)
                        });
                    }
                    else if (e is TextEvent)
                    {
                        TextEvent c = e as TextEvent;
                        track.Events.Add(new Mid.MetaEvent()
                        {
                            DeltaTime = (uint)(c.Time - delta), Type = 0x1, Data = Util.Encoding.GetBytes(c.Text)
                        });
                    }
                    delta = e.Time;
                }
                foreach (NoteEvent n in OpenNotes)
                {
                    track.Events.Add(new Mid.ChannelEvent()
                    {
                        DeltaTime = (uint)(n.Time + n.Duration - delta), Channel = n.Channel, Type = 0x8, Parameter1 = n.Note, Parameter2 = n.ReleaseVelocity
                    });
                    delta = n.Time + n.Duration;
                }

                track.Events.Add(new Mid.MetaEvent()
                {
                    DeltaTime = 0, Type = 0x2F, Data = new byte[0]
                });

                mid.Tracks.Add(track);
            }

            return(mid);
        }
Пример #3
0
        public static Midi Create(Mid mid)
        {
            Midi midi = new Midi();

            midi.Division = mid.Division as Mid.TicksPerBeatDivision;
            List <NoteEvent> OpenNotes = new List <NoteEvent>();

            foreach (Mid.Track t in mid.Tracks)
            {
                Track track = new Track();
                ulong time  = 0;
                foreach (Mid.Event e in t.Events)
                {
                    time += e.DeltaTime;
                    if (e is Mid.MetaEvent)
                    {
                        Mid.MetaEvent meta = e as Mid.MetaEvent;
                        if (meta.Type == 0x3)
                        {
                            track.Name = Util.Encoding.GetString(meta.Data);
                            if (midi.Name == null)
                            {
                                midi.Name = track.Name;
                            }
                        }
                        else if (meta.Type == 0x1)
                        {
                            track.Comments.Add(new TextEvent(time, Util.Encoding.GetString(meta.Data)));
                        }
                        else if (meta.Type == 0x5)
                        {
                            track.Lyrics.Add(new TextEvent(time, Util.Encoding.GetString(meta.Data)));
                        }
                        else if (meta.Type == 0x6)
                        {
                            track.Markers.Add(new TextEvent(time, Util.Encoding.GetString(meta.Data)));
                        }
                        else if (meta.Type == 0x51)
                        {
                            byte[] data = new byte[4];
                            meta.Data.CopyTo(data, 1);
                            midi.BPM.Add(new TempoEvent(time, BigEndianConverter.ToUInt32(data)));
                        }
                        else if (meta.Type == 0x58)
                        {
                            midi.Signature.Add(new TimeSignatureEvent(time, meta.Data[0], meta.Data[1], meta.Data[2], meta.Data[3]));
                        }
                        else if (meta.Type == 0x2F)
                        {
                        }                         //else
                                                  //throw new Exception("OHSHIT");
                    }
                    else if (e is Mid.ChannelEvent)
                    {
                        Mid.ChannelEvent c = e as Mid.ChannelEvent;
                        if (c.Type == 0x8 || (c.Type == 0x9 && c.Parameter2 == 0))                           // Note off
                        // ( A note on with velocity 0 acts as a note off )
                        {
                            NoteEvent note = OpenNotes.Find(n => n.Note == c.Parameter1);
                            if (note != null)
                            {
                                note.Duration        = time - note.Time;
                                note.ReleaseVelocity = c.Parameter2;
                                OpenNotes.Remove(note);
                            }
                        }
                        else if (c.Type == 0x9)                             // Note on
                        {
                            NoteEvent note = new NoteEvent(time, c.Channel, c.Parameter1, c.Parameter2, 0);
                            OpenNotes.Add(note);
                            track.Notes.Add(note);
                        }
                        else if (c.Type == 0xC)                             // Program Change
                        {
                            InstrumentEvent change = new InstrumentEvent(time, c.Channel, c.Parameter1, c.Parameter2);
                            track.Instruments.Add(change);
                        }
                        else if (c.Type == 0xB)                             // Controller
                        {
                            switch (c.Parameter1)
                            {
                            case 0x00:                                     // Bank Select
                                BankEvent bank = new BankEvent(time, c.Channel, c.Parameter2);
                                track.Banks.Add(bank);
                                break;
                            }
                        }                         //else
                                                  //throw new Exception("OHSHIT");
                    }
                }

                if (track.Notes.Count > 0 || track.Comments.Count > 0 || track.Lyrics.Count > 0)
                {
                    midi.Tracks.Add(track);
                }
            }

            return(midi);
        }
Пример #4
0
        public static Mid Create(Stream stream)
        {
            EndianReader reader = new EndianReader(stream, Endianness.BigEndian);

            if (reader.ReadUInt32() != 0x4D546864)
            {
                return(null);
            }
            if (reader.ReadUInt32() != 6)
            {
                return(null);
            }

            Mid mid = new Mid();

            mid.Type = (MidiType)reader.ReadUInt16();
            ushort tracks   = reader.ReadUInt16();
            ushort division = reader.ReadUInt16();

            if ((division & 0x8000) == 0)
            {
                mid.Division = new TicksPerBeatDivision((ushort)(division & 0x7FFF));
            }
            else
            {
                mid.Division = new FramesPerSecondDivision()
                {
                    FramesPerSecond = (byte)((division & 0x7F00) >> 8),
                    TicksPerFrame   = (byte)(division & 0x00FF)
                }
            };
            for (int i = 0; i < tracks; i++)
            {
                Track track = new Track();
                if (reader.ReadUInt32() != 0x4D54726B)
                {
                    return(null);
                }
                uint size = reader.ReadUInt32();
                uint pos  = (uint)stream.Position;

                byte oldb = 0;
                while (stream.Position - pos < size)
                {
                    uint delta = (uint)Mid.ReadVariable(stream);
                    byte b     = reader.ReadByte();

                    if (b == 0xFF)                       // Meta Event
                    {
                        MetaEvent e = new MetaEvent();
                        e.DeltaTime = delta;
                        e.Type      = reader.ReadByte();

                        uint length = (uint)Mid.ReadVariable(stream);
                        e.Data = reader.ReadBytes((int)length);
                        track.Events.Add(e);
                        //if (e.Type == 0x2F) // End Track meta event
                        //break;
                    }
                    else if (b == 0xF0)
                    {
                        throw new NotImplementedException();
                    }
                    else if (b == 0xF7)
                    {
                        throw new NotImplementedException();
                    }
                    else                         // Channel Event
                    {
                        ChannelEvent e = new ChannelEvent();
                        e.DeltaTime = delta;

                        if ((b & 0x80) == 0)
                        {
                            e.Parameter1 = b;
                            b            = oldb;
                        }
                        else
                        {
                            oldb         = b;
                            e.Parameter1 = (byte)reader.ReadByte();
                        }

                        e.Type = (byte)(b >> 4);

                        e.Channel = (byte)(b & 0x0F);
                        if (e.Type != 0xC && e.Type != 0xD)
                        {
                            e.Parameter2 = (byte)reader.ReadByte();
                        }
                        track.Events.Add(e);
                    }
                }

                mid.Tracks.Add(track);
            }

            return(mid);
        }