2Grey

Scale Generator

Jul 29th, 2021
840
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import Foundation
  2.  
  3. class ScaleGenerator {
  4.     private static let sharpScale = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]
  5.     private static let flatScale = ["C", "Db", "D", "Eb", "E", "F", "Gb", "G", "Ab", "A", "Bb", "B"]
  6.     private static let flatKeys = ["F", "Bb", "Eb", "Ab", "Db", "Gb", "d", "g", "c", "f", "bb", "eb"]
  7.  
  8.     private enum Interval: Character {
  9.         case minor = "m"
  10.         case major = "M"
  11.         case augmented = "A"
  12.  
  13.         var interval: Int {
  14.             switch self {
  15.             case .minor: return 1
  16.             case .major: return 2
  17.             case .augmented: return 3
  18.             }
  19.         }
  20.     }
  21.  
  22.     private let tonic: String
  23.     private let pattern: String
  24.     private(set) var name: String
  25.  
  26.     init(tonic: String, scaleName: String, pattern: String = "") {
  27.         self.tonic = tonic
  28.         self.pattern = pattern
  29.         self.name = "\(tonic.uppercased()) \(scaleName)"
  30.     }
  31.  
  32.     func pitches() -> [String] {
  33.         let pitches = self.generateChromaticPattern()
  34.  
  35.         guard self.pattern.isEmpty == false else { return pitches }
  36.  
  37.         var index = 0
  38.         return self.pattern.map {
  39.             let pitch = pitches[index]
  40.             index += Interval(rawValue: $0)?.interval ?? 0
  41.             return pitch
  42.         }
  43.     }
  44.  
  45.     private func generateChromaticPattern() -> [String] {
  46.         let pitches = ScaleGenerator.flatKeys.contains(self.tonic) ? ScaleGenerator.flatScale : ScaleGenerator.sharpScale
  47.  
  48.         let capitalizedTonic = tonic.capitalized
  49.         var returnArray = [String]()
  50.  
  51.         guard var startIndex = pitches.index(of: capitalizedTonic) else { return returnArray }
  52.  
  53.         var pitch = capitalizedTonic
  54.         repeat {
  55.             startIndex = (startIndex == pitches.count - 1) ? 0 : startIndex + 1
  56.             returnArray.append(pitch)
  57.             pitch = pitches[startIndex]
  58.         } while pitch != capitalizedTonic
  59.         return returnArray
  60.     }
  61. }
RAW Paste Data