Пример #1
0
 public void OpenFile(string path)
 {
     midi = MidiFile.Read(path, new ReadingSettings
     {
         NoHeaderChunkPolicy  = NoHeaderChunkPolicy.Ignore,
         NotEnoughBytesPolicy = NotEnoughBytesPolicy.Ignore,
         InvalidChannelEventParameterValuePolicy = InvalidChannelEventParameterValuePolicy.ReadValid,
         InvalidChunkSizePolicy = InvalidChunkSizePolicy.Ignore,
         InvalidMetaEventParameterValuePolicy = InvalidMetaEventParameterValuePolicy.SnapToLimits,
         MissedEndOfTrackPolicy           = MissedEndOfTrackPolicy.Ignore,
         UnexpectedTrackChunksCountPolicy = UnexpectedTrackChunksCountPolicy.Ignore,
         ExtraTrackChunkPolicy            = ExtraTrackChunkPolicy.Read,
         UnknownChunkIdPolicy             = UnknownChunkIdPolicy.ReadAsUnknownChunk,
         SilentNoteOnPolicy = SilentNoteOnPolicy.NoteOff
     });
     Tmap = midi.GetTempoMap();
 }
        private static void WriteTrackChunkEnd(
            StreamWriter streamWriter,
            int trackNumber,
            long time,
            MidiFileCsvConversionSettings settings,
            TempoMap tempoMap)
        {
            switch (settings.CsvLayout)
            {
            case MidiFileCsvLayout.DryWetMidi:
                return;

            case MidiFileCsvLayout.MidiCsv:
                WriteRecord(streamWriter, trackNumber, time, MidiCsvRecordTypes.File.TrackChunkEnd, settings, tempoMap);
                break;
            }
        }
        private void SplitByGrid_MultipleSteps(IEnumerable <TObject> inputObjects,
                                               ITimeSpan gridStart,
                                               IEnumerable <ITimeSpan> gridSteps,
                                               Dictionary <TObject, IEnumerable <TimeAndLength> > expectedParts,
                                               TempoMap tempoMap)
        {
            var expectedObjects = expectedParts
                                  .SelectMany(p => p.Value.Select(tl => CloneAndChangeTimeAndLength(
                                                                      p.Key,
                                                                      TimeConverter.ConvertFrom(tl.Time, tempoMap),
                                                                      LengthConverter.ConvertFrom(tl.Length, tl.Time, tempoMap))))
                                  .ToArray();

            var actualObjects = Splitter.SplitByGrid(inputObjects, new SteppedGrid(gridStart, gridSteps), tempoMap).ToArray();

            ObjectMethods.AssertCollectionsAreEqual(expectedObjects, actualObjects);
        }
Пример #4
0
        private static MarkablePlaybackEvent GetPlaybackEventWithNoteTag(
            Note note,
            TimedEvent timedEvent,
            TempoMap tempoMap)
        {
            var playbackEvent = new MarkablePlaybackEvent(
                timedEvent.Event,
                timedEvent.TimeAs <MetricTimeSpan>(tempoMap),
                timedEvent.Time);

            TimeSpan noteStartTime = note.TimeAs <MetricTimeSpan>(tempoMap);
            TimeSpan noteEndTime   = TimeConverter.ConvertTo <MetricTimeSpan>(note.Time + note.Length, tempoMap);

            playbackEvent.Metadata = new NotePlaybackEventMetadata(note, noteStartTime, noteEndTime);

            return(playbackEvent);
        }
