Skip to content

YIN algorithm, conversion of GuitarTuner example to Swift 3 #39

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Oct 23, 2016
Merged
16 changes: 15 additions & 1 deletion Beethoven.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
objects = {

/* Begin PBXBuildFile section */
AF3190521DABE01600C897CA /* YINTransformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF3190511DABE01600C897CA /* YINTransformer.swift */; };
AF4AFD9A1DAA3462002B6DC9 /* YINUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF4AFD991DAA3462002B6DC9 /* YINUtil.swift */; };
AFFF3FF11DB633B4004AD9D9 /* YINEstimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFFF3FF01DB633B4004AD9D9 /* YINEstimator.swift */; };
D51575B61C343B77006F8E75 /* Beethoven.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D51575AB1C343B77006F8E75 /* Beethoven.framework */; };
D59CB1571C345E0A00290B63 /* Config.swift in Sources */ = {isa = PBXBuildFile; fileRef = D59CB1371C345E0A00290B63 /* Config.swift */; };
D59CB1581C345E0A00290B63 /* Buffer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D59CB1391C345E0A00290B63 /* Buffer.swift */; };
Expand Down Expand Up @@ -55,12 +58,15 @@
/* End PBXContainerItemProxy section */

/* Begin PBXFileReference section */
AF3190511DABE01600C897CA /* YINTransformer.swift */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.swift; path = YINTransformer.swift; sourceTree = "<group>"; tabWidth = 4; };
AF4AFD991DAA3462002B6DC9 /* YINUtil.swift */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.swift; path = YINUtil.swift; sourceTree = "<group>"; tabWidth = 4; };
AFFF3FF01DB633B4004AD9D9 /* YINEstimator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YINEstimator.swift; sourceTree = "<group>"; };
D51575AB1C343B77006F8E75 /* Beethoven.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Beethoven.framework; sourceTree = BUILT_PRODUCTS_DIR; };
D51575B51C343B77006F8E75 /* Beethoven-iOS-Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Beethoven-iOS-Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
D59CB1371C345E0A00290B63 /* Config.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Config.swift; sourceTree = "<group>"; };
D59CB1391C345E0A00290B63 /* Buffer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Buffer.swift; sourceTree = "<group>"; };
D59CB13B1C345E0A00290B63 /* EstimationError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EstimationError.swift; sourceTree = "<group>"; };
D59CB13C1C345E0A00290B63 /* EstimationFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EstimationFactory.swift; sourceTree = "<group>"; };
D59CB13C1C345E0A00290B63 /* EstimationFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.swift; path = EstimationFactory.swift; sourceTree = "<group>"; tabWidth = 2; };
D59CB13D1C345E0A00290B63 /* EstimationStrategy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EstimationStrategy.swift; sourceTree = "<group>"; };
D59CB13E1C345E0A00290B63 /* Estimator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Estimator.swift; sourceTree = "<group>"; };
D59CB13F1C345E0A00290B63 /* LocationEstimator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocationEstimator.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -130,7 +136,9 @@
D5A49CCE1C343FD700427BF8 /* BeethovenTests */,
D51575AC1C343B77006F8E75 /* Products */,
);
indentWidth = 2;
sourceTree = "<group>";
tabWidth = 2;
};
D51575AC1C343B77006F8E75 /* Products */ = {
isa = PBXGroup;
Expand Down Expand Up @@ -172,6 +180,7 @@
D59CB13D1C345E0A00290B63 /* EstimationStrategy.swift */,
D59CB13E1C345E0A00290B63 /* Estimator.swift */,
D59CB13F1C345E0A00290B63 /* LocationEstimator.swift */,
AF4AFD991DAA3462002B6DC9 /* YINUtil.swift */,
);
path = Estimation;
sourceTree = "<group>";
Expand All @@ -186,6 +195,7 @@
D59CB1451C345E0A00290B63 /* QuadradicEstimator.swift */,
D59CB1461C345E0A00290B63 /* QuinnsFirstEstimator.swift */,
D59CB1471C345E0A00290B63 /* QuinnsSecondEstimator.swift */,
AFFF3FF01DB633B4004AD9D9 /* YINEstimator.swift */,
);
path = Strategies;
sourceTree = "<group>";
Expand Down Expand Up @@ -232,6 +242,7 @@
children = (
D59CB1521C345E0A00290B63 /* FFTTransformer.swift */,
D59CB1531C345E0A00290B63 /* SimpleTransformer.swift */,
AF3190511DABE01600C897CA /* YINTransformer.swift */,
);
path = Strategies;
sourceTree = "<group>";
Expand Down Expand Up @@ -495,9 +506,11 @@
D59CB16D1C345E0A00290B63 /* TransformFactory.swift in Sources */,
D59CB1631C345E0A00290B63 /* QuinnsFirstEstimator.swift in Sources */,
D59CB15B1C345E0A00290B63 /* EstimationStrategy.swift in Sources */,
AF4AFD9A1DAA3462002B6DC9 /* YINUtil.swift in Sources */,
D59CB15E1C345E0A00290B63 /* BarycentricEstimator.swift in Sources */,
D59CB1621C345E0A00290B63 /* QuadradicEstimator.swift in Sources */,
D59CB1591C345E0A00290B63 /* EstimationError.swift in Sources */,
AFFF3FF11DB633B4004AD9D9 /* YINEstimator.swift in Sources */,
D59CB1671C345E0A00290B63 /* SignalTracker.swift in Sources */,
D59CB16C1C345E0A00290B63 /* Transformer.swift in Sources */,
D59CB1661C345E0A00290B63 /* PitchEngine.swift in Sources */,
Expand All @@ -508,6 +521,7 @@
D59CB1571C345E0A00290B63 /* Config.swift in Sources */,
D59CB1681C345E0A00290B63 /* InputSignalTracker.swift in Sources */,
D59CB1581C345E0A00290B63 /* Buffer.swift in Sources */,
AF3190521DABE01600C897CA /* YINTransformer.swift in Sources */,
D59CB16A1C345E0A00290B63 /* FFTTransformer.swift in Sources */,
D59CB15A1C345E0A00290B63 /* EstimationFactory.swift in Sources */,
);
Expand Down
25 changes: 21 additions & 4 deletions Example/GuitarTuner/GuitarTuner.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,9 @@
7FCBD55DDFAE042D34748647 /* Frameworks */,
28B4E9F09A7A47F3AF3538A7 /* Pods */,
);
indentWidth = 2;
sourceTree = "<group>";
tabWidth = 2;
};
D57D40FE1BE95A350026B005 /* Products */ = {
isa = PBXGroup;
Expand All @@ -118,7 +120,7 @@
isa = PBXNativeTarget;
buildConfigurationList = D57D410F1BE95A350026B005 /* Build configuration list for PBXNativeTarget "GuitarTuner" */;
buildPhases = (
0E47FCD898C9F86D6AB5429F /* 📦 Check Pods Manifest.lock */,
0E47FCD898C9F86D6AB5429F /* [CP] Check Pods Manifest.lock */,
1962EBAD1F8E34314E982594 /* [CP] Check Pods Manifest.lock */,
D57D40F91BE95A350026B005 /* Sources */,
D57D40FA1BE95A350026B005 /* Frameworks */,
Expand All @@ -143,11 +145,13 @@
D57D40F51BE95A350026B005 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0700;
LastUpgradeCheck = 0800;
ORGANIZATIONNAME = "Vadym Markov";
TargetAttributes = {
D57D40FC1BE95A350026B005 = {
CreatedOnToolsVersion = 7.0.1;
DevelopmentTeam = 6YMA3EN78R;
LastSwiftMigration = 0800;
};
};
};
Expand Down Expand Up @@ -182,14 +186,14 @@
/* End PBXResourcesBuildPhase section */

/* Begin PBXShellScriptBuildPhase section */
0E47FCD898C9F86D6AB5429F /* 📦 Check Pods Manifest.lock */ = {
0E47FCD898C9F86D6AB5429F /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "📦 Check Pods Manifest.lock";
name = "[CP] Check Pods Manifest.lock";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -311,8 +315,10 @@
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
Expand All @@ -339,6 +345,7 @@
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 3.0;
};
name = Debug;
};
Expand All @@ -355,8 +362,10 @@
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
Expand All @@ -375,6 +384,8 @@
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_VERSION = 3.0;
VALIDATE_PRODUCT = YES;
};
name = Release;
Expand All @@ -383,23 +394,29 @@
isa = XCBuildConfiguration;
baseConfigurationReference = 1B8EABAEB6DB7CDA44CCC1AD /* Pods-GuitarTuner.debug.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
DEVELOPMENT_TEAM = 6YMA3EN78R;
INFOPLIST_FILE = "$(SRCROOT)/GuitarTuner/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.vadymmarkov.GuitarTuner;
PRODUCT_NAME = GuitarTuner;
SWIFT_VERSION = 3.0;
};
name = Debug;
};
D57D41111BE95A350026B005 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 00C49D4F07D54BCD11781B94 /* Pods-GuitarTuner.release.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
DEVELOPMENT_TEAM = 6YMA3EN78R;
INFOPLIST_FILE = "$(SRCROOT)/GuitarTuner/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.vadymmarkov.GuitarTuner;
PRODUCT_NAME = GuitarTuner;
SWIFT_VERSION = 3.0;
};
name = Release;
};
Expand Down
2 changes: 2 additions & 0 deletions Example/GuitarTuner/GuitarTuner/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSMicrophoneUsageDescription</key>
<string>app needs microphone access</string>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
Expand Down
12 changes: 6 additions & 6 deletions Example/GuitarTuner/GuitarTuner/Source/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
return controller
}()

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
window = UIWindow(frame: UIScreen.mainScreen().bounds)
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
window?.rootViewController = navigationController

applyStyles()
Expand All @@ -29,12 +29,12 @@ class AppDelegate: UIResponder, UIApplicationDelegate {

func applyStyles() {
let navigationBar = UINavigationBar.appearance()
navigationBar.barStyle = .Black
navigationBar.barTintColor = UIColor.hex("111011")
navigationBar.translucent = false
navigationBar.barStyle = .black
navigationBar.barTintColor = UIColor(hex: "111011")
navigationBar.isTranslucent = false
navigationBar.shadowImage = UIImage()
navigationBar.titleTextAttributes = [
NSForegroundColorAttributeName: UIColor.whiteColor()
NSForegroundColorAttributeName: UIColor.white
]
}
}
68 changes: 38 additions & 30 deletions Example/GuitarTuner/GuitarTuner/Source/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ class ViewController: UIViewController {
lazy var noteLabel: UILabel = {
let label = UILabel()
label.text = "--"
label.font = UIFont.boldSystemFontOfSize(65)
label.textColor = UIColor.hex("DCD9DB")
label.textAlignment = .Center
label.font = UIFont.boldSystemFont(ofSize: 65)
label.textColor = UIColor(hex: "DCD9DB")
label.textAlignment = .center
label.numberOfLines = 0
label.sizeToFit()

Expand All @@ -20,31 +20,34 @@ class ViewController: UIViewController {

lazy var offsetLabel: UILabel = { [unowned self] in
let label = UILabel()
label.font = UIFont.systemFontOfSize(28)
label.textColor = UIColor.whiteColor()
label.textAlignment = .Center
label.font = UIFont.systemFont(ofSize: 28)
label.textColor = UIColor.white
label.textAlignment = .center
label.numberOfLines = 0
label.sizeToFit()

return label
}()

lazy var actionButton: UIButton = { [unowned self] in
let button = UIButton(type: .System)
let button = UIButton(type: .system)
button.layer.cornerRadius = 20
button.backgroundColor = UIColor.hex("3DAFAE")
button.titleLabel?.font = UIFont.systemFontOfSize(20)
button.setTitleColor(UIColor.whiteColor(), forState: .Normal)
button.backgroundColor = UIColor(hex: "3DAFAE")
button.titleLabel?.font = UIFont.systemFont(ofSize: 20)
button.setTitleColor(UIColor.white, for: UIControlState())

button.addTarget(self, action: #selector(ViewController.actionButtonDidPress(_:)),
forControlEvents: .TouchUpInside)
button.setTitle("Start".uppercaseString, forState: .Normal)
for: .touchUpInside)
button.setTitle("Start".uppercased(), for: UIControlState())

return button
}()

lazy var pitchEngine: PitchEngine = { [unowned self] in
let pitchEngine = PitchEngine(delegate: self)
var config = Config()
config.transformStrategy = .yin
config.estimationStrategy = .yin
let pitchEngine = PitchEngine(config: config, delegate: self)
pitchEngine.levelThreshold = -30.0

return pitchEngine
Expand All @@ -55,8 +58,8 @@ class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()

title = "Tuner".uppercaseString
view.backgroundColor = UIColor.hex("111011")
title = "Tuner".uppercased()
view.backgroundColor = UIColor(hex: "111011")

[noteLabel, actionButton, offsetLabel].forEach {
view.addSubview($0)
Expand All @@ -67,25 +70,25 @@ class ViewController: UIViewController {

// MARK: - Action methods

func actionButtonDidPress(button: UIButton) {
func actionButtonDidPress(_ button: UIButton) {
let text = pitchEngine.active
? NSLocalizedString("Start", comment: "").uppercaseString
: NSLocalizedString("Stop", comment: "").uppercaseString
? NSLocalizedString("Start", comment: "").uppercased()
: NSLocalizedString("Stop", comment: "").uppercased()

button.setTitle(text, forState: .Normal)
button.setTitle(text, for: .normal)
button.backgroundColor = pitchEngine.active
? UIColor.hex("3DAFAE")
: UIColor.hex("E13C6C")
? UIColor(hex: "3DAFAE")
: UIColor(hex: "E13C6C")

noteLabel.text = "--"
pitchEngine.active ? pitchEngine.stop() : pitchEngine.start()
offsetLabel.hidden = !pitchEngine.active
offsetLabel.isHidden = !pitchEngine.active
}

// MARK: - Constrains

func setupLayout() {
let totalSize = UIScreen.mainScreen().bounds
let totalSize = UIScreen.main.bounds

constrain(actionButton, noteLabel, offsetLabel) {
actionButton, noteLabel, offsetLabel in
Expand All @@ -111,16 +114,16 @@ class ViewController: UIViewController {

// MARK: - UI

func offsetColor(offsetPercentage: Double) -> UIColor {
func offsetColor(_ offsetPercentage: Double) -> UIColor {
let color: UIColor

switch abs(offsetPercentage) {
case 0...5:
color = UIColor.hex("3DAFAE")
color = UIColor(hex: "3DAFAE")
case 6...25:
color = UIColor.hex("FDFFB1")
color = UIColor(hex: "FDFFB1")
default:
color = UIColor.hex("E13C6C")
color = UIColor(hex: "E13C6C")
}

return color
Expand All @@ -131,7 +134,7 @@ class ViewController: UIViewController {

extension ViewController: PitchEngineDelegate {

func pitchEngineDidRecievePitch(pitchEngine: PitchEngine, pitch: Pitch) {
func pitchEngineDidReceivePitch(_ pitchEngine: PitchEngine, pitch: Pitch) {
noteLabel.text = pitch.note.string

let offsetPercentage = pitch.closestOffset.percentage
Expand All @@ -148,10 +151,15 @@ extension ViewController: PitchEngineDelegate {

offsetLabel.text = "\(prefix)" + String(format:"%.2f", absOffsetPercentage) + "%"
offsetLabel.textColor = color
offsetLabel.hidden = false
offsetLabel.isHidden = false
}

func pitchEngineDidRecieveError(pitchEngine: PitchEngine, error: ErrorType) {
func pitchEngineDidReceiveError(_ pitchEngine: PitchEngine, error: Error) {
print(error)
}

public func pitchEngineWentBelowLevelThreshold(_ pitchEngine: PitchEngine) {

}

}
Loading