Skip to content

Commit 0192a7d

Browse files
authored
Merge pull request #39 from glaurent/YINalgorithm
YIN algorithm, conversion of GuitarTuner example to Swift 3
2 parents 2125c4e + d89f9cb commit 0192a7d

File tree

14 files changed

+421
-57
lines changed

14 files changed

+421
-57
lines changed

Beethoven.xcodeproj/project.pbxproj

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
objects = {
88

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

5760
/* Begin PBXFileReference section */
61+
AF3190511DABE01600C897CA /* YINTransformer.swift */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.swift; path = YINTransformer.swift; sourceTree = "<group>"; tabWidth = 4; };
62+
AF4AFD991DAA3462002B6DC9 /* YINUtil.swift */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.swift; path = YINUtil.swift; sourceTree = "<group>"; tabWidth = 4; };
63+
AFFF3FF01DB633B4004AD9D9 /* YINEstimator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YINEstimator.swift; sourceTree = "<group>"; };
5864
D51575AB1C343B77006F8E75 /* Beethoven.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Beethoven.framework; sourceTree = BUILT_PRODUCTS_DIR; };
5965
D51575B51C343B77006F8E75 /* Beethoven-iOS-Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Beethoven-iOS-Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
6066
D59CB1371C345E0A00290B63 /* Config.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Config.swift; sourceTree = "<group>"; };
6167
D59CB1391C345E0A00290B63 /* Buffer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Buffer.swift; sourceTree = "<group>"; };
6268
D59CB13B1C345E0A00290B63 /* EstimationError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EstimationError.swift; sourceTree = "<group>"; };
63-
D59CB13C1C345E0A00290B63 /* EstimationFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EstimationFactory.swift; sourceTree = "<group>"; };
69+
D59CB13C1C345E0A00290B63 /* EstimationFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.swift; path = EstimationFactory.swift; sourceTree = "<group>"; tabWidth = 2; };
6470
D59CB13D1C345E0A00290B63 /* EstimationStrategy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EstimationStrategy.swift; sourceTree = "<group>"; };
6571
D59CB13E1C345E0A00290B63 /* Estimator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Estimator.swift; sourceTree = "<group>"; };
6672
D59CB13F1C345E0A00290B63 /* LocationEstimator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocationEstimator.swift; sourceTree = "<group>"; };
@@ -130,7 +136,9 @@
130136
D5A49CCE1C343FD700427BF8 /* BeethovenTests */,
131137
D51575AC1C343B77006F8E75 /* Products */,
132138
);
139+
indentWidth = 2;
133140
sourceTree = "<group>";
141+
tabWidth = 2;
134142
};
135143
D51575AC1C343B77006F8E75 /* Products */ = {
136144
isa = PBXGroup;
@@ -172,6 +180,7 @@
172180
D59CB13D1C345E0A00290B63 /* EstimationStrategy.swift */,
173181
D59CB13E1C345E0A00290B63 /* Estimator.swift */,
174182
D59CB13F1C345E0A00290B63 /* LocationEstimator.swift */,
183+
AF4AFD991DAA3462002B6DC9 /* YINUtil.swift */,
175184
);
176185
path = Estimation;
177186
sourceTree = "<group>";
@@ -186,6 +195,7 @@
186195
D59CB1451C345E0A00290B63 /* QuadradicEstimator.swift */,
187196
D59CB1461C345E0A00290B63 /* QuinnsFirstEstimator.swift */,
188197
D59CB1471C345E0A00290B63 /* QuinnsSecondEstimator.swift */,
198+
AFFF3FF01DB633B4004AD9D9 /* YINEstimator.swift */,
189199
);
190200
path = Strategies;
191201
sourceTree = "<group>";
@@ -232,6 +242,7 @@
232242
children = (
233243
D59CB1521C345E0A00290B63 /* FFTTransformer.swift */,
234244
D59CB1531C345E0A00290B63 /* SimpleTransformer.swift */,
245+
AF3190511DABE01600C897CA /* YINTransformer.swift */,
235246
);
236247
path = Strategies;
237248
sourceTree = "<group>";
@@ -495,9 +506,11 @@
495506
D59CB16D1C345E0A00290B63 /* TransformFactory.swift in Sources */,
496507
D59CB1631C345E0A00290B63 /* QuinnsFirstEstimator.swift in Sources */,
497508
D59CB15B1C345E0A00290B63 /* EstimationStrategy.swift in Sources */,
509+
AF4AFD9A1DAA3462002B6DC9 /* YINUtil.swift in Sources */,
498510
D59CB15E1C345E0A00290B63 /* BarycentricEstimator.swift in Sources */,
499511
D59CB1621C345E0A00290B63 /* QuadradicEstimator.swift in Sources */,
500512
D59CB1591C345E0A00290B63 /* EstimationError.swift in Sources */,
513+
AFFF3FF11DB633B4004AD9D9 /* YINEstimator.swift in Sources */,
501514
D59CB1671C345E0A00290B63 /* SignalTracker.swift in Sources */,
502515
D59CB16C1C345E0A00290B63 /* Transformer.swift in Sources */,
503516
D59CB1661C345E0A00290B63 /* PitchEngine.swift in Sources */,
@@ -508,6 +521,7 @@
508521
D59CB1571C345E0A00290B63 /* Config.swift in Sources */,
509522
D59CB1681C345E0A00290B63 /* InputSignalTracker.swift in Sources */,
510523
D59CB1581C345E0A00290B63 /* Buffer.swift in Sources */,
524+
AF3190521DABE01600C897CA /* YINTransformer.swift in Sources */,
511525
D59CB16A1C345E0A00290B63 /* FFTTransformer.swift in Sources */,
512526
D59CB15A1C345E0A00290B63 /* EstimationFactory.swift in Sources */,
513527
);