Пример #5
0
        /// <summary>
        /// Merges nearby notes in the specified collection of notes.
        /// </summary>
        /// <param name="notes">Collection of notes to merge notes in.</param>
        /// <param name="tempoMap">Tempo map used to calculate distances between notes.</param>
        /// <param name="settings">Settings according to which notes should be merged.</param>
        /// <returns>Collection of notes which produced from the input one by merging nearby notes.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="notes"/> is null.</exception>
        public IEnumerable <Note> Merge(IEnumerable <Note> notes, TempoMap tempoMap, NotesMergingSettings settings = null)
        {
            ThrowIfArgument.IsNull(nameof(notes), notes);

            settings = settings ?? new NotesMergingSettings();

            var currentNotes  = new Dictionary <NoteId, NoteHolder>();
            var toleranceType = settings.Tolerance.GetType();

            foreach (var note in notes.Where(n => n != null).OrderBy(n => n.Time))
            {
                var noteId = note.GetNoteId();

                NoteHolder currentNoteHolder;
                if (!currentNotes.TryGetValue(noteId, out currentNoteHolder))
                {
                    currentNotes.Add(noteId, CreateNoteHolder(note, settings));
                    continue;
                }

                var currentEndTime    = currentNoteHolder.EndTime;
                var distance          = Math.Max(0, note.Time - currentEndTime);
                var convertedDistance = LengthConverter.ConvertTo((MidiTimeSpan)distance,
                                                                  toleranceType,
                                                                  currentEndTime,
                                                                  tempoMap);

                if (convertedDistance.CompareTo(settings.Tolerance) <= 0)
                {
                    var endTime = Math.Max(note.Time + note.Length, currentEndTime);
                    currentNoteHolder.EndTime = endTime;
                    currentNoteHolder.MergeVelocities(note);
                }
                else
                {
                    yield return(currentNotes[noteId].GetResultNote());

                    currentNotes[noteId] = CreateNoteHolder(note, settings);
                }
            }

            foreach (var note in currentNotes.Values)
            {
                yield return(note.GetResultNote());
            }
        }
Пример #6
0
        static string NoteToString(Note note, TempoMap tempoMap)
        {
            string representation = "\t\t\t{";

            //find the note name
            string name = note.NoteName.ToString();

            //convert the sharp into notation that the synth recognizes
            if (name.Contains("Sharp"))
            {
                name = name[0] + "s";
            }

            representation += ".note = \"" + name + "\"";

            //find the note octave
            int octave = note.Octave;

            representation += ", .octave = " + octave;

            //find the note duration
            MetricTimeSpan noteDuration = LengthConverter.ConvertTo <MetricTimeSpan>(note.Length, note.Time, tempoMap);

            double seconds = noteDuration.TotalMicroseconds * MICROSECONDS_TO_SECONDS;

            representation += ", .duration = " + seconds;

            //find the note peak and sustain intensity
            double peakIntensity    = System.Math.Pow(INTENSITY_SENSITIVITY, note.Velocity);
            double sustainIntensity = peakIntensity * SUSTAINABILITY;

            representation += ", .peak_intensity = " + peakIntensity + ", .sustain_intensity = " + sustainIntensity;

            //find the adsr envelope
            double adPercent = AD_SLOPE * (System.Math.Abs(note.Velocity) - 127) + MIN_AD_PERCENT;
            double aPercent  = adPercent * AD_PROPORTION;
            double dPercent  = adPercent - aPercent;
            double rPercent  = R_SLOPE * (System.Math.Abs(note.Velocity) - 127) + MIN_R_PERCENT;
            double sPercent  = 1 - aPercent - dPercent - rPercent;

            representation += ", .adsr_envelope = (double[]) {" + aPercent + ", " + dPercent + ", " + sPercent + ", " + rPercent + "}";

            representation += "}";
            return(representation);
        }
Пример #7
0
        private static QuantizedTime FindNearestTime(IReadOnlyList <long> grid,
                                                     long time,
                                                     TimeSpanType distanceCalculationType,
                                                     double quantizingLevel,
                                                     TempoMap tempoMap)
        {
            var distanceToGridTime          = -1L;
            var convertedDistanceToGridTime = TimeSpanUtilities.GetMaxTimeSpan(distanceCalculationType);
            var gridTime = -1L;

            for (int i = 0; i < grid.Count; i++)
            {
                var currentGridTime = grid[i];

                var distance          = Math.Abs(time - currentGridTime);
                var convertedDistance = LengthConverter.ConvertTo(distance, distanceCalculationType, Math.Min(time, currentGridTime), tempoMap);
                if (convertedDistance.CompareTo(convertedDistanceToGridTime) >= 0)
                {
                    break;
                }

                distanceToGridTime          = distance;
                convertedDistanceToGridTime = convertedDistance;
                gridTime = currentGridTime;
            }

            //

            var shift         = convertedDistanceToGridTime.Multiply(quantizingLevel);
            var convertedTime = TimeConverter.ConvertTo(time, distanceCalculationType, tempoMap);

            var newTime = TimeConverter.ConvertFrom(
                gridTime > time
                    ? convertedTime.Add(shift, TimeSpanMode.TimeLength)
                    : convertedTime.Subtract(shift, TimeSpanMode.TimeLength),
                tempoMap);

            //

            return(new QuantizedTime(newTime,
                                     gridTime,
                                     shift,
                                     distanceToGridTime,
                                     convertedDistanceToGridTime));
        }
