@aelionsdk/audio 1.2.0-rc.5 → 1.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
@@ -5,10 +5,10 @@ Audio scheduling and deterministic PCM processing primitives for AelionSDK.
5
5
  ## Install
6
6
 
7
7
  ```bash
8
- npm install @aelionsdk/audio@next
8
+ npm install @aelionsdk/audio
9
9
  ```
10
10
 
11
- `next` currently resolves to `1.2.0-rc.5`. Product applications should prefer
11
+ `latest` currently resolves to `1.2.0`. Product applications should prefer
12
12
  `@aelionsdk/sdk`; use this package directly when building a custom audio host,
13
13
  analysis pipeline or renderer integration.
14
14
 
@@ -1 +1 @@
1
- {"version":3,"file":"transferable-worklet-clock.d.ts","sourceRoot":"","sources":["../src/transferable-worklet-clock.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,OAAO,EACL,oBAAoB,EACpB,KAAK,4BAA4B,EAClC,MAAM,6BAA6B,CAAC;AAoBrC,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,OAAO,CAAC,EAAE,YAAY,CAAC;IAChC,gEAAgE;IAChE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC;IAClC,4EAA4E;IAC5E,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;CACrC;AAED,qBAAa,6BAA8B,YAAW,UAAU;;IAC9D,SAAgB,OAAO,EAAE,YAAY,CAAC;IACtC,SAAgB,KAAK,EAAE,oBAAoB,CAAC;gBAazB,OAAO,GAAE,6BAAkC;IAa9D,IAAW,QAAQ,IAAI,OAAO,CAE7B;IAED,IAAW,WAAW,IAAI,OAAO,CAEhC;IAED,IAAW,UAAU,IAAI,MAAM,CAE9B;IAED,IAAW,UAAU,IAAI,uBAAuB,GAAG,SAAS,CAE3D;IAEY,UAAU,CACrB,iBAAiB,SAA2C,GAC3D,OAAO,CAAC,IAAI,CAAC;IAwDH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAM5B,kBAAkB,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO;IAkB1C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAItB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAI7B,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAY5B,KAAK,IAAI,MAAM;IAQf,QAAQ,IAAI,4BAA4B;IAIxC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAyBhC;AAED,MAAM,MAAM,0BAA0B,GAClC;IAAE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,uBAAuB,CAAA;CAAE,GAC1E;IAAE,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,iCAAiC,CAAA;CAAE,CAAC;AAEhG,wBAAgB,2BAA2B,CAAC,WAAW,EAAE;IACvD,QAAQ,CAAC,mBAAmB,EAAE,OAAO,CAAC;IACtC,QAAQ,CAAC,0BAA0B,EAAE,OAAO,CAAC;CAC9C,GAAG,0BAA0B,CAI7B"}
1
+ {"version":3,"file":"transferable-worklet-clock.d.ts","sourceRoot":"","sources":["../src/transferable-worklet-clock.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,OAAO,EACL,oBAAoB,EACpB,KAAK,4BAA4B,EAClC,MAAM,6BAA6B,CAAC;AAoBrC,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,OAAO,CAAC,EAAE,YAAY,CAAC;IAChC,gEAAgE;IAChE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC;IAClC,4EAA4E;IAC5E,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;CACrC;AAED,qBAAa,6BAA8B,YAAW,UAAU;;IAC9D,SAAgB,OAAO,EAAE,YAAY,CAAC;IACtC,SAAgB,KAAK,EAAE,oBAAoB,CAAC;gBAczB,OAAO,GAAE,6BAAkC;IAa9D,IAAW,QAAQ,IAAI,OAAO,CAE7B;IAED,IAAW,WAAW,IAAI,OAAO,CAEhC;IAED,IAAW,UAAU,IAAI,MAAM,CAE9B;IAED,IAAW,UAAU,IAAI,uBAAuB,GAAG,SAAS,CAE3D;IAEY,UAAU,CACrB,iBAAiB,SAA2C,GAC3D,OAAO,CAAC,IAAI,CAAC;IAyDH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAO5B,kBAAkB,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO;IAkB1C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAKtB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAkB7B,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAY5B,KAAK,IAAI,MAAM;IAQf,QAAQ,IAAI,4BAA4B;IAIxC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CA0BhC;AAED,MAAM,MAAM,0BAA0B,GAClC;IAAE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,uBAAuB,CAAA;CAAE,GAC1E;IAAE,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,iCAAiC,CAAA;CAAE,CAAC;AAEhG,wBAAgB,2BAA2B,CAAC,WAAW,EAAE;IACvD,QAAQ,CAAC,mBAAmB,EAAE,OAAO,CAAC;IACtC,QAAQ,CAAC,0BAA0B,EAAE,OAAO,CAAC;CAC9C,GAAG,0BAA0B,CAI7B"}
@@ -19,6 +19,7 @@ export class TransferableAudioWorkletClock {
19
19
  queue;
20
20
  #ownsContext;
21
21
  #node;
22
+ #outputConnected = false;
22
23
  #initializeTask;
23
24
  #disposeTask;
24
25
  #disposed = false;
@@ -97,6 +98,7 @@ export class TransferableAudioWorkletClock {
97
98
  node.port.start();
98
99
  node.connect(this.context.destination);
99
100
  connected = true;
101
+ this.#outputConnected = true;
100
102
  this.#throwIfInitializationStale(generation);
101
103
  this.#contextOriginTime = this.context.currentTime;
102
104
  this.#node = node;
@@ -110,6 +112,7 @@ export class TransferableAudioWorkletClock {
110
112
  }
111
113
  async start() {
112
114
  await this.initialize();
115
+ this.#connectOutput();
113
116
  this.#node?.port.postMessage({ type: 'start', generation: this.#generation });
114
117
  await this.context.resume();
115
118
  }
@@ -130,13 +133,28 @@ export class TransferableAudioWorkletClock {
130
133
  return true;
131
134
  }
132
135
  async pause() {
136
+ this.#disconnectOutput();
133
137
  if (this.context.state === 'running')
134
138
  await this.context.suspend();
135
139
  }
136
140
  async resume() {
141
+ this.#connectOutput();
137
142
  if (this.context.state !== 'running')
138
143
  await this.context.resume();
139
144
  }
145
+ #connectOutput() {
146
+ if (this.#node === undefined || this.#outputConnected)
147
+ return;
148
+ this.#node.connect(this.context.destination);
149
+ this.#outputConnected = true;
150
+ }
151
+ #disconnectOutput() {
152
+ if (this.#node === undefined || !this.#outputConnected)
153
+ return;
154
+ this.#node.disconnect();
155
+ this.#outputConnected = false;
156
+ this.queue.flush();
157
+ }
140
158
  seek(timeUs) {
141
159
  if (!Number.isSafeInteger(timeUs) || timeUs < 0) {
142
160
  throw new RangeError('Seek target must be a non-negative safe integer microsecond value');
@@ -166,6 +184,7 @@ export class TransferableAudioWorkletClock {
166
184
  this.queue.close();
167
185
  this.#node?.port.postMessage({ type: 'close' });
168
186
  this.#node?.disconnect();
187
+ this.#outputConnected = false;
169
188
  this.#node?.port.close();
170
189
  this.#node = undefined;
171
190
  if (this.#ownsContext && this.context.state !== 'closed')
@@ -1 +1 @@
1
- {"version":3,"file":"worklet-clock.d.ts","sourceRoot":"","sources":["../src/worklet-clock.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,OAAO,EAAE,mBAAmB,EAAE,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC;AAE1E,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;CACpC;AAED,MAAM,MAAM,eAAe,GACvB;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACrD;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACpD;IAAE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACzD;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACrD;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtF,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,OAAO,CAAC,EAAE,YAAY,CAAC;IAChC,gEAAgE;IAChE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC;IAClC,4EAA4E;IAC5E,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;CACrC;AAED,MAAM,MAAM,wBAAwB,GAAG,iBAAiB,GAAG,aAAa,CAAC;AAEzE,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,wBAAwB,EAClC,OAAO,EAAE,wBAAwB,GAChC,aAAa,GAAG,SAAS,GAAG,SAAS,CAIvC;AAoBD,qBAAa,iBAAkB,YAAW,UAAU;;IAClD,SAAgB,OAAO,EAAE,YAAY,CAAC;IACtC,SAAgB,IAAI,EAAE,mBAAmB,CAAC;gBAuBvB,OAAO,GAAE,iBAAsB;IAkBlD,IAAW,QAAQ,IAAI,OAAO,CAE7B;IAED,IAAW,WAAW,IAAI,OAAO,CAEhC;IAED,IAAW,UAAU,IAAI,gBAAgB,GAAG,SAAS,CAEpD;IAED,IAAW,UAAU,IAAI,MAAM,CAE9B;IAEY,UAAU,CAAC,iBAAiB,SAA0B,GAAG,OAAO,CAAC,IAAI,CAAC;IAsDtE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAMtB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAKtB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAO7B,SAAS,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,GAAG,MAAM,IAAI;IAKjE,YAAY,CAAC,MAAM,SAAI,GAAG,MAAM;IAYhC,KAAK,IAAI,MAAM;IAQf,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CA+BhC"}
1
+ {"version":3,"file":"worklet-clock.d.ts","sourceRoot":"","sources":["../src/worklet-clock.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,OAAO,EAAE,mBAAmB,EAAE,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC;AAE1E,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;CACpC;AAED,MAAM,MAAM,eAAe,GACvB;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACrD;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACpD;IAAE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACzD;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACrD;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtF,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,OAAO,CAAC,EAAE,YAAY,CAAC;IAChC,gEAAgE;IAChE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC;IAClC,4EAA4E;IAC5E,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;CACrC;AAED,MAAM,MAAM,wBAAwB,GAAG,iBAAiB,GAAG,aAAa,CAAC;AAEzE,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,wBAAwB,EAClC,OAAO,EAAE,wBAAwB,GAChC,aAAa,GAAG,SAAS,GAAG,SAAS,CAIvC;AAoBD,qBAAa,iBAAkB,YAAW,UAAU;;IAClD,SAAgB,OAAO,EAAE,YAAY,CAAC;IACtC,SAAgB,IAAI,EAAE,mBAAmB,CAAC;gBAwBvB,OAAO,GAAE,iBAAsB;IAkBlD,IAAW,QAAQ,IAAI,OAAO,CAE7B;IAED,IAAW,WAAW,IAAI,OAAO,CAEhC;IAED,IAAW,UAAU,IAAI,gBAAgB,GAAG,SAAS,CAEpD;IAED,IAAW,UAAU,IAAI,MAAM,CAE9B;IAEY,UAAU,CAAC,iBAAiB,SAA0B,GAAG,OAAO,CAAC,IAAI,CAAC;IAuDtE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAOtB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAMtB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IA0B7B,SAAS,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,GAAG,MAAM,IAAI;IAKjE,YAAY,CAAC,MAAM,SAAI,GAAG,MAAM;IAYhC,KAAK,IAAI,MAAM;IAQf,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAgChC"}
@@ -28,6 +28,7 @@ export class AudioWorkletClock {
28
28
  #initializeTask;
29
29
  #disposeTask;
30
30
  #ownsContext;
31
+ #outputConnected = false;
31
32
  #disposed = false;
32
33
  #lifecycleGeneration = 0;
33
34
  #lastReport;
@@ -114,6 +115,7 @@ export class AudioWorkletClock {
114
115
  // module-loading latency appears as permanent A/V drift.
115
116
  node.connect(this.context.destination);
116
117
  connected = true;
118
+ this.#outputConnected = true;
117
119
  this.#throwIfInitializationStale(generation);
118
120
  this.#contextOriginTime = this.context.currentTime;
119
121
  this.#node = node;
@@ -127,20 +129,41 @@ export class AudioWorkletClock {
127
129
  }
128
130
  async start() {
129
131
  await this.initialize();
132
+ this.#connectOutput();
130
133
  await withTimeout(this.context.resume(), 5_000, 'AudioContext resume');
131
134
  this.#emit('started');
132
135
  }
133
136
  async pause() {
137
+ this.#disconnectOutput();
134
138
  if (this.context.state === 'running')
135
139
  await this.context.suspend();
136
140
  this.#emit('paused');
137
141
  }
138
142
  async resume() {
143
+ this.#connectOutput();
139
144
  if (this.context.state !== 'running') {
140
145
  await withTimeout(this.context.resume(), 5_000, 'AudioContext resume');
141
146
  }
142
147
  this.#emit('resumed');
143
148
  }
149
+ #connectOutput() {
150
+ if (this.#node === undefined || this.#outputConnected)
151
+ return;
152
+ this.#node.connect(this.context.destination);
153
+ this.#outputConnected = true;
154
+ }
155
+ #disconnectOutput() {
156
+ if (this.#node === undefined || !this.#outputConnected)
157
+ return;
158
+ // Disconnect only. A pause does not move the playback position, so the
159
+ // buffered frames are still the ones that come next and resuming should
160
+ // continue from them. Dropping them here would also reset the ring's play
161
+ // and underrun counters, which are reported as session telemetry, and cost
162
+ // a full refill on every resume. An edit while paused is what makes those
163
+ // frames stale, and `AelionPlayer.invalidate` handles that case.
164
+ this.#node.disconnect();
165
+ this.#outputConnected = false;
166
+ }
144
167
  subscribe(listener) {
145
168
  this.#listeners.add(listener);
146
169
  return () => this.#listeners.delete(listener);
@@ -171,6 +194,7 @@ export class AudioWorkletClock {
171
194
  this.context.removeEventListener('statechange', this.#onStateChange);
172
195
  this.ring.close();
173
196
  this.#node?.disconnect();
197
+ this.#outputConnected = false;
174
198
  this.#node?.port.close();
175
199
  this.#node = undefined;
176
200
  if (this.#ownsContext && this.context.state !== 'closed')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aelionsdk/audio",
3
- "version": "1.2.0-rc.5",
3
+ "version": "1.2.0",
4
4
  "description": "AudioWorklet clock, PCM buffering and audio mixing for AelionSDK",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -34,8 +34,8 @@
34
34
  "provenance": true
35
35
  },
36
36
  "dependencies": {
37
- "@aelionsdk/core": "1.2.0-rc.5",
38
- "@aelionsdk/render-ir": "1.2.0-rc.5"
37
+ "@aelionsdk/core": "1.2.0",
38
+ "@aelionsdk/render-ir": "1.2.0"
39
39
  },
40
40
  "scripts": {
41
41
  "build": "tsc -b",