@ai-ecoverse/pi-audio 1.2.0 → 1.3.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 +2 -0
- package/dist/convert.js +294 -0
- package/dist/convert.js.map +7 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +2 -2
- package/dist/types/convert.d.ts +5 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/worklet/convert.d.ts +30 -0
- package/dist/worklet/convert.js +80 -0
- package/dist/worklet/convert.js.map +7 -0
- package/package.json +5 -1
package/README.md
CHANGED
|
@@ -21,6 +21,8 @@ addAudioCounters(total, usage);
|
|
|
21
21
|
|
|
22
22
|
pi-audio does not apply that patch. Hosts such as slicc-agent record monkeypatches in `patches/patches.json`.
|
|
23
23
|
|
|
24
|
+
`convertAudio` and `convertAudioSource` convert between `AudioFormat`s: PCM16, float32, G.711 μ-law and A-law, mono and stereo, sample rate, and PCM16 WAV. Opus, MP3 and FLAC pass through only when the format does not change. `encodeAudioBase64` and `decodeAudioBase64` are the wire helpers for JSON protocols. `AudioChunk.data` stays binary. The same converter runs in an AudioWorklet from `@ai-ecoverse/pi-audio/worklet` (`AUDIO_CONVERT_PROCESSOR`, `registerAudioConvertWorklet`). Adapters declare `inputFormats` and `outputFormats` and do not resample on their own.
|
|
25
|
+
|
|
24
26
|
## Development
|
|
25
27
|
|
|
26
28
|
```sh
|
package/dist/convert.js
ADDED
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
const compressed = /* @__PURE__ */ new Set(["opus", "mp3", "flac"]);
|
|
2
|
+
const LAW_BIAS = 132;
|
|
3
|
+
const base64Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
4
|
+
function byteAt(data, index) {
|
|
5
|
+
const byte = data[index];
|
|
6
|
+
return byte === void 0 ? 0 : byte;
|
|
7
|
+
}
|
|
8
|
+
function symbolAt(index) {
|
|
9
|
+
return base64Alphabet.charAt(index);
|
|
10
|
+
}
|
|
11
|
+
function encodeAudioBase64(data) {
|
|
12
|
+
let encoded = "";
|
|
13
|
+
for (let index = 0; index < data.length; index += 3) {
|
|
14
|
+
const second = data[index + 1];
|
|
15
|
+
const third = data[index + 2];
|
|
16
|
+
const triple = byteAt(data, index) << 16 | byteAt(data, index + 1) << 8 | byteAt(data, index + 2);
|
|
17
|
+
encoded += symbolAt(triple >> 18 & 63);
|
|
18
|
+
encoded += symbolAt(triple >> 12 & 63);
|
|
19
|
+
encoded += second === void 0 ? "=" : symbolAt(triple >> 6 & 63);
|
|
20
|
+
encoded += third === void 0 ? "=" : symbolAt(triple & 63);
|
|
21
|
+
}
|
|
22
|
+
return encoded;
|
|
23
|
+
}
|
|
24
|
+
function codeAt(value, index) {
|
|
25
|
+
const character = value[index];
|
|
26
|
+
if (character === void 0) return -1;
|
|
27
|
+
const code = base64Alphabet.indexOf(character);
|
|
28
|
+
if (code < 0) throw new Error("Invalid base64 audio");
|
|
29
|
+
return code;
|
|
30
|
+
}
|
|
31
|
+
function sextet(code) {
|
|
32
|
+
return code < 0 ? 0 : code;
|
|
33
|
+
}
|
|
34
|
+
function decodeAudioBase64(value) {
|
|
35
|
+
const cleaned = value.replaceAll("=", "");
|
|
36
|
+
if (cleaned.length % 4 === 1) throw new Error("Invalid base64 audio");
|
|
37
|
+
const bytes = [];
|
|
38
|
+
for (let index = 0; index < cleaned.length; index += 4) {
|
|
39
|
+
const first = codeAt(cleaned, index);
|
|
40
|
+
const second = codeAt(cleaned, index + 1);
|
|
41
|
+
const third = codeAt(cleaned, index + 2);
|
|
42
|
+
const fourth = codeAt(cleaned, index + 3);
|
|
43
|
+
const triple = sextet(first) << 18 | sextet(second) << 12 | sextet(third) << 6 | sextet(fourth);
|
|
44
|
+
bytes.push(triple >> 16 & 255);
|
|
45
|
+
if (third >= 0) bytes.push(triple >> 8 & 255);
|
|
46
|
+
if (fourth >= 0) bytes.push(triple & 255);
|
|
47
|
+
}
|
|
48
|
+
return Uint8Array.from(bytes);
|
|
49
|
+
}
|
|
50
|
+
function convertAudio(chunk, format) {
|
|
51
|
+
checkFormat(chunk.format);
|
|
52
|
+
checkFormat(format);
|
|
53
|
+
if (sameFormat(chunk.format, format)) {
|
|
54
|
+
return { data: chunk.data.slice(), format, timestamp: chunk.timestamp };
|
|
55
|
+
}
|
|
56
|
+
if (compressed.has(chunk.format.encoding) || compressed.has(format.encoding)) {
|
|
57
|
+
throw new Error(
|
|
58
|
+
`Cannot convert ${chunk.format.encoding} to ${format.encoding} without a codec`
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
const decoded = decode(chunk.data, chunk.format);
|
|
62
|
+
const mixed = mix(decoded.channels, format.channels);
|
|
63
|
+
const resampled = mixed.map(
|
|
64
|
+
(channel) => resample(channel, decoded.sampleRate, format.sampleRate)
|
|
65
|
+
);
|
|
66
|
+
return {
|
|
67
|
+
data: encode(resampled, format),
|
|
68
|
+
format,
|
|
69
|
+
timestamp: chunk.timestamp
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
async function* convertAudioSource(source, format) {
|
|
73
|
+
for await (const chunk of source) yield convertAudio(chunk, format);
|
|
74
|
+
}
|
|
75
|
+
function sameFormat(left, right) {
|
|
76
|
+
return left.encoding === right.encoding && left.sampleRate === right.sampleRate && left.channels === right.channels;
|
|
77
|
+
}
|
|
78
|
+
function checkFormat(format) {
|
|
79
|
+
if (format.channels !== 1 && format.channels !== 2) {
|
|
80
|
+
throw new Error(`Unsupported channel count ${String(format.channels)}`);
|
|
81
|
+
}
|
|
82
|
+
if (!Number.isFinite(format.sampleRate) || format.sampleRate <= 0) {
|
|
83
|
+
throw new Error(`Unsupported sample rate ${String(format.sampleRate)}`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function decode(data, format) {
|
|
87
|
+
if (format.encoding === "wav") return decodeWav(data);
|
|
88
|
+
return { channels: decodePcm(data, format), sampleRate: format.sampleRate };
|
|
89
|
+
}
|
|
90
|
+
function decodePcm(data, format) {
|
|
91
|
+
const width = sampleWidth(format.encoding);
|
|
92
|
+
const frames = Math.floor(data.byteLength / (width * format.channels));
|
|
93
|
+
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
94
|
+
const channels = Array.from({ length: format.channels }, () => new Float32Array(frames));
|
|
95
|
+
for (let frame = 0; frame < frames; frame++) {
|
|
96
|
+
for (let channel = 0; channel < format.channels; channel++) {
|
|
97
|
+
const offset = (frame * format.channels + channel) * width;
|
|
98
|
+
channels[channel][frame] = readSample(view, offset, format.encoding);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return channels;
|
|
102
|
+
}
|
|
103
|
+
function sampleWidth(encoding) {
|
|
104
|
+
if (encoding === "pcm16") return 2;
|
|
105
|
+
if (encoding === "pcmf32") return 4;
|
|
106
|
+
if (encoding === "mulaw" || encoding === "alaw") return 1;
|
|
107
|
+
throw new Error(`Unsupported audio encoding ${encoding}`);
|
|
108
|
+
}
|
|
109
|
+
function readSample(view, offset, encoding) {
|
|
110
|
+
if (encoding === "pcm16") return int16ToFloat(view.getInt16(offset, true));
|
|
111
|
+
if (encoding === "pcmf32") return finite(view.getFloat32(offset, true));
|
|
112
|
+
if (encoding === "mulaw") return int16ToFloat(mulawToLinear(view.getUint8(offset)));
|
|
113
|
+
return int16ToFloat(alawToLinear(view.getUint8(offset)));
|
|
114
|
+
}
|
|
115
|
+
function encode(channels, format) {
|
|
116
|
+
if (format.encoding === "wav") {
|
|
117
|
+
const pcm = encode(channels, { ...format, encoding: "pcm16" });
|
|
118
|
+
return wavBytes(pcm, format.sampleRate, format.channels);
|
|
119
|
+
}
|
|
120
|
+
const width = sampleWidth(format.encoding);
|
|
121
|
+
const frames = channels[0]?.length ?? 0;
|
|
122
|
+
const bytes = new Uint8Array(frames * format.channels * width);
|
|
123
|
+
const view = new DataView(bytes.buffer);
|
|
124
|
+
for (let frame = 0; frame < frames; frame++) {
|
|
125
|
+
for (let channel = 0; channel < format.channels; channel++) {
|
|
126
|
+
const offset = (frame * format.channels + channel) * width;
|
|
127
|
+
writeSample(view, offset, format.encoding, channels[channel]?.[frame] ?? 0);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return bytes;
|
|
131
|
+
}
|
|
132
|
+
function writeSample(view, offset, encoding, sample) {
|
|
133
|
+
const unit = finite(sample);
|
|
134
|
+
if (encoding === "pcm16") view.setInt16(offset, floatToInt16(unit), true);
|
|
135
|
+
else if (encoding === "pcmf32") view.setFloat32(offset, unit, true);
|
|
136
|
+
else if (encoding === "mulaw") view.setUint8(offset, linearToMulaw(floatToInt16(unit)));
|
|
137
|
+
else view.setUint8(offset, linearToAlaw(floatToInt16(unit)));
|
|
138
|
+
}
|
|
139
|
+
function mix(channels, target) {
|
|
140
|
+
const length = channels[0]?.length ?? 0;
|
|
141
|
+
if (channels.length === target) return channels;
|
|
142
|
+
if (target === 1) {
|
|
143
|
+
const mixed = new Float32Array(length);
|
|
144
|
+
if (channels.length === 0) return [mixed];
|
|
145
|
+
for (let index = 0; index < length; index++) {
|
|
146
|
+
let sum = 0;
|
|
147
|
+
for (const channel of channels) sum += channel[index] ?? 0;
|
|
148
|
+
mixed[index] = sum / channels.length;
|
|
149
|
+
}
|
|
150
|
+
return [mixed];
|
|
151
|
+
}
|
|
152
|
+
const left = channels[0] ?? new Float32Array(length);
|
|
153
|
+
return [left, channels[1] ?? left];
|
|
154
|
+
}
|
|
155
|
+
function resample(input, inRate, outRate) {
|
|
156
|
+
if (inRate === outRate || input.length === 0) return input;
|
|
157
|
+
const outLength = Math.max(1, Math.round(input.length * outRate / inRate));
|
|
158
|
+
const output = new Float32Array(outLength);
|
|
159
|
+
const scale = inRate / outRate;
|
|
160
|
+
const last = input.length - 1;
|
|
161
|
+
for (let index = 0; index < outLength; index++) {
|
|
162
|
+
const position = index * scale;
|
|
163
|
+
const cursor = Math.min(Math.floor(position), last);
|
|
164
|
+
const next = Math.min(cursor + 1, last);
|
|
165
|
+
const fraction = position - cursor;
|
|
166
|
+
const left = input[cursor] ?? 0;
|
|
167
|
+
const right = input[next] ?? 0;
|
|
168
|
+
output[index] = left + (right - left) * fraction;
|
|
169
|
+
}
|
|
170
|
+
return output;
|
|
171
|
+
}
|
|
172
|
+
function finite(sample) {
|
|
173
|
+
return Number.isFinite(sample) ? sample : 0;
|
|
174
|
+
}
|
|
175
|
+
function floatToInt16(sample) {
|
|
176
|
+
const clamped = Math.max(-1, Math.min(1, sample));
|
|
177
|
+
const scaled = clamped < 0 ? clamped * 32768 : clamped * 32767;
|
|
178
|
+
return Math.max(-32768, Math.min(32767, Math.round(scaled)));
|
|
179
|
+
}
|
|
180
|
+
function int16ToFloat(sample) {
|
|
181
|
+
return sample < 0 ? sample / 32768 : sample / 32767;
|
|
182
|
+
}
|
|
183
|
+
function mulawToLinear(mulaw) {
|
|
184
|
+
const value = ~mulaw;
|
|
185
|
+
const exponent = (value & 112) >> 4;
|
|
186
|
+
let sample = ((value & 15) << 3) + LAW_BIAS;
|
|
187
|
+
sample <<= exponent;
|
|
188
|
+
return (value & 128) !== 0 ? LAW_BIAS - sample : sample - LAW_BIAS;
|
|
189
|
+
}
|
|
190
|
+
function alawToLinear(alaw) {
|
|
191
|
+
const value = alaw ^ 85;
|
|
192
|
+
const exponent = (value & 112) >> 4;
|
|
193
|
+
const mantissa = value & 15;
|
|
194
|
+
const sample = exponent === 0 ? mantissa + mantissa + 1 << 3 : mantissa + mantissa + 1 + 32 << exponent + 2;
|
|
195
|
+
return (value & 128) !== 0 ? sample : -sample;
|
|
196
|
+
}
|
|
197
|
+
function buildLawTable(expand, mask) {
|
|
198
|
+
const table = new Uint8Array(16384);
|
|
199
|
+
table[8192] = mask;
|
|
200
|
+
let cursor = 1;
|
|
201
|
+
for (let code = 0; code < 127; code++) {
|
|
202
|
+
const left = expand(code ^ mask);
|
|
203
|
+
const right = expand(code + 1 ^ mask);
|
|
204
|
+
const limit = left + right + 4 >> 3;
|
|
205
|
+
for (; cursor < limit; cursor += 1) {
|
|
206
|
+
table[8192 - cursor] = (code ^ (mask ^ 128)) & 255;
|
|
207
|
+
table[8192 + cursor] = (code ^ mask) & 255;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
for (; cursor < 8192; cursor++) {
|
|
211
|
+
table[8192 - cursor] = (127 ^ (mask ^ 128)) & 255;
|
|
212
|
+
table[8192 + cursor] = (127 ^ mask) & 255;
|
|
213
|
+
}
|
|
214
|
+
table[0] = table[1] ?? mask;
|
|
215
|
+
return table;
|
|
216
|
+
}
|
|
217
|
+
const mulawTable = buildLawTable(mulawToLinear, 255);
|
|
218
|
+
const alawTable = buildLawTable(alawToLinear, 213);
|
|
219
|
+
function lawCode(table, pcm, fallback) {
|
|
220
|
+
return table[pcm + 32768 >> 2] ?? fallback;
|
|
221
|
+
}
|
|
222
|
+
function linearToMulaw(pcm) {
|
|
223
|
+
return lawCode(mulawTable, pcm, 255);
|
|
224
|
+
}
|
|
225
|
+
function linearToAlaw(pcm) {
|
|
226
|
+
return lawCode(alawTable, pcm, 213);
|
|
227
|
+
}
|
|
228
|
+
function decodeWav(data) {
|
|
229
|
+
if (data.byteLength < 44) throw new Error("Invalid WAV audio");
|
|
230
|
+
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
231
|
+
if (text(data, 0, 4) !== "RIFF" || text(data, 8, 4) !== "WAVE")
|
|
232
|
+
throw new Error("Invalid WAV audio");
|
|
233
|
+
let cursor = 12;
|
|
234
|
+
let format;
|
|
235
|
+
let payload;
|
|
236
|
+
while (cursor + 8 <= data.byteLength) {
|
|
237
|
+
const id = text(data, cursor, 4);
|
|
238
|
+
const size = view.getUint32(cursor + 4, true);
|
|
239
|
+
const start = cursor + 8;
|
|
240
|
+
const end = Math.min(start + size, data.byteLength);
|
|
241
|
+
if (id === "fmt " && end - start >= 16) {
|
|
242
|
+
format = {
|
|
243
|
+
audioFormat: view.getUint16(start, true),
|
|
244
|
+
channels: view.getUint16(start + 2, true),
|
|
245
|
+
sampleRate: view.getUint32(start + 4, true),
|
|
246
|
+
width: view.getUint16(start + 14, true) / 8
|
|
247
|
+
};
|
|
248
|
+
} else if (id === "data") payload = data.subarray(start, end);
|
|
249
|
+
cursor = start + size + size % 2;
|
|
250
|
+
}
|
|
251
|
+
if (!format || !payload) throw new Error("Invalid WAV audio");
|
|
252
|
+
if (format.audioFormat !== 1 || format.width !== 2) throw new Error("WAV audio must be PCM16");
|
|
253
|
+
if (format.channels !== 1 && format.channels !== 2) throw new Error("Invalid WAV audio");
|
|
254
|
+
return {
|
|
255
|
+
channels: decodePcm(payload, {
|
|
256
|
+
encoding: "pcm16",
|
|
257
|
+
sampleRate: format.sampleRate,
|
|
258
|
+
channels: format.channels
|
|
259
|
+
}),
|
|
260
|
+
sampleRate: format.sampleRate
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
function wavBytes(pcm, sampleRate, channels) {
|
|
264
|
+
const bytes = new Uint8Array(44 + pcm.byteLength);
|
|
265
|
+
const view = new DataView(bytes.buffer);
|
|
266
|
+
bytes.set(ascii("RIFF"), 0);
|
|
267
|
+
view.setUint32(4, 36 + pcm.byteLength, true);
|
|
268
|
+
bytes.set(ascii("WAVE"), 8);
|
|
269
|
+
bytes.set(ascii("fmt "), 12);
|
|
270
|
+
view.setUint32(16, 16, true);
|
|
271
|
+
view.setUint16(20, 1, true);
|
|
272
|
+
view.setUint16(22, channels, true);
|
|
273
|
+
view.setUint32(24, sampleRate, true);
|
|
274
|
+
view.setUint32(28, sampleRate * channels * 2, true);
|
|
275
|
+
view.setUint16(32, channels * 2, true);
|
|
276
|
+
view.setUint16(34, 16, true);
|
|
277
|
+
bytes.set(ascii("data"), 36);
|
|
278
|
+
view.setUint32(40, pcm.byteLength, true);
|
|
279
|
+
bytes.set(pcm, 44);
|
|
280
|
+
return bytes;
|
|
281
|
+
}
|
|
282
|
+
function text(data, offset, length) {
|
|
283
|
+
return String.fromCharCode(...data.subarray(offset, offset + length));
|
|
284
|
+
}
|
|
285
|
+
function ascii(value) {
|
|
286
|
+
return Uint8Array.from(value, (character) => character.charCodeAt(0));
|
|
287
|
+
}
|
|
288
|
+
export {
|
|
289
|
+
convertAudio,
|
|
290
|
+
convertAudioSource,
|
|
291
|
+
decodeAudioBase64,
|
|
292
|
+
encodeAudioBase64
|
|
293
|
+
};
|
|
294
|
+
//# sourceMappingURL=convert.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/convert.ts"],
|
|
4
|
+
"sourcesContent": ["import type { AudioChunk, AudioEncoding, AudioFormat, AudioSource } from './audio.ts';\n\nconst compressed = new Set<AudioEncoding>(['opus', 'mp3', 'flac']);\nconst LAW_BIAS = 0x84;\n\nconst base64Alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\n\nfunction byteAt(data: Uint8Array, index: number): number {\n const byte = data[index];\n return byte === undefined ? 0 : byte;\n}\n\nfunction symbolAt(index: number): string {\n return base64Alphabet.charAt(index);\n}\n\nexport function encodeAudioBase64(data: Uint8Array): string {\n let encoded = '';\n for (let index = 0; index < data.length; index += 3) {\n const second = data[index + 1];\n const third = data[index + 2];\n const triple =\n (byteAt(data, index) << 16) | (byteAt(data, index + 1) << 8) | byteAt(data, index + 2);\n encoded += symbolAt((triple >> 18) & 63);\n encoded += symbolAt((triple >> 12) & 63);\n encoded += second === undefined ? '=' : symbolAt((triple >> 6) & 63);\n encoded += third === undefined ? '=' : symbolAt(triple & 63);\n }\n return encoded;\n}\n\nfunction codeAt(value: string, index: number): number {\n const character = value[index];\n if (character === undefined) return -1;\n const code = base64Alphabet.indexOf(character);\n if (code < 0) throw new Error('Invalid base64 audio');\n return code;\n}\n\nfunction sextet(code: number): number {\n return code < 0 ? 0 : code;\n}\n\nexport function decodeAudioBase64(value: string): Uint8Array {\n const cleaned = value.replaceAll('=', '');\n if (cleaned.length % 4 === 1) throw new Error('Invalid base64 audio');\n const bytes = [];\n for (let index = 0; index < cleaned.length; index += 4) {\n const first = codeAt(cleaned, index);\n const second = codeAt(cleaned, index + 1);\n const third = codeAt(cleaned, index + 2);\n const fourth = codeAt(cleaned, index + 3);\n const triple =\n (sextet(first) << 18) | (sextet(second) << 12) | (sextet(third) << 6) | sextet(fourth);\n bytes.push((triple >> 16) & 0xff);\n if (third >= 0) bytes.push((triple >> 8) & 0xff);\n if (fourth >= 0) bytes.push(triple & 0xff);\n }\n return Uint8Array.from(bytes);\n}\n\nexport function convertAudio(chunk: AudioChunk, format: AudioFormat): AudioChunk {\n checkFormat(chunk.format);\n checkFormat(format);\n if (sameFormat(chunk.format, format)) {\n return { data: chunk.data.slice(), format, timestamp: chunk.timestamp };\n }\n if (compressed.has(chunk.format.encoding) || compressed.has(format.encoding)) {\n throw new Error(\n `Cannot convert ${chunk.format.encoding} to ${format.encoding} without a codec`\n );\n }\n const decoded = decode(chunk.data, chunk.format);\n const mixed = mix(decoded.channels, format.channels);\n const resampled = mixed.map((channel) =>\n resample(channel, decoded.sampleRate, format.sampleRate)\n );\n return {\n data: encode(resampled, format),\n format,\n timestamp: chunk.timestamp,\n };\n}\n\nexport async function* convertAudioSource(source: AudioSource, format: AudioFormat): AudioSource {\n for await (const chunk of source) yield convertAudio(chunk, format);\n}\n\nfunction sameFormat(left: AudioFormat, right: AudioFormat): boolean {\n return (\n left.encoding === right.encoding &&\n left.sampleRate === right.sampleRate &&\n left.channels === right.channels\n );\n}\n\nfunction checkFormat(format: AudioFormat): void {\n if (format.channels !== 1 && format.channels !== 2) {\n throw new Error(`Unsupported channel count ${String(format.channels)}`);\n }\n if (!Number.isFinite(format.sampleRate) || format.sampleRate <= 0) {\n throw new Error(`Unsupported sample rate ${String(format.sampleRate)}`);\n }\n}\n\ninterface Planar {\n channels: Float32Array[];\n sampleRate: number;\n}\n\nfunction decode(data: Uint8Array, format: AudioFormat): Planar {\n if (format.encoding === 'wav') return decodeWav(data);\n return { channels: decodePcm(data, format), sampleRate: format.sampleRate };\n}\n\nfunction decodePcm(data: Uint8Array, format: AudioFormat): Float32Array[] {\n const width = sampleWidth(format.encoding);\n const frames = Math.floor(data.byteLength / (width * format.channels));\n const view = new DataView(data.buffer, data.byteOffset, data.byteLength);\n const channels = Array.from({ length: format.channels }, () => new Float32Array(frames));\n for (let frame = 0; frame < frames; frame++) {\n for (let channel = 0; channel < format.channels; channel++) {\n const offset = (frame * format.channels + channel) * width;\n channels[channel][frame] = readSample(view, offset, format.encoding);\n }\n }\n return channels;\n}\n\nfunction sampleWidth(encoding: AudioEncoding): number {\n if (encoding === 'pcm16') return 2;\n if (encoding === 'pcmf32') return 4;\n if (encoding === 'mulaw' || encoding === 'alaw') return 1;\n throw new Error(`Unsupported audio encoding ${encoding}`);\n}\n\nfunction readSample(view: DataView, offset: number, encoding: AudioEncoding): number {\n if (encoding === 'pcm16') return int16ToFloat(view.getInt16(offset, true));\n if (encoding === 'pcmf32') return finite(view.getFloat32(offset, true));\n if (encoding === 'mulaw') return int16ToFloat(mulawToLinear(view.getUint8(offset)));\n return int16ToFloat(alawToLinear(view.getUint8(offset)));\n}\n\nfunction encode(channels: Float32Array[], format: AudioFormat): Uint8Array {\n if (format.encoding === 'wav') {\n const pcm = encode(channels, { ...format, encoding: 'pcm16' });\n return wavBytes(pcm, format.sampleRate, format.channels);\n }\n const width = sampleWidth(format.encoding);\n const frames = channels[0]?.length ?? 0;\n const bytes = new Uint8Array(frames * format.channels * width);\n const view = new DataView(bytes.buffer);\n for (let frame = 0; frame < frames; frame++) {\n for (let channel = 0; channel < format.channels; channel++) {\n const offset = (frame * format.channels + channel) * width;\n writeSample(view, offset, format.encoding, channels[channel]?.[frame] ?? 0);\n }\n }\n return bytes;\n}\n\nfunction writeSample(\n view: DataView,\n offset: number,\n encoding: AudioEncoding,\n sample: number\n): void {\n const unit = finite(sample);\n if (encoding === 'pcm16') view.setInt16(offset, floatToInt16(unit), true);\n else if (encoding === 'pcmf32') view.setFloat32(offset, unit, true);\n else if (encoding === 'mulaw') view.setUint8(offset, linearToMulaw(floatToInt16(unit)));\n else view.setUint8(offset, linearToAlaw(floatToInt16(unit)));\n}\n\nfunction mix(channels: Float32Array[], target: 1 | 2): Float32Array[] {\n const length = channels[0]?.length ?? 0;\n if (channels.length === target) return channels;\n if (target === 1) {\n const mixed = new Float32Array(length);\n if (channels.length === 0) return [mixed];\n for (let index = 0; index < length; index++) {\n let sum = 0;\n for (const channel of channels) sum += channel[index] ?? 0;\n mixed[index] = sum / channels.length;\n }\n return [mixed];\n }\n const left = channels[0] ?? new Float32Array(length);\n return [left, channels[1] ?? left];\n}\n\nfunction resample(input: Float32Array, inRate: number, outRate: number): Float32Array {\n if (inRate === outRate || input.length === 0) return input;\n const outLength = Math.max(1, Math.round((input.length * outRate) / inRate));\n const output = new Float32Array(outLength);\n const scale = inRate / outRate;\n const last = input.length - 1;\n for (let index = 0; index < outLength; index++) {\n const position = index * scale;\n const cursor = Math.min(Math.floor(position), last);\n const next = Math.min(cursor + 1, last);\n const fraction = position - cursor;\n const left = input[cursor] ?? 0;\n const right = input[next] ?? 0;\n output[index] = left + (right - left) * fraction;\n }\n return output;\n}\n\nfunction finite(sample: number): number {\n return Number.isFinite(sample) ? sample : 0;\n}\n\nfunction floatToInt16(sample: number): number {\n const clamped = Math.max(-1, Math.min(1, sample));\n const scaled = clamped < 0 ? clamped * 0x8000 : clamped * 0x7fff;\n return Math.max(-0x8000, Math.min(0x7fff, Math.round(scaled)));\n}\n\nfunction int16ToFloat(sample: number): number {\n return sample < 0 ? sample / 0x8000 : sample / 0x7fff;\n}\n\nfunction mulawToLinear(mulaw: number): number {\n const value = ~mulaw;\n const exponent = (value & 0x70) >> 4;\n let sample = ((value & 0x0f) << 3) + LAW_BIAS;\n sample <<= exponent;\n return (value & 0x80) !== 0 ? LAW_BIAS - sample : sample - LAW_BIAS;\n}\n\nfunction alawToLinear(alaw: number): number {\n const value = alaw ^ 0x55;\n const exponent = (value & 0x70) >> 4;\n const mantissa = value & 0x0f;\n const sample =\n exponent === 0\n ? (mantissa + mantissa + 1) << 3\n : (mantissa + mantissa + 1 + 32) << (exponent + 2);\n return (value & 0x80) !== 0 ? sample : -sample;\n}\n\nfunction buildLawTable(expand: (code: number) => number, mask: number): Uint8Array {\n const table = new Uint8Array(16384);\n table[8192] = mask;\n let cursor = 1;\n for (let code = 0; code < 127; code++) {\n const left = expand(code ^ mask);\n const right = expand((code + 1) ^ mask);\n const limit = (left + right + 4) >> 3;\n for (; cursor < limit; cursor += 1) {\n table[8192 - cursor] = (code ^ (mask ^ 0x80)) & 0xff;\n table[8192 + cursor] = (code ^ mask) & 0xff;\n }\n }\n for (; cursor < 8192; cursor++) {\n table[8192 - cursor] = (127 ^ (mask ^ 0x80)) & 0xff;\n table[8192 + cursor] = (127 ^ mask) & 0xff;\n }\n table[0] = table[1] ?? mask;\n return table;\n}\n\nconst mulawTable = buildLawTable(mulawToLinear, 0xff);\nconst alawTable = buildLawTable(alawToLinear, 0xd5);\n\nfunction lawCode(table: Uint8Array, pcm: number, fallback: number): number {\n return table[(pcm + 32768) >> 2] ?? fallback;\n}\n\nfunction linearToMulaw(pcm: number): number {\n return lawCode(mulawTable, pcm, 0xff);\n}\n\nfunction linearToAlaw(pcm: number): number {\n return lawCode(alawTable, pcm, 0xd5);\n}\n\nfunction decodeWav(data: Uint8Array): Planar {\n if (data.byteLength < 44) throw new Error('Invalid WAV audio');\n const view = new DataView(data.buffer, data.byteOffset, data.byteLength);\n if (text(data, 0, 4) !== 'RIFF' || text(data, 8, 4) !== 'WAVE')\n throw new Error('Invalid WAV audio');\n let cursor = 12;\n let format:\n | { audioFormat: number; channels: number; sampleRate: number; width: number }\n | undefined;\n let payload: Uint8Array | undefined;\n while (cursor + 8 <= data.byteLength) {\n const id = text(data, cursor, 4);\n const size = view.getUint32(cursor + 4, true);\n const start = cursor + 8;\n const end = Math.min(start + size, data.byteLength);\n if (id === 'fmt ' && end - start >= 16) {\n format = {\n audioFormat: view.getUint16(start, true),\n channels: view.getUint16(start + 2, true),\n sampleRate: view.getUint32(start + 4, true),\n width: view.getUint16(start + 14, true) / 8,\n };\n } else if (id === 'data') payload = data.subarray(start, end);\n cursor = start + size + (size % 2);\n }\n if (!format || !payload) throw new Error('Invalid WAV audio');\n if (format.audioFormat !== 1 || format.width !== 2) throw new Error('WAV audio must be PCM16');\n if (format.channels !== 1 && format.channels !== 2) throw new Error('Invalid WAV audio');\n return {\n channels: decodePcm(payload, {\n encoding: 'pcm16',\n sampleRate: format.sampleRate,\n channels: format.channels,\n }),\n sampleRate: format.sampleRate,\n };\n}\n\nfunction wavBytes(pcm: Uint8Array, sampleRate: number, channels: number): Uint8Array {\n const bytes = new Uint8Array(44 + pcm.byteLength);\n const view = new DataView(bytes.buffer);\n bytes.set(ascii('RIFF'), 0);\n view.setUint32(4, 36 + pcm.byteLength, true);\n bytes.set(ascii('WAVE'), 8);\n bytes.set(ascii('fmt '), 12);\n view.setUint32(16, 16, true);\n view.setUint16(20, 1, true);\n view.setUint16(22, channels, true);\n view.setUint32(24, sampleRate, true);\n view.setUint32(28, sampleRate * channels * 2, true);\n view.setUint16(32, channels * 2, true);\n view.setUint16(34, 16, true);\n bytes.set(ascii('data'), 36);\n view.setUint32(40, pcm.byteLength, true);\n bytes.set(pcm, 44);\n return bytes;\n}\n\nfunction text(data: Uint8Array, offset: number, length: number): string {\n return String.fromCharCode(...data.subarray(offset, offset + length));\n}\n\nfunction ascii(value: string): Uint8Array {\n return Uint8Array.from(value, (character) => character.charCodeAt(0));\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { resolveVoiceAuth } from "./auth.js";
|
|
2
2
|
import { blankUsage } from "./blank-usage.js";
|
|
3
|
+
import {
|
|
4
|
+
convertAudio,
|
|
5
|
+
convertAudioSource,
|
|
6
|
+
decodeAudioBase64,
|
|
7
|
+
encodeAudioBase64
|
|
8
|
+
} from "./convert.js";
|
|
3
9
|
import { VoiceRequestError } from "./errors.js";
|
|
4
10
|
import {
|
|
5
11
|
getVoiceModel,
|
|
@@ -25,6 +31,10 @@ export {
|
|
|
25
31
|
addAudioCounters,
|
|
26
32
|
blankUsage,
|
|
27
33
|
connectRealtime,
|
|
34
|
+
convertAudio,
|
|
35
|
+
convertAudioSource,
|
|
36
|
+
decodeAudioBase64,
|
|
37
|
+
encodeAudioBase64,
|
|
28
38
|
getVoiceModel,
|
|
29
39
|
listVoiceModels,
|
|
30
40
|
listen,
|
package/dist/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/index.ts"],
|
|
4
|
-
"sourcesContent": ["export type {\n AudioChunk,\n AudioEncoding,\n AudioFormat,\n AudioSink,\n AudioSource,\n AudioTag,\n CharAlignment,\n TextSpan,\n} from './audio.ts';\nexport { resolveVoiceAuth } from './auth.ts';\nexport { blankUsage } from './blank-usage.ts';\nexport { VoiceRequestError } from './errors.ts';\nexport type {\n Delivery,\n DeliverySupport,\n KnownRealtimeApi,\n KnownSpeechApi,\n KnownTranscriptionApi,\n RealtimeApi,\n RealtimeModel,\n SpeechApi,\n SpeechModel,\n TranscriptionApi,\n TranscriptionModel,\n VoiceInfo,\n VoiceModel,\n VoiceModelType,\n} from './models.ts';\nexport {\n getVoiceModel,\n listVoiceModels,\n registerVoiceModel,\n} from './models.ts';\nexport type {\n RealtimeApiProvider,\n RealtimeContext,\n RealtimeEvent,\n RealtimeOptions,\n RealtimeSession,\n RealtimeToken,\n} from './realtime.ts';\nexport {\n connectRealtime,\n listen,\n registerRealtimeApiProvider,\n registerSpeechApiProvider,\n registerTranscriptionApiProvider,\n speak,\n transcribe,\n} from './registry.ts';\nexport type { SpeechApiProvider, SpeechEvent, SpeechInput } from './speech.ts';\nexport { SpeechEventStream } from './speech.ts';\nexport type {\n AudioInput,\n ListenOptions,\n Transcript,\n TranscriptionApiProvider,\n TranscriptionEvent,\n TranscriptSegment,\n} from './transcription.ts';\nexport { TranscriptionEventStream } from './transcription.ts';\nexport type {\n AudioCost,\n AudioCounters,\n AudioUsage,\n RealtimeAudioCost,\n SpeechAudioCost,\n TranscriptionAudioCost,\n} from './usage.ts';\nexport { addAudioCounters, priceAudio } from './usage.ts';\n"],
|
|
5
|
-
"mappings": "AAUA,SAAS,wBAAwB;AACjC,SAAS,kBAAkB;AAC3B,SAAS,yBAAyB;AAiBlC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AASP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEP,SAAS,yBAAyB;AASlC,SAAS,gCAAgC;AASzC,SAAS,kBAAkB,kBAAkB;",
|
|
4
|
+
"sourcesContent": ["export type {\n AudioChunk,\n AudioEncoding,\n AudioFormat,\n AudioSink,\n AudioSource,\n AudioTag,\n CharAlignment,\n TextSpan,\n} from './audio.ts';\nexport { resolveVoiceAuth } from './auth.ts';\nexport { blankUsage } from './blank-usage.ts';\nexport {\n convertAudio,\n convertAudioSource,\n decodeAudioBase64,\n encodeAudioBase64,\n} from './convert.ts';\nexport { VoiceRequestError } from './errors.ts';\nexport type {\n Delivery,\n DeliverySupport,\n KnownRealtimeApi,\n KnownSpeechApi,\n KnownTranscriptionApi,\n RealtimeApi,\n RealtimeModel,\n SpeechApi,\n SpeechModel,\n TranscriptionApi,\n TranscriptionModel,\n VoiceInfo,\n VoiceModel,\n VoiceModelType,\n} from './models.ts';\nexport {\n getVoiceModel,\n listVoiceModels,\n registerVoiceModel,\n} from './models.ts';\nexport type {\n RealtimeApiProvider,\n RealtimeContext,\n RealtimeEvent,\n RealtimeOptions,\n RealtimeSession,\n RealtimeToken,\n} from './realtime.ts';\nexport {\n connectRealtime,\n listen,\n registerRealtimeApiProvider,\n registerSpeechApiProvider,\n registerTranscriptionApiProvider,\n speak,\n transcribe,\n} from './registry.ts';\nexport type { SpeechApiProvider, SpeechEvent, SpeechInput } from './speech.ts';\nexport { SpeechEventStream } from './speech.ts';\nexport type {\n AudioInput,\n ListenOptions,\n Transcript,\n TranscriptionApiProvider,\n TranscriptionEvent,\n TranscriptSegment,\n} from './transcription.ts';\nexport { TranscriptionEventStream } from './transcription.ts';\nexport type {\n AudioCost,\n AudioCounters,\n AudioUsage,\n RealtimeAudioCost,\n SpeechAudioCost,\n TranscriptionAudioCost,\n} from './usage.ts';\nexport { addAudioCounters, priceAudio } from './usage.ts';\n"],
|
|
5
|
+
"mappings": "AAUA,SAAS,wBAAwB;AACjC,SAAS,kBAAkB;AAC3B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,yBAAyB;AAiBlC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AASP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEP,SAAS,yBAAyB;AASlC,SAAS,gCAAgC;AASzC,SAAS,kBAAkB,kBAAkB;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { AudioChunk, AudioFormat, AudioSource } from './audio.ts';
|
|
2
|
+
export declare function encodeAudioBase64(data: Uint8Array): string;
|
|
3
|
+
export declare function decodeAudioBase64(value: string): Uint8Array;
|
|
4
|
+
export declare function convertAudio(chunk: AudioChunk, format: AudioFormat): AudioChunk;
|
|
5
|
+
export declare function convertAudioSource(source: AudioSource, format: AudioFormat): AudioSource;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export type { AudioChunk, AudioEncoding, AudioFormat, AudioSink, AudioSource, AudioTag, CharAlignment, TextSpan, } from './audio.ts';
|
|
2
2
|
export { resolveVoiceAuth } from './auth.ts';
|
|
3
3
|
export { blankUsage } from './blank-usage.ts';
|
|
4
|
+
export { convertAudio, convertAudioSource, decodeAudioBase64, encodeAudioBase64, } from './convert.ts';
|
|
4
5
|
export { VoiceRequestError } from './errors.ts';
|
|
5
6
|
export type { Delivery, DeliverySupport, KnownRealtimeApi, KnownSpeechApi, KnownTranscriptionApi, RealtimeApi, RealtimeModel, SpeechApi, SpeechModel, TranscriptionApi, TranscriptionModel, VoiceInfo, VoiceModel, VoiceModelType, } from './models.ts';
|
|
6
7
|
export { getVoiceModel, listVoiceModels, registerVoiceModel, } from './models.ts';
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { AudioFormat } from '../audio.ts';
|
|
2
|
+
export declare const AUDIO_CONVERT_PROCESSOR = "pi-audio-convert";
|
|
3
|
+
export interface AudioConvertProcessorOptions {
|
|
4
|
+
processorOptions?: {
|
|
5
|
+
format?: AudioFormat;
|
|
6
|
+
sampleRate?: number;
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
interface WorkletScope {
|
|
10
|
+
AudioWorkletProcessor?: new (options?: AudioConvertProcessorOptions) => {
|
|
11
|
+
port?: {
|
|
12
|
+
postMessage(message: unknown): void;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
registerProcessor?: (name: string, processor: new (options?: AudioConvertProcessorOptions) => object) => void;
|
|
16
|
+
}
|
|
17
|
+
declare const WorkletBase: new (options?: AudioConvertProcessorOptions) => {
|
|
18
|
+
port?: {
|
|
19
|
+
postMessage(message: unknown): void;
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
export declare class AudioConvertProcessor extends WorkletBase {
|
|
23
|
+
#private;
|
|
24
|
+
constructor(options?: AudioConvertProcessorOptions);
|
|
25
|
+
process(inputs: Array<ArrayLike<Float32Array | undefined> | undefined>): boolean;
|
|
26
|
+
take(): Uint8Array[];
|
|
27
|
+
}
|
|
28
|
+
export declare function registerAudioConvertWorklet(target?: WorkletScope): void;
|
|
29
|
+
export declare function audioConvertWorkletUrl(): string;
|
|
30
|
+
export {};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { convertAudio } from "../convert.js";
|
|
2
|
+
const AUDIO_CONVERT_PROCESSOR = "pi-audio-convert";
|
|
3
|
+
const scope = globalThis;
|
|
4
|
+
const WorkletBase = scope.AudioWorkletProcessor ?? class {
|
|
5
|
+
port;
|
|
6
|
+
};
|
|
7
|
+
class AudioConvertProcessor extends WorkletBase {
|
|
8
|
+
#format;
|
|
9
|
+
#sampleRate;
|
|
10
|
+
#frames = 0;
|
|
11
|
+
#pending = [];
|
|
12
|
+
constructor(options) {
|
|
13
|
+
super(options);
|
|
14
|
+
this.#format = options?.processorOptions?.format ?? {
|
|
15
|
+
encoding: "pcm16",
|
|
16
|
+
sampleRate: 24e3,
|
|
17
|
+
channels: 1
|
|
18
|
+
};
|
|
19
|
+
const sampleRate = options?.processorOptions?.sampleRate;
|
|
20
|
+
this.#sampleRate = sampleRate !== void 0 && Number.isFinite(sampleRate) && sampleRate > 0 ? sampleRate : 48e3;
|
|
21
|
+
}
|
|
22
|
+
process(inputs) {
|
|
23
|
+
const input = inputs[0];
|
|
24
|
+
const channels = [];
|
|
25
|
+
if (input) {
|
|
26
|
+
for (let index = 0; index < input.length; index++) {
|
|
27
|
+
const channel = input[index];
|
|
28
|
+
if (channel) channels.push(channel);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
const frames = channels[0]?.length ?? 0;
|
|
32
|
+
if (channels.length === 0 || frames === 0) return true;
|
|
33
|
+
const count = Math.min(channels.length, 2);
|
|
34
|
+
const data = new Uint8Array(frames * count * 4);
|
|
35
|
+
const view = new DataView(data.buffer);
|
|
36
|
+
for (let frame = 0; frame < frames; frame++) {
|
|
37
|
+
for (let channel = 0; channel < count; channel++) {
|
|
38
|
+
view.setFloat32((frame * count + channel) * 4, channels[channel]?.[frame] ?? 0, true);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const converted = convertAudio(
|
|
42
|
+
{
|
|
43
|
+
data,
|
|
44
|
+
format: {
|
|
45
|
+
encoding: "pcmf32",
|
|
46
|
+
sampleRate: this.#sampleRate,
|
|
47
|
+
channels: count === 1 ? 1 : 2
|
|
48
|
+
},
|
|
49
|
+
timestamp: this.#frames / this.#sampleRate * 1e3
|
|
50
|
+
},
|
|
51
|
+
this.#format
|
|
52
|
+
);
|
|
53
|
+
this.#frames += frames;
|
|
54
|
+
this.#pending.push(converted.data);
|
|
55
|
+
this.port?.postMessage({
|
|
56
|
+
data: converted.data,
|
|
57
|
+
format: converted.format,
|
|
58
|
+
timestamp: converted.timestamp
|
|
59
|
+
});
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
take() {
|
|
63
|
+
return this.#pending.splice(0);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function registerAudioConvertWorklet(target = scope) {
|
|
67
|
+
if (typeof target.registerProcessor !== "function") return;
|
|
68
|
+
target.registerProcessor(AUDIO_CONVERT_PROCESSOR, AudioConvertProcessor);
|
|
69
|
+
}
|
|
70
|
+
function audioConvertWorkletUrl() {
|
|
71
|
+
return new URL(import.meta.url).href;
|
|
72
|
+
}
|
|
73
|
+
registerAudioConvertWorklet();
|
|
74
|
+
export {
|
|
75
|
+
AUDIO_CONVERT_PROCESSOR,
|
|
76
|
+
AudioConvertProcessor,
|
|
77
|
+
audioConvertWorkletUrl,
|
|
78
|
+
registerAudioConvertWorklet
|
|
79
|
+
};
|
|
80
|
+
//# sourceMappingURL=convert.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/worklet/convert.ts"],
|
|
4
|
+
"sourcesContent": ["import type { AudioFormat } from '../audio.ts';\nimport { convertAudio } from '../convert.ts';\n\nexport const AUDIO_CONVERT_PROCESSOR = 'pi-audio-convert';\n\nexport interface AudioConvertProcessorOptions {\n processorOptions?: {\n format?: AudioFormat;\n sampleRate?: number;\n };\n}\n\ninterface WorkletScope {\n AudioWorkletProcessor?: new (\n options?: AudioConvertProcessorOptions\n ) => {\n port?: { postMessage(message: unknown): void };\n };\n registerProcessor?: (\n name: string,\n processor: new (options?: AudioConvertProcessorOptions) => object\n ) => void;\n}\n\nconst scope = globalThis as WorkletScope;\n\nconst WorkletBase =\n scope.AudioWorkletProcessor ??\n class {\n port?: { postMessage(message: unknown): void };\n };\n\nexport class AudioConvertProcessor extends WorkletBase {\n readonly #format: AudioFormat;\n readonly #sampleRate: number;\n #frames = 0;\n readonly #pending: Uint8Array[] = [];\n\n constructor(options?: AudioConvertProcessorOptions) {\n super(options);\n this.#format = options?.processorOptions?.format ?? {\n encoding: 'pcm16',\n sampleRate: 24000,\n channels: 1,\n };\n const sampleRate = options?.processorOptions?.sampleRate;\n this.#sampleRate =\n sampleRate !== undefined && Number.isFinite(sampleRate) && sampleRate > 0\n ? sampleRate\n : 48000;\n }\n\n process(inputs: Array<ArrayLike<Float32Array | undefined> | undefined>): boolean {\n const input = inputs[0];\n const channels: Float32Array[] = [];\n if (input) {\n for (let index = 0; index < input.length; index++) {\n const channel = input[index];\n if (channel) channels.push(channel);\n }\n }\n const frames = channels[0]?.length ?? 0;\n if (channels.length === 0 || frames === 0) return true;\n const count = Math.min(channels.length, 2);\n const data = new Uint8Array(frames * count * 4);\n const view = new DataView(data.buffer);\n for (let frame = 0; frame < frames; frame++) {\n for (let channel = 0; channel < count; channel++) {\n view.setFloat32((frame * count + channel) * 4, channels[channel]?.[frame] ?? 0, true);\n }\n }\n const converted = convertAudio(\n {\n data,\n format: {\n encoding: 'pcmf32',\n sampleRate: this.#sampleRate,\n channels: count === 1 ? 1 : 2,\n },\n timestamp: (this.#frames / this.#sampleRate) * 1000,\n },\n this.#format\n );\n this.#frames += frames;\n this.#pending.push(converted.data);\n this.port?.postMessage({\n data: converted.data,\n format: converted.format,\n timestamp: converted.timestamp,\n });\n return true;\n }\n\n take(): Uint8Array[] {\n return this.#pending.splice(0);\n }\n}\n\nexport function registerAudioConvertWorklet(target: WorkletScope = scope): void {\n if (typeof target.registerProcessor !== 'function') return;\n target.registerProcessor(AUDIO_CONVERT_PROCESSOR, AudioConvertProcessor);\n}\n\nexport function audioConvertWorkletUrl(): string {\n return new URL(import.meta.url).href;\n}\n\nregisterAudioConvertWorklet();\n"],
|
|
5
|
+
"mappings": "AACA,SAAS,oBAAoB;AAEtB,MAAM,0BAA0B;AAqBvC,MAAM,QAAQ;AAEd,MAAM,cACJ,MAAM,yBACN,MAAM;AAAA,EACJ;AACF;AAEK,MAAM,8BAA8B,YAAY;AAAA,EAC5C;AAAA,EACA;AAAA,EACT,UAAU;AAAA,EACD,WAAyB,CAAC;AAAA,EAEnC,YAAY,SAAwC;AAClD,UAAM,OAAO;AACb,SAAK,UAAU,SAAS,kBAAkB,UAAU;AAAA,MAClD,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,UAAU;AAAA,IACZ;AACA,UAAM,aAAa,SAAS,kBAAkB;AAC9C,SAAK,cACH,eAAe,UAAa,OAAO,SAAS,UAAU,KAAK,aAAa,IACpE,aACA;AAAA,EACR;AAAA,EAEA,QAAQ,QAAyE;AAC/E,UAAM,QAAQ,OAAO,CAAC;AACtB,UAAM,WAA2B,CAAC;AAClC,QAAI,OAAO;AACT,eAAS,QAAQ,GAAG,QAAQ,MAAM,QAAQ,SAAS;AACjD,cAAM,UAAU,MAAM,KAAK;AAC3B,YAAI,QAAS,UAAS,KAAK,OAAO;AAAA,MACpC;AAAA,IACF;AACA,UAAM,SAAS,SAAS,CAAC,GAAG,UAAU;AACtC,QAAI,SAAS,WAAW,KAAK,WAAW,EAAG,QAAO;AAClD,UAAM,QAAQ,KAAK,IAAI,SAAS,QAAQ,CAAC;AACzC,UAAM,OAAO,IAAI,WAAW,SAAS,QAAQ,CAAC;AAC9C,UAAM,OAAO,IAAI,SAAS,KAAK,MAAM;AACrC,aAAS,QAAQ,GAAG,QAAQ,QAAQ,SAAS;AAC3C,eAAS,UAAU,GAAG,UAAU,OAAO,WAAW;AAChD,aAAK,YAAY,QAAQ,QAAQ,WAAW,GAAG,SAAS,OAAO,IAAI,KAAK,KAAK,GAAG,IAAI;AAAA,MACtF;AAAA,IACF;AACA,UAAM,YAAY;AAAA,MAChB;AAAA,QACE;AAAA,QACA,QAAQ;AAAA,UACN,UAAU;AAAA,UACV,YAAY,KAAK;AAAA,UACjB,UAAU,UAAU,IAAI,IAAI;AAAA,QAC9B;AAAA,QACA,WAAY,KAAK,UAAU,KAAK,cAAe;AAAA,MACjD;AAAA,MACA,KAAK;AAAA,IACP;AACA,SAAK,WAAW;AAChB,SAAK,SAAS,KAAK,UAAU,IAAI;AACjC,SAAK,MAAM,YAAY;AAAA,MACrB,MAAM,UAAU;AAAA,MAChB,QAAQ,UAAU;AAAA,MAClB,WAAW,UAAU;AAAA,IACvB,CAAC;AACD,WAAO;AAAA,EACT;AAAA,EAEA,OAAqB;AACnB,WAAO,KAAK,SAAS,OAAO,CAAC;AAAA,EAC/B;AACF;AAEO,SAAS,4BAA4B,SAAuB,OAAa;AAC9E,MAAI,OAAO,OAAO,sBAAsB,WAAY;AACpD,SAAO,kBAAkB,yBAAyB,qBAAqB;AACzE;AAEO,SAAS,yBAAiC;AAC/C,SAAO,IAAI,IAAI,YAAY,GAAG,EAAE;AAClC;AAEA,4BAA4B;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-ecoverse/pi-audio",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Voice bindings for pi: speech-to-text, text-to-speech and realtime speech for pi-coding-agent plugins and slicc-agent",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -29,6 +29,10 @@
|
|
|
29
29
|
"./faux": {
|
|
30
30
|
"types": "./dist/types/faux/index.d.ts",
|
|
31
31
|
"default": "./dist/faux/index.js"
|
|
32
|
+
},
|
|
33
|
+
"./worklet": {
|
|
34
|
+
"types": "./dist/types/worklet/convert.d.ts",
|
|
35
|
+
"default": "./dist/worklet/convert.js"
|
|
32
36
|
}
|
|
33
37
|
},
|
|
34
38
|
"files": [
|