@swiftbrowser/native 0.18.3 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/README.md +19 -0
  2. package/bin/swiftbrowser-native.mjs +47 -0
  3. package/dist/bridge.d.ts +34 -7
  4. package/dist/bridge.d.ts.map +1 -1
  5. package/dist/bridge.js.map +1 -1
  6. package/dist/encoding.d.ts +13 -0
  7. package/dist/encoding.d.ts.map +1 -1
  8. package/dist/encoding.js +24 -0
  9. package/dist/encoding.js.map +1 -1
  10. package/dist/fetch.d.ts +10 -4
  11. package/dist/fetch.d.ts.map +1 -1
  12. package/dist/fetch.js +19 -11
  13. package/dist/fetch.js.map +1 -1
  14. package/dist/hostRequests.d.ts +22 -6
  15. package/dist/hostRequests.d.ts.map +1 -1
  16. package/dist/hostRequests.js +65 -13
  17. package/dist/hostRequests.js.map +1 -1
  18. package/dist/ios.d.ts +79 -0
  19. package/dist/ios.d.ts.map +1 -0
  20. package/dist/ios.js +181 -0
  21. package/dist/ios.js.map +1 -0
  22. package/dist/runtime.d.ts.map +1 -1
  23. package/dist/runtime.js +16 -7
  24. package/dist/runtime.js.map +1 -1
  25. package/dist/subtle.d.ts +1 -1
  26. package/dist/subtle.d.ts.map +1 -1
  27. package/dist/subtle.js +9 -5
  28. package/dist/subtle.js.map +1 -1
  29. package/dist/webSocket.d.ts +12 -5
  30. package/dist/webSocket.d.ts.map +1 -1
  31. package/dist/webSocket.js +24 -10
  32. package/dist/webSocket.js.map +1 -1
  33. package/package.json +7 -3
  34. package/src/bridge.ts +30 -7
  35. package/src/encoding.ts +22 -0
  36. package/src/fetch.ts +18 -13
  37. package/src/hostRequests.ts +72 -19
  38. package/src/ios.ts +253 -0
  39. package/src/runtime.ts +23 -8
  40. package/src/subtle.ts +10 -6
  41. package/src/webSocket.ts +27 -12
  42. package/swift/Packages/SwiftBrowserDSP/Package.swift +31 -0
  43. package/swift/Packages/SwiftBrowserDSP/README.md +42 -0
  44. package/swift/Packages/SwiftBrowserDSP/Sources/SwiftBrowserDSP/ProgramNode.swift +203 -0
  45. package/swift/Packages/SwiftBrowserDSP/Sources/SwiftBrowserDSPCore/Machine.swift +523 -0
  46. package/swift/Packages/SwiftBrowserDSP/Sources/SwiftBrowserDSPCore/Program.swift +188 -0
  47. package/swift/Packages/SwiftBrowserLocalModel/Package.swift +35 -0
  48. package/swift/Packages/SwiftBrowserLocalModel/README.md +66 -0
  49. package/swift/Packages/SwiftBrowserLocalModel/Sources/SwiftBrowserLocalModel/LlamaEngine.swift +223 -0
  50. package/swift/Packages/SwiftBrowserLocalModel/Sources/SwiftBrowserLocalModel/LocalLanguageModel.swift +409 -0
  51. package/swift/Sources/SwiftBrowserNative/Host/AudioEngineBridge.swift +921 -0
  52. package/swift/Sources/SwiftBrowserNative/Host/AudioEngineNodes.swift +70 -0
  53. package/swift/Sources/SwiftBrowserNative/Host/FilesBridge.swift +3 -3
  54. package/swift/Sources/SwiftBrowserNative/Host/HostBridge.swift +106 -28
  55. package/swift/Sources/SwiftBrowserNative/Host/HostRequestBridge.swift +43 -13
  56. package/swift/Sources/SwiftBrowserNative/Host/JSHost.swift +116 -0
  57. package/swift/Sources/SwiftBrowserNative/Host/JavaScriptCoreHost.swift +141 -2
  58. package/swift/Sources/SwiftBrowserNative/Host/LanguageModelBridge.swift +511 -0
  59. package/swift/Sources/SwiftBrowserNative/Host/LanguageModelProvider.swift +195 -0
  60. package/swift/Sources/SwiftBrowserNative/Host/WebSocketBridge.swift +24 -11
  61. package/swift/Sources/SwiftBrowserNative/Host/WorkerHost.swift +3 -2
  62. package/swift/Sources/SwiftBrowserNative/Views/ElementView.swift +1 -0
  63. package/swift/Sources/SwiftBrowserNative/Views/Kinds/Controls.swift +18 -1
  64. package/swift/Sources/SwiftBrowserNative/Views/Kinds/Lists.swift +41 -1
  65. package/swift/Sources/SwiftBrowserNative/Views/Kinds/More.swift +88 -17
  66. package/swift/Sources/SwiftBrowserNative/Views/Kinds/Navigation.swift +81 -20
  67. package/swift/Sources/SwiftBrowserNative/Views/Kinds/PinchTracker.swift +200 -0
  68. package/swift/Sources/SwiftBrowserNative/Views/Kinds/PopTap.swift +100 -0
  69. package/swift/Sources/SwiftBrowserNative/Views/Kinds/Stacks.swift +3 -2
  70. package/swift/Sources/SwiftBrowserNative/Views/StyleModifier.swift +4 -0
  71. package/swift/Sources/SwiftBrowserProtocol/Props.swift +26 -0
  72. package/swift/Sources/SwiftBrowserTree/OpTree.swift +25 -0
  73. package/wasm/SwiftBrowserNative.wasm +2 -2
