/// <summary> /// Adds the specified collection of objects to <see cref="TrackChunk"/>. /// </summary> /// <param name="trackChunk"><see cref="TrackChunk"/> to add objects to.</param> /// <param name="timedObjects">Objects to add to <paramref name="trackChunk"/>.</param> /// <exception cref="ArgumentNullException"> /// <para>One of the following errors occured:</para> /// <list type="bullet"> /// <item> /// <description><paramref name="trackChunk"/> is <c>null</c>.</description> /// </item> /// <item> /// <description><paramref name="timedObjects"/> is <c>null</c>.</description> /// </item> /// </list> /// </exception> public static void AddObjects(this TrackChunk trackChunk, IEnumerable <ITimedObject> timedObjects) { ThrowIfArgument.IsNull(nameof(trackChunk), trackChunk); ThrowIfArgument.IsNull(nameof(timedObjects), timedObjects); trackChunk.Events.AddObjects(timedObjects); }
private static TrackChunk AddEventsOfNote( TrackChunk chunkito, Note n, byte channel) { var noteOn = new NoteOnEvent() { Channel = new FourBitNumber(channel), DeltaTime = n.StartSinceBeginningOfSongInTicks, NoteNumber = new SevenBitNumber(n.Pitch), Velocity = new SevenBitNumber(n.Volume) }; chunkito.Events.Add(noteOn); var noteOff = new NoteOffEvent() { Channel = new FourBitNumber(channel), DeltaTime = n.EndSinceBeginningOfSongInTicks, NoteNumber = new SevenBitNumber(n.Pitch) }; chunkito.Events.Add(noteOff); foreach (var pb in n.PitchBending) { var p = new PitchBendEvent() { Channel = new FourBitNumber(channel), DeltaTime = pb.TicksSinceBeginningOfSong, PitchValue = pb.Pitch }; chunkito.Events.Add(p); } return(chunkito); }
/// <summary> /// Creates an instance of the <see cref="ChordsManager"/> initializing it with the /// events collection of the specified track chunk, notes tolerance and comparison delegate for events /// that have same time. /// </summary> /// <param name="trackChunk"><see cref="TrackChunk"/> that holds chords to manage.</param> /// <param name="notesTolerance">Notes tolerance that defines maximum distance of notes from the /// start of the first note of a chord. Notes within this tolerance will be considered as a chord.</param> /// <param name="sameTimeEventsComparison">Delegate to compare events with the same absolute time.</param> /// <returns>An instance of the <see cref="ChordsManager"/> that can be used to manage /// chords represented by the <paramref name="trackChunk"/>.</returns> /// <exception cref="ArgumentNullException"><paramref name="trackChunk"/> is null.</exception> /// <exception cref="ArgumentOutOfRangeException"><paramref name="notesTolerance"/> is negative.</exception> public static ChordsManager ManageChords(this TrackChunk trackChunk, long notesTolerance = 0, Comparison <MidiEvent> sameTimeEventsComparison = null) { ThrowIfArgument.IsNull(nameof(trackChunk), trackChunk); ThrowIfNotesTolerance.IsNegative(nameof(notesTolerance), notesTolerance); return(trackChunk.Events.ManageChords(notesTolerance, sameTimeEventsComparison)); }
public static IEnumerable <ILengthedObject> GetNotesAndRests(this TrackChunk trackChunk, RestSeparationPolicy restSeparationPolicy) { ThrowIfArgument.IsNull(nameof(trackChunk), trackChunk); ThrowIfArgument.IsInvalidEnumValue(nameof(restSeparationPolicy), restSeparationPolicy); return(trackChunk.GetNotes().GetNotesAndRests(restSeparationPolicy)); }
/// <summary> /// Adds collection of timed events to the specified <see cref="TrackChunk"/>. /// </summary> /// <param name="trackChunk"><see cref="TrackChunk"/> to add timed events to.</param> /// <param name="events">Timed events to add to the <paramref name="trackChunk"/>.</param> /// <exception cref="ArgumentNullException"><paramref name="trackChunk"/> is null. -or- /// <paramref name="events"/> is null.</exception> public static void AddTimedEvents(this TrackChunk trackChunk, IEnumerable <TimedEvent> events) { ThrowIfArgument.IsNull(nameof(trackChunk), trackChunk); ThrowIfArgument.IsNull(nameof(events), events); trackChunk.Events.AddTimedEvents(events); }
/// <summary> /// Adds collection of notes to the specified <see cref="TrackChunk"/>. /// </summary> /// <param name="trackChunk"><see cref="TrackChunk"/> to add notes to.</param> /// <param name="notes">Notes to add to the <paramref name="trackChunk"/>.</param> /// <exception cref="ArgumentNullException"> /// <para>One of the following errors occured:</para> /// <list type="bullet"> /// <item> /// <description><paramref name="trackChunk"/> is <c>null</c>.</description> /// </item> /// <item> /// <description><paramref name="notes"/> is <c>null</c>.</description> /// </item> /// </list> /// </exception> public static void AddNotes(this TrackChunk trackChunk, IEnumerable <Note> notes) { ThrowIfArgument.IsNull(nameof(trackChunk), trackChunk); ThrowIfArgument.IsNull(nameof(notes), notes); trackChunk.Events.AddNotes(notes); }
public void CompareWithSelf_WithDefaultSettings() { var trackChunk = new TrackChunk(); var areEqual = MidiChunk.Equals(trackChunk, trackChunk); Assert.IsTrue(areEqual, "Chunk isn't equal to self."); }
private void parseTracks(MidiFile midiFile) { IEnumerable <TrackChunk> trackChunks = midiFile.GetTrackChunks(); if (trackChunks.Count() > 1) { for (int i = 0; i < trackChunks.Count(); i++) { TrackChunk tr = trackChunks.ElementAt(i); if (i == 0) { parseHeader(tr, midiFile.GetTempoMap()); } else { MidiTrack track = new MidiTrack(tr, midiFile.GetTempoMap()); if (track.timeSignatures.Count > 0) { this.timeSignatures.AddRange(track.timeSignatures); } this.tracks.Add(track); } } } }
/// <summary> /// reads all tracks in filestream into three lists /// </summary> /// <returns>true if successful</returns> private bool ReadAllTracks() { // number of tracks in the file int numberOfTracks = ByteConverter.ToInt(this.Header.Tracks); // loop each track for (int i = 0; i < numberOfTracks; i++) { // add new track this.Tracks.Add(new TrackChunk()); TrackChunk track = this.Tracks[this.Tracks.Count - 1]; // try reading the track info into the new track if (!track.Read(this.Stream, this.TempoChanges, this.TimeSignatureChanges)) { Console.WriteLine("Error reading track at index {0}.", i); return(false); } #if DEBUG #endif } // order tempo and timesignature changes by absolute timing this.TempoChanges = this.TempoChanges.OrderBy(x => x.AbsoluteTiming).ToList(); this.TimeSignatureChanges = this.TimeSignatureChanges.OrderBy(x => x.AbsoluteTiming).ToList(); // order all trackevents and remove useless tracks this.Tracks.RemoveAll(x => x.Events.Count == 0); foreach (TrackChunk track in this.Tracks) { track.Events = track.Events.OrderBy(x => x.AbsoluteTiming).ToList(); } return(true); }
public MidiBuilder(Section section) { var bpm = section.Bpm; if (bpm == 0M) { bpm = 120M; } _trackChunks = new List <TrackChunk>(); foreach (var phrase in section.Phrases) { var trackChunk = new TrackChunk(); AddBpmEvent(trackChunk, bpm); AddTimeSignatureEvent(trackChunk); AddNameEvent(trackChunk, phrase.Description); SetInstrument(trackChunk, phrase); SetPan(trackChunk, phrase); _trackChunks.Add(trackChunk); } foreach (var sourcePhrase in section.Phrases) { var index = section.Phrases.IndexOf(sourcePhrase); var phrase = sourcePhrase.Clone(); PhraseHelper.UnmergeRepeatedNotes(phrase); PhraseHelper.UnmergeChords(phrase); using (var notesManager = _trackChunks[index].ManageNotes()) { var notes = phrase.Elements .Select(x => new Note ( GetMidiNoteNumber(x.Note), GetMidiNoteLength(x.Duration), GetMidiNoteLength(x.Position) ) { Velocity = (SevenBitNumber)x.Velocity }).ToList(); notesManager.Notes.Add(notes); } var notesOn = _trackChunks[index].Events.OfType <NoteOnEvent>().ToList(); foreach (var noteOn in notesOn) { noteOn.Channel = GetChannel(index, sourcePhrase); } var notesOff = _trackChunks[index].Events.OfType <NoteOffEvent>().ToList(); foreach (var noteOff in notesOff) { noteOff.Channel = GetChannel(index, sourcePhrase); } } }
/// <summary> /// Retrieves an instance of the <see cref="Playback"/> for playing MIDI events contained in /// the specified <see cref="TrackChunk"/>. /// </summary> /// <param name="trackChunk"><see cref="TrackChunk"/> containing events to play.</param> /// <param name="tempoMap">Tempo map used to calculate events times.</param> /// <returns>An instance of the <see cref="Playback"/> for playing MIDI events contained in /// the <paramref name="trackChunk"/>.</returns> /// <exception cref="ArgumentNullException"><paramref name="trackChunk"/> is null. -or- /// <paramref name="tempoMap"/> is null.</exception> public static Playback GetPlayback(this TrackChunk trackChunk, TempoMap tempoMap) { ThrowIfArgument.IsNull(nameof(trackChunk), trackChunk); ThrowIfArgument.IsNull(nameof(tempoMap), tempoMap); return(new Playback(trackChunk.Events, tempoMap)); }
public static void Test() { var midiFile = new MidiFile(); TempoMap tempoMap = midiFile.GetTempoMap(); var trackChunk = new TrackChunk(); using (var notesManager = trackChunk.ManageNotes()) { NotesCollection notes = notesManager.Notes; var g = Enum.GetValues(typeof(NoteName)); NoteName n = (NoteName)g.GetValue(MainWindow._rnd.Next(g.Length)); notes.Add(new InterNote(n, 4, LC.ConvertFrom( new MetricTimeSpan(hours: 0, minutes: 0, seconds: 2), 0, tempoMap))); n = (NoteName)g.GetValue(MainWindow._rnd.Next(g.Length)); notes.Add(new InterNote(n, 3, LC.ConvertFrom( new MetricTimeSpan(hours: 0, minutes: 0, seconds: 1, milliseconds: 500), 0, tempoMap))); n = (NoteName)g.GetValue(MainWindow._rnd.Next(g.Length)); notes.Add(new InterNote(n, 5, LC.ConvertFrom( new MetricTimeSpan(hours: 0, minutes: 0, seconds: 3), 0, tempoMap))); } midiFile.Chunks.Add(trackChunk); using (var outputDevice = OutputDevice.GetByName("Microsoft GS Wavetable Synth")) using (var playback = midiFile.GetPlayback(outputDevice)) { // playback.Speed = 2.0; playback.Play(); } }
private void ProcessChords_DetectionSettings_EventsCollection_WithoutPredicate( ContainerType containerType, ChordDetectionSettings settings, ICollection <MidiEvent> midiEvents, Action <Chord> action, ICollection <MidiEvent> expectedMidiEvents) { var chordsCount = midiEvents.GetChords(settings).Count; switch (containerType) { case ContainerType.EventsCollection: { var eventsCollection = new EventsCollection(); eventsCollection.AddRange(midiEvents); Assert.AreEqual( chordsCount, eventsCollection.ProcessChords(action, settings), "Invalid count of processed chords."); var expectedEventsCollection = new EventsCollection(); expectedEventsCollection.AddRange(expectedMidiEvents); MidiAsserts.AreEqual(expectedEventsCollection, eventsCollection, true, "Events are invalid."); Assert.IsTrue( eventsCollection.All(e => midiEvents.Any(ee => object.ReferenceEquals(e, ee))), "There are new events references."); } break; case ContainerType.TrackChunk: { var trackChunk = new TrackChunk(midiEvents); Assert.AreEqual( chordsCount, trackChunk.ProcessChords(action, settings), "Invalid count of processed chords."); var expectedTrackChunk = new TrackChunk(expectedMidiEvents); MidiAsserts.AreEqual(expectedTrackChunk, trackChunk, true, "Events are invalid."); Assert.IsTrue( trackChunk.Events.All(e => midiEvents.Any(ee => object.ReferenceEquals(e, ee))), "There are new events references."); } break; case ContainerType.TrackChunks: case ContainerType.File: { ProcessChords_DetectionSettings_TrackChunks_WithoutPredicate( containerType == ContainerType.File, settings, new[] { midiEvents }, action, new[] { expectedMidiEvents }); } break; } }
public static void ExportMsb(Stream dataStream, string outPath) { var file = MsbFile.Read(dataStream); var midiFile = new MidiFile(); var tempoMap = TempoMap.Create(new TicksPerQuarterNoteTimeDivision(960), Tempo.FromBeatsPerMinute((int)file.BpmEntries[0].Bpm)); foreach (var score in file.ScoreEntries) { var track = new TrackChunk(); var scoreNotes = new List <Note>(); foreach (var bar in score.Bars) { scoreNotes.Add(new Note(new SevenBitNumber((byte)(bar.Note + 24)), bar.Length, bar.Offset)); } track.AddNotes(scoreNotes); midiFile.Chunks.Add(track); } midiFile.ReplaceTempoMap(tempoMap); midiFile.Write(outPath); }
/// <summary> /// Exports the current <see cref="Pattern"/> to track chunk. /// </summary> /// <param name="tempoMap">Tempo map to process pattern data according with.</param> /// <param name="channel">Channel of notes that will be generated by pattern.</param> /// <returns>The <see cref="TrackChunk"/> containing notes events generated by the current <see cref="Pattern"/>.</returns> /// <exception cref="ArgumentNullException"><paramref name="tempoMap"/> is null.</exception> public TrackChunk ToTrackChunk(TempoMap tempoMap, FourBitNumber channel) { ThrowIfArgument.IsNull(nameof(tempoMap), tempoMap); var context = new PatternContext(tempoMap, channel); var result = InvokeActions(0, context); // var trackChunk = new TrackChunk(); using (var notesManager = trackChunk.ManageNotes()) { notesManager.Notes.Add(result.Notes ?? Enumerable.Empty <Note>()); } using (var eventsManager = trackChunk.ManageTimedEvents()) { eventsManager.Events.Add(result.Events ?? Enumerable.Empty <TimedEvent>()); } // return(trackChunk); }
public void GetTrack_ValidFile_ShouldReturnCorrectTrackChunk() { TrackChunk output = null; TrackChunk[] tracks = new TrackChunk[] { new TrackChunk(new MidiEvent[] { new SequenceTrackNameEvent("Track 0"), new ProgramNameEvent("Unit Testing Sample MIDI File") }), new TrackChunk(new MidiEvent[] { new SequenceTrackNameEvent("Track 1") }), new TrackChunk(new MidiEvent[] { new SequenceTrackNameEvent("Track 2"), new NoteOnEvent(), new NoteOffEvent() }) }; MidiFile input = new MidiFile(tracks); output = MidiHelper.GetTrack(input, 1); if (output != tracks[1]) { Assert.Fail("Returned incorrect TrackChunk."); } }
public midiTrack(int trackIndex, string trackName) { var chunk = MainForm.loadedMid.Chunks[trackIndex]; this.trackIndex = trackIndex; this.track = (chunk as TrackChunk); if (track == null) { throw new Exception("Not a track???"); } this.trackName = trackName; foreach (var midEvent in track.Events) { if (midEvent.EventType == MidiEventType.ProgramChange) // look for program change event to set channel and instrument { _channel = (midEvent as ProgramChangeEvent).Channel; _instrument = (midEvent as ProgramChangeEvent).ProgramNumber; originalInstrument = _instrument; } if (midEvent.EventType == MidiEventType.SequenceTrackName) { this.trackName = (midEvent as SequenceTrackNameEvent).Text; } if (this.channel != -1 && this.instrument != -1 && !string.IsNullOrEmpty(this.trackName)) { break; } } }
public void GetTrack_ValidFileButIndexNegative_ShouldReturnNull() { TrackChunk output = null; TrackChunk[] tracks = new TrackChunk[] { new TrackChunk(new MidiEvent[] { new SequenceTrackNameEvent("Track 0"), new ProgramNameEvent("Unit Testing Sample MIDI File") }), new TrackChunk(new MidiEvent[] { new SequenceTrackNameEvent("Track 1") }), new TrackChunk(new MidiEvent[] { new SequenceTrackNameEvent("Track 2"), new NoteOnEvent(), new NoteOffEvent() }) }; MidiFile input = new MidiFile(tracks); output = MidiHelper.GetTrack(input, -10); if (output != null) { Assert.Fail("Output not null."); } }
public void Decode(string midiFile, int keyNoteOctave) { try { DecoderDic ddic = new DecoderDic(keyNoteOctave); MidiFile midi = MidiFile.Read(midiFile); List <TrackChunk> trackList = midi.GetTrackChunks().ToList(); string result = ""; TrackChunk track = trackList[0]; NotesManager noteManager = track.ManageNotes(); foreach (Note note in noteManager.Notes) { result += ddic.GetChar(note.NoteName, note.Octave); } Console.WriteLine("-----------------------------------------"); Console.WriteLine("DECODED MIDI FILE MESSAGE: " + result); Console.WriteLine("-----------------------------------------"); } catch (IOException) { Console.WriteLine("[ERROR] Cannot read " + midiFile + "! Maybe is already used by another process?"); Environment.Exit(-1); } catch (Exception e) { Console.WriteLine("[ERROR] Something goes wrong here: " + e.Message); Environment.Exit(-1); } }
public void GenerateTrackList_ValidFile_ShouldListAllTrackNames() { string[] output = null; TrackChunk[] chunks = new TrackChunk[] { new TrackChunk(new MidiEvent[] { new SequenceTrackNameEvent("Track 0") }), new TrackChunk(new MidiEvent[] { new SequenceTrackNameEvent("Track 1") }), new TrackChunk(new MidiEvent[] { new SequenceTrackNameEvent("Track 2") }) }; MidiFile testFile = new MidiFile(chunks); output = MidiHelper.GenerateTrackList(testFile); if (output.Count() != 3) { Assert.Fail("Output array size incorrect."); } else if (output[0] != "0 - Track 0") { Assert.Fail($"Track 0 name incorrect: \"{output[0]}\"."); } else if (output[1] != "1 - Track 1") { Assert.Fail($"Track 1 name incorrect: \"{output[1]}\"."); } else if (output[2] != "2 - Track 2") { Assert.Fail($"Track 2 name incorrect: \"{output[2]}\"."); } }
/// <summary> /// Retrieves an instance of the <see cref="Playback"/> for playing MIDI events contained in /// the specified <see cref="TrackChunk"/>. /// </summary> /// <param name="trackChunk"><see cref="TrackChunk"/> containing events to play.</param> /// <param name="tempoMap">Tempo map used to calculate events times.</param> /// <param name="clockSettings">Settings of the internal playback's clock.</param> /// <returns>An instance of the <see cref="Playback"/> for playing MIDI events contained in /// the <paramref name="trackChunk"/>.</returns> /// <exception cref="ArgumentNullException"> /// <para>One of the following errors occured:</para> /// <list type="bullet"> /// <item> /// <description><paramref name="trackChunk"/> is <c>null</c>.</description> /// </item> /// <item> /// <description><paramref name="tempoMap"/> is <c>null</c>.</description> /// </item> /// </list> /// </exception> public static Playback GetPlayback(this TrackChunk trackChunk, TempoMap tempoMap, MidiClockSettings clockSettings = null) { ThrowIfArgument.IsNull(nameof(trackChunk), trackChunk); ThrowIfArgument.IsNull(nameof(tempoMap), tempoMap); return(new Playback(trackChunk.Events, tempoMap, clockSettings)); }
/// <summary> /// Adds collection of chords to the specified <see cref="TrackChunk"/>. /// </summary> /// <param name="trackChunk"><see cref="TrackChunk"/> to add chords to.</param> /// <param name="chords">Chords to add to the <paramref name="trackChunk"/>.</param> /// <exception cref="ArgumentNullException"> /// <para>One of the following errors occured:</para> /// <list type="bullet"> /// <item> /// <description><paramref name="trackChunk"/> is <c>null</c>.</description> /// </item> /// <item> /// <description><paramref name="chords"/> is <c>null</c>.</description> /// </item> /// </list> /// </exception> public static void AddChords(this TrackChunk trackChunk, IEnumerable <Chord> chords) { ThrowIfArgument.IsNull(nameof(trackChunk), trackChunk); ThrowIfArgument.IsNull(nameof(chords), chords); trackChunk.Events.AddChords(chords); }
/// <summary> /// Performs the specified action on each <see cref="TimedEvent"/> contained in the <see cref="TrackChunk"/>. /// </summary> /// <param name="trackChunk"><see cref="TrackChunk"/> to search for events to process.</param> /// <param name="action">The action to perform on each <see cref="TimedEvent"/> contained in the /// <paramref name="trackChunk"/>.</param> /// <param name="match">The predicate that defines the conditions of the <see cref="TimedEvent"/> to process.</param> /// <exception cref="ArgumentNullException"><paramref name="trackChunk"/> is null. -or- /// <paramref name="action"/> is null.</exception> public static void ProcessTimedEvents(this TrackChunk trackChunk, Action <TimedEvent> action, Predicate <TimedEvent> match = null) { ThrowIfArgument.IsNull(nameof(trackChunk), trackChunk); ThrowIfArgument.IsNull(nameof(action), action); trackChunk.Events.ProcessTimedEvents(action, match); }
private static MidiFile CreateTestFile() { const int trackChunksNumber = 100; const int chordsPerTrackChunk = 1000; const int noteLength = 100; const int notesPerChord = 10; var midiFile = new MidiFile(); for (int i = 0; i < trackChunksNumber; i++) { var trackChunk = new TrackChunk(); using (var chordsManager = trackChunk.ManageChords()) { for (int j = 0; j < chordsPerTrackChunk; j++) { var noteNumber = (SevenBitNumber)(j % SevenBitNumber.MaxValue); var notes = Enumerable.Range(0, notesPerChord).Select(_ => new Note(noteNumber, noteLength)); chordsManager.Chords.Add(new Chord(notes, j)); } } midiFile.Chunks.Add(trackChunk); } return(midiFile); }
public static bool IsEmptyTrackChunk(MidiChunk chunk) { if (chunk == null) { return(true); } else if (chunk.GetType() != typeof(TrackChunk)) { return(false); } TrackChunk track = (TrackChunk)chunk; foreach (MidiEvent currentEvent in track.Events) { Type eventType = currentEvent.GetType(); if (eventType == typeof(NoteOnEvent) || eventType == typeof(SetTempoEvent)) { return(false); } } return(true); }
public override Task<List<TrackChunk>> Process() { var trackChunk = new List<TrackChunk> { Song.TrackContainers[ProcessorConfig.Track].SourceTrackChunk }.Concat(ProcessorConfig.IncludedTracks.Select(track => Song.TrackContainers[track].SourceTrackChunk)).Merge(); var lyricEvents = new List<TimedEvent>(); var lyricLineCount = 0; var tempoMap = Song.SourceTempoMap.Clone(); foreach (var midiEvent in trackChunk.GetTimedEvents().Where(e => e.Event.EventType == MidiEventType.Lyric)) { lyricLineCount++; midiEvent.Time = midiEvent.TimeAs<MetricTimeSpan>(tempoMap).TotalMicroseconds / 1000 + 120000; lyricEvents.Add(midiEvent); } var trackChunks = new List<TrackChunk>(); for (var i = 0; i < ProcessorConfig.PlayerCount; i++) { trackChunk = new TrackChunk(); trackChunk.AddObjects(lyricEvents); trackChunk.AddObjects(new List<ITimedObject>{new TimedEvent(new SequenceTrackNameEvent("lyric:"+lyricLineCount))}); trackChunks.Add(trackChunk); } return Task.FromResult(trackChunks); }
/// <summary> /// Removes all the <see cref="Chord"/> that match the conditions defined by the specified predicate. /// </summary> /// <param name="trackChunk"><see cref="TrackChunk"/> to search for chords to remove.</param> /// <param name="match">The predicate that defines the conditions of the <see cref="Chord"/> to remove.</param> /// <param name="notesTolerance">Notes tolerance that defines maximum distance of notes from the /// start of the first note of a chord. Notes within this tolerance will be considered as a chord.</param> /// <exception cref="ArgumentNullException"><paramref name="trackChunk"/> is null.</exception> /// <exception cref="ArgumentOutOfRangeException"><paramref name="notesTolerance"/> is negative.</exception> public static void RemoveChords(this TrackChunk trackChunk, Predicate <Chord> match = null, long notesTolerance = 0) { ThrowIfArgument.IsNull(nameof(trackChunk), trackChunk); ThrowIfNotesTolerance.IsNegative(nameof(notesTolerance), notesTolerance); trackChunk.Events.RemoveChords(match, notesTolerance); }
/// <summary> /// reads and determines the type of a track event, and adds that to the proper list /// </summary> /// <param name="from">stream where to read from</param> /// <param name="allevents">list of all events (notes and controllers)</param> /// <param name="tempoevents">list of tempo events</param> /// <param name="tsigevents">list of time signature events</param> /// <returns>number of bytes read</returns> public static int Read(AudioStream from, TrackChunk track, List <TempoEvent> tempoevents, List <TimeSignatureEvent> tsigevents) { track.Events.Add(new TrackEvent()); int index = track.Events.Count - 1; int eventSize = from.Read(track.Events[index], vlv: "Timing", skipFields: new string[1] { "AbsoluteTiming" }); track.TickSize += ByteConverter.ToInt(track.Events[index].Timing); track.Events[index].AbsoluteTiming = track.TickSize; // meta and sysex events switch (track.Events[index].Prefix) { case (byte)TrackEvent.EventType.SysEx1: case (byte)TrackEvent.EventType.SysEx2: Console.WriteLine("System exclusive events are not supported."); return(-1); case (byte)TrackEvent.EventType.Meta: eventSize += MetaEvent.Read(from, track, tempoevents, tsigevents); break; default: int midiread = MidiEvent.Read(from, track.Events); if (midiread == -1) { return(-1); } eventSize += midiread; break; } return(eventSize); }
/// <summary> /// Gets chords contained in the specified <see cref="TrackChunk"/>. /// </summary> /// <param name="trackChunk"><see cref="TrackChunk"/> to search for chords.</param> /// <param name="notesTolerance">Notes tolerance that defines maximum distance of notes from the /// start of the first note of a chord. Notes within this tolerance will be considered as a chord.</param> /// <returns>Collection of chords contained in <paramref name="trackChunk"/> ordered by time.</returns> /// <exception cref="ArgumentNullException"><paramref name="trackChunk"/> is null.</exception> /// <exception cref="ArgumentOutOfRangeException"><paramref name="notesTolerance"/> is negative.</exception> public static IEnumerable <Chord> GetChords(this TrackChunk trackChunk, long notesTolerance = 0) { ThrowIfArgument.IsNull(nameof(trackChunk), trackChunk); ThrowIfNotesTolerance.IsNegative(nameof(notesTolerance), notesTolerance); return(trackChunk.Events.GetChords(notesTolerance)); }
/// <summary> /// Removes all the <see cref="TimedEvent"/> that match the conditions defined by the specified predicate. /// </summary> /// <param name="trackChunk"><see cref="TrackChunk"/> to search for events to remove.</param> /// <param name="match">The predicate that defines the conditions of the <see cref="TimedEvent"/> to remove.</param> /// <returns>Count of removed timed events.</returns> /// <exception cref="ArgumentNullException"> /// <para>One of the following errors occured:</para> /// <list type="bullet"> /// <item> /// <description><paramref name="trackChunk"/> is <c>null</c>.</description> /// </item> /// <item> /// <description><paramref name="match"/> is <c>null</c>.</description> /// </item> /// </list> /// </exception> public static int RemoveTimedEvents(this TrackChunk trackChunk, Predicate <TimedEvent> match) { ThrowIfArgument.IsNull(nameof(trackChunk), trackChunk); ThrowIfArgument.IsNull(nameof(match), match); return(trackChunk.Events.RemoveTimedEvents(match)); }