Пример #8
0
        public void InitPlay()
        {
            _midiFile = new MidiFile();
            TempoMap tempoMap = _midiFile.GetTempoMap();

            var trackChunk = new TrackChunk();

            using (var notesManager = trackChunk.ManageNotes())
            {
                NotesCollection notes = notesManager.Notes;
                var             len   = LC.ConvertFrom(new MetricTimeSpan(hours: 0, minutes: 0, seconds: 1), 0, tempoMap);

                notes.Add(new InterNote(Note, Octave, len));
            }


            _midiFile.Chunks.Add(trackChunk);
        }
Пример #9
0
        private void CheckRecordedEvents(
            IReadOnlyList <TimedEvent> recordedEvents,
            IReadOnlyList <TimeSpan> expectedTimes,
            TempoMap tempoMap)
        {
            for (var i = 0; i < recordedEvents.Count; i++)
            {
                var recordedEvent = recordedEvents[i];
                var expectedTime  = expectedTimes[i];

                var convertedRecordedTime  = (TimeSpan)recordedEvent.TimeAs <MetricTimeSpan>(tempoMap);
                var offsetFromExpectedTime = (convertedRecordedTime - expectedTime).Duration();
                Assert.LessOrEqual(
                    offsetFromExpectedTime,
                    SendReceiveUtilities.MaximumEventSendReceiveDelay,
                    $"Event was recorded at wrong time (at {convertedRecordedTime} instead of {expectedTime}).");
            }
        }
Пример #10
0
 public static void ConvertToCsv(IEnumerable <Note> notes, Stream stream, TempoMap tempoMap, NoteCsvConversionSettings settings)
 {
     using (var csvWriter = new CsvWriter(stream, settings.CsvDelimiter))
     {
         foreach (var note in notes.Where(n => n != null))
         {
             csvWriter.WriteRecord(new object[]
             {
                 note.TimeAs(settings.TimeType, tempoMap),
                 note.Channel,
                 NoteCsvConversionUtilities.FormatNoteNumber(note.NoteNumber, settings.NoteNumberFormat),
                 note.LengthAs(settings.NoteLengthType, tempoMap),
                 note.Velocity,
                 note.OffVelocity
             });
         }
     }
 }
Пример #11
0
        /// <summary> Constructs an IMidiFile instance based on a MIDI file stream.</summary>
        /// <param name="stream"> stream of the midi file content. </param>
        /// <param name="disposeStream"> Set true if stream is to be closed by the constructor once it's done reading the file. </param>
        internal DryWetMidiAdapter(Stream stream, bool disposeStream = false)
        {
            // initialization
            Stream          = stream;
            stream.Position = 0;
            _midiContent    = MidiFile.Read(stream);
            _tempoMap       = _midiContent.GetTempoMap();
            IList <TrackChunk> trackChunks = _midiContent.GetTrackChunks().ToList();

            _metadataTrack = trackChunks.First();
            _metaEvents    = _metadataTrack.Events.ToList();

            // set midi title property
            Title = (((from e in _metaEvents
                       where e.EventType == MidiEventType.SequenceTrackName
                       select e).First()) as BaseTextEvent)?.Text ?? "Undefined";

            // set key signature property
            TimeSignatureEvent timeSignatureEvent = (from e in _metaEvents
                                                     where e.EventType == MidiEventType.TimeSignature
                                                     select e)?.First() as TimeSignatureEvent;

            KeySignature = MusicTheoryFactory.CreateDuration(timeSignatureEvent.Numerator, timeSignatureEvent.Denominator, false);

            // set number of bars property
            BarBeatFractionTimeSpan duration = _midiContent.GetDuration <BarBeatFractionTimeSpan>();

            NumberOfBars = (int)duration.Bars + (int)Math.Ceiling(duration.Beats / timeSignatureEvent.Numerator);

            // set BPM property
            BeatsPerMinute = (byte)(_midiContent.GetTempoMap()?.Tempo.AtTime(0).BeatsPerMinute);

            // set MIDI pitch range
            IEnumerable <DWMidiI.Note> notes = _midiContent.GetNotes();

            LowestPitch  = (NotePitch)(byte)(notes.Min(note => note.NoteNumber));
            HighestPitch = (NotePitch)(byte)(notes.Max(note => note.NoteNumber));

            // dispose stream if requested
            if (disposeStream)
            {
                stream.Dispose();
            }
        }
