]> git.djapps.eu Git - pkg/ggml/sources/whisper.cpp/commitdiff
examples : add whisper.swiftui demo app (#308)
authorDigipom <redacted>
Fri, 23 Dec 2022 08:56:18 +0000 (03:56 -0500)
committerGitHub <redacted>
Fri, 23 Dec 2022 08:56:18 +0000 (10:56 +0200)
* Add SwiftUI demo project.

* Add -DGGML_USE_ACCELERATE

18 files changed:
examples/whisper.swiftui/README.md [new file with mode: 0644]
examples/whisper.swiftui/whisper.cpp.swift/LibWhisper.swift [new file with mode: 0644]
examples/whisper.swiftui/whisper.cpp.swift/WhisperCppDemo-Bridging-Header.h [new file with mode: 0644]
examples/whisper.swiftui/whisper.swiftui.demo/Models/WhisperState.swift [new file with mode: 0644]
examples/whisper.swiftui/whisper.swiftui.demo/Supporting files/Assets.xcassets/AccentColor.colorset/Contents.json [new file with mode: 0644]
examples/whisper.swiftui/whisper.swiftui.demo/Supporting files/Assets.xcassets/AppIcon.appiconset/Contents.json [new file with mode: 0644]
examples/whisper.swiftui/whisper.swiftui.demo/Supporting files/Assets.xcassets/Contents.json [new file with mode: 0644]
examples/whisper.swiftui/whisper.swiftui.demo/Supporting files/Preview Content/Preview Assets.xcassets/Contents.json [new file with mode: 0644]
examples/whisper.swiftui/whisper.swiftui.demo/Supporting files/WhisperCppDemo.entitlements [new file with mode: 0644]
examples/whisper.swiftui/whisper.swiftui.demo/UI/ContentView.swift [new file with mode: 0644]
examples/whisper.swiftui/whisper.swiftui.demo/Utils/Recorder.swift [new file with mode: 0644]
examples/whisper.swiftui/whisper.swiftui.demo/Utils/RiffWaveUtils.swift [new file with mode: 0644]
examples/whisper.swiftui/whisper.swiftui.demo/WhisperCppDemoApp.swift [new file with mode: 0644]
examples/whisper.swiftui/whisper.swiftui.xcodeproj/.gitignore [new file with mode: 0644]
examples/whisper.swiftui/whisper.swiftui.xcodeproj/project.pbxproj [new file with mode: 0644]
examples/whisper.swiftui/whisper.swiftui.xcodeproj/project.xcworkspace/.gitignore [new file with mode: 0644]
examples/whisper.swiftui/whisper.swiftui.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist [new file with mode: 0644]
examples/whisper.swiftui/whisper.swiftui.xcodeproj/xcshareddata/xcschemes/WhisperCppDemo.xcscheme [new file with mode: 0644]

diff --git a/examples/whisper.swiftui/README.md b/examples/whisper.swiftui/README.md
new file mode 100644 (file)
index 0000000..0fa2246
--- /dev/null
@@ -0,0 +1,12 @@
+A sample SwiftUI app using [whisper.cpp](https://github.com/ggerganov/whisper.cpp/) to do voice-to-text transcriptions.
+See also: [whisper.objc](https://github.com/ggerganov/whisper.cpp/tree/master/examples/whisper.objc).
+
+To use:
+
+1. Select a model from the [whisper.cpp repository](https://github.com/ggerganov/whisper.cpp/tree/master/models).[^1]
+2. Add the model to "whisper.swiftui.demo/Resources/models" via Xcode.
+3. Select a sample audio file (for example, [jfk.wav](https://github.com/ggerganov/whisper.cpp/raw/master/samples/jfk.wav)).
+4. Add the model to "whisper.swiftui.demo/Resources/samples" via Xcode.
+5. Select the "release" build configuration under "Run", then deploy and run to your device.
+
+[^1]: I recommend the tiny, base or small models for running on an iOS device.
diff --git a/examples/whisper.swiftui/whisper.cpp.swift/LibWhisper.swift b/examples/whisper.swiftui/whisper.cpp.swift/LibWhisper.swift
new file mode 100644 (file)
index 0000000..9adfb42
--- /dev/null
@@ -0,0 +1,70 @@
+import Foundation
+
+enum WhisperError: Error {
+    case couldNotInitializeContext
+}
+
+// Meet Whisper C++ constraint: Don't access from more than one thread at a time.
+actor WhisperContext {
+    private var context: OpaquePointer
+    
+    init(context: OpaquePointer) {
+        self.context = context
+    }
+    
+    deinit {
+        whisper_free(context)
+    }
+    
+    func fullTranscribe(samples: [Float]) {
+        // Leave 2 processors free (i.e. the high-efficiency cores).
+        let maxThreads = max(1, min(8, cpuCount() - 2))
+        print("Selecting \(maxThreads) threads")
+        var params = whisper_full_default_params(WHISPER_SAMPLING_GREEDY)
+        "en".withCString { en in
+            // Adapted from whisper.objc
+            params.print_realtime = true
+            params.print_progress = false
+            params.print_timestamps = true
+            params.print_special = false
+            params.translate = false
+            params.language = en
+            params.n_threads = Int32(maxThreads)
+            params.offset_ms = 0
+            params.no_context = true
+            params.single_segment = false
+            
+            whisper_reset_timings(context)
+            print("About to run whisper_full")
+            samples.withUnsafeBufferPointer { samples in
+                if (whisper_full(context, params, samples.baseAddress, Int32(samples.count)) != 0) {
+                    print("Failed to run the model")
+                } else {
+                    whisper_print_timings(context)
+                }
+            }
+        }
+    }
+    
+    func getTranscription() -> String {
+        var transcription = ""
+        for i in 0..<whisper_full_n_segments(context) {
+            transcription += String.init(cString: whisper_full_get_segment_text(context, i))
+        }
+        return transcription
+    }
+    
+    static func createContext(path: String) throws -> WhisperContext {
+        let context = whisper_init(path)
+        if let context {
+            return WhisperContext(context: context)
+        } else {
+            print("Couldn't load model at \(path)")
+            throw WhisperError.couldNotInitializeContext
+        }
+    }
+}
+
+fileprivate func cpuCount() -> Int {
+    ProcessInfo.processInfo.processorCount
+}
diff --git a/examples/whisper.swiftui/whisper.cpp.swift/WhisperCppDemo-Bridging-Header.h b/examples/whisper.swiftui/whisper.cpp.swift/WhisperCppDemo-Bridging-Header.h
new file mode 100644 (file)
index 0000000..f5ed59c
--- /dev/null
@@ -0,0 +1,4 @@
+//
+//  Use this file to import your target's public headers that you would like to expose to Swift.
+//
+#import "whisper.h"
diff --git a/examples/whisper.swiftui/whisper.swiftui.demo/Models/WhisperState.swift b/examples/whisper.swiftui/whisper.swiftui.demo/Models/WhisperState.swift
new file mode 100644 (file)
index 0000000..0142a6f
--- /dev/null
@@ -0,0 +1,162 @@
+import Foundation
+import SwiftUI
+import AVFoundation
+
+@MainActor
+class WhisperState: NSObject, ObservableObject, AVAudioRecorderDelegate {
+    @Published var isModelLoaded = false
+    @Published var messageLog = ""
+    @Published var canTranscribe = false
+    @Published var isRecording = false
+    
+    private var whisperContext: WhisperContext?
+    private let recorder = Recorder()
+    private var recordedFile: URL? = nil
+    private var audioPlayer: AVAudioPlayer?
+    
+    private var modelUrl: URL? {
+        Bundle.main.url(forResource: "ggml-tiny.en", withExtension: "bin", subdirectory: "models")
+    }
+    
+    private var sampleUrl: URL? {
+        Bundle.main.url(forResource: "jfk", withExtension: "wav", subdirectory: "samples")
+    }
+    
+    private enum LoadError: Error {
+        case couldNotLocateModel
+    }
+    
+    override init() {
+        super.init()
+        do {
+            try loadModel()
+            canTranscribe = true
+        } catch {
+            print(error.localizedDescription)
+            messageLog += "\(error.localizedDescription)\n"
+        }
+    }
+    
+    private func loadModel() throws {
+        messageLog += "Loading model...\n"
+        if let modelUrl {
+            whisperContext = try WhisperContext.createContext(path: modelUrl.path())
+            messageLog += "Loaded model \(modelUrl.lastPathComponent)\n"
+        } else {
+            messageLog += "Could not locate model\n"
+        }
+    }
+    
+    func transcribeSample() async {
+        if let sampleUrl {
+            await transcribeAudio(sampleUrl)
+        } else {
+            messageLog += "Could not locate sample\n"
+        }
+    }
+    
+    private func transcribeAudio(_ url: URL) async {
+        if (!canTranscribe) {
+            return
+        }
+        guard let whisperContext else {
+            return
+        }
+        
+        do {
+            canTranscribe = false
+            messageLog += "Reading wave samples...\n"
+            let data = try readAudioSamples(url)
+            messageLog += "Transcribing data...\n"
+            await whisperContext.fullTranscribe(samples: data)
+            let text = await whisperContext.getTranscription()
+            messageLog += "Done: \(text)\n"
+        } catch {
+            print(error.localizedDescription)
+            messageLog += "\(error.localizedDescription)\n"
+        }
+        
+        canTranscribe = true
+    }
+    
+    private func readAudioSamples(_ url: URL) throws -> [Float] {
+        stopPlayback()
+        try startPlayback(url)
+        return try decodeWaveFile(url)
+    }
+    
+    func toggleRecord() async {
+        if isRecording {
+            await recorder.stopRecording()
+            isRecording = false
+            if let recordedFile {
+                await transcribeAudio(recordedFile)
+            }
+        } else {
+            requestRecordPermission { granted in
+                if granted {
+                    Task {
+                        do {
+                            self.stopPlayback()
+                            let file = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
+                                .appending(path: "output.wav")
+                            try await self.recorder.startRecording(toOutputFile: file, delegate: self)
+                            self.isRecording = true
+                            self.recordedFile = file
+                        } catch {
+                            print(error.localizedDescription)
+                            self.messageLog += "\(error.localizedDescription)\n"
+                            self.isRecording = false
+                        }
+                    }
+                }
+            }
+        }
+    }
+    
+    private func requestRecordPermission(response: @escaping (Bool) -> Void) {
+#if os(macOS)
+        response(true)
+#else
+        AVAudioSession.sharedInstance().requestRecordPermission { granted in
+            response(granted)
+        }
+#endif
+    }
+    
+    private func startPlayback(_ url: URL) throws {
+        audioPlayer = try AVAudioPlayer(contentsOf: url)
+        audioPlayer?.play()
+    }
+    
+    private func stopPlayback() {
+        audioPlayer?.stop()
+        audioPlayer = nil
+    }
+    
+    // MARK: AVAudioRecorderDelegate
+    
+    nonisolated func audioRecorderEncodeErrorDidOccur(_ recorder: AVAudioRecorder, error: Error?) {
+        if let error {
+            Task {
+                await handleRecError(error)
+            }
+        }
+    }
+    
+    private func handleRecError(_ error: Error) {
+        print(error.localizedDescription)
+        messageLog += "\(error.localizedDescription)\n"
+        isRecording = false
+    }
+    
+    nonisolated func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool) {
+        Task {
+            await onDidFinishRecording()
+        }
+    }
+    
+    private func onDidFinishRecording() {
+        isRecording = false
+    }
+}
diff --git a/examples/whisper.swiftui/whisper.swiftui.demo/Supporting files/Assets.xcassets/AccentColor.colorset/Contents.json b/examples/whisper.swiftui/whisper.swiftui.demo/Supporting files/Assets.xcassets/AccentColor.colorset/Contents.json
new file mode 100644 (file)
index 0000000..eb87897
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "colors" : [
+    {
+      "idiom" : "universal"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/examples/whisper.swiftui/whisper.swiftui.demo/Supporting files/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/whisper.swiftui/whisper.swiftui.demo/Supporting files/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644 (file)
index 0000000..532cd72
--- /dev/null
@@ -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/whisper.swiftui/whisper.swiftui.demo/Supporting files/Assets.xcassets/Contents.json b/examples/whisper.swiftui/whisper.swiftui.demo/Supporting files/Assets.xcassets/Contents.json
new file mode 100644 (file)
index 0000000..73c0059
--- /dev/null
@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/examples/whisper.swiftui/whisper.swiftui.demo/Supporting files/Preview Content/Preview Assets.xcassets/Contents.json b/examples/whisper.swiftui/whisper.swiftui.demo/Supporting files/Preview Content/Preview Assets.xcassets/Contents.json
new file mode 100644 (file)
index 0000000..73c0059
--- /dev/null
@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/examples/whisper.swiftui/whisper.swiftui.demo/Supporting files/WhisperCppDemo.entitlements b/examples/whisper.swiftui/whisper.swiftui.demo/Supporting files/WhisperCppDemo.entitlements
new file mode 100644 (file)
index 0000000..4a6467e
--- /dev/null
@@ -0,0 +1,12 @@
+<?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.security.app-sandbox</key>
+       <true/>
+       <key>com.apple.security.device.audio-input</key>
+       <true/>
+       <key>com.apple.security.files.user-selected.read-only</key>
+       <true/>
+</dict>
+</plist>
diff --git a/examples/whisper.swiftui/whisper.swiftui.demo/UI/ContentView.swift b/examples/whisper.swiftui/whisper.swiftui.demo/UI/ContentView.swift
new file mode 100644 (file)
index 0000000..d8ef47e
--- /dev/null
@@ -0,0 +1,43 @@
+import SwiftUI
+import AVFoundation
+
+struct ContentView: View {
+    @StateObject var whisperState = WhisperState()
+    
+    var body: some View {
+        NavigationStack {
+            VStack {
+                HStack {
+                    Button("Transcribe", action: {
+                        Task {
+                            await whisperState.transcribeSample()
+                        }
+                    })
+                    .buttonStyle(.bordered)
+                    .disabled(!whisperState.canTranscribe)
+                    
+                    Button(whisperState.isRecording ? "Stop recording" : "Start recording", action: {
+                        Task {
+                            await whisperState.toggleRecord()
+                        }
+                    })
+                    .buttonStyle(.bordered)
+                    .disabled(!whisperState.canTranscribe)
+                }
+                
+                ScrollView {
+                    Text(verbatim: whisperState.messageLog)
+                        .frame(maxWidth: .infinity, alignment: .leading)
+                }
+            }
+            .navigationTitle("Whisper SwiftUI Demo")
+            .padding()
+        }
+    }
+}
+
+struct ContentView_Previews: PreviewProvider {
+    static var previews: some View {
+        ContentView()
+    }
+}
diff --git a/examples/whisper.swiftui/whisper.swiftui.demo/Utils/Recorder.swift b/examples/whisper.swiftui/whisper.swiftui.demo/Utils/Recorder.swift
new file mode 100644 (file)
index 0000000..0e6eefc
--- /dev/null
@@ -0,0 +1,35 @@
+import Foundation
+import AVFoundation
+
+actor Recorder {
+    private var recorder: AVAudioRecorder?
+    
+    enum RecorderError: Error {
+        case couldNotStartRecording
+    }
+    
+    func startRecording(toOutputFile url: URL, delegate: AVAudioRecorderDelegate?) throws {
+        let recordSettings: [String : Any] = [
+            AVFormatIDKey: Int(kAudioFormatLinearPCM),
+            AVSampleRateKey: 16000.0,
+            AVNumberOfChannelsKey: 1,
+            AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
+        ]
+#if !os(macOS)
+        let session = AVAudioSession.sharedInstance()
+        try session.setCategory(.playAndRecord, mode: .default)
+#endif
+        let recorder = try AVAudioRecorder(url: url, settings: recordSettings)
+        recorder.delegate = delegate
+        if recorder.record() == false {
+            print("Could not start recording")
+            throw RecorderError.couldNotStartRecording
+        }
+        self.recorder = recorder
+    }
+    
+    func stopRecording() {
+        recorder?.stop()
+        recorder = nil
+    }
+}
diff --git a/examples/whisper.swiftui/whisper.swiftui.demo/Utils/RiffWaveUtils.swift b/examples/whisper.swiftui/whisper.swiftui.demo/Utils/RiffWaveUtils.swift
new file mode 100644 (file)
index 0000000..ea86708
--- /dev/null
@@ -0,0 +1,12 @@
+import Foundation
+
+func decodeWaveFile(_ url: URL) throws -> [Float] {
+    let data = try Data(contentsOf: url)
+    let floats = stride(from: 44, to: data.count, by: 2).map {
+        return data[$0..<$0 + 2].withUnsafeBytes {
+            let short = Int16(littleEndian: $0.load(as: Int16.self))
+            return max(-1.0, min(Float(short) / 32767.0, 1.0))
+        }
+    }
+    return floats
+}
diff --git a/examples/whisper.swiftui/whisper.swiftui.demo/WhisperCppDemoApp.swift b/examples/whisper.swiftui/whisper.swiftui.demo/WhisperCppDemoApp.swift
new file mode 100644 (file)
index 0000000..d846407
--- /dev/null
@@ -0,0 +1,10 @@
+import SwiftUI
+
+@main
+struct WhisperCppDemoApp: App {
+    var body: some Scene {
+        WindowGroup {
+            ContentView()
+        }
+    }
+}
diff --git a/examples/whisper.swiftui/whisper.swiftui.xcodeproj/.gitignore b/examples/whisper.swiftui/whisper.swiftui.xcodeproj/.gitignore
new file mode 100644 (file)
index 0000000..c545112
--- /dev/null
@@ -0,0 +1 @@
+xcuserdata/
diff --git a/examples/whisper.swiftui/whisper.swiftui.xcodeproj/project.pbxproj b/examples/whisper.swiftui/whisper.swiftui.xcodeproj/project.pbxproj
new file mode 100644 (file)
index 0000000..9cc09c0
--- /dev/null
@@ -0,0 +1,467 @@
+// !$*UTF8*$!
+{
+       archiveVersion = 1;
+       classes = {
+       };
+       objectVersion = 56;
+       objects = {
+
+/* Begin PBXBuildFile section */
+               0A8E49002954B3F100704C1B /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = 0A8E48FF2954B3F100704C1B /* README.md */; };
+               0AA751482953AC2E001EE061 /* samples in Resources */ = {isa = PBXBuildFile; fileRef = 0AA751462953AC2E001EE061 /* samples */; };
+               0AA751492953AC2E001EE061 /* models in Resources */ = {isa = PBXBuildFile; fileRef = 0AA751472953AC2E001EE061 /* models */; };
+               0AA7514C2953B569001EE061 /* RiffWaveUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AA7514B2953B569001EE061 /* RiffWaveUtils.swift */; };
+               0AA7514E2953D958001EE061 /* Recorder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AA7514D2953D958001EE061 /* Recorder.swift */; };
+               0AAC5D9B29539CCF003032C3 /* WhisperCppDemoApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AAC5D9A29539CCF003032C3 /* WhisperCppDemoApp.swift */; };
+               0AAC5D9D29539CCF003032C3 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AAC5D9C29539CCF003032C3 /* ContentView.swift */; };
+               0AAC5D9F29539CD0003032C3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0AAC5D9E29539CD0003032C3 /* Assets.xcassets */; };
+               0AAC5DA329539CD0003032C3 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0AAC5DA229539CD0003032C3 /* Preview Assets.xcassets */; };
+               0AAC5DCB29539EB1003032C3 /* whisper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0AAC5DC729539EB0003032C3 /* whisper.cpp */; settings = {COMPILER_FLAGS = "-Wno-shorten-64-to-32"; }; };
+               0AAC5DCC29539EB1003032C3 /* ggml.c in Sources */ = {isa = PBXBuildFile; fileRef = 0AAC5DC929539EB0003032C3 /* ggml.c */; settings = {COMPILER_FLAGS = "-DGGML_USE_ACCELERATE -Wno-shorten-64-to-32"; }; };
+               0AAC5DCE2953A05C003032C3 /* WhisperState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AAC5DCD2953A05C003032C3 /* WhisperState.swift */; };
+               0AAC5DD12953A394003032C3 /* LibWhisper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AAC5DD02953A394003032C3 /* LibWhisper.swift */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+               0A8E48FF2954B3F100704C1B /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
+               0AA751462953AC2E001EE061 /* samples */ = {isa = PBXFileReference; lastKnownFileType = folder; path = samples; sourceTree = "<group>"; };
+               0AA751472953AC2E001EE061 /* models */ = {isa = PBXFileReference; lastKnownFileType = folder; path = models; sourceTree = "<group>"; };
+               0AA7514B2953B569001EE061 /* RiffWaveUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RiffWaveUtils.swift; sourceTree = "<group>"; };
+               0AA7514D2953D958001EE061 /* Recorder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Recorder.swift; sourceTree = "<group>"; };
+               0AAC5D9729539CCF003032C3 /* whisper.swiftui.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = whisper.swiftui.app; sourceTree = BUILT_PRODUCTS_DIR; };
+               0AAC5D9A29539CCF003032C3 /* WhisperCppDemoApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WhisperCppDemoApp.swift; sourceTree = "<group>"; };
+               0AAC5D9C29539CCF003032C3 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
+               0AAC5D9E29539CD0003032C3 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
+               0AAC5DA029539CD0003032C3 /* WhisperCppDemo.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = WhisperCppDemo.entitlements; sourceTree = "<group>"; };
+               0AAC5DA229539CD0003032C3 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
+               0AAC5DC629539EAF003032C3 /* WhisperCppDemo-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "WhisperCppDemo-Bridging-Header.h"; sourceTree = "<group>"; };
+               0AAC5DC729539EB0003032C3 /* whisper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = whisper.cpp; path = ../../../whisper.cpp; sourceTree = "<group>"; };
+               0AAC5DC829539EB0003032C3 /* whisper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = whisper.h; path = ../../../whisper.h; sourceTree = "<group>"; };
+               0AAC5DC929539EB0003032C3 /* ggml.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ggml.c; path = ../../../ggml.c; sourceTree = "<group>"; };
+               0AAC5DCA29539EB0003032C3 /* ggml.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ggml.h; path = ../../../ggml.h; sourceTree = "<group>"; };
+               0AAC5DCD2953A05C003032C3 /* WhisperState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WhisperState.swift; sourceTree = "<group>"; };
+               0AAC5DD02953A394003032C3 /* LibWhisper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LibWhisper.swift; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+               0AAC5D9429539CCF003032C3 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+               0AA7513F2953AB32001EE061 /* Models */ = {
+                       isa = PBXGroup;
+                       children = (
+                               0AAC5DCD2953A05C003032C3 /* WhisperState.swift */,
+                       );
+                       path = Models;
+                       sourceTree = "<group>";
+               };
+               0AA751402953ABA6001EE061 /* Resources */ = {
+                       isa = PBXGroup;
+                       children = (
+                               0AA751472953AC2E001EE061 /* models */,
+                               0AA751462953AC2E001EE061 /* samples */,
+                       );
+                       path = Resources;
+                       sourceTree = "<group>";
+               };
+               0AA7514A2953B561001EE061 /* Utils */ = {
+                       isa = PBXGroup;
+                       children = (
+                               0AA7514B2953B569001EE061 /* RiffWaveUtils.swift */,
+                               0AA7514D2953D958001EE061 /* Recorder.swift */,
+                       );
+                       path = Utils;
+                       sourceTree = "<group>";
+               };
+               0AAC5D8E29539CCF003032C3 = {
+                       isa = PBXGroup;
+                       children = (
+                               0A8E48FF2954B3F100704C1B /* README.md */,
+                               0AAC5DC529539E89003032C3 /* whisper.cpp */,
+                               0AAC5DCF2953A36C003032C3 /* whisper.cpp.swift */,
+                               0AAC5D9929539CCF003032C3 /* whisper.swiftui.demo */,
+                               0AAC5D9829539CCF003032C3 /* Products */,
+                       );
+                       sourceTree = "<group>";
+               };
+               0AAC5D9829539CCF003032C3 /* Products */ = {
+                       isa = PBXGroup;
+                       children = (
+                               0AAC5D9729539CCF003032C3 /* whisper.swiftui.app */,
+                       );
+                       name = Products;
+                       sourceTree = "<group>";
+               };
+               0AAC5D9929539CCF003032C3 /* whisper.swiftui.demo */ = {
+                       isa = PBXGroup;
+                       children = (
+                               0AA7514A2953B561001EE061 /* Utils */,
+                               0AA751402953ABA6001EE061 /* Resources */,
+                               0AA7513F2953AB32001EE061 /* Models */,
+                               0AAC5DD32953A9ED003032C3 /* Supporting files */,
+                               0AAC5DD22953A9E3003032C3 /* UI */,
+                               0AAC5D9A29539CCF003032C3 /* WhisperCppDemoApp.swift */,
+                       );
+                       path = whisper.swiftui.demo;
+                       sourceTree = "<group>";
+               };
+               0AAC5DA129539CD0003032C3 /* Preview Content */ = {
+                       isa = PBXGroup;
+                       children = (
+                               0AAC5DA229539CD0003032C3 /* Preview Assets.xcassets */,
+                       );
+                       name = "Preview Content";
+                       path = "../Preview Content";
+                       sourceTree = "<group>";
+               };
+               0AAC5DC529539E89003032C3 /* whisper.cpp */ = {
+                       isa = PBXGroup;
+                       children = (
+                               0AAC5DC929539EB0003032C3 /* ggml.c */,
+                               0AAC5DCA29539EB0003032C3 /* ggml.h */,
+                               0AAC5DC729539EB0003032C3 /* whisper.cpp */,
+                               0AAC5DC829539EB0003032C3 /* whisper.h */,
+                       );
+                       path = whisper.cpp;
+                       sourceTree = "<group>";
+               };
+               0AAC5DCF2953A36C003032C3 /* whisper.cpp.swift */ = {
+                       isa = PBXGroup;
+                       children = (
+                               0AAC5DC629539EAF003032C3 /* WhisperCppDemo-Bridging-Header.h */,
+                               0AAC5DD02953A394003032C3 /* LibWhisper.swift */,
+                       );
+                       path = whisper.cpp.swift;
+                       sourceTree = "<group>";
+               };
+               0AAC5DD22953A9E3003032C3 /* UI */ = {
+                       isa = PBXGroup;
+                       children = (
+                               0AAC5D9C29539CCF003032C3 /* ContentView.swift */,
+                       );
+                       path = UI;
+                       sourceTree = "<group>";
+               };
+               0AAC5DD32953A9ED003032C3 /* Supporting files */ = {
+                       isa = PBXGroup;
+                       children = (
+                               0AAC5D9E29539CD0003032C3 /* Assets.xcassets */,
+                               0AAC5DA029539CD0003032C3 /* WhisperCppDemo.entitlements */,
+                               0AAC5DA129539CD0003032C3 /* Preview Content */,
+                       );
+                       path = "Supporting files";
+                       sourceTree = "<group>";
+               };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+               0AAC5D9629539CCF003032C3 /* whisper.swiftui */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = 0AAC5DBC29539CD0003032C3 /* Build configuration list for PBXNativeTarget "whisper.swiftui" */;
+                       buildPhases = (
+                               0AAC5D9329539CCF003032C3 /* Sources */,
+                               0AAC5D9429539CCF003032C3 /* Frameworks */,
+                               0AAC5D9529539CCF003032C3 /* Resources */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                       );
+                       name = whisper.swiftui;
+                       productName = WhisperCppDemo;
+                       productReference = 0AAC5D9729539CCF003032C3 /* whisper.swiftui.app */;
+                       productType = "com.apple.product-type.application";
+               };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+               0AAC5D8F29539CCF003032C3 /* Project object */ = {
+                       isa = PBXProject;
+                       attributes = {
+                               BuildIndependentTargetsInParallel = 1;
+                               LastSwiftUpdateCheck = 1410;
+                               LastUpgradeCheck = 1410;
+                               TargetAttributes = {
+                                       0AAC5D9629539CCF003032C3 = {
+                                               CreatedOnToolsVersion = 14.1;
+                                               LastSwiftMigration = 1410;
+                                       };
+                               };
+                       };
+                       buildConfigurationList = 0AAC5D9229539CCF003032C3 /* Build configuration list for PBXProject "whisper.swiftui" */;
+                       compatibilityVersion = "Xcode 14.0";
+                       developmentRegion = en;
+                       hasScannedForEncodings = 0;
+                       knownRegions = (
+                               en,
+                               Base,
+                       );
+                       mainGroup = 0AAC5D8E29539CCF003032C3;
+                       productRefGroup = 0AAC5D9829539CCF003032C3 /* Products */;
+                       projectDirPath = "";
+                       projectRoot = "";
+                       targets = (
+                               0AAC5D9629539CCF003032C3 /* whisper.swiftui */,
+                       );
+               };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+               0AAC5D9529539CCF003032C3 /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               0AA751482953AC2E001EE061 /* samples in Resources */,
+                               0AAC5DA329539CD0003032C3 /* Preview Assets.xcassets in Resources */,
+                               0A8E49002954B3F100704C1B /* README.md in Resources */,
+                               0AA751492953AC2E001EE061 /* models in Resources */,
+                               0AAC5D9F29539CD0003032C3 /* Assets.xcassets in Resources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+               0AAC5D9329539CCF003032C3 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               0AAC5D9D29539CCF003032C3 /* ContentView.swift in Sources */,
+                               0AAC5D9B29539CCF003032C3 /* WhisperCppDemoApp.swift in Sources */,
+                               0AAC5DCC29539EB1003032C3 /* ggml.c in Sources */,
+                               0AAC5DCE2953A05C003032C3 /* WhisperState.swift in Sources */,
+                               0AAC5DD12953A394003032C3 /* LibWhisper.swift in Sources */,
+                               0AA7514C2953B569001EE061 /* RiffWaveUtils.swift in Sources */,
+                               0AAC5DCB29539EB1003032C3 /* whisper.cpp in Sources */,
+                               0AA7514E2953D958001EE061 /* Recorder.swift in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+               0AAC5DBA29539CD0003032C3 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               ALWAYS_SEARCH_USER_PATHS = NO;
+                               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;
+                               GCC_C_LANGUAGE_STANDARD = gnu11;
+                               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;
+                               INFOPLIST_KEY_NSMicrophoneUsageDescription = "Needed to transcribe audio";
+                               MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+                               MTL_FAST_MATH = YES;
+                               ONLY_ACTIVE_ARCH = YES;
+                               SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+                               SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+                       };
+                       name = Debug;
+               };
+               0AAC5DBB29539CD0003032C3 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               ALWAYS_SEARCH_USER_PATHS = NO;
+                               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;
+                               GCC_C_LANGUAGE_STANDARD = gnu11;
+                               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;
+                               INFOPLIST_KEY_NSMicrophoneUsageDescription = "Needed to transcribe audio";
+                               MTL_ENABLE_DEBUG_INFO = NO;
+                               MTL_FAST_MATH = YES;
+                               SWIFT_COMPILATION_MODE = wholemodule;
+                               SWIFT_OPTIMIZATION_LEVEL = "-O";
+                       };
+                       name = Release;
+               };
+               0AAC5DBD29539CD0003032C3 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+                               ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+                               CLANG_ENABLE_MODULES = YES;
+                               CODE_SIGN_ENTITLEMENTS = "whisper.swiftui.demo/Supporting files/WhisperCppDemo.entitlements";
+                               CODE_SIGN_STYLE = Automatic;
+                               CURRENT_PROJECT_VERSION = 1;
+                               DEVELOPMENT_ASSET_PATHS = "\"whisper.swiftui.demo/Supporting files/Preview Content\"";
+                               DEVELOPMENT_TEAM = 3TZ9BM962G;
+                               ENABLE_HARDENED_RUNTIME = YES;
+                               ENABLE_PREVIEWS = YES;
+                               GENERATE_INFOPLIST_FILE = YES;
+                               "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 = 16.1;
+                               LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks";
+                               "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
+                               MACOSX_DEPLOYMENT_TARGET = 13.0;
+                               MARKETING_VERSION = 1.0;
+                               PRODUCT_BUNDLE_IDENTIFIER = com.whispercppdemo.WhisperCppDemo;
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                               SDKROOT = auto;
+                               SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx";
+                               SWIFT_EMIT_LOC_STRINGS = YES;
+                               SWIFT_OBJC_BRIDGING_HEADER = "whisper.cpp.swift/WhisperCppDemo-Bridging-Header.h";
+                               SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+                               SWIFT_VERSION = 5.0;
+                               TARGETED_DEVICE_FAMILY = "1,2";
+                       };
+                       name = Debug;
+               };
+               0AAC5DBE29539CD0003032C3 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+                               ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+                               CLANG_ENABLE_MODULES = YES;
+                               CODE_SIGN_ENTITLEMENTS = "whisper.swiftui.demo/Supporting files/WhisperCppDemo.entitlements";
+                               CODE_SIGN_STYLE = Automatic;
+                               CURRENT_PROJECT_VERSION = 1;
+                               DEVELOPMENT_ASSET_PATHS = "\"whisper.swiftui.demo/Supporting files/Preview Content\"";
+                               DEVELOPMENT_TEAM = 3TZ9BM962G;
+                               ENABLE_HARDENED_RUNTIME = YES;
+                               ENABLE_PREVIEWS = YES;
+                               GENERATE_INFOPLIST_FILE = YES;
+                               "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 = 16.1;
+                               LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks";
+                               "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
+                               LLVM_LTO = YES;
+                               MACOSX_DEPLOYMENT_TARGET = 13.0;
+                               MARKETING_VERSION = 1.0;
+                               PRODUCT_BUNDLE_IDENTIFIER = com.whispercppdemo.WhisperCppDemo;
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                               SDKROOT = auto;
+                               SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx";
+                               SWIFT_EMIT_LOC_STRINGS = YES;
+                               SWIFT_OBJC_BRIDGING_HEADER = "whisper.cpp.swift/WhisperCppDemo-Bridging-Header.h";
+                               SWIFT_VERSION = 5.0;
+                               TARGETED_DEVICE_FAMILY = "1,2";
+                       };
+                       name = Release;
+               };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+               0AAC5D9229539CCF003032C3 /* Build configuration list for PBXProject "whisper.swiftui" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               0AAC5DBA29539CD0003032C3 /* Debug */,
+                               0AAC5DBB29539CD0003032C3 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+               0AAC5DBC29539CD0003032C3 /* Build configuration list for PBXNativeTarget "whisper.swiftui" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               0AAC5DBD29539CD0003032C3 /* Debug */,
+                               0AAC5DBE29539CD0003032C3 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+/* End XCConfigurationList section */
+       };
+       rootObject = 0AAC5D8F29539CCF003032C3 /* Project object */;
+}
diff --git a/examples/whisper.swiftui/whisper.swiftui.xcodeproj/project.xcworkspace/.gitignore b/examples/whisper.swiftui/whisper.swiftui.xcodeproj/project.xcworkspace/.gitignore
new file mode 100644 (file)
index 0000000..ad73994
--- /dev/null
@@ -0,0 +1 @@
+contents.xcworkspacedata
diff --git a/examples/whisper.swiftui/whisper.swiftui.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/examples/whisper.swiftui/whisper.swiftui.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644 (file)
index 0000000..18d9810
--- /dev/null
@@ -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/whisper.swiftui/whisper.swiftui.xcodeproj/xcshareddata/xcschemes/WhisperCppDemo.xcscheme b/examples/whisper.swiftui/whisper.swiftui.xcodeproj/xcshareddata/xcschemes/WhisperCppDemo.xcscheme
new file mode 100644 (file)
index 0000000..1c6b63b
--- /dev/null
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1410"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "0AAC5D9629539CCF003032C3"
+               BuildableName = "whisper.swiftui.app"
+               BlueprintName = "whisper.swiftui"
+               ReferencedContainer = "container:whisper.swiftui.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+      <Testables>
+         <TestableReference
+            skipped = "NO"
+            parallelizable = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "0AAC5DA729539CD0003032C3"
+               BuildableName = "whisper.swiftuiTests.xctest"
+               BlueprintName = "whisper.swiftuiTests"
+               ReferencedContainer = "container:whisper.swiftui.xcodeproj">
+            </BuildableReference>
+         </TestableReference>
+         <TestableReference
+            skipped = "NO"
+            parallelizable = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "0AAC5DB129539CD0003032C3"
+               BuildableName = "whisper.swiftuiUITests.xctest"
+               BlueprintName = "whisper.swiftuiUITests"
+               ReferencedContainer = "container:whisper.swiftui.xcodeproj">
+            </BuildableReference>
+         </TestableReference>
+      </Testables>
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Release"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "0AAC5D9629539CCF003032C3"
+            BuildableName = "whisper.swiftui.app"
+            BlueprintName = "whisper.swiftui"
+            ReferencedContainer = "container:whisper.swiftui.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "0AAC5D9629539CCF003032C3"
+            BuildableName = "whisper.swiftui.app"
+            BlueprintName = "whisper.swiftui"
+            ReferencedContainer = "container:whisper.swiftui.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>