@@ -0,0 +1,523 @@
1
+ import Foundation
2
+
3
+ /// The DSP machine: runs a `DSPProgram` for up to 16 voices, a lane each, in
4
+ /// blocks of up to 128 frames. It is the JavaScript machine
5
+ /// (packages/dsp/src/machine.ts) instruction for instruction, so a program
6
+ /// sounds the same in a native app and on a page; ParityTests hold the two
7
+ /// to the samples the JavaScript one renders.
8
+ ///
9
+ /// Real-time safe once made: `render` and the note and parameter calls
10
+ /// allocate nothing, take no lock and call nothing that might; every buffer
11
+ /// is sized from the program in `init`, and the program was checked there,
12
+ /// so no instruction can reach outside them. One thread at a time: the audio
13
+ /// thread renders and applies events, which another thread hands it
14
+ /// (ProgramNode.swift in SwiftBrowserDSP).
15
+ ///
16
+ /// Events apply at the next block. A note takes the lane already playing it,
17
+ /// else a free one, else the oldest released, else the oldest; a lane's gate
18
+ /// is up from its note on to its note off, or under the sustain pedal until
19
+ /// the pedal lifts, and it sounds while the gate is up and then while any
20
+ /// `adsr` in the program has not finished its release.
21
+ public final class DSPMachine: @unchecked Sendable {
22
+ public let program: DSPProgram
23
+ public let sampleRate: Float
24
+
25
+ private static let lanes = 16
26
+ private let registers: UnsafeMutablePointer<Float>
27
+ private let state: UnsafeMutablePointer<Float>
28
+ private let stateCount: Int
29
+ private let noise: UnsafeMutablePointer<UInt32>
30
+ private let noiseCount: Int
31
+ private let blockCode: UnsafeMutablePointer<Int32>
32
+ private let blockCount: Int
33
+ private let sampleCode: UnsafeMutablePointer<Int32>
34
+ private let sampleCount: Int
35
+ /// Each instance's builtin and where its state starts (in floats, lanes included; a noise instance's in `noise`).
36
+ private let instanceKinds: [DSPBuiltin]
37
+ private let instanceOffsets: [Int]
38
+ private let envelopeOffsets: [Int]
39
+ private let filterOffsets: [Int]
40
+ private let parameterRegisters: [Int]
41
+ private let parameterRanges: [(min: Float, max: Float)]
42
+ private let parameterIndices: [String: Int]
43
+ private let targets: UnsafeMutablePointer<Float>
44
+ private var snapped = true
45
+
46
+ private let laneNote: UnsafeMutablePointer<Int32>
47
+ private let laneGate: UnsafeMutablePointer<Float>
48
+ private let laneVelocity: UnsafeMutablePointer<Float>
49
+ private let laneHeld: UnsafeMutablePointer<Bool>
50
+ private let laneActive: UnsafeMutablePointer<Float>
51
+ private let laneAge: UnsafeMutablePointer<Double>
52
+ private let trigger: UnsafeMutablePointer<Float>
53
+ private var age: Double = 0
54
+ private var pedal = false
55
+ private var bend: Double = 0
56
+
57
+ public init(program: DSPProgram, sampleRate: Double) {
58
+ let L = Self.lanes
59
+ self.program = program
60
+ self.sampleRate = Float(sampleRate)
61
+ registers = .allocate(capacity: program.registers * L)
62
+ registers.initialize(repeating: 0, count: program.registers * L)
63
+ var kinds: [DSPBuiltin] = []
64
+ var offsets: [Int] = []
65
+ var envelopes: [Int] = []
66
+ var filters: [Int] = []
67
+ var words = 0
68
+ var noises = 0
69
+ for builtin in program.instances {
70
+ kinds.append(builtin)
71
+ if builtin == .noise {
72
+ offsets.append(noises * L)
73
+ noises += 1
74
+ } else {
75
+ offsets.append(words * L)
76
+ if builtin == .adsr { envelopes.append(words * L) }
77
+ if builtin == .lowpass || builtin == .highpass || builtin == .bandpass { filters.append(words * L) }
78
+ words += builtin.words
79
+ }
80
+ }
81
+ instanceKinds = kinds
82
+ instanceOffsets = offsets
83
+ envelopeOffsets = envelopes
84
+ filterOffsets = filters
85
+ stateCount = max(1, words) * L
86
+ state = .allocate(capacity: stateCount)
87
+ state.initialize(repeating: 0, count: stateCount)
88
+ noiseCount = max(1, noises) * L
89
+ noise = .allocate(capacity: noiseCount)
90
+ noise.initialize(repeating: 1, count: noiseCount)
91
+ (blockCode, blockCount) = Self.decode(program.block, offsets: offsets)
92
+ (sampleCode, sampleCount) = Self.decode(program.sample, offsets: offsets)
93
+ for constant in program.constants {
94
+ (registers + constant.register * L).update(repeating: constant.value, count: L)
95
+ }
96
+ registers.update(repeating: Float(sampleRate), count: L)
97
+ parameterRegisters = program.parameters.map(\.register)
98
+ parameterRanges = program.parameters.map { ($0.min, $0.max) }
99
+ parameterIndices = Dictionary(program.parameters.enumerated().map { ($1.name, $0) }, uniquingKeysWith: { first, _ in first })
100
+ targets = .allocate(capacity: max(1, program.parameters.count))
101
+ for (i, parameter) in program.parameters.enumerated() {
102
+ targets[i] = parameter.defaultValue
103
+ (registers + parameter.register * L).update(repeating: parameter.defaultValue, count: L)
104
+ }
105
+ laneNote = .allocate(capacity: L)
106
+ laneNote.initialize(repeating: -1, count: L)
107
+ laneGate = .allocate(capacity: L)
108
+ laneGate.initialize(repeating: 0, count: L)
109
+ laneVelocity = .allocate(capacity: L)
110
+ laneVelocity.initialize(repeating: 0, count: L)
111
+ laneHeld = .allocate(capacity: L)
112
+ laneHeld.initialize(repeating: false, count: L)
113
+ laneActive = .allocate(capacity: L)
114
+ laneActive.initialize(repeating: 0, count: L)
115
+ laneAge = .allocate(capacity: L)
116
+ laneAge.initialize(repeating: 0, count: L)
117
+ trigger = .allocate(capacity: L)
118
+ trigger.initialize(repeating: 0, count: L)
119
+ for lane in 0..<L { resetLane(lane) }
120
+ }
121
+
122
+ deinit {
123
+ for pointer in [registers, state, targets, laneGate, laneVelocity, laneActive, trigger] { pointer.deallocate() }
124
+ noise.deallocate()
125
+ blockCode.deallocate()
126
+ sampleCode.deallocate()
127
+ laneNote.deallocate()
128
+ laneHeld.deallocate()
129
+ laneAge.deallocate()
130
+ }
131
+
132
+ /// Instructions at a stride of 8 (op, destination, five operands, state offset), registers as offsets into the file.
133
+ private static func decode(_ code: [Int32], offsets: [Int]) -> (UnsafeMutablePointer<Int32>, Int) {
134
+ var out: [Int32] = []
135
+ var pc = 0
136
+ while pc < code.count {
137
+ let op = DSPOpcode(rawValue: code[pc])!
138
+ var slot = [Int32](repeating: 0, count: 8)
139
+ slot[0] = op.rawValue
140
+ slot[1] = code[pc + 1] * Int32(lanes)
141
+ for k in 0..<op.arity { slot[2 + k] = code[pc + 2 + k] * Int32(lanes) }
142
+ if op.builtin != nil { slot[7] = Int32(offsets[Int(code[pc + 2 + op.arity])]) }
143
+ out += slot
144
+ pc += 2 + op.arity + (op.builtin == nil ? 0 : 1)
145
+ }
146
+ let pointer = UnsafeMutablePointer<Int32>.allocate(capacity: max(8, out.count))
147
+ pointer.initialize(repeating: 0, count: max(8, out.count))
148
+ out.withUnsafeBufferPointer { pointer.update(from: $0.baseAddress!, count: out.count) }
149
+ return (pointer, out.count / 8)
150
+ }
151
+
152
+ // MARK: Events
153
+
154
+ /// The index `setParameter(at:_:)` takes for a parameter's name: look it up off the audio thread.
155
+ public func parameterIndex(_ name: String) -> Int? {
156
+ parameterIndices[name]
157
+ }
158
+
159
+ /// A parameter, clamped to its range; it glides there over about 20 ms.
160
+ public func setParameter(at index: Int, _ value: Float) {
161
+ guard index >= 0, index < parameterRegisters.count, value.isFinite else { return }
162
+ targets[index] = Swift.min(Swift.max(value, parameterRanges[index].min), parameterRanges[index].max)
163
+ }
164
+
165
+ /// MIDI note on: `velocity` 1 … 127 (0 is a note off).
166
+ public func noteOn(_ note: Int32, velocity: Int32) {
167
+ if velocity <= 0 {
168
+ noteOff(note)
169
+ return
170
+ }
171
+ let voices = program.voices
172
+ var lane = -1
173
+ for l in 0..<voices where lane < 0 && laneNote[l] == note && laneGate[l] > 0.5 { lane = l }
174
+ var fresh = false
175
+ if lane < 0 {
176
+ for l in 0..<voices where lane < 0 && laneActive[l] == 0 { lane = l }
177
+ fresh = lane >= 0
178
+ }
179
+ if lane < 0 {
180
+ // Steal: the oldest released voice, else the oldest.
181
+ var best = -1
182
+ for l in 0..<voices where laneGate[l] <= 0.5 && !laneHeld[l] && (best < 0 || laneAge[l] < laneAge[best]) { best = l }
183
+ if best < 0 { for l in 0..<voices where best < 0 || laneAge[l] < laneAge[best] { best = l } }
184
+ lane = best
185
+ fresh = true
186
+ }
187
+ if fresh { resetLane(lane) }
188
+ laneNote[lane] = note
189
+ laneGate[lane] = 1
190
+ laneHeld[lane] = false
191
+ laneVelocity[lane] = Float(Double(Swift.min(127, velocity)) / 127)
192
+ laneActive[lane] = 1
193
+ trigger[lane] += 1
194
+ age += 1
195
+ laneAge[lane] = age
196
+ }
197
+
198
+ public func noteOff(_ note: Int32) {
199
+ for l in 0..<program.voices where laneNote[l] == note && laneGate[l] > 0.5 {
200
+ // Under the pedal the gate stays up until it lifts.
201
+ if pedal { laneHeld[l] = true } else { laneGate[l] = 0 }
202
+ }
203
+ }
204
+
205
+ /// 64 the sustain pedal, 120 all sound off, 123 all notes off.
206
+ public func controller(_ number: Int32, value: Int32) {
207
+ let L = Self.lanes
208
+ switch number {
209
+ case 64:
210
+ pedal = value >= 64
211
+ if !pedal {
212
+ for l in 0..<L where laneHeld[l] { laneGate[l] = 0 }
213
+ laneHeld.update(repeating: false, count: L)
214
+ }
215
+ case 123:
216
+ laneGate.update(repeating: 0, count: L)
217
+ laneHeld.update(repeating: false, count: L)
218
+ case 120:
219
+ for l in 0..<L {
220
+ laneGate[l] = 0
221
+ laneHeld[l] = false
222
+ laneActive[l] = 0
223
+ resetLane(l)
224
+ }
225
+ default:
226
+ break
227
+ }
228
+ }
229
+
230
+ /// The pitch wheel, 0 … 16383, 8192 centered: ±2 semitones.
231
+ public func pitchBend(_ value: Int32) {
232
+ bend = Double(Swift.min(16383, Swift.max(0, value)) - 8192) / 8192 * 2
233
+ }
234
+
235
+ /// Silences every voice at once.
236
+ public func reset() {
237
+ controller(120, value: 0)
238
+ }
239
+
240
+ /// How many voices sound now.
241
+ public var sounding: Int {
242
+ (0..<Self.lanes).reduce(0) { $0 + (laneActive[$1] != 0 ? 1 : 0) }
243
+ }
244
+
245
+ // MARK: Rendering
246
+
247
+ /// Writes `frames` mono frames to `out`, in blocks of up to 128.
248
+ public func render(into out: UnsafeMutablePointer<Float>, frames: Int) {
249
+ var done = 0
250
+ while done < frames {
251
+ let n = Swift.min(DSPProgram.blockFrames, frames - done)
252
+ block(out + done, n)
253
+ done += n
254
+ }
255
+ }
256
+
257
+ private func resetLane(_ l: Int) {
258
+ let L = Self.lanes
259
+ for entry in program.state { registers[entry.register * L + l] = entry.initial }
260
+ for (i, kind) in instanceKinds.enumerated() {
261
+ let base = instanceOffsets[i] + l
262
+ if kind == .noise {
263
+ let seed = UInt32(truncatingIfNeeded: i + 1) &* 2_654_435_761 &+ UInt32(truncatingIfNeeded: l + 1) &* 2_246_822_519
264
+ noise[base] = seed == 0 ? 1 : seed
265
+ continue
266
+ }
267
+ for w in 0..<kind.words { state[base + w * L] = 0 }
268
+ if kind == .adsr {
269
+ state[base + 4 * L] = .nan
270
+ state[base + 6 * L] = .nan
271
+ } else if kind.words == 8 {
272
+ state[base + 2 * L] = .nan
273
+ }
274
+ }
275
+ }
276
+
277
+ private func block(_ out: UnsafeMutablePointer<Float>, _ n: Int) {
278
+ let L = Self.lanes
279
+ let R = registers
280
+ let sr = sampleRate
281
+ // Parameters glide toward their targets, about 20 ms.
282
+ let alpha = snapped ? Float(1) : 1 - exp(-Float(n) / (0.02 * sr))
283
+ snapped = false
284
+ for (i, register) in parameterRegisters.enumerated() {
285
+ let at = R + register * L
286
+ at.update(repeating: at[0] + (targets[i] - at[0]) * alpha, count: L)
287
+ }
288
+ var any = false
289
+ for l in 0..<L where laneActive[l] != 0 { any = true }
290
+ guard any else {
291
+ out.update(repeating: 0, count: n)
292
+ return
293
+ }
294
+ for l in 0..<L {
295
+ let note = laneNote[l]
296
+ R[1 * L + l] = note >= 0 ? Float(440 * Foundation.pow(2, (Double(note) - 69 + bend) / 12)) : 0
297
+ R[2 * L + l] = laneGate[l]
298
+ R[3 * L + l] = laneVelocity[l]
299
+ R[4 * L + l] = note >= 0 ? Float(note) : 0
300
+ }
301
+ run(blockCode, blockCount)
302
+ let o = R + program.output * L
303
+ var check: Float = 0
304
+ for i in 0..<n {
305
+ run(sampleCode, sampleCount)
306
+ var sum: Float = 0
307
+ for l in 0..<L { sum += o[l] * laneActive[l] }
308
+ out[i] = sum
309
+ check += sum
310
+ }
311
+ guard check.isFinite else {
312
+ // A voice went to infinity or NaN: silence the block and start every voice over.
313
+ out.update(repeating: 0, count: n)
314
+ for l in 0..<L {
315
+ laneActive[l] = 0
316
+ laneGate[l] = 0
317
+ laneHeld[l] = false
318
+ resetLane(l)
319
+ }
320
+ return
321
+ }
322
+ // Denormals in the filters' integrators would slow every frame after.
323
+ for offset in filterOffsets {
324
+ for k in offset..<(offset + 2 * L) where Swift.abs(state[k]) < 1e-20 { state[k] = 0 }
325
+ }
326
+ // A released voice sounds until its envelopes finish.
327
+ for l in 0..<L where laneActive[l] != 0 && laneGate[l] <= 0.5 && !laneHeld[l] {
328
+ var sounding = false
329
+ for offset in envelopeOffsets where state[offset + l] != 0 { sounding = true }
330
+ if !sounding { laneActive[l] = 0 }
331
+ }
332
+ }
333
+
334
+ @inline(__always)
335
+ private static func blep(_ t: Float, _ dt: Float) -> Float {
336
+ if t < dt {
337
+ let x = t / dt
338
+ return x + x - x * x - 1
339
+ }
340
+ if t > 1 - dt {
341
+ let x = (t - 1) / dt
342
+ return x * x + x + x + 1
343
+ }
344
+ return 0
345
+ }
346
+
347
+ // The interpreter: one instruction at a time, every lane per instruction.
348
+ private func run(_ code: UnsafeMutablePointer<Int32>, _ count: Int) {
349
+ let L = Self.lanes
350
+ let R = registers
351
+ let S = state
352
+ let N = noise
353
+ let sr = sampleRate
354
+ var at = 0
355
+ let end = count * 8
356
+ while at < end {
357
+ let op = code[at]
358
+ let d = R + Int(code[at + 1])
359
+ let a = R + Int(code[at + 2])
360
+ let b = R + Int(code[at + 3])
361
+ let c = R + Int(code[at + 4])
362
+ switch op {
363
+ case 0: for l in 0..<L { d[l] = a[l] }
364
+ case 1: for l in 0..<L { d[l] = a[l] + b[l] }
365
+ case 2: for l in 0..<L { d[l] = a[l] - b[l] }
366
+ case 3: for l in 0..<L { d[l] = a[l] * b[l] }
367
+ case 4: for l in 0..<L { d[l] = a[l] / b[l] }
368
+ case 5: for l in 0..<L { d[l] = a[l].truncatingRemainder(dividingBy: b[l]) }
369
+ case 6: for l in 0..<L { d[l] = -a[l] }
370
+ case 7: for l in 0..<L { d[l] = Swift.min(a[l], b[l]) }
371
+ case 8: for l in 0..<L { d[l] = Swift.max(a[l], b[l]) }
372
+ case 9: for l in 0..<L { d[l] = Swift.abs(a[l]) }
373
+ case 10: for l in 0..<L { d[l] = a[l].rounded(.down) }
374
+ case 11: for l in 0..<L { d[l] = a[l].rounded(.up) }
375
+ case 12: for l in 0..<L { d[l] = (a[l] + 0.5).rounded(.down) }
376
+ case 13: for l in 0..<L { d[l] = a[l].squareRoot() }
377
+ case 14: for l in 0..<L { d[l] = Foundation.sin(a[l]) }
378
+ case 15: for l in 0..<L { d[l] = Foundation.cos(a[l]) }
379
+ case 16: for l in 0..<L { d[l] = Foundation.tan(a[l]) }
380
+ case 17: for l in 0..<L { d[l] = Foundation.exp(a[l]) }
381
+ case 18: for l in 0..<L { d[l] = Foundation.log(a[l]) }
382
+ case 19: for l in 0..<L { d[l] = Foundation.pow(a[l], b[l]) }
383
+ case 20: for l in 0..<L { d[l] = Foundation.tanh(a[l]) }
384
+ case 21: for l in 0..<L { d[l] = a[l] < b[l] ? 1 : 0 }
385
+ case 22: for l in 0..<L { d[l] = a[l] <= b[l] ? 1 : 0 }
386
+ case 23: for l in 0..<L { d[l] = a[l] > b[l] ? 1 : 0 }
387
+ case 24: for l in 0..<L { d[l] = a[l] >= b[l] ? 1 : 0 }
388
+ case 25: for l in 0..<L { d[l] = a[l] == b[l] ? 1 : 0 }
389
+ case 26: for l in 0..<L { d[l] = a[l] != b[l] ? 1 : 0 }
390
+ case 27: for l in 0..<L { d[l] = a[l] != 0 && b[l] != 0 ? 1 : 0 }
391
+ case 28: for l in 0..<L { d[l] = a[l] != 0 || b[l] != 0 ? 1 : 0 }
392
+ case 29: for l in 0..<L { d[l] = a[l] == 0 ? 1 : 0 }
393
+ case 30: for l in 0..<L { d[l] = a[l] != 0 ? b[l] : c[l] }
394
+ case 31: for l in 0..<L { d[l] = Swift.min(Swift.max(a[l], b[l]), c[l]) }
395
+ case 32: for l in 0..<L { d[l] = a[l] + (b[l] - a[l]) * c[l] }
396
+ case 33: for l in 0..<L { d[l] = a[l] - a[l].rounded(.down) }
397
+ case 34: for l in 0..<L { d[l] = a[l] > 0 ? 1 : a[l] < 0 ? -1 : 0 }
398
+ case 35: for l in 0..<L { d[l] = Foundation.atan(a[l]) }
399
+ case 40, 41, 42, 43, 44:
400
+ // Oscillators: the output from the phase now, then the phase steps by freq / sampleRate.
401
+ let s = S + Int(code[at + 7])
402
+ for l in 0..<L {
403
+ let p = s[l]
404
+ let dt = a[l] / sr
405
+ var v: Float
406
+ switch op {
407
+ case 40: v = p
408
+ case 41: v = Foundation.sin(2 * Float.pi * p)
409
+ case 42:
410
+ v = 2 * p - 1
411
+ if dt > 0 { v -= Self.blep(p, dt) }
412
+ case 43:
413
+ let w = Swift.min(Swift.max(b[l], 0), 1)
414
+ v = p < w ? 1 : -1
415
+ if dt > 0 {
416
+ let q = p + 1 - w
417
+ v += Self.blep(p, dt) - Self.blep(q - q.rounded(.down), dt)
418
+ }
419
+ default: v = 1 - 4 * Swift.abs(p - 0.5)
420
+ }
421
+ d[l] = v
422
+ let next = p + dt
423
+ s[l] = next - next.rounded(.down)
424
+ }
425
+ case 45:
426
+ let s = N + Int(code[at + 7])
427
+ for l in 0..<L {
428
+ var x = s[l]
429
+ x ^= x << 13
430
+ x ^= x >> 17
431
+ x ^= x << 5
432
+ s[l] = x
433
+ d[l] = Float(Double(x) / 4_294_967_296 * 2 - 1)
434
+ }
435
+ case 46:
436
+ // adsr(gate, attack, decay, sustain, release): stage, level, trigger, gate before, decay time and coefficient, release time and coefficient.
437
+ let s = S + Int(code[at + 7])
438
+ let sustainIn = R + Int(code[at + 5])
439
+ let releaseIn = R + Int(code[at + 6])
440
+ for l in 0..<L {
441
+ let gate = a[l]
442
+ var stage = s[l]
443
+ var level = s[L + l]
444
+ if s[2 * L + l] != trigger[l] {
445
+ s[2 * L + l] = trigger[l]
446
+ if gate > 0.5 { stage = 1 }
447
+ } else if gate > 0.5 && s[3 * L + l] <= 0.5 {
448
+ stage = 1
449
+ }
450
+ if gate <= 0.5 && stage >= 1 && stage <= 3 { stage = 4 }
451
+ s[3 * L + l] = gate
452
+ let sustain = Swift.min(Swift.max(sustainIn[l], 0), 1)
453
+ if stage == 1 {
454
+ level += 1 / Swift.max(1, b[l] * sr)
455
+ if level >= 1 {
456
+ level = 1
457
+ stage = 2
458
+ }
459
+ } else if stage == 2 {
460
+ let time = c[l]
461
+ if !(s[4 * L + l] == time) {
462
+ s[4 * L + l] = time
463
+ s[5 * L + l] = Foundation.exp(-9.2 / Swift.max(1, time * sr))
464
+ }
465
+ level = sustain + (level - sustain) * s[5 * L + l]
466
+ if level - sustain < 0.0001 { stage = 3 }
467
+ } else if stage == 3 {
468
+ level = sustain
469
+ } else if stage == 4 {
470
+ let time = releaseIn[l]
471
+ if !(s[6 * L + l] == time) {
472
+ s[6 * L + l] = time
473
+ s[7 * L + l] = Foundation.exp(-9.2 / Swift.max(1, time * sr))
474
+ }
475
+ level *= s[7 * L + l]
476
+ if level < 0.0001 {
477
+ level = 0
478
+ stage = 0
479
+ }
480
+ } else {
481
+ level = 0
482
+ }
483
+ s[l] = stage
484
+ s[L + l] = level
485
+ d[l] = level
486
+ }
487
+ case 47, 48, 49:
488
+ // A state-variable filter (Simper's form): resonance 0 … 1.
489
+ let s = S + Int(code[at + 7])
490
+ for l in 0..<L {
491
+ let cutoff = Swift.min(Swift.max(b[l], 10), 0.49 * sr)
492
+ let resonance = Swift.min(Swift.max(c[l], 0), 0.98)
493
+ if !(s[2 * L + l] == cutoff && s[3 * L + l] == resonance) {
494
+ s[2 * L + l] = cutoff
495
+ s[3 * L + l] = resonance
496
+ let g = Foundation.tan(Float.pi * cutoff / sr)
497
+ let k = 2 - 2 * resonance
498
+ let a1 = 1 / (1 + g * (g + k))
499
+ s[4 * L + l] = a1
500
+ s[5 * L + l] = g * a1
501
+ s[6 * L + l] = g * g * a1
502
+ s[7 * L + l] = k
503
+ }
504
+ let a1 = s[4 * L + l]
505
+ let a2 = s[5 * L + l]
506
+ let a3 = s[6 * L + l]
507
+ let ic1 = s[l]
508
+ let ic2 = s[L + l]
509
+ let x = a[l]
510
+ let v3 = x - ic2
511
+ let v1 = a1 * ic1 + a2 * v3
512
+ let v2 = ic2 + a2 * ic1 + a3 * v3
513
+ s[l] = 2 * v1 - ic1
514
+ s[L + l] = 2 * v2 - ic2
515
+ d[l] = op == 47 ? v2 : op == 49 ? v1 : x - s[7 * L + l] * v1 - v2
516
+ }
517
+ default:
518
+ break
519
+ }
520
+ at += 8
521
+ }
522
+ }
523
+ }