Пример #12
0
 private void parseNotes(IEnumerable <Note> noteList, TempoMap tempoMap)
 {
     foreach (var note in noteList)
     {
         int nr = Int32.Parse(note.Channel.ToString());
         if (nr == instrument.channel)
         {
             string   name        = note.NoteName.ToString();
             int      octave      = note.Octave;
             MidiTime time        = new MidiTime(note.Time, tempoMap);
             MidiTime length      = new MidiTime(note.Length, tempoMap);
             int      velocity    = Int32.Parse(note.Velocity.ToString());
             int      velocityOff = Int32.Parse(note.OffVelocity.ToString());
             int      noteNr      = Int32.Parse(note.NoteNumber.ToString());
             MidiNote midiNote    = new MidiNote(name, octave, time, length, velocity, velocityOff, noteNr);
             this.notes.Add(midiNote);
         }
     }
 }
        private static void WriteRecord(
            StreamWriter streamWriter,
            int?trackNumber,
            long?time,
            string type,
            MidiFileCsvConversionSettings settings,
            TempoMap tempoMap,
            params object[] parameters)
        {
            var convertedTime = time == null
                ? null
                : TimeConverter.ConvertTo(time.Value, settings.TimeType, tempoMap);

            var processedParameters = parameters.SelectMany(ProcessParameter);

            streamWriter.WriteLine(CsvUtilities.MergeCsvValues(
                                       settings.CsvDelimiter,
                                       new object[] { trackNumber, convertedTime, type }.Concat(processedParameters)));
        }
Пример #14
0
        private void Merge(IEnumerable <Note> inputNotes,
                           IEnumerable <Note> expectedNotes,
                           TempoMap tempoMap,
                           VelocityMergingPolicy velocityMergingPolicy    = VelocityMergingPolicy.First,
                           VelocityMergingPolicy offVelocityMergingPolicy = VelocityMergingPolicy.Last,
                           ITimeSpan tolerance = null)
        {
            var settings = new NotesMergingSettings
            {
                VelocityMergingPolicy    = velocityMergingPolicy,
                OffVelocityMergingPolicy = offVelocityMergingPolicy,
                Tolerance = tolerance ?? new MidiTimeSpan()
            };

            var actualNotes = new NotesMerger().Merge(inputNotes, tempoMap, settings);

            MidiAsserts.AreEqual(
                expectedNotes.OrderBy(n => n.Time),
                actualNotes.OrderBy(n => n.Time),
                "Merging detached notes failed.");

            //

            var trackChunk = inputNotes.ToTrackChunk();

            trackChunk.MergeNotes(tempoMap, settings);

            MidiAsserts.AreEqual(
                expectedNotes.OrderBy(n => n.Time),
                trackChunk.GetNotes(),
                "Merging notes inside a track chunk failed.");

            //

            var midiFile = inputNotes.ToFile();

            midiFile.MergeNotes(settings);

            MidiAsserts.AreEqual(
                expectedNotes.OrderBy(n => n.Time),
                midiFile.GetNotes(),
                "Merging notes inside a file failed.");
        }
Пример #15
0
 public void OpenFile(byte[] s)
 {
     midi = MidiFile.Read(new MemoryStream(s), new ReadingSettings
     {
         NoHeaderChunkPolicy  = NoHeaderChunkPolicy.Ignore,
         NotEnoughBytesPolicy = NotEnoughBytesPolicy.Ignore,
         InvalidChannelEventParameterValuePolicy = InvalidChannelEventParameterValuePolicy.ReadValid,
         InvalidChunkSizePolicy = InvalidChunkSizePolicy.Ignore,
         InvalidMetaEventParameterValuePolicy = InvalidMetaEventParameterValuePolicy.SnapToLimits,
         MissedEndOfTrackPolicy           = MissedEndOfTrackPolicy.Ignore,
         UnexpectedTrackChunksCountPolicy = UnexpectedTrackChunksCountPolicy.Ignore,
         ExtraTrackChunkPolicy            = ExtraTrackChunkPolicy.Read,
         UnknownChunkIdPolicy             = UnknownChunkIdPolicy.ReadAsUnknownChunk,
         SilentNoteOnPolicy = SilentNoteOnPolicy.NoteOff,
         TextEncoding       = Encoding.Default,
         InvalidSystemCommonEventParameterValuePolicy = InvalidSystemCommonEventParameterValuePolicy.SnapToLimits,
     });
     Tmap = midi.GetTempoMap();
 }
