@swiftbrowser/native 0.25.0 → 0.26.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@swiftbrowser/native",
3
- "version": "0.25.0",
3
+ "version": "0.26.0",
4
4
  "type": "module",
5
5
  "description": "Run a @swiftbrowser/react app natively: the runtime a JavaScriptCore-hosted app needs (timers, console, fetch and the other web globals over the SwiftBrowser Native bridge), the `run` entry that renders into the native SwiftUI renderer, and the bundler that builds app.js for the Xcode target.",
6
6
  "repository": {
@@ -63,8 +63,8 @@
63
63
  },
64
64
  "dependencies": {
65
65
  "@babel/core": "^7.29.7",
66
- "@swiftbrowser/react": "0.25.0",
67
- "@swiftbrowser/web": "0.25.0",
66
+ "@swiftbrowser/react": "0.26.0",
67
+ "@swiftbrowser/web": "0.26.0",
68
68
  "esbuild": "^0.28.2",
69
69
  "react-refresh": "^0.17.0"
70
70
  },
@@ -42,7 +42,9 @@ import Foundation
42
42
  /// Block processing: a block runs in chunks of 16 frames, each instruction over every frame of the chunk for every
43
43
  /// sounding lane, but for a stream's serial part (feedback through state, which it schedules when it loads the
44
44
  /// program), which runs frame by frame within the chunk. Unlike the JavaScript machine's, a register holds a frame's lanes side by side,
45
- /// then the next frame's, so the loops over lanes stay vector loops; the results are the same.
45
+ /// then the next frame's, so the loops over lanes stay vector loops; the results are the same. The lanes side by side are
46
+ /// those that run: the sounding voices' (up to the highest), or the master stage's one, so every instruction runs over
47
+ /// one span of memory, however many voices sound.
46
48
  public final class DSPMachine: @unchecked Sendable {
47
49
  public let program: DSPProgram
48
50
  public let sampleRate: Float
@@ -50,8 +52,8 @@ public final class DSPMachine: @unchecked Sendable {
50
52
  private static let lanes = 16
51
53
  /// Frames a chunk has: each instruction runs over a chunk's frames together (block processing).
52
54
  private static let frames = 16
53
- /// The registers, each `width` values: a chunk's frames one after another, each its lanes (as many as the
54
- /// program has voices) side by side, so an instruction runs over lanes as a SIMD vector and a builtin's state
55
+ /// The registers, each `width` values: a chunk's frames one after another, each its lanes (as many as run: the
56
+ /// sounding voices', or the master stage's one) side by side, so an instruction runs over lanes as a SIMD vector and a builtin's state
55
57
  /// follows its lanes; a state register's value is its lane's at the first frame.
56
58
  private let registers: UnsafeMutablePointer<Float>
57
59
  private let width: Int
@@ -1533,7 +1535,8 @@ public final class DSPMachine: @unchecked Sendable {
1533
1535
  return
1534
1536
  }
1535
1537
  if any {
1536
- let V = program.voices
1538
+ // A frame's lanes side by side, as many as sound this block (`run`).
1539
+ let V = lanes
1537
1540
  for l in 0..<V {
1538
1541
  let note = laneNote[l]
1539
1542
  let freq = note >= 0 ? Float(440 * Foundation.pow(2, (Double(note) - 69 + bend) / 12)) : 0
@@ -1556,19 +1559,20 @@ public final class DSPMachine: @unchecked Sendable {
1556
1559
  l >= 0 ? laneVelocity[l] : 0,
1557
1560
  note >= 0 ? Float(note) : 0,
1558
1561
  ]
1559
- let V = program.voices
1560
- for (i, value) in values.enumerated() { for k in 0..<F { R[(7 + i) * W + k * V] = value } }
1562
+ // The master stage's one lane: a frame after another.
1563
+ for (i, value) in values.enumerated() { for k in 0..<F { R[(7 + i) * W + k] = value } }
1561
1564
  }
1562
1565
  let o = R + program.output * W
1563
1566
  let or = R + (program.outputRight ?? program.output) * W
1564
- let V = program.voices
1567
+ let V = Swift.max(lanes, 1)
1565
1568
  var check: Float = 0
1566
1569
  // A chunk of up to 16 frames at a time: each instruction over all of them, the serial part frame by frame.
1567
1570
  var chunk = 0
1568
1571
  while chunk < n {
1569
1572
  let fc = Swift.min(F, n - chunk)
1573
+ let start = beat
1570
1574
  for k in 0..<fc {
1571
- for l in 0..<Swift.max(lanes, 1) { R[6 * W + k * V + l] = Float(beat) }
1575
+ for l in 0..<V { R[6 * W + k * V + l] = Float(beat) }
1572
1576
  beat += beatStep
1573
1577
  }
1574
1578
  if any {
@@ -1589,8 +1593,8 @@ public final class DSPMachine: @unchecked Sendable {
1589
1593
  }
1590
1594
  }
1591
1595
  if let master {
1592
- R[master.inputs[0] * W + k * V] = leftSum
1593
- R[master.inputs[1] * W + k * V] = rightSum
1596
+ R[master.inputs[0] * W + k] = leftSum
1597
+ R[master.inputs[1] * W + k] = rightSum
1594
1598
  } else {
1595
1599
  if let right {
1596
1600
  out[chunk + k] = leftSum
@@ -1602,14 +1606,20 @@ public final class DSPMachine: @unchecked Sendable {
1602
1606
  }
1603
1607
  }
1604
1608
  if let master {
1609
+ // The beat in the master stage's one lane: a frame after another, added up as the voices' was.
1610
+ var at = start
1611
+ for k in 0..<fc {
1612
+ R[6 * W + k] = Float(at)
1613
+ at += beatStep
1614
+ }
1605
1615
  run(masterCode, 0..<masterSerial.lowerBound, lanes: 1, trigger: masterTrigger, frames: fc)
1606
1616
  if !masterSerial.isEmpty {
1607
1617
  for k in 0..<fc { run(masterCode, masterSerial, lanes: 1, trigger: masterTrigger, frames: 1, frame: k) }
1608
1618
  }
1609
1619
  run(masterCode, masterSerial.upperBound..<masterCount, lanes: 1, trigger: masterTrigger, frames: fc)
1610
1620
  for k in 0..<fc {
1611
- let leftSum = R[master.outputs[0] * W + k * V]
1612
- let rightSum = R[master.outputs[1] * W + k * V]
1621
+ let leftSum = R[master.outputs[0] * W + k]
1622
+ let rightSum = R[master.outputs[1] * W + k]
1613
1623
  if let right {
1614
1624
  out[chunk + k] = leftSum
1615
1625
  right[chunk + k] = rightSum
@@ -1679,7 +1689,9 @@ public final class DSPMachine: @unchecked Sendable {
1679
1689
  let sr = sampleRate
1680
1690
  let serial = frame >= 0
1681
1691
  let fc = serial ? 1 : frames
1682
- let V = program.voices
1692
+ // A frame's lanes side by side, as many as run (the sounding voices', or the master stage's one): every
1693
+ // instruction then runs over one span of memory.
1694
+ let V = Swift.max(lanes, 1)
1683
1695
  let shift = serial ? frame * V : 0
1684
1696
  // A stateless instruction: every lane's frames at once (the chunk's last ones, past fc, go unread), the
1685
1697
  // sounding lanes of each frame; in the serial part, the one frame's.