예제 #1
0
        static string ChordToString(Chord chord, TempoMap tempoMap)
        {
            string representation = "\t\t{.music_notes = (struct MusicNote[]) {\n";

            //append each note to the chord
            int numNotes = 0;

            foreach (Note note in chord.Notes)
            {
                if (numNotes != 0)
                {
                    representation += ",\n";
                }
                representation += NoteToString(note, tempoMap);
                numNotes++;
            }

            representation += "\n\t\t}";

            //find the duration
            MetricTimeSpan chordDuration = LengthConverter.ConvertTo <MetricTimeSpan>(chord.Length, chord.Time, tempoMap);
            double         seconds       = chordDuration.TotalMicroseconds * MICROSECONDS_TO_SECONDS;

            representation += ", .duration = " + seconds + ", .num_notes = " + numNotes + "}";

            return(representation);
        }
예제 #2
0
 public void ToTimeSpan_Length()
 {
     foreach (var midiTime in _midiTimes)
     {
         var timeSpanLength = LengthConverter.ConvertTo <TTimeSpan>(Length, midiTime, TempoMap);
     }
 }
        private static void ResizeNotes(IEnumerable <Note> notes,
                                        IEnumerable <TimeAndLength> expectedTimesAndLengths,
                                        ITimeSpan length,
                                        TimeSpanType lengthType,
                                        TempoMap tempoMap)
        {
            notes.ResizeNotes(length, lengthType, tempoMap);

            var notesTimesAndLengths = notes.Where(n => n != null)
                                       .Zip(expectedTimesAndLengths, (n, tl) => new
            {
                Note          = n,
                TimeAndLength = tl
            });

            foreach (var noteTimeAndLength in notesTimesAndLengths)
            {
                var note           = noteTimeAndLength.Note;
                var expectedTime   = noteTimeAndLength.TimeAndLength.Time;
                var expectedLength = noteTimeAndLength.TimeAndLength.Length;

                var convertedLength = LengthConverter.ConvertTo((MidiTimeSpan)note.Length,
                                                                expectedLength.GetType(),
                                                                note.Time,
                                                                tempoMap);
                Assert.AreEqual(expectedLength, convertedLength, "Length is invalid.");

                var convertedTime = TimeConverter.ConvertTo((MidiTimeSpan)note.Time,
                                                            expectedTime.GetType(),
                                                            tempoMap);
                Assert.AreEqual(expectedTime, convertedTime, "Time is invalid.");
            }
        }
예제 #4
0
        public static void Subtract_LengthLength(ITimeSpan timeSpan1, ITimeSpan timeSpan2, TempoMap tempoMap, long time)
        {
            var mathTimeSpan = CheckMathTimeSpan(timeSpan1, timeSpan2, MathOperation.Subtract, TimeSpanMode.LengthLength);

            AreEqual(timeSpan1,
                     LengthConverter.ConvertTo(mathTimeSpan.Add(timeSpan2, TimeSpanMode.LengthLength),
                                               timeSpan1.GetType(),
                                               time,
                                               tempoMap),
                     $"({timeSpan1} - {timeSpan2}) + {timeSpan2} != {timeSpan1}.");
        }
예제 #5
0
        public void Convert_Default_4()
        {
            var tempoMap = TimeSpanTestUtilities.DefaultTempoMap;
            var time     = LargeMetricTime;

            TimeSpanTestUtilities.TestConversion(LengthConverter.ConvertTo <MidiTimeSpan>(MetricSpan,
                                                                                          time,
                                                                                          tempoMap),
                                                 MetricSpan,
                                                 time,
                                                 tempoMap);
        }
예제 #6
0
        public void Convert_Complex_3()
        {
            var tempoMap = TimeSpanTestUtilities.ComplexTempoMap;
            var time     = ShortMetricTime;

            TimeSpanTestUtilities.TestConversion(LengthConverter.ConvertTo <MidiTimeSpan>(MetricSpan,
                                                                                          time,
                                                                                          tempoMap),
                                                 MetricSpan,
                                                 time,
                                                 tempoMap);
        }