Пример #16
0
        public static void UpdateBpm(MidiFile rawMidi, SongItem songItem)
        {
            if (rawMidi == null)
            {
                Debug.LogError("Cannot find the midi file");
                return;
            }
            songItem.notes.Clear();
            var detectedTempoMap = rawMidi.GetTempoMap();
            var tempoMap         = songItem.useCurrentBpmMidiImport ? TempoMap.Create(detectedTempoMap.TimeDivision, Tempo.FromBeatsPerMinute(songItem.bpm), detectedTempoMap.TimeSignature.AtTime(0)) : detectedTempoMap;

            if (!songItem.useCurrentBpmMidiImport)
            {
                songItem.bpm = (int)rawMidi.GetTempoMap().Tempo.AtTime(0).BeatsPerMinute;
            }

            Debug.Log($"Updating Midi Data {tempoMap.TimeDivision}, {songItem.bpm}bpm");

            int count = 0;

            foreach (var note in rawMidi.GetNotes())
            {
                count++;
                var beat       = GetMetricTimeSpanTotal(note.TimeAs <MetricTimeSpan>(tempoMap)) * songItem.bpm / 60;
                var beatLength = GetMetricTimeSpanTotal(note.LengthAs <MetricTimeSpan>(tempoMap)) * songItem.bpm / 60;
                // Debug.Log(RoundToNearestBeat(beat));

                songItem.notes.Add(new SongItem.MidiNote()
                {
                    noteName   = ParseEnum <SongItem.NoteName>(note.NoteName.ToString()),
                    noteOctave = note.Octave,
                    time       = GetMetricTimeSpanTotal(note.TimeAs <MetricTimeSpan>(tempoMap)),
                    noteLength = GetMetricTimeSpanTotal(note.LengthAs <MetricTimeSpan>(tempoMap)),

                    //This two is for recalculating the currect time when the bpm is changed
                    beatIndex       = SongItem.RoundToNearestBeat(beat),
                    beatLengthIndex = SongItem.RoundToNearestBeat(beatLength),
                });
            }
            Debug.Log(count + " Note(s) detected from Midi file");
            EditorUtility.SetDirty(songItem);
        }
        private static void WriteHeader(
            StreamWriter streamWriter,
            MidiFile midiFile,
            MidiFileCsvConversionSettings settings,
            TempoMap tempoMap)
        {
            MidiFileFormat?format = null;

            try
            {
                format = midiFile.OriginalFormat;
            }
            catch { }

            var trackChunksCount = midiFile.GetTrackChunks().Count();

            switch (settings.CsvLayout)
            {
            case MidiFileCsvLayout.DryWetMidi:
                WriteRecord(streamWriter,
                            null,
                            null,
                            DryWetMidiRecordTypes.File.Header,
                            settings,
                            tempoMap,
                            format,
                            midiFile.TimeDivision.ToInt16());
                break;

            case MidiFileCsvLayout.MidiCsv:
                WriteRecord(streamWriter,
                            0,
                            0,
                            MidiCsvRecordTypes.File.Header,
                            settings,
                            tempoMap,
                            format != null ? (ushort)format.Value : (trackChunksCount > 1 ? 1 : 0),
                            trackChunksCount,
                            midiFile.TimeDivision.ToInt16());
                break;
            }
        }
Пример #18
0
        public void Run()
        {
            MidiFile           file     = MidiFile.Read(midiPath);
            IEnumerable <Note> notes    = file.GetNotes();
            TempoMap           tempoMap = file.GetTempoMap();

            foreach (var note in notes)
            {
                MetricTimeSpan metricTime   = note.TimeAs <MetricTimeSpan>(tempoMap);
                MetricTimeSpan metricLength = note.LengthAs <MetricTimeSpan>(tempoMap);
            }
            using (StreamWriter newTask = new StreamWriter(this.txtPath, false))
            {
                foreach (var note in notes)
                {
                    MetricTimeSpan metricTime   = note.TimeAs <MetricTimeSpan>(tempoMap);
                    MetricTimeSpan metricLength = note.LengthAs <MetricTimeSpan>(tempoMap);
                }
            }
        }
