@aelionsdk/audio 0.1.0-beta.1

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 (42) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +7 -0
  3. package/dist/device-state.d.ts +28 -0
  4. package/dist/device-state.d.ts.map +1 -0
  5. package/dist/device-state.js +119 -0
  6. package/dist/index.d.ts +11 -0
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/index.js +10 -0
  9. package/dist/ir-mixer.d.ts +30 -0
  10. package/dist/ir-mixer.d.ts.map +1 -0
  11. package/dist/ir-mixer.js +235 -0
  12. package/dist/pcm-message-player.worklet.d.ts +2 -0
  13. package/dist/pcm-message-player.worklet.d.ts.map +1 -0
  14. package/dist/pcm-message-player.worklet.js +119 -0
  15. package/dist/pcm-player.worklet.d.ts +2 -0
  16. package/dist/pcm-player.worklet.d.ts.map +1 -0
  17. package/dist/pcm-player.worklet.js +36 -0
  18. package/dist/pcm-ring.d.ts +39 -0
  19. package/dist/pcm-ring.d.ts.map +1 -0
  20. package/dist/pcm-ring.js +174 -0
  21. package/dist/processing.d.ts +106 -0
  22. package/dist/processing.d.ts.map +1 -0
  23. package/dist/processing.js +386 -0
  24. package/dist/resampler.d.ts +22 -0
  25. package/dist/resampler.d.ts.map +1 -0
  26. package/dist/resampler.js +99 -0
  27. package/dist/time-stretch.d.ts +30 -0
  28. package/dist/time-stretch.d.ts.map +1 -0
  29. package/dist/time-stretch.js +180 -0
  30. package/dist/transferable-pcm-queue.d.ts +30 -0
  31. package/dist/transferable-pcm-queue.d.ts.map +1 -0
  32. package/dist/transferable-pcm-queue.js +73 -0
  33. package/dist/transferable-worklet-clock.d.ts +51 -0
  34. package/dist/transferable-worklet-clock.d.ts.map +1 -0
  35. package/dist/transferable-worklet-clock.js +185 -0
  36. package/dist/video-scheduler.d.ts +39 -0
  37. package/dist/video-scheduler.d.ts.map +1 -0
  38. package/dist/video-scheduler.js +111 -0
  39. package/dist/worklet-clock.d.ts +55 -0
  40. package/dist/worklet-clock.d.ts.map +1 -0
  41. package/dist/worklet-clock.js +193 -0
  42. package/package.json +44 -0
