예제 #1
0
        public MidiMusic DemoPixelMidi()
        {
            MidiMusic result = new MidiMusic();

            short noteLen = 0x03C0;
            int   offset  = 4 * noteLen;

            result.DeltaTimeSpec = noteLen;
            result.Format        = 1;

            var track_sys = GetMetaTrack(FileName);

            result.AddTrack(track_sys);

            var track = new MidiTrack();

            track.AddMessage(new MidiMessage(0, new MidiEvent(MidiEvent.Meta, 3, 0, Encoding.Default.GetBytes("Demo"))));
            var delta = new int[128];

            for (int x = 0; x < 128; x++)
            {
                var noteOn  = new MidiEvent(MidiEvent.NoteOn, (byte)x, 0x64, Encoding.Default.GetBytes(""));
                var noteOff = new MidiEvent(MidiEvent.NoteOn, (byte)x, 0x00, Encoding.Default.GetBytes(""));
                track.AddMessage(new MidiMessage(0, noteOn));
                track.AddMessage(new MidiMessage(offset, noteOff));
            }
            track.AddMessage(new MidiMessage(0, new MidiEvent(MidiEvent.Meta, 0x2F, 0, Encoding.Default.GetBytes(""))));
            result.AddTrack(track);

            return(result);
        }
예제 #2
0
    private void cutMusic(int from, int to, MidiMusic music, string outputFilename)
    {
        FileStream stream = File.Create(outputFilename);
        SmfWriter  writer = new SmfWriter(stream);

        writer.WriteHeader(music.Format, (short)music.Tracks.Count, music.DeltaTimeSpec);
        IList <MidiTrack> tracks = music.Tracks;

        for (var i = 0; i < tracks.Count; i++)
        {
            var  track          = tracks[i];
            int  passedTime     = 0;
            var  newTrack       = new MidiTrack();
            bool isFirstMessage = true;

            for (var j = 0; j < track.Messages.Count; j++)
            {
                var message = track.Messages[j];
                passedTime += message.DeltaTime;

                if (passedTime < from && message.Event.EventType != MidiEvent.NoteOn && message.Event.EventType != MidiEvent.NoteOff)
                {
                    var convertedMsg = MidiUtil.convertTimeToZero(message);
                    newTrack.AddMessage(convertedMsg);
                }
                else if (passedTime >= from && passedTime < to)
                {
                    if (isFirstMessage)
                    {
                        int newDeltaTime = passedTime - from;
                        newTrack.AddMessage(new MidiMessage(newDeltaTime, message.Event));
                        isFirstMessage = false;
                    }
                    else
                    {
                        newTrack.AddMessage(message);
                    }
                }
                else if (passedTime >= to && message.Event.EventType == MidiEvent.Meta && message.Event.MetaType == MidiMetaType.EndOfTrack)
                {
                    MidiMessage convertedMsg = MidiUtil.convertTimeToZero(message);
                    newTrack.AddMessage(convertedMsg);
                }
            }

            track = newTrack;
            // Debug.Log("Track " + (i + 1) + " Passed time:" + passedTime);
            writer.WriteTrack(track);
        }

        stream.Close();
    }
예제 #3
0
    /// Only call once per MIDI as this marks the end of the MIDI.
    /// To my knowledge it doesn't matter which track is passed.
    private void AddEndOfTrackMessage(MidiTrack track)
    {
        var evt = new MidiEvent(MidiEvent.Meta, MidiMetaType.EndOfTrack, (byte)0x00, null); // 'FF 2F 00' -> end of track
        var msg = new MidiMessage(0, evt);

        track.AddMessage(msg);
    }
예제 #4
0
 private void AddSMPTEOffsetEvent(MidiTrack track)
 {
     track.AddMessage(new MidiMessage(0, new MidiEvent(
                                          MidiEvent.Meta,
                                          MidiMetaType.SmpteOffset,
                                          (byte)0x05, // length: 5 bytes will follow
                                          new byte[] { 0x01, 0x00, 0x05, 0x00, 0x00 })));
 }
예제 #5
0
        /// <summary>
        /// Cuts track by "from" and "to" in ticks
        /// </summary>
        /// <param name="track"></param>
        /// <param name="fromTick"></param>
        /// <param name="toTick"></param>
        /// <returns></returns>
        private MidiTrack cutTrackByTicks(MidiTrack track, int fromTick, int toTick)
        {
            int       passedTicks    = 0;
            MidiTrack resultTrack    = new MidiTrack();
            bool      isFirstMessage = true;

            foreach (MidiMessage msg in track.Messages)
            {
                passedTicks += msg.DeltaTime;

                // messages before 'from' or messages after 'to':
                // Keep each message that isn't playing a note but give it a delta time of zero.
                if (passedTicks < fromTick && msg.Event.EventType != MidiEvent.NoteOn && msg.Event.EventType != MidiEvent.NoteOff ||
                    passedTicks >= toTick && msg.Event.EventType == MidiEvent.Meta && msg.Event.MetaType == MidiMetaType.EndOfTrack)
                {
                    MidiMessage convertedMsg = MidiUtil.convertTimeToZero(msg);
                    resultTrack.AddMessage(convertedMsg);
                }
                // messages within 'from' and 'to':
                // Keep these, just make sure the first message has the right time offset.
                else if (passedTicks >= fromTick && passedTicks < toTick)
                {
                    if (isFirstMessage)
                    {
                        resultTrack.AddMessage(new MidiMessage(passedTicks - fromTick, msg.Event));
                        isFirstMessage = false;
                    }
                    else
                    {
                        resultTrack.AddMessage(msg);
                    }
                }
            }


            // MidiEvent endOfTrackEvent = new MidiEvent(MidiEvent.Meta, MidiMetaType.EndOfTrack, (byte) 0x00, new byte[0]);
            // resultTrack.AddMessage(new MidiMessage(0, endOfTrackEvent));

            printTrackMessages(resultTrack);

            return(resultTrack);
        }