Пример #19
0
        /// <summary>
        /// Performs additional actions before the new time will be set to an object.
        /// </summary>
        /// <remarks>
        /// Inside this method the new time can be changed or quantizing of an object can be cancelled.
        /// </remarks>
        /// <param name="obj">Object to quantize.</param>
        /// <param name="quantizedTime">Holds information about new time for an object.</param>
        /// <param name="grid">Grid to quantize object by.</param>
        /// <param name="tempoMap">Tempo map used to quantize object.</param>
        /// <param name="settings">Settings according to which object should be quantized.</param>
        /// <returns>An object indicating whether the new time should be set to the object
        /// or not. Also returned object contains that new time.</returns>
        protected override TimeProcessingInstruction OnObjectQuantizing(
            TObject obj,
            QuantizedTime quantizedTime,
            IGrid grid,
            TempoMap tempoMap,
            TSettings settings)
        {
            var newTime = quantizedTime.NewTime;

            switch (settings.QuantizingTarget)
            {
            case LengthedObjectTarget.Start:
                return(CorrectObjectOnStartQuantizing(obj, newTime, tempoMap, settings));

            case LengthedObjectTarget.End:
                return(CorrectObjectOnEndQuantizing(obj, newTime, tempoMap, settings));
            }

            return(new TimeProcessingInstruction(newTime));
        }
Пример #20
0
        private List <VoiceLine> GetVoices(MidiFile midiFile)
        {
            List <VoiceLine> voiceLines = new List <VoiceLine>();
            TempoMap         tempoMap   = midiFile.GetTempoMap();
            var tracks = midiFile.GetTrackChunks();

            int i = 0;

            foreach (var track in tracks)
            {
                var notes = (List <Melanchall.DryWetMidi.Smf.Interaction.Note>)track.GetNotes();
                if (notes.Count > 0)
                {
                    voiceLines.Add(new VoiceLine(GetBars(notes, tempoMap), i, notes));
                }

                i++;
            }
            return(voiceLines);
        }
Пример #21
0
        public static Songs.Model.Song readMidi(string fileName)
        {
            var midiFile = MidiFile.Read(fileName);

            List <SongNote> notes    = new List <SongNote>();
            TempoMap        tempoMap = midiFile.GetTempoMap();

            foreach (var trackChunk in midiFile.GetTrackChunks())
            {
                using (var notesManager = trackChunk.ManageNotes()) {
                    foreach (Melanchall.DryWetMidi.Smf.Interaction.Note midiNote in notesManager.Notes)
                    {
                        SongNote note = new SongNote(midiNote.NoteName, midiNote.Octave, midiNote.Time / 1000f, (midiNote.Time + midiNote.Length) / 1000f);
                        notes.Add(note);
                    }
                }
            }

            return(new Songs.Model.Song(notes));
        }
Пример #22
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Playback"/> with the specified
        /// collection of MIDI events collections, tempo map and output MIDI device to play events through.
        /// </summary>
        /// <param name="events">Collection of MIDI events collections to play.</param>
        /// <param name="tempoMap">Tempo map used to calculate events times.</param>
        /// <param name="outputDevice">Output MIDI device to play <paramref name="events"/> through.</param>
        /// <exception cref="ArgumentNullException"><paramref name="events"/> is null. -or-
        /// <paramref name="tempoMap"/> is null. -or- <paramref name="outputDevice"/> is null.</exception>
        public Playback(IEnumerable <IEnumerable <MidiEvent> > events, TempoMap tempoMap, OutputDevice outputDevice)
        {
            ThrowIfArgument.IsNull(nameof(events), events);
            ThrowIfArgument.IsNull(nameof(tempoMap), tempoMap);
            ThrowIfArgument.IsNull(nameof(outputDevice), outputDevice);

            var playbackEvents = GetPlaybackEvents(events, tempoMap);

            _duration        = playbackEvents.LastOrDefault()?.Time ?? TimeSpan.Zero;
            _durationInTicks = playbackEvents.LastOrDefault()?.RawTime ?? 0;

            _eventsEnumerator = playbackEvents.GetEnumerator();
            _eventsEnumerator.MoveNext();

            TempoMap     = tempoMap;
            OutputDevice = outputDevice;

            _clock       = new MidiClock(ClockInterval);
            _clock.Tick += OnClockTick;
        }