예제 #7
0
        static void Main(string[] args)
        {
            var midiFile = MidiFile.Read(args[0]);

            var chords   = midiFile.GetChords();
            var tempoMap = midiFile.GetTempoMap();

            List <List <Chord> > tracks = SortChords(chords);

#if DEBUG
            //output some debug data if necessary

            foreach (List <Chord> track in tracks)
            {
                System.Console.WriteLine("--TRACK START--");

                MetricTimeSpan totalTrackTime = new MetricTimeSpan(0);
                foreach (Chord chord in track)
                {
                    MetricTimeSpan chordStartTime = TimeConverter.ConvertTo <MetricTimeSpan>(chord.Time, tempoMap);
                    MetricTimeSpan chordDuration  = LengthConverter.ConvertTo <MetricTimeSpan>(chord.Length, chord.Time, tempoMap);
                    MetricTimeSpan chordEndTime   = chordStartTime + chordDuration;

                    System.Console.WriteLine("start: " + chordStartTime + " end: " + chordEndTime);

                    totalTrackTime += chordDuration;
                }

                System.Console.WriteLine("--TRACK END--");
                System.Console.WriteLine("TIME ELAPSED: " + totalTrackTime + "\n\n");
            }
#else
            //translate the tracks into code readable by the synth
            string songRepresentation = "{.music_tracks = (struct MusicTrack[]) {\n";

            foreach (List <Chord> track in tracks)
            {
                songRepresentation += TrackToString(track, tempoMap);
                if (tracks[tracks.Count - 1] != track)
                {
                    songRepresentation += ",\n";
                }
            }

            songRepresentation += "\n}, .num_tracks = " + tracks.Count + "}";

            System.Console.Write(songRepresentation);
#endif
        }
예제 #8
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, currentNoteHolder = 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());
            }
        }
예제 #9
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);
        }
예제 #10
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));
        }
예제 #11
0
        public static void TestConversion <TTimeSpan>(TTimeSpan timeSpan, ITimeSpan referenceTimeSpan, ITimeSpan time, TempoMap tempoMap)
            where TTimeSpan : ITimeSpan
        {
            time = time ?? new MidiTimeSpan();

            var ticks = LengthConverter.ConvertFrom(timeSpan, time, tempoMap);

            AreEqual(timeSpan,
                     LengthConverter.ConvertTo <TTimeSpan>(ticks, time, tempoMap),
                     "Cyclic conversion failed.");

            AreEqual(timeSpan,
                     LengthConverter.ConvertTo <TTimeSpan>(referenceTimeSpan, time, tempoMap),
                     "ConvertTo failed.");

            Assert.AreEqual(LengthConverter.ConvertFrom(referenceTimeSpan, time, tempoMap),
                            ticks,
                            "ConvertFrom failed.");
        }
예제 #12
0
        static string TrackToString(List <Chord> track, TempoMap tempoMap)
        {
            string representation = "\t{.music_chords = (struct MusicChord[]) {\n";

            int num_chords = track.Count;

            MetricTimeSpan lastChordEndTime = new MetricTimeSpan(0);

            foreach (Chord chord in track)
            {
                MetricTimeSpan chordStartTime = TimeConverter.ConvertTo <MetricTimeSpan>(chord.Time, tempoMap);
                MetricTimeSpan chordDuration  = LengthConverter.ConvertTo <MetricTimeSpan>(chord.Length, chord.Time, tempoMap);
                MetricTimeSpan chordEndTime   = chordStartTime + chordDuration;

                //pad the track if necessary with rests
                if (lastChordEndTime < chordStartTime)
                {
                    representation += RestToString(chordStartTime - lastChordEndTime) + ",\n";
                    num_chords++;
                }

                //add the chord's string representation
                representation += ChordToString(chord, tempoMap);
                if (track[track.Count - 1] != chord)
                {
                    representation += ",\n";
                }

                //record the end time for the next chord
                lastChordEndTime = chordEndTime;
            }

            representation += "\n\t}, .playback_type = PLAYBACK_MONO, .length = " + num_chords + "}";

            return(representation);
        }
예제 #13
0
 public void Setup()
 {
     _timeSpanTimes   = _midiTimes.Select(time => TimeConverter.ConvertTo <TTimeSpan>(time, TempoMap)).ToList();
     _timeSpanLengths = _midiTimes.Select(time => Tuple.Create(LengthConverter.ConvertTo <TTimeSpan>(Length, time, TempoMap), time)).ToList();
 }
 public void ConvertToInvalidDestination()
 {
     new Action(() => _converter.ConvertTo(1, typeof(Guid))).ShouldThrow <NotSupportedException>();
 }