예제 #6
0
        private MidiTrack GetMetaTrack(string name)
        {
            var track = new MidiTrack();

            // Sequence or track name
            track.AddMessage(new MidiMessage(0, new MidiEvent(MidiEvent.Meta, 0x03, 0, Encoding.Default.GetBytes(name))));
            // Copyright notice
            track.AddMessage(new MidiMessage(0, new MidiEvent(MidiEvent.Meta, 0x02, 0, Encoding.Default.GetBytes("Copyright 2018 NetCharm"))));
            // Text event
            track.AddMessage(new MidiMessage(0, new MidiEvent(MidiEvent.Meta, 0x01, 0, Encoding.Default.GetBytes("NetCharm"))));
            // Instrument name
            //track_sys.AddMessage(new MidiMessage(0, new MidiEvent(MidiEvent.Meta, 0x04, 0, Encoding.Default.GetBytes("Piano"))));
            // Time signature
            track.AddMessage(new MidiMessage(0, new MidiEvent(MidiEvent.Meta, 0x58, 0, Encoding.Default.GetBytes("\x04\x02\x18\x08"))));
            // Key signature
            track.AddMessage(new MidiMessage(0, new MidiEvent(MidiEvent.Meta, 0x59, 0, Encoding.Default.GetBytes("\x00\x00"))));
            // Tempo setting (us/quarter-note)
            track.AddMessage(new MidiMessage(0, new MidiEvent(MidiEvent.Meta, 0x51, 0, Encoding.Default.GetBytes("\x07\xA1\x20")))); // 120  beats/minute
            //track_sys.AddMessage(new MidiMessage(0, new MidiEvent(MidiEvent.Meta, 0x51, 0, Encoding.Default.GetBytes("\x09\x27\xC0")))); // 100  beats/minute
            // End of track
            track.AddMessage(new MidiMessage(0, new MidiEvent(MidiEvent.Meta, 0x2F, 0, Encoding.Default.GetBytes(""))));

            return(track);
        }
예제 #7
0
        /// <summary>
        ///
        /// -----------------------
        /// Type    Event
        /// -----------------------
        /// 0x00    Sequence number
        /// 0x01    Text event
        /// 0x02    Copyright notice
        /// 0x03    Sequence or track name
        /// 0x04    Instrument name
        /// 0x05    Lyric text
        /// 0x06    Marker text
        /// 0x07    Cue point
        /// 0x20    MIDI channel prefix assignment
        /// 0x2F    End of track
        /// 0x51    Tempo setting
        /// 0x54    SMPTE offset
        /// 0x58    Time signature
        /// 0x59    Key signature
        /// 0x7F    Sequencer specific event
        /// -----------------------
        ///
        ///
        /// </summary>
        /// <param name="bitmap"></param>
        /// <param name="singleTrack"></param>
        /// <returns></returns>
        public MidiMusic GetPixelMidi(Bitmap bitmap, bool singleTrack = true)
        {
            MidiMusic result = null;

            if (bitmap is Bitmap)
            {
                int delta = (int)(noteLen * NoteType);

                result = new MidiMusic();
                result.DeltaTimeSpec = noteLen;
                result.Format        = 1;

                var track_sys = GetMetaTrack(FileName);
                result.AddTrack(track_sys);

                if (singleTrack)
                {
                    var track = GetPixelTrack(bitmap, FileName);
                    result.AddTrack(track);
                }
                else
                {
                    var gray = GrayScale(bitmap.Height > 128 ? Resize(bitmap, 0, 128): bitmap);
                    if (InvertSource)
                    {
                        gray = Invert(gray);
                    }

                    Color c;
                    Color co    = gray.GetPixel(0, 0);
                    int   count = 0;

                    for (int y = 0; y < gray.Height; y++)
                    {
                        count = 0;
                        var track = new MidiTrack();
                        track.AddMessage(new MidiMessage(0, new MidiEvent(MidiEvent.Meta, 0x00, 0, Encoding.Default.GetBytes($"{y}"))));
                        track.AddMessage(new MidiMessage(0, new MidiEvent(MidiEvent.Meta, 0x03, 0, Encoding.Default.GetBytes($"{FileName}_{y}"))));
                        for (int x = 0; x < gray.Width; x++)
                        {
                            c = gray.GetPixel(x, y);
                            byte velocity = 0x40;
                            var  alpha    = CalcAlpha(c, co, out velocity);
                            if (alpha > 0)
                            {
                                var noteOn  = new MidiEvent(MidiEvent.NoteOn, 0x40, velocity, Encoding.Default.GetBytes(""));
                                var noteOff = new MidiEvent(MidiEvent.NoteOn, 0x40, 0x00, Encoding.Default.GetBytes(""));
                                track.AddMessage(new MidiMessage(count * delta, noteOn));
                                track.AddMessage(new MidiMessage(delta, noteOff));
                                count = 0;
                            }
                            else
                            {
                                count++;
                            }
                        }
                        track.AddMessage(new MidiMessage(0, new MidiEvent(MidiEvent.Meta, 0x2F, 0, Encoding.Default.GetBytes(""))));
                        result.AddTrack(track);
                    }
                }
            }
            Music = result;

            return(result);
        }