Пример #23
0
        /// <summary>
        /// Merges nearby notes in the specified <see cref="TrackChunk"/>.
        /// </summary>
        /// <param name="trackChunk"><see cref="TrackChunk"/> to merge nearby notes in.</param>
        /// <param name="tempoMap">Tempo map used to calculate distances between notes.</param>
        /// <param name="settings">Settings according to which notes should be merged.</param>
        /// <param name="filter">Filter for notes to merge.</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="tempoMap"/> is <c>null</c>.</description>
        /// </item>
        /// </list>
        /// </exception>
        public static void MergeNotes(this TrackChunk trackChunk,
                                      TempoMap tempoMap,
                                      NotesMergingSettings settings = null,
                                      Predicate <Note> filter       = null)
        {
            ThrowIfArgument.IsNull(nameof(trackChunk), trackChunk);
            ThrowIfArgument.IsNull(nameof(tempoMap), tempoMap);

            using (var notesManager = trackChunk.ManageNotes())
            {
                var notes = notesManager.Notes;

                var notesMerger = new NotesMerger();
                var newNotes    = notesMerger.Merge(notes.Where(n => filter == null || filter(n)), tempoMap, settings)
                                  .ToList();

                notes.Clear();
                notes.Add(newNotes);
            }
        }
Пример #24
0
        public void Conversion_Metric_Math_Subtract_TempoChanged()
        {
            TempoMap tempoMap = null;

            using (var tempoMapManager = new TempoMapManager())
            {
                tempoMapManager.SetTempo(new MetricTime(0, 1, 5), new Tempo(20000));
                tempoMapManager.SetTempo(new MetricTime(0, 1, 50), new Tempo(2400));
                tempoMap = tempoMapManager.TempoMap;
            }

            var mathLength = new MathLength(new MetricLength(0, 0, 20),
                                            new MetricLength(0, 0, 50));
            var mathTime = new MathTime(new MetricTime(0, 2, 0),
                                        mathLength,
                                        MathOperation.Subtract);

            Assert.AreEqual(TimeConverter.ConvertFrom(new MetricTime(0, 0, 50), tempoMap),
                            TimeConverter.ConvertFrom(mathTime, tempoMap));
        }
Пример #25
0
    public static IEnumerable <NoteInfo> GetNotesInfo(string filePath, out TempoMap tempoMap)
    {
        var midiFile = MidiFile.Read(filePath);

        Debug.Log("Time div: " + midiFile.TimeDivision);

        tempoMap = midiFile.GetTempoMap();

        var programChanges = new Dictionary <FourBitNumber, Dictionary <long, SevenBitNumber> >();

        foreach (var timedEvent in midiFile.GetTimedEvents())
        {
            var programChangeEvent = timedEvent.Event as ProgramChangeEvent;
            //Debug.Log("Seconds: " + timedEvent.TimeAs<MetricTimeSpan>(tempoMap).Seconds);
            if (programChangeEvent == null)
            {
                continue;
            }

            var channel = programChangeEvent.Channel;

            Dictionary <long, SevenBitNumber> changes;
            if (!programChanges.TryGetValue(channel, out changes))
            {
                programChanges.Add(channel, changes = new Dictionary <long, SevenBitNumber>());
            }

            changes[timedEvent.Time] = programChangeEvent.ProgramNumber;
        }

        // collect notes info

        return(midiFile.GetNotes()
               .Select(n => new NoteInfo
        {
            ProgramNumber = GetProgramNumber(n.Channel, n.Time, programChanges),
            Time = n.Time,
            Length = n.Length,
            NoteNumber = n.NoteNumber
        }));
    }
Пример #26
0
    public void ResetSong()
    {
        mutex       = true;
        paused      = true;
        songStarted = false;
        if (!midiPath.Contains(".mid"))
        {
            midiPath = Application.streamingAssetsPath + "/Songs/" + midiPath + ".mid";
        }
        MidiFile midiFile = MidiFile.Read(midiPath);

        tempoMap = midiFile.GetTempoMap();

        notes = new List <Note>(midiFile.GetNotes());

        startTime      = Time.time;
        songTime       = 0 - delay;
        earlySongTime  = 0;
        noteIndex      = 0;
        earlyNoteIndex = 0;
        mutex          = false;
    }
Пример #27
0
        /// <summary>
        /// Gets points in time of the current grid.
        /// </summary>
        /// <param name="tempoMap">Tempo map used to get grid's times.</param>
        /// <returns>Collection of points in time of the current grid.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="tempoMap"/> is null.</exception>
        public IEnumerable <long> GetTimes(TempoMap tempoMap)
        {
            ThrowIfArgument.IsNull(nameof(tempoMap), tempoMap);

            if (!Steps.Any())
            {
                yield break;
            }

            var time = TimeConverter.ConvertFrom(Start, tempoMap);

            yield return(time);

            while (true)
            {
                foreach (var step in Steps)
                {
                    time += LengthConverter.ConvertFrom(step, time, tempoMap);
                    yield return(time);
                }
            }
        }
