Skip to content

Commit

Permalink
Ios handle apostrophes (#29)
Browse files Browse the repository at this point in the history
* handle apostrophes & quotes

* rm throw, add quotes to valid characters

* move helper function outside class

* fix synthesizeToFile

* minor - change fn name

* build

* revert info

* whitespace

* use tag

* lint

* post release

---------

Co-authored-by: Albert Ho <[email protected]>
  • Loading branch information
albho and Albert Ho authored Jun 7, 2024
1 parent a2a2e33 commit f17fa71
Show file tree
Hide file tree
Showing 10 changed files with 183 additions and 107 deletions.
4 changes: 2 additions & 2 deletions binding/ios/Orca-iOS.podspec
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Pod::Spec.new do |s|
s.name = 'Orca-iOS'
s.module_name = 'Orca'
s.version = '0.2.1'
s.version = '0.2.2'
s.license = {:type => 'Apache 2.0'}
s.summary = 'iOS binding for Picovoice\'s Orca Text-to-Speech Engine.'
s.description =
Expand All @@ -18,7 +18,7 @@ Pod::Spec.new do |s|
DESC
s.homepage = 'https://github.com/Picovoice/orca/tree/main/binding/ios'
s.author = { 'Picovoice' => '[email protected]' }
s.source = { :git => "https://github.com/Picovoice/orca.git", :tag => "Orca-iOS-v0.2.1" }
s.source = { :git => "https://github.com/Picovoice/orca.git", :tag => "Orca-iOS-v0.2.2" }
s.ios.deployment_target = '13.0'
s.swift_version = '5.0'
s.vendored_frameworks = 'lib/ios/PvOrca.xcframework'
Expand Down
23 changes: 19 additions & 4 deletions binding/ios/Orca.swift
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,15 @@ public struct OrcaWord {
}
}

private func swapQuotes(_ text: String) -> String {
var output = text
output = output.replacingOccurrences(of: "", with: "'")
output = output.replacingOccurrences(of: "", with: "'")
output = output.replacingOccurrences(of: "", with: "\"")
output = output.replacingOccurrences(of: "", with: "\"")
return output
}

