コード例 #1
0
        object ICloneable.Clone()
        {
            NoteWithAttackPoint n = (NoteWithAttackPoint)base.Clone();

            n.AttackPoint = AttackPoint;
            return(n);
        }
コード例 #2
0
        /// <summary>
        /// Returns the likely alphabets for this group, with a score from 0 to 100 representing the probability that each alphabet is correct.
        /// Alphabets are chosen based on looking at longer notes on stronger beats.
        /// </summary>
        /// <returns></returns>
        public List <Tuple <Alphabet, float> > GetAlphabetsWithLikelihoods()
        {
            List <Tuple <Alphabet, float> > results = new List <Tuple <Alphabet, float> >();

            int[] attackPointLevels = Measures[0].GetAttackPointLevels();

            // Score all possible alphabets.
            float totalScore = 0;

            foreach (Alphabet a in possibleGroupAlphabets)
            {
                // set up scoring for each pitch in the alphabet.
                Dictionary <int, float> scores = new Dictionary <int, float>();                 // (pitch class, score) Scores between 0 and 1.
                foreach (ScaleDegree sd in a)
                {
                    scores[Key.GetScaleDegreePitchClass(sd)] = 0;
                }

                // Tally the 1) duration and 2) beat strength for each pitch in the group, if it's found in the alphabet.
                List <NoteWithAttackPoint> notes = AllNotes;
                foreach (NoteWithAttackPoint n in notes)
                {
                    int dur    = Math.Min(n.duration, 16);                      // 1-16
                    int attack = n.AttackPoint;
                    int level  = attackPointLevels[attack];                     // stength from 0-4 of beat position.
                    if (n.midiInfo == null)
                    {
                        continue;
                    }
                    int pc = n.midiInfo.PitchClass;
                    if (scores.ContainsKey(pc))
                    {
                        scores[pc] += (dur / 16.0f) * Constants.ALPHABET_SCORING_DURATION_WEIGHT + (level / 4.0f) * Constants.ALPHABET_SCORING_LEVEL_WEIGHT;
                    }
                }

                // Bonus for ending group in chord (just add additional salience to final note).
                if (notes.Count > 0)
                {
                    NoteWithAttackPoint n = notes[notes.Count - 1];
                    if (n.midiInfo != null)
                    {
                        int pc = n.midiInfo.PitchClass;
                        if (scores.ContainsKey(pc))
                        {
                            int dur = Math.Min(n.duration, 16); // 1-16
                            scores[pc] += (dur / 16.0f) * Constants.ALPHABET_SCORING_FINAL_NOTE_WEIGHT;
                        }
                    }
                }

                // Sum the scores over all notes in the alphabet to get alphabet score.
                float score = 0;
                foreach (ScaleDegreeWithStability sd in a)
                {
                    // TODO: add in small score for non-stable notes too.
                    score += sd.Stability * scores[Key.GetScaleDegreePitchClass(sd)];
                }

                // Bonus for starting piece on tonic chord.
                if (this.MinLocation == 0 && a.RootScaleDegree.IsTonic)
                {
                    score *= 5;
                }


                //score = 100.0f * (score / 7);
                results.Add(Tuple.Create(a, score));
                totalScore += score;
            }

            // Normalize results.
            List <Tuple <Alphabet, float> > resultsNormalized = new List <Tuple <Alphabet, float> >();

            foreach (Tuple <Alphabet, float> x in results)
            {
                resultsNormalized.Add(Tuple.Create(x.Item1, 100.0f * x.Item2 / totalScore));
            }

            return(resultsNormalized);
        }