← back to Exo
open source astra example
b85d1956bcd36f6ce37a2af81f9fb9e2f4d42739 · 2024-08-18 20:24:14 +0100 · Alex Cheema
Files touched
M .gitignoreA examples/astra/astra.xcodeproj/project.pbxprojA examples/astra/astra.xcodeproj/project.xcworkspace/contents.xcworkspacedataA examples/astra/astra.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plistA examples/astra/astra.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolvedA examples/astra/astra/Assets.xcassets/AccentColor.colorset/Contents.jsonA examples/astra/astra/Assets.xcassets/AppIcon.appiconset/Contents.jsonA examples/astra/astra/Assets.xcassets/Contents.jsonA examples/astra/astra/ContentView.swiftA examples/astra/astra/Preview Content/Preview Assets.xcassets/Contents.jsonA examples/astra/astra/astra.entitlementsA examples/astra/astra/astraApp.swiftA examples/astra/astraTests/astraTests.swiftA examples/astra/astraUITests/astraUITests.swiftA examples/astra/astraUITests/astraUITestsLaunchTests.swift
Diff
commit b85d1956bcd36f6ce37a2af81f9fb9e2f4d42739
Author: Alex Cheema <alexcheema123@gmail.com>
Date: Sun Aug 18 20:24:14 2024 +0100
open source astra example
---
.gitignore | 2 +
examples/astra/astra.xcodeproj/project.pbxproj | 651 +++++++++++++++++++++
.../project.xcworkspace/contents.xcworkspacedata | 7 +
.../xcshareddata/IDEWorkspaceChecks.plist | 8 +
.../xcshareddata/swiftpm/Package.resolved | 33 ++
.../AccentColor.colorset/Contents.json | 11 +
.../AppIcon.appiconset/Contents.json | 63 ++
examples/astra/astra/Assets.xcassets/Contents.json | 6 +
examples/astra/astra/ContentView.swift | 243 ++++++++
.../Preview Assets.xcassets/Contents.json | 6 +
examples/astra/astra/astra.entitlements | 20 +
examples/astra/astra/astraApp.swift | 17 +
examples/astra/astraTests/astraTests.swift | 35 ++
examples/astra/astraUITests/astraUITests.swift | 41 ++
.../astraUITests/astraUITestsLaunchTests.swift | 32 +
15 files changed, 1175 insertions(+)
diff --git a/.gitignore b/.gitignore
index fcae47e7..bc9f0578 100644
--- a/.gitignore
+++ b/.gitignore
@@ -168,3 +168,5 @@ cython_debug/
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
+
+**/*.xcodeproj/*
\ No newline at end of file
diff --git a/examples/astra/astra.xcodeproj/project.pbxproj b/examples/astra/astra.xcodeproj/project.pbxproj
new file mode 100644
index 00000000..3cd74239
--- /dev/null
+++ b/examples/astra/astra.xcodeproj/project.pbxproj
@@ -0,0 +1,651 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 56;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ FA3E988F2C725A0200E4E795 /* astraApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA3E988E2C725A0200E4E795 /* astraApp.swift */; };
+ FA3E98912C725A0200E4E795 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA3E98902C725A0200E4E795 /* ContentView.swift */; };
+ FA3E98932C725A0300E4E795 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = FA3E98922C725A0300E4E795 /* Assets.xcassets */; };
+ FA3E98972C725A0300E4E795 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = FA3E98962C725A0300E4E795 /* Preview Assets.xcassets */; };
+ FA3E98A12C725A0300E4E795 /* astraTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA3E98A02C725A0300E4E795 /* astraTests.swift */; };
+ FA3E98AB2C725A0300E4E795 /* astraUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA3E98AA2C725A0300E4E795 /* astraUITests.swift */; };
+ FA3E98AD2C725A0300E4E795 /* astraUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA3E98AC2C725A0300E4E795 /* astraUITestsLaunchTests.swift */; };
+ FA3E98BB2C725BF800E4E795 /* WhisperKit in Frameworks */ = {isa = PBXBuildFile; productRef = FA3E98BA2C725BF800E4E795 /* WhisperKit */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ FA3E989D2C725A0300E4E795 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = FA3E98832C725A0200E4E795 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = FA3E988A2C725A0200E4E795;
+ remoteInfo = astra;
+ };
+ FA3E98A72C725A0300E4E795 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = FA3E98832C725A0200E4E795 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = FA3E988A2C725A0200E4E795;
+ remoteInfo = astra;
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXFileReference section */
+ FA3E988B2C725A0200E4E795 /* astra.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = astra.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ FA3E988E2C725A0200E4E795 /* astraApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = astraApp.swift; sourceTree = "<group>"; };
+ FA3E98902C725A0200E4E795 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
+ FA3E98922C725A0300E4E795 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
+ FA3E98942C725A0300E4E795 /* astra.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = astra.entitlements; sourceTree = "<group>"; };
+ FA3E98962C725A0300E4E795 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
+ FA3E989C2C725A0300E4E795 /* astraTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = astraTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+ FA3E98A02C725A0300E4E795 /* astraTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = astraTests.swift; sourceTree = "<group>"; };
+ FA3E98A62C725A0300E4E795 /* astraUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = astraUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+ FA3E98AA2C725A0300E4E795 /* astraUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = astraUITests.swift; sourceTree = "<group>"; };
+ FA3E98AC2C725A0300E4E795 /* astraUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = astraUITestsLaunchTests.swift; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ FA3E98882C725A0200E4E795 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ FA3E98BB2C725BF800E4E795 /* WhisperKit in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ FA3E98992C725A0300E4E795 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ FA3E98A32C725A0300E4E795 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ FA3E98822C725A0200E4E795 = {
+ isa = PBXGroup;
+ children = (
+ FA3E988D2C725A0200E4E795 /* astra */,
+ FA3E989F2C725A0300E4E795 /* astraTests */,
+ FA3E98A92C725A0300E4E795 /* astraUITests */,
+ FA3E988C2C725A0200E4E795 /* Products */,
+ );
+ sourceTree = "<group>";
+ };
+ FA3E988C2C725A0200E4E795 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ FA3E988B2C725A0200E4E795 /* astra.app */,
+ FA3E989C2C725A0300E4E795 /* astraTests.xctest */,
+ FA3E98A62C725A0300E4E795 /* astraUITests.xctest */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ FA3E988D2C725A0200E4E795 /* astra */ = {
+ isa = PBXGroup;
+ children = (
+ FA3E988E2C725A0200E4E795 /* astraApp.swift */,
+ FA3E98902C725A0200E4E795 /* ContentView.swift */,
+ FA3E98922C725A0300E4E795 /* Assets.xcassets */,
+ FA3E98942C725A0300E4E795 /* astra.entitlements */,
+ FA3E98952C725A0300E4E795 /* Preview Content */,
+ );
+ path = astra;
+ sourceTree = "<group>";
+ };
+ FA3E98952C725A0300E4E795 /* Preview Content */ = {
+ isa = PBXGroup;
+ children = (
+ FA3E98962C725A0300E4E795 /* Preview Assets.xcassets */,
+ );
+ path = "Preview Content";
+ sourceTree = "<group>";
+ };
+ FA3E989F2C725A0300E4E795 /* astraTests */ = {
+ isa = PBXGroup;
+ children = (
+ FA3E98A02C725A0300E4E795 /* astraTests.swift */,
+ );
+ path = astraTests;
+ sourceTree = "<group>";
+ };
+ FA3E98A92C725A0300E4E795 /* astraUITests */ = {
+ isa = PBXGroup;
+ children = (
+ FA3E98AA2C725A0300E4E795 /* astraUITests.swift */,
+ FA3E98AC2C725A0300E4E795 /* astraUITestsLaunchTests.swift */,
+ );
+ path = astraUITests;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ FA3E988A2C725A0200E4E795 /* astra */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = FA3E98B02C725A0300E4E795 /* Build configuration list for PBXNativeTarget "astra" */;
+ buildPhases = (
+ FA3E98872C725A0200E4E795 /* Sources */,
+ FA3E98882C725A0200E4E795 /* Frameworks */,
+ FA3E98892C725A0200E4E795 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = astra;
+ packageProductDependencies = (
+ FA3E98BA2C725BF800E4E795 /* WhisperKit */,
+ );
+ productName = astra;
+ productReference = FA3E988B2C725A0200E4E795 /* astra.app */;
+ productType = "com.apple.product-type.application";
+ };
+ FA3E989B2C725A0300E4E795 /* astraTests */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = FA3E98B32C725A0300E4E795 /* Build configuration list for PBXNativeTarget "astraTests" */;
+ buildPhases = (
+ FA3E98982C725A0300E4E795 /* Sources */,
+ FA3E98992C725A0300E4E795 /* Frameworks */,
+ FA3E989A2C725A0300E4E795 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ FA3E989E2C725A0300E4E795 /* PBXTargetDependency */,
+ );
+ name = astraTests;
+ productName = astraTests;
+ productReference = FA3E989C2C725A0300E4E795 /* astraTests.xctest */;
+ productType = "com.apple.product-type.bundle.unit-test";
+ };
+ FA3E98A52C725A0300E4E795 /* astraUITests */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = FA3E98B62C725A0300E4E795 /* Build configuration list for PBXNativeTarget "astraUITests" */;
+ buildPhases = (
+ FA3E98A22C725A0300E4E795 /* Sources */,
+ FA3E98A32C725A0300E4E795 /* Frameworks */,
+ FA3E98A42C725A0300E4E795 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ FA3E98A82C725A0300E4E795 /* PBXTargetDependency */,
+ );
+ name = astraUITests;
+ productName = astraUITests;
+ productReference = FA3E98A62C725A0300E4E795 /* astraUITests.xctest */;
+ productType = "com.apple.product-type.bundle.ui-testing";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ FA3E98832C725A0200E4E795 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ BuildIndependentTargetsInParallel = 1;
+ LastSwiftUpdateCheck = 1540;
+ LastUpgradeCheck = 1540;
+ TargetAttributes = {
+ FA3E988A2C725A0200E4E795 = {
+ CreatedOnToolsVersion = 15.4;
+ };
+ FA3E989B2C725A0300E4E795 = {
+ CreatedOnToolsVersion = 15.4;
+ TestTargetID = FA3E988A2C725A0200E4E795;
+ };
+ FA3E98A52C725A0300E4E795 = {
+ CreatedOnToolsVersion = 15.4;
+ TestTargetID = FA3E988A2C725A0200E4E795;
+ };
+ };
+ };
+ buildConfigurationList = FA3E98862C725A0200E4E795 /* Build configuration list for PBXProject "astra" */;
+ compatibilityVersion = "Xcode 14.0";
+ developmentRegion = en;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );
+ mainGroup = FA3E98822C725A0200E4E795;
+ packageReferences = (
+ FA3E98B92C725BF800E4E795 /* XCRemoteSwiftPackageReference "whisperkit" */,
+ );
+ productRefGroup = FA3E988C2C725A0200E4E795 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ FA3E988A2C725A0200E4E795 /* astra */,
+ FA3E989B2C725A0300E4E795 /* astraTests */,
+ FA3E98A52C725A0300E4E795 /* astraUITests */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ FA3E98892C725A0200E4E795 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ FA3E98972C725A0300E4E795 /* Preview Assets.xcassets in Resources */,
+ FA3E98932C725A0300E4E795 /* Assets.xcassets in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ FA3E989A2C725A0300E4E795 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ FA3E98A42C725A0300E4E795 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ FA3E98872C725A0200E4E795 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ FA3E98912C725A0200E4E795 /* ContentView.swift in Sources */,
+ FA3E988F2C725A0200E4E795 /* astraApp.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ FA3E98982C725A0300E4E795 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ FA3E98A12C725A0300E4E795 /* astraTests.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ FA3E98A22C725A0300E4E795 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ FA3E98AD2C725A0300E4E795 /* astraUITestsLaunchTests.swift in Sources */,
+ FA3E98AB2C725A0300E4E795 /* astraUITests.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ FA3E989E2C725A0300E4E795 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = FA3E988A2C725A0200E4E795 /* astra */;
+ targetProxy = FA3E989D2C725A0300E4E795 /* PBXContainerItemProxy */;
+ };
+ FA3E98A82C725A0300E4E795 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = FA3E988A2C725A0200E4E795 /* astra */;
+ targetProxy = FA3E98A72C725A0300E4E795 /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin XCBuildConfiguration section */
+ FA3E98AE2C725A0300E4E795 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ ENABLE_USER_SCRIPT_SANDBOXING = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu17;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ 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;
+ LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
+ MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+ MTL_FAST_MATH = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ };
+ name = Debug;
+ };
+ FA3E98AF2C725A0300E4E795 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_USER_SCRIPT_SANDBOXING = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu17;
+ GCC_NO_COMMON_BLOCKS = YES;
+ 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;
+ LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ MTL_FAST_MATH = YES;
+ SWIFT_COMPILATION_MODE = wholemodule;
+ };
+ name = Release;
+ };
+ FA3E98B12C725A0300E4E795 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+ CODE_SIGN_ENTITLEMENTS = astra/astra.entitlements;
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ DEVELOPMENT_ASSET_PATHS = "\"astra/Preview Content\"";
+ DEVELOPMENT_TEAM = 8NFAS2P4ND;
+ ENABLE_HARDENED_RUNTIME = YES;
+ ENABLE_PREVIEWS = YES;
+ GENERATE_INFOPLIST_FILE = YES;
+ INFOPLIST_KEY_NSMicrophoneUsageDescription = "Uses your microphone for transcribing audio";
+ "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES;
+ "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES;
+ "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphoneos*]" = YES;
+ "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphonesimulator*]" = YES;
+ "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphoneos*]" = YES;
+ "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphonesimulator*]" = YES;
+ "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphoneos*]" = UIStatusBarStyleDefault;
+ "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphonesimulator*]" = UIStatusBarStyleDefault;
+ INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
+ INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
+ IPHONEOS_DEPLOYMENT_TARGET = 17.5;
+ LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks";
+ "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
+ MACOSX_DEPLOYMENT_TARGET = 14.4;
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = net.exolabs.astra;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = auto;
+ SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx";
+ SWIFT_EMIT_LOC_STRINGS = YES;
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ FA3E98B22C725A0300E4E795 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+ CODE_SIGN_ENTITLEMENTS = astra/astra.entitlements;
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ DEVELOPMENT_ASSET_PATHS = "\"astra/Preview Content\"";
+ DEVELOPMENT_TEAM = 8NFAS2P4ND;
+ ENABLE_HARDENED_RUNTIME = YES;
+ ENABLE_PREVIEWS = YES;
+ GENERATE_INFOPLIST_FILE = YES;
+ INFOPLIST_KEY_NSMicrophoneUsageDescription = "Uses your microphone for transcribing audio";
+ "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES;
+ "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES;
+ "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphoneos*]" = YES;
+ "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphonesimulator*]" = YES;
+ "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphoneos*]" = YES;
+ "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphonesimulator*]" = YES;
+ "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphoneos*]" = UIStatusBarStyleDefault;
+ "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphonesimulator*]" = UIStatusBarStyleDefault;
+ INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
+ INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
+ IPHONEOS_DEPLOYMENT_TARGET = 17.5;
+ LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks";
+ "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
+ MACOSX_DEPLOYMENT_TARGET = 14.4;
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = net.exolabs.astra;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = auto;
+ SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx";
+ SWIFT_EMIT_LOC_STRINGS = YES;
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Release;
+ };
+ FA3E98B42C725A0300E4E795 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
+ BUNDLE_LOADER = "$(TEST_HOST)";
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ DEVELOPMENT_TEAM = 8NFAS2P4ND;
+ GENERATE_INFOPLIST_FILE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 17.5;
+ MACOSX_DEPLOYMENT_TARGET = 14.4;
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = net.exolabs.astraTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = auto;
+ SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx";
+ SWIFT_EMIT_LOC_STRINGS = NO;
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/astra.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/astra";
+ };
+ name = Debug;
+ };
+ FA3E98B52C725A0300E4E795 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
+ BUNDLE_LOADER = "$(TEST_HOST)";
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ DEVELOPMENT_TEAM = 8NFAS2P4ND;
+ GENERATE_INFOPLIST_FILE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 17.5;
+ MACOSX_DEPLOYMENT_TARGET = 14.4;
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = net.exolabs.astraTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = auto;
+ SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx";
+ SWIFT_EMIT_LOC_STRINGS = NO;
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/astra.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/astra";
+ };
+ name = Release;
+ };
+ FA3E98B72C725A0300E4E795 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ DEVELOPMENT_TEAM = 8NFAS2P4ND;
+ GENERATE_INFOPLIST_FILE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 17.5;
+ MACOSX_DEPLOYMENT_TARGET = 14.4;
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = net.exolabs.astraUITests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = auto;
+ SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx";
+ SWIFT_EMIT_LOC_STRINGS = NO;
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ TEST_TARGET_NAME = astra;
+ };
+ name = Debug;
+ };
+ FA3E98B82C725A0300E4E795 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ DEVELOPMENT_TEAM = 8NFAS2P4ND;
+ GENERATE_INFOPLIST_FILE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 17.5;
+ MACOSX_DEPLOYMENT_TARGET = 14.4;
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = net.exolabs.astraUITests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = auto;
+ SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx";
+ SWIFT_EMIT_LOC_STRINGS = NO;
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ TEST_TARGET_NAME = astra;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ FA3E98862C725A0200E4E795 /* Build configuration list for PBXProject "astra" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ FA3E98AE2C725A0300E4E795 /* Debug */,
+ FA3E98AF2C725A0300E4E795 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ FA3E98B02C725A0300E4E795 /* Build configuration list for PBXNativeTarget "astra" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ FA3E98B12C725A0300E4E795 /* Debug */,
+ FA3E98B22C725A0300E4E795 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ FA3E98B32C725A0300E4E795 /* Build configuration list for PBXNativeTarget "astraTests" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ FA3E98B42C725A0300E4E795 /* Debug */,
+ FA3E98B52C725A0300E4E795 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ FA3E98B62C725A0300E4E795 /* Build configuration list for PBXNativeTarget "astraUITests" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ FA3E98B72C725A0300E4E795 /* Debug */,
+ FA3E98B82C725A0300E4E795 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+
+/* Begin XCRemoteSwiftPackageReference section */
+ FA3E98B92C725BF800E4E795 /* XCRemoteSwiftPackageReference "whisperkit" */ = {
+ isa = XCRemoteSwiftPackageReference;
+ repositoryURL = "https://github.com/argmaxinc/whisperkit";
+ requirement = {
+ branch = main;
+ kind = branch;
+ };
+ };
+/* End XCRemoteSwiftPackageReference section */
+
+/* Begin XCSwiftPackageProductDependency section */
+ FA3E98BA2C725BF800E4E795 /* WhisperKit */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = FA3E98B92C725BF800E4E795 /* XCRemoteSwiftPackageReference "whisperkit" */;
+ productName = WhisperKit;
+ };
+/* End XCSwiftPackageProductDependency section */
+ };
+ rootObject = FA3E98832C725A0200E4E795 /* Project object */;
+}
diff --git a/examples/astra/astra.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/examples/astra/astra.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 00000000..919434a6
--- /dev/null
+++ b/examples/astra/astra.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+ version = "1.0">
+ <FileRef
+ location = "self:">
+ </FileRef>
+</Workspace>
diff --git a/examples/astra/astra.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/examples/astra/astra.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 00000000..18d98100
--- /dev/null
+++ b/examples/astra/astra.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>IDEDidComputeMac32BitWarning</key>
+ <true/>
+</dict>
+</plist>
diff --git a/examples/astra/astra.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/examples/astra/astra.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
new file mode 100644
index 00000000..edc15da2
--- /dev/null
+++ b/examples/astra/astra.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
@@ -0,0 +1,33 @@
+{
+ "originHash" : "8f61689e55c5551e76f2c686d145061dc1fa621a58cbca576565ebfabc15c894",
+ "pins" : [
+ {
+ "identity" : "swift-argument-parser",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/apple/swift-argument-parser.git",
+ "state" : {
+ "revision" : "c8ed701b513cf5177118a175d85fbbbcd707ab41",
+ "version" : "1.3.0"
+ }
+ },
+ {
+ "identity" : "swift-transformers",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/huggingface/swift-transformers.git",
+ "state" : {
+ "revision" : "74b94211bdc741694ed7e700a1104c72e5ba68fe",
+ "version" : "0.1.7"
+ }
+ },
+ {
+ "identity" : "whisperkit",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/argmaxinc/whisperkit",
+ "state" : {
+ "branch" : "main",
+ "revision" : "59aaa4e5f211622f9a5e133440220d9974641d3b"
+ }
+ }
+ ],
+ "version" : 3
+}
diff --git a/examples/astra/astra/Assets.xcassets/AccentColor.colorset/Contents.json b/examples/astra/astra/Assets.xcassets/AccentColor.colorset/Contents.json
new file mode 100644
index 00000000..eb878970
--- /dev/null
+++ b/examples/astra/astra/Assets.xcassets/AccentColor.colorset/Contents.json
@@ -0,0 +1,11 @@
+{
+ "colors" : [
+ {
+ "idiom" : "universal"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/examples/astra/astra/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/astra/astra/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 00000000..532cd729
--- /dev/null
+++ b/examples/astra/astra/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,63 @@
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "platform" : "ios",
+ "size" : "1024x1024"
+ },
+ {
+ "idiom" : "mac",
+ "scale" : "1x",
+ "size" : "16x16"
+ },
+ {
+ "idiom" : "mac",
+ "scale" : "2x",
+ "size" : "16x16"
+ },
+ {
+ "idiom" : "mac",
+ "scale" : "1x",
+ "size" : "32x32"
+ },
+ {
+ "idiom" : "mac",
+ "scale" : "2x",
+ "size" : "32x32"
+ },
+ {
+ "idiom" : "mac",
+ "scale" : "1x",
+ "size" : "128x128"
+ },
+ {
+ "idiom" : "mac",
+ "scale" : "2x",
+ "size" : "128x128"
+ },
+ {
+ "idiom" : "mac",
+ "scale" : "1x",
+ "size" : "256x256"
+ },
+ {
+ "idiom" : "mac",
+ "scale" : "2x",
+ "size" : "256x256"
+ },
+ {
+ "idiom" : "mac",
+ "scale" : "1x",
+ "size" : "512x512"
+ },
+ {
+ "idiom" : "mac",
+ "scale" : "2x",
+ "size" : "512x512"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/examples/astra/astra/Assets.xcassets/Contents.json b/examples/astra/astra/Assets.xcassets/Contents.json
new file mode 100644
index 00000000..73c00596
--- /dev/null
+++ b/examples/astra/astra/Assets.xcassets/Contents.json
@@ -0,0 +1,6 @@
+{
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/examples/astra/astra/ContentView.swift b/examples/astra/astra/ContentView.swift
new file mode 100644
index 00000000..250a228f
--- /dev/null
+++ b/examples/astra/astra/ContentView.swift
@@ -0,0 +1,243 @@
+import SwiftUI
+import WhisperKit
+import AVFoundation
+
+struct ContentView: View {
+ @State private var whisperKit: WhisperKit?
+ @State private var isListening = false
+ @State private var currentText = ""
+ @State private var bufferSeconds: Double = 0.5 // or whatever the actual buffer size is
+ @State private var modelState: ModelState = .unloaded
+
+ @AppStorage("selectedModel") private var selectedModel: String = "large"
+ @AppStorage("selectedLanguage") private var selectedLanguage: String = "english"
+ @AppStorage("selectedTask") private var selectedTask: String = "transcribe"
+
+ @State private var isRecordingMemo = false
+ @State private var currentMemo = ""
+ @State private var lastVoiceActivityTime = Date()
+ @State private var silenceTimer: Timer?
+ @State private var voiceActivityThreshold: Float = 0.3 // Start with a lower value
+ @State private var silenceTimeThreshold = 1.0
+ @State private var debugText = ""
+
+ var body: some View {
+ VStack {
+ Text(currentText)
+ .padding()
+
+ Text(isListening ? "Listening..." : "Not listening")
+ .foregroundColor(isListening ? .green : .red)
+
+ if isRecordingMemo {
+ Text("Recording memo...")
+ .foregroundColor(.blue)
+ }
+
+ Picker("Model", selection: $selectedModel) {
+ Text("large").tag("large")
+ Text("base").tag("base")
+ Text("small").tag("small")
+ }
+ .pickerStyle(SegmentedPickerStyle())
+ .padding()
+
+ Button("Load Model") {
+ loadModel(selectedModel)
+ }
+ .disabled(modelState == .loaded)
+ .padding()
+
+ Text("Model State: \(modelState.description)")
+
+ Text(debugText)
+ .font(.caption)
+ .foregroundColor(.gray)
+
+ Slider(value: $voiceActivityThreshold, in: 0.01...1.0) {
+ Text("Voice Activity Threshold: \(voiceActivityThreshold, specifier: "%.2f")")
+ }
+ }
+ .onAppear {
+ setupWhisperKit()
+ }
+ }
+
+ private func setupWhisperKit() {
+ Task {
+ do {
+ whisperKit = try await WhisperKit(verbose: true)
+ print("WhisperKit initialized successfully")
+ startListening()
+ } catch {
+ print("Error initializing WhisperKit: \(error)")
+ }
+ }
+ }
+
+ private func loadModel(_ model: String) {
+ Task {
+ let success = try await loadModel(selectedModel)
+ if success {
+ startListening()
+ } else {
+ print("Model failed to load, cannot start listening")
+ }
+ }
+ }
+
+ private func startListening() {
+ guard let audioProcessor = whisperKit?.audioProcessor else {
+ print("AudioProcessor not available")
+ return
+ }
+
+ do {
+ try audioProcessor.startRecordingLive { buffer in
+ DispatchQueue.main.async {
+ checkVoiceActivity()
+ }
+ }
+ isListening = true
+ } catch {
+ print("Error starting listening: \(error)")
+ }
+ }
+
+ private func checkVoiceActivity() {
+ guard let audioProcessor = whisperKit?.audioProcessor else { return }
+
+ let voiceDetected = AudioProcessor.isVoiceDetected(
+ in: audioProcessor.relativeEnergy,
+ nextBufferInSeconds: Float(bufferSeconds),
+ silenceThreshold: Float(voiceActivityThreshold)
+ )
+
+ // Debug logging
+ let energyValuesToConsider = Int(Float(bufferSeconds) / 0.1)
+ let nextBufferEnergies = audioProcessor.relativeEnergy.suffix(energyValuesToConsider)
+ let numberOfValuesToCheck = max(10, nextBufferEnergies.count - 10)
+ let relevantEnergies = Array(nextBufferEnergies.prefix(numberOfValuesToCheck))
+
+ debugText = """
+ Buffer seconds: \(bufferSeconds)
+ Energy values to consider: \(energyValuesToConsider)
+ Number of values to check: \(numberOfValuesToCheck)
+ Silence threshold: \(voiceActivityThreshold)
+ Relevant energies: \(relevantEnergies)
+ Max energy: \(relevantEnergies.max() ?? 0)
+ Voice detected: \(voiceDetected)
+ """
+
+ if voiceDetected {
+ lastVoiceActivityTime = Date()
+ if !isRecordingMemo {
+ startNewMemo()
+ }
+ } else {
+ checkSilence()
+ }
+ }
+
+ private func checkSilence() {
+ let silenceDuration = Date().timeIntervalSince(lastVoiceActivityTime)
+ debugText += "\nSilence duration: \(silenceDuration)"
+
+ if silenceDuration > silenceTimeThreshold {
+ endCurrentMemo()
+ }
+ }
+
+ private func endCurrentMemo() {
+ if isRecordingMemo {
+ isRecordingMemo = false
+ silenceTimer?.invalidate()
+ silenceTimer = nil
+ if !currentMemo.isEmpty {
+ saveMemoToFile(currentMemo)
+ currentMemo = ""
+ }
+ // Flush the transcribed text and reset audio samples
+ currentText = ""
+ whisperKit?.audioProcessor.purgeAudioSamples(keepingLast: 0)
+ print("Ended memo")
+ debugText += "\nMemo ended"
+ }
+ }
+
+ private func startNewMemo() {
+ isRecordingMemo = true
+ currentMemo = ""
+ silenceTimer?.invalidate()
+ silenceTimer = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { _ in
+ checkSilence()
+ }
+ transcribeInRealTime()
+ print("Started new memo")
+ }
+
+ private func transcribeInRealTime() {
+ Task {
+ while isRecordingMemo {
+ if let samples = whisperKit?.audioProcessor.audioSamples, samples.count > WhisperKit.sampleRate {
+ do {
+ let result = try await whisperKit?.transcribe(audioArray: Array(samples))
+ await MainActor.run {
+ let newText = result?.first?.text ?? ""
+ if !newText.isEmpty {
+ currentMemo += newText
+ currentText += newText
+ }
+ }
+ whisperKit?.audioProcessor.purgeAudioSamples(keepingLast: 0)
+ } catch {
+ print("Transcription error: \(error)")
+ }
+ }
+ try await Task.sleep(nanoseconds: 500_000_000) // Sleep for 0.5 seconds
+ }
+ }
+ }
+
+ private func saveMemoToFile(_ memo: String) {
+ let dateFormatter = DateFormatter()
+ dateFormatter.dateFormat = "yyyy-MM-dd_HH-mm-ss"
+ let fileName = "memo_\(dateFormatter.string(from: Date())).txt"
+
+ guard let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else {
+ print("Unable to access documents directory")
+ return
+ }
+
+ let fileURL = documentsDirectory.appendingPathComponent(fileName)
+
+ do {
+ try memo.write(to: fileURL, atomically: true, encoding: .utf8)
+ print("Memo saved to: \(fileURL.path)")
+ } catch {
+ print("Error saving memo: \(error)")
+ }
+ }
+
+ private func loadModel(_ model: String) async throws -> Bool {
+ guard let whisperKit = whisperKit else {
+ print("WhisperKit instance not initialized")
+ return false
+ }
+
+ modelState = .loading
+ do {
+ print("Starting to load model: \(model)")
+ try await whisperKit.loadModels()
+ await MainActor.run {
+ modelState = .loaded
+ print("Model loaded successfully: \(model)")
+ }
+ return true
+ } catch {
+ print("Error loading model: \(error)")
+ await MainActor.run { modelState = .unloaded }
+ return false
+ }
+ }
+}
diff --git a/examples/astra/astra/Preview Content/Preview Assets.xcassets/Contents.json b/examples/astra/astra/Preview Content/Preview Assets.xcassets/Contents.json
new file mode 100644
index 00000000..73c00596
--- /dev/null
+++ b/examples/astra/astra/Preview Content/Preview Assets.xcassets/Contents.json
@@ -0,0 +1,6 @@
+{
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/examples/astra/astra/astra.entitlements b/examples/astra/astra/astra.entitlements
new file mode 100644
index 00000000..dc74f055
--- /dev/null
+++ b/examples/astra/astra/astra.entitlements
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>com.apple.developer.kernel.increased-memory-limit</key>
+ <true/>
+ <key>com.apple.security.app-sandbox</key>
+ <true/>
+ <key>com.apple.security.device.audio-input</key>
+ <true/>
+ <key>com.apple.security.files.downloads.read-only</key>
+ <true/>
+ <key>com.apple.security.files.user-selected.read-write</key>
+ <true/>
+ <key>com.apple.security.network.client</key>
+ <true/>
+ <key>com.apple.security.network.server</key>
+ <true/>
+</dict>
+</plist>
diff --git a/examples/astra/astra/astraApp.swift b/examples/astra/astra/astraApp.swift
new file mode 100644
index 00000000..79cfe707
--- /dev/null
+++ b/examples/astra/astra/astraApp.swift
@@ -0,0 +1,17 @@
+//
+// astraApp.swift
+// astra
+//
+// Created by Alex on 18/08/2024.
+//
+
+import SwiftUI
+
+@main
+struct astraApp: App {
+ var body: some Scene {
+ WindowGroup {
+ ContentView()
+ }
+ }
+}
diff --git a/examples/astra/astraTests/astraTests.swift b/examples/astra/astraTests/astraTests.swift
new file mode 100644
index 00000000..982e0c91
--- /dev/null
+++ b/examples/astra/astraTests/astraTests.swift
@@ -0,0 +1,35 @@
+//
+// astraTests.swift
+// astraTests
+//
+// Created by Alex on 18/08/2024.
+//
+
+import XCTest
+
+final class astraTests: XCTestCase {
+
+ override func setUpWithError() throws {
+ // Put setup code here. This method is called before the invocation of each test method in the class.
+ }
+
+ override func tearDownWithError() throws {
+ // Put teardown code here. This method is called after the invocation of each test method in the class.
+ }
+
+ func testExample() throws {
+ // This is an example of a functional test case.
+ // Use XCTAssert and related functions to verify your tests produce the correct results.
+ // Any test you write for XCTest can be annotated as throws and async.
+ // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error.
+ // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards.
+ }
+
+ func testPerformanceExample() throws {
+ // This is an example of a performance test case.
+ measure {
+ // Put the code you want to measure the time of here.
+ }
+ }
+
+}
diff --git a/examples/astra/astraUITests/astraUITests.swift b/examples/astra/astraUITests/astraUITests.swift
new file mode 100644
index 00000000..97a293d9
--- /dev/null
+++ b/examples/astra/astraUITests/astraUITests.swift
@@ -0,0 +1,41 @@
+//
+// astraUITests.swift
+// astraUITests
+//
+// Created by Alex on 18/08/2024.
+//
+
+import XCTest
+
+final class astraUITests: XCTestCase {
+
+ override func setUpWithError() throws {
+ // Put setup code here. This method is called before the invocation of each test method in the class.
+
+ // In UI tests it is usually best to stop immediately when a failure occurs.
+ continueAfterFailure = false
+
+ // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
+ }
+
+ override func tearDownWithError() throws {
+ // Put teardown code here. This method is called after the invocation of each test method in the class.
+ }
+
+ func testExample() throws {
+ // UI tests must launch the application that they test.
+ let app = XCUIApplication()
+ app.launch()
+
+ // Use XCTAssert and related functions to verify your tests produce the correct results.
+ }
+
+ func testLaunchPerformance() throws {
+ if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) {
+ // This measures how long it takes to launch your application.
+ measure(metrics: [XCTApplicationLaunchMetric()]) {
+ XCUIApplication().launch()
+ }
+ }
+ }
+}
diff --git a/examples/astra/astraUITests/astraUITestsLaunchTests.swift b/examples/astra/astraUITests/astraUITestsLaunchTests.swift
new file mode 100644
index 00000000..d05a1484
--- /dev/null
+++ b/examples/astra/astraUITests/astraUITestsLaunchTests.swift
@@ -0,0 +1,32 @@
+//
+// astraUITestsLaunchTests.swift
+// astraUITests
+//
+// Created by Alex on 18/08/2024.
+//
+
+import XCTest
+
+final class astraUITestsLaunchTests: XCTestCase {
+
+ override class var runsForEachTargetApplicationUIConfiguration: Bool {
+ true
+ }
+
+ override func setUpWithError() throws {
+ continueAfterFailure = false
+ }
+
+ func testLaunch() throws {
+ let app = XCUIApplication()
+ app.launch()
+
+ // Insert steps here to perform after app launch but before taking a screenshot,
+ // such as logging into a test account or navigating somewhere in the app
+
+ let attachment = XCTAttachment(screenshot: app.screenshot())
+ attachment.name = "Launch Screen"
+ attachment.lifetime = .keepAlways
+ add(attachment)
+ }
+}
← e2e98c30 Update README.md
·
back to Exo
·
send api request in astra example ff71ccc6 →