private Phrase GenratePhraseBasic(int noteCount)
        {
            var phrase = new Phrase();

            var selectedNotes =
                (from onoffProbability in _probabilities
                 let noteOn = GetRandomBool(onoffProbability.OnOffChance)
                              where noteOn
                              select onoffProbability).ToList();

            while (selectedNotes.Count > noteCount)
            {
                var leastPopularNote = selectedNotes.OrderBy(x => x.OnOffChance).FirstOrDefault();
                selectedNotes.Remove(leastPopularNote);
            }
            while (selectedNotes.Count < noteCount)
            {
                var mostPopularNote = _probabilities.Except(selectedNotes)
                                      .OrderByDescending(x => x.OnOffChance)
                                      .FirstOrDefault();
                selectedNotes.Add(mostPopularNote);
            }

            selectedNotes = selectedNotes.Where(x => x != null).ToList();

            selectedNotes = selectedNotes.OrderBy(x => x.Position).ToList();

            foreach (var note in selectedNotes)
            {
                var randomNote = GetRandomNote(note.Notes);

                phrase.Elements.Add(new PhraseElement
                {
                    Position = note.Position,
                    Duration = 1,
                    Note     = randomNote
                });
            }
            phrase.Elements.RemoveAll(x => x.Position >= _riffLength);

            PhraseHelper.UpdateDurationsFromPositions(phrase, _riffLength);
            return(phrase);
        }
        public Phrase GeneratePhrase(string baseRiff = "")
        {
            var riffs = _riffs.OrderBy(x => _random.NextDouble()).Take(_numberOfRiffsToMerge).ToList();

            if (baseRiff != "")
            {
                var riff = _riffs.Where(x => x.Description.ToLower() == baseRiff.ToLower()).ToList();
                if (riff.Count == 1)
                {
                    riffs = riffs.Except(riff).Take(_numberOfRiffsToMerge - 1).ToList();
                    riffs.InsertRange(0, riff);
                }
            }

            GenerateRiffProbabilities(riffs);

            var noteCount = GetNumberOfNotes();
            var phrase    = GenratePhraseBasic(noteCount);

            var perfectRepeats = GetPerfectRepeats();
            var timingRepeats  = GetTimingRepeats(perfectRepeats);
            var repeats        = perfectRepeats.Union(timingRepeats)
                                 .OrderBy(x => x.WindowSize)
                                 .ThenBy(x => x.WindowStart)
                                 .ThenBy(x => x.MatchWindowStart)
                                 .ToList();

            foreach (var repeat in repeats)
            {
                var sectionStartPositions = new List <decimal>
                {
                    repeat.WindowStart,
                    repeat.WindowStart + repeat.WindowSize,
                    repeat.MatchWindowStart,
                    repeat.MatchWindowStart + repeat.WindowSize
                };

                foreach (var position in sectionStartPositions)
                {
                    var element = phrase.Elements.FirstOrDefault(x => x.Position == position);
                    if (element != null)
                    {
                        continue;
                    }

                    element = GetNewRandomElement(position);
                    if (element != null)
                    {
                        phrase.Elements.Add(element);
                    }
                }
            }

            foreach (var repeat in repeats)
            {
                phrase.Elements.RemoveAll(x => x.Position >= repeat.MatchWindowStart &&
                                          x.Position < repeat.MatchWindowStart + repeat.WindowSize);

                var repeatingElements = phrase
                                        .Elements
                                        .Where(x => x.Position >= repeat.WindowStart &&
                                               x.Position < repeat.WindowStart + repeat.WindowSize)
                                        .Select(x => x.Clone())
                                        .ToList();

                foreach (var element in repeatingElements)
                {
                    element.Position = element.Position - repeat.WindowStart + repeat.MatchWindowStart;
                    if (repeat.MatchType != RepeatingElementsFinder.MatchResult.TimingMatch)
                    {
                        continue;
                    }

                    var probability = _probabilities.FirstOrDefault(x => x.Position == element.Position);
                    if (probability != null)
                    {
                        element.Note = GetRandomNote(probability.Notes);
                    }
                }

                phrase.Elements.AddRange(repeatingElements);
            }


            phrase.Elements = phrase.Elements.OrderBy(x => x.Position).ToList();
            phrase.Elements.RemoveAll(x => x.Position >= _riffLength);

            PhraseHelper.UpdateDurationsFromPositions(phrase, _riffLength);

            phrase.Bpm = 60;


            var lowNote = phrase.Elements.Min(x => x.Note);

            if (lowNote <= NoteHelper.NoteToNumber("C2"))
            {
                NoteHelper.ShiftNotesDirect(phrase, 1, Interval.Octave, Direction.Up);
            }

            return(phrase);
        }