Example/GuitarTuner/GuitarTuner.xcodeproj/project.pbxproj

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,9 @@
101101
7FCBD55DDFAE042D34748647 /* Frameworks */,
102102
28B4E9F09A7A47F3AF3538A7 /* Pods */,
103103
);
104+
indentWidth = 2;
104105
sourceTree = "<group>";
106+
tabWidth = 2;
105107
};
106108
D57D40FE1BE95A350026B005 /* Products */ = {
107109
isa = PBXGroup;
@@ -118,7 +120,7 @@
118120
isa = PBXNativeTarget;
119121
buildConfigurationList = D57D410F1BE95A350026B005 /* Build configuration list for PBXNativeTarget "GuitarTuner" */;
120122
buildPhases = (
121-
0E47FCD898C9F86D6AB5429F /* 📦 Check Pods Manifest.lock */,
123+
0E47FCD898C9F86D6AB5429F /* [CP] Check Pods Manifest.lock */,
122124
1962EBAD1F8E34314E982594 /* [CP] Check Pods Manifest.lock */,
123125
D57D40F91BE95A350026B005 /* Sources */,
124126
D57D40FA1BE95A350026B005 /* Frameworks */,
@@ -143,11 +145,13 @@
143145
D57D40F51BE95A350026B005 /* Project object */ = {
144146
isa = PBXProject;
145147
attributes = {
146-
LastUpgradeCheck = 0700;
148+
LastUpgradeCheck = 0800;
147149
ORGANIZATIONNAME = "Vadym Markov";
148150
TargetAttributes = {
149151
D57D40FC1BE95A350026B005 = {
150152
CreatedOnToolsVersion = 7.0.1;
153+
DevelopmentTeam = 6YMA3EN78R;
154+
LastSwiftMigration = 0800;
151155
};
152156
};
153157
};
@@ -182,14 +186,14 @@
182186
/* End PBXResourcesBuildPhase section */
183187

184188
/* Begin PBXShellScriptBuildPhase section */
185-
0E47FCD898C9F86D6AB5429F /* 📦 Check Pods Manifest.lock */ = {
189+
0E47FCD898C9F86D6AB5429F /* [CP] Check Pods Manifest.lock */ = {
186190
isa = PBXShellScriptBuildPhase;
187191
buildActionMask = 2147483647;
188192
files = (
189193
);
190194
inputPaths = (
191195
);
192-
name = "📦 Check Pods Manifest.lock";
196+
name = "[CP] Check Pods Manifest.lock";
193197
outputPaths = (
194198
);
195199
runOnlyForDeploymentPostprocessing = 0;
@@ -311,8 +315,10 @@
311315
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
312316
CLANG_WARN_EMPTY_BODY = YES;
313317
CLANG_WARN_ENUM_CONVERSION = YES;
318+
CLANG_WARN_INFINITE_RECURSION = YES;
314319
CLANG_WARN_INT_CONVERSION = YES;
315320
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
321+
CLANG_WARN_SUSPICIOUS_MOVE = YES;
316322
CLANG_WARN_UNREACHABLE_CODE = YES;
317323
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
318324
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
@@ -339,6 +345,7 @@
339345
ONLY_ACTIVE_ARCH = YES;
340346
SDKROOT = iphoneos;
341347
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
348+
SWIFT_VERSION = 3.0;
342349
};
343350
name = Debug;
344351
};
@@ -355,8 +362,10 @@
355362
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
356363
CLANG_WARN_EMPTY_BODY = YES;
357364
CLANG_WARN_ENUM_CONVERSION = YES;
365+
CLANG_WARN_INFINITE_RECURSION = YES;
358366
CLANG_WARN_INT_CONVERSION = YES;
359367
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
368+
CLANG_WARN_SUSPICIOUS_MOVE = YES;
360369
CLANG_WARN_UNREACHABLE_CODE = YES;
361370
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
362371
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
@@ -375,6 +384,8 @@
375384
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
376385
MTL_ENABLE_DEBUG_INFO = NO;
377386
SDKROOT = iphoneos;
387+
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
388+
SWIFT_VERSION = 3.0;
378389
VALIDATE_PRODUCT = YES;
379390
};
380391
name = Release;
@@ -383,23 +394,29 @@
383394
isa = XCBuildConfiguration;
384395
baseConfigurationReference = 1B8EABAEB6DB7CDA44CCC1AD /* Pods-GuitarTuner.debug.xcconfig */;
385396
buildSettings = {
397+
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
386398
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
399+
DEVELOPMENT_TEAM = 6YMA3EN78R;
387400
INFOPLIST_FILE = "$(SRCROOT)/GuitarTuner/Info.plist";
388401
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
389402
PRODUCT_BUNDLE_IDENTIFIER = com.vadymmarkov.GuitarTuner;
390403
PRODUCT_NAME = GuitarTuner;
404+
SWIFT_VERSION = 3.0;
391405
};
392406
name = Debug;
393407
};
394408
D57D41111BE95A350026B005 /* Release */ = {
395409
isa = XCBuildConfiguration;
396410
baseConfigurationReference = 00C49D4F07D54BCD11781B94 /* Pods-GuitarTuner.release.xcconfig */;
397411
buildSettings = {
412+
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
398413
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
414+
DEVELOPMENT_TEAM = 6YMA3EN78R;
399415
INFOPLIST_FILE = "$(SRCROOT)/GuitarTuner/Info.plist";
400416
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
401417
PRODUCT_BUNDLE_IDENTIFIER = com.vadymmarkov.GuitarTuner;
402418
PRODUCT_NAME = GuitarTuner;
419+
SWIFT_VERSION = 3.0;
403420
};
404421
name = Release;
405422
};

Example/GuitarTuner/GuitarTuner/Info.plist

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
<string>1</string>
2323
<key>LSRequiresIPhoneOS</key>
2424
<true/>
25+
<key>NSMicrophoneUsageDescription</key>
26+
<string>app needs microphone access</string>
2527
<key>UILaunchStoryboardName</key>
2628
<string>LaunchScreen</string>
2729
<key>UIRequiredDeviceCapabilities</key>

Example/GuitarTuner/GuitarTuner/Source/AppDelegate.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
1616
return controller
1717
}()
1818

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

