Seed Swift package for demucs-rs SDK
Package.swift (binary target placeholder + Demucs wrapper target), README, and UniFFI-generated demucs.swift. The release workflow in ondeinference/demucs-rs rewrites the binary target URL/checksum and regenerates demucs.swift on every swift-X.Y.Z tag. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PMgTdQhdPV6h4XXpNKRKn7
Claude committed
Jul 9, 2026 at 10:19 UTC
6f1f785a9350c0892ee85a624262a08d4e2bf654
4 files changed
+2292
.gitignore
new
+2
@@ -0,0 +1,2 @@
1
+.DS_Store
2
+.build/
Package.swift
new
+41
@@ -0,0 +1,41 @@
1
+// swift-tools-version:5.9
2
+import PackageDescription
3
+
4
+// These two constants are rewritten automatically by the demucs-rs
5
+// "Release SDK Swift" workflow on every release. Do not reformat them —
6
+// the rewrite regex depends on this exact layout.
7
+//
8
+// For local development against a locally built framework, comment out the
9
+// url/checksum binaryTarget below and use the path form instead:
10
+// .binaryTarget(name: "DemucsFramework", path: "../demucs-rs/dist/swift/DemucsFramework.xcframework"),
11
+// (run .github/scripts/build-swift-xcframework.sh in demucs-rs first).
12
+// Never commit the path form — CI overwrites this file on every release.
13
+let releaseFrameworkURL =
14
+ "https://github.com/ondeinference/demucs-rs/releases/download/swift-0.1.0/DemucsFramework.xcframework.zip"
15
+let releaseFrameworkChecksum =
16
+ "0000000000000000000000000000000000000000000000000000000000000000"
17
+
18
+let package = Package(
19
+ name: "Demucs",
20
+ platforms: [
21
+ .iOS(.v16),
22
+ .macOS(.v14),
23
+ .tvOS(.v16),
24
+ .visionOS(.v1),
25
+ ],
26
+ products: [
27
+ .library(name: "Demucs", targets: ["Demucs"])
28
+ ],
29
+ targets: [
30
+ .binaryTarget(
31
+ name: "DemucsFramework",
32
+ url: releaseFrameworkURL,
33
+ checksum: releaseFrameworkChecksum
34
+ ),
35
+ .target(
36
+ name: "Demucs",
37
+ dependencies: ["DemucsFramework"],
38
+ path: "Sources/Demucs"
39
+ ),
40
+ ]
41
+)
README.md
new
+80
@@ -0,0 +1,80 @@
1
+# demucs-swift
2
+
3
+Swift SDK for [demucs-rs](https://github.com/ondeinference/demucs-rs) — on-device
4
+music source separation (HTDemucs v4) for iOS, macOS, tvOS, and visionOS,
5
+GPU-accelerated via Metal.
6
+
7
+> **This repository is machine-published.** Every release of
8
+> [demucs-rs](https://github.com/ondeinference/demucs-rs) rewrites
9
+> `Package.swift` and `Sources/Demucs/demucs.swift` via CI. Do not edit them
10
+> by hand — changes belong in the `demucs-ffi` crate in demucs-rs.
11
+
12
+## Installation
13
+
14
+```swift
15
+dependencies: [
16
+ .package(url: "https://github.com/ondeinference/demucs-swift", from: "0.1.0")
17
+]
18
+```
19
+
20
+## Usage
21
+
22
+```swift
23
+import Demucs
24
+
25
+// 1. Sandboxed platforms (iOS/tvOS/visionOS): point the weight cache inside
26
+// the app container once at launch.
27
+let caches = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)[0]
28
+configureCacheDir(path: caches.appendingPathComponent("demucs").path)
29
+
30
+// 2. Download weights (84–333 MB, from HuggingFace, cached on disk).
31
+final class DownloadHandler: DownloadProgressListener {
32
+ func onProgress(progress: DownloadProgress) -> Bool {
33
+ print("download \(Int(progress.fraction * 100))%")
34
+ return true // return false to cancel
35
+ }
36
+}
37
+try await downloadModel(model: .fourStem, listener: DownloadHandler())
38
+
39
+// 3. Load the model and pre-compile GPU shaders.
40
+let engine = DemucsEngine()
41
+let seconds = try await engine.loadModel(model: .fourStem)
42
+try await engine.warmup()
43
+
44
+// 4. Separate. Input is per-channel PCM at any sample rate (use AVFoundation
45
+// to decode files); output stems are stereo PCM at 44100 Hz.
46
+final class ProgressHandler: SeparationProgressListener {
47
+ func onProgress(progress: SeparationProgress) -> Bool {
48
+ print("separating \(Int(progress.fraction * 100))%")
49
+ return true // return false to cancel
50
+ }
51
+}
52
+let stems = try await separateWithProgress(
53
+ engine: engine,
54
+ left: leftSamples, right: rightSamples,
55
+ sampleRate: 44100,
56
+ listener: ProgressHandler()
57
+)
58
+for stem in stems {
59
+ print(stem.kind, stem.left.count)
60
+}
61
+
62
+// Or without progress reporting:
63
+let stems2 = try await engine.separate(left: leftSamples, right: rightSamples, sampleRate: 44100)
64
+```
65
+
66
+## Models
67
+
68
+| Model | Case | Stems | Size |
69
+|-------|------|-------|------|
70
+| htdemucs | `.fourStem` | drums, bass, other, vocals | ~84 MB |
71
+| htdemucs_6s | `.sixStem` | + guitar, piano | ~84 MB |
72
+| htdemucs_ft | `.fineTuned(stems:)` | up to 4, best quality | ~333 MB |
73
+
74
+Weights download from HuggingFace on demand and are cached locally
75
+(`allModels()`, `isModelCached(model:)`, `deleteCachedModel(model:)` manage
76
+the cache).
77
+
78
+## License
79
+
80
+Apache-2.0, same as demucs-rs.
Sources/Demucs/demucs.swift
new
+2169
@@ -0,0 +1,2169 @@
1
+// This file was autogenerated by some hot garbage in the `uniffi` crate.
2
+// Trust me, you don't want to mess with it!
3
+
4
+// swiftlint:disable all
5
+import Foundation
6
+
7
+// Depending on the consumer's build setup, the low-level FFI code
8
+// might be in a separate module, or it might be compiled inline into
9
+// this module. This is a bit of light hackery to work with both.
10
+#if canImport(demucsFFI)
11
+import demucsFFI
12
+#endif
13
+
14
+fileprivate extension RustBuffer {
15
+ // Allocate a new buffer, copying the contents of a `UInt8` array.
16
+ init(bytes: [UInt8]) {
17
+ let rbuf = bytes.withUnsafeBufferPointer { ptr in
18
+ RustBuffer.from(ptr)
19
+ }
20
+ self.init(capacity: rbuf.capacity, len: rbuf.len, data: rbuf.data)
21
+ }
22
+
23
+ static func empty() -> RustBuffer {
24
+ RustBuffer(capacity: 0, len:0, data: nil)
25
+ }
26
+
27
+ static func from(_ ptr: UnsafeBufferPointer<UInt8>) -> RustBuffer {
28
+ try! rustCall { ffi_demucs_rustbuffer_from_bytes(ForeignBytes(bufferPointer: ptr), $0) }
29
+ }
30
+
31
+ // Frees the buffer in place.
32
+ // The buffer must not be used after this is called.
33
+ func deallocate() {
34
+ try! rustCall { ffi_demucs_rustbuffer_free(self, $0) }
35
+ }
36
+}
37
+
38
+fileprivate extension ForeignBytes {
39
+ init(bufferPointer: UnsafeBufferPointer<UInt8>) {
40
+ self.init(len: Int32(bufferPointer.count), data: bufferPointer.baseAddress)
41
+ }
42
+}
43
+
44
+// For every type used in the interface, we provide helper methods for conveniently
45
+// lifting and lowering that type from C-compatible data, and for reading and writing
46
+// values of that type in a buffer.
47
+
48
+// Helper classes/extensions that don't change.
49
+// Someday, this will be in a library of its own.
50
+
51
+fileprivate extension Data {
52
+ init(rustBuffer: RustBuffer) {
53
+ self.init(
54
+ bytesNoCopy: rustBuffer.data!,
55
+ count: Int(rustBuffer.len),
56
+ deallocator: .none
57
+ )
58
+ }
59
+}
60
+
61
+// Define reader functionality. Normally this would be defined in a class or
62
+// struct, but we use standalone functions instead in order to make external
63
+// types work.
64
+//
65
+// With external types, one swift source file needs to be able to call the read
66
+// method on another source file's FfiConverter, but then what visibility
67
+// should Reader have?
68
+// - If Reader is fileprivate, then this means the read() must also
69
+// be fileprivate, which doesn't work with external types.
70
+// - If Reader is internal/public, we'll get compile errors since both source
71
+// files will try define the same type.
72
+//
73
+// Instead, the read() method and these helper functions input a tuple of data
74
+
75
+fileprivate func createReader(data: Data) -> (data: Data, offset: Data.Index) {
76
+ (data: data, offset: 0)
77
+}
78
+
79
+// Reads an integer at the current offset, in big-endian order, and advances
80
+// the offset on success. Throws if reading the integer would move the
81
+// offset past the end of the buffer.
82
+fileprivate func readInt<T: FixedWidthInteger>(_ reader: inout (data: Data, offset: Data.Index)) throws -> T {
83
+ let range = reader.offset..<reader.offset + MemoryLayout<T>.size
84
+ guard reader.data.count >= range.upperBound else {
85
+ throw UniffiInternalError.bufferOverflow
86
+ }
87
+ if T.self == UInt8.self {
88
+ let value = reader.data[reader.offset]
89
+ reader.offset += 1
90
+ return value as! T
91
+ }
92
+ var value: T = 0
93
+ let _ = withUnsafeMutableBytes(of: &value, { reader.data.copyBytes(to: $0, from: range)})
94
+ reader.offset = range.upperBound
95
+ return value.bigEndian
96
+}
97
+
98
+// Reads an arbitrary number of bytes, to be used to read
99
+// raw bytes, this is useful when lifting strings
100
+fileprivate func readBytes(_ reader: inout (data: Data, offset: Data.Index), count: Int) throws -> Array<UInt8> {
101
+ let range = reader.offset..<(reader.offset+count)
102
+ guard reader.data.count >= range.upperBound else {
103
+ throw UniffiInternalError.bufferOverflow
104
+ }
105
+ var value = [UInt8](repeating: 0, count: count)
106
+ value.withUnsafeMutableBufferPointer({ buffer in
107
+ reader.data.copyBytes(to: buffer, from: range)
108
+ })
109
+ reader.offset = range.upperBound
110
+ return value
111
+}
112
+
113
+// Reads a float at the current offset.
114
+fileprivate func readFloat(_ reader: inout (data: Data, offset: Data.Index)) throws -> Float {
115
+ return Float(bitPattern: try readInt(&reader))
116
+}
117
+
118
+// Reads a float at the current offset.
119
+fileprivate func readDouble(_ reader: inout (data: Data, offset: Data.Index)) throws -> Double {
120
+ return Double(bitPattern: try readInt(&reader))
121
+}
122
+
123
+// Indicates if the offset has reached the end of the buffer.
124
+fileprivate func hasRemaining(_ reader: (data: Data, offset: Data.Index)) -> Bool {
125
+ return reader.offset < reader.data.count
126
+}
127
+
128
+// Define writer functionality. Normally this would be defined in a class or
129
+// struct, but we use standalone functions instead in order to make external
130
+// types work. See the above discussion on Readers for details.
131
+
132
+fileprivate func createWriter() -> [UInt8] {
133
+ return []
134
+}
135
+
136
+fileprivate func writeBytes<S>(_ writer: inout [UInt8], _ byteArr: S) where S: Sequence, S.Element == UInt8 {
137
+ writer.append(contentsOf: byteArr)
138
+}
139
+
140
+// Writes an integer in big-endian order.
141
+//
142
+// Warning: make sure what you are trying to write
143
+// is in the correct type!
144
+fileprivate func writeInt<T: FixedWidthInteger>(_ writer: inout [UInt8], _ value: T) {
145
+ var value = value.bigEndian
146
+ withUnsafeBytes(of: &value) { writer.append(contentsOf: $0) }
147
+}
148
+
149
+fileprivate func writeFloat(_ writer: inout [UInt8], _ value: Float) {
150
+ writeInt(&writer, value.bitPattern)
151
+}
152
+
153
+fileprivate func writeDouble(_ writer: inout [UInt8], _ value: Double) {
154
+ writeInt(&writer, value.bitPattern)
155
+}
156
+
157
+// Protocol for types that transfer other types across the FFI. This is
158
+// analogous to the Rust trait of the same name.
159
+fileprivate protocol FfiConverter {
160
+ associatedtype FfiType
161
+ associatedtype SwiftType
162
+
163
+ static func lift(_ value: FfiType) throws -> SwiftType
164
+ static func lower(_ value: SwiftType) -> FfiType
165
+ static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SwiftType
166
+ static func write(_ value: SwiftType, into buf: inout [UInt8])
167
+}
168
+
169
+// Types conforming to `Primitive` pass themselves directly over the FFI.
170
+fileprivate protocol FfiConverterPrimitive: FfiConverter where FfiType == SwiftType { }
171
+
172
+extension FfiConverterPrimitive {
173
+#if swift(>=5.8)
174
+ @_documentation(visibility: private)
175
+#endif
176
+ public static func lift(_ value: FfiType) throws -> SwiftType {
177
+ return value
178
+ }
179
+
180
+#if swift(>=5.8)
181
+ @_documentation(visibility: private)
182
+#endif
183
+ public static func lower(_ value: SwiftType) -> FfiType {
184
+ return value
185
+ }
186
+}
187
+
188
+// Types conforming to `FfiConverterRustBuffer` lift and lower into a `RustBuffer`.
189
+// Used for complex types where it's hard to write a custom lift/lower.
190
+fileprivate protocol FfiConverterRustBuffer: FfiConverter where FfiType == RustBuffer {}
191
+
192
+extension FfiConverterRustBuffer {
193
+#if swift(>=5.8)
194
+ @_documentation(visibility: private)
195
+#endif
196
+ public static func lift(_ buf: RustBuffer) throws -> SwiftType {
197
+ var reader = createReader(data: Data(rustBuffer: buf))
198
+ let value = try read(from: &reader)
199
+ if hasRemaining(reader) {
200
+ throw UniffiInternalError.incompleteData
201
+ }
202
+ buf.deallocate()
203
+ return value
204
+ }
205
+
206
+#if swift(>=5.8)
207
+ @_documentation(visibility: private)
208
+#endif
209
+ public static func lower(_ value: SwiftType) -> RustBuffer {
210
+ var writer = createWriter()
211
+ write(value, into: &writer)
212
+ return RustBuffer(bytes: writer)
213
+ }
214
+}
215
+// An error type for FFI errors. These errors occur at the UniFFI level, not
216
+// the library level.
217
+fileprivate enum UniffiInternalError: LocalizedError {
218
+ case bufferOverflow
219
+ case incompleteData
220
+ case unexpectedOptionalTag
221
+ case unexpectedEnumCase
222
+ case unexpectedNullPointer
223
+ case unexpectedRustCallStatusCode
224
+ case unexpectedRustCallError
225
+ case unexpectedStaleHandle
226
+ case rustPanic(_ message: String)
227
+
228
+ public var errorDescription: String? {
229
+ switch self {
230
+ case .bufferOverflow: return "Reading the requested value would read past the end of the buffer"
231
+ case .incompleteData: return "The buffer still has data after lifting its containing value"
232
+ case .unexpectedOptionalTag: return "Unexpected optional tag; should be 0 or 1"
233
+ case .unexpectedEnumCase: return "Raw enum value doesn't match any cases"
234
+ case .unexpectedNullPointer: return "Raw pointer value was null"
235
+ case .unexpectedRustCallStatusCode: return "Unexpected RustCallStatus code"
236
+ case .unexpectedRustCallError: return "CALL_ERROR but no errorClass specified"
237
+ case .unexpectedStaleHandle: return "The object in the handle map has been dropped already"
238
+ case let .rustPanic(message): return message
239
+ }
240
+ }
241
+}
242
+
243
+fileprivate extension NSLock {
244
+ func withLock<T>(f: () throws -> T) rethrows -> T {
245
+ self.lock()
246
+ defer { self.unlock() }
247
+ return try f()
248
+ }
249
+}
250
+
251
+fileprivate let CALL_SUCCESS: Int8 = 0
252
+fileprivate let CALL_ERROR: Int8 = 1
253
+fileprivate let CALL_UNEXPECTED_ERROR: Int8 = 2
254
+fileprivate let CALL_CANCELLED: Int8 = 3
255
+
256
+fileprivate extension RustCallStatus {
257
+ init() {
258
+ self.init(
259
+ code: CALL_SUCCESS,
260
+ errorBuf: RustBuffer.init(
261
+ capacity: 0,
262
+ len: 0,
263
+ data: nil
264
+ )
265
+ )
266
+ }
267
+}
268
+
269
+private func rustCall<T>(_ callback: (UnsafeMutablePointer<RustCallStatus>) -> T) throws -> T {
270
+ let neverThrow: ((RustBuffer) throws -> Never)? = nil
271
+ return try makeRustCall(callback, errorHandler: neverThrow)
272
+}
273
+
274
+private func rustCallWithError<T, E: Swift.Error>(
275
+ _ errorHandler: @escaping (RustBuffer) throws -> E,
276
+ _ callback: (UnsafeMutablePointer<RustCallStatus>) -> T) throws -> T {
277
+ try makeRustCall(callback, errorHandler: errorHandler)
278
+}
279
+
280
+private func makeRustCall<T, E: Swift.Error>(
281
+ _ callback: (UnsafeMutablePointer<RustCallStatus>) -> T,
282
+ errorHandler: ((RustBuffer) throws -> E)?
283
+) throws -> T {
284
+ uniffiEnsureDemucsInitialized()
285
+ var callStatus = RustCallStatus.init()
286
+ let returnedVal = callback(&callStatus)
287
+ try uniffiCheckCallStatus(callStatus: callStatus, errorHandler: errorHandler)
288
+ return returnedVal
289
+}
290
+
291
+private func uniffiCheckCallStatus<E: Swift.Error>(
292
+ callStatus: RustCallStatus,
293
+ errorHandler: ((RustBuffer) throws -> E)?
294
+) throws {
295
+ switch callStatus.code {
296
+ case CALL_SUCCESS:
297
+ return
298
+
299
+ case CALL_ERROR:
300
+ if let errorHandler = errorHandler {
301
+ throw try errorHandler(callStatus.errorBuf)
302
+ } else {
303
+ callStatus.errorBuf.deallocate()
304
+ throw UniffiInternalError.unexpectedRustCallError
305
+ }
306
+
307
+ case CALL_UNEXPECTED_ERROR:
308
+ // When the rust code sees a panic, it tries to construct a RustBuffer
309
+ // with the message. But if that code panics, then it just sends back
310
+ // an empty buffer.
311
+ if callStatus.errorBuf.len > 0 {
312
+ throw UniffiInternalError.rustPanic(try FfiConverterString.lift(callStatus.errorBuf))
313
+ } else {
314
+ callStatus.errorBuf.deallocate()
315
+ throw UniffiInternalError.rustPanic("Rust panic")
316
+ }
317
+
318
+ case CALL_CANCELLED:
319
+ fatalError("Cancellation not supported yet")
320
+
321
+ default:
322
+ throw UniffiInternalError.unexpectedRustCallStatusCode
323
+ }
324
+}
325
+
326
+private func uniffiTraitInterfaceCall<T>(
327
+ callStatus: UnsafeMutablePointer<RustCallStatus>,
328
+ makeCall: () throws -> T,
329
+ writeReturn: (T) -> ()
330
+) {
331
+ do {
332
+ try writeReturn(makeCall())
333
+ } catch let error {
334
+ callStatus.pointee.code = CALL_UNEXPECTED_ERROR
335
+ callStatus.pointee.errorBuf = FfiConverterString.lower(String(describing: error))
336
+ }
337
+}
338
+
339
+private func uniffiTraitInterfaceCallWithError<T, E>(
340
+ callStatus: UnsafeMutablePointer<RustCallStatus>,
341
+ makeCall: () throws -> T,
342
+ writeReturn: (T) -> (),
343
+ lowerError: (E) -> RustBuffer
344
+) {
345
+ do {
346
+ try writeReturn(makeCall())
347
+ } catch let error as E {
348
+ callStatus.pointee.code = CALL_ERROR
349
+ callStatus.pointee.errorBuf = lowerError(error)
350
+ } catch {
351
+ callStatus.pointee.code = CALL_UNEXPECTED_ERROR
352
+ callStatus.pointee.errorBuf = FfiConverterString.lower(String(describing: error))
353
+ }
354
+}
355
+// Initial value and increment amount for handles.
356
+// These ensure that SWIFT handles always have the lowest bit set
357
+fileprivate let UNIFFI_HANDLEMAP_INITIAL: UInt64 = 1
358
+fileprivate let UNIFFI_HANDLEMAP_DELTA: UInt64 = 2
359
+
360
+fileprivate final class UniffiHandleMap<T>: @unchecked Sendable {
361
+ // All mutation happens with this lock held, which is why we implement @unchecked Sendable.
362
+ private let lock = NSLock()
363
+ private var map: [UInt64: T] = [:]
364
+ private var currentHandle: UInt64 = UNIFFI_HANDLEMAP_INITIAL
365
+
366
+ func insert(obj: T) -> UInt64 {
367
+ lock.withLock {
368
+ return doInsert(obj)
369
+ }
370
+ }
371
+
372
+ // Low-level insert function, this assumes `lock` is held.
373
+ private func doInsert(_ obj: T) -> UInt64 {
374
+ let handle = currentHandle
375
+ currentHandle += UNIFFI_HANDLEMAP_DELTA
376
+ map[handle] = obj
377
+ return handle
378
+ }
379
+
380
+ func get(handle: UInt64) throws -> T {
381
+ try lock.withLock {
382
+ guard let obj = map[handle] else {
383
+ throw UniffiInternalError.unexpectedStaleHandle
384
+ }
385
+ return obj
386
+ }
387
+ }
388
+
389
+ func clone(handle: UInt64) throws -> UInt64 {
390
+ try lock.withLock {
391
+ guard let obj = map[handle] else {
392
+ throw UniffiInternalError.unexpectedStaleHandle
393
+ }
394
+ return doInsert(obj)
395
+ }
396
+ }
397
+
398
+ @discardableResult
399
+ func remove(handle: UInt64) throws -> T {
400
+ try lock.withLock {
401
+ guard let obj = map.removeValue(forKey: handle) else {
402
+ throw UniffiInternalError.unexpectedStaleHandle
403
+ }
404
+ return obj
405
+ }
406
+ }
407
+
408
+ var count: Int {
409
+ get {
410
+ map.count
411
+ }
412
+ }
413
+}
414
+
415
+
416
+// Public interface members begin here.
417
+// Magic number for the Rust proxy to call using the same mechanism as every other method,
418
+// to free the callback once it's dropped by Rust.
419
+private let IDX_CALLBACK_FREE: Int32 = 0
420
+// Callback return codes
421
+private let UNIFFI_CALLBACK_SUCCESS: Int32 = 0
422
+private let UNIFFI_CALLBACK_ERROR: Int32 = 1
423
+private let UNIFFI_CALLBACK_UNEXPECTED_ERROR: Int32 = 2
424
+
425
+#if swift(>=5.8)
426
+@_documentation(visibility: private)
427
+#endif
428
+fileprivate struct FfiConverterUInt32: FfiConverterPrimitive {
429
+ typealias FfiType = UInt32
430
+ typealias SwiftType = UInt32
431
+
432
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> UInt32 {
433
+ return try lift(readInt(&buf))
434
+ }
435
+
436
+ public static func write(_ value: SwiftType, into buf: inout [UInt8]) {
437
+ writeInt(&buf, lower(value))
438
+ }
439
+}
440
+
441
+#if swift(>=5.8)
442
+@_documentation(visibility: private)
443
+#endif
444
+fileprivate struct FfiConverterUInt64: FfiConverterPrimitive {
445
+ typealias FfiType = UInt64
446
+ typealias SwiftType = UInt64
447
+
448
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> UInt64 {
449
+ return try lift(readInt(&buf))
450
+ }
451
+
452
+ public static func write(_ value: SwiftType, into buf: inout [UInt8]) {
453
+ writeInt(&buf, lower(value))
454
+ }
455
+}
456
+
457
+#if swift(>=5.8)
458
+@_documentation(visibility: private)
459
+#endif
460
+fileprivate struct FfiConverterFloat: FfiConverterPrimitive {
461
+ typealias FfiType = Float
462
+ typealias SwiftType = Float
463
+
464
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Float {
465
+ return try lift(readFloat(&buf))
466
+ }
467
+
468
+ public static func write(_ value: Float, into buf: inout [UInt8]) {
469
+ writeFloat(&buf, lower(value))
470
+ }
471
+}
472
+
473
+#if swift(>=5.8)
474
+@_documentation(visibility: private)
475
+#endif
476
+fileprivate struct FfiConverterDouble: FfiConverterPrimitive {
477
+ typealias FfiType = Double
478
+ typealias SwiftType = Double
479
+
480
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Double {
481
+ return try lift(readDouble(&buf))
482
+ }
483
+
484
+ public static func write(_ value: Double, into buf: inout [UInt8]) {
485
+ writeDouble(&buf, lower(value))
486
+ }
487
+}
488
+
489
+#if swift(>=5.8)
490
+@_documentation(visibility: private)
491
+#endif
492
+fileprivate struct FfiConverterBool : FfiConverter {
493
+ typealias FfiType = Int8
494
+ typealias SwiftType = Bool
495
+
496
+ public static func lift(_ value: Int8) throws -> Bool {
497
+ return value != 0
498
+ }
499
+
500
+ public static func lower(_ value: Bool) -> Int8 {
501
+ return value ? 1 : 0
502
+ }
503
+
504
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> Bool {
505
+ return try lift(readInt(&buf))
506
+ }
507
+
508
+ public static func write(_ value: Bool, into buf: inout [UInt8]) {
509
+ writeInt(&buf, lower(value))
510
+ }
511
+}
512
+
513
+#if swift(>=5.8)
514
+@_documentation(visibility: private)
515
+#endif
516
+fileprivate struct FfiConverterString: FfiConverter {
517
+ typealias SwiftType = String
518
+ typealias FfiType = RustBuffer
519
+
520
+ public static func lift(_ value: RustBuffer) throws -> String {
521
+ defer {
522
+ value.deallocate()
523
+ }
524
+ if value.data == nil {
525
+ return String()
526
+ }
527
+ let bytes = UnsafeBufferPointer<UInt8>(start: value.data!, count: Int(value.len))
528
+ return String(bytes: bytes, encoding: String.Encoding.utf8)!
529
+ }
530
+
531
+ public static func lower(_ value: String) -> RustBuffer {
532
+ return value.utf8CString.withUnsafeBufferPointer { ptr in
533
+ // The swift string gives us int8_t, we want uint8_t.
534
+ ptr.withMemoryRebound(to: UInt8.self) { ptr in
535
+ // The swift string gives us a trailing null byte, we don't want it.
536
+ let buf = UnsafeBufferPointer(rebasing: ptr.prefix(upTo: ptr.count - 1))
537
+ return RustBuffer.from(buf)
538
+ }
539
+ }
540
+ }
541
+
542
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> String {
543
+ let len: Int32 = try readInt(&buf)
544
+ return String(bytes: try readBytes(&buf, count: Int(len)), encoding: String.Encoding.utf8)!
545
+ }
546
+
547
+ public static func write(_ value: String, into buf: inout [UInt8]) {
548
+ let len = Int32(value.utf8.count)
549
+ writeInt(&buf, len)
550
+ writeBytes(&buf, value.utf8)
551
+ }
552
+}
553
+
554
+
555
+
556
+
557
+/**
558
+ * Thread-safe HTDemucs source-separation engine.
559
+ *
560
+ * Typical lifecycle from Swift:
561
+ * ```swift
562
+ * configureCacheDir(path: appSupportDir) // sandboxed platforms
563
+ * try await downloadModel(model: .fourStem, listener: dl)
564
+ * let engine = DemucsEngine()
565
+ * let secs = try await engine.loadModel(model: .fourStem)
566
+ * try await engine.warmup()
567
+ * let stems = try await engine.separate(left: l, right: r, sampleRate: 44100)
568
+ * ```
569
+ */
570
+public protocol DemucsEngineProtocol: AnyObject, Sendable {
571
+
572
+ func isLoaded() async -> Bool
573
+
574
+ /**
575
+ * Load a model's weights from the local cache into memory (and onto the
576
+ * GPU device). Errors with `NotCached` if `downloadModel` has not been
577
+ * run for this model. Returns the wall-clock load time in seconds.
578
+ */
579
+ func loadModel(model: DemucsModel) async throws -> Double
580
+
581
+ /**
582
+ * The model currently loaded, if any.
583
+ */
584
+ func loadedModel() async -> DemucsModel?
585
+
586
+ /**
587
+ * Separate a stereo track into stems.
588
+ *
589
+ * `left` and `right` are per-channel PCM samples (any sample rate;
590
+ * resampled to 44100 Hz internally). Mono input: pass the same samples
591
+ * for both channels. Output stems are stereo PCM at 44100 Hz.
592
+ *
593
+ * Holds the engine lock for the whole separation, so concurrent calls
594
+ * on one engine serialize.
595
+ */
596
+ func separate(left: [Float], right: [Float], sampleRate: UInt32) async throws -> [StemResult]
597
+
598
+ /**
599
+ * Drop the loaded model, freeing CPU and GPU memory. Returns true if a
600
+ * model was loaded.
601
+ */
602
+ func unloadModel() async -> Bool
603
+
604
+ /**
605
+ * Run the full pipeline once on synthetic audio to pre-compile GPU
606
+ * shaders and resolve autotune. Optional but recommended before the
607
+ * first `separate` call; takes a few seconds on first run.
608
+ */
609
+ func warmup() async throws
610
+
611
+}
612
+/**
613
+ * Thread-safe HTDemucs source-separation engine.
614
+ *
615
+ * Typical lifecycle from Swift:
616
+ * ```swift
617
+ * configureCacheDir(path: appSupportDir) // sandboxed platforms
618
+ * try await downloadModel(model: .fourStem, listener: dl)
619
+ * let engine = DemucsEngine()
620
+ * let secs = try await engine.loadModel(model: .fourStem)
621
+ * try await engine.warmup()
622
+ * let stems = try await engine.separate(left: l, right: r, sampleRate: 44100)
623
+ * ```
624
+ */
625
+open class DemucsEngine: DemucsEngineProtocol, @unchecked Sendable {
626
+ fileprivate let handle: UInt64
627
+
628
+ /// Used to instantiate a [FFIObject] without an actual handle, for fakes in tests, mostly.
629
+#if swift(>=5.8)
630
+ @_documentation(visibility: private)
631
+#endif
632
+ public struct NoHandle {
633
+ public init() {}
634
+ }
635
+
636
+ // TODO: We'd like this to be `private` but for Swifty reasons,
637
+ // we can't implement `FfiConverter` without making this `required` and we can't
638
+ // make it `required` without making it `public`.
639
+#if swift(>=5.8)
640
+ @_documentation(visibility: private)
641
+#endif
642
+ required public init(unsafeFromHandle handle: UInt64) {
643
+ self.handle = handle
644
+ }
645
+
646
+ // This constructor can be used to instantiate a fake object.
647
+ // - Parameter noHandle: Placeholder value so we can have a constructor separate from the default empty one that may be implemented for classes extending [FFIObject].
648
+ //
649
+ // - Warning:
650
+ // Any object instantiated with this constructor cannot be passed to an actual Rust-backed object. Since there isn't a backing handle the FFI lower functions will crash.
651
+#if swift(>=5.8)
652
+ @_documentation(visibility: private)
653
+#endif
654
+ public init(noHandle: NoHandle) {
655
+ self.handle = 0
656
+ }
657
+
658
+#if swift(>=5.8)
659
+ @_documentation(visibility: private)
660
+#endif
661
+ public func uniffiCloneHandle() -> UInt64 {
662
+ return try! rustCall { uniffi_demucs_fn_clone_demucsengine(self.handle, $0) }
663
+ }
664
+public convenience init() {
665
+ let handle =
666
+ try! rustCall() {
667
+ uniffi_demucs_fn_constructor_demucsengine_new($0
668
+ )
669
+}
670
+ self.init(unsafeFromHandle: handle)
671
+}
672
+
673
+ deinit {
674
+ if handle == 0 {
675
+ // Mock objects have handle=0 don't try to free them
676
+ return
677
+ }
678
+
679
+ try! rustCall { uniffi_demucs_fn_free_demucsengine(handle, $0) }
680
+ }
681
+
682
+
683
+
684
+
685
+open func isLoaded()async -> Bool {
686
+ return
687
+ try! await uniffiRustCallAsync(
688
+ rustFutureFunc: {
689
+ uniffi_demucs_fn_method_demucsengine_is_loaded(
690
+ self.uniffiCloneHandle()
691
+
692
+ )
693
+ },
694
+ pollFunc: ffi_demucs_rust_future_poll_i8,
695
+ completeFunc: ffi_demucs_rust_future_complete_i8,
696
+ freeFunc: ffi_demucs_rust_future_free_i8,
697
+ liftFunc: FfiConverterBool.lift,
698
+ errorHandler: nil
699
+
700
+ )
701
+}
702
+
703
+ /**
704
+ * Load a model's weights from the local cache into memory (and onto the
705
+ * GPU device). Errors with `NotCached` if `downloadModel` has not been
706
+ * run for this model. Returns the wall-clock load time in seconds.
707
+ */
708
+open func loadModel(model: DemucsModel)async throws -> Double {
709
+ return
710
+ try await uniffiRustCallAsync(
711
+ rustFutureFunc: {
712
+ uniffi_demucs_fn_method_demucsengine_load_model(
713
+ self.uniffiCloneHandle(),
714
+ FfiConverterTypeDemucsModel_lower(model)
715
+ )
716
+ },
717
+ pollFunc: ffi_demucs_rust_future_poll_f64,
718
+ completeFunc: ffi_demucs_rust_future_complete_f64,
719
+ freeFunc: ffi_demucs_rust_future_free_f64,
720
+ liftFunc: FfiConverterDouble.lift,
721
+ errorHandler: FfiConverterTypeDemucsFfiError_lift
722
+ )
723
+}
724
+
725
+ /**
726
+ * The model currently loaded, if any.
727
+ */
728
+open func loadedModel()async -> DemucsModel? {
729
+ return
730
+ try! await uniffiRustCallAsync(
731
+ rustFutureFunc: {
732
+ uniffi_demucs_fn_method_demucsengine_loaded_model(
733
+ self.uniffiCloneHandle()
734
+
735
+ )
736
+ },
737
+ pollFunc: ffi_demucs_rust_future_poll_rust_buffer,
738
+ completeFunc: ffi_demucs_rust_future_complete_rust_buffer,
739
+ freeFunc: ffi_demucs_rust_future_free_rust_buffer,
740
+ liftFunc: FfiConverterOptionTypeDemucsModel.lift,
741
+ errorHandler: nil
742
+
743
+ )
744
+}
745
+
746
+ /**
747
+ * Separate a stereo track into stems.
748
+ *
749
+ * `left` and `right` are per-channel PCM samples (any sample rate;
750
+ * resampled to 44100 Hz internally). Mono input: pass the same samples
751
+ * for both channels. Output stems are stereo PCM at 44100 Hz.
752
+ *
753
+ * Holds the engine lock for the whole separation, so concurrent calls
754
+ * on one engine serialize.
755
+ */
756
+open func separate(left: [Float], right: [Float], sampleRate: UInt32)async throws -> [StemResult] {
757
+ return
758
+ try await uniffiRustCallAsync(
759
+ rustFutureFunc: {
760
+ uniffi_demucs_fn_method_demucsengine_separate(
761
+ self.uniffiCloneHandle(),
762
+ FfiConverterSequenceFloat.lower(left),FfiConverterSequenceFloat.lower(right),FfiConverterUInt32.lower(sampleRate)
763
+ )
764
+ },
765
+ pollFunc: ffi_demucs_rust_future_poll_rust_buffer,
766
+ completeFunc: ffi_demucs_rust_future_complete_rust_buffer,
767
+ freeFunc: ffi_demucs_rust_future_free_rust_buffer,
768
+ liftFunc: FfiConverterSequenceTypeStemResult.lift,
769
+ errorHandler: FfiConverterTypeDemucsFfiError_lift
770
+ )
771
+}
772
+
773
+ /**
774
+ * Drop the loaded model, freeing CPU and GPU memory. Returns true if a
775
+ * model was loaded.
776
+ */
777
+open func unloadModel()async -> Bool {
778
+ return
779
+ try! await uniffiRustCallAsync(
780
+ rustFutureFunc: {
781
+ uniffi_demucs_fn_method_demucsengine_unload_model(
782
+ self.uniffiCloneHandle()
783
+
784
+ )
785
+ },
786
+ pollFunc: ffi_demucs_rust_future_poll_i8,
787
+ completeFunc: ffi_demucs_rust_future_complete_i8,
788
+ freeFunc: ffi_demucs_rust_future_free_i8,
789
+ liftFunc: FfiConverterBool.lift,
790
+ errorHandler: nil
791
+
792
+ )
793
+}
794
+
795
+ /**
796
+ * Run the full pipeline once on synthetic audio to pre-compile GPU
797
+ * shaders and resolve autotune. Optional but recommended before the
798
+ * first `separate` call; takes a few seconds on first run.
799
+ */
800
+open func warmup()async throws {
801
+ return
802
+ try await uniffiRustCallAsync(
803
+ rustFutureFunc: {
804
+ uniffi_demucs_fn_method_demucsengine_warmup(
805
+ self.uniffiCloneHandle()
806
+
807
+ )
808
+ },
809
+ pollFunc: ffi_demucs_rust_future_poll_void,
810
+ completeFunc: ffi_demucs_rust_future_complete_void,
811
+ freeFunc: ffi_demucs_rust_future_free_void,
812
+ liftFunc: { $0 },
813
+ errorHandler: FfiConverterTypeDemucsFfiError_lift
814
+ )
815
+}
816
+
817
+
818
+
819
+}
820
+
821
+
822
+#if swift(>=5.8)
823
+@_documentation(visibility: private)
824
+#endif
825
+public struct FfiConverterTypeDemucsEngine: FfiConverter {
826
+ typealias FfiType = UInt64
827
+ typealias SwiftType = DemucsEngine
828
+
829
+ public static func lift(_ handle: UInt64) throws -> DemucsEngine {
830
+ return DemucsEngine(unsafeFromHandle: handle)
831
+ }
832
+
833
+ public static func lower(_ value: DemucsEngine) -> UInt64 {
834
+ return value.uniffiCloneHandle()
835
+ }
836
+
837
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> DemucsEngine {
838
+ let handle: UInt64 = try readInt(&buf)
839
+ return try lift(handle)
840
+ }
841
+
842
+ public static func write(_ value: DemucsEngine, into buf: inout [UInt8]) {
843
+ writeInt(&buf, lower(value))
844
+ }
845
+}
846
+
847
+
848
+#if swift(>=5.8)
849
+@_documentation(visibility: private)
850
+#endif
851
+public func FfiConverterTypeDemucsEngine_lift(_ handle: UInt64) throws -> DemucsEngine {
852
+ return try FfiConverterTypeDemucsEngine.lift(handle)
853
+}
854
+
855
+#if swift(>=5.8)
856
+@_documentation(visibility: private)
857
+#endif
858
+public func FfiConverterTypeDemucsEngine_lower(_ value: DemucsEngine) -> UInt64 {
859
+ return FfiConverterTypeDemucsEngine.lower(value)
860
+}
861
+
862
+
863
+
864
+
865
+/**
866
+ * Progress payload for weight downloads.
867
+ */
868
+public struct DownloadProgress: Equatable, Hashable {
869
+ public var downloadedBytes: UInt64
870
+ /**
871
+ * 0 when the server did not report a Content-Length.
872
+ */
873
+ public var totalBytes: UInt64
874
+ /**
875
+ * 0.0–1.0, or 0.0 when the total is unknown.
876
+ */
877
+ public var fraction: Double
878
+ public var done: Bool
879
+
880
+ // Default memberwise initializers are never public by default, so we
881
+ // declare one manually.
882
+ public init(downloadedBytes: UInt64,
883
+ /**
884
+ * 0 when the server did not report a Content-Length.
885
+ */totalBytes: UInt64,
886
+ /**
887
+ * 0.0–1.0, or 0.0 when the total is unknown.
888
+ */fraction: Double, done: Bool) {
889
+ self.downloadedBytes = downloadedBytes
890
+ self.totalBytes = totalBytes
891
+ self.fraction = fraction
892
+ self.done = done
893
+ }
894
+
895
+
896
+
897
+
898
+}
899
+
900
+#if compiler(>=6)
901
+extension DownloadProgress: Sendable {}
902
+#endif
903
+
904
+#if swift(>=5.8)
905
+@_documentation(visibility: private)
906
+#endif
907
+public struct FfiConverterTypeDownloadProgress: FfiConverterRustBuffer {
908
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> DownloadProgress {
909
+ return
910
+ try DownloadProgress(
911
+ downloadedBytes: FfiConverterUInt64.read(from: &buf),
912
+ totalBytes: FfiConverterUInt64.read(from: &buf),
913
+ fraction: FfiConverterDouble.read(from: &buf),
914
+ done: FfiConverterBool.read(from: &buf)
915
+ )
916
+ }
917
+
918
+ public static func write(_ value: DownloadProgress, into buf: inout [UInt8]) {
919
+ FfiConverterUInt64.write(value.downloadedBytes, into: &buf)
920
+ FfiConverterUInt64.write(value.totalBytes, into: &buf)
921
+ FfiConverterDouble.write(value.fraction, into: &buf)
922
+ FfiConverterBool.write(value.done, into: &buf)
923
+ }
924
+}
925
+
926
+
927
+#if swift(>=5.8)
928
+@_documentation(visibility: private)
929
+#endif
930
+public func FfiConverterTypeDownloadProgress_lift(_ buf: RustBuffer) throws -> DownloadProgress {
931
+ return try FfiConverterTypeDownloadProgress.lift(buf)
932
+}
933
+
934
+#if swift(>=5.8)
935
+@_documentation(visibility: private)
936
+#endif
937
+public func FfiConverterTypeDownloadProgress_lower(_ value: DownloadProgress) -> RustBuffer {
938
+ return FfiConverterTypeDownloadProgress.lower(value)
939
+}
940
+
941
+
942
+/**
943
+ * Descriptive metadata for a model variant.
944
+ */
945
+public struct ModelMetadata: Equatable, Hashable {
946
+ public var id: String
947
+ public var label: String
948
+ public var description: String
949
+ /**
950
+ * Safetensors weight file name, e.g. "htdemucs.safetensors".
951
+ */
952
+ public var filename: String
953
+ public var sizeMb: UInt32
954
+ public var stems: [StemKind]
955
+ public var downloadUrl: String
956
+
957
+ // Default memberwise initializers are never public by default, so we
958
+ // declare one manually.
959
+ public init(id: String, label: String, description: String,
960
+ /**
961
+ * Safetensors weight file name, e.g. "htdemucs.safetensors".
962
+ */filename: String, sizeMb: UInt32, stems: [StemKind], downloadUrl: String) {
963
+ self.id = id
964
+ self.label = label
965
+ self.description = description
966
+ self.filename = filename
967
+ self.sizeMb = sizeMb
968
+ self.stems = stems
969
+ self.downloadUrl = downloadUrl
970
+ }
971
+
972
+
973
+
974
+
975
+}
976
+
977
+#if compiler(>=6)
978
+extension ModelMetadata: Sendable {}
979
+#endif
980
+
981
+#if swift(>=5.8)
982
+@_documentation(visibility: private)
983
+#endif
984
+public struct FfiConverterTypeModelMetadata: FfiConverterRustBuffer {
985
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> ModelMetadata {
986
+ return
987
+ try ModelMetadata(
988
+ id: FfiConverterString.read(from: &buf),
989
+ label: FfiConverterString.read(from: &buf),
990
+ description: FfiConverterString.read(from: &buf),
991
+ filename: FfiConverterString.read(from: &buf),
992
+ sizeMb: FfiConverterUInt32.read(from: &buf),
993
+ stems: FfiConverterSequenceTypeStemKind.read(from: &buf),
994
+ downloadUrl: FfiConverterString.read(from: &buf)
995
+ )
996
+ }
997
+
998
+ public static func write(_ value: ModelMetadata, into buf: inout [UInt8]) {
999
+ FfiConverterString.write(value.id, into: &buf)
1000
+ FfiConverterString.write(value.label, into: &buf)
1001
+ FfiConverterString.write(value.description, into: &buf)
1002
+ FfiConverterString.write(value.filename, into: &buf)
1003
+ FfiConverterUInt32.write(value.sizeMb, into: &buf)
1004
+ FfiConverterSequenceTypeStemKind.write(value.stems, into: &buf)
1005
+ FfiConverterString.write(value.downloadUrl, into: &buf)
1006
+ }
1007
+}
1008
+
1009
+
1010
+#if swift(>=5.8)
1011
+@_documentation(visibility: private)
1012
+#endif
1013
+public func FfiConverterTypeModelMetadata_lift(_ buf: RustBuffer) throws -> ModelMetadata {
1014
+ return try FfiConverterTypeModelMetadata.lift(buf)
1015
+}
1016
+
1017
+#if swift(>=5.8)
1018
+@_documentation(visibility: private)
1019
+#endif
1020
+public func FfiConverterTypeModelMetadata_lower(_ value: ModelMetadata) -> RustBuffer {
1021
+ return FfiConverterTypeModelMetadata.lower(value)
1022
+}
1023
+
1024
+
1025
+/**
1026
+ * Coarse separation progress derived from chunk/stem counters.
1027
+ */
1028
+public struct SeparationProgress: Equatable, Hashable {
1029
+ /**
1030
+ * 0.0–1.0 overall fraction.
1031
+ */
1032
+ public var fraction: Double
1033
+ /**
1034
+ * 0-based index of the chunk currently in flight.
1035
+ */
1036
+ public var currentChunk: UInt64
1037
+ public var totalChunks: UInt64
1038
+
1039
+ // Default memberwise initializers are never public by default, so we
1040
+ // declare one manually.
1041
+ public init(
1042
+ /**
1043
+ * 0.0–1.0 overall fraction.
1044
+ */fraction: Double,
1045
+ /**
1046
+ * 0-based index of the chunk currently in flight.
1047
+ */currentChunk: UInt64, totalChunks: UInt64) {
1048
+ self.fraction = fraction
1049
+ self.currentChunk = currentChunk
1050
+ self.totalChunks = totalChunks
1051
+ }
1052
+
1053
+
1054
+
1055
+
1056
+}
1057
+
1058
+#if compiler(>=6)
1059
+extension SeparationProgress: Sendable {}
1060
+#endif
1061
+
1062
+#if swift(>=5.8)
1063
+@_documentation(visibility: private)
1064
+#endif
1065
+public struct FfiConverterTypeSeparationProgress: FfiConverterRustBuffer {
1066
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SeparationProgress {
1067
+ return
1068
+ try SeparationProgress(
1069
+ fraction: FfiConverterDouble.read(from: &buf),
1070
+ currentChunk: FfiConverterUInt64.read(from: &buf),
1071
+ totalChunks: FfiConverterUInt64.read(from: &buf)
1072
+ )
1073
+ }
1074
+
1075
+ public static func write(_ value: SeparationProgress, into buf: inout [UInt8]) {
1076
+ FfiConverterDouble.write(value.fraction, into: &buf)
1077
+ FfiConverterUInt64.write(value.currentChunk, into: &buf)
1078
+ FfiConverterUInt64.write(value.totalChunks, into: &buf)
1079
+ }
1080
+}
1081
+
1082
+
1083
+#if swift(>=5.8)
1084
+@_documentation(visibility: private)
1085
+#endif
1086
+public func FfiConverterTypeSeparationProgress_lift(_ buf: RustBuffer) throws -> SeparationProgress {
1087
+ return try FfiConverterTypeSeparationProgress.lift(buf)
1088
+}
1089
+
1090
+#if swift(>=5.8)
1091
+@_documentation(visibility: private)
1092
+#endif
1093
+public func FfiConverterTypeSeparationProgress_lower(_ value: SeparationProgress) -> RustBuffer {
1094
+ return FfiConverterTypeSeparationProgress.lower(value)
1095
+}
1096
+
1097
+
1098
+/**
1099
+ * One separated stem: interleaved-free stereo PCM at 44100 Hz.
1100
+ */
1101
+public struct StemResult: Equatable, Hashable {
1102
+ public var kind: StemKind
1103
+ public var left: [Float]
1104
+ public var right: [Float]
1105
+
1106
+ // Default memberwise initializers are never public by default, so we
1107
+ // declare one manually.
1108
+ public init(kind: StemKind, left: [Float], right: [Float]) {
1109
+ self.kind = kind
1110
+ self.left = left
1111
+ self.right = right
1112
+ }
1113
+
1114
+
1115
+
1116
+
1117
+}
1118
+
1119
+#if compiler(>=6)
1120
+extension StemResult: Sendable {}
1121
+#endif
1122
+
1123
+#if swift(>=5.8)
1124
+@_documentation(visibility: private)
1125
+#endif
1126
+public struct FfiConverterTypeStemResult: FfiConverterRustBuffer {
1127
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> StemResult {
1128
+ return
1129
+ try StemResult(
1130
+ kind: FfiConverterTypeStemKind.read(from: &buf),
1131
+ left: FfiConverterSequenceFloat.read(from: &buf),
1132
+ right: FfiConverterSequenceFloat.read(from: &buf)
1133
+ )
1134
+ }
1135
+
1136
+ public static func write(_ value: StemResult, into buf: inout [UInt8]) {
1137
+ FfiConverterTypeStemKind.write(value.kind, into: &buf)
1138
+ FfiConverterSequenceFloat.write(value.left, into: &buf)
1139
+ FfiConverterSequenceFloat.write(value.right, into: &buf)
1140
+ }
1141
+}
1142
+
1143
+
1144
+#if swift(>=5.8)
1145
+@_documentation(visibility: private)
1146
+#endif
1147
+public func FfiConverterTypeStemResult_lift(_ buf: RustBuffer) throws -> StemResult {
1148
+ return try FfiConverterTypeStemResult.lift(buf)
1149
+}
1150
+
1151
+#if swift(>=5.8)
1152
+@_documentation(visibility: private)
1153
+#endif
1154
+public func FfiConverterTypeStemResult_lower(_ value: StemResult) -> RustBuffer {
1155
+ return FfiConverterTypeStemResult.lower(value)
1156
+}
1157
+
1158
+
1159
+/**
1160
+ * Errors surfaced across the FFI boundary.
1161
+ */
1162
+public enum DemucsFfiError: Swift.Error, Equatable, Hashable, Foundation.LocalizedError {
1163
+
1164
+
1165
+
1166
+ case NoModelLoaded
1167
+ case AlreadyLoaded(modelId: String
1168
+ )
1169
+ case Weights(reason: String
1170
+ )
1171
+ case Dsp(reason: String
1172
+ )
1173
+ case Tensor(reason: String
1174
+ )
1175
+ case Internal(reason: String
1176
+ )
1177
+ case Cancelled
1178
+ case NotCached(reason: String
1179
+ )
1180
+ case Io(reason: String
1181
+ )
1182
+ case NoCacheDir
1183
+ case Download(reason: String
1184
+ )
1185
+
1186
+
1187
+
1188
+
1189
+
1190
+
1191
+ public var errorDescription: String? {
1192
+ String(reflecting: self)
1193
+ }
1194
+
1195
+}
1196
+
1197
+#if compiler(>=6)
1198
+extension DemucsFfiError: Sendable {}
1199
+#endif
1200
+
1201
+#if swift(>=5.8)
1202
+@_documentation(visibility: private)
1203
+#endif
1204
+public struct FfiConverterTypeDemucsFfiError: FfiConverterRustBuffer {
1205
+ typealias SwiftType = DemucsFfiError
1206
+
1207
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> DemucsFfiError {
1208
+ let variant: Int32 = try readInt(&buf)
1209
+ switch variant {
1210
+
1211
+
1212
+
1213
+
1214
+ case 1: return .NoModelLoaded
1215
+ case 2: return .AlreadyLoaded(
1216
+ modelId: try FfiConverterString.read(from: &buf)
1217
+ )
1218
+ case 3: return .Weights(
1219
+ reason: try FfiConverterString.read(from: &buf)
1220
+ )
1221
+ case 4: return .Dsp(
1222
+ reason: try FfiConverterString.read(from: &buf)
1223
+ )
1224
+ case 5: return .Tensor(
1225
+ reason: try FfiConverterString.read(from: &buf)
1226
+ )
1227
+ case 6: return .Internal(
1228
+ reason: try FfiConverterString.read(from: &buf)
1229
+ )
1230
+ case 7: return .Cancelled
1231
+ case 8: return .NotCached(
1232
+ reason: try FfiConverterString.read(from: &buf)
1233
+ )
1234
+ case 9: return .Io(
1235
+ reason: try FfiConverterString.read(from: &buf)
1236
+ )
1237
+ case 10: return .NoCacheDir
1238
+ case 11: return .Download(
1239
+ reason: try FfiConverterString.read(from: &buf)
1240
+ )
1241
+
1242
+ default: throw UniffiInternalError.unexpectedEnumCase
1243
+ }
1244
+ }
1245
+
1246
+ public static func write(_ value: DemucsFfiError, into buf: inout [UInt8]) {
1247
+ switch value {
1248
+
1249
+
1250
+
1251
+
1252
+
1253
+ case .NoModelLoaded:
1254
+ writeInt(&buf, Int32(1))
1255
+
1256
+
1257
+ case let .AlreadyLoaded(modelId):
1258
+ writeInt(&buf, Int32(2))
1259
+ FfiConverterString.write(modelId, into: &buf)
1260
+
1261
+
1262
+ case let .Weights(reason):
1263
+ writeInt(&buf, Int32(3))
1264
+ FfiConverterString.write(reason, into: &buf)
1265
+
1266
+
1267
+ case let .Dsp(reason):
1268
+ writeInt(&buf, Int32(4))
1269
+ FfiConverterString.write(reason, into: &buf)
1270
+
1271
+
1272
+ case let .Tensor(reason):
1273
+ writeInt(&buf, Int32(5))
1274
+ FfiConverterString.write(reason, into: &buf)
1275
+
1276
+
1277
+ case let .Internal(reason):
1278
+ writeInt(&buf, Int32(6))
1279
+ FfiConverterString.write(reason, into: &buf)
1280
+
1281
+
1282
+ case .Cancelled:
1283
+ writeInt(&buf, Int32(7))
1284
+
1285
+
1286
+ case let .NotCached(reason):
1287
+ writeInt(&buf, Int32(8))
1288
+ FfiConverterString.write(reason, into: &buf)
1289
+
1290
+
1291
+ case let .Io(reason):
1292
+ writeInt(&buf, Int32(9))
1293
+ FfiConverterString.write(reason, into: &buf)
1294
+
1295
+
1296
+ case .NoCacheDir:
1297
+ writeInt(&buf, Int32(10))
1298
+
1299
+
1300
+ case let .Download(reason):
1301
+ writeInt(&buf, Int32(11))
1302
+ FfiConverterString.write(reason, into: &buf)
1303
+
1304
+ }
1305
+ }
1306
+}
1307
+
1308
+
1309
+#if swift(>=5.8)
1310
+@_documentation(visibility: private)
1311
+#endif
1312
+public func FfiConverterTypeDemucsFfiError_lift(_ buf: RustBuffer) throws -> DemucsFfiError {
1313
+ return try FfiConverterTypeDemucsFfiError.lift(buf)
1314
+}
1315
+
1316
+#if swift(>=5.8)
1317
+@_documentation(visibility: private)
1318
+#endif
1319
+public func FfiConverterTypeDemucsFfiError_lower(_ value: DemucsFfiError) -> RustBuffer {
1320
+ return FfiConverterTypeDemucsFfiError.lower(value)
1321
+}
1322
+
1323
+// Note that we don't yet support `indirect` for enums.
1324
+// See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion.
1325
+/**
1326
+ * Which HTDemucs variant to load.
1327
+ */
1328
+
1329
+public enum DemucsModel: Equatable, Hashable {
1330
+
1331
+ /**
1332
+ * htdemucs — 4 stems, balanced speed and quality (~84 MB).
1333
+ */
1334
+ case fourStem
1335
+ /**
1336
+ * htdemucs_6s — 6 stems, adds guitar and piano (~84 MB).
1337
+ */
1338
+ case sixStem
1339
+ /**
1340
+ * htdemucs_ft — fine-tuned, best quality, one sub-model per requested
1341
+ * stem so inference time scales with `stems.len()` (~333 MB).
1342
+ */
1343
+ case fineTuned(stems: [StemKind]
1344
+ )
1345
+
1346
+
1347
+
1348
+
1349
+
1350
+}
1351
+
1352
+#if compiler(>=6)
1353
+extension DemucsModel: Sendable {}
1354
+#endif
1355
+
1356
+#if swift(>=5.8)
1357
+@_documentation(visibility: private)
1358
+#endif
1359
+public struct FfiConverterTypeDemucsModel: FfiConverterRustBuffer {
1360
+ typealias SwiftType = DemucsModel
1361
+
1362
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> DemucsModel {
1363
+ let variant: Int32 = try readInt(&buf)
1364
+ switch variant {
1365
+
1366
+ case 1: return .fourStem
1367
+
1368
+ case 2: return .sixStem
1369
+
1370
+ case 3: return .fineTuned(stems: try FfiConverterSequenceTypeStemKind.read(from: &buf)
1371
+ )
1372
+
1373
+ default: throw UniffiInternalError.unexpectedEnumCase
1374
+ }
1375
+ }
1376
+
1377
+ public static func write(_ value: DemucsModel, into buf: inout [UInt8]) {
1378
+ switch value {
1379
+
1380
+
1381
+ case .fourStem:
1382
+ writeInt(&buf, Int32(1))
1383
+
1384
+
1385
+ case .sixStem:
1386
+ writeInt(&buf, Int32(2))
1387
+
1388
+
1389
+ case let .fineTuned(stems):
1390
+ writeInt(&buf, Int32(3))
1391
+ FfiConverterSequenceTypeStemKind.write(stems, into: &buf)
1392
+
1393
+ }
1394
+ }
1395
+}
1396
+
1397
+
1398
+#if swift(>=5.8)
1399
+@_documentation(visibility: private)
1400
+#endif
1401
+public func FfiConverterTypeDemucsModel_lift(_ buf: RustBuffer) throws -> DemucsModel {
1402
+ return try FfiConverterTypeDemucsModel.lift(buf)
1403
+}
1404
+
1405
+#if swift(>=5.8)
1406
+@_documentation(visibility: private)
1407
+#endif
1408
+public func FfiConverterTypeDemucsModel_lower(_ value: DemucsModel) -> RustBuffer {
1409
+ return FfiConverterTypeDemucsModel.lower(value)
1410
+}
1411
+
1412
+
1413
+// Note that we don't yet support `indirect` for enums.
1414
+// See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion.
1415
+/**
1416
+ * A single separable audio source.
1417
+ */
1418
+
1419
+public enum StemKind: Equatable, Hashable {
1420
+
1421
+ case drums
1422
+ case bass
1423
+ case other
1424
+ case vocals
1425
+ case guitar
1426
+ case piano
1427
+
1428
+
1429
+
1430
+
1431
+
1432
+}
1433
+
1434
+#if compiler(>=6)
1435
+extension StemKind: Sendable {}
1436
+#endif
1437
+
1438
+#if swift(>=5.8)
1439
+@_documentation(visibility: private)
1440
+#endif
1441
+public struct FfiConverterTypeStemKind: FfiConverterRustBuffer {
1442
+ typealias SwiftType = StemKind
1443
+
1444
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> StemKind {
1445
+ let variant: Int32 = try readInt(&buf)
1446
+ switch variant {
1447
+
1448
+ case 1: return .drums
1449
+
1450
+ case 2: return .bass
1451
+
1452
+ case 3: return .other
1453
+
1454
+ case 4: return .vocals
1455
+
1456
+ case 5: return .guitar
1457
+
1458
+ case 6: return .piano
1459
+
1460
+ default: throw UniffiInternalError.unexpectedEnumCase
1461
+ }
1462
+ }
1463
+
1464
+ public static func write(_ value: StemKind, into buf: inout [UInt8]) {
1465
+ switch value {
1466
+
1467
+
1468
+ case .drums:
1469
+ writeInt(&buf, Int32(1))
1470
+
1471
+
1472
+ case .bass:
1473
+ writeInt(&buf, Int32(2))
1474
+
1475
+
1476
+ case .other:
1477
+ writeInt(&buf, Int32(3))
1478
+
1479
+
1480
+ case .vocals:
1481
+ writeInt(&buf, Int32(4))
1482
+
1483
+
1484
+ case .guitar:
1485
+ writeInt(&buf, Int32(5))
1486
+
1487
+
1488
+ case .piano:
1489
+ writeInt(&buf, Int32(6))
1490
+
1491
+ }
1492
+ }
1493
+}
1494
+
1495
+
1496
+#if swift(>=5.8)
1497
+@_documentation(visibility: private)
1498
+#endif
1499
+public func FfiConverterTypeStemKind_lift(_ buf: RustBuffer) throws -> StemKind {
1500
+ return try FfiConverterTypeStemKind.lift(buf)
1501
+}
1502
+
1503
+#if swift(>=5.8)
1504
+@_documentation(visibility: private)
1505
+#endif
1506
+public func FfiConverterTypeStemKind_lower(_ value: StemKind) -> RustBuffer {
1507
+ return FfiConverterTypeStemKind.lower(value)
1508
+}
1509
+
1510
+
1511
+
1512
+
1513
+
1514
+/**
1515
+ * Receives download progress. Return true to continue, false to cancel —
1516
+ * the partial file is deleted and `download_model` returns `Cancelled`.
1517
+ */
1518
+public protocol DownloadProgressListener: AnyObject, Sendable {
1519
+
1520
+ func onProgress(progress: DownloadProgress) -> Bool
1521
+
1522
+}
1523
+
1524
+
1525
+// Put the implementation in a struct so we don't pollute the top-level namespace
1526
+fileprivate struct UniffiCallbackInterfaceDownloadProgressListener {
1527
+
1528
+ // Create the VTable using a series of closures.
1529
+ // Swift automatically converts these into C callback functions.
1530
+ //
1531
+ // This creates 1-element array, since this seems to be the only way to construct a const
1532
+ // pointer that we can pass to the Rust code.
1533
+ static let vtable: [UniffiVTableCallbackInterfaceDownloadProgressListener] = [UniffiVTableCallbackInterfaceDownloadProgressListener(
1534
+ uniffiFree: { (uniffiHandle: UInt64) -> () in
1535
+ do {
1536
+ try FfiConverterCallbackInterfaceDownloadProgressListener.handleMap.remove(handle: uniffiHandle)
1537
+ } catch {
1538
+ print("Uniffi callback interface DownloadProgressListener: handle missing in uniffiFree")
1539
+ }
1540
+ },
1541
+ uniffiClone: { (uniffiHandle: UInt64) -> UInt64 in
1542
+ do {
1543
+ return try FfiConverterCallbackInterfaceDownloadProgressListener.handleMap.clone(handle: uniffiHandle)
1544
+ } catch {
1545
+ fatalError("Uniffi callback interface DownloadProgressListener: handle missing in uniffiClone")
1546
+ }
1547
+ },
1548
+ onProgress: { (
1549
+ uniffiHandle: UInt64,
1550
+ progress: RustBuffer,
1551
+ uniffiOutReturn: UnsafeMutablePointer<Int8>,
1552
+ uniffiCallStatus: UnsafeMutablePointer<RustCallStatus>
1553
+ ) in
1554
+ let makeCall = {
1555
+ () throws -> Bool in
1556
+ guard let uniffiObj = try? FfiConverterCallbackInterfaceDownloadProgressListener.handleMap.get(handle: uniffiHandle) else {
1557
+ throw UniffiInternalError.unexpectedStaleHandle
1558
+ }
1559
+ return uniffiObj.onProgress(
1560
+ progress: try FfiConverterTypeDownloadProgress_lift(progress)
1561
+ )
1562
+ }
1563
+
1564
+
1565
+ let writeReturn = { uniffiOutReturn.pointee = FfiConverterBool.lower($0) }
1566
+ uniffiTraitInterfaceCall(
1567
+ callStatus: uniffiCallStatus,
1568
+ makeCall: makeCall,
1569
+ writeReturn: writeReturn
1570
+ )
1571
+ }
1572
+ )]
1573
+}
1574
+
1575
+private func uniffiCallbackInitDownloadProgressListener() {
1576
+ uniffi_demucs_fn_init_callback_vtable_downloadprogresslistener(UniffiCallbackInterfaceDownloadProgressListener.vtable)
1577
+}
1578
+
1579
+// FfiConverter protocol for callback interfaces
1580
+#if swift(>=5.8)
1581
+@_documentation(visibility: private)
1582
+#endif
1583
+fileprivate struct FfiConverterCallbackInterfaceDownloadProgressListener {
1584
+ fileprivate static let handleMap = UniffiHandleMap<DownloadProgressListener>()
1585
+}
1586
+
1587
+#if swift(>=5.8)
1588
+@_documentation(visibility: private)
1589
+#endif
1590
+extension FfiConverterCallbackInterfaceDownloadProgressListener : FfiConverter {
1591
+ typealias SwiftType = DownloadProgressListener
1592
+ typealias FfiType = UInt64
1593
+
1594
+#if swift(>=5.8)
1595
+ @_documentation(visibility: private)
1596
+#endif
1597
+ public static func lift(_ handle: UInt64) throws -> SwiftType {
1598
+ try handleMap.get(handle: handle)
1599
+ }
1600
+
1601
+#if swift(>=5.8)
1602
+ @_documentation(visibility: private)
1603
+#endif
1604
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SwiftType {
1605
+ let handle: UInt64 = try readInt(&buf)
1606
+ return try lift(handle)
1607
+ }
1608
+
1609
+#if swift(>=5.8)
1610
+ @_documentation(visibility: private)
1611
+#endif
1612
+ public static func lower(_ v: SwiftType) -> UInt64 {
1613
+ return handleMap.insert(obj: v)
1614
+ }
1615
+
1616
+#if swift(>=5.8)
1617
+ @_documentation(visibility: private)
1618
+#endif
1619
+ public static func write(_ v: SwiftType, into buf: inout [UInt8]) {
1620
+ writeInt(&buf, lower(v))
1621
+ }
1622
+}
1623
+
1624
+
1625
+#if swift(>=5.8)
1626
+@_documentation(visibility: private)
1627
+#endif
1628
+public func FfiConverterCallbackInterfaceDownloadProgressListener_lift(_ handle: UInt64) throws -> DownloadProgressListener {
1629
+ return try FfiConverterCallbackInterfaceDownloadProgressListener.lift(handle)
1630
+}
1631
+
1632
+#if swift(>=5.8)
1633
+@_documentation(visibility: private)
1634
+#endif
1635
+public func FfiConverterCallbackInterfaceDownloadProgressListener_lower(_ v: DownloadProgressListener) -> UInt64 {
1636
+ return FfiConverterCallbackInterfaceDownloadProgressListener.lower(v)
1637
+}
1638
+
1639
+
1640
+
1641
+
1642
+/**
1643
+ * Receives coarse progress during separation.
1644
+ *
1645
+ * Called from the inference task; keep the callback fast. Return true to
1646
+ * continue, false to cancel — the engine then returns `Cancelled`.
1647
+ */
1648
+public protocol SeparationProgressListener: AnyObject, Sendable {
1649
+
1650
+ func onProgress(progress: SeparationProgress) -> Bool
1651
+
1652
+}
1653
+
1654
+
1655
+// Put the implementation in a struct so we don't pollute the top-level namespace
1656
+fileprivate struct UniffiCallbackInterfaceSeparationProgressListener {
1657
+
1658
+ // Create the VTable using a series of closures.
1659
+ // Swift automatically converts these into C callback functions.
1660
+ //
1661
+ // This creates 1-element array, since this seems to be the only way to construct a const
1662
+ // pointer that we can pass to the Rust code.
1663
+ static let vtable: [UniffiVTableCallbackInterfaceSeparationProgressListener] = [UniffiVTableCallbackInterfaceSeparationProgressListener(
1664
+ uniffiFree: { (uniffiHandle: UInt64) -> () in
1665
+ do {
1666
+ try FfiConverterCallbackInterfaceSeparationProgressListener.handleMap.remove(handle: uniffiHandle)
1667
+ } catch {
1668
+ print("Uniffi callback interface SeparationProgressListener: handle missing in uniffiFree")
1669
+ }
1670
+ },
1671
+ uniffiClone: { (uniffiHandle: UInt64) -> UInt64 in
1672
+ do {
1673
+ return try FfiConverterCallbackInterfaceSeparationProgressListener.handleMap.clone(handle: uniffiHandle)
1674
+ } catch {
1675
+ fatalError("Uniffi callback interface SeparationProgressListener: handle missing in uniffiClone")
1676
+ }
1677
+ },
1678
+ onProgress: { (
1679
+ uniffiHandle: UInt64,
1680
+ progress: RustBuffer,
1681
+ uniffiOutReturn: UnsafeMutablePointer<Int8>,
1682
+ uniffiCallStatus: UnsafeMutablePointer<RustCallStatus>
1683
+ ) in
1684
+ let makeCall = {
1685
+ () throws -> Bool in
1686
+ guard let uniffiObj = try? FfiConverterCallbackInterfaceSeparationProgressListener.handleMap.get(handle: uniffiHandle) else {
1687
+ throw UniffiInternalError.unexpectedStaleHandle
1688
+ }
1689
+ return uniffiObj.onProgress(
1690
+ progress: try FfiConverterTypeSeparationProgress_lift(progress)
1691
+ )
1692
+ }
1693
+
1694
+
1695
+ let writeReturn = { uniffiOutReturn.pointee = FfiConverterBool.lower($0) }
1696
+ uniffiTraitInterfaceCall(
1697
+ callStatus: uniffiCallStatus,
1698
+ makeCall: makeCall,
1699
+ writeReturn: writeReturn
1700
+ )
1701
+ }
1702
+ )]
1703
+}
1704
+
1705
+private func uniffiCallbackInitSeparationProgressListener() {
1706
+ uniffi_demucs_fn_init_callback_vtable_separationprogresslistener(UniffiCallbackInterfaceSeparationProgressListener.vtable)
1707
+}
1708
+
1709
+// FfiConverter protocol for callback interfaces
1710
+#if swift(>=5.8)
1711
+@_documentation(visibility: private)
1712
+#endif
1713
+fileprivate struct FfiConverterCallbackInterfaceSeparationProgressListener {
1714
+ fileprivate static let handleMap = UniffiHandleMap<SeparationProgressListener>()
1715
+}
1716
+
1717
+#if swift(>=5.8)
1718
+@_documentation(visibility: private)
1719
+#endif
1720
+extension FfiConverterCallbackInterfaceSeparationProgressListener : FfiConverter {
1721
+ typealias SwiftType = SeparationProgressListener
1722
+ typealias FfiType = UInt64
1723
+
1724
+#if swift(>=5.8)
1725
+ @_documentation(visibility: private)
1726
+#endif
1727
+ public static func lift(_ handle: UInt64) throws -> SwiftType {
1728
+ try handleMap.get(handle: handle)
1729
+ }
1730
+
1731
+#if swift(>=5.8)
1732
+ @_documentation(visibility: private)
1733
+#endif
1734
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SwiftType {
1735
+ let handle: UInt64 = try readInt(&buf)
1736
+ return try lift(handle)
1737
+ }
1738
+
1739
+#if swift(>=5.8)
1740
+ @_documentation(visibility: private)
1741
+#endif
1742
+ public static func lower(_ v: SwiftType) -> UInt64 {
1743
+ return handleMap.insert(obj: v)
1744
+ }
1745
+
1746
+#if swift(>=5.8)
1747
+ @_documentation(visibility: private)
1748
+#endif
1749
+ public static func write(_ v: SwiftType, into buf: inout [UInt8]) {
1750
+ writeInt(&buf, lower(v))
1751
+ }
1752
+}
1753
+
1754
+
1755
+#if swift(>=5.8)
1756
+@_documentation(visibility: private)
1757
+#endif
1758
+public func FfiConverterCallbackInterfaceSeparationProgressListener_lift(_ handle: UInt64) throws -> SeparationProgressListener {
1759
+ return try FfiConverterCallbackInterfaceSeparationProgressListener.lift(handle)
1760
+}
1761
+
1762
+#if swift(>=5.8)
1763
+@_documentation(visibility: private)
1764
+#endif
1765
+public func FfiConverterCallbackInterfaceSeparationProgressListener_lower(_ v: SeparationProgressListener) -> UInt64 {
1766
+ return FfiConverterCallbackInterfaceSeparationProgressListener.lower(v)
1767
+}
1768
+
1769
+#if swift(>=5.8)
1770
+@_documentation(visibility: private)
1771
+#endif
1772
+fileprivate struct FfiConverterOptionString: FfiConverterRustBuffer {
1773
+ typealias SwiftType = String?
1774
+
1775
+ public static func write(_ value: SwiftType, into buf: inout [UInt8]) {
1776
+ guard let value = value else {
1777
+ writeInt(&buf, Int8(0))
1778
+ return
1779
+ }
1780
+ writeInt(&buf, Int8(1))
1781
+ FfiConverterString.write(value, into: &buf)
1782
+ }
1783
+
1784
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SwiftType {
1785
+ switch try readInt(&buf) as Int8 {
1786
+ case 0: return nil
1787
+ case 1: return try FfiConverterString.read(from: &buf)
1788
+ default: throw UniffiInternalError.unexpectedOptionalTag
1789
+ }
1790
+ }
1791
+}
1792
+
1793
+#if swift(>=5.8)
1794
+@_documentation(visibility: private)
1795
+#endif
1796
+fileprivate struct FfiConverterOptionTypeDemucsModel: FfiConverterRustBuffer {
1797
+ typealias SwiftType = DemucsModel?
1798
+
1799
+ public static func write(_ value: SwiftType, into buf: inout [UInt8]) {
1800
+ guard let value = value else {
1801
+ writeInt(&buf, Int8(0))
1802
+ return
1803
+ }
1804
+ writeInt(&buf, Int8(1))
1805
+ FfiConverterTypeDemucsModel.write(value, into: &buf)
1806
+ }
1807
+
1808
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SwiftType {
1809
+ switch try readInt(&buf) as Int8 {
1810
+ case 0: return nil
1811
+ case 1: return try FfiConverterTypeDemucsModel.read(from: &buf)
1812
+ default: throw UniffiInternalError.unexpectedOptionalTag
1813
+ }
1814
+ }
1815
+}
1816
+
1817
+#if swift(>=5.8)
1818
+@_documentation(visibility: private)
1819
+#endif
1820
+fileprivate struct FfiConverterSequenceFloat: FfiConverterRustBuffer {
1821
+ typealias SwiftType = [Float]
1822
+
1823
+ public static func write(_ value: [Float], into buf: inout [UInt8]) {
1824
+ let len = Int32(value.count)
1825
+ writeInt(&buf, len)
1826
+ for item in value {
1827
+ FfiConverterFloat.write(item, into: &buf)
1828
+ }
1829
+ }
1830
+
1831
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> [Float] {
1832
+ let len: Int32 = try readInt(&buf)
1833
+ var seq = [Float]()
1834
+ seq.reserveCapacity(Int(len))
1835
+ for _ in 0 ..< len {
1836
+ seq.append(try FfiConverterFloat.read(from: &buf))
1837
+ }
1838
+ return seq
1839
+ }
1840
+}
1841
+
1842
+#if swift(>=5.8)
1843
+@_documentation(visibility: private)
1844
+#endif
1845
+fileprivate struct FfiConverterSequenceTypeModelMetadata: FfiConverterRustBuffer {
1846
+ typealias SwiftType = [ModelMetadata]
1847
+
1848
+ public static func write(_ value: [ModelMetadata], into buf: inout [UInt8]) {
1849
+ let len = Int32(value.count)
1850
+ writeInt(&buf, len)
1851
+ for item in value {
1852
+ FfiConverterTypeModelMetadata.write(item, into: &buf)
1853
+ }
1854
+ }
1855
+
1856
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> [ModelMetadata] {
1857
+ let len: Int32 = try readInt(&buf)
1858
+ var seq = [ModelMetadata]()
1859
+ seq.reserveCapacity(Int(len))
1860
+ for _ in 0 ..< len {
1861
+ seq.append(try FfiConverterTypeModelMetadata.read(from: &buf))
1862
+ }
1863
+ return seq
1864
+ }
1865
+}
1866
+
1867
+#if swift(>=5.8)
1868
+@_documentation(visibility: private)
1869
+#endif
1870
+fileprivate struct FfiConverterSequenceTypeStemResult: FfiConverterRustBuffer {
1871
+ typealias SwiftType = [StemResult]
1872
+
1873
+ public static func write(_ value: [StemResult], into buf: inout [UInt8]) {
1874
+ let len = Int32(value.count)
1875
+ writeInt(&buf, len)
1876
+ for item in value {
1877
+ FfiConverterTypeStemResult.write(item, into: &buf)
1878
+ }
1879
+ }
1880
+
1881
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> [StemResult] {
1882
+ let len: Int32 = try readInt(&buf)
1883
+ var seq = [StemResult]()
1884
+ seq.reserveCapacity(Int(len))
1885
+ for _ in 0 ..< len {
1886
+ seq.append(try FfiConverterTypeStemResult.read(from: &buf))
1887
+ }
1888
+ return seq
1889
+ }
1890
+}
1891
+
1892
+#if swift(>=5.8)
1893
+@_documentation(visibility: private)
1894
+#endif
1895
+fileprivate struct FfiConverterSequenceTypeStemKind: FfiConverterRustBuffer {
1896
+ typealias SwiftType = [StemKind]
1897
+
1898
+ public static func write(_ value: [StemKind], into buf: inout [UInt8]) {
1899
+ let len = Int32(value.count)
1900
+ writeInt(&buf, len)
1901
+ for item in value {
1902
+ FfiConverterTypeStemKind.write(item, into: &buf)
1903
+ }
1904
+ }
1905
+
1906
+ public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> [StemKind] {
1907
+ let len: Int32 = try readInt(&buf)
1908
+ var seq = [StemKind]()
1909
+ seq.reserveCapacity(Int(len))
1910
+ for _ in 0 ..< len {
1911
+ seq.append(try FfiConverterTypeStemKind.read(from: &buf))
1912
+ }
1913
+ return seq
1914
+ }
1915
+}
1916
+private let UNIFFI_RUST_FUTURE_POLL_READY: Int8 = 0
1917
+private let UNIFFI_RUST_FUTURE_POLL_WAKE: Int8 = 1
1918
+
1919
+fileprivate let uniffiContinuationHandleMap = UniffiHandleMap<UnsafeContinuation<Int8, Never>>()
1920
+
1921
+fileprivate func uniffiRustCallAsync<F, T>(
1922
+ rustFutureFunc: () -> UInt64,
1923
+ pollFunc: (UInt64, @escaping UniffiRustFutureContinuationCallback, UInt64) -> (),
1924
+ completeFunc: (UInt64, UnsafeMutablePointer<RustCallStatus>) -> F,
1925
+ freeFunc: (UInt64) -> (),
1926
+ liftFunc: (F) throws -> T,
1927
+ errorHandler: ((RustBuffer) throws -> Swift.Error)?
1928
+) async throws -> T {
1929
+ // Make sure to call the ensure init function since future creation doesn't have a
1930
+ // RustCallStatus param, so doesn't use makeRustCall()
1931
+ uniffiEnsureDemucsInitialized()
1932
+ let rustFuture = rustFutureFunc()
1933
+ defer {
1934
+ freeFunc(rustFuture)
1935
+ }
1936
+ var pollResult: Int8;
1937
+ repeat {
1938
+ pollResult = await withUnsafeContinuation {
1939
+ pollFunc(
1940
+ rustFuture,
1941
+ { handle, pollResult in
1942
+ uniffiFutureContinuationCallback(handle: handle, pollResult: pollResult)
1943
+ },
1944
+ uniffiContinuationHandleMap.insert(obj: $0)
1945
+ )
1946
+ }
1947
+ } while pollResult != UNIFFI_RUST_FUTURE_POLL_READY
1948
+
1949
+ return try liftFunc(makeRustCall(
1950
+ { completeFunc(rustFuture, $0) },
1951
+ errorHandler: errorHandler
1952
+ ))
1953
+}
1954
+
1955
+// Callback handlers for an async calls. These are invoked by Rust when the future is ready. They
1956
+// lift the return value or error and resume the suspended function.
1957
+fileprivate func uniffiFutureContinuationCallback(handle: UInt64, pollResult: Int8) {
1958
+ if let continuation = try? uniffiContinuationHandleMap.remove(handle: handle) {
1959
+ continuation.resume(returning: pollResult)
1960
+ } else {
1961
+ print("uniffiFutureContinuationCallback invalid handle")
1962
+ }
1963
+}
1964
+/**
1965
+ * Metadata for every supported model variant.
1966
+ */
1967
+public func allModels() -> [ModelMetadata] {
1968
+ return try! FfiConverterSequenceTypeModelMetadata.lift(try! rustCall() {
1969
+ uniffi_demucs_fn_func_all_models($0
1970
+ )
1971
+})
1972
+}
1973
+/**
1974
+ * Filesystem path the model's weights live at once downloaded, or None if
1975
+ * not cached yet.
1976
+ */
1977
+public func cachedModelPath(model: DemucsModel) -> String? {
1978
+ return try! FfiConverterOptionString.lift(try! rustCall() {
1979
+ uniffi_demucs_fn_func_cached_model_path(
1980
+ FfiConverterTypeDemucsModel_lower(model),$0
1981
+ )
1982
+})
1983
+}
1984
+/**
1985
+ * Override the model cache directory.
1986
+ *
1987
+ * On iOS/tvOS/visionOS call this once at app launch — before
1988
+ * `downloadModel` or `DemucsEngine.loadModel` — with a directory inside the
1989
+ * app sandbox, e.g. the app's Application Support or Caches directory.
1990
+ * The directory is created if missing.
1991
+ */
1992
+public func configureCacheDir(path: String) {try! rustCall() {
1993
+ uniffi_demucs_fn_func_configure_cache_dir(
1994
+ FfiConverterString.lower(path),$0
1995
+ )
1996
+}
1997
+}
1998
+/**
1999
+ * Delete a model's weights from the local cache. Returns true if a file was
2000
+ * removed.
2001
+ */
2002
+public func deleteCachedModel(model: DemucsModel) -> Bool {
2003
+ return try! FfiConverterBool.lift(try! rustCall() {
2004
+ uniffi_demucs_fn_func_delete_cached_model(
2005
+ FfiConverterTypeDemucsModel_lower(model),$0
2006
+ )
2007
+})
2008
+}
2009
+/**
2010
+ * Whether the model's weights are already in the local cache.
2011
+ */
2012
+public func isModelCached(model: DemucsModel) -> Bool {
2013
+ return try! FfiConverterBool.lift(try! rustCall() {
2014
+ uniffi_demucs_fn_func_is_model_cached(
2015
+ FfiConverterTypeDemucsModel_lower(model),$0
2016
+ )
2017
+})
2018
+}
2019
+/**
2020
+ * Metadata (name, size, stems, download URL) for a model variant.
2021
+ */
2022
+public func modelMetadata(model: DemucsModel) -> ModelMetadata {
2023
+ return try! FfiConverterTypeModelMetadata_lift(try! rustCall() {
2024
+ uniffi_demucs_fn_func_model_metadata(
2025
+ FfiConverterTypeDemucsModel_lower(model),$0
2026
+ )
2027
+})
2028
+}
2029
+/**
2030
+ * Number of inference chunks a track of `n_samples` (per channel, at
2031
+ * 44100 Hz) is split into. Useful for sizing progress UIs.
2032
+ */
2033
+public func numChunks(nSamples: UInt64) -> UInt64 {
2034
+ return try! FfiConverterUInt64.lift(try! rustCall() {
2035
+ uniffi_demucs_fn_func_num_chunks(
2036
+ FfiConverterUInt64.lower(nSamples),$0
2037
+ )
2038
+})
2039
+}
2040
+/**
2041
+ * Download a model's weights into the local cache.
2042
+ *
2043
+ * No-op (immediately reports `done`) if the model is already cached. Call
2044
+ * `configureCacheDir` first on sandboxed platforms.
2045
+ */
2046
+public func downloadModel(model: DemucsModel, listener: DownloadProgressListener)async throws {
2047
+ return
2048
+ try await uniffiRustCallAsync(
2049
+ rustFutureFunc: {
2050
+ uniffi_demucs_fn_func_download_model(FfiConverterTypeDemucsModel_lower(model),FfiConverterCallbackInterfaceDownloadProgressListener_lower(listener)
2051
+ )
2052
+ },
2053
+ pollFunc: ffi_demucs_rust_future_poll_void,
2054
+ completeFunc: ffi_demucs_rust_future_complete_void,
2055
+ freeFunc: ffi_demucs_rust_future_free_void,
2056
+ liftFunc: { $0 },
2057
+ errorHandler: FfiConverterTypeDemucsFfiError_lift
2058
+ )
2059
+}
2060
+/**
2061
+ * `DemucsEngine.separate` with progress reporting and cancellation.
2062
+ *
2063
+ * A free function because UniFFI 0.31 only supports callback interfaces as
2064
+ * free-function parameters.
2065
+ */
2066
+public func separateWithProgress(engine: DemucsEngine, left: [Float], right: [Float], sampleRate: UInt32, listener: SeparationProgressListener)async throws -> [StemResult] {
2067
+ return
2068
+ try await uniffiRustCallAsync(
2069
+ rustFutureFunc: {
2070
+ uniffi_demucs_fn_func_separate_with_progress(FfiConverterTypeDemucsEngine_lower(engine),FfiConverterSequenceFloat.lower(left),FfiConverterSequenceFloat.lower(right),FfiConverterUInt32.lower(sampleRate),FfiConverterCallbackInterfaceSeparationProgressListener_lower(listener)
2071
+ )
2072
+ },
2073
+ pollFunc: ffi_demucs_rust_future_poll_rust_buffer,
2074
+ completeFunc: ffi_demucs_rust_future_complete_rust_buffer,
2075
+ freeFunc: ffi_demucs_rust_future_free_rust_buffer,
2076
+ liftFunc: FfiConverterSequenceTypeStemResult.lift,
2077
+ errorHandler: FfiConverterTypeDemucsFfiError_lift
2078
+ )
2079
+}
2080
+
2081
+private enum InitializationResult {
2082
+ case ok
2083
+ case contractVersionMismatch
2084
+ case apiChecksumMismatch
2085
+}
2086
+// Use a global variable to perform the versioning checks. Swift ensures that
2087
+// the code inside is only computed once.
2088
+private let initializationResult: InitializationResult = {
2089
+ // Get the bindings contract version from our ComponentInterface
2090
+ let bindings_contract_version = 30
2091
+ // Get the scaffolding contract version by calling the into the dylib
2092
+ let scaffolding_contract_version = ffi_demucs_uniffi_contract_version()
2093
+ if bindings_contract_version != scaffolding_contract_version {
2094
+ return InitializationResult.contractVersionMismatch
2095
+ }
2096
+ if (uniffi_demucs_checksum_func_all_models() != 40632) {
2097
+ return InitializationResult.apiChecksumMismatch
2098
+ }
2099
+ if (uniffi_demucs_checksum_func_cached_model_path() != 59385) {
2100
+ return InitializationResult.apiChecksumMismatch
2101
+ }
2102
+ if (uniffi_demucs_checksum_func_configure_cache_dir() != 33315) {
2103
+ return InitializationResult.apiChecksumMismatch
2104
+ }
2105
+ if (uniffi_demucs_checksum_func_delete_cached_model() != 23501) {
2106
+ return InitializationResult.apiChecksumMismatch
2107
+ }
2108
+ if (uniffi_demucs_checksum_func_is_model_cached() != 9391) {
2109
+ return InitializationResult.apiChecksumMismatch
2110
+ }
2111
+ if (uniffi_demucs_checksum_func_model_metadata() != 64919) {
2112
+ return InitializationResult.apiChecksumMismatch
2113
+ }
2114
+ if (uniffi_demucs_checksum_func_num_chunks() != 27500) {
2115
+ return InitializationResult.apiChecksumMismatch
2116
+ }
2117
+ if (uniffi_demucs_checksum_func_download_model() != 37675) {
2118
+ return InitializationResult.apiChecksumMismatch
2119
+ }
2120
+ if (uniffi_demucs_checksum_func_separate_with_progress() != 6510) {
2121
+ return InitializationResult.apiChecksumMismatch
2122
+ }
2123
+ if (uniffi_demucs_checksum_method_demucsengine_is_loaded() != 28086) {
2124
+ return InitializationResult.apiChecksumMismatch
2125
+ }
2126
+ if (uniffi_demucs_checksum_method_demucsengine_load_model() != 54613) {
2127
+ return InitializationResult.apiChecksumMismatch
2128
+ }
2129
+ if (uniffi_demucs_checksum_method_demucsengine_loaded_model() != 45821) {
2130
+ return InitializationResult.apiChecksumMismatch
2131
+ }
2132
+ if (uniffi_demucs_checksum_method_demucsengine_separate() != 52086) {
2133
+ return InitializationResult.apiChecksumMismatch
2134
+ }
2135
+ if (uniffi_demucs_checksum_method_demucsengine_unload_model() != 24792) {
2136
+ return InitializationResult.apiChecksumMismatch
2137
+ }
2138
+ if (uniffi_demucs_checksum_method_demucsengine_warmup() != 20811) {
2139
+ return InitializationResult.apiChecksumMismatch
2140
+ }
2141
+ if (uniffi_demucs_checksum_constructor_demucsengine_new() != 51674) {
2142
+ return InitializationResult.apiChecksumMismatch
2143
+ }
2144
+ if (uniffi_demucs_checksum_method_downloadprogresslistener_on_progress() != 44819) {
2145
+ return InitializationResult.apiChecksumMismatch
2146
+ }
2147
+ if (uniffi_demucs_checksum_method_separationprogresslistener_on_progress() != 56005) {
2148
+ return InitializationResult.apiChecksumMismatch
2149
+ }
2150
+
2151
+ uniffiCallbackInitDownloadProgressListener()
2152
+ uniffiCallbackInitSeparationProgressListener()
2153
+ return InitializationResult.ok
2154
+}()
2155
+
2156
+// Make the ensure init function public so that other modules which have external type references to
2157
+// our types can call it.
2158
+public func uniffiEnsureDemucsInitialized() {
2159
+ switch initializationResult {
2160
+ case .ok:
2161
+ break
2162
+ case .contractVersionMismatch:
2163
+ fatalError("UniFFI contract version mismatch: try cleaning and rebuilding your project")
2164
+ case .apiChecksumMismatch:
2165
+ fatalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
2166
+ }
2167
+}
2168
+
2169
+// swiftlint:enable all
\ No newline at end of file