/// <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);
        }
Example #2
0
        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);
        }
Example #3
0
        /// <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));
        }
Example #4
0
        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);
        }
Example #6
0
        /// <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);
        }
Example #7
0
        public void CompareWithSelf_WithDefaultSettings()
        {
            var trackChunk = new TrackChunk();
            var areEqual   = MidiChunk.Equals(trackChunk, trackChunk);

            Assert.IsTrue(areEqual, "Chunk isn't equal to self.");
        }
Example #8
0
        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);
                    }
                }
            }
        }
Example #9
0
        /// <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);
        }
Example #10
0
        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);
                }
            }
        }
Example #11
0
        /// <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));
        }
Example #12
0
        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;
            }
        }
Example #14
0
        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);
        }
Example #15
0
        /// <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);
        }
Example #16
0
        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.");
            }
        }
Example #17
0
        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;
                }
            }
        }
Example #18
0
        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);
            }
        }
Example #20
0
        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);
            }
Example #25
0
        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);
        }
Example #27
0
        /// <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);
        }
Example #28
0
        /// <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);
        }
Example #29
0
        /// <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));
        }