Description of a scale's pattern as it ascends through an octave.
This class describes the general behavior of a scale as it ascends from a tonic up to the next tonic. It is described in terms of semitones relative to the tonic; to apply it to a particular tonic, pass one of these to the constructor of Scale.
Example #1
0
        /// <summary>
        /// Builds a scale.
        /// </summary>
        /// <param name="tonic">The tonic.</param>
        /// <param name="pattern">The scale pattern.</param>
        /// <param name="positionInOctaveToSequenceIndex">Must have 12 elements, and is filled with
        /// the 0-indexed scale position (or -1) for each position in the octave.</param>
        /// <param name="noteSequence">Must have pattern.Ascent.Length elements, and is filled with
        /// the notes for each scale degree.</param>
        /// <param name="numAccidentals">Filled with the total number of accidentals in the built
        /// scale.</param>
        private static void Build(Note tonic, ScalePattern pattern,
                                  int[] positionInOctaveToSequenceIndex, Note[] noteSequence, out int numAccidentals)
        {
            numAccidentals = 0;
            for (int i = 0; i < 12; ++i)
            {
                positionInOctaveToSequenceIndex[i] = -1;
            }
            Pitch tonicPitch = tonic.PitchInOctave(0);

            for (int i = 0; i < pattern.Ascent.Length; ++i)
            {
                Pitch pitch = tonicPitch + pattern.Ascent[i];
                Note  note;
                if (pattern.Ascent.Length == 7)
                {
                    char letter = (char)(i + (int)(tonic.Letter));
                    if (letter > 'G')
                    {
                        letter = (char)((int)letter - 7);
                    }
                    note = pitch.NoteWithLetter(letter);
                }
                else
                {
                    note = pitch.NotePreferringSharps();
                }
                noteSequence[i] = note;
                positionInOctaveToSequenceIndex[pitch.PositionInOctave()] = i;
            }
        }
Example #2
0
        /// <summary>
        /// Value equality.
        /// </summary>
        public override bool Equals(System.Object obj)
        {
            ScalePattern other = obj as ScalePattern;

            if ((Object)other == null)
            {
                return(false);
            }
            if (!this.name.Equals(other.name))
            {
                return(false);
            }
            if (this.ascent.Length != other.ascent.Length)
            {
                return(false);
            }
            for (int i = 0; i < this.ascent.Length; ++i)
            {
                if (this.ascent[i] != other.ascent[i])
                {
                    return(false);
                }
            }
            return(true);
        }
Example #3
0
        /// <summary>
        /// Constructs a scale from its tonic and its pattern.
        /// </summary>
        /// <param name="tonic">The tonic note.</param>
        /// <param name="pattern">The scale pattern.</param>
        /// <exception cref="ArgumentNullException">tonic or pattern is null.</exception>
        public Scale(Note tonic, ScalePattern pattern)
        {
            if (tonic == null || pattern == null)
            {
                throw new ArgumentNullException();
            }
            this.tonic   = tonic;
            this.pattern = pattern;
            this.positionInOctaveToSequenceIndex = new int[12];
            this.noteSequence = new Note[pattern.Ascent.Length];
            int numAccidentals;

            Build(this.tonic, this.pattern, this.positionInOctaveToSequenceIndex, this.noteSequence,
                  out numAccidentals);
        }
Example #4
0
 public void Properties()
 {
     ScalePattern sp = new ScalePattern("a", new int[] { 0, 1, 2, 3 });
     Assert.AreEqual(sp.Name, "a");
     Assert.AreEqual(sp.Ascent.Length, 4);
 }
Example #5
0
 /// <summary>
 /// Builds a scale.
 /// </summary>
 /// <param name="tonic">The tonic.</param>
 /// <param name="pattern">The scale pattern.</param>
 /// <param name="positionInOctaveToSequenceIndex">Must have 12 elements, and is filled with
 /// the 0-indexed scale position (or -1) for each position in the octave.</param>
 /// <param name="noteSequence">Must have pattern.Ascent.Length elements, and is filled with
 /// the notes for each scale degree.</param>
 /// <param name="numAccidentals">Filled with the total number of accidentals in the built
 /// scale.</param>
 private static void Build(Note tonic, ScalePattern pattern,
     int[] positionInOctaveToSequenceIndex, Note[] noteSequence, out int numAccidentals)
 {
     numAccidentals = 0;
     for (int i = 0; i < 12; ++i)
     {
         positionInOctaveToSequenceIndex[i] = -1;
     }
     Pitch tonicPitch = tonic.PitchInOctave(0);
     for (int i = 0; i < pattern.Ascent.Length; ++i)
     {
         Pitch pitch = tonicPitch + pattern.Ascent[i];
         Note note;
         if (pattern.Ascent.Length == 7)
         {
             char letter = (char)(i + (int)(tonic.Letter));
             if (letter > 'G')
             {
                 letter = (char)((int)letter - 7);
             }
             note = pitch.NoteWithLetter(letter);
         }
         else
         {
             note = pitch.NotePreferringSharps();
         }
         noteSequence[i] = note;
         positionInOctaveToSequenceIndex[pitch.PositionInOctave()] = i;
     }
 }
Example #6
0
 /// <summary>
 /// Constructs a scale from its tonic and its pattern.
 /// </summary>
 /// <param name="tonic">The tonic note.</param>
 /// <param name="pattern">The scale pattern.</param>
 /// <exception cref="ArgumentNullException">tonic or pattern is null.</exception>
 public Scale(Note tonic, ScalePattern pattern)
 {
     if (tonic == null || pattern == null)
     {
         throw new ArgumentNullException();
     }
     this.tonic = tonic;
     this.pattern = pattern;
     this.positionInOctaveToSequenceIndex = new int[12];
     this.noteSequence = new Note[pattern.Ascent.Length];
     int numAccidentals;
     Build(this.tonic, this.pattern, this.positionInOctaveToSequenceIndex, this.noteSequence,
         out numAccidentals);
 }