-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
roux george buciu
committed
Nov 25, 2018
1 parent
79771ea
commit fdac751
Showing
21 changed files
with
3,545 additions
and
0 deletions.
There are no files selected for viewing
514 changes: 514 additions & 0 deletions
514
Swift Musicology/Swift Musicology.xcodeproj/project.pbxproj
Large diffs are not rendered by default.
Oops, something went wrong.
7 changes: 7 additions & 0 deletions
7
Swift Musicology/Swift Musicology.xcodeproj/project.xcworkspace/contents.xcworkspacedata
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
8 changes: 8 additions & 0 deletions
8
...logy/Swift Musicology.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
<plist version="1.0"> | ||
<dict> | ||
<key>IDEDidComputeMac32BitWarning</key> | ||
<true/> | ||
</dict> | ||
</plist> |
Binary file added
BIN
+25.5 KB
...deproj/project.xcworkspace/xcuserdata/acmelabs.xcuserdatad/UserInterfaceState.xcuserstate
Binary file not shown.
14 changes: 14 additions & 0 deletions
14
...t Musicology.xcodeproj/xcuserdata/acmelabs.xcuserdatad/xcschemes/xcschememanagement.plist
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
<plist version="1.0"> | ||
<dict> | ||
<key>SchemeUserState</key> | ||
<dict> | ||
<key>Swift Musicology.xcscheme_^#shared#^_</key> | ||
<dict> | ||
<key>orderHint</key> | ||
<integer>0</integer> | ||
</dict> | ||
</dict> | ||
</dict> | ||
</plist> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,226 @@ | ||
// | ||
// Accidental.swift | ||
// Swift Musicology | ||
// | ||
// Created by roux g. buciu on 2018-11-25. | ||
// Copyright © 2018 roux g. buciu. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
|
||
/// Used for calculating values of the `Key`s and `Pitche`s. | ||
public enum Accidental: Codable, Equatable, Hashable { | ||
|
||
// Base definition of accidentals. | ||
/// No accidental. | ||
case natural | ||
/// Reduces the `Key` or `Pitch` value by the given amount of semitones. | ||
case flats(amount: Int) | ||
/// Increases the `Key` or `Pitch` value by the given amount of semitones. | ||
case sharps(amount: Int) | ||
|
||
|
||
// Human friendly definition of accidentals. | ||
public static let flat: Accidental = .flats(amount: 1) | ||
public static let sharp: Accidental = .sharps(amount: 1) | ||
public static let doubleFlat: Accidental = .flats(amount: 2) | ||
public static let doubleSharp: Accidental = .sharps(amount: 2) | ||
|
||
/// A flag for `description` function that determines if it should use double sharp | ||
/// and double flat symbols. It's useful to set it to `false` where fonts do not | ||
/// support those symbols. Defaults to `true`. | ||
public static var shouldUseDoubleFlatAndDoubleSharpNotation = true | ||
} | ||
|
||
|
||
extension Accidental: RawRepresentable { | ||
|
||
public typealias RawValue = Int | ||
|
||
/// Value of the accidental in terms of semitones. | ||
public var rawValue: Int { | ||
switch self { | ||
case .natural: | ||
return 0 | ||
case let .flats(amount): | ||
return -amount | ||
case let .sharps(amount): | ||
return amount | ||
} | ||
} | ||
|
||
/// Initilizes the accidental with an integer that represents the semitone amount. | ||
/// | ||
/// - Parameter rawValue: semitone value of the accidental. Zero if natural; above | ||
/// zero if sharp; below zero if flat. | ||
public init?(rawValue: Accidental.RawValue) { | ||
if rawValue == 0 { | ||
self = .natural | ||
} else if rawValue > 0 { | ||
self = .sharps(amount: rawValue) | ||
} else { | ||
self = .flats(amount: -rawValue) | ||
} | ||
} | ||
} | ||
|
||
|
||
extension Accidental: ExpressibleByIntegerLiteral { | ||
|
||
public typealias IntegerLiteralType = Int | ||
|
||
/// Initilizes the accidental with an integer literal value. | ||
/// | ||
/// - Parameter value: semitone value of the accidental. Zero if natural; above | ||
/// zero if sharp; below zero if flat. | ||
public init(integerLiteral value: Accidental.IntegerLiteralType) { | ||
self = Accidental(rawValue: value) ?? .natural | ||
} | ||
} | ||
|
||
|
||
extension Accidental: ExpressibleByStringLiteral { | ||
|
||
public typealias StringLiteralType = String | ||
|
||
public init(stringLiteral value: Accidental.StringLiteralType) { | ||
var sum = 0 | ||
for i in 0 ..< value.count { | ||
switch value[value.index(value.startIndex, offsetBy: i)] { | ||
case "#", "♯": | ||
sum += 1 | ||
case "b", "♭": | ||
sum -= 1 | ||
default: | ||
break | ||
} | ||
} | ||
self = Accidental(rawValue: sum) ?? .natural | ||
} | ||
} | ||
|
||
|
||
extension Accidental: CustomStringConvertible { | ||
|
||
/// Returns the notation string of the accidental. | ||
public var notation: String { | ||
if case .natural = self { | ||
return "♮" | ||
} | ||
return description | ||
} | ||
|
||
/// Returns the notation string of the accidental. Returns empty string if the Accidental is natural. | ||
public var description: String { | ||
switch self { | ||
case .natural: | ||
return "" | ||
case let .flats(amount): | ||
switch amount { | ||
case 0: return Accidental.natural.description | ||
case 1: return "♭" | ||
case 2 where Accidental.shouldUseDoubleFlatAndDoubleSharpNotation: return "𝄫" | ||
default: return amount > 0 ? (0 ..< amount).map({ _ in Accidental.flats(amount: 1).description }).joined() : "" | ||
} | ||
case let .sharps(amount): | ||
switch amount { | ||
case 0: return Accidental.natural.description | ||
case 1: return "♯" | ||
case 2 where Accidental.shouldUseDoubleFlatAndDoubleSharpNotation: return "𝄪" | ||
default: return amount > 0 ? (0 ..< amount).map({ _ in Accidental.sharps(amount: 1).description }).joined() : "" | ||
} | ||
} | ||
} | ||
} | ||
|
||
|
||
// MARK: - Accidental Operations | ||
|
||
/// Returns a new accidental by adding up two accidentals in the equation. | ||
/// | ||
/// - Parameters: | ||
/// - lhs: Left hand side of the equation. | ||
/// - rhs: Right hand side of the equation. | ||
/// - Returns: Returns the sum of two accidentals. | ||
public func + (lhs: Accidental, rhs: Accidental) -> Accidental { | ||
return Accidental(integerLiteral: lhs.rawValue + rhs.rawValue) | ||
} | ||
|
||
/// Returns a new accidental by substracting two accidentals in the equation. | ||
/// | ||
/// - Parameters: | ||
/// - lhs: Left hand side of the equation. | ||
/// - rhs: Right hand side of the equation. | ||
/// - Returns: Returns the difference of two accidentals. | ||
public func - (lhs: Accidental, rhs: Accidental) -> Accidental { | ||
return Accidental(integerLiteral: lhs.rawValue - rhs.rawValue) | ||
} | ||
|
||
/// Returns a new accidental by adding up an int to the accidental in the equation. | ||
/// | ||
/// - Parameters: | ||
/// - lhs: Left hand side of the equation. | ||
/// - rhs: Right hand side of the equation. | ||
/// - Returns: Returns the sum of two accidentals. | ||
public func + (lhs: Accidental, rhs: Int) -> Accidental { | ||
return Accidental(integerLiteral: lhs.rawValue + rhs) | ||
} | ||
|
||
/// Returns a new accidental by substracting an int from the accidental in the equation. | ||
/// | ||
/// - Parameters: | ||
/// - lhs: Left hand side of the equation. | ||
/// - rhs: Right hand side of the equation. | ||
/// - Returns: Returns the difference of two accidentals. | ||
public func - (lhs: Accidental, rhs: Int) -> Accidental { | ||
return Accidental(integerLiteral: lhs.rawValue - rhs) | ||
} | ||
|
||
/// Multiples an accidental with a multiplier. | ||
/// | ||
/// - Parameters: | ||
/// - lhs: Accidental you want to multiply. | ||
/// - rhs: Multiplier. | ||
/// - Returns: Returns a multiplied acceident. | ||
public func * (lhs: Accidental, rhs: Int) -> Accidental { | ||
return Accidental(integerLiteral: lhs.rawValue * rhs) | ||
} | ||
|
||
/// Divides an accidental with a multiplier | ||
/// | ||
/// - Parameters: | ||
/// - lhs: Accidental you want to divide. | ||
/// - rhs: Multiplier. | ||
/// - Returns: Returns a divided accidental. | ||
public func / (lhs: Accidental, rhs: Int) -> Accidental { | ||
return Accidental(integerLiteral: lhs.rawValue / rhs) | ||
} | ||
|
||
/// Checks if the two accidental is identical in terms of their semitone values. | ||
/// | ||
/// - Parameters: | ||
/// - lhs: Left hand side of the equation. | ||
/// - rhs: Right hand side of the equation. | ||
/// - Returns: Returns true if two accidentalals is identical. | ||
public func == (lhs: Accidental, rhs: Accidental) -> Bool { | ||
return lhs.rawValue == rhs.rawValue | ||
} | ||
|
||
/// Checks if the two accidental is exactly identical. | ||
/// | ||
/// - Parameters: | ||
/// - lhs: Left hand side of the equation. | ||
/// - rhs: Right hand side of the equation. | ||
/// - Returns: Returns true if two accidentalals is identical. | ||
public func === (lhs: Accidental, rhs: Accidental) -> Bool { | ||
switch (lhs, rhs) { | ||
case (.natural, .natural): | ||
return true | ||
case let (.sharps(a), .sharps(b)): | ||
return a == b | ||
case let (.flats(a), .flats(b)): | ||
return a == b | ||
default: | ||
return false | ||
} | ||
} |
Oops, something went wrong.