/// iOS (Swift) binding for Orca Text-to-Speech engine. Provides a Swift interface to the Orca library.
public class Orca {

Expand Down Expand Up @@ -116,9 +125,11 @@ public class Orca {
var cNumSamples: Int32 = 0
var cPcm: UnsafeMutablePointer<Int16>?

let formattedText = swapQuotes(text)

let status = pv_orca_stream_synthesize(
stream,
text,
formattedText,
&cNumSamples,
&cPcm)
if status != PV_STATUS_SUCCESS {
Expand Down Expand Up @@ -228,7 +239,7 @@ public class Orca {
let messageStack = try getMessageStack()
throw pvStatusToOrcaError(validCharactersStatus, "Unable to get Orca valid characters", messageStack)
}
var validCharacters: Set<String> = []
var validCharacters: Set<String> = ["", "", "", ""]
for i in 0..<cNumCharacters {
if let cString = cCharacters?.advanced(by: Int(i)).pointee {
let swiftString = String(cString: cString)
Expand Down Expand Up @@ -316,9 +327,11 @@ public class Orca {
var cNumAlignments: Int32 = 0
var cAlignments: UnsafeMutablePointer<UnsafeMutablePointer<pv_orca_word_alignment_t>?>?

let formattedText = swapQuotes(text)

let status = pv_orca_synthesize(
handle,
text,
formattedText,
cSynthesizeParams,
&cNumSamples,
&cPcm,
Expand Down Expand Up @@ -401,9 +414,11 @@ public class Orca {
var cNumAlignments: Int32 = 0
var cAlignments: UnsafeMutablePointer<UnsafeMutablePointer<pv_orca_word_alignment_t>?>?

let formattedText = swapQuotes(text)

let status = pv_orca_synthesize_to_file(
handle,
text,
formattedText,
cSynthesizeParams,
outputPath,
&cNumAlignments,
Expand Down
124 changes: 62 additions & 62 deletions binding/ios/OrcaAppTest/OrcaAppTest.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ class OrcaAppTestUITests: BaseTest {
for orca in self.orcas {
XCTAssertGreaterThan(orca.validCharacters!.count, 0)
XCTAssert(orca.validCharacters!.contains(","))
XCTAssert(orca.validCharacters!.contains(""))
XCTAssert(orca.validCharacters!.contains(""))
XCTAssert(orca.validCharacters!.contains(""))
XCTAssert(orca.validCharacters!.contains(""))
}
}

Expand Down Expand Up @@ -178,12 +182,71 @@ class OrcaAppTestUITests: BaseTest {
let audioFile = audioDir.appendingPathComponent("test.wav")

for orca in self.orcas {
try orca.synthesizeToFile(text: self.testData!.test_sentences.text, outputURL: audioFile)
let wordArrayFromURL = try orca.synthesizeToFile(
text: self.testData!.test_sentences.text, outputURL: audioFile)
XCTAssert(FileManager().fileExists(atPath: audioFile.path))
XCTAssertGreaterThan(wordArrayFromURL.count, 0)
try FileManager().removeItem(at: audioFile)

try orca.synthesizeToFile(text: self.testData!.test_sentences.text, outputPath: audioFile.path)
let wordArrayFromPath = try orca.synthesizeToFile(
text: self.testData!.test_sentences.text, outputPath: audioFile.path)
XCTAssert(FileManager().fileExists(atPath: audioFile.path))
XCTAssertGreaterThan(wordArrayFromPath.count, 0)
try FileManager().removeItem(at: audioFile)
}
}

let textQuotes =
"iOS uses different quotation marks for ‘single’ and “double” quotes."

func testStreamingQuotes() throws {
for orca in self.orcas {
let orcaStream = try orca.streamOpen()

var fullPcm = [Int16]()
for c in textQuotes {
if let pcm = try orcaStream.synthesize(text: String(c)) {
if !pcm.isEmpty {
fullPcm.append(contentsOf: pcm)
}
}
}

if let flushedPcm = try orcaStream.flush(), !flushedPcm.isEmpty {
fullPcm.append(contentsOf: flushedPcm)
}

orcaStream.close()
XCTAssertGreaterThan(fullPcm.count, 0)
}
}

func testSynthesizeQuotes() throws {
for orca in self.orcas {
let (pcm, wordArray) = try orca.synthesize(
text: textQuotes)
XCTAssertGreaterThan(pcm.count, 0)
XCTAssertGreaterThan(wordArray.count, 0)
}
}

func testSynthesizeToFileQuotes() throws {
let audioDir = try FileManager.default.url(
for: .documentDirectory,
in: .userDomainMask,
appropriateFor: nil,
create: false)
let audioFile = audioDir.appendingPathComponent("test.wav")

for orca in self.orcas {
let wordArrayFromURL = try orca.synthesizeToFile(text: textQuotes, outputURL: audioFile)
XCTAssert(FileManager().fileExists(atPath: audioFile.path))
XCTAssertGreaterThan(wordArrayFromURL.count, 0)
try FileManager().removeItem(at: audioFile)

let wordArrayFromPath = try orca.synthesizeToFile(text: textQuotes, outputPath: audioFile.path)
XCTAssert(FileManager().fileExists(atPath: audioFile.path))
XCTAssertGreaterThan(wordArrayFromPath.count, 0)
try FileManager().removeItem(at: audioFile)
}
}
Expand Down
6 changes: 3 additions & 3 deletions binding/ios/OrcaAppTest/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ source 'https://cdn.cocoapods.org/'
platform :ios, '13.0'

target 'OrcaAppTest' do
pod 'Orca-iOS', '~> 0.2.1'
pod 'Orca-iOS', '~> 0.2.2'
end

target 'OrcaAppTestUITests' do
pod 'Orca-iOS', '~> 0.2.1'
pod 'Orca-iOS', '~> 0.2.2'
end

target 'PerformanceTest' do
pod 'Orca-iOS', '~> 0.2.1'
pod 'Orca-iOS', '~> 0.2.2'
end
8 changes: 4 additions & 4 deletions binding/ios/OrcaAppTest/Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
PODS:
- Orca-iOS (0.2.1)
- Orca-iOS (0.2.2)

DEPENDENCIES:
- Orca-iOS (~> 0.2.1)
- Orca-iOS (~> 0.2.2)

SPEC REPOS:
trunk:
- Orca-iOS

SPEC CHECKSUMS:
Orca-iOS: f6b6124d78189e26c8c0457022a5948217ebe2d3
Orca-iOS: 567ca0e53671d8fc28ba15338db8fe4ff5101d8d

PODFILE CHECKSUM: c74fc8347aa5171d01ba9ce86c96a401037847d4
PODFILE CHECKSUM: 2deb98490df78cf895d797180dcfeccea4f2ad25

COCOAPODS: 1.15.2
42 changes: 21 additions & 21 deletions demo/ios/OrcaDemo/OrcaDemo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 54;
objectVersion = 60;
objects = {

/* Begin PBXBuildFile section */
Expand All @@ -13,7 +13,7 @@
02A1195F268D3FD600A2AC99 /* ViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02A1195E268D3FD600A2AC99 /* ViewModel.swift */; };
1E001B682B76FFE700D8E72D /* AudioPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E001B672B76FFE700D8E72D /* AudioPlayer.swift */; };
1E001B6A2B7D451200D8E72D /* orca_params_female.pv in Resources */ = {isa = PBXBuildFile; fileRef = 1E001B692B7D451200D8E72D /* orca_params_female.pv */; };
B218600C461D96EA568B6D6C /* libPods-OrcaDemo.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A9E91B80C84BF594FCF1FCBD /* libPods-OrcaDemo.a */; };
93BE66087E58F64A2193D44C /* libPods-OrcaDemo.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6293833704AEC548A02FB651 /* libPods-OrcaDemo.a */; };
E125E1892BE99DCA008B6D56 /* AtomicBool.swift in Sources */ = {isa = PBXBuildFile; fileRef = E125E1882BE99DCA008B6D56 /* AtomicBool.swift */; };
E1C5A45F2BE587A2002C0C40 /* AudioPlayerStream.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1C5A45E2BE587A2002C0C40 /* AudioPlayerStream.swift */; };
/* End PBXBuildFile section */
Expand All @@ -25,11 +25,11 @@
02A1194C268D39AB00A2AC99 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
02A11951268D39AB00A2AC99 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
02A1195E268D3FD600A2AC99 /* ViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewModel.swift; sourceTree = "<group>"; };
1C5DAA8ED5D246C3A58AA45B /* Pods-OrcaDemo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-OrcaDemo.release.xcconfig"; path = "Target Support Files/Pods-OrcaDemo/Pods-OrcaDemo.release.xcconfig"; sourceTree = "<group>"; };
1E001B672B76FFE700D8E72D /* AudioPlayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioPlayer.swift; sourceTree = "<group>"; };
1E001B692B7D451200D8E72D /* orca_params_female.pv */ = {isa = PBXFileReference; lastKnownFileType = file; name = orca_params_female.pv; path = ../../../../lib/common/orca_params_female.pv; sourceTree = "<group>"; };
2C3AE1B63A5DD37711F6DD7E /* Pods-OrcaDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-OrcaDemo.debug.xcconfig"; path = "Target Support Files/Pods-OrcaDemo/Pods-OrcaDemo.debug.xcconfig"; sourceTree = "<group>"; };
97762F0F3B18F16DC68C5D67 /* Pods-OrcaDemo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-OrcaDemo.release.xcconfig"; path = "Target Support Files/Pods-OrcaDemo/Pods-OrcaDemo.release.xcconfig"; sourceTree = "<group>"; };
A9E91B80C84BF594FCF1FCBD /* libPods-OrcaDemo.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-OrcaDemo.a"; sourceTree = BUILT_PRODUCTS_DIR; };
3B38AA40E88807F9C21BFD02 /* Pods-OrcaDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-OrcaDemo.debug.xcconfig"; path = "Target Support Files/Pods-OrcaDemo/Pods-OrcaDemo.debug.xcconfig"; sourceTree = "<group>"; };
6293833704AEC548A02FB651 /* libPods-OrcaDemo.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-OrcaDemo.a"; sourceTree = BUILT_PRODUCTS_DIR; };
E125E1882BE99DCA008B6D56 /* AtomicBool.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AtomicBool.swift; sourceTree = "<group>"; };
E1C5A45E2BE587A2002C0C40 /* AudioPlayerStream.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioPlayerStream.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
Expand All @@ -39,7 +39,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
B218600C461D96EA568B6D6C /* libPods-OrcaDemo.a in Frameworks */,
93BE66087E58F64A2193D44C /* libPods-OrcaDemo.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand All @@ -52,7 +52,7 @@
02A11947268D39A700A2AC99 /* OrcaDemo */,
02A11946268D39A700A2AC99 /* Products */,
8DB92FF3DC81AB04D3FF7242 /* Pods */,
4374BA75AB06EC0D059377CD /* Frameworks */,
D4BC0C682CB4645A73894BC8 /* Frameworks */,
);
sourceTree = "<group>";
};
Expand Down Expand Up @@ -80,21 +80,21 @@
path = OrcaDemo;
sourceTree = "<group>";
};
4374BA75AB06EC0D059377CD /* Frameworks */ = {
8DB92FF3DC81AB04D3FF7242 /* Pods */ = {
isa = PBXGroup;
children = (
A9E91B80C84BF594FCF1FCBD /* libPods-OrcaDemo.a */,
3B38AA40E88807F9C21BFD02 /* Pods-OrcaDemo.debug.xcconfig */,
1C5DAA8ED5D246C3A58AA45B /* Pods-OrcaDemo.release.xcconfig */,
);
name = Frameworks;
path = Pods;
sourceTree = "<group>";
};
8DB92FF3DC81AB04D3FF7242 /* Pods */ = {
D4BC0C682CB4645A73894BC8 /* Frameworks */ = {
isa = PBXGroup;
children = (
2C3AE1B63A5DD37711F6DD7E /* Pods-OrcaDemo.debug.xcconfig */,
97762F0F3B18F16DC68C5D67 /* Pods-OrcaDemo.release.xcconfig */,
6293833704AEC548A02FB651 /* libPods-OrcaDemo.a */,
);
path = Pods;
name = Frameworks;
sourceTree = "<group>";
};
/* End PBXGroup section */
Expand All @@ -104,11 +104,11 @@
isa = PBXNativeTarget;
buildConfigurationList = 02A11954268D39AB00A2AC99 /* Build configuration list for PBXNativeTarget "OrcaDemo" */;
buildPhases = (
E5EA3B129B59D3DF4752D82D /* [CP] Check Pods Manifest.lock */,
953F197786B352AA828626D7 /* [CP] Check Pods Manifest.lock */,
02A11941268D39A700A2AC99 /* Sources */,
02A11942268D39A700A2AC99 /* Frameworks */,
02A11943268D39A700A2AC99 /* Resources */,
E85A144184F1D605DB772089 /* [CP] Embed Pods Frameworks */,
C4DE16407A77E6DE174EE4DB /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
Expand All @@ -134,7 +134,7 @@
};
};
buildConfigurationList = 02A11940268D39A700A2AC99 /* Build configuration list for PBXProject "OrcaDemo" */;
compatibilityVersion = "Xcode 9.3";
compatibilityVersion = "Xcode 15.0";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
Expand Down Expand Up @@ -164,7 +164,7 @@
/* End PBXResourcesBuildPhase section */

/* Begin PBXShellScriptBuildPhase section */
E5EA3B129B59D3DF4752D82D /* [CP] Check Pods Manifest.lock */ = {
953F197786B352AA828626D7 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
Expand All @@ -186,7 +186,7 @@
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/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# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
E85A144184F1D605DB772089 /* [CP] Embed Pods Frameworks */ = {
C4DE16407A77E6DE174EE4DB /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
Expand Down Expand Up @@ -340,7 +340,7 @@
};
02A11955268D39AB00A2AC99 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 2C3AE1B63A5DD37711F6DD7E /* Pods-OrcaDemo.debug.xcconfig */;
baseConfigurationReference = 3B38AA40E88807F9C21BFD02 /* Pods-OrcaDemo.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
Expand All @@ -363,7 +363,7 @@
};
02A11956268D39AB00A2AC99 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 97762F0F3B18F16DC68C5D67 /* Pods-OrcaDemo.release.xcconfig */;
baseConfigurationReference = 1C5DAA8ED5D246C3A58AA45B /* Pods-OrcaDemo.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
Expand Down
6 changes: 2 additions & 4 deletions demo/ios/OrcaDemo/OrcaDemo/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,8 @@ struct ContentView: View {
.font(.title3)
.background(lightGray)
.foregroundColor(Color.black)
.onChange(of: text) { newValue in
let updatedText = String(
newValue.prefix(Int(exactly: viewModel.maxCharacterLimit)!))
text = updatedText.replacingOccurrences(of: "", with: "'")
.onChange(of: text) { _ in
text = String(text.prefix(Int(exactly: viewModel.maxCharacterLimit)!))
viewModel.isValid(text: text)
}
.disabled(viewModel.state == .PLAYING)
Expand Down
2 changes: 1 addition & 1 deletion demo/ios/OrcaDemo/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ source 'https://cdn.cocoapods.org/'
platform :ios, '13.0'

target 'OrcaDemo' do
pod 'Orca-iOS', '~> 0.2.1'
pod 'Orca-iOS', '~> 0.2.2'
end
8 changes: 4 additions & 4 deletions demo/ios/OrcaDemo/Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
PODS:
- Orca-iOS (0.2.1)
- Orca-iOS (0.2.2)

DEPENDENCIES:
- Orca-iOS (~> 0.2.1)
- Orca-iOS (~> 0.2.2)

SPEC REPOS:
trunk:
- Orca-iOS

SPEC CHECKSUMS:
Orca-iOS: f6b6124d78189e26c8c0457022a5948217ebe2d3
Orca-iOS: 567ca0e53671d8fc28ba15338db8fe4ff5101d8d

PODFILE CHECKSUM: 652a0a00a9d97df5db1dd9d329fcda8f33faf935
PODFILE CHECKSUM: 118fa8c1767dd3edcc2ec366a16ab74191c6176c

COCOAPODS: 1.15.2

0 comments on commit f17fa71

Please sign in to comment.