public void Flip_Should_Flip_From_Middle_When_Changing_Octave_Is_Not_Possible() { //Arrange MidiService target = new MidiService(); Stream midiStream = File.Open($"{TestFilesPath}flip_from_middle_0_127.mid", FileMode.Open); const int firstNote = 127; const int secondNote = 64; const int thirdNote = 63; const int lastNote = 0; //Act Stream flippedMidiStream = target.Flip(midiStream, 0); //Assert MidiSequence flippedMidi = MidiSequence.Open(flippedMidiStream); int firstFlippedNote = flippedMidi.Tracks[2].Events.OfType <OnNoteVoiceMidiEvent>().First().Note; int secondFlippedNote = flippedMidi.Tracks[2].Events.OfType <OnNoteVoiceMidiEvent>().ElementAt(1).Note; int thirdFlippedNote = flippedMidi.Tracks[2].Events.OfType <OnNoteVoiceMidiEvent>().ElementAt(2).Note; int lastFlippedNote = flippedMidi.Tracks[2].Events.OfType <OnNoteVoiceMidiEvent>().Last().Note; //Midi should be flipped around the middle Assert.AreEqual(firstNote, lastFlippedNote); Assert.AreEqual(secondNote, thirdFlippedNote); Assert.AreEqual(thirdNote, secondFlippedNote); Assert.AreEqual(firstFlippedNote, lastNote); }
static void Main(string[] args) { if (args.Length != 1) { Console.WriteLine("Usage: SeparateTracks.exe filename.mid"); Console.WriteLine(" filename.mid = MIDI file for which to generate code"); Console.WriteLine(); return; } if (!File.Exists(args[0])) { Console.WriteLine("Error: file {0} not found", args[0]); return; } try { MidiSequence sequence; using (Stream inputStream = File.OpenRead(args[0])) { sequence = MidiSequence.Open(inputStream); } for (int i = 0; i < sequence.Tracks.Count; i++) { MidiSequence newSequence = new MidiSequence(Format.Zero, sequence.Division); newSequence.Tracks.Add(sequence.Tracks[i]); using (Stream outputStream = File.OpenWrite(args[0] + "." + i + ".mid")) { newSequence.Save(outputStream); } } } catch (Exception exc) { Console.Error.WriteLine("Error: {0}", exc.Message); } }
static void Main(string[] args) { if (args.Length != 1) { Console.WriteLine("Usage: ExtractLyrics.exe filename.mid"); Console.WriteLine(" filename.mid = MIDI file from which to extract lyric events text"); Console.WriteLine(); return; } if (!File.Exists(args[0])) { Console.WriteLine("Error: file {0} not found", args[0]); return; } try { MidiSequence sequence; using (Stream inputStream = File.OpenRead(args[0])) { sequence = MidiSequence.Open(inputStream); } string[] lyrics = sequence.SelectMany(track => track.Events).OfType <LyricTextMetaMidiEvent>().Select(e => e.Text.Trim()).ToArray(); Console.WriteLine(lyrics.Length > 0 ? string.Join(" ", lyrics) : "(no lyrics found)"); } catch (Exception exc) { Console.Error.WriteLine("Error: {0}", exc.Message); } }
static void Main(string[] args) { if (args.Length != 1) { Console.WriteLine("Usage: GenerateMidiCode.exe filename.mid"); Console.WriteLine(" filename.mid = MIDI file for which to generate code"); Console.WriteLine(); return; } if (!File.Exists(args[0])) { Console.WriteLine("Error: file {0} not found", args[0]); return; } try { MidiSequence sequence; using (Stream inputStream = File.OpenRead(args[0])) { sequence = MidiSequence.Open(inputStream); } CSharpCodeGenerator.Write(sequence, "GeneratedCode", "Example", Console.Out); } catch (Exception exc) { Console.Error.WriteLine("Error: {0}", exc.Message); } }
static void Main(string[] args) { if (args.Length != 1) { Console.WriteLine("Usage: DumpMidi.exe filename.mid"); Console.WriteLine(" filename.mid = MIDI file from which to extract lyric events text"); Console.WriteLine(); return; } if (!File.Exists(args[0])) { Console.WriteLine("Error: file {0} not found", args[0]); return; } try { using (Stream inputStream = File.OpenRead(args[0])) { Console.WriteLine(MidiSequence.Open(inputStream)); } } catch (Exception exc) { Console.Error.WriteLine("Error: {0}", exc.Message); } }
private void RoundtripEventsCore(MidiSequence seq1) { string tmpPath = Utils.SaveToTempFile(seq1); using (var s = File.OpenRead(tmpPath)) { Utils.AssertAreEqual(seq1, MidiSequence.Open(s)); } File.Delete(tmpPath); }
public static void StrawberryPiano() { //File.WriteAllText("StrawberryPiano.bat", $"ffmpeg.exe -framerate 25 -i {Path.GetFullPath("StrawberryPianoFrames")}/frame*.png -r 25 -pix_fmt yuv420p out.mp4"); var folder = @"C:\Users\alexm\Downloads"; HashSet <byte> pressed = new HashSet <byte>(); using (var f = new FileStream(@$ "{ folder}\Strawberry Piano.mid", FileMode.Open)) { var m = MidiSequence.Open(f); List <NoteVoiceMidiEvent> notes = new List <NoteVoiceMidiEvent>(); foreach (var t in m.Tracks) { notes.AddRange(t.Events.OfType <NoteVoiceMidiEvent>()); } { //Convert to absolute time long previous = 0; foreach (var n in notes) { var dt = n.DeltaTime; n.DeltaTime = (dt + previous) / 30; previous += dt; } Console.WriteLine($"Note count: {notes.Count} "); Console.WriteLine($"Last note: {notes.Last().DeltaTime} ms"); Console.WriteLine($"Last note: {notes.Last().DeltaTime / 1000} seconds"); } var dir = @$ "{folder}\Strawberry Piano Frames"; Directory.CreateDirectory(dir); int frameRate = 25; Console.WriteLine($"Frames: {notes.Last().DeltaTime * frameRate / 1000} frames"); using (StrawberryVisualizer v = new StrawberryVisualizer(@$ "Strawberry Piano Note.png", $"StrawberryPianoFrames")) { KeyTracker keys = new KeyTracker(); int index = 0; int i = 0; while (index < notes.Count) { double time = i * 1000 / frameRate; i++; var now = notes.Skip(index).TakeWhile(n => n.DeltaTime <= time); keys.Process(now); index += now.Count(); v.AddFrame(keys.pressed); //Console.WriteLine($"Time: {time}"); //Console.WriteLine($"Index: {index}"); } Process.Start(Path.GetFullPath("StrawberryPiano.bat")); } }
private void importMIDIToolStripMenuItem_Click(object sender, EventArgs e) { try { fileSelector.Title = "Open MIDI file"; fileSelector.ShowDialog(); var myfile = fileSelector.FileName; var b = File.OpenRead(myfile); currentSequence = MidiSequence.Open(b); } catch (Exception E) { Console.WriteLine("heck\n{0}", E.ToString()); MessageBox.Show("Not a valid midi file."); } }
static void Main(string[] args) { if (args.Length != 2) { Console.WriteLine("Usage: TransposeMidi.exe filename.mid steps"); Console.WriteLine(" filename.mid = MIDI file to be transposed"); Console.WriteLine(" steps = Number of steps to transpose, positive or negative"); Console.WriteLine(); return; } if (!File.Exists(args[0])) { Console.WriteLine("Error: file {0} not found", args[0]); return; } int steps; if (!int.TryParse(args[1], out steps)) { Console.WriteLine("Error: invalid number of steps {0}", args[1]); return; } try { MidiSequence sequence; using (Stream inputStream = File.OpenRead(args[0])) { sequence = MidiSequence.Open(inputStream); } sequence.Transpose(steps); string outputPath = args[0] + ".transposed.mid"; using (Stream outputStream = File.OpenWrite(outputPath)) { sequence.Save(outputStream); } Console.WriteLine("Transposed MIDI written to: {0}", outputPath); } catch (Exception exc) { Console.Error.WriteLine("Error: {0}", exc.Message); } }
public static MidiSequence LoadMidiFile(string fileName) { MidiSequence sequence = null; try { using (Stream inputStream = File.OpenRead(fileName)) { sequence = MidiSequence.Open(inputStream); } } catch (Exception exc) { Debug.LogError("Error: " + exc.Message); } return(sequence); }
public void Flip_Should_Lower_Octave_When_Flipping_Above_127() { //Arrange MidiService target = new MidiService(); Stream midiStream = File.Open($"{TestFilesPath}out_of_range_127.mid", FileMode.Open); const int firstNote = 127; const int lastNote = 115; //Act Stream flippedMidiStream = target.Flip(midiStream, 0); //Assert MidiSequence flippedMidi = MidiSequence.Open(flippedMidiStream); int firstFlippedNote = flippedMidi.Tracks[2].Events.OfType <OnNoteVoiceMidiEvent>().First().Note; int lastFlippedNote = flippedMidi.Tracks[2].Events.OfType <OnNoteVoiceMidiEvent>().Last().Note; //Midi should be flipped while also having been lowered by one octave Assert.AreEqual(firstNote, lastFlippedNote); Assert.AreEqual(firstFlippedNote, lastNote); }
public void LoadMIDI(string path) { try { using (System.IO.Stream inputStream = System.IO.File.OpenRead(path)) { sequence = MidiSequence.Open(inputStream); } var lbl = (Label)GetNode("SC/Label"); lbl.Text = (string)sequence.ToString(); Stop(); //Stop the player and clear the channels. //Set the MIDI sequence for the player. player.sequence = sequence; Clock.Reset(sequence.Tracks.Count); //RESET THE CLOCK. This properly sets the number of tracks for the clock to check. AudioStreamGenerator streamGenerator = (AudioStreamGenerator)player.Stream; player.parser.ParseSequence(sequence, streamGenerator.MixRate); } catch (MidiParser.MidiParserException e) { GD.Print("WARNING: Encountered a problem parsing MIDI.\n", e.ToString()); } }
public IActionResult UploadFile() { try { var file = Request.Form.Files[0]; string folderName = "Upload"; string webRootPath = "C:/"; string newPath = Path.Combine(webRootPath, folderName); if (!Directory.Exists(newPath)) { Directory.CreateDirectory(newPath); } if (file.Length > 0) { string fileName = ContentDispositionHeaderValue.Parse(file.ContentDisposition).FileName.Trim('"'); string fullPath = Path.Combine(newPath, fileName); using (var stream = new FileStream(fullPath, FileMode.Create)) { file.CopyTo(stream); } MidiSequence sequence; using (Stream inputStream = System.IO.File.OpenRead(fullPath)) { sequence = MidiSequence.Open(inputStream); } int index = -1; for (int i = 0; i < sequence.Tracks.Count && index == -1; i++) { for (int j = 0; j < sequence.Tracks[i].Events.Count; j++) { if (sequence.Tracks[i].Events[j].ToString().Contains("0x51")) { index = i; } } } if (index > 0) { foreach (MidiEvent Event in sequence.Tracks[0].Events) { if (Event.ToString().Contains("0x2F")) { sequence.Tracks[0].Events.Remove(Event); break; } } sequence.Tracks[0].Events.AddRange(sequence.Tracks[index].Events); sequence.Tracks.Remove(sequence.Tracks[index]); } using (Stream outputStream = System.IO.File.OpenWrite(fullPath)) { sequence.Save(outputStream); } FileStream fs = new FileStream(fullPath, FileMode.Open); return(File(fs, "application/vnd.android.package-archive", fileName)); } return(null); } catch (System.Exception ex) { return(null); } }
static void Main(string[] args) { double toneDistance = 1; double beatDistance = 1; double n; List <string> lines = new List <string>(); lines.Add("INSERT PUNCHHOLE"); string path; double note; double ticks; double time; if (args.Length == 0) { Console.WriteLine("Usage: WintergatanLaserMIDI <filename.mid> [Tone Distance (mm)] [Beat Distance (mm)]"); Console.WriteLine("\tfilename.mid = MIDI file for which to generate code"); Console.WriteLine("\tTone Distance = Defines the distance between every note-pitch."); Console.WriteLine("\tBeat Distance = Defines how far away the beats are from each other."); Console.WriteLine(); return; } if (!File.Exists(args[0])) { Console.WriteLine("Error: file {0} not found", args[0]); return; } path = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase) + "\\" + args[0] + ".scr"; path = new Uri(path).LocalPath; if (File.Exists(path)) { File.Delete(path); } if (args.Length == 2 && !string.IsNullOrEmpty(args[1])) { if (double.TryParse(args[1], out n)) { toneDistance = n; } else { Console.WriteLine("Tone Distance must be a number!"); return; } } if (args.Length == 3 && !string.IsNullOrEmpty(args[2])) { if (double.TryParse(args[2], out n)) { beatDistance = n; } else { Console.WriteLine("Beat Distance must be a number!"); return; } } try { MidiSequence sequence = MidiSequence.Open(File.OpenRead(args[0])); ticks = (double)sequence.Division; foreach (MidiTrack track in sequence) { track.Events.ConvertDeltasToTotals(); foreach (MidiEvent ev in track.Events) { if (ev.GetType().ToString() == "MidiSharp.Events.Voice.Note.OnNoteVoiceMidiEvent") { NoteVoiceMidiEvent nvme = ev as NoteVoiceMidiEvent; note = (double)nvme.Note; time = (double)ev.DeltaTime; Console.WriteLine(((time / ticks) * beatDistance) + "," + ((note - 60.0d) * toneDistance)); if (lines.Count >= 2) { lines.Add(" " + ((time / ticks) * beatDistance) + "," + ((note - 60.0d) * toneDistance) + ",0 1 1 0"); } else { lines.Add(((time / ticks) * beatDistance) + "," + ((note - 60.0d) * toneDistance) + ",0 1 1 0"); } } } } System.IO.File.WriteAllLines(path, lines); } catch (Exception exc) { Console.Error.WriteLine("Error: {0}", exc.Message); } }
static void Main(string[] args) { int[] codeMidi = new int[] { 0, 0, 0, 0, 0, 0, 0 }; if (args.Length != 1) { Console.WriteLine("Usage: TransposeMidi.exe filename.mid steps"); Console.WriteLine(" filename.mid = MIDI file to be transposed"); Console.WriteLine(" steps = Number of steps to transpose, positive or negative"); Console.WriteLine(); return; } string originpath = System.IO.Directory.GetCurrentDirectory(); string[] op = originpath.Split('\\'); originpath = ""; for (int i = 0; i < (op.Length) - 4; i++) { originpath += op[i]; originpath += "\\"; } if (!File.Exists(args[0])) { Console.WriteLine("Error: file {0} not found", args[0]); return; } /* int steps; * if (!int.TryParse(args[1], out steps)) * { * Console.WriteLine("Error: invalid number of steps {0}", args[1]); * return; * }*/ try { MidiSequence sequence; using (Stream inputStream = File.OpenRead(args[0])) { sequence = MidiSequence.Open(inputStream); } for (int i = 0; i < 8; i++) { MidiSequence newSequence = sequence.Trim(1857 * i, 1857 * (i + 1) + 10); // sequence.Transpose(steps); using (Stream outputStream = File.OpenWrite(originpath + @"\\toUnity\\" + i + "\\" + "originmelody." + i + ".trimed.mid.txt")) { newSequence.Save(outputStream); } foreach (MidiTrack track in newSequence) { for (int j = 1; j < track.Events.Count - 1; j = j + 2) { //Console.WriteLine(track.Events[i].ToString().IndexOf("G4")); //Console.WriteLine(track.Events[i].ToString()); //Console.WriteLine(track.Events[i].ToString().Substring(5,7)); char spt = '\t'; string[] spstring = track.Events[j].ToString().Split(spt); switch (spstring[2]) { case "C6": codeMidi[2] = codeMidi[2] + 3; codeMidi[5] = codeMidi[5] + 2; codeMidi[0]++; break; case "D6": codeMidi[3] = codeMidi[3] + 3; codeMidi[6] = codeMidi[6] + 2; codeMidi[1]++; break; case "E6": codeMidi[4] = codeMidi[4] + 3; codeMidi[0] = codeMidi[0] + 2; codeMidi[2]++; break; case "F6": codeMidi[5] = codeMidi[5] + 3; codeMidi[1] = codeMidi[1] + 2; codeMidi[3]++; break; case "G6": codeMidi[6] = codeMidi[6] + 3; codeMidi[2] = codeMidi[2] + 2; codeMidi[4]++; break; case "A6": codeMidi[0] = codeMidi[0] + 3; codeMidi[5] = codeMidi[5] + 2; codeMidi[3]++; break; case "B6": codeMidi[1] = codeMidi[1] + 3; codeMidi[6] = codeMidi[5] + 2; codeMidi[4]++; break; default: break; } //Console.WriteLine(spstring[2]); } int maxValue = codeMidi.Max(); String path = System.IO.Directory.GetCurrentDirectory() + @"\\toUnity\\" + i; DirectoryInfo dirInfo = new DirectoryInfo(path); if (dirInfo.Exists == false) { Directory.CreateDirectory(path); } for (int j = 0; j < 8; j++) { if (codeMidi[j] == maxValue) { //Console.WriteLine(j); List <String> MyFiles = Directory.GetFiles(originpath + @"\Resources\\" + j).ToList(); foreach (string file in MyFiles) { FileInfo mFile = new FileInfo(file); // to remove name collisions if (new FileInfo(originpath + @"\\toUnity\\" + i + "\\" + mFile.Name).Exists == false) { mFile.CopyTo(originpath + @"\\toUnity\\" + i + "\\" + mFile.Name + ".txt"); } } MyFiles.Clear(); MyFiles = null; break; } } System.Array.Clear(codeMidi, 0, 7); } } } /*string outputPath = args[0] + ".transposed.mid"; * using (Stream outputStream = File.OpenWrite(outputPath)) { * sequence.Save(outputStream); * } * Console.WriteLine("Transposed MIDI written to: {0}", outputPath);*/ // catch (Exception exc) { Console.Error.WriteLine("Error: {0}", exc.Message); } }
public MidiInterpretation(Stream midiStream, INoteSegmentProvider noteSegmentProvider) { MidiFile = MidiSequence.Open(midiStream); TempoCollection = new TempoCollection(MidiFile.TicksPerBeatOrFrame); NoteSegments = new List <NoteSegment>(); // Calculate the absolute times for all events in each track // Also pair note on events with note off events for (int track = 0; track < MidiFile.Tracks.Count; track++) { // Key is a tuple of Channel and Note var onEvents = new Dictionary <(byte Channel, int Note), Queue <MidiEventWithTime <OnNoteVoiceMidiEvent> > >(); // Time in ticks long time = 0; foreach (var midiEvent in MidiFile.Tracks[track].Events) { if (midiEvent.DeltaTime > 0) { time += midiEvent.DeltaTime; } if (midiEvent is TempoMetaMidiEvent tempoEvent) { TempoCollection.AddTempoEvent(time, tempoEvent); } else if (midiEvent is OnNoteVoiceMidiEvent onNote) { var onNoteIdentifier = (onNote.Channel, onNote.Note); if (!onEvents.ContainsKey(onNoteIdentifier)) { onEvents[onNoteIdentifier] = new Queue <MidiEventWithTime <OnNoteVoiceMidiEvent> >(); } // If the Velocity is 0, we are turning off a note using another OnNote (see https://stackoverflow.com/a/43322203/1984712) // Basically, if a NoteOn event is received with a velocity of 0, we effectively have a NoteOff event. if (onNote.Velocity == 0) { if (onEvents.TryGetValue(onNoteIdentifier, out var midiEventQueue)) { NoteSegments.Add(noteSegmentProvider.CreateNoteSegment( TempoCollection, track, midiEventQueue.Dequeue(), // Get the first matching On Event that matches this identifier new MidiEventWithTime <OffNoteVoiceMidiEvent>(time, CreateOffNoteFromOnNote(onNote)) )); } else { System.Diagnostics.Debug.WriteLine(string.Format("OnNote event with Velocity = 0 at [ Channel: {0}; Note: {1} ] is missing a corresponding OnNote event with Velocity > 0.", onNoteIdentifier.Channel, onNoteIdentifier.Note)); } } // Otherwise, queue the note so that an OffNote can match to it else { onEvents[onNoteIdentifier].Enqueue(new MidiEventWithTime <OnNoteVoiceMidiEvent>(time, onNote)); } } else if (midiEvent is OffNoteVoiceMidiEvent offNote) { var offNoteIdentifer = (offNote.Channel, offNote.Note); if (onEvents.TryGetValue(offNoteIdentifer, out var midiEventQueue)) { NoteSegments.Add(noteSegmentProvider.CreateNoteSegment( TempoCollection, track, midiEventQueue.Dequeue(), // Get the first matching On Event new MidiEventWithTime <OffNoteVoiceMidiEvent>(time, offNote)) ); } else { System.Diagnostics.Debug.WriteLine(string.Format("OffNote event at [ Channel: {0}; Note: {1} ] is missing a corresponding OnNote event.", offNoteIdentifer.Channel, offNoteIdentifer.Note)); } } } if (onEvents.Any(e => e.Value.Count > 0)) { System.Diagnostics.Debug.WriteLine("One or more OnNote events weren't paired with an OffNote event."); } } TotalDurationSamples = NoteSegments.Max(segment => segment.StartSample + segment.DurationSamples); }
public Stream Flip(Stream midiFile, int octaveChangeOption) { //Load midi file MidiSequence midi = MidiSequence.Open(midiFile); //The anchor note to flip everything else around float anchorNote = midi.Tracks .Where(t => t.Events.OfType <NoteVoiceMidiEvent>().Any() && t.Events.OfType <NoteVoiceMidiEvent>().Any(n => n.Channel != 9 && n.Channel != 10)) .Select(t => t.Events.OfType <NoteVoiceMidiEvent>().First()) .OrderBy(e => e.DeltaTime).GroupBy(e => e.DeltaTime).First() //Find the first note .Min(e => e.Note); //Order by note number if there are notes playing at the same time int highestNote = midi.Tracks .Where(t => t.Events.OfType <NoteVoiceMidiEvent>().Any(n => n.Channel != 9 && n.Channel != 10)) .SelectMany(t => t.Events.OfType <NoteVoiceMidiEvent>()) .Max(e => e.Note); int lowestNote = midi.Tracks .Where(t => t.Events.OfType <NoteVoiceMidiEvent>().Any(n => n.Channel != 9 && n.Channel != 10)) .SelectMany(t => t.Events.OfType <NoteVoiceMidiEvent>()) .Min(e => e.Note); int octaveChange = 0; //Global octave change required for this sequence octaveChangeOption *= Constants.Octave; bool flipFromMiddle = false; //If octave changes aren't possible, sequence needs to be flipped around the middle //Check if flipping won't make the notes go out of range (0-127) TODO: Test all cases if (anchorNote - lowestNote > highestNote - anchorNote) { //Flipping might make notes go past 127, if so, try to decrease octave float outOfRange = anchorNote + (anchorNote - lowestNote); if (outOfRange > Constants.MaxMidiNote) { while (outOfRange + octaveChange > Constants.MaxMidiNote) { octaveChange -= Constants.Octave; } if (lowestNote + octaveChange < Constants.MinMidiNote) { //Out of range on the other side now, flip everything around the middle note instead and don't change octave flipFromMiddle = true; octaveChange = 0; } } } else { //Flipping might make notes go below 0, if so, try to increase octave float outOfRange = anchorNote - (highestNote - anchorNote); if (outOfRange < Constants.MinMidiNote) { while (outOfRange + octaveChange < Constants.MinMidiNote) { octaveChange += Constants.Octave; } if (highestNote + octaveChange > Constants.MaxMidiNote) { //Out of range on the other side now, flip everything around the middle note instead and don't change octave flipFromMiddle = true; octaveChange = 0; } } } if (flipFromMiddle) //Changing octaves is not possible, flip everything around the middle { anchorNote = (float)(highestNote - lowestNote) / 2; } //Flip all notes foreach (MidiTrack track in midi.Tracks) { IEnumerable <NoteVoiceMidiEvent> noteEvents = track.OfType <NoteVoiceMidiEvent>().Where(n => n.Channel != 9 && n.Channel != 10); if (!noteEvents.Any()) { continue; //Nothing to flip } foreach (NoteVoiceMidiEvent onNoteEvent in noteEvents) { onNoteEvent.Note = (byte)(anchorNote + anchorNote - onNoteEvent.Note + octaveChange + octaveChangeOption); } } //Create flipped MIDI-file Stream flippedMidiStream = new MemoryStream(); midi.Save(flippedMidiStream); flippedMidiStream.Position = 0; return(flippedMidiStream); }