예제 #8
0
        private MidiTrack GetPixelTrack(Bitmap bitmap, string name, bool grayscale = true, bool invert = true)
        {
            MidiTrack result = null;

            if (bitmap is Bitmap)
            {
                result = new MidiTrack();

                int delta = (int)(noteLen * NoteType);

                var gray = bitmap.Height > 128 ? Resize(bitmap, 0, 128): bitmap;
                gray = grayscale ? GrayScale(gray) : gray;
                if (InvertSource && invert)
                {
                    gray = Invert(gray);
                }

                Color c;
                Color co    = gray.GetPixel(0, 0);
                int   count = 0;

                int[,] om = new int[gray.Width, gray.Height];
                Dictionary <int[, ], byte> nm = new Dictionary <int[, ], byte>();

                count = 0;

                bool[] blank = new bool[gray.Width];
                for (int i = 0; i < blank.Length; i++)
                {
                    blank[i] = true;
                }
                int marginL = 0;
                int marginR = 0;
                for (int x = 0; x < gray.Width; x++)
                {
                    //for (int y = 0; y < gray.Height; y++)
                    for (int y = gray.Height - 1; y >= 0; y--)
                    {
                        c = gray.GetPixel(x, y);
                        byte velocity = 0x40;
                        var  alpha    = CalcAlpha(c, co, out velocity);
                        if (alpha > 0)
                        {
                            om[x, y] = count * delta;
                            blank[x] = false;
                            if (marginL == 0)
                            {
                                marginL = x;
                            }
                            count = 0;
                            break;
                        }
                    }
                    if (blank[x])
                    {
                        count++;
                    }
                }
                marginR = count;

                //int offset = (int)(gray.Height / 2.0 - NoteCenter);
                int offset = (int)(NoteCenter - gray.Height / 2.0);
                if (offset < 0)
                {
                    offset = 0;
                }

                var track = new MidiTrack();
                track.AddMessage(new MidiMessage(0, new MidiEvent(MidiEvent.Meta, 0x03, 0, Encoding.Default.GetBytes(name))));
                track.AddMessage(new MidiMessage(0, new MidiEvent(MidiEvent.NoteOff, (byte)NoteCenter, 0, Encoding.Default.GetBytes(""))));

                double[] alphav = new double[128];
                for (int x = 0; x < gray.Width; x++)
                {
                    if (blank[x])
                    {
                        continue;
                    }

                    bool IsDelta = false;
                    for (int y = gray.Height - 1; y >= 0; y--)
                    {
                        c = gray.GetPixel(x, y);
                        byte velocity = 0x40;
                        alphav[y] = CalcAlpha(c, co, out velocity);
                        if (alphav[y] > 0)
                        {
                            var noteOn = new MidiEvent(MidiEvent.NoteOn, (byte)(gray.Height - y - 1 + offset), velocity, Encoding.Default.GetBytes(""));
                            if (IsDelta)
                            {
                                track.AddMessage(new MidiMessage(0, noteOn));
                            }
                            else
                            {
                                track.AddMessage(new MidiMessage(om[x, y], noteOn));
                                IsDelta = true;
                            }
                        }
                    }
                    IsDelta = false;
                    for (int y = 0; y < gray.Height; y++)
                    {
                        if (alphav[y] > 0)
                        {
                            var noteOff = new MidiEvent(MidiEvent.NoteOn, (byte)(gray.Height - y - 1 + offset), 0x00, Encoding.Default.GetBytes(""));
                            if (IsDelta)
                            {
                                track.AddMessage(new MidiMessage(0, noteOff));
                            }
                            else
                            {
                                track.AddMessage(new MidiMessage(delta, noteOff));
                                IsDelta = true;
                            }
                        }
                    }
                }

                track.AddMessage(new MidiMessage(marginR * delta, new MidiEvent(MidiEvent.NoteOff, (byte)NoteCenter, 0, Encoding.Default.GetBytes(""))));
                track.AddMessage(new MidiMessage(0, new MidiEvent(MidiEvent.Meta, 0x2F, 0, Encoding.Default.GetBytes(""))));

                result = track;
            }

            return(result);
        }