public static List <RhythmValue> GetRhythm(List <float> noteDurations, int measureDuration, int beatDuration)
        {
            float sum      = noteDurations.Sum();
            float scaling  = measureDuration / sum;
            var   noteEnds = new List <float>();
            float total    = 0;

            for (int i = 0; i < noteDurations.Count; ++i)
            {
                noteDurations[i] *= scaling;
                total            += noteDurations[i];
                noteEnds.Add(total);
            }

            MatchRhythm(noteEnds, 0, noteEnds.Count, 0, measureDuration, beatDuration);

            // determine final note values
            var   ret    = new List <RhythmValue>();
            float offset = 0;

            foreach (var end in noteEnds)
            {
                var rhythm = new RhythmValue()
                {
                    Duration  = (int)Math.Round(end - offset),
                    NoteIndex = ret.Count
                };
                offset = end;
                ret.Add(rhythm);
            }
            SplitDurations(ret, measureDuration, beatDuration);
            return(ret);
        }
Esempio n. 2
0
        public static List<RhythmValue> GetRhythm(List<float> noteDurations, int measureDuration, int beatDuration)
        {
            float sum = noteDurations.Sum();
            float scaling = measureDuration / sum;
            var noteEnds = new List<float>();
            float total = 0;
            for (int i = 0; i < noteDurations.Count; ++i)
            {
                noteDurations[i] *= scaling;
                total += noteDurations[i];
                noteEnds.Add(total);
            }

            MatchRhythm(noteEnds, 0, noteEnds.Count, 0, measureDuration, beatDuration);

            // determine final note values
            var ret = new List<RhythmValue>();
            float offset = 0;
            foreach (var end in noteEnds)
            {
                var rhythm = new RhythmValue()
                {
                    Duration = (int)Math.Round(end - offset),
                    NoteIndex = ret.Count
                };
                offset = end;
                ret.Add(rhythm);
            }
            SplitDurations(ret, measureDuration, beatDuration);
            return ret;
        }
        static void SplitDurations(List <RhythmValue> durations, int measureDuration, int beatLength)
        {
            // This function takes care of note values that cannot (or should not) be represented
            // by a single note, and it also tries to split up the rhythm in a more or less
            // readable way. This means e.g. that triplet notes should not stand alone.
            // (Although the algorithm may not be perfect in prevent single triplets.)
            int curPos = 0;

            for (int i = 0; i < durations.Count; ++i)
            {
                if (durations[i].Duration <= 1)
                {
                    continue;
                }

                if (PrintableDurations.Contains(durations[i].Duration))
                {
                    curPos += durations[i].Duration;
                    continue;
                }

                //Console.WriteLine("  At pos {0}, trying to split duration {1}...", curPos, durations[i].Duration);

                bool done = false;

                int curBeat = beatLength;
                int noteEnd = curPos + durations[i].Duration;
                int n       = 2;
                int d       = 3;

                while (!done && curBeat >= 2)
                {
                    int maxMult = noteEnd / curBeat;
                    for (int j = maxMult; j >= 1; --j)
                    {
                        int remaining = noteEnd - j * curBeat;
                        if (remaining < 2 && remaining != 0)
                        {
                            break;
                        }
                        int duration = durations[i].Duration - remaining;
                        if (PrintableDurations.Contains(duration))
                        {
                            durations[i].Duration = duration;
                            if (remaining != 0)
                            {
                                durations.Insert(i + 1, new RhythmValue()
                                {
                                    Duration  = remaining,
                                    NoteIndex = durations[i].NoteIndex
                                });
                            }
                            done = true;
                            break;
                        }
                    }

                    // try next smaller even / triplet beat
                    curBeat = curBeat * n / d;
                    if (n == 2)
                    {
                        n = 3;
                        d = 4;
                    }
                    else
                    {
                        n = 2;
                        d = 3;
                    }
                }

                if (!PrintableDurations.Contains(durations[i].Duration))
                {
                    Console.WriteLine("  Warning: Failed to split note duration {0} properly, splitting in half...", durations[i].Duration);
                    var newNote = new RhythmValue()
                    {
                        Duration  = durations[i].Duration / 2,
                        NoteIndex = durations[i].NoteIndex
                    };
                    durations[i].Duration -= newNote.Duration;
                    durations.Insert(i + 1, newNote);
                    --i;
                }
                else
                {
                    curPos += durations[i].Duration;
                }
            }
        }
Esempio n. 4
0
        static void SplitDurations(List<RhythmValue> durations, int measureDuration, int beatLength)
        {
            // This function takes care of note values that cannot (or should not) be represented
            // by a single note, and it also tries to split up the rhythm in a more or less 
            // readable way. This means e.g. that triplet notes should not stand alone.
            // (Although the algorithm may not be perfect in prevent single triplets.)
            int curPos = 0;
            for (int i = 0; i < durations.Count; ++i)
            {
                if (durations[i].Duration <= 1)
                    continue;

                if (PrintableDurations.Contains(durations[i].Duration))
                {
                    curPos += durations[i].Duration;
                    continue;
                }

                //Console.WriteLine("  At pos {0}, trying to split duration {1}...", curPos, durations[i].Duration);

                bool done = false;

                int curBeat = beatLength;
                int noteEnd = curPos + durations[i].Duration;
                int n = 2;
                int d = 3;

                while (!done && curBeat >= 2)
                {
                    int maxMult = noteEnd / curBeat;
                    for (int j = maxMult; j >= 1; --j)
                    {
                        int remaining = noteEnd - j * curBeat;
                        if (remaining < 2 && remaining != 0)
                            break;
                        int duration = durations[i].Duration - remaining;
                        if (PrintableDurations.Contains(duration))
                        {
                            durations[i].Duration = duration;
                            if (remaining != 0)
                            {
                                durations.Insert(i + 1, new RhythmValue()
                                {
                                    Duration = remaining,
                                    NoteIndex = durations[i].NoteIndex
                                });
                            }
                            done = true;
                            break;
                        }
                    }

                    // try next smaller even / triplet beat
                    curBeat = curBeat * n / d;
                    if (n == 2)
                    {
                        n = 3;
                        d = 4;
                    }
                    else
                    {
                        n = 2;
                        d = 3;
                    }
                }

                if (!PrintableDurations.Contains(durations[i].Duration))
                {
                    Console.WriteLine("  Warning: Failed to split note duration {0} properly, splitting in half...", durations[i].Duration);
                    var newNote = new RhythmValue()
                    {
                        Duration = durations[i].Duration / 2,
                        NoteIndex = durations[i].NoteIndex
                    };
                    durations[i].Duration -= newNote.Duration;
                    durations.Insert(i + 1, newNote);
                    --i;
                }
                else
                {
                    curPos += durations[i].Duration;
                }
            }
        }