Skip to content

Commit

Permalink
v0.2 ios
Browse files Browse the repository at this point in the history
  • Loading branch information
ksyeo1010 authored Nov 6, 2023
1 parent 81e86b4 commit 4c1fe0f
Show file tree
Hide file tree
Showing 16 changed files with 243 additions and 66 deletions.
52 changes: 52 additions & 0 deletions .github/workflows/ios-demos.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
name: iOS Demos

on:
workflow_dispatch:
push:
branches: [ main ]
paths:
- 'demo/ios/EagleDemo/**'
- '.github/workflows/ios-demos.yml'
pull_request:
branches: [ main, 'v[0-9]+.[0-9]+' ]
paths:
- 'demo/ios/EagleDemo/**'
- '.github/workflows/ios-demos.yml'

defaults:
run:
working-directory: demo/ios/EagleDemo

jobs:
build:
runs-on: macos-latest

steps:
- name: Checkout
uses: actions/checkout@v3

- name: Set up Node.js LTS
uses: actions/setup-node@v3
with:
node-version: lts/*

- name: Install Cocoapods
run: gem install cocoapods

- name: Install AppCenter CLI
run: npm install -g appcenter-cli

- name: Make build dir
run: mkdir ddp

- name: Run Cocoapods
run: pod install

- name: Build
run: xcrun xcodebuild build
-configuration Debug
-workspace EagleDemo.xcworkspace
-sdk iphoneos
-scheme EagleDemo
-derivedDataPath ddp
CODE_SIGNING_ALLOWED=NO
6 changes: 3 additions & 3 deletions binding/ios/Eagle-iOS.podspec
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Pod::Spec.new do |s|
s.name = 'Eagle-iOS'
s.module_name = 'Eagle'
s.version = '0.1.0'
s.version = '0.2.0'
s.license = {:type => 'Apache 2.0'}
s.summary = 'iOS binding for Picovoice\'s Eagle speaker recognition engine'
s.description =
Expand All @@ -10,8 +10,8 @@ Pod::Spec.new do |s|
DESC
s.homepage = 'https://github.com/Picovoice/eagle/tree/master/binding/ios'
s.author = { 'Picovoice' => '[email protected]' }
s.source = { :git => "https://github.com/Picovoice/eagle.git", :tag => "Eagle-iOS-v0.1.0" }
s.ios.deployment_target = '11.0'
s.source = { :git => "https://github.com/Picovoice/eagle.git", :tag => "Eagle-iOS-v0.2.0" }
s.ios.deployment_target = '13.0'
s.swift_version = '5.0'
s.vendored_frameworks = 'lib/ios/PvEagle.xcframework'
s.resources = 'lib/common/eagle_params.pv'
Expand Down
11 changes: 8 additions & 3 deletions binding/ios/Eagle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,17 @@ public class Eagle: EagleBase {

speakerCount = speakerProfiles.count

pv_set_sdk(Eagle.sdk)

let status = pv_eagle_init(
accessKey,
modelPathArg,
Int32(speakerCount),
speakerHandles,
&handle)
if status != PV_STATUS_SUCCESS {
throw pvStatusToEagleError(status, "Eagle init failed")
let messageStack = try getMessageStack()
throw pvStatusToEagleError(status, "Eagle init failed", messageStack)
}
}

Expand Down Expand Up @@ -116,7 +119,8 @@ public class Eagle: EagleBase {
scores.baseAddress)

if status != PV_STATUS_SUCCESS {
throw pvStatusToEagleError(status, "Eagle process failed")
let messageStack = try getMessageStack()
throw pvStatusToEagleError(status, "Eagle process failed", messageStack)
}

return Array(scores)
Expand All @@ -137,7 +141,8 @@ public class Eagle: EagleBase {
let status = pv_eagle_reset(handle)

if status != PV_STATUS_SUCCESS {
throw pvStatusToEagleError(status, "Eagle reset failed")
let messageStack = try getMessageStack()
throw pvStatusToEagleError(status, "Eagle reset failed", messageStack)
}
}
}
12 changes: 6 additions & 6 deletions binding/ios/EagleAppTest/EagleAppTest.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -674,7 +674,7 @@
INFOPLIST_KEY_UIMainStoryboardFile = Main;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand Down Expand Up @@ -704,7 +704,7 @@
INFOPLIST_KEY_UIMainStoryboardFile = Main;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand All @@ -726,7 +726,7 @@
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 65723695GD;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand All @@ -751,7 +751,7 @@
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 65723695GD;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand All @@ -776,7 +776,7 @@
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 65723695GD;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand All @@ -803,7 +803,7 @@
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 65723695GD;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand Down
8 changes: 1 addition & 7 deletions binding/ios/EagleAppTest/EagleAppTest/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,4 @@

import UIKit

class ViewController: UIViewController {

override func viewDidLoad() {
super.viewDidLoad()
}

}
class ViewController: UIViewController { }
Original file line number Diff line number Diff line change
Expand Up @@ -123,4 +123,84 @@ class EagleAppTestUITests: BaseTest {
XCTAssertLessThan(scores.max()!, 0.5)
eagle.delete()
}

func testMessageStack() throws {
let enrollUrls = enrollUrls()

let eagleProfiler = try EagleProfiler(accessKey: accessKey)
for url in enrollUrls {
let pcm = try readPcmFromFile(testAudioURL: url)
(_, _) = try eagleProfiler.enroll(pcm: pcm)
}

let profile = try eagleProfiler.export()
eagleProfiler.delete()

var first_error: String = ""
do {
let eagle = try Eagle(accessKey: "invalid", speakerProfiles: [profile])
XCTAssertNil(eagle)
} catch {
first_error = "\(error.localizedDescription)"
XCTAssert(first_error.count < 1024)
}

do {
let eagle = try Eagle(accessKey: "invalid", speakerProfiles: [profile])
XCTAssertNil(eagle)
} catch {
XCTAssert("\(error.localizedDescription)".count == first_error.count)
}
}

func testEnrollExportMessageStack() throws {
let e = try EagleProfiler.init(accessKey: accessKey)
e.delete()

var testPcm: [Int16] = []
testPcm.reserveCapacity(Int(Eagle.frameLength))

do {
let (res, _) = try e.enroll(pcm: testPcm)
XCTAssert(res == -1)
} catch {
XCTAssert("\(error.localizedDescription)".count > 0)
XCTAssert("\(error.localizedDescription)".count < 1024)
}

do {
let res = try e.export()
XCTAssertNil(res)
} catch {
XCTAssert("\(error.localizedDescription)".count > 0)
XCTAssert("\(error.localizedDescription)".count < 1024)
}
}

func testProcessMessageStack() throws {
let enrollUrls = enrollUrls()

let eagleProfiler = try EagleProfiler(accessKey: accessKey)
for url in enrollUrls {
let pcm = try readPcmFromFile(testAudioURL: url)
(_, _) = try eagleProfiler.enroll(pcm: pcm)
}

let profile = try eagleProfiler.export()
eagleProfiler.delete()

let e = try Eagle.init(accessKey: accessKey, speakerProfiles: [profile])
e.delete()

var testPcm: [Int16] = []
testPcm.reserveCapacity(Int(Eagle.frameLength))

do {
let res = try e.process(pcm: testPcm)
XCTAssert(res.count == -1)
} catch {
XCTAssert("\(error.localizedDescription)".count > 0)
XCTAssert("\(error.localizedDescription)".count < 1024)
}
}
}
8 changes: 4 additions & 4 deletions binding/ios/EagleAppTest/Podfile
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
source 'https://cdn.cocoapods.org/'
platform :ios, '11.0'
platform :ios, '13.0'

target 'EagleAppTest' do
pod 'Eagle-iOS', '~> 0.1.0'
pod 'Eagle-iOS', :podspec => 'https://raw.githubusercontent.com/Picovoice/eagle/v0.2-ios/binding/ios/Eagle-iOS.podspec'
end

target 'EagleAppTestUITests' do
pod 'Eagle-iOS', '~> 0.1.0'
pod 'Eagle-iOS', :podspec => 'https://raw.githubusercontent.com/Picovoice/eagle/v0.2-ios/binding/ios/Eagle-iOS.podspec'
end

target 'PerformanceTest' do
pod 'Eagle-iOS', '~> 0.1.0'
pod 'Eagle-iOS', :podspec => 'https://raw.githubusercontent.com/Picovoice/eagle/v0.2-ios/binding/ios/Eagle-iOS.podspec'
end
16 changes: 8 additions & 8 deletions binding/ios/EagleAppTest/Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
PODS:
- Eagle-iOS (0.1.0)
- Eagle-iOS (0.2.0)

DEPENDENCIES:
- Eagle-iOS (~> 0.1.0)
- Eagle-iOS (from `https://raw.githubusercontent.com/Picovoice/eagle/v0.2-ios/binding/ios/Eagle-iOS.podspec`)

SPEC REPOS:
trunk:
- Eagle-iOS
EXTERNAL SOURCES:
Eagle-iOS:
:podspec: https://raw.githubusercontent.com/Picovoice/eagle/v0.2-ios/binding/ios/Eagle-iOS.podspec

SPEC CHECKSUMS:
Eagle-iOS: 2d510466a68b22ba137dd2b39086268c4130c321
Eagle-iOS: 155eb54e73e37533a0accf3ea5fa1a37d8c999ad

PODFILE CHECKSUM: a3a1c94c7c11252c2152ed23f2cead73c1cf3762
PODFILE CHECKSUM: 6ecb4b66367607455bddf4dcad4ec1f8c70935a7

COCOAPODS: 1.12.1
COCOAPODS: 1.11.3
54 changes: 41 additions & 13 deletions binding/ios/EagleBase.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ public class EagleBase {
/// Eagle/EagleProfiler version
public static let version = String(cString: pv_eagle_version())

internal static var sdk = "ios"

public static func setSdk(sdk: String) {
self.sdk = sdk
}

/// Given a path, return the full path to the resource.
///
/// - Parameters:
Expand All @@ -31,34 +37,38 @@ public class EagleBase {
/// - Parameters:
/// - status: C enum value.
/// - message: message to include with the EagleError.
/// - messageStack: Error stack returned from Eagle.
/// - Returns: An EagleError.
internal func pvStatusToEagleError(_ status: pv_status_t, _ message: String) -> EagleError {
internal func pvStatusToEagleError(
_ status: pv_status_t,
_ message: String,
_ messageStack: [String] = []) -> EagleError {
switch status {
case PV_STATUS_OUT_OF_MEMORY:
return EagleMemoryError(message)
return EagleMemoryError(message, messageStack)
case PV_STATUS_IO_ERROR:
return EagleIOError(message)
return EagleIOError(message, messageStack)
case PV_STATUS_INVALID_ARGUMENT:
return EagleInvalidArgumentError(message)
return EagleInvalidArgumentError(message, messageStack)
case PV_STATUS_STOP_ITERATION:
return EagleStopIterationError(message)
return EagleStopIterationError(message, messageStack)
case PV_STATUS_KEY_ERROR:
return EagleKeyError(message)
return EagleKeyError(message, messageStack)
case PV_STATUS_INVALID_STATE:
return EagleInvalidStateError(message)
return EagleInvalidStateError(message, messageStack)
case PV_STATUS_RUNTIME_ERROR:
return EagleRuntimeError(message)
return EagleRuntimeError(message, messageStack)
case PV_STATUS_ACTIVATION_ERROR:
return EagleActivationError(message)
return EagleActivationError(message, messageStack)
case PV_STATUS_ACTIVATION_LIMIT_REACHED:
return EagleActivationLimitError(message)
return EagleActivationLimitError(message, messageStack)
case PV_STATUS_ACTIVATION_THROTTLED:
return EagleActivationThrottledError(message)
return EagleActivationThrottledError(message, messageStack)
case PV_STATUS_ACTIVATION_REFUSED:
return EagleActivationRefusedError(message)
return EagleActivationRefusedError(message, messageStack)
default:
let pvStatusString = String(cString: pv_status_to_string(status))
return EagleError("\(pvStatusString): \(message)")
return EagleError("\(pvStatusString): \(message)", messageStack)
}
}

Expand All @@ -84,4 +94,22 @@ public class EagleBase {
return EagleProfilerEnrollFeedback.AUDIO_OK
}
}

internal func getMessageStack() throws -> [String] {
var messageStackRef: UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>?
var messageStackDepth: Int32 = 0
let status = pv_get_error_stack(&messageStackRef, &messageStackDepth)
if status != PV_STATUS_SUCCESS {
throw pvStatusToEagleError(status, "Unable to get Eagle error state")
}

var messageStack: [String] = []
for i in 0..<messageStackDepth {
messageStack.append(String(cString: messageStackRef!.advanced(by: Int(i)).pointee!))
}

pv_free_error_stack(messageStackRef)

return messageStack
}
}
Loading

0 comments on commit 4c1fe0f

Please sign in to comment.