Пример #28
0
        private static void TestSimpleTempoMap(TempoMap tempoMap,
                                               TimeDivision expectedTimeDivision,
                                               Tempo expectedTempo,
                                               TimeSignature expectedTimeSignature)
        {
            Assert.AreEqual(expectedTimeDivision,
                            tempoMap.TimeDivision,
                            "Unexpected time division.");

            Assert.AreEqual(expectedTempo,
                            tempoMap.Tempo.AtTime(0),
                            "Unexpected tempo at the start of tempo map.");
            Assert.AreEqual(expectedTempo,
                            tempoMap.Tempo.AtTime(1000),
                            "Unexpected tempo at the arbitrary time of tempo map.");

            Assert.AreEqual(expectedTimeSignature,
                            tempoMap.TimeSignature.AtTime(0),
                            "Unexpected time signature at the start of tempo map.");
            Assert.AreEqual(expectedTimeSignature,
                            tempoMap.TimeSignature.AtTime(1000),
                            "Unexpected time signature at the arbitrary time of tempo map.");
        }
Пример #29
0
        public void CreateTxt()
        {
            MidiFile           file     = MidiFile.Read(midiPath);
            IEnumerable <Note> notes    = file.GetNotes();
            TempoMap           tempoMap = file.GetTempoMap();

            foreach (var note in notes)
            {
                MetricTimeSpan metricTime   = note.TimeAs <MetricTimeSpan>(tempoMap);
                MetricTimeSpan metricLength = note.LengthAs <MetricTimeSpan>(tempoMap);
            }
            using (StreamWriter newTask = new StreamWriter(this.txtPath, false))
            {
                foreach (var note in notes)
                {
                    MetricTimeSpan metricTime   = note.TimeAs <MetricTimeSpan>(tempoMap);
                    MetricTimeSpan metricLength = note.LengthAs <MetricTimeSpan>(tempoMap);
                    var            name         = note.NoteName;
                    var            value        = note.NoteNumber;
                    newTask.WriteLine(metricTime + "," + metricLength + "," + name + "," + value);
                }
            }
        }
        public void Encode(string textToEncode, string outputFileName, int keyNoteOctave)
        {
            try
            {
                if (File.Exists(outputFileName))
                {
                    File.Delete(outputFileName);
                }
                EncoderDic encoderDic = new EncoderDic(keyNoteOctave);
                MidiFile   midi       = new MidiFile();
                TempoMap   tempo      = midi.GetTempoMap();

                TrackChunk trackChunk = new TrackChunk();
                using (NotesManager notesManager = trackChunk.ManageNotes())
                {
                    int timePos = 0;
                    for (int i = 0; i < textToEncode.Length; i++)
                    {
                        Note note = new Note(encoderDic.GetNoteName(textToEncode[i]), encoderDic.GetOctave(textToEncode[i]), LengthConverter.ConvertFrom(2 * MusicalTimeSpan.Eighth.Triplet(), 0, tempo), timePos);
                        //(Tipo de nota, octava, longitud de la nota, posicion en el tiempo);
                        timePos += 65;
                        notesManager.Notes.Add(note);
                    }
                }
                midi.Chunks.Add(trackChunk);
                midi.Write(outputFileName);
            }catch (IOException)
            {
                Console.WriteLine("[ERROR] Cannot create " + outputFileName + "! 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);
            }
        }
Пример #31
0
		public void SetMidiData(MidiData md)
		{
			Mfd = md;
			_tm = new TempoMap(Mfd);
			Stop();
			Reset();
			Eot = 0;
			Drumtracks = new List<int>();
			if (Mfd != null)
				Mc = new MidiClock(120, Mfd.Resolution.Resolution);
			var cnt = 0;
			if (Mfd != null)
				foreach (var lst in Mfd.Tracks)
				{
					if ((lst.Channel.GetValueOrDefault() == 9) && !Drumtracks.Contains(cnt))
						Drumtracks.Add(cnt);

					if (Eot < lst.TickLength)
						Eot = lst.TickLength;
					cnt++;
				}

			IsLoaded = true;
		}