@aeonentertainment/mixer 0.1.0 → 0.2.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/README.md CHANGED
@@ -15,7 +15,7 @@ Each [release](https://github.com/aeonentertainment/aeon-mixer/releases) carries
15
15
  Depend on its URL, and the lockfile pins its hash:
16
16
 
17
17
  ```bash
18
- npm install https://github.com/aeonentertainment/aeon-mixer/releases/download/v0.1.0/aeonentertainment-mixer-0.1.0.tgz
18
+ npm install https://github.com/aeonentertainment/aeon-mixer/releases/download/v0.2.0/aeonentertainment-mixer-0.2.0.tgz
19
19
  ```
20
20
 
21
21
  ## Use
@@ -58,6 +58,10 @@ await engine.close();
58
58
  - **`rtpReturn`** sends the mix to mediasoup's PlainTransport as 10 ms Opus with in-band FEC.
59
59
  `host` is an IP address, never a name.
60
60
  - **Reactions** play through `engine.reactions.play` between songs and during them.
61
+ - **The timer engine**, `openEngine({ output: { timer: true } })`, is for a box with no sound
62
+ card. It opens no device; its own thread renders a block at each deadline on the OS's
63
+ monotonic clock, and the mix leaves on `rtpReturn`. `measure-clock` prints its timing:
64
+ `cargo run --release -p devices --bin measure-clock` in `native/`.
61
65
  - **The offline engine**, `openEngine({ output: { offline: true } })`, opens no device and
62
66
  renders only when its caller runs `engine.pump(blocks)`. The tests run on it.
63
67
 
package/dist/index.d.mts CHANGED
@@ -19,7 +19,7 @@ declare class Engine$1 {
19
19
  */
20
20
  createMixer(kinds: Array<string>, rtpReturn?: RtpReturnInput | undefined | null): Mixer$1;
21
21
  get output(): OutputInfo$1;
22
- /** The outputs this OS offers, the default marked. Empty on the offline clock. */
22
+ /** The outputs this OS offers, the default marked. Empty on the offline and timer clocks. */
23
23
  outputs(): Array<OutputEntry>;
24
24
  /** Offline clock only: renders `blocks` blocks and returns them as interleaved stereo. */
25
25
  pump(blocks: number): Float32Array;
@@ -144,9 +144,8 @@ interface NoteInput {
144
144
  endFrame: number;
145
145
  }
146
146
  interface OpenOptions {
147
- /** The offline driver, pumped from JavaScript, instead of a device. */
148
- offline: boolean;
149
- /** An id from `outputs`, or the default output. */
147
+ clock: 'offline' | 'timer' | 'device';
148
+ /** A device clock's output: an id from `outputs`, or the default output. */
150
149
  device?: string;
151
150
  periodFrames: number;
152
151
  /** The jitter buffer's playout delay for every `rtp` and `l16` slot. */
@@ -211,9 +210,15 @@ type Capability = "guideVocal" | "key" | "speed" | "seek" | "shortVersion" | "pa
211
210
  type IngestKind = "rtp" | "l16" | "push";
212
211
  type StemKind = "instrumental" | "guideVocals";
213
212
  interface OpenEngineOptions {
213
+ /**
214
+ * A device; `timer` for a box with no sound card, whose own thread renders on the OS's clock
215
+ * and whose mix leaves only on a mixer's `rtpReturn`; `offline` for tests, which pump it.
216
+ */
214
217
  output: {
215
218
  device?: string;
216
219
  periodFrames?: 64 | 128;
220
+ } | {
221
+ timer: true;
217
222
  } | {
218
223
  offline: true;
219
224
  };
@@ -424,8 +429,8 @@ export declare class Mixer {
424
429
  /** An engine on the test clock. Its caller pumps it; nothing plays. */
425
430
  type OfflineEngine = Engine & Required<Pick<Engine, "pump">>;
426
431
  /**
427
- * Opens the engine for the life of the process: the device, or the offline driver, running the
428
- * silent graph until a mixer starts.
432
+ * Opens the engine for the life of the process: the device, the timer clock on a box with no
433
+ * sound card, or the offline driver, running the silent graph until a mixer starts.
429
434
  */
430
435
  export declare function openEngine(options: OpenEngineOptions & {
431
436
  output: {
package/dist/index.mjs CHANGED
@@ -546,16 +546,21 @@ var Engine = class {
546
546
  };
547
547
  if ("offline" in options.output) {
548
548
  this.#native = new NativeEngine({
549
- offline: true,
549
+ clock: "offline",
550
550
  periodFrames: 128,
551
551
  playoutDelayFrames
552
552
  }, deliver);
553
553
  this.pump = (blocks) => this.#native.pump(integerIn("blocks", blocks, 1, 1 << 20));
554
- } else {
554
+ } else if ("timer" in options.output) this.#native = new NativeEngine({
555
+ clock: "timer",
556
+ periodFrames: 128,
557
+ playoutDelayFrames
558
+ }, deliver);
559
+ else {
555
560
  const { device, periodFrames = 128 } = options.output;
556
561
  if (periodFrames !== 64 && periodFrames !== 128) throw new RangeError(`periodFrames must be 64 or 128, got ${String(periodFrames)}`);
557
562
  this.#native = new NativeEngine({
558
- offline: false,
563
+ clock: "device",
559
564
  periodFrames,
560
565
  playoutDelayFrames,
561
566
  ...device === void 0 ? {} : { device }
@@ -31,7 +31,7 @@ export declare class Engine {
31
31
  */
32
32
  createMixer(kinds: Array<string>, rtpReturn?: RtpReturnInput | undefined | null): Mixer
33
33
  get output(): OutputInfo
34
- /** The outputs this OS offers, the default marked. Empty on the offline clock. */
34
+ /** The outputs this OS offers, the default marked. Empty on the offline and timer clocks. */
35
35
  outputs(): Array<OutputEntry>
36
36
  /** Offline clock only: renders `blocks` blocks and returns them as interleaved stereo. */
37
37
  pump(blocks: number): Float32Array
@@ -105,6 +105,16 @@ export interface BackingInput {
105
105
  speed: number
106
106
  }
107
107
 
108
+ /** What drives the audio thread. */
109
+ export declare const enum ClockKind {
110
+ /** The offline driver, pumped from JavaScript. */
111
+ Offline = 'offline',
112
+ /** The timer clock, for a box with no sound card: no device, and nothing to pump. */
113
+ Timer = 'timer',
114
+ /** An OS output. */
115
+ Device = 'device',
116
+ }
117
+
108
118
  export interface CorrectorInput {
109
119
  enabled: boolean
110
120
  strength: number
@@ -137,9 +147,8 @@ export interface NoteInput {
137
147
  }
138
148
 
139
149
  export interface OpenOptions {
140
- /** The offline driver, pumped from JavaScript, instead of a device. */
141
- offline: boolean
142
- /** An id from `outputs`, or the default output. */
150
+ clock: 'offline' | 'timer' | 'device'
151
+ /** A device clock's output: an id from `outputs`, or the default output. */
143
152
  device?: string
144
153
  periodFrames: number
145
154
  /** The jitter buffer's playout delay for every `rtp` and `l16` slot. */
@@ -838,3 +838,4 @@ module.exports = nativeBinding
838
838
  module.exports.BackingRender = nativeBinding.BackingRender
839
839
  module.exports.Engine = nativeBinding.Engine
840
840
  module.exports.Mixer = nativeBinding.Mixer
841
+ module.exports.ClockKind = nativeBinding.ClockKind
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aeonentertainment/mixer",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Low-latency LAN audio mixer for Aeon Karaoke: phone and house mics, a backing track, one mix to the room.",
5
5
  "bugs": {
6
6
  "url": "https://github.com/aeonentertainment/aeon-mixer/issues"