@@ -0,0 +1,39 @@
1
+ export type PcmRingState = 'open' | 'ended' | 'closed';
2
+ export interface PcmRingDescriptor {
3
+ readonly buffer: SharedArrayBuffer;
4
+ readonly capacityFrames: number;
5
+ readonly channelCount: number;
6
+ readonly sampleRate: number;
7
+ }
8
+ export interface PcmRingSnapshot {
9
+ readonly capacityFrames: number;
10
+ readonly availableReadFrames: number;
11
+ readonly availableWriteFrames: number;
12
+ readonly playedFrames: number;
13
+ readonly underrunFrames: number;
14
+ readonly state: PcmRingState;
15
+ }
16
+ export declare class SharedPcmRingBuffer {
17
+ #private;
18
+ readonly capacityFrames: number;
19
+ readonly channelCount: number;
20
+ readonly sampleRate: number;
21
+ readonly buffer: SharedArrayBuffer;
22
+ static allocate(capacityFrames: number, channelCount: number, sampleRate: number): SharedPcmRingBuffer;
23
+ constructor(descriptor: PcmRingDescriptor);
24
+ descriptor(): PcmRingDescriptor;
25
+ availableReadFrames(): number;
26
+ availableWriteFrames(): number;
27
+ writeInterleaved(input: Float32Array): number;
28
+ readPlanar(outputs: readonly Float32Array[]): number;
29
+ end(): void;
30
+ close(): void;
31
+ /**
32
+ * Drops queued PCM and starts a new transport generation without reallocating
33
+ * the bounded SharedArrayBuffer. The AudioWorklet may race one render quantum;
34
+ * generation-aware scheduling treats that quantum as belonging to the old seek.
35
+ */
36
+ flush(): void;
37
+ snapshot(): PcmRingSnapshot;
38
+ }
39
+ //# sourceMappingURL=pcm-ring.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pcm-ring.d.ts","sourceRoot":"","sources":["../src/pcm-ring.ts"],"names":[],"mappings":"AAQA,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;AAEvD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;IACnC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;IACtC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;CAC9B;AAcD,qBAAa,mBAAmB;;IAI9B,SAAgB,cAAc,EAAE,MAAM,CAAC;IACvC,SAAgB,YAAY,EAAE,MAAM,CAAC;IACrC,SAAgB,UAAU,EAAE,MAAM,CAAC;IACnC,SAAgB,MAAM,EAAE,iBAAiB,CAAC;WAE5B,QAAQ,CACpB,cAAc,EAAE,MAAM,EACtB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,GACjB,mBAAmB;gBAYH,UAAU,EAAE,iBAAiB;IAoBzC,UAAU,IAAI,iBAAiB;IAS/B,mBAAmB,IAAI,MAAM;IAO7B,oBAAoB,IAAI,MAAM;IAI9B,gBAAgB,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM;IAqB7C,UAAU,CAAC,OAAO,EAAE,SAAS,YAAY,EAAE,GAAG,MAAM;IA6CpD,GAAG,IAAI,IAAI;IAIX,KAAK,IAAI,IAAI;IAUpB;;;;OAIG;IACI,KAAK,IAAI,IAAI;IAWb,QAAQ,IAAI,eAAe;CAWnC"}
@@ -0,0 +1,174 @@
1
+ const READ_FRAME = 0;
2
+ const WRITE_FRAME = 1;
3
+ const PLAYED_FRAME = 2;
4
+ const UNDERRUN_FRAME = 3;
5
+ const STATE = 4;
6
+ const HEADER_LENGTH = 8;
7
+ const HEADER_BYTES = HEADER_LENGTH * Int32Array.BYTES_PER_ELEMENT;
8
+ function assertPositiveInteger(value, name) {
9
+ if (!Number.isSafeInteger(value) || value <= 0) {
10
+ throw new RangeError(`${name} must be a positive safe integer`);
11
+ }
12
+ }
13
+ function stateName(value) {
14
+ if (value === 1)
15
+ return 'ended';
16
+ if (value === 2)
17
+ return 'closed';
18
+ return 'open';
19
+ }
20
+ export class SharedPcmRingBuffer {
21
+ #header;
22
+ #samples;
23
+ capacityFrames;
24
+ channelCount;
25
+ sampleRate;
26
+ buffer;
27
+ static allocate(capacityFrames, channelCount, sampleRate) {
28
+ assertPositiveInteger(capacityFrames, 'capacityFrames');
29
+ assertPositiveInteger(channelCount, 'channelCount');
30
+ assertPositiveInteger(sampleRate, 'sampleRate');
31
+ const sampleCount = capacityFrames * channelCount;
32
+ if (!Number.isSafeInteger(sampleCount))
33
+ throw new RangeError('PCM ring is too large');
34
+ const buffer = new SharedArrayBuffer(HEADER_BYTES + sampleCount * Float32Array.BYTES_PER_ELEMENT);
35
+ return new SharedPcmRingBuffer({ buffer, capacityFrames, channelCount, sampleRate });
36
+ }
37
+ constructor(descriptor) {
38
+ assertPositiveInteger(descriptor.capacityFrames, 'capacityFrames');
39
+ assertPositiveInteger(descriptor.channelCount, 'channelCount');
40
+ assertPositiveInteger(descriptor.sampleRate, 'sampleRate');
41
+ const expectedBytes = HEADER_BYTES +
42
+ descriptor.capacityFrames * descriptor.channelCount * Float32Array.BYTES_PER_ELEMENT;
43
+ if (descriptor.buffer.byteLength !== expectedBytes) {
44
+ throw new RangeError(`PCM ring byteLength must be ${expectedBytes}; received ${descriptor.buffer.byteLength}`);
45
+ }
46
+ this.buffer = descriptor.buffer;
47
+ this.capacityFrames = descriptor.capacityFrames;
48
+ this.channelCount = descriptor.channelCount;
49
+ this.sampleRate = descriptor.sampleRate;
50
+ this.#header = new Int32Array(this.buffer, 0, HEADER_LENGTH);
51
+ this.#samples = new Float32Array(this.buffer, HEADER_BYTES);
52
+ }
53
+ descriptor() {
54
+ return {
55
+ buffer: this.buffer,
56
+ capacityFrames: this.capacityFrames,
57
+ channelCount: this.channelCount,
58
+ sampleRate: this.sampleRate,
59
+ };
60
+ }
61
+ availableReadFrames() {
62
+ // A closed transport has no readable ownership even if an AudioWorklet
63
+ // render quantum raced the close and still holds stale cursor values.
64
+ if (stateName(Atomics.load(this.#header, STATE)) === 'closed')
65
+ return 0;
66
+ return Atomics.load(this.#header, WRITE_FRAME) - Atomics.load(this.#header, READ_FRAME);
67
+ }
68
+ availableWriteFrames() {
69
+ return this.capacityFrames - this.availableReadFrames();
70
+ }
71
+ writeInterleaved(input) {
72
+ if (input.length % this.channelCount !== 0) {
73
+ throw new RangeError('Interleaved PCM length must be divisible by channelCount');
74
+ }
75
+ if (stateName(Atomics.load(this.#header, STATE)) !== 'open')
76
+ return 0;
77
+ const requestedFrames = input.length / this.channelCount;
78
+ const frames = Math.min(requestedFrames, this.availableWriteFrames());
79
+ const writeFrame = Atomics.load(this.#header, WRITE_FRAME);
80
+ for (let frame = 0; frame < frames; frame += 1) {
81
+ const ringFrame = (writeFrame + frame) % this.capacityFrames;
82
+ for (let channel = 0; channel < this.channelCount; channel += 1) {
83
+ const source = frame * this.channelCount + channel;
84
+ const target = ringFrame * this.channelCount + channel;
85
+ this.#samples[target] = input[source] ?? 0;
86
+ }
87
+ }
88
+ Atomics.store(this.#header, WRITE_FRAME, writeFrame + frames);
89
+ Atomics.notify(this.#header, WRITE_FRAME);
90
+ return frames;
91
+ }
92
+ readPlanar(outputs) {
93
+ if (outputs.length !== this.channelCount) {
94
+ throw new RangeError('Output plane count must equal channelCount');
95
+ }
96
+ const requestedFrames = outputs[0]?.length ?? 0;
97
+ if (outputs.some(output => output.length !== requestedFrames)) {
98
+ throw new RangeError('All output planes must have the same frame count');
99
+ }
100
+ const readFrame = Atomics.load(this.#header, READ_FRAME);
101
+ const frames = Math.min(requestedFrames, this.availableReadFrames());
102
+ for (let frame = 0; frame < frames; frame += 1) {
103
+ const ringFrame = (readFrame + frame) % this.capacityFrames;
104
+ for (let channel = 0; channel < this.channelCount; channel += 1) {
105
+ const source = ringFrame * this.channelCount + channel;
106
+ const plane = outputs[channel];
107
+ if (plane !== undefined)
108
+ plane[frame] = this.#samples[source] ?? 0;
109
+ }
110
+ }
111
+ for (const output of outputs)
112
+ output.fill(0, frames);
113
+ // close() may publish the terminal state while this AudioWorklet quantum is
114
+ // copying samples. Never overwrite its drained cursor or mutate terminal
115
+ // counters after observing that state.
116
+ if (stateName(Atomics.load(this.#header, STATE)) !== 'closed') {
117
+ // A seek flush or close may advance READ_FRAME while this Worklet quantum
118
+ // is copying samples. Commit only if the cursor is still ours; otherwise
119
+ // silence the stale quantum and leave the terminal/new-generation cursor
120
+ // untouched.
121
+ const committed = Atomics.compareExchange(this.#header, READ_FRAME, readFrame, readFrame + frames) ===
122
+ readFrame;
123
+ if (!committed) {
124
+ for (const output of outputs)
125
+ output.fill(0);
126
+ return 0;
127
+ }
128
+ Atomics.add(this.#header, PLAYED_FRAME, requestedFrames);
129
+ if (frames < requestedFrames) {
130
+ Atomics.add(this.#header, UNDERRUN_FRAME, requestedFrames - frames);
131
+ }
132
+ }
133
+ Atomics.notify(this.#header, READ_FRAME);
134
+ return frames;
135
+ }
136
+ end() {
137
+ Atomics.compareExchange(this.#header, STATE, 0, 1);
138
+ }
139
+ close() {
140
+ Atomics.store(this.#header, STATE, 2);
141
+ // Closing is terminal: queued PCM must not remain retained or appear in a
142
+ // post-disposal resource snapshot. Publish the terminal state first so a
143
+ // racing reader observes zero buffered frames throughout teardown.
144
+ Atomics.store(this.#header, READ_FRAME, Atomics.load(this.#header, WRITE_FRAME));
145
+ Atomics.notify(this.#header, READ_FRAME);
146
+ Atomics.notify(this.#header, WRITE_FRAME);
147
+ }
148
+ /**
149
+ * Drops queued PCM and starts a new transport generation without reallocating
150
+ * the bounded SharedArrayBuffer. The AudioWorklet may race one render quantum;
151
+ * generation-aware scheduling treats that quantum as belonging to the old seek.
152
+ */
153
+ flush() {
154
+ if (stateName(Atomics.load(this.#header, STATE)) !== 'open') {
155
+ throw new Error('Only an open PCM ring can be flushed');
156
+ }
157
+ const writeFrame = Atomics.load(this.#header, WRITE_FRAME);
158
+ Atomics.store(this.#header, READ_FRAME, writeFrame);
159
+ Atomics.store(this.#header, PLAYED_FRAME, 0);
160
+ Atomics.store(this.#header, UNDERRUN_FRAME, 0);
161
+ Atomics.notify(this.#header, READ_FRAME);
162
+ }
163
+ snapshot() {
164
+ const availableReadFrames = this.availableReadFrames();
165
+ return {
166
+ capacityFrames: this.capacityFrames,
167
+ availableReadFrames,
168
+ availableWriteFrames: this.capacityFrames - availableReadFrames,
169
+ playedFrames: Atomics.load(this.#header, PLAYED_FRAME),
170
+ underrunFrames: Atomics.load(this.#header, UNDERRUN_FRAME),
171
+ state: stateName(Atomics.load(this.#header, STATE)),
172
+ };
173
+ }
174
+ }
@@ -0,0 +1,106 @@
1
+ export interface AudioChannelMatrix {
2
+ readonly inputChannels: number;
3
+ readonly outputChannels: number;
4
+ /** Row-major output × input gain matrix. */
5
+ readonly gains: readonly number[];
6
+ }
7
+ export declare function applyChannelMatrix(input: Float32Array, matrix: AudioChannelMatrix): Float32Array;
8
+ export interface SidechainDuckerOptions {
9
+ readonly sampleRate: number;
10
+ readonly channelCount: number;
11
+ readonly thresholdDb: number;
12
+ readonly reductionDb: number;
13
+ readonly attackUs: number;
14
+ readonly releaseUs: number;
15
+ readonly lookaheadUs: number;
16
+ }
17
+ export declare class SidechainDucker {
18
+ #private;
19
+ constructor(options: SidechainDuckerOptions);
20
+ get latencyFrames(): number;
21
+ reset(): void;
22
+ process(program: Float32Array, sidechain: Float32Array): Float32Array;
23
+ }
24
+ export interface LoudnessReport {
25
+ readonly integratedLufs: number;
26
+ readonly ungatedLufs: number;
27
+ readonly truePeakDbtp: number;
28
+ readonly samplePeakDbfs: number;
29
+ readonly gatedBlocks: number;
30
+ readonly totalBlocks: number;
31
+ }
32
+ /** Deterministic EBU-style block gating with 4× linear true-peak estimation. */
33
+ export declare function analyzeLoudness(pcm: Float32Array, sampleRate: number, channelCount: number): LoudnessReport;
34
+ export interface TruePeakLimiterOptions {
35
+ readonly sampleRate: number;
36
+ readonly channelCount: number;
37
+ readonly ceilingDbtp?: number;
38
+ readonly lookaheadUs?: number;
39
+ readonly releaseUs?: number;
40
+ }
41
+ export declare class TruePeakLimiter {
42
+ #private;
43
+ constructor(options: TruePeakLimiterOptions);
44
+ get latencyFrames(): number;
45
+ process(input: Float32Array): Float32Array;
46
+ }
47
+ /** Incremental variant of analyzeLoudness for bounded-memory export prepasses. */
48
+ export declare class StreamingLoudnessAnalyzer {
49
+ #private;
50
+ constructor(sampleRate: number, channelCount: number);
51
+ process(pcm: Float32Array): void;
52
+ finish(): LoudnessReport;
53
+ }
54
+ export interface WaveformPeak {
55
+ readonly startFrame: number;
56
+ readonly frameCount: number;
57
+ readonly min: readonly number[];
58
+ readonly max: readonly number[];
59
+ readonly rms: readonly number[];
60
+ }
61
+ export interface WaveformPeakResult {
62
+ readonly sampleRate: number;
63
+ readonly channelCount: number;
64
+ readonly totalFrames: number;
65
+ readonly windowFrames: number;
66
+ readonly peaks: readonly WaveformPeak[];
67
+ }
68
+ export interface BuildWaveformPeaksOptions {
69
+ readonly sampleRate: number;
70
+ readonly channelCount: number;
71
+ readonly totalFrames: number;
72
+ readonly windowFrames?: number;
73
+ readonly maxPoints?: number;
74
+ readonly readFrames: (startFrame: number, frameCount: number, signal?: AbortSignal) => Promise<Float32Array>;
75
+ readonly signal?: AbortSignal;
76
+ readonly onProgress?: (progress: number) => void;
77
+ }
78
+ export declare function buildWaveformPeaks(options: BuildWaveformPeaksOptions): Promise<WaveformPeakResult>;
79
+ export interface AudioFrameRange {
80
+ readonly startFrame: number;
81
+ readonly frameCount: number;
82
+ }
83
+ export interface SilenceDetectionResult {
84
+ readonly sampleRate: number;
85
+ readonly channelCount: number;
86
+ readonly totalFrames: number;
87
+ readonly thresholdDb: number;
88
+ readonly nonSilent: readonly AudioFrameRange[];
89
+ readonly silent: readonly AudioFrameRange[];
90
+ readonly removedFrames: number;
91
+ }
92
+ export interface DetectSilenceOptions {
93
+ readonly sampleRate: number;
94
+ readonly channelCount: number;
95
+ readonly totalFrames: number;
96
+ readonly thresholdDb?: number;
97
+ readonly minimumSilenceUs?: number;
98
+ readonly paddingUs?: number;
99
+ readonly windowFrames?: number;
100
+ readonly readFrames: (startFrame: number, frameCount: number, signal?: AbortSignal) => Promise<Float32Array>;
101
+ readonly signal?: AbortSignal;
102
+ readonly onProgress?: (progress: number) => void;
103
+ }
104
+ /** Detect audible ranges with bounded reads and deterministic window merging. */
105
+ export declare function detectSilence(options: DetectSilenceOptions): Promise<SilenceDetectionResult>;
106
+ //# sourceMappingURL=processing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"processing.d.ts","sourceRoot":"","sources":["../src/processing.ts"],"names":[],"mappings":"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"}