Esempio n. 1
0
        // Returned list contains one value for each note, computed with simple single-level model
        public List <float> GetNoteExpectednessLarson(Key key, Alphabet alphabet)
        {
            List <NoteWithAttackPoint> notes = this.AllNotes;

            List <float> noteExpectednessLarson = new List <float>(notes.Count);

            Note n1 = null;
            Note n2 = null;

            for (int i = 0; i < notes.Count; i++)
            {
                Note  n3 = notes[i];
                int   G = 0, I = 0;
                float M = 0;

                // Require at least 2 notes for Gravity and Magnetism forces, all 3 required for Inertia.
                if (n2 != null)
                {
                    int         n2MIDI = n2.Midi;
                    ScaleDegree sd2    = n2.GetScaleDegree(key);
                    if (sd2 != null)
                    {
                        int diff2 = n2MIDI - n3.Midi;
                        // Gravity.

                        if (diff2 > 0 && (sd2 == null || !sd2.IsTonic))
                        {
                            G = 1;
                        }

                        // Magnetism.
                        // Is previous note a stable note? If so, no prediction.
                        if (!alphabet.isStable(sd2))
                        {
                            // Not stable. Compute the magnetism based on the distance in half-steps to the nearest goals from the 2nd pitch.

                            // Go up until we find a stable note.
                            int stableAboveMidi = -1;
                            int stableBelowMidi = -1;

                            for (int midi = n2MIDI + 1; ; midi++)
                            {
                                ScaleDegree sdx = new Note(-1, false, false, new MidiInfo(midi, Accidental.Natural)).GetScaleDegree(key);
                                if (sdx != null)
                                {
                                    if (alphabet.isStable(sdx))
                                    {
                                        stableAboveMidi = midi;
                                        break;
                                    }
                                }
                            }
                            for (int midi = n2MIDI - 1; ; midi--)
                            {
                                ScaleDegree sdx = new Note(-1, false, false, new MidiInfo(midi, Accidental.Natural)).GetScaleDegree(key);
                                if (sdx != null)
                                {
                                    if (alphabet.isStable(sdx))
                                    {
                                        stableBelowMidi = midi;
                                        break;
                                    }
                                }
                            }

                            int distAbove = stableAboveMidi - n2MIDI;
                            int distBelow = n2MIDI - stableBelowMidi;

                            float mag    = 1.0f / (distAbove * distAbove) - 1.0f / (distBelow * distBelow);
                            float magMag = Math.Abs(mag); // magnitude of magnetism

                            // Test direction
                            if (diff2 * mag > 0)
                            {
                                // Going in opposite direction (because diff2 is positive when going down and mag is positive when going up.
                                M = -magMag;
                            }
                            else
                            {
                                // Going in same direction.
                                M = magMag;
                            }
                        }

                        // Inertia.
                        if (n1 != null)
                        {
                            int diff1 = n1.Midi - n2.Midi;
                            if (diff1 != 0)
                            {
                                I = (diff1 * diff2 > 0) ? 1 : -1;
                            }
                        }
                    }
                }

                /// Compute force of expecting this note.
                float force = G * Constants.LARSON_WEIGHT_G + I * Constants.LARSON_WEIGHT_I + M * Constants.LARSON_WEIGHT_M;
                noteExpectednessLarson.Add(force);
                //throw new Exception("Force computed: " + force.ToString());

                n1 = n2;
                n2 = n3;
            }
            return(noteExpectednessLarson);
        }
Esempio n. 2
0
        public override void Run()
        {
            if (group == null)
            {
                group = workspace.PickRandomGroupByRecency();
            }

            if (group == null)
            {
                return;
            }

            if (!workspace.groups.Contains(group))
            {
                return;
            }

            // Add to attention history.
            workspace.RecordCodeletAttentionHistory(this, group.MinLocation);
            workspace.RecordCodeletAttentionHistory(this, group.MaxLocation);


            // Check the final note of the rhythm.
            // Score based on the duration and tonic/dominantness of the pitch.

            Measure m = group.Measures[group.Measures.Count - 1];
            Note    n = m.rhythm.notes[m.rhythm.notes.Count - 1];

            if (n.midiInfo == null)
            {
                return;
            }

            ScaleDegree degree = n.midiInfo.GetScaleDegree(new Key());                  // assume C major.
            int         dur    = n.duartionIncludingTiesAfter;

            double score = 0;

            // check for minor/chromatic.
            if (degree == null)
            {
                // maybe its minor (TODO: crude)
                degree = n.midiInfo.GetScaleDegree(new Key());                  // assume C minor.
            }

            // maybe it's chromatic
            if (degree == null)
            {
                return;
            }
            else
            {
                switch (degree.Number)
                {
                case 1:                         // tonic
                    score = 100;

                    break;

                case 5:                         // dominant
                    score = 100;
                    break;

                case 2:                         // supertonic
                    score = 30;
                    break;

                default:
                    return;
                }
            }

            // Now average in harmonic context of pitch, if available.
            double   str1     = group.AlphabetStrength;
            double   str2     = m.AlphabetStrength;
            Alphabet alphabet = null;

            if (str1 >= str2)
            {
                alphabet = group.Alphabet;
            }
            else
            {
                alphabet = m.Alphabet;
            }
            if (alphabet != null)
            {
                // Average in 0 or 100 points depending on stability
                if (alphabet.isStable(degree))
                {
                    score = (score + 100) / 2;
                }
                else
                {
                    score = (score + 0) / 2;
                }
            }

            // Duration
            if (dur < 8)
            {
                score = score * (dur / 8.0);
            }

            if (score > 25)
            {
                if (degree.Number == 1)
                {
                    group.AddGroupReason(new GroupReasonEndTonic(group, score));
                }
                else
                {
                    group.AddGroupReason(new GroupReasonEndDominant(group, score));
                }
            }
        }