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); }
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(); }
/// 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); }
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 }))); }
/// <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); }
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); }
/// <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); }
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); }