2323
applyStyles()
@@ -29,12 +29,12 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
2929

3030
func applyStyles() {
3131
let navigationBar = UINavigationBar.appearance()
32-
navigationBar.barStyle = .Black
33-
navigationBar.barTintColor = UIColor.hex("111011")
34-
navigationBar.translucent = false
32+
navigationBar.barStyle = .black
33+
navigationBar.barTintColor = UIColor(hex: "111011")
34+
navigationBar.isTranslucent = false
3535
navigationBar.shadowImage = UIImage()
3636
navigationBar.titleTextAttributes = [
37-
NSForegroundColorAttributeName: UIColor.whiteColor()
37+
NSForegroundColorAttributeName: UIColor.white
3838
]
3939
}
4040
}

Example/GuitarTuner/GuitarTuner/Source/ViewController.swift

Lines changed: 38 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ class ViewController: UIViewController {
99
lazy var noteLabel: UILabel = {
1010
let label = UILabel()
1111
label.text = "--"
12-
label.font = UIFont.boldSystemFontOfSize(65)
13-
label.textColor = UIColor.hex("DCD9DB")
14-
label.textAlignment = .Center
12+
label.font = UIFont.boldSystemFont(ofSize: 65)
13+
label.textColor = UIColor(hex: "DCD9DB")
14+
label.textAlignment = .center
1515
label.numberOfLines = 0
1616
label.sizeToFit()
1717

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

2121
lazy var offsetLabel: UILabel = { [unowned self] in
2222
let label = UILabel()
23-
label.font = UIFont.systemFontOfSize(28)
24-
label.textColor = UIColor.whiteColor()
25-
label.textAlignment = .Center
23+
label.font = UIFont.systemFont(ofSize: 28)
24+
label.textColor = UIColor.white
25+
label.textAlignment = .center
2626
label.numberOfLines = 0
2727
label.sizeToFit()
2828

2929
return label
3030
}()
3131

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

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

4343
return button
4444
}()
4545

4646
lazy var pitchEngine: PitchEngine = { [unowned self] in
47-
let pitchEngine = PitchEngine(delegate: self)
47+
var config = Config()
48+
config.transformStrategy = .yin
49+
config.estimationStrategy = .yin
50+
let pitchEngine = PitchEngine(config: config, delegate: self)
4851
pitchEngine.levelThreshold = -30.0
4952

5053
return pitchEngine
@@ -55,8 +58,8 @@ class ViewController: UIViewController {
5558
override func viewDidLoad() {
5659
super.viewDidLoad()
5760

58-
title = "Tuner".uppercaseString
59-
view.backgroundColor = UIColor.hex("111011")
61+
title = "Tuner".uppercased()
62+
view.backgroundColor = UIColor(hex: "111011")
6063

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

6871
// MARK: - Action methods
6972

70-
func actionButtonDidPress(button: UIButton) {
73+
func actionButtonDidPress(_ button: UIButton) {
7174
let text = pitchEngine.active
72-
? NSLocalizedString("Start", comment: "").uppercaseString
73-
: NSLocalizedString("Stop", comment: "").uppercaseString
75+
? NSLocalizedString("Start", comment: "").uppercased()
76+
: NSLocalizedString("Stop", comment: "").uppercased()
7477

75-
button.setTitle(text, forState: .Normal)
78+
button.setTitle(text, for: .normal)
7679
button.backgroundColor = pitchEngine.active
77-
? UIColor.hex("3DAFAE")
78-
: UIColor.hex("E13C6C")
80+
? UIColor(hex: "3DAFAE")
81+
: UIColor(hex: "E13C6C")
7982

8083
noteLabel.text = "--"
8184
pitchEngine.active ? pitchEngine.stop() : pitchEngine.start()
82-
offsetLabel.hidden = !pitchEngine.active
85+
offsetLabel.isHidden = !pitchEngine.active
8386
}
8487

8588
// MARK: - Constrains
8689

8790
func setupLayout() {
88-
let totalSize = UIScreen.mainScreen().bounds
91+
let totalSize = UIScreen.main.bounds
8992

9093
constrain(actionButton, noteLabel, offsetLabel) {
9194
actionButton, noteLabel, offsetLabel in
@@ -111,16 +114,16 @@ class ViewController: UIViewController {
111114

112115
// MARK: - UI
113116

114-
func offsetColor(offsetPercentage: Double) -> UIColor {
117+
func offsetColor(_ offsetPercentage: Double) -> UIColor {
115118
let color: UIColor
116119

117120
switch abs(offsetPercentage) {
118121
case 0...5:
119-
color = UIColor.hex("3DAFAE")
122+
color = UIColor(hex: "3DAFAE")
120123
case 6...25:
121-
color = UIColor.hex("FDFFB1")
124+
color = UIColor(hex: "FDFFB1")
122125
default:
123-
color = UIColor.hex("E13C6C")
126+
color = UIColor(hex: "E13C6C")
124127
}
125128

126129
return color
@@ -131,7 +134,7 @@ class ViewController: UIViewController {
131134

132135
extension ViewController: PitchEngineDelegate {
133136

134-
func pitchEngineDidRecievePitch(pitchEngine: PitchEngine, pitch: Pitch) {
137+
func pitchEngineDidReceivePitch(_ pitchEngine: PitchEngine, pitch: Pitch) {
135138
noteLabel.text = pitch.note.string
136139

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

149152
offsetLabel.text = "\(prefix)" + String(format:"%.2f", absOffsetPercentage) + "%"
150153
offsetLabel.textColor = color
151-
offsetLabel.hidden = false
154+
offsetLabel.isHidden = false
152155
}
153156

154-
func pitchEngineDidRecieveError(pitchEngine: PitchEngine, error: ErrorType) {
157+
func pitchEngineDidReceiveError(_ pitchEngine: PitchEngine, error: Error) {
155158
print(error)
156159
}
160+
161+
public func pitchEngineWentBelowLevelThreshold(_ pitchEngine: PitchEngine) {
162+
163+
}
164+
157165
}

0 commit comments

Comments
 (0)