diff --git a/.slather.yml b/.slather.yml deleted file mode 100644 index 2c6b215..0000000 --- a/.slather.yml +++ /dev/null @@ -1,4 +0,0 @@ -ci_service: travis_ci -coverage_service: coveralls -xcodeproj: Beethoven.xcodeproj -source_directory: Source diff --git a/.swift-version b/.swift-version new file mode 100644 index 0000000..9f55b2c --- /dev/null +++ b/.swift-version @@ -0,0 +1 @@ +3.0 diff --git a/.swiftlint.yml b/.swiftlint.yml new file mode 100644 index 0000000..fda547e --- /dev/null +++ b/.swiftlint.yml @@ -0,0 +1,39 @@ +included: # paths to include during linting. `--path` is ignored if present. + - Source +excluded: # paths to ignore during linting. Takes precedence over `included`. + - Carthage + - Pods +disabled_rules: + - type_name + +# configurable rules can be customized from this configuration file +# binary rules can set their severity level +force_cast: warning # implicitly +force_try: + severity: warning # explicitly +# rules that have both warning and error levels, can set just the warning level +# implicitly +line_length: 200 +# they can set both implicitly with an array +type_body_length: + - 300 # warning + - 400 # error +# or they can set both explicitly +file_length: + warning: 500 + error: 1200 +# naming rules can set warnings/errors for min_length and max_length +# additionally they can set excluded names +type_name: + min_length: 3 # only warning + max_length: # warning and error + warning: 40 + error: 50 + excluded: iPhone # excluded via string +variable_name: + min_length: # only min_length + error: 2 # only error + excluded: # excluded via string array + - x + - y +reporter: "xcode" # reporter type (xcode, json, csv, checkstyle) diff --git a/.travis.yml b/.travis.yml index 1a32ede..788a38c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,12 +1,14 @@ +osx_image: xcode8 language: objective-c -cache: cocoapods -before_install: gem install cocoapods obcd slather -N -# Use when you don't have third party dependencies -script: xctool -project Pod/Pod.xcodeproj -scheme Tests -sdk iphonesimulator build test GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES GCC_GENERATE_TEST_COVERAGE_FILES=YES clean test +before_install: +- brew update +- if brew outdated | grep -qx carthage; then brew upgrade carthage; fi +- travis_wait 35 carthage bootstrap --platform iOS -# Use when you have third party dependencies (CocoaPods generates a workspace) -# podfile: Pod/Podfile -# script: xctool -workspace Pod/Pod.xcworkspace -scheme Tests -sdk iphonesimulator build test GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES GCC_GENERATE_TEST_COVERAGE_FILES=YES clean test +script: +- xcodebuild clean build -project Beethoven.xcodeproj -scheme "Beethoven-iOS" -sdk iphonesimulator | xcpretty && exit ${PIPESTATUS[0]} +- xcodebuild test -project Beethoven.xcodeproj -scheme "Beethoven-iOS" -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 6,OS=10.0' | xcpretty && exit ${PIPESTATUS[0]} -after_success: slather +notifications: + email: false diff --git a/Beethoven.podspec b/Beethoven.podspec index 81f66d9..f1ca049 100644 --- a/Beethoven.podspec +++ b/Beethoven.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = "Beethoven" s.summary = "A maestro of pitch detection" - s.version = "2.0.0" + s.version = "3.0.0" s.homepage = "https://github.com/vadymmarkov/Beethoven" s.license = 'MIT' s.author = { "Vadym Markov" => "markov.vadym@gmail.com" } @@ -18,4 +18,6 @@ Pod::Spec.new do |s| s.frameworks = 'Foundation', 'AVFoundation', 'Accelerate' s.dependency 'Pitchy' + + s.pod_target_xcconfig = { 'SWIFT_VERSION' => '3.0' } end diff --git a/Beethoven.xcodeproj/project.pbxproj b/Beethoven.xcodeproj/project.pbxproj index 1063562..71ba40b 100644 --- a/Beethoven.xcodeproj/project.pbxproj +++ b/Beethoven.xcodeproj/project.pbxproj @@ -8,14 +8,21 @@ /* 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 */; }; + D55C020F1DBD211E00575260 /* ConfigSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D55C01F71DBD210600575260 /* ConfigSpec.swift */; }; + D55C02111DBD211E00575260 /* EstimationFactorySpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D55C01FB1DBD210600575260 /* EstimationFactorySpec.swift */; }; + D55C02121DBD211E00575260 /* EstimatorSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D55C01FC1DBD210600575260 /* EstimatorSpec.swift */; }; + D55C02131DBD211E00575260 /* ArrayExtensionsSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D55C01FE1DBD210600575260 /* ArrayExtensionsSpec.swift */; }; + D55C02141DBD211E00575260 /* FFTTransformerSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D55C02011DBD210600575260 /* FFTTransformerSpec.swift */; }; + D5843EDF1DBD2CF50077F86E /* Buffer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5843EDE1DBD2CF50077F86E /* Buffer.swift */; }; + D5843EE21DBD2D110077F86E /* Array+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5843EE11DBD2D110077F86E /* Array+Extensions.swift */; }; + D5843EE41DBD2D290077F86E /* YINUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5843EE31DBD2D290077F86E /* YINUtil.swift */; }; + D5843EE71DBD2FAA0077F86E /* EstimationFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5843EE51DBD2FAA0077F86E /* EstimationFactory.swift */; }; + D5843EE81DBD2FAA0077F86E /* EstimationStrategy.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5843EE61DBD2FAA0077F86E /* EstimationStrategy.swift */; }; + D5843EEC1DBD34AD0077F86E /* BufferSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5843EEA1DBD34680077F86E /* BufferSpec.swift */; }; D59CB1571C345E0A00290B63 /* Config.swift in Sources */ = {isa = PBXBuildFile; fileRef = D59CB1371C345E0A00290B63 /* Config.swift */; }; - D59CB1581C345E0A00290B63 /* Buffer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D59CB1391C345E0A00290B63 /* Buffer.swift */; }; D59CB1591C345E0A00290B63 /* EstimationError.swift in Sources */ = {isa = PBXBuildFile; fileRef = D59CB13B1C345E0A00290B63 /* EstimationError.swift */; }; - D59CB15A1C345E0A00290B63 /* EstimationFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = D59CB13C1C345E0A00290B63 /* EstimationFactory.swift */; }; - D59CB15B1C345E0A00290B63 /* EstimationStrategy.swift in Sources */ = {isa = PBXBuildFile; fileRef = D59CB13D1C345E0A00290B63 /* EstimationStrategy.swift */; }; D59CB15C1C345E0A00290B63 /* Estimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D59CB13E1C345E0A00290B63 /* Estimator.swift */; }; D59CB15D1C345E0A00290B63 /* LocationEstimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D59CB13F1C345E0A00290B63 /* LocationEstimator.swift */; }; D59CB15E1C345E0A00290B63 /* BarycentricEstimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D59CB1411C345E0A00290B63 /* BarycentricEstimator.swift */; }; @@ -25,7 +32,6 @@ D59CB1621C345E0A00290B63 /* QuadradicEstimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D59CB1451C345E0A00290B63 /* QuadradicEstimator.swift */; }; D59CB1631C345E0A00290B63 /* QuinnsFirstEstimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D59CB1461C345E0A00290B63 /* QuinnsFirstEstimator.swift */; }; D59CB1641C345E0A00290B63 /* QuinnsSecondEstimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D59CB1471C345E0A00290B63 /* QuinnsSecondEstimator.swift */; }; - D59CB1651C345E0A00290B63 /* Array+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D59CB1491C345E0A00290B63 /* Array+Extensions.swift */; }; D59CB1661C345E0A00290B63 /* PitchEngine.swift in Sources */ = {isa = PBXBuildFile; fileRef = D59CB14A1C345E0A00290B63 /* PitchEngine.swift */; }; D59CB1671C345E0A00290B63 /* SignalTracker.swift in Sources */ = {isa = PBXBuildFile; fileRef = D59CB14C1C345E0A00290B63 /* SignalTracker.swift */; }; D59CB1681C345E0A00290B63 /* InputSignalTracker.swift in Sources */ = {isa = PBXBuildFile; fileRef = D59CB14E1C345E0A00290B63 /* InputSignalTracker.swift */; }; @@ -33,15 +39,6 @@ D59CB16A1C345E0A00290B63 /* FFTTransformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D59CB1521C345E0A00290B63 /* FFTTransformer.swift */; }; D59CB16B1C345E0A00290B63 /* SimpleTransformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D59CB1531C345E0A00290B63 /* SimpleTransformer.swift */; }; D59CB16C1C345E0A00290B63 /* Transformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D59CB1541C345E0A00290B63 /* Transformer.swift */; }; - D59CB16D1C345E0A00290B63 /* TransformFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = D59CB1551C345E0A00290B63 /* TransformFactory.swift */; }; - D59CB16E1C345E0A00290B63 /* TransformStrategy.swift in Sources */ = {isa = PBXBuildFile; fileRef = D59CB1561C345E0A00290B63 /* TransformStrategy.swift */; }; - D59CB1711C34600E00290B63 /* BufferSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D59CB1701C34600E00290B63 /* BufferSpec.swift */; }; - D59CB1741C34610000290B63 /* ArrayExtensionsSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D59CB1731C34610000290B63 /* ArrayExtensionsSpec.swift */; }; - D59CB1781C3462C300290B63 /* FFTTransformerSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D59CB1771C3462C300290B63 /* FFTTransformerSpec.swift */; }; - D59CB17A1C34652200290B63 /* TransformFactorySpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D59CB1791C34652200290B63 /* TransformFactorySpec.swift */; }; - D59CB17D1C34665800290B63 /* EstimatorSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D59CB17C1C34665800290B63 /* EstimatorSpec.swift */; }; - D59CB17F1C34666900290B63 /* EstimationFactorySpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D59CB17E1C34666900290B63 /* EstimationFactorySpec.swift */; }; - D59CB1811C34692E00290B63 /* ConfigSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D59CB1801C34692E00290B63 /* ConfigSpec.swift */; }; D5A49C751C343EC300427BF8 /* Quick.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D5A49C731C343EC300427BF8 /* Quick.framework */; }; D5A49C761C343EC300427BF8 /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D5A49C741C343EC300427BF8 /* Nimble.framework */; }; D5A49CDE1C3458EA00427BF8 /* Pitchy.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D5A49CDD1C3458EA00427BF8 /* Pitchy.framework */; }; @@ -58,16 +55,25 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - AF3190511DABE01600C897CA /* YINTransformer.swift */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.swift; path = YINTransformer.swift; sourceTree = ""; tabWidth = 4; }; - AF4AFD991DAA3462002B6DC9 /* YINUtil.swift */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.swift; path = YINUtil.swift; sourceTree = ""; tabWidth = 4; }; + AF3190511DABE01600C897CA /* YINTransformer.swift */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.swift; path = YINTransformer.swift; sourceTree = ""; tabWidth = 2; }; AFFF3FF01DB633B4004AD9D9 /* YINEstimator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YINEstimator.swift; sourceTree = ""; }; 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; }; + D55C01F71DBD210600575260 /* ConfigSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConfigSpec.swift; sourceTree = ""; }; + D55C01FB1DBD210600575260 /* EstimationFactorySpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EstimationFactorySpec.swift; sourceTree = ""; }; + D55C01FC1DBD210600575260 /* EstimatorSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EstimatorSpec.swift; sourceTree = ""; }; + D55C01FE1DBD210600575260 /* ArrayExtensionsSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArrayExtensionsSpec.swift; sourceTree = ""; }; + D55C02011DBD210600575260 /* FFTTransformerSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FFTTransformerSpec.swift; sourceTree = ""; }; + D55C02041DBD210600575260 /* Info-iOS-Tests.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info-iOS-Tests.plist"; sourceTree = ""; }; + D55C02051DBD210600575260 /* Info-iOS.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info-iOS.plist"; sourceTree = ""; }; + D5843EDE1DBD2CF50077F86E /* Buffer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Buffer.swift; sourceTree = ""; }; + D5843EE11DBD2D110077F86E /* Array+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Array+Extensions.swift"; sourceTree = ""; }; + D5843EE31DBD2D290077F86E /* YINUtil.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YINUtil.swift; sourceTree = ""; }; + D5843EE51DBD2FAA0077F86E /* EstimationFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EstimationFactory.swift; sourceTree = ""; }; + D5843EE61DBD2FAA0077F86E /* EstimationStrategy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EstimationStrategy.swift; sourceTree = ""; }; + D5843EEA1DBD34680077F86E /* BufferSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BufferSpec.swift; sourceTree = ""; }; D59CB1371C345E0A00290B63 /* Config.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Config.swift; sourceTree = ""; }; - D59CB1391C345E0A00290B63 /* Buffer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Buffer.swift; sourceTree = ""; }; D59CB13B1C345E0A00290B63 /* EstimationError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EstimationError.swift; sourceTree = ""; }; - D59CB13C1C345E0A00290B63 /* EstimationFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.swift; path = EstimationFactory.swift; sourceTree = ""; tabWidth = 2; }; - D59CB13D1C345E0A00290B63 /* EstimationStrategy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EstimationStrategy.swift; sourceTree = ""; }; D59CB13E1C345E0A00290B63 /* Estimator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Estimator.swift; sourceTree = ""; }; D59CB13F1C345E0A00290B63 /* LocationEstimator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocationEstimator.swift; sourceTree = ""; }; D59CB1411C345E0A00290B63 /* BarycentricEstimator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BarycentricEstimator.swift; sourceTree = ""; }; @@ -77,7 +83,6 @@ D59CB1451C345E0A00290B63 /* QuadradicEstimator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QuadradicEstimator.swift; sourceTree = ""; }; D59CB1461C345E0A00290B63 /* QuinnsFirstEstimator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QuinnsFirstEstimator.swift; sourceTree = ""; }; D59CB1471C345E0A00290B63 /* QuinnsSecondEstimator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QuinnsSecondEstimator.swift; sourceTree = ""; }; - D59CB1491C345E0A00290B63 /* Array+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Array+Extensions.swift"; sourceTree = ""; }; D59CB14A1C345E0A00290B63 /* PitchEngine.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PitchEngine.swift; sourceTree = ""; }; D59CB14C1C345E0A00290B63 /* SignalTracker.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SignalTracker.swift; sourceTree = ""; }; D59CB14E1C345E0A00290B63 /* InputSignalTracker.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InputSignalTracker.swift; sourceTree = ""; }; @@ -85,21 +90,8 @@ D59CB1521C345E0A00290B63 /* FFTTransformer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FFTTransformer.swift; sourceTree = ""; }; D59CB1531C345E0A00290B63 /* SimpleTransformer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SimpleTransformer.swift; sourceTree = ""; }; D59CB1541C345E0A00290B63 /* Transformer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Transformer.swift; sourceTree = ""; }; - D59CB1551C345E0A00290B63 /* TransformFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransformFactory.swift; sourceTree = ""; }; - D59CB1561C345E0A00290B63 /* TransformStrategy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransformStrategy.swift; sourceTree = ""; }; - D59CB1701C34600E00290B63 /* BufferSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BufferSpec.swift; sourceTree = ""; }; - D59CB1731C34610000290B63 /* ArrayExtensionsSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArrayExtensionsSpec.swift; sourceTree = ""; }; - D59CB1771C3462C300290B63 /* FFTTransformerSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FFTTransformerSpec.swift; sourceTree = ""; }; - D59CB1791C34652200290B63 /* TransformFactorySpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransformFactorySpec.swift; sourceTree = ""; }; - D59CB17C1C34665800290B63 /* EstimatorSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EstimatorSpec.swift; sourceTree = ""; }; - D59CB17E1C34666900290B63 /* EstimationFactorySpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EstimationFactorySpec.swift; sourceTree = ""; }; - D59CB1801C34692E00290B63 /* ConfigSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConfigSpec.swift; sourceTree = ""; }; D5A49C731C343EC300427BF8 /* Quick.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Quick.framework; path = Carthage/Build/iOS/Quick.framework; sourceTree = ""; }; D5A49C741C343EC300427BF8 /* Nimble.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Nimble.framework; path = Carthage/Build/iOS/Nimble.framework; sourceTree = ""; }; - D5A49CD01C343FD700427BF8 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - D5A49CD21C343FD700427BF8 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - D5A49CD61C343FD700427BF8 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - D5A49CD81C343FD700427BF8 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; D5A49CDD1C3458EA00427BF8 /* Pitchy.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Pitchy.framework; path = Carthage/Build/iOS/Pitchy.framework; sourceTree = ""; }; /* End PBXFileReference section */ @@ -128,13 +120,11 @@ D51575A11C343B77006F8E75 = { isa = PBXGroup; children = ( - D5A49C731C343EC300427BF8 /* Quick.framework */, - D5A49C741C343EC300427BF8 /* Nimble.framework */, - D5A49CDD1C3458EA00427BF8 /* Pitchy.framework */, - D59CB1361C345E0A00290B63 /* Source */, - D5A49CD41C343FD700427BF8 /* Beethoven */, - D5A49CCE1C343FD700427BF8 /* BeethovenTests */, + D55C01F41DBD1F8100575260 /* Frameworks */, D51575AC1C343B77006F8E75 /* Products */, + D55C02031DBD210600575260 /* Project */, + D59CB1361C345E0A00290B63 /* Source */, + D55C01F51DBD210600575260 /* Tests */, ); indentWidth = 2; sourceTree = ""; @@ -149,207 +139,180 @@ name = Products; sourceTree = ""; }; - D59CB1361C345E0A00290B63 /* Source */ = { + D55C01F41DBD1F8100575260 /* Frameworks */ = { isa = PBXGroup; children = ( - D59CB1381C345E0A00290B63 /* Data */, - D59CB1481C345E0A00290B63 /* Extensions */, - D59CB14B1C345E0A00290B63 /* SignalTracking */, - D59CB1501C345E0A00290B63 /* Transform */, - D59CB13A1C345E0A00290B63 /* Estimation */, - D59CB14A1C345E0A00290B63 /* PitchEngine.swift */, - D59CB1371C345E0A00290B63 /* Config.swift */, + D5A49C731C343EC300427BF8 /* Quick.framework */, + D5A49C741C343EC300427BF8 /* Nimble.framework */, + D5A49CDD1C3458EA00427BF8 /* Pitchy.framework */, ); - path = Source; + name = Frameworks; sourceTree = ""; }; - D59CB1381C345E0A00290B63 /* Data */ = { + D55C01F51DBD210600575260 /* Tests */ = { isa = PBXGroup; children = ( - D59CB1391C345E0A00290B63 /* Buffer.swift */, + D55C01F61DBD210600575260 /* Spec */, ); - path = Data; + path = Tests; sourceTree = ""; }; - D59CB13A1C345E0A00290B63 /* Estimation */ = { + D55C01F61DBD210600575260 /* Spec */ = { isa = PBXGroup; children = ( - D59CB1401C345E0A00290B63 /* Strategies */, - D59CB13B1C345E0A00290B63 /* EstimationError.swift */, - D59CB13C1C345E0A00290B63 /* EstimationFactory.swift */, - D59CB13D1C345E0A00290B63 /* EstimationStrategy.swift */, - D59CB13E1C345E0A00290B63 /* Estimator.swift */, - D59CB13F1C345E0A00290B63 /* LocationEstimator.swift */, - AF4AFD991DAA3462002B6DC9 /* YINUtil.swift */, + D55C01F71DBD210600575260 /* ConfigSpec.swift */, + D55C01FA1DBD210600575260 /* Estimation */, + D55C01FD1DBD210600575260 /* Extensions */, + D5843EE91DBD34680077F86E /* Library */, + D55C01FF1DBD210600575260 /* Transform */, ); - path = Estimation; + path = Spec; sourceTree = ""; }; - D59CB1401C345E0A00290B63 /* Strategies */ = { + D55C01FA1DBD210600575260 /* Estimation */ = { isa = PBXGroup; children = ( - D59CB1411C345E0A00290B63 /* BarycentricEstimator.swift */, - D59CB1421C345E0A00290B63 /* HPSEstimator.swift */, - D59CB1431C345E0A00290B63 /* JainsEstimator.swift */, - D59CB1441C345E0A00290B63 /* MaxValueEstimator.swift */, - D59CB1451C345E0A00290B63 /* QuadradicEstimator.swift */, - D59CB1461C345E0A00290B63 /* QuinnsFirstEstimator.swift */, - D59CB1471C345E0A00290B63 /* QuinnsSecondEstimator.swift */, - AFFF3FF01DB633B4004AD9D9 /* YINEstimator.swift */, + D55C01FB1DBD210600575260 /* EstimationFactorySpec.swift */, + D55C01FC1DBD210600575260 /* EstimatorSpec.swift */, ); - path = Strategies; + path = Estimation; sourceTree = ""; }; - D59CB1481C345E0A00290B63 /* Extensions */ = { + D55C01FD1DBD210600575260 /* Extensions */ = { isa = PBXGroup; children = ( - D59CB1491C345E0A00290B63 /* Array+Extensions.swift */, + D55C01FE1DBD210600575260 /* ArrayExtensionsSpec.swift */, ); path = Extensions; sourceTree = ""; }; - D59CB14B1C345E0A00290B63 /* SignalTracking */ = { - isa = PBXGroup; - children = ( - D59CB14D1C345E0A00290B63 /* Units */, - D59CB14C1C345E0A00290B63 /* SignalTracker.swift */, - ); - path = SignalTracking; - sourceTree = ""; - }; - D59CB14D1C345E0A00290B63 /* Units */ = { - isa = PBXGroup; - children = ( - D59CB14E1C345E0A00290B63 /* InputSignalTracker.swift */, - D59CB14F1C345E0A00290B63 /* OutputSignalTracker.swift */, - ); - path = Units; - sourceTree = ""; - }; - D59CB1501C345E0A00290B63 /* Transform */ = { + D55C01FF1DBD210600575260 /* Transform */ = { isa = PBXGroup; children = ( - D59CB1511C345E0A00290B63 /* Strategies */, - D59CB1541C345E0A00290B63 /* Transformer.swift */, - D59CB1551C345E0A00290B63 /* TransformFactory.swift */, - D59CB1561C345E0A00290B63 /* TransformStrategy.swift */, + D55C02001DBD210600575260 /* Strategies */, ); path = Transform; sourceTree = ""; }; - D59CB1511C345E0A00290B63 /* Strategies */ = { + D55C02001DBD210600575260 /* Strategies */ = { isa = PBXGroup; children = ( - D59CB1521C345E0A00290B63 /* FFTTransformer.swift */, - D59CB1531C345E0A00290B63 /* SimpleTransformer.swift */, - AF3190511DABE01600C897CA /* YINTransformer.swift */, + D55C02011DBD210600575260 /* FFTTransformerSpec.swift */, ); path = Strategies; sourceTree = ""; }; - D59CB16F1C345FFE00290B63 /* Data */ = { - isa = PBXGroup; - children = ( - D59CB1701C34600E00290B63 /* BufferSpec.swift */, - ); - path = Data; - sourceTree = ""; - }; - D59CB1721C3460EB00290B63 /* Extensions */ = { + D55C02031DBD210600575260 /* Project */ = { isa = PBXGroup; children = ( - D59CB1731C34610000290B63 /* ArrayExtensionsSpec.swift */, + D55C02041DBD210600575260 /* Info-iOS-Tests.plist */, + D55C02051DBD210600575260 /* Info-iOS.plist */, ); - path = Extensions; + path = Project; sourceTree = ""; }; - D59CB1751C3462A100290B63 /* Transform */ = { + D5843EDD1DBD2CF50077F86E /* Library */ = { isa = PBXGroup; children = ( - D59CB1761C3462AD00290B63 /* Strategies */, - D59CB1791C34652200290B63 /* TransformFactorySpec.swift */, + D5843EE01DBD2D110077F86E /* Extensions */, + D5843EE31DBD2D290077F86E /* YINUtil.swift */, + D5843EDE1DBD2CF50077F86E /* Buffer.swift */, ); - path = Transform; + path = Library; sourceTree = ""; }; - D59CB1761C3462AD00290B63 /* Strategies */ = { + D5843EE01DBD2D110077F86E /* Extensions */ = { isa = PBXGroup; children = ( - D59CB1771C3462C300290B63 /* FFTTransformerSpec.swift */, + D5843EE11DBD2D110077F86E /* Array+Extensions.swift */, ); - path = Strategies; + path = Extensions; sourceTree = ""; }; - D59CB17B1C34662900290B63 /* Estimation */ = { + D5843EE91DBD34680077F86E /* Library */ = { isa = PBXGroup; children = ( - D59CB17C1C34665800290B63 /* EstimatorSpec.swift */, - D59CB17E1C34666900290B63 /* EstimationFactorySpec.swift */, + D5843EEA1DBD34680077F86E /* BufferSpec.swift */, ); - path = Estimation; + path = Library; sourceTree = ""; }; - D5A49CCE1C343FD700427BF8 /* BeethovenTests */ = { + D59CB1361C345E0A00290B63 /* Source */ = { isa = PBXGroup; children = ( - D5A49CCF1C343FD700427BF8 /* iOS */, - D5A49CD11C343FD700427BF8 /* Mac */, - D5A49CD31C343FD700427BF8 /* Spec */, + D59CB1371C345E0A00290B63 /* Config.swift */, + D59CB14A1C345E0A00290B63 /* PitchEngine.swift */, + D59CB13A1C345E0A00290B63 /* Estimation */, + D5843EDD1DBD2CF50077F86E /* Library */, + D59CB14B1C345E0A00290B63 /* SignalTracking */, + D59CB1501C345E0A00290B63 /* Transform */, ); - path = BeethovenTests; + path = Source; sourceTree = ""; }; - D5A49CCF1C343FD700427BF8 /* iOS */ = { + D59CB13A1C345E0A00290B63 /* Estimation */ = { isa = PBXGroup; children = ( - D5A49CD01C343FD700427BF8 /* Info.plist */, + D59CB13B1C345E0A00290B63 /* EstimationError.swift */, + D5843EE51DBD2FAA0077F86E /* EstimationFactory.swift */, + D5843EE61DBD2FAA0077F86E /* EstimationStrategy.swift */, + D59CB13E1C345E0A00290B63 /* Estimator.swift */, + D59CB13F1C345E0A00290B63 /* LocationEstimator.swift */, + D59CB1401C345E0A00290B63 /* Strategies */, ); - path = iOS; + path = Estimation; sourceTree = ""; }; - D5A49CD11C343FD700427BF8 /* Mac */ = { + D59CB1401C345E0A00290B63 /* Strategies */ = { isa = PBXGroup; children = ( - D5A49CD21C343FD700427BF8 /* Info.plist */, + D59CB1411C345E0A00290B63 /* BarycentricEstimator.swift */, + D59CB1421C345E0A00290B63 /* HPSEstimator.swift */, + D59CB1431C345E0A00290B63 /* JainsEstimator.swift */, + D59CB1441C345E0A00290B63 /* MaxValueEstimator.swift */, + D59CB1451C345E0A00290B63 /* QuadradicEstimator.swift */, + D59CB1461C345E0A00290B63 /* QuinnsFirstEstimator.swift */, + D59CB1471C345E0A00290B63 /* QuinnsSecondEstimator.swift */, + AFFF3FF01DB633B4004AD9D9 /* YINEstimator.swift */, ); - path = Mac; + path = Strategies; sourceTree = ""; }; - D5A49CD31C343FD700427BF8 /* Spec */ = { + D59CB14B1C345E0A00290B63 /* SignalTracking */ = { isa = PBXGroup; children = ( - D59CB16F1C345FFE00290B63 /* Data */, - D59CB1721C3460EB00290B63 /* Extensions */, - D59CB1751C3462A100290B63 /* Transform */, - D59CB17B1C34662900290B63 /* Estimation */, - D59CB1801C34692E00290B63 /* ConfigSpec.swift */, + D59CB14D1C345E0A00290B63 /* Units */, + D59CB14C1C345E0A00290B63 /* SignalTracker.swift */, ); - path = Spec; + path = SignalTracking; sourceTree = ""; }; - D5A49CD41C343FD700427BF8 /* Beethoven */ = { + D59CB14D1C345E0A00290B63 /* Units */ = { isa = PBXGroup; children = ( - D5A49CD51C343FD700427BF8 /* iOS */, - D5A49CD71C343FD700427BF8 /* Mac */, + D59CB14E1C345E0A00290B63 /* InputSignalTracker.swift */, + D59CB14F1C345E0A00290B63 /* OutputSignalTracker.swift */, ); - path = Beethoven; + path = Units; sourceTree = ""; }; - D5A49CD51C343FD700427BF8 /* iOS */ = { + D59CB1501C345E0A00290B63 /* Transform */ = { isa = PBXGroup; children = ( - D5A49CD61C343FD700427BF8 /* Info.plist */, + D59CB1511C345E0A00290B63 /* Strategies */, + D59CB1541C345E0A00290B63 /* Transformer.swift */, ); - path = iOS; + path = Transform; sourceTree = ""; }; - D5A49CD71C343FD700427BF8 /* Mac */ = { + D59CB1511C345E0A00290B63 /* Strategies */ = { isa = PBXGroup; children = ( - D5A49CD81C343FD700427BF8 /* Info.plist */, + D59CB1521C345E0A00290B63 /* FFTTransformer.swift */, + D59CB1531C345E0A00290B63 /* SimpleTransformer.swift */, + AF3190511DABE01600C897CA /* YINTransformer.swift */, ); - path = Mac; + path = Strategies; sourceTree = ""; }; /* End PBXGroup section */ @@ -374,6 +337,7 @@ D51575A81C343B77006F8E75 /* Headers */, D51575A91C343B77006F8E75 /* Resources */, D5A49CE11C34591300427BF8 /* Copy frameworks with Carthage */, + D55C01F31DBD1BF400575260 /* SwiftLint */, ); buildRules = ( ); @@ -410,7 +374,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; + LastUpgradeCheck = 0800; ORGANIZATIONNAME = "Vadym Markov"; TargetAttributes = { D51575AA1C343B77006F8E75 = { @@ -459,6 +423,20 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ + D55C01F31DBD1BF400575260 /* SwiftLint */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = SwiftLint; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "if which swiftlint >/dev/null; then\nswiftlint\nelse\necho \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi"; + }; D5A49C7B1C343EF300427BF8 /* Copy frameworks with Carthage */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -498,15 +476,11 @@ buildActionMask = 2147483647; files = ( D59CB1641C345E0A00290B63 /* QuinnsSecondEstimator.swift in Sources */, - D59CB16E1C345E0A00290B63 /* TransformStrategy.swift in Sources */, - D59CB1651C345E0A00290B63 /* Array+Extensions.swift in Sources */, D59CB1601C345E0A00290B63 /* JainsEstimator.swift in Sources */, D59CB15C1C345E0A00290B63 /* Estimator.swift in Sources */, D59CB15D1C345E0A00290B63 /* LocationEstimator.swift in Sources */, - D59CB16D1C345E0A00290B63 /* TransformFactory.swift in Sources */, D59CB1631C345E0A00290B63 /* QuinnsFirstEstimator.swift in Sources */, - D59CB15B1C345E0A00290B63 /* EstimationStrategy.swift in Sources */, - AF4AFD9A1DAA3462002B6DC9 /* YINUtil.swift in Sources */, + D5843EE81DBD2FAA0077F86E /* EstimationStrategy.swift in Sources */, D59CB15E1C345E0A00290B63 /* BarycentricEstimator.swift in Sources */, D59CB1621C345E0A00290B63 /* QuadradicEstimator.swift in Sources */, D59CB1591C345E0A00290B63 /* EstimationError.swift in Sources */, @@ -515,15 +489,17 @@ D59CB16C1C345E0A00290B63 /* Transformer.swift in Sources */, D59CB1661C345E0A00290B63 /* PitchEngine.swift in Sources */, D59CB1691C345E0A00290B63 /* OutputSignalTracker.swift in Sources */, + D5843EE41DBD2D290077F86E /* YINUtil.swift in Sources */, D59CB1611C345E0A00290B63 /* MaxValueEstimator.swift in Sources */, D59CB15F1C345E0A00290B63 /* HPSEstimator.swift in Sources */, D59CB16B1C345E0A00290B63 /* SimpleTransformer.swift in Sources */, + D5843EE21DBD2D110077F86E /* Array+Extensions.swift in Sources */, D59CB1571C345E0A00290B63 /* Config.swift in Sources */, D59CB1681C345E0A00290B63 /* InputSignalTracker.swift in Sources */, - D59CB1581C345E0A00290B63 /* Buffer.swift in Sources */, AF3190521DABE01600C897CA /* YINTransformer.swift in Sources */, + D5843EDF1DBD2CF50077F86E /* Buffer.swift in Sources */, D59CB16A1C345E0A00290B63 /* FFTTransformer.swift in Sources */, - D59CB15A1C345E0A00290B63 /* EstimationFactory.swift in Sources */, + D5843EE71DBD2FAA0077F86E /* EstimationFactory.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -531,13 +507,12 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - D59CB1811C34692E00290B63 /* ConfigSpec.swift in Sources */, - D59CB17A1C34652200290B63 /* TransformFactorySpec.swift in Sources */, - D59CB1781C3462C300290B63 /* FFTTransformerSpec.swift in Sources */, - D59CB1741C34610000290B63 /* ArrayExtensionsSpec.swift in Sources */, - D59CB17D1C34665800290B63 /* EstimatorSpec.swift in Sources */, - D59CB17F1C34666900290B63 /* EstimationFactorySpec.swift in Sources */, - D59CB1711C34600E00290B63 /* BufferSpec.swift in Sources */, + D55C02121DBD211E00575260 /* EstimatorSpec.swift in Sources */, + D55C02111DBD211E00575260 /* EstimationFactorySpec.swift in Sources */, + D55C02141DBD211E00575260 /* FFTTransformerSpec.swift in Sources */, + D55C02131DBD211E00575260 /* ArrayExtensionsSpec.swift in Sources */, + D5843EEC1DBD34AD0077F86E /* BufferSpec.swift in Sources */, + D55C020F1DBD211E00575260 /* ConfigSpec.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -565,8 +540,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"; @@ -613,8 +590,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"; @@ -634,6 +613,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 9.2; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; @@ -644,6 +624,7 @@ D51575C01C343B77006F8E75 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; @@ -652,7 +633,7 @@ "$(inherited)", "$(PROJECT_DIR)/Carthage/Build/iOS", ); - INFOPLIST_FILE = "$(SRCROOT)/Beethoven/iOS/Info.plist"; + INFOPLIST_FILE = "$(SRCROOT)/Project/Info-iOS.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; @@ -666,6 +647,7 @@ D51575C11C343B77006F8E75 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; @@ -674,7 +656,7 @@ "$(inherited)", "$(PROJECT_DIR)/Carthage/Build/iOS", ); - INFOPLIST_FILE = "$(SRCROOT)/Beethoven/iOS/Info.plist"; + INFOPLIST_FILE = "$(SRCROOT)/Project/Info-iOS.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; @@ -693,7 +675,7 @@ "$(inherited)", "$(PROJECT_DIR)/Carthage/Build/iOS", ); - INFOPLIST_FILE = "$(SRCROOT)/BeethovenTests/iOS/Info.plist"; + INFOPLIST_FILE = "$(SRCROOT)/Project/Info-iOS-Tests.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.vadymmarkov.BeethovenTests; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -710,7 +692,7 @@ "$(inherited)", "$(PROJECT_DIR)/Carthage/Build/iOS", ); - INFOPLIST_FILE = "$(SRCROOT)/BeethovenTests/iOS/Info.plist"; + INFOPLIST_FILE = "$(SRCROOT)/Project/Info-iOS-Tests.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.vadymmarkov.BeethovenTests; PRODUCT_NAME = "$(TARGET_NAME)"; diff --git a/Beethoven.xcodeproj/xcshareddata/xcschemes/Beethoven-iOS.xcscheme b/Beethoven.xcodeproj/xcshareddata/xcschemes/Beethoven-iOS.xcscheme index ce34f7f..6ea43e3 100644 --- a/Beethoven.xcodeproj/xcshareddata/xcschemes/Beethoven-iOS.xcscheme +++ b/Beethoven.xcodeproj/xcshareddata/xcschemes/Beethoven-iOS.xcscheme @@ -1,6 +1,6 @@ /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; + shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; showEnvVarsInLog = 0; }; 1962EBAD1F8E34314E982594 /* [CP] Check Pods Manifest.lock */ = { diff --git a/Example/GuitarTuner/GuitarTuner/Source/ViewController.swift b/Example/GuitarTuner/GuitarTuner/Source/ViewController.swift index 839b161..e09923c 100644 --- a/Example/GuitarTuner/GuitarTuner/Source/ViewController.swift +++ b/Example/GuitarTuner/GuitarTuner/Source/ViewController.swift @@ -18,7 +18,7 @@ class ViewController: UIViewController { return label }() - lazy var offsetLabel: UILabel = { [unowned self] in + lazy var offsetLabel: UILabel = { let label = UILabel() label.font = UIFont.systemFont(ofSize: 28) label.textColor = UIColor.white @@ -43,10 +43,8 @@ class ViewController: UIViewController { return button }() - lazy var pitchEngine: PitchEngine = { [unowned self] in - var config = Config() - config.transformStrategy = .yin - config.estimationStrategy = .yin + lazy var pitchEngine: PitchEngine = { [weak self] in + var config = Config(estimationStrategy: .yin) let pitchEngine = PitchEngine(config: config, delegate: self) pitchEngine.levelThreshold = -30.0 @@ -85,7 +83,7 @@ class ViewController: UIViewController { offsetLabel.isHidden = !pitchEngine.active } - // MARK: - Constrains + // MARK: - Layout func setupLayout() { let totalSize = UIScreen.main.bounds @@ -140,7 +138,7 @@ extension ViewController: PitchEngineDelegate { let offsetPercentage = pitch.closestOffset.percentage let absOffsetPercentage = abs(offsetPercentage) - NSLog("pitch : \(pitch.note.string) - percentage : \(offsetPercentage)") + print("pitch : \(pitch.note.string) - percentage : \(offsetPercentage)") guard absOffsetPercentage > 1.0 else { return @@ -159,7 +157,6 @@ extension ViewController: PitchEngineDelegate { } public func pitchEngineWentBelowLevelThreshold(_ pitchEngine: PitchEngine) { - + print("Below level threshold") } - } diff --git a/Example/GuitarTuner/Podfile.lock b/Example/GuitarTuner/Podfile.lock index 388ea65..72db953 100644 --- a/Example/GuitarTuner/Podfile.lock +++ b/Example/GuitarTuner/Podfile.lock @@ -1,5 +1,5 @@ PODS: - - Beethoven (2.0.0): + - Beethoven (3.0.0): - Pitchy - Cartography (1.0.1) - Hue (2.0.0) @@ -12,7 +12,7 @@ DEPENDENCIES: EXTERNAL SOURCES: Beethoven: - :path: ../../ + :path: "../../" Hue: :git: https://github.com/hyperoslo/Hue @@ -22,11 +22,11 @@ CHECKOUT OPTIONS: :git: https://github.com/hyperoslo/Hue SPEC CHECKSUMS: - Beethoven: 8dedb982e34b53a1a2c5c79ee879929d65710869 + Beethoven: 70d27286285b8d2a80c253b3da7db9b0d1157425 Cartography: c1460e99395b824d9d75360b0382faeb0b33dcd7 Hue: 2b317616a04cc5d7cccdb024c88e6d143e2b9cf1 Pitchy: 00dbe7cb7ac87fd9c32cb2aa6ce50d11f931289f PODFILE CHECKSUM: 1e153b4e2c75610a8ffdfdf508f1f60b13da109d -COCOAPODS: 1.0.1 +COCOAPODS: 1.1.0.rc.3 diff --git a/Package.swift b/Package.swift index c870b75..cdc5155 100644 --- a/Package.swift +++ b/Package.swift @@ -3,6 +3,6 @@ import PackageDescription let package = Package( name: "Beethoven", dependencies: [ - .Package(url: "https://github.com/vadymmarkov/Pitchy.git", majorVersion: 1), + .Package(url: "https://github.com/vadymmarkov/Pitchy.git", majorVersion: 2), ] ) diff --git a/Pod/Podfile b/Pod/Podfile deleted file mode 100644 index 8b8025f..0000000 --- a/Pod/Podfile +++ /dev/null @@ -1,7 +0,0 @@ -platform :ios, '8.0' -use_frameworks! -inhibit_all_warnings! - -pod 'Pitchy', git: 'https://github.com/vadymmarkov/Pitchy' -pod 'Nimble' -pod 'Quick' diff --git a/Pod/Podfile.lock b/Pod/Podfile.lock deleted file mode 100644 index 8cd3b9b..0000000 --- a/Pod/Podfile.lock +++ /dev/null @@ -1,25 +0,0 @@ -PODS: - - Nimble (3.0.0) - - Pitchy (0.1.0) - - Quick (0.8.0) - -DEPENDENCIES: - - Nimble - - Pitchy (from `https://github.com/vadymmarkov/Pitchy`) - - Quick - -EXTERNAL SOURCES: - Pitchy: - :git: https://github.com/vadymmarkov/Pitchy - -CHECKOUT OPTIONS: - Pitchy: - :commit: d88e2a8084c2aa59db6ee0fc17eb1cc100f2584d - :git: https://github.com/vadymmarkov/Pitchy - -SPEC CHECKSUMS: - Nimble: 4c353d43735b38b545cbb4cb91504588eb5de926 - Pitchy: a41a236f8bf01ac97f6790d1267c154ca4e86688 - Quick: 563d0f6ec5f72e394645adb377708639b7dd38ab - -COCOAPODS: 0.39.0 diff --git a/Pod/Tests/Info.plist b/Pod/Tests/Info.plist deleted file mode 100644 index ba72822..0000000 --- a/Pod/Tests/Info.plist +++ /dev/null @@ -1,24 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - BNDL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - - diff --git a/Pod/Tuner.xcodeproj/project.pbxproj b/Pod/Tuner.xcodeproj/project.pbxproj deleted file mode 100644 index e6da834..0000000 --- a/Pod/Tuner.xcodeproj/project.pbxproj +++ /dev/null @@ -1,538 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - D50800FF1C0E70F600168040 /* Array+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D50800FE1C0E70F600168040 /* Array+Extensions.swift */; }; - D55F5BAD1C066FF800B36AE5 /* Estimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D55F5B9E1C066FF800B36AE5 /* Estimator.swift */; }; - D55F5BC01C0675D900B36AE5 /* QuadradicEstimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D55F5BB91C0675D900B36AE5 /* QuadradicEstimator.swift */; }; - D55F5BC11C0675D900B36AE5 /* QuinnsSecondEstimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D55F5BBA1C0675D900B36AE5 /* QuinnsSecondEstimator.swift */; }; - D55F5BC21C0675D900B36AE5 /* HPSEstimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D55F5BBB1C0675D900B36AE5 /* HPSEstimator.swift */; }; - D55F5BC31C0675D900B36AE5 /* JainsEstimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D55F5BBC1C0675D900B36AE5 /* JainsEstimator.swift */; }; - D55F5BC41C0675D900B36AE5 /* QuinnsFirstEstimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D55F5BBD1C0675D900B36AE5 /* QuinnsFirstEstimator.swift */; }; - D55F5BC51C0675D900B36AE5 /* BarycentricEstimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D55F5BBE1C0675D900B36AE5 /* BarycentricEstimator.swift */; }; - D55F5BC61C0675D900B36AE5 /* MaxValueEstimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D55F5BBF1C0675D900B36AE5 /* MaxValueEstimator.swift */; }; - D55F5BD51C06793400B36AE5 /* SignalTracker.swift in Sources */ = {isa = PBXBuildFile; fileRef = D55F5BD11C06793400B36AE5 /* SignalTracker.swift */; }; - D55F5BD61C06793400B36AE5 /* InputSignalTracker.swift in Sources */ = {isa = PBXBuildFile; fileRef = D55F5BD31C06793400B36AE5 /* InputSignalTracker.swift */; }; - D55F5BD71C06793400B36AE5 /* OutputSignalTracker.swift in Sources */ = {isa = PBXBuildFile; fileRef = D55F5BD41C06793400B36AE5 /* OutputSignalTracker.swift */; }; - D5B7CBB21C1E0CF7002DDCCE /* Buffer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5B7CBB11C1E0CF7002DDCCE /* Buffer.swift */; }; - D5B7CBB41C1E0DCF002DDCCE /* LocationEstimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5B7CBB31C1E0DCF002DDCCE /* LocationEstimator.swift */; }; - D5B7CBB61C1E0E73002DDCCE /* EstimationError.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5B7CBB51C1E0E73002DDCCE /* EstimationError.swift */; }; - D5BE32F21BE815FB00945677 /* PitchEngine.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5BE32F11BE815FB00945677 /* PitchEngine.swift */; }; - D5C175131C0FC80300E1BE4E /* Config.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5C175121C0FC80300E1BE4E /* Config.swift */; }; - D5C175151C0FC8BE00E1BE4E /* EstimationStrategy.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5C175141C0FC8BE00E1BE4E /* EstimationStrategy.swift */; }; - D5C175201C0FC9F500E1BE4E /* FFTTransformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5C1751B1C0FC9F500E1BE4E /* FFTTransformer.swift */; }; - D5C175211C0FC9F500E1BE4E /* SimpleTransformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5C1751C1C0FC9F500E1BE4E /* SimpleTransformer.swift */; }; - D5C175221C0FC9F500E1BE4E /* Transformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5C1751D1C0FC9F500E1BE4E /* Transformer.swift */; }; - D5C175231C0FC9F500E1BE4E /* TransformStrategy.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5C1751E1C0FC9F500E1BE4E /* TransformStrategy.swift */; }; - D5C175271C0FCA6E00E1BE4E /* EstimationFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5C175261C0FCA6E00E1BE4E /* EstimationFactory.swift */; }; - D5C175291C0FD15900E1BE4E /* TransformFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5C175281C0FD15900E1BE4E /* TransformFactory.swift */; }; - ED55ACED4108BAAD20C2F684 /* Pods.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7BBA2578CC3D0D752EAD4195 /* Pods.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 146D72AC1AB782920058798C /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 146D72B11AB782920058798C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 14C136511AB784B200B7B07A /* .travis.yml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = .travis.yml; path = ../.travis.yml; sourceTree = ""; }; - 14C136521AB784B200B7B07A /* CONTRIBUTING.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; name = CONTRIBUTING.md; path = ../CONTRIBUTING.md; sourceTree = ""; }; - 14C136541AB784B200B7B07A /* LICENSE.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; name = LICENSE.md; path = ../LICENSE.md; sourceTree = ""; }; - 14C136551AB784B200B7B07A /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; - 716897C2D5B5626C8648DBB1 /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = ""; }; - 7BBA2578CC3D0D752EAD4195 /* Pods.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - D50800FE1C0E70F600168040 /* Array+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Array+Extensions.swift"; sourceTree = ""; }; - D55F5B9E1C066FF800B36AE5 /* Estimator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Estimator.swift; sourceTree = ""; }; - D55F5BB91C0675D900B36AE5 /* QuadradicEstimator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QuadradicEstimator.swift; sourceTree = ""; }; - D55F5BBA1C0675D900B36AE5 /* QuinnsSecondEstimator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QuinnsSecondEstimator.swift; sourceTree = ""; }; - D55F5BBB1C0675D900B36AE5 /* HPSEstimator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HPSEstimator.swift; sourceTree = ""; }; - D55F5BBC1C0675D900B36AE5 /* JainsEstimator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JainsEstimator.swift; sourceTree = ""; }; - D55F5BBD1C0675D900B36AE5 /* QuinnsFirstEstimator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QuinnsFirstEstimator.swift; sourceTree = ""; }; - D55F5BBE1C0675D900B36AE5 /* BarycentricEstimator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BarycentricEstimator.swift; sourceTree = ""; }; - D55F5BBF1C0675D900B36AE5 /* MaxValueEstimator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MaxValueEstimator.swift; sourceTree = ""; }; - D55F5BD11C06793400B36AE5 /* SignalTracker.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SignalTracker.swift; sourceTree = ""; }; - D55F5BD31C06793400B36AE5 /* InputSignalTracker.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InputSignalTracker.swift; sourceTree = ""; }; - D55F5BD41C06793400B36AE5 /* OutputSignalTracker.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OutputSignalTracker.swift; sourceTree = ""; }; - D5B7CBB11C1E0CF7002DDCCE /* Buffer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Buffer.swift; sourceTree = ""; }; - D5B7CBB31C1E0DCF002DDCCE /* LocationEstimator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocationEstimator.swift; sourceTree = ""; }; - D5B7CBB51C1E0E73002DDCCE /* EstimationError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EstimationError.swift; sourceTree = ""; }; - D5BE32F11BE815FB00945677 /* PitchEngine.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PitchEngine.swift; sourceTree = ""; }; - D5C175121C0FC80300E1BE4E /* Config.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Config.swift; sourceTree = ""; }; - D5C175141C0FC8BE00E1BE4E /* EstimationStrategy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EstimationStrategy.swift; sourceTree = ""; }; - D5C1751B1C0FC9F500E1BE4E /* FFTTransformer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FFTTransformer.swift; sourceTree = ""; }; - D5C1751C1C0FC9F500E1BE4E /* SimpleTransformer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SimpleTransformer.swift; sourceTree = ""; }; - D5C1751D1C0FC9F500E1BE4E /* Transformer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Transformer.swift; sourceTree = ""; }; - D5C1751E1C0FC9F500E1BE4E /* TransformStrategy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransformStrategy.swift; sourceTree = ""; }; - D5C175261C0FCA6E00E1BE4E /* EstimationFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EstimationFactory.swift; sourceTree = ""; }; - D5C175281C0FD15900E1BE4E /* TransformFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransformFactory.swift; sourceTree = ""; }; - FDF848418969FFB5A7D6A669 /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 146D72A91AB782920058798C /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ED55ACED4108BAAD20C2F684 /* Pods.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 146D728A1AB782920058798C = { - isa = PBXGroup; - children = ( - 14C1365B1AB784BC00B7B07A /* Source */, - 14C136501AB7849300B7B07A /* Metadata */, - 146D72AF1AB782920058798C /* Tests */, - 146D72941AB782920058798C /* Products */, - 7649234BAD996796266563CF /* Pods */, - 92E1BAB7F59123A52219F625 /* Frameworks */, - ); - indentWidth = 2; - sourceTree = ""; - tabWidth = 2; - }; - 146D72941AB782920058798C /* Products */ = { - isa = PBXGroup; - children = ( - 146D72AC1AB782920058798C /* Tests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 146D72AF1AB782920058798C /* Tests */ = { - isa = PBXGroup; - children = ( - 146D72B01AB782920058798C /* Supporting Files */, - ); - path = Tests; - sourceTree = ""; - }; - 146D72B01AB782920058798C /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 146D72B11AB782920058798C /* Info.plist */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 14C136501AB7849300B7B07A /* Metadata */ = { - isa = PBXGroup; - children = ( - 14C136511AB784B200B7B07A /* .travis.yml */, - 14C136521AB784B200B7B07A /* CONTRIBUTING.md */, - 14C136541AB784B200B7B07A /* LICENSE.md */, - 14C136551AB784B200B7B07A /* README.md */, - ); - name = Metadata; - sourceTree = ""; - }; - 14C1365B1AB784BC00B7B07A /* Source */ = { - isa = PBXGroup; - children = ( - D5B7CBB01C1E0CE1002DDCCE /* Data */, - D50800FD1C0E70E800168040 /* Extensions */, - D55F5BD01C06793400B36AE5 /* SignalTracking */, - D55F5B9C1C066FF800B36AE5 /* Estimation */, - D5C175181C0FC9F500E1BE4E /* Transform */, - D5C175121C0FC80300E1BE4E /* Config.swift */, - D5BE32F11BE815FB00945677 /* PitchEngine.swift */, - ); - name = Source; - path = ../Source; - sourceTree = ""; - }; - 7649234BAD996796266563CF /* Pods */ = { - isa = PBXGroup; - children = ( - 716897C2D5B5626C8648DBB1 /* Pods.debug.xcconfig */, - FDF848418969FFB5A7D6A669 /* Pods.release.xcconfig */, - ); - name = Pods; - sourceTree = ""; - }; - 92E1BAB7F59123A52219F625 /* Frameworks */ = { - isa = PBXGroup; - children = ( - 7BBA2578CC3D0D752EAD4195 /* Pods.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; - D50800FD1C0E70E800168040 /* Extensions */ = { - isa = PBXGroup; - children = ( - D50800FE1C0E70F600168040 /* Array+Extensions.swift */, - ); - path = Extensions; - sourceTree = ""; - }; - D55F5B9C1C066FF800B36AE5 /* Estimation */ = { - isa = PBXGroup; - children = ( - D55F5BB81C06750200B36AE5 /* Strategies */, - D55F5B9E1C066FF800B36AE5 /* Estimator.swift */, - D5B7CBB31C1E0DCF002DDCCE /* LocationEstimator.swift */, - D5B7CBB51C1E0E73002DDCCE /* EstimationError.swift */, - D5C175141C0FC8BE00E1BE4E /* EstimationStrategy.swift */, - D5C175261C0FCA6E00E1BE4E /* EstimationFactory.swift */, - ); - path = Estimation; - sourceTree = ""; - }; - D55F5BB81C06750200B36AE5 /* Strategies */ = { - isa = PBXGroup; - children = ( - D55F5BBF1C0675D900B36AE5 /* MaxValueEstimator.swift */, - D55F5BB91C0675D900B36AE5 /* QuadradicEstimator.swift */, - D55F5BBE1C0675D900B36AE5 /* BarycentricEstimator.swift */, - D55F5BBD1C0675D900B36AE5 /* QuinnsFirstEstimator.swift */, - D55F5BBA1C0675D900B36AE5 /* QuinnsSecondEstimator.swift */, - D55F5BBC1C0675D900B36AE5 /* JainsEstimator.swift */, - D55F5BBB1C0675D900B36AE5 /* HPSEstimator.swift */, - ); - path = Strategies; - sourceTree = ""; - }; - D55F5BD01C06793400B36AE5 /* SignalTracking */ = { - isa = PBXGroup; - children = ( - D55F5BD21C06793400B36AE5 /* Units */, - D55F5BD11C06793400B36AE5 /* SignalTracker.swift */, - ); - path = SignalTracking; - sourceTree = ""; - }; - D55F5BD21C06793400B36AE5 /* Units */ = { - isa = PBXGroup; - children = ( - D55F5BD31C06793400B36AE5 /* InputSignalTracker.swift */, - D55F5BD41C06793400B36AE5 /* OutputSignalTracker.swift */, - ); - path = Units; - sourceTree = ""; - }; - D5B7CBB01C1E0CE1002DDCCE /* Data */ = { - isa = PBXGroup; - children = ( - D5B7CBB11C1E0CF7002DDCCE /* Buffer.swift */, - ); - path = Data; - sourceTree = ""; - }; - D5C175181C0FC9F500E1BE4E /* Transform */ = { - isa = PBXGroup; - children = ( - D5C1751A1C0FC9F500E1BE4E /* Strategies */, - D5C1751D1C0FC9F500E1BE4E /* Transformer.swift */, - D5C1751E1C0FC9F500E1BE4E /* TransformStrategy.swift */, - D5C175281C0FD15900E1BE4E /* TransformFactory.swift */, - ); - path = Transform; - sourceTree = ""; - }; - D5C1751A1C0FC9F500E1BE4E /* Strategies */ = { - isa = PBXGroup; - children = ( - D5C1751B1C0FC9F500E1BE4E /* FFTTransformer.swift */, - D5C1751C1C0FC9F500E1BE4E /* SimpleTransformer.swift */, - ); - path = Strategies; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 146D72AB1AB782920058798C /* Tests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 146D72B91AB782920058798C /* Build configuration list for PBXNativeTarget "Tests" */; - buildPhases = ( - E463113BCE3E1D98B0F78F70 /* Check Pods Manifest.lock */, - 146D72A81AB782920058798C /* Sources */, - 146D72A91AB782920058798C /* Frameworks */, - 146D72AA1AB782920058798C /* Resources */, - ED1F367A5318D5FEAC1CEB6C /* Embed Pods Frameworks */, - 5BFF4B1EB33F9A8C837009EB /* Copy Pods Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = Tests; - productName = PodTests; - productReference = 146D72AC1AB782920058798C /* Tests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 146D728B1AB782920058798C /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 0700; - LastUpgradeCheck = 0700; - ORGANIZATIONNAME = Example; - TargetAttributes = { - 146D72AB1AB782920058798C = { - CreatedOnToolsVersion = 6.2; - }; - }; - }; - buildConfigurationList = 146D728E1AB782920058798C /* Build configuration list for PBXProject "Tuner" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 146D728A1AB782920058798C; - productRefGroup = 146D72941AB782920058798C /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 146D72AB1AB782920058798C /* Tests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 146D72AA1AB782920058798C /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 5BFF4B1EB33F9A8C837009EB /* Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Copy Pods Resources"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; - E463113BCE3E1D98B0F78F70 /* Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Check Pods Manifest.lock"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; - showEnvVarsInLog = 0; - }; - ED1F367A5318D5FEAC1CEB6C /* Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Embed Pods Frameworks"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 146D72A81AB782920058798C /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - D55F5BC01C0675D900B36AE5 /* QuadradicEstimator.swift in Sources */, - D55F5BC11C0675D900B36AE5 /* QuinnsSecondEstimator.swift in Sources */, - D5C175151C0FC8BE00E1BE4E /* EstimationStrategy.swift in Sources */, - D55F5BAD1C066FF800B36AE5 /* Estimator.swift in Sources */, - D5BE32F21BE815FB00945677 /* PitchEngine.swift in Sources */, - D55F5BD51C06793400B36AE5 /* SignalTracker.swift in Sources */, - D55F5BC51C0675D900B36AE5 /* BarycentricEstimator.swift in Sources */, - D5B7CBB21C1E0CF7002DDCCE /* Buffer.swift in Sources */, - D55F5BC31C0675D900B36AE5 /* JainsEstimator.swift in Sources */, - D5C175271C0FCA6E00E1BE4E /* EstimationFactory.swift in Sources */, - D5C175201C0FC9F500E1BE4E /* FFTTransformer.swift in Sources */, - D50800FF1C0E70F600168040 /* Array+Extensions.swift in Sources */, - D5C175291C0FD15900E1BE4E /* TransformFactory.swift in Sources */, - D55F5BC41C0675D900B36AE5 /* QuinnsFirstEstimator.swift in Sources */, - D55F5BD61C06793400B36AE5 /* InputSignalTracker.swift in Sources */, - D5B7CBB61C1E0E73002DDCCE /* EstimationError.swift in Sources */, - D5C175231C0FC9F500E1BE4E /* TransformStrategy.swift in Sources */, - D5B7CBB41C1E0DCF002DDCCE /* LocationEstimator.swift in Sources */, - D5C175131C0FC80300E1BE4E /* Config.swift in Sources */, - D55F5BC21C0675D900B36AE5 /* HPSEstimator.swift in Sources */, - D5C175211C0FC9F500E1BE4E /* SimpleTransformer.swift in Sources */, - D55F5BC61C0675D900B36AE5 /* MaxValueEstimator.swift in Sources */, - D55F5BD71C06793400B36AE5 /* OutputSignalTracker.swift in Sources */, - D5C175221C0FC9F500E1BE4E /* Transformer.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - 146D72B41AB782920058798C /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - }; - name = Debug; - }; - 146D72B51AB782920058798C /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 146D72BA1AB782920058798C /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 716897C2D5B5626C8648DBB1 /* Pods.debug.xcconfig */; - buildSettings = { - CLANG_ENABLE_MODULES = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(SDKROOT)/Developer/Library/Frameworks", - "$(inherited)", - ); - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - INFOPLIST_FILE = Tests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "com.example.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_INSTALL_OBJC_HEADER = NO; - SWIFT_OBJC_BRIDGING_HEADER = ""; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Debug; - }; - 146D72BB1AB782920058798C /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = FDF848418969FFB5A7D6A669 /* Pods.release.xcconfig */; - buildSettings = { - CLANG_ENABLE_MODULES = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(SDKROOT)/Developer/Library/Frameworks", - "$(inherited)", - ); - INFOPLIST_FILE = Tests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "com.example.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_INSTALL_OBJC_HEADER = NO; - SWIFT_OBJC_BRIDGING_HEADER = ""; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 146D728E1AB782920058798C /* Build configuration list for PBXProject "Tuner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 146D72B41AB782920058798C /* Debug */, - 146D72B51AB782920058798C /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 146D72B91AB782920058798C /* Build configuration list for PBXNativeTarget "Tests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 146D72BA1AB782920058798C /* Debug */, - 146D72BB1AB782920058798C /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 146D728B1AB782920058798C /* Project object */; -} diff --git a/Pod/Tuner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Pod/Tuner.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 428fae8..0000000 --- a/Pod/Tuner.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/Pod/Tuner.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Pod/Tuner.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme deleted file mode 100644 index 2e20910..0000000 --- a/Pod/Tuner.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Pod/Tuner.xcworkspace/contents.xcworkspacedata b/Pod/Tuner.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 3d9d8f5..0000000 --- a/Pod/Tuner.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - diff --git a/BeethovenTests/iOS/Info.plist b/Project/Info-iOS-Tests.plist similarity index 100% rename from BeethovenTests/iOS/Info.plist rename to Project/Info-iOS-Tests.plist diff --git a/Beethoven/iOS/Info.plist b/Project/Info-iOS.plist similarity index 100% rename from Beethoven/iOS/Info.plist rename to Project/Info-iOS.plist diff --git a/README.md b/README.md index 6ceadf9..12cada9 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ [![CI Status](http://img.shields.io/travis/vadymmarkov/Beethoven.svg?style=flat)](https://travis-ci.org/vadymmarkov/Beethoven) [![Version](https://img.shields.io/cocoapods/v/Beethoven.svg?style=flat)](http://cocoadocs.org/docsets/Beethoven) [![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) +![Swift](https://img.shields.io/badge/%20in-swift%203.0-orange.svg) [![License](https://img.shields.io/cocoapods/l/Beethoven.svg?style=flat)](http://cocoadocs.org/docsets/Beethoven) [![Platform](https://img.shields.io/cocoapods/p/Beethoven.svg?style=flat)](http://cocoadocs.org/docsets/Beethoven) @@ -14,10 +15,10 @@ signals. You can read more about this subject on The basic workflow is to get the audio buffer from the input/output source, transform it to a format applicable for processing and apply one of the pitch estimation algorithms to find the fundamental frequency. For the end user it -comes down to choosing transform strategy, estimation algorithm and -implementation of delegate methods. +comes down to choosing estimation algorithm and implementation of delegate +methods. -The library is designed to be flexible, customizable and highly extensible. +**Beethoven** is designed to be flexible, customizable and highly extensible. The main purpose of the library is to collect Swift implementations of various time and frequency domain algorithms for monophonic pitch extraction, with @@ -49,60 +50,49 @@ and more than welcome! ## Key features -- Audio signal tracking with `AVAudioEngine` and audio nodes (Available in - iOS 8.0 and later). -- Pre-processing of audio buffer by one of the available "transformers", to -convert `AVAudioPCMBuffer` object to the array of floating numbers (with - possible optimizations). -- Pitch estimation. +- [x] Audio signal tracking with `AVAudioEngine` and audio nodes. +- [x] Pre-processing of audio buffer by one of the available "transformers". +- [x] Pitch estimation. ## Usage ### Configuration -Configure buffer size, transform strategy and estimation strategy with the -`Config` struct that could be used in the initialization of `PitchEngine`. For -the case when a signal needs to be tracked from the device output there is -`audioURL` parameter which is the URL to your audio file. +Configure buffer size and estimation strategy with the `Config` struct, which +is used in the initialization of `PitchEngine`. For the case when a signal +needs to be tracked from the device output, there is the `audioUrl` parameter, +which is meant to be a URL of your audio file. ```swift -// Creates a configuration for the input signal tracking (by default) +// Creates a configuration for the input signal tracking (by default). let config = Config( bufferSize: 4096, - transformStrategy: .FFT, - estimationStrategy: .HPS) + estimationStrategy: .yin +) -// Creates a configuration for the output signal tracking +// Creates a configuration for the output signal tracking. let config = Config( bufferSize: 4096, - transformStrategy: .FFT, - estimationStrategy: .HPS, - audioURL: URL) + estimationStrategy: .yin, + audioUrl: URL +) ``` -Initializer has default values: - -```swift -public init(bufferSize: AVAudioFrameCount = 4096, - transformStrategy: TransformStrategy = .FFT, - estimationStrategy: EstimationStrategy = .HPS, - audioURL: NSURL? = nil) -``` - -It means that `Config` could also be instantiated without any parameters: +`Config` could also be instantiated without any parameters: ```swift +// Input signal tracking with YIN algorithm. let config = Config() ``` ### Pitch engine `PitchEngine` is the main class you are going to work with to find the pitch. -It could be instantiated with a configuration and delegate: +It can be instantiated with a configuration and delegate: ```swift let pitchEngine = PitchEngine(config: config, delegate: pitchEngineDelegate) ``` -Both parameters are optional, standard config is used by default, and delegate +Both parameters are optional, standard config is used by default, and `delegate` could always be set later: ```swift @@ -114,8 +104,9 @@ pitchEngine.delegate = pitchEngineDelegate the pitch detection has been started: ```swift -func pitchEngineDidRecievePitch(pitchEngine: PitchEngine, pitch: Pitch) -func pitchEngineDidRecieveError(pitchEngine: PitchEngine, error: ErrorType) +func pitchEngineDidReceivePitch(_ pitchEngine: PitchEngine, pitch: Pitch) +func pitchEngineDidReceiveError(_ pitchEngine: PitchEngine, error: Error) +func pitchEngineWentBelowLevelThreshold(_ pitchEngine: PitchEngine) ``` To start or stop the pitch tracking process just use the corresponding @@ -131,17 +122,18 @@ There are 2 signal tracking classes: - `InputSignalTracker` uses `AVAudioInputNode` to get an audio buffer from the recording input (microphone) in real-time. - `OutputSignalTracker` uses `AVAudioOutputNode` and `AVAudioFile` to play an -audio file and get an audio buffer from the playback output. +audio file and get the audio buffer from the playback output. ### Transform Transform is the first step of audio processing where `AVAudioPCMBuffer` object -is converted to the array of floating numbers. Also it's a place for different +is converted to an array of floating numbers. Also it's a place for different kind of optimizations. Then array is kept in the `elements` property of the -internal `Buffer` struct which also has optional `realElements` and +internal `Buffer` struct, which also has optional `realElements` and `imagElements` properties that could be useful in the further calculations. -There are 2 types of transformations at the moment: -- FFT [Fast Fourier transform](https://en.wikipedia.org/wiki/Fast_Fourier_transform) +There are 3 types of transformations at the moment: +- [Fast Fourier transform](https://en.wikipedia.org/wiki/Fast_Fourier_transform) +- [YIN](http://recherche.ircam.fr/equipes/pcm/cheveign/pss/2002_JASA_YIN.pdf) - `Simple` conversion to use raw float channel data A new transform strategy could be easily added by implementing of `Transformer` @@ -149,13 +141,10 @@ protocol: ```swift public protocol Transformer { - func transformBuffer(buffer: AVAudioPCMBuffer) -> Buffer + func transform(buffer: AVAudioPCMBuffer) -> Buffer } ``` -Then it should be added to `TransformStrategy` enum and in the `create` method -of `TransformFactory` struct. - ### Estimation A pitch detection algorithm (PDA) is an algorithm designed to estimate the pitch or fundamental frequency. Pitch is a psycho-acoustic phenomena, and it's @@ -163,42 +152,47 @@ important to choose the most suitable algorithm for your kind of input source, considering allowable error rate and needed performance. The list of available implemented algorithms: -- `MaxValue` - the index of the maximum value in the audio buffer used as a peak. -- `Quadradic` - [Quadratic interpolation of spectral peaks](https://ccrma.stanford.edu/%7Ejos/sasp/Quadratic_Interpolation_Spectral_Peaks.html) -- `Barycentric` - [Barycentric correction](http://www.dspguru.com/dsp/howtos/how-to-interpolate-fft-peak) -- `QuinnsFirst` - [Quinn's First Estimator](http://www.dspguru.com/dsp/howtos/how-to-interpolate-fft-peak) -- `QuinnsSecond` - [Quinn's Second Estimator](http://www.dspguru.com/dsp/howtos/how-to-interpolate-fft-peak) -- `Jains` - [Jain's Method](http://www.dspguru.com/dsp/howtos/how-to-interpolate-fft-peak) -- `HPS` - [Harmonic Product Spectrum](http://musicweb.ucsd.edu/~trsmyth/analysis/Harmonic_Product_Spectrum.html) +- `maxValue` - the index of the maximum value in the audio buffer used as a peak +- `quadradic` - [Quadratic interpolation of spectral peaks](https://ccrma.stanford.edu/%7Ejos/sasp/Quadratic_Interpolation_Spectral_Peaks.html) +- `barycentric` - [Barycentric correction](http://www.dspguru.com/dsp/howtos/how-to-interpolate-fft-peak) +- `quinnsFirst` - [Quinn's First Estimator](http://www.dspguru.com/dsp/howtos/how-to-interpolate-fft-peak) +- `quinnsSecond` - [Quinn's Second Estimator](http://www.dspguru.com/dsp/howtos/how-to-interpolate-fft-peak) +- `jains` - [Jain's Method](http://www.dspguru.com/dsp/howtos/how-to-interpolate-fft-peak) +- `hps` - [Harmonic Product Spectrum](http://musicweb.ucsd.edu/~trsmyth/analysis/Harmonic_Product_Spectrum.html) +- `yin` - [YIN](http://recherche.ircam.fr/equipes/pcm/cheveign/pss/2002_JASA_YIN.pdf) A new estimation algorithm could be easily added by implementing of `Estimator` or `LocationEstimator` protocol: ```swift -public protocol Estimator { +protocol Estimator { + var transformer: Transformer { get } + func estimateFrequency(sampleRate: Float, buffer: Buffer) throws -> Float func estimateFrequency(sampleRate: Float, location: Int, bufferCount: Int) -> Float } -public protocol LocationEstimator: Estimator { +protocol LocationEstimator: Estimator { func estimateLocation(buffer: Buffer) throws -> Int } ``` Then it should be added to `EstimationStrategy` enum and in the `create` method -of `EstimationFactory` struct. +of `EstimationFactory` struct. Normally, a buffer transformation should be +performed in a separate struct or class to keep the code base more clean and +readable. ### Error handling -Pitch detection is not a trivial task due to some difficulties such as attack +Pitch detection is not a trivial task due to some difficulties, such as attack transients, low and high frequencies. Also it's a real-time processing, so we -are not protected against different kind of errors. For this purpose there is a +are not protected against different kinds of errors. For this purpose there is a range of error types that should be handled properly. **Signal tracking errors** ```swift -public enum Error: ErrorType { - case InputNodeMissing +public enum InputSignalTrackerError: Error { + case inputNodeMissing } ``` @@ -208,8 +202,8 @@ public enum Error: ErrorType { permission is denied it produces the corresponding error: ```swift -public enum Error: ErrorType { - case RecordPermissionDenied +public enum PitchEngineError: Error { + case recordPermissionDenied } ``` @@ -218,33 +212,33 @@ public enum Error: ErrorType { Some errors could occur during the process of pitch estimation: ```swift -public enum EstimationError: ErrorType { - case EmptyBuffer - case UnknownMaxIndex - case UnknownLocation - case UnknownFrequency +public enum EstimationError: Error { + case emptyBuffer + case unknownMaxIndex + case unknownLocation + case unknownFrequency } ``` ## Pitch detection specifics -**Beethoven** performs a pitch detection of a monophonic recording only at the -moment. +At the moment **Beethoven** performs only a pitch detection of a monophonic +recording. **Based on Stackoverflow** [answer](http://stackoverflow.com/a/14503090): -Pitch detection depends greatly on the musical content you want to work with. -Extracting the pitch of a monophonic recording (i.e. single instrument or voice) -is not the same as extracting the pitch of a single instrument from a polyphonic -mixture (e.g. extracting the pitch of the melody from a polyphonic recording). +> Pitch detection depends greatly on the musical content you want to work with. +> Extracting the pitch of a monophonic recording (i.e. single instrument or voice) +> is not the same as extracting the pitch of a single instrument from a polyphonic +> mixture (e.g. extracting the pitch of the melody from a polyphonic recording). -For monophonic pitch extraction there are various algorithm that could be -implemented both in the time domain and frequency domain -([Wikipedia](https://en.wikipedia.org/wiki/Pitch_detection_algorithm)). +> For monophonic pitch extraction there are various algorithm that could be +> implemented both in the time domain and frequency domain +> ([Wikipedia](https://en.wikipedia.org/wiki/Pitch_detection_algorithm)). -However, neither will work well if you want to extract the melody from -polyphonic material. Melody extraction from polyphonic music is still a -research problem. +> However, neither will work well if you want to extract the melody from +> polyphonic material. Melody extraction from polyphonic music is still a +> research problem. ## Examples @@ -252,9 +246,9 @@ research problem. Check out [Guitar Tuner](https://github.com/vadymmarkov/Beethoven/blob/master/Example/GuitarTuner) example to see how you can use **Beethoven** in the real-world scenario to tune -your instrument. It uses a combination of [FFT](https://github.com/vadymmarkov/Beethoven/blob/master/Source/Transform/Strategies/FFTTransformer.swift) -transform and [HPS](https://github.com/vadymmarkov/Beethoven/blob/master/Source/Estimation/Strategies/HPSEstimator.swift) estimation algorithm that appear to be quite accurate in the pitch detection of -guitar strings. +your instrument. It uses [YIN](http://recherche.ircam.fr/equipes/pcm/cheveign/pss/2002_JASA_YIN.pdf) +estimation algorithm, adopted by @glaurent, and it appears to be quite accurate +in the pitch detection of electric and acoustic guitar strings. ## Installation @@ -272,6 +266,9 @@ To install just write into your Cartfile: github "vadymmarkov/Beethoven" ``` +**Beethoven** can also be installed manually. Just download and drop `Sources` +folders in your project. + ## Components **Beethoven** uses [Pitchy](https://github.com/vadymmarkov/Pitchy) library to diff --git a/Source/Config.swift b/Source/Config.swift index 7d828db..eff7c99 100644 --- a/Source/Config.swift +++ b/Source/Config.swift @@ -1,21 +1,18 @@ import AVFoundation public struct Config { - + public var bufferSize: AVAudioFrameCount - public var transformStrategy: TransformStrategy public var estimationStrategy: EstimationStrategy - public var audioURL: URL? + public var audioUrl: URL? // MARK: - Initialization public init(bufferSize: AVAudioFrameCount = 4096, - transformStrategy: TransformStrategy = .fft, - estimationStrategy: EstimationStrategy = .hps, - audioURL: URL? = nil) { + estimationStrategy: EstimationStrategy = .yin, + audioUrl: URL? = nil) { self.bufferSize = bufferSize - self.transformStrategy = transformStrategy self.estimationStrategy = estimationStrategy - self.audioURL = audioURL + self.audioUrl = audioUrl } } diff --git a/Source/Data/Buffer.swift b/Source/Data/Buffer.swift deleted file mode 100644 index 9b7bd90..0000000 --- a/Source/Data/Buffer.swift +++ /dev/null @@ -1,18 +0,0 @@ -public struct Buffer { - - public var elements: [Float] - public var realElements: [Float]? - public var imagElements: [Float]? - - public var count: Int { - return elements.count - } - - // MARK: - Initialization - - public init(elements: [Float], realElements: [Float]? = nil, imagElements: [Float]? = nil) { - self.elements = elements - self.realElements = realElements - self.imagElements = imagElements - } -} diff --git a/Source/Estimation/Estimator.swift b/Source/Estimation/Estimator.swift index 30f8c3c..bcfdc3f 100644 --- a/Source/Estimation/Estimator.swift +++ b/Source/Estimation/Estimator.swift @@ -1,20 +1,21 @@ -public protocol Estimator { +protocol Estimator { + var transformer: Transformer { get } - func estimateFrequency(_ sampleRate: Float, buffer: Buffer) throws -> Float - func estimateFrequency(_ sampleRate: Float, location: Int, bufferCount: Int) -> Float + func estimateFrequency(sampleRate: Float, buffer: Buffer) throws -> Float + func estimateFrequency(sampleRate: Float, location: Int, bufferCount: Int) -> Float } extension Estimator { // MARK: - Default implementation - public func estimateFrequency(_ sampleRate: Float, location: Int, bufferCount: Int) -> Float { + func estimateFrequency(sampleRate: Float, location: Int, bufferCount: Int) -> Float { return Float(location) * sampleRate / (Float(bufferCount) * 2) } // MARK: - Helpers - func maxBufferIndex(_ buffer: [Float]) throws -> Int { + func maxBufferIndex(from buffer: [Float]) throws -> Int { guard buffer.count > 0 else { throw EstimationError.emptyBuffer } @@ -26,7 +27,7 @@ extension Estimator { return index } - func sanitize(_ location: Int, reserveLocation: Int, elements: [Float]) -> Int { + func sanitize(location: Int, reserveLocation: Int, elements: [Float]) -> Int { return location >= 0 && location < elements.count ? location : reserveLocation diff --git a/Source/Estimation/LocationEstimator.swift b/Source/Estimation/LocationEstimator.swift index 5255a6c..8fb1542 100644 --- a/Source/Estimation/LocationEstimator.swift +++ b/Source/Estimation/LocationEstimator.swift @@ -1,14 +1,17 @@ -public protocol LocationEstimator: Estimator { - - func estimateLocation(_ buffer: Buffer) throws -> Int +protocol LocationEstimator: Estimator { + func estimateLocation(buffer: Buffer) throws -> Int } extension LocationEstimator { // MARK: - Default implementation - public func estimateFrequency(_ sampleRate: Float, buffer: Buffer) throws -> Float { - let location = try estimateLocation(buffer) - return estimateFrequency(sampleRate, location: location, bufferCount: buffer.count) + var transformer: Transformer { + return FFTTransformer() + } + + func estimateFrequency(sampleRate: Float, buffer: Buffer) throws -> Float { + let location = try estimateLocation(buffer: buffer) + return estimateFrequency(sampleRate: sampleRate, location: location, bufferCount: buffer.count) } } diff --git a/Source/Estimation/Strategies/BarycentricEstimator.swift b/Source/Estimation/Strategies/BarycentricEstimator.swift index 8856508..d7a7fbe 100644 --- a/Source/Estimation/Strategies/BarycentricEstimator.swift +++ b/Source/Estimation/Strategies/BarycentricEstimator.swift @@ -1,10 +1,10 @@ import Foundation -public struct BarycentricEstimator: LocationEstimator { +struct BarycentricEstimator: LocationEstimator { - public func estimateLocation(_ buffer: Buffer) throws -> Int { + func estimateLocation(buffer: Buffer) throws -> Int { let elements = buffer.elements - let maxIndex = try maxBufferIndex(elements) + let maxIndex = try maxBufferIndex(from: elements) let y2 = abs(elements[maxIndex]) let y1 = maxIndex == 0 ? y2 : abs(elements[maxIndex - 1]) @@ -17,6 +17,6 @@ public struct BarycentricEstimator: LocationEstimator { let location = maxIndex + Int(round(d)) - return sanitize(location, reserveLocation: maxIndex, elements: elements) + return sanitize(location: location, reserveLocation: maxIndex, elements: elements) } } diff --git a/Source/Estimation/Strategies/HPSEstimator.swift b/Source/Estimation/Strategies/HPSEstimator.swift index 5c3c3a4..fca5aa6 100644 --- a/Source/Estimation/Strategies/HPSEstimator.swift +++ b/Source/Estimation/Strategies/HPSEstimator.swift @@ -1,9 +1,9 @@ -public struct HPSEstimator: LocationEstimator { +struct HPSEstimator: LocationEstimator { - public var harmonics = 5 - public var minIndex = 20 + let harmonics = 5 + let minIndex = 20 - public func estimateLocation(_ buffer: Buffer) throws -> Int { + func estimateLocation(buffer: Buffer) throws -> Int { var spectrum = buffer.elements let maxIndex = spectrum.count - 1 var maxHIndex = spectrum.count / harmonics @@ -45,6 +45,6 @@ public struct HPSEstimator: LocationEstimator { } } - return sanitize(location, reserveLocation: maxIndex, elements: spectrum) + return sanitize(location: location, reserveLocation: maxIndex, elements: spectrum) } } diff --git a/Source/Estimation/Strategies/JainsEstimator.swift b/Source/Estimation/Strategies/JainsEstimator.swift index 9d3541b..af2e166 100644 --- a/Source/Estimation/Strategies/JainsEstimator.swift +++ b/Source/Estimation/Strategies/JainsEstimator.swift @@ -1,10 +1,10 @@ import Foundation -public struct JainsEstimator: LocationEstimator { +struct JainsEstimator: LocationEstimator { - public func estimateLocation(_ buffer: Buffer) throws -> Int { + func estimateLocation(buffer: Buffer) throws -> Int { let elements = buffer.elements - let maxIndex = try maxBufferIndex(elements) + let maxIndex = try maxBufferIndex(from: elements) let y2 = abs(elements[maxIndex]) let y1 = maxIndex == 0 ? y2 : abs(elements[maxIndex - 1]) @@ -21,6 +21,6 @@ public struct JainsEstimator: LocationEstimator { location = maxIndex + Int(round(d)) } - return sanitize(location, reserveLocation: maxIndex, elements: elements) + return sanitize(location: location, reserveLocation: maxIndex, elements: elements) } } diff --git a/Source/Estimation/Strategies/MaxValueEstimator.swift b/Source/Estimation/Strategies/MaxValueEstimator.swift index 590d37a..16c3942 100644 --- a/Source/Estimation/Strategies/MaxValueEstimator.swift +++ b/Source/Estimation/Strategies/MaxValueEstimator.swift @@ -1,6 +1,6 @@ -public struct MaxValueEstimator: LocationEstimator { +struct MaxValueEstimator: LocationEstimator { - public func estimateLocation(_ buffer: Buffer) throws -> Int { - return try maxBufferIndex(buffer.elements) + func estimateLocation(buffer: Buffer) throws -> Int { + return try maxBufferIndex(from: buffer.elements) } } diff --git a/Source/Estimation/Strategies/QuadradicEstimator.swift b/Source/Estimation/Strategies/QuadradicEstimator.swift index cd343c4..811ce6f 100644 --- a/Source/Estimation/Strategies/QuadradicEstimator.swift +++ b/Source/Estimation/Strategies/QuadradicEstimator.swift @@ -1,10 +1,10 @@ import Foundation -public struct QuadradicEstimator: LocationEstimator { +struct QuadradicEstimator: LocationEstimator { - public func estimateLocation(_ buffer: Buffer) throws -> Int { + func estimateLocation(buffer: Buffer) throws -> Int { let elements = buffer.elements - let maxIndex = try maxBufferIndex(elements) + let maxIndex = try maxBufferIndex(from: elements) let y2 = abs(elements[maxIndex]) let y1 = maxIndex == 0 ? y2 : abs(elements[maxIndex - 1]) @@ -12,6 +12,6 @@ public struct QuadradicEstimator: LocationEstimator { let d = (y3 - y1) / (2 * (2 * y2 - y1 - y3)) let location = maxIndex + Int(round(d)) - return sanitize(location, reserveLocation: maxIndex, elements: elements) + return sanitize(location: location, reserveLocation: maxIndex, elements: elements) } } diff --git a/Source/Estimation/Strategies/QuinnsFirstEstimator.swift b/Source/Estimation/Strategies/QuinnsFirstEstimator.swift index 6c4a813..535c30d 100644 --- a/Source/Estimation/Strategies/QuinnsFirstEstimator.swift +++ b/Source/Estimation/Strategies/QuinnsFirstEstimator.swift @@ -1,10 +1,10 @@ import Foundation -public struct QuinnsFirstEstimator: LocationEstimator { +struct QuinnsFirstEstimator: LocationEstimator { - public func estimateLocation(_ buffer: Buffer) throws -> Int { + func estimateLocation(buffer: Buffer) throws -> Int { let elements = buffer.elements - let maxIndex = try maxBufferIndex(elements) + let maxIndex = try maxBufferIndex(from: elements) guard let realElements = buffer.realElements, let imagElements = buffer.imagElements else { return maxIndex @@ -24,6 +24,6 @@ public struct QuinnsFirstEstimator: LocationEstimator { let d = dp > 0 && dm > 0 ? dp : dm let location = maxIndex + Int(round(d)) - return sanitize(location, reserveLocation: maxIndex, elements: elements) + return sanitize(location: location, reserveLocation: maxIndex, elements: elements) } } diff --git a/Source/Estimation/Strategies/QuinnsSecondEstimator.swift b/Source/Estimation/Strategies/QuinnsSecondEstimator.swift index 6a07c52..1987324 100644 --- a/Source/Estimation/Strategies/QuinnsSecondEstimator.swift +++ b/Source/Estimation/Strategies/QuinnsSecondEstimator.swift @@ -1,10 +1,10 @@ import Foundation -public struct QuinnsSecondEstimator: LocationEstimator { +struct QuinnsSecondEstimator: LocationEstimator { - public func estimateLocation(_ buffer: Buffer) throws -> Int { + func estimateLocation(buffer: Buffer) throws -> Int { let elements = buffer.elements - let maxIndex = try maxBufferIndex(elements) + let maxIndex = try maxBufferIndex(from: elements) guard let realElements = buffer.realElements, let imagElements = buffer.imagElements else { return maxIndex @@ -24,7 +24,7 @@ public struct QuinnsSecondEstimator: LocationEstimator { let d = (dp + dm) / 2 + tau(dp * dp) - tau(dm * dm) let location = maxIndex + Int(round(d)) - return sanitize(location, reserveLocation: maxIndex, elements: elements) + return sanitize(location: location, reserveLocation: maxIndex, elements: elements) } func tau(_ x: Float) -> Float { @@ -32,6 +32,7 @@ public struct QuinnsSecondEstimator: LocationEstimator { let part1 = x + 1 - sqrt(2/3) let part2 = x + 1 + sqrt(2/3) let p2 = log(part1 / part2) + return 1/4 * p1 - sqrt(6)/24 * p2 } } diff --git a/Source/Estimation/Strategies/YINEstimator.swift b/Source/Estimation/Strategies/YINEstimator.swift index 0968880..c542b71 100644 --- a/Source/Estimation/Strategies/YINEstimator.swift +++ b/Source/Estimation/Strategies/YINEstimator.swift @@ -8,19 +8,18 @@ import UIKit -class YINEstimator: Estimator { +struct YINEstimator: Estimator { - var threshold:Float = 0.05 - - func estimateFrequency(_ sampleRate: Float, buffer: Buffer) throws -> Float { + let transformer: Transformer = YINTransformer() + let threshold: Float = 0.05 + func estimateFrequency(sampleRate: Float, buffer: Buffer) throws -> Float { var elements = buffer.elements YINUtil.cumulativeDifference(yinBuffer: &elements) let tau = YINUtil.absoluteThreshold(yinBuffer: elements, withThreshold: threshold) - - var f0:Float + var f0: Float if tau != 0 { let interpolatedTau = YINUtil.parabolicInterpolation(yinBuffer: elements, tau: tau) @@ -29,9 +28,6 @@ class YINEstimator: Estimator { f0 = 0.0 } - NSLog("YINEstimator : f0 = \(f0)") - return f0 } - } diff --git a/Source/Library/Buffer.swift b/Source/Library/Buffer.swift new file mode 100644 index 0000000..970b22c --- /dev/null +++ b/Source/Library/Buffer.swift @@ -0,0 +1,18 @@ +struct Buffer { + + var elements: [Float] + var realElements: [Float]? + var imagElements: [Float]? + + var count: Int { + return elements.count + } + + // MARK: - Initialization + + init(elements: [Float], realElements: [Float]? = nil, imagElements: [Float]? = nil) { + self.elements = elements + self.realElements = realElements + self.imagElements = imagElements + } +} diff --git a/Source/Extensions/Array+Extensions.swift b/Source/Library/Extensions/Array+Extensions.swift similarity index 80% rename from Source/Extensions/Array+Extensions.swift rename to Source/Library/Extensions/Array+Extensions.swift index b722f68..f0eab8d 100644 --- a/Source/Extensions/Array+Extensions.swift +++ b/Source/Library/Extensions/Array+Extensions.swift @@ -1,7 +1,7 @@ extension Array where Element:Comparable { static func fromUnsafePointer(_ data: UnsafePointer, count: Int) -> [Element] { - let buffer = UnsafeBufferPointer(start: data, count: count); + let buffer = UnsafeBufferPointer(start: data, count: count) return Array(buffer) } diff --git a/Source/Estimation/YINUtil.swift b/Source/Library/YINUtil.swift similarity index 82% rename from Source/Estimation/YINUtil.swift rename to Source/Library/YINUtil.swift index a88c16b..dec9acf 100644 --- a/Source/Estimation/YINUtil.swift +++ b/Source/Library/YINUtil.swift @@ -13,12 +13,9 @@ import Accelerate class YINUtil { - // slow and eats a lot of CPU, but working - // - class func difference2(buffer:[Float]) -> [Float] { - + // Slow and eats a lot of CPU, but working + class func difference2(buffer: [Float]) -> [Float] { let bufferHalfCount = buffer.count / 2 - var resultBuffer = [Float](repeating:0.0, count:bufferHalfCount) for tau in 0 ..< bufferHalfCount { @@ -31,21 +28,17 @@ class YINUtil { return resultBuffer } - // accelerated version of difference2 - Instruments shows roughly around 22% CPU usage, compared to 95% for difference2 - // - class func differenceA(buffer:[Float]) -> [Float] { + // Accelerated version of difference2 - + // Instruments shows roughly around 22% CPU usage, compared to 95% for difference2 + class func differenceA(buffer: [Float]) -> [Float] { let bufferHalfCount = buffer.count / 2 - var resultBuffer = [Float](repeating:0.0, count:bufferHalfCount) - var tempBuffer = [Float](repeating:0.0, count:bufferHalfCount) var tempBufferSq = [Float](repeating:0.0, count:bufferHalfCount) - let len = vDSP_Length(bufferHalfCount) - var vSum:Float = 0.0 + var vSum: Float = 0.0 for tau in 0 ..< bufferHalfCount { - let bufferTau = UnsafePointer(buffer).advanced(by: tau) // do a diff of buffer with itself at tau offset vDSP_vsub(buffer, 1, bufferTau, 1, &tempBuffer, 1, len) @@ -60,26 +53,23 @@ class YINUtil { return resultBuffer } - // supposedly faster and less CPU consuming, but doesn't work, must be because I missed something when porting it from + // Supposedly faster and less CPU consuming, but doesn't work, must be because I missed something when porting it from // https://code.soundsoftware.ac.uk/projects/pyin/repository but I don't know what // - // kept for reference only - // - class func difference_broken_do_not_use(buffer:[Float]) -> [Float] { + // Kept for reference only. + class func difference_broken_do_not_use(buffer: [Float]) -> [Float] { let frameSize = buffer.count let yinBufferSize = frameSize / 2 - // power terms calculation - // var powerTerms = [Float](repeating:0, count:yinBufferSize) - let addSquare = { (res:Float, element:Float) -> Float in + _ = { (res: Float, element: Float) -> Float in res + element * element } - var powerTermFirstElement:Float = 0.0 + var powerTermFirstElement: Float = 0.0 for j in 0 ..< yinBufferSize { powerTermFirstElement += buffer[j] * buffer[j] } @@ -99,10 +89,6 @@ class YINUtil { let bufferSizePOT = Int(1 << log2n) let inputCount = bufferSizePOT / 2 let fftSetup = vDSP_create_fftsetup(log2n, Int32(kFFTRadix2)) - - // buffer.count : 4410 - inputCount : 2048 - yinBufferSize : 2205 - NSLog("buffer.count : \(buffer.count) - inputCount : \(inputCount) - yinBufferSize : \(yinBufferSize)") - var audioRealp = [Float](repeating: 0, count: inputCount) var audioImagp = [Float](repeating: 0, count: inputCount) var audioTransformedComplex = DSPSplitComplex(realp: &audioRealp, imagp: &audioImagp) @@ -140,14 +126,13 @@ class YINUtil { vDSP_fft_zrip(fftSetup!, &kernelTransformedComplex, 1, log2n, FFTDirection(FFT_FORWARD)) - var yinStyleACFRealp = [Float](repeating: 0, count: frameSize) var yinStyleACFImagp = [Float](repeating: 0, count: frameSize) var yinStyleACFComplex = DSPSplitComplex(realp: &yinStyleACFRealp, imagp: &yinStyleACFImagp) for j in 0 ..< inputCount { - yinStyleACFRealp[j] = audioRealp[j] * kernelRealp[j] - audioImagp[j] * kernelImagp[j]; - yinStyleACFImagp[j] = audioRealp[j] * kernelImagp[j] + audioImagp[j] * kernelRealp[j]; + yinStyleACFRealp[j] = audioRealp[j] * kernelRealp[j] - audioImagp[j] * kernelImagp[j] + yinStyleACFImagp[j] = audioRealp[j] * kernelImagp[j] + audioImagp[j] * kernelRealp[j] } vDSP_fft_zrip(fftSetup!, &yinStyleACFComplex, 1, log2n, FFTDirection(FFT_INVERSE)) @@ -164,10 +149,11 @@ class YINUtil { class func cumulativeDifference(yinBuffer: inout [Float]) { yinBuffer[0] = 1.0 - var runningSum:Float = 0.0 + var runningSum: Float = 0.0 for tau in 1 ..< yinBuffer.count { runningSum += yinBuffer[tau] + if runningSum == 0 { yinBuffer[tau] = 1 } else { @@ -176,14 +162,12 @@ class YINUtil { } } - class func absoluteThreshold(yinBuffer:[Float], withThreshold threshold: Float) -> Int { - + class func absoluteThreshold(yinBuffer: [Float], withThreshold threshold: Float) -> Int { var tau = 2 var minTau = 0 - var minVal:Float = 1000.0 + var minVal: Float = 1000.0 while tau < yinBuffer.count { - if yinBuffer[tau] < threshold { while (tau + 1) < yinBuffer.count && yinBuffer[tau + 1] < yinBuffer[tau] { tau += 1 @@ -205,14 +189,14 @@ class YINUtil { return 0 } - class func parabolicInterpolation(yinBuffer:[Float], tau:Int) -> Float { - - guard tau != yinBuffer.count else { return Float(tau) } + class func parabolicInterpolation(yinBuffer: [Float], tau: Int) -> Float { + guard tau != yinBuffer.count else { + return Float(tau) + } - var betterTau:Float = 0.0 + var betterTau: Float = 0.0 if tau > 0 && tau < yinBuffer.count - 1 { - let s0 = yinBuffer[tau - 1] let s1 = yinBuffer[tau] let s2 = yinBuffer[tau + 1] @@ -224,18 +208,15 @@ class YINUtil { } betterTau = Float(tau) + adjustment - } else { - betterTau = Float(tau) - } return fabs(betterTau) } - class func sumSquare(yinBuffer:[Float], start:Int, end:Int) -> Float { - var out:Float = 0.0 + class func sumSquare(yinBuffer: [Float], start: Int, end: Int) -> Float { + var out: Float = 0.0 for i in start ..< end { out += yinBuffer[i] * yinBuffer[i] @@ -243,5 +224,4 @@ class YINUtil { return out } - } diff --git a/Source/PitchEngine.swift b/Source/PitchEngine.swift index 2941bc8..ce74f7d 100644 --- a/Source/PitchEngine.swift +++ b/Source/PitchEngine.swift @@ -8,30 +8,29 @@ public protocol PitchEngineDelegate: class { func pitchEngineWentBelowLevelThreshold(_ pitchEngine: PitchEngine) } -open class PitchEngine { +public enum PitchEngineError: Error { + case recordPermissionDenied +} - public enum PitchEngineError: Error { - case recordPermissionDenied - } +public class PitchEngine { public enum Mode { case record, playback } - open let bufferSize: AVAudioFrameCount - open var active = false - open weak var delegate: PitchEngineDelegate? + public let bufferSize: AVAudioFrameCount + public var active = false + public weak var delegate: PitchEngineDelegate? - fileprivate var transformer: Transformer fileprivate var estimator: Estimator fileprivate var signalTracker: SignalTracker fileprivate var queue: DispatchQueue - open var mode: Mode { + public var mode: Mode { return signalTracker is InputSignalTracker ? .record : .playback } - open var levelThreshold:Float? { + public var levelThreshold: Float? { get { return self.signalTracker.levelThreshold } @@ -40,7 +39,7 @@ open class PitchEngine { } } - public var signalLevel:Float { + public var signalLevel: Float { get { return signalTracker.averageLevel ?? 0.0 } } @@ -48,25 +47,22 @@ open class PitchEngine { public init(config: Config = Config(), delegate: PitchEngineDelegate? = nil) { bufferSize = config.bufferSize - transformer = TransformFactory.create(config.transformStrategy) estimator = EstimationFactory.create(config.estimationStrategy) - if let audioURL = config.audioURL { - signalTracker = OutputSignalTracker(audioURL: audioURL, bufferSize: bufferSize) + if let audioUrl = config.audioUrl { + signalTracker = OutputSignalTracker(audioUrl: audioUrl, bufferSize: bufferSize) } else { signalTracker = InputSignalTracker(bufferSize: bufferSize) } queue = DispatchQueue(label: "BeethovenQueue", attributes: []) - signalTracker.delegate = self - self.delegate = delegate } // MARK: - Processing - open func start() { + public func start() { guard mode == .playback else { activate() return @@ -102,7 +98,7 @@ open class PitchEngine { } } - open func stop() { + public func stop() { signalTracker.stop() active = false } @@ -121,15 +117,15 @@ open class PitchEngine { extension PitchEngine: SignalTrackerDelegate { - public func signalTracker(_ signalTracker: SignalTracker, + func signalTracker(_ signalTracker: SignalTracker, didReceiveBuffer buffer: AVAudioPCMBuffer, atTime time: AVAudioTime) { queue.async { [weak self] in guard let weakSelf = self else { return } - let transformedBuffer = weakSelf.transformer.transformBuffer(buffer) - do { - let frequency = try weakSelf.estimator.estimateFrequency(Float(time.sampleRate), + let transformedBuffer = try weakSelf.estimator.transformer.transform(buffer: buffer) + let frequency = try weakSelf.estimator.estimateFrequency( + sampleRate: Float(time.sampleRate), buffer: transformedBuffer) let pitch = try Pitch(frequency: Double(frequency)) @@ -144,11 +140,9 @@ extension PitchEngine: SignalTrackerDelegate { } } - public func signalTrackerWentBelowLevelThreshold(_ signalTracker: SignalTracker) { + func signalTrackerWentBelowLevelThreshold(_ signalTracker: SignalTracker) { DispatchQueue.main.async { self.delegate?.pitchEngineWentBelowLevelThreshold(self) } - } - } diff --git a/Source/SignalTracking/SignalTracker.swift b/Source/SignalTracking/SignalTracker.swift index 4340323..a9e444a 100644 --- a/Source/SignalTracking/SignalTracker.swift +++ b/Source/SignalTracking/SignalTracker.swift @@ -1,19 +1,17 @@ import AVFoundation -public protocol SignalTrackerDelegate: class { - +protocol SignalTrackerDelegate: class { func signalTracker(_ signalTracker: SignalTracker, didReceiveBuffer buffer: AVAudioPCMBuffer, atTime time: AVAudioTime) - func signalTrackerWentBelowLevelThreshold(_ signalTracker:SignalTracker) + func signalTrackerWentBelowLevelThreshold(_ signalTracker: SignalTracker) } -public protocol SignalTracker: class { - - var levelThreshold:Float? { get set } - var peakLevel:Float? { get } - var averageLevel:Float? { get } +protocol SignalTracker: class { + var levelThreshold: Float? { get set } + var peakLevel: Float? { get } + var averageLevel: Float? { get } weak var delegate: SignalTrackerDelegate? { get set } func start() throws diff --git a/Source/SignalTracking/Units/InputSignalTracker.swift b/Source/SignalTracking/Units/InputSignalTracker.swift index c28f5f6..0315913 100644 --- a/Source/SignalTracking/Units/InputSignalTracker.swift +++ b/Source/SignalTracking/Units/InputSignalTracker.swift @@ -1,28 +1,28 @@ import AVFoundation -open class InputSignalTracker: SignalTracker { +public enum InputSignalTrackerError: Error { + case inputNodeMissing +} - public enum InputSignalTrackerError: Error { - case inputNodeMissing - } +class InputSignalTracker: SignalTracker { - open let bufferSize: AVAudioFrameCount - open weak var delegate: SignalTrackerDelegate? - open var levelThreshold: Float? + weak var delegate: SignalTrackerDelegate? + var levelThreshold: Float? - var audioChannel: AVCaptureAudioChannel? - let captureSession = AVCaptureSession() + fileprivate let bufferSize: AVAudioFrameCount + fileprivate var audioChannel: AVCaptureAudioChannel? + fileprivate let captureSession = AVCaptureSession() fileprivate var audioEngine: AVAudioEngine? fileprivate let session = AVAudioSession.sharedInstance() fileprivate let bus = 0 - public var peakLevel: Float? { + var peakLevel: Float? { get { return audioChannel?.peakHoldLevel } } - public var averageLevel: Float? { + var averageLevel: Float? { get { return audioChannel?.averagePowerLevel } @@ -30,7 +30,8 @@ open class InputSignalTracker: SignalTracker { // MARK: - Initialization - public required init(bufferSize: AVAudioFrameCount = 2048, delegate: SignalTrackerDelegate? = nil) { + required init(bufferSize: AVAudioFrameCount = 2048, + delegate: SignalTrackerDelegate? = nil) { self.bufferSize = bufferSize self.delegate = delegate @@ -39,7 +40,7 @@ open class InputSignalTracker: SignalTracker { // MARK: - Tracking - open func start() throws { + func start() throws { try session.setCategory(AVAudioSessionCategoryPlayAndRecord) try session.overrideOutputAudioPort(AVAudioSessionPortOverride.speaker) @@ -52,7 +53,6 @@ open class InputSignalTracker: SignalTracker { let format = inputNode.inputFormat(forBus: bus) inputNode.installTap(onBus: bus, bufferSize: bufferSize, format: format) { buffer, time in - guard let averageLevel = self.averageLevel else { return } let levelThreshold = self.levelThreshold ?? -1000000.0 @@ -73,7 +73,7 @@ open class InputSignalTracker: SignalTracker { try audioEngine?.start() } - open func stop() { + func stop() { guard audioEngine != nil else { return } @@ -84,7 +84,7 @@ open class InputSignalTracker: SignalTracker { captureSession.stopRunning() } - func setupAudio() { + fileprivate func setupAudio() { do { let audioDevice = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeAudio) let audioCaptureInput = try AVCaptureDeviceInput(device: audioDevice) @@ -92,13 +92,10 @@ open class InputSignalTracker: SignalTracker { captureSession.addInput(audioCaptureInput) let audioOutput = AVCaptureAudioDataOutput() - captureSession.addOutput(audioOutput) - let connection = audioOutput.connections[0] as! AVCaptureConnection - let firstAudioChannel = connection.audioChannels[0] as! AVCaptureAudioChannel - - audioChannel = firstAudioChannel + let connection = audioOutput.connections[0] as? AVCaptureConnection + audioChannel = connection?.audioChannels[0] as? AVCaptureAudioChannel } catch {} } } diff --git a/Source/SignalTracking/Units/OutputSignalTracker.swift b/Source/SignalTracking/Units/OutputSignalTracker.swift index 3d1cb8f..fd650b9 100644 --- a/Source/SignalTracking/Units/OutputSignalTracker.swift +++ b/Source/SignalTracking/Units/OutputSignalTracker.swift @@ -1,44 +1,44 @@ import AVFoundation -open class OutputSignalTracker: SignalTracker { +class OutputSignalTracker: SignalTracker { - open let bufferSize: AVAudioFrameCount - open let audioURL: URL - open weak var delegate: SignalTrackerDelegate? - open var levelThreshold: Float? + weak var delegate: SignalTrackerDelegate? + var levelThreshold: Float? + + fileprivate let bufferSize: AVAudioFrameCount + fileprivate let audioUrl: URL fileprivate var audioEngine: AVAudioEngine! fileprivate var audioPlayer: AVAudioPlayerNode! fileprivate let bus = 0 - public var peakLevel: Float? { + var peakLevel: Float? { get { return 0.0 } } - public var averageLevel: Float? { + var averageLevel: Float? { get { return 0.0 } } - // MARK: - Initialization - public required init(audioURL: URL, bufferSize: AVAudioFrameCount = 2048, delegate: SignalTrackerDelegate? = nil) { - self.audioURL = audioURL + required init(audioUrl: URL, bufferSize: AVAudioFrameCount = 2048, + delegate: SignalTrackerDelegate? = nil) { + self.audioUrl = audioUrl self.bufferSize = bufferSize self.delegate = delegate } // MARK: - Tracking - open func start() throws { + func start() throws { let session = AVAudioSession.sharedInstance() - try session.setCategory(AVAudioSessionCategoryPlayback) audioEngine = AVAudioEngine() audioPlayer = AVAudioPlayerNode() - let audioFile = try AVAudioFile(forReading: audioURL) + let audioFile = try AVAudioFile(forReading: audioUrl) audioEngine.attach(audioPlayer) audioEngine.connect(audioPlayer, to: audioEngine.outputNode, format: audioFile.processingFormat) @@ -58,7 +58,7 @@ open class OutputSignalTracker: SignalTracker { audioPlayer.play() } - open func stop() { + func stop() { audioPlayer.stop() audioEngine.stop() audioEngine.reset() diff --git a/Source/Transform/Strategies/FFTTransformer.swift b/Source/Transform/Strategies/FFTTransformer.swift index bb255b8..c985f43 100644 --- a/Source/Transform/Strategies/FFTTransformer.swift +++ b/Source/Transform/Strategies/FFTTransformer.swift @@ -1,9 +1,9 @@ import AVFoundation import Accelerate -public struct FFTTransformer: Transformer { +struct FFTTransformer: Transformer { - public func transformBuffer(_ buffer: AVAudioPCMBuffer) -> Buffer { + func transform(buffer: AVAudioPCMBuffer) throws -> Buffer { let frameCount = buffer.frameLength let log2n = UInt(round(log2(Double(frameCount)))) let bufferSizePOT = Int(1 << log2n) @@ -25,14 +25,9 @@ public struct FFTTransformer: Transformer { let temp = UnsafePointer(transferBuffer) temp.withMemoryRebound(to: DSPComplex.self, capacity: transferBuffer.count) { (typeConvertedTransferBuffer) -> Void in - vDSP_ctoz(typeConvertedTransferBuffer, 2, - &output, 1, vDSP_Length(inputCount)) - + vDSP_ctoz(typeConvertedTransferBuffer, 2, &output, 1, vDSP_Length(inputCount)) } -// vDSP_ctoz(UnsafePointer(transferBuffer), 2, -// &output, 1, vDSP_Length(inputCount)) - vDSP_fft_zrip(fftSetup!, &output, 1, log2n, FFTDirection(FFT_FORWARD)) var magnitudes = [Float](repeating: 0.0, count: inputCount) diff --git a/Source/Transform/Strategies/SimpleTransformer.swift b/Source/Transform/Strategies/SimpleTransformer.swift index 6a0775e..f59f529 100644 --- a/Source/Transform/Strategies/SimpleTransformer.swift +++ b/Source/Transform/Strategies/SimpleTransformer.swift @@ -1,13 +1,17 @@ import AVFoundation -public struct SimpleTransformer: Transformer { +struct SimpleTransformer: Transformer { - public func transformBuffer(_ buffer: AVAudioPCMBuffer) -> Buffer { -// let pointer = UnsafePointer(buffer.floatChannelData) -// let elements = Array.fromUnsafePointer(pointer, count: Int(buffer.frameLength)) + enum SimpleTransformerError: Error { + case FloatChannelDataIsNil + } + + func transform(buffer: AVAudioPCMBuffer) throws -> Buffer { + guard let pointer = buffer.floatChannelData else { + throw SimpleTransformerError.FloatChannelDataIsNil + } - let pointer = buffer.floatChannelData - let elements = Array.fromUnsafePointer((pointer?.pointee)!, count:Int(buffer.frameLength)) + let elements = Array.fromUnsafePointer(pointer.pointee, count:Int(buffer.frameLength)) return Buffer(elements: elements) } } diff --git a/Source/Transform/Strategies/YINTransformer.swift b/Source/Transform/Strategies/YINTransformer.swift index fc26a72..7498ac5 100644 --- a/Source/Transform/Strategies/YINTransformer.swift +++ b/Source/Transform/Strategies/YINTransformer.swift @@ -10,14 +10,11 @@ import Foundation import AVFoundation -public struct YINTransformer : Transformer { +struct YINTransformer: Transformer { - public func transformBuffer(_ buffer: AVAudioPCMBuffer) -> Buffer { - - let pointer = buffer.floatChannelData - let elements = Array.fromUnsafePointer((pointer?.pointee)!, count:Int(buffer.frameLength)) - - let diffElements = YINUtil.differenceA(buffer: elements) + func transform(buffer: AVAudioPCMBuffer) throws -> Buffer { + let buffer = try SimpleTransformer().transform(buffer: buffer) + let diffElements = YINUtil.differenceA(buffer: buffer.elements) return Buffer(elements: diffElements) } diff --git a/Source/Transform/TransformFactory.swift b/Source/Transform/TransformFactory.swift deleted file mode 100644 index 4b62d00..0000000 --- a/Source/Transform/TransformFactory.swift +++ /dev/null @@ -1,17 +0,0 @@ -struct TransformFactory { - - static func create(_ strategy: TransformStrategy) -> Transformer { - let transformer: Transformer - - switch strategy { - case .fft: - transformer = FFTTransformer() - case .yin: - transformer = YINTransformer() - default: - transformer = SimpleTransformer() - } - - return transformer - } -} diff --git a/Source/Transform/TransformStrategy.swift b/Source/Transform/TransformStrategy.swift deleted file mode 100644 index 6007e2a..0000000 --- a/Source/Transform/TransformStrategy.swift +++ /dev/null @@ -1,5 +0,0 @@ -public enum TransformStrategy { - case simple - case fft - case yin -} diff --git a/Source/Transform/Transformer.swift b/Source/Transform/Transformer.swift index ca02b2e..75a4756 100644 --- a/Source/Transform/Transformer.swift +++ b/Source/Transform/Transformer.swift @@ -1,6 +1,5 @@ import AVFoundation -public protocol Transformer { - - func transformBuffer(_ buffer: AVAudioPCMBuffer) -> Buffer +protocol Transformer { + func transform(buffer: AVAudioPCMBuffer) throws -> Buffer } diff --git a/BeethovenTests/Spec/ConfigSpec.swift b/Tests/Spec/ConfigSpec.swift similarity index 83% rename from BeethovenTests/Spec/ConfigSpec.swift rename to Tests/Spec/ConfigSpec.swift index 8c37f68..63bd8aa 100644 --- a/BeethovenTests/Spec/ConfigSpec.swift +++ b/Tests/Spec/ConfigSpec.swift @@ -13,8 +13,7 @@ class ConfigSpec: QuickSpec { config = Config() expect(config.bufferSize).to(equal(4096)) - expect(config.transformStrategy).to(equal(TransformStrategy.FFT)) - expect(config.estimationStrategy).to(equal(EstimationStrategy.HPS)) + expect(config.estimationStrategy).to(equal(EstimationStrategy.yin)) expect(config.audioURL).to(beNil()) } } diff --git a/BeethovenTests/Spec/Estimation/EstimationFactorySpec.swift b/Tests/Spec/Estimation/EstimationFactorySpec.swift similarity index 55% rename from BeethovenTests/Spec/Estimation/EstimationFactorySpec.swift rename to Tests/Spec/Estimation/EstimationFactorySpec.swift index 45501ee..956952a 100644 --- a/BeethovenTests/Spec/Estimation/EstimationFactorySpec.swift +++ b/Tests/Spec/Estimation/EstimationFactorySpec.swift @@ -8,31 +8,35 @@ class EstimationFactorySpec: QuickSpec { describe("EstimationFactory") { describe(".create") { it("creates QuadradicEstimator") { - expect(EstimationFactory.create(.Quadradic) is QuadradicEstimator).to(beTrue()) + expect(EstimationFactory.create(.quadradic) is QuadradicEstimator).to(beTrue()) } it("creates Barycentric") { - expect(EstimationFactory.create(.Barycentric) is BarycentricEstimator).to(beTrue()) + expect(EstimationFactory.create(.barycentric) is BarycentricEstimator).to(beTrue()) } it("creates QuinnsFirst") { - expect(EstimationFactory.create(.QuinnsFirst) is QuinnsFirstEstimator).to(beTrue()) + expect(EstimationFactory.create(.quinnsFirst) is QuinnsFirstEstimator).to(beTrue()) } it("creates QuinnsSecond") { - expect(EstimationFactory.create(.QuinnsSecond) is QuinnsSecondEstimator).to(beTrue()) + expect(EstimationFactory.create(.quinnsSecond) is QuinnsSecondEstimator).to(beTrue()) } it("creates Jains") { - expect(EstimationFactory.create(.Jains) is JainsEstimator).to(beTrue()) + expect(EstimationFactory.create(.jains) is JainsEstimator).to(beTrue()) } it("creates HPS") { - expect(EstimationFactory.create(.HPS) is HPSEstimator).to(beTrue()) + expect(EstimationFactory.create(.hps) is HPSEstimator).to(beTrue()) + } + + it("creates YIN") { + expect(EstimationFactory.create(.yin) is YINEstimator).to(beTrue()) } it("creates MaxValue") { - expect(EstimationFactory.create(.MaxValue) is MaxValueEstimator).to(beTrue()) + expect(EstimationFactory.create(.maxValue) is MaxValueEstimator).to(beTrue()) } } } diff --git a/BeethovenTests/Spec/Estimation/EstimatorSpec.swift b/Tests/Spec/Estimation/EstimatorSpec.swift similarity index 77% rename from BeethovenTests/Spec/Estimation/EstimatorSpec.swift rename to Tests/Spec/Estimation/EstimatorSpec.swift index d02f0ab..141812f 100644 --- a/BeethovenTests/Spec/Estimation/EstimatorSpec.swift +++ b/Tests/Spec/Estimation/EstimatorSpec.swift @@ -15,7 +15,7 @@ class EstimatorSpec: QuickSpec { describe("#maxBufferIndex") { it("returns the index of the max element in the array") { let array: [Float] = [0.1, 0.3, 0.2] - let result = try! estimator.maxBufferIndex(array) + let result = try! estimator.maxBufferIndex(from: array) expect(result).to(equal(1)) } @@ -24,14 +24,14 @@ class EstimatorSpec: QuickSpec { describe("#sanitize") { it("returns the passed location if it doesn't extend array bounds") { let array: [Float] = [0.1, 0.3, 0.2] - let result = estimator.sanitize(1, reserveLocation: 0, elements: array) + let result = estimator.sanitize(location: 1, reserveLocation: 0, elements: array) expect(result).to(equal(1)) } it("returns the reserve location if the passed location extends array bounds") { let array: [Float] = [0.1, 0.3, 0.2] - let result = estimator.sanitize(4, reserveLocation: 0, elements: array) + let result = estimator.sanitize(location: 4, reserveLocation: 0, elements: array) expect(result).to(equal(0)) } diff --git a/BeethovenTests/Spec/Extensions/ArrayExtensionsSpec.swift b/Tests/Spec/Extensions/ArrayExtensionsSpec.swift similarity index 100% rename from BeethovenTests/Spec/Extensions/ArrayExtensionsSpec.swift rename to Tests/Spec/Extensions/ArrayExtensionsSpec.swift diff --git a/BeethovenTests/Spec/Data/BufferSpec.swift b/Tests/Spec/Library/BufferSpec.swift similarity index 100% rename from BeethovenTests/Spec/Data/BufferSpec.swift rename to Tests/Spec/Library/BufferSpec.swift diff --git a/BeethovenTests/Spec/Transform/Strategies/FFTTransformerSpec.swift b/Tests/Spec/Transform/Strategies/FFTTransformerSpec.swift similarity index 88% rename from BeethovenTests/Spec/Transform/Strategies/FFTTransformerSpec.swift rename to Tests/Spec/Transform/Strategies/FFTTransformerSpec.swift index b9d88ed..ad1ac9d 100644 --- a/BeethovenTests/Spec/Transform/Strategies/FFTTransformerSpec.swift +++ b/Tests/Spec/Transform/Strategies/FFTTransformerSpec.swift @@ -16,7 +16,7 @@ class FFTTransformerSpec: QuickSpec { describe("#sqrtq") { it("returns the array's square") { let array: [Float] = [0.1, 0.2, 0.3] - var expected = [Float](count: array.count, repeatedValue: 0.0) + var expected = [Float](repeating: 0.0, count: array.count) vvsqrtf(&expected, array, [Int32(array.count)]) expect(transformer.sqrtq(array)).to(equal(expected)) diff --git a/swiftlint.sh b/swiftlint.sh new file mode 100644 index 0000000..04d63ef --- /dev/null +++ b/swiftlint.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +# Installs the SwiftLint package. + +set -e + +SWIFTLINT_SOURCE_URL="https://github.com/realm/SwiftLint.git" +SWIFTLINT_SOURCE_PATH="/tmp/SwiftLint" +SWIFTLINT_PKG_PATH="/tmp/SwiftLint.pkg" +SWIFTLINT_PKG_URL="https://github.com/realm/SwiftLint/releases/download/0.11.1/SwiftLint.pkg" + +wget --output-document=$SWIFTLINT_PKG_PATH $SWIFTLINT_PKG_URL + +if [ -f $SWIFTLINT_PKG_PATH ]; then + echo "Installing SwiftLint..." + sudo installer -pkg $SWIFTLINT_PKG_PATH -target / +else + echo "Failed to install SwiftLint. Compiling from source..." && + git clone $SWIFTLINT_SOURCE_URL $SWIFTLINT_SOURCE_PATH && + cd $SWIFTLINT_SOURCE_PATH && + git submodule update --init --recursive && + sudo make install +fi