@pompeii-labs/audio 0.1.1 → 0.1.3

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/dist/index.js CHANGED
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
2
 
3
+ var alawmulaw = require('alawmulaw');
4
+
3
5
  // src/decoders/wav.ts
4
6
  function decodeWAV(bytes) {
5
7
  const view = new DataView(bytes.buffer);
@@ -74,306 +76,11 @@ function decodeWAV(bytes) {
74
76
  };
75
77
  return result;
76
78
  }
77
-
78
- // src/decoders/mulaw.ts
79
79
  function mulawToPcm16(mulawData) {
80
- const pcmData = new Int16Array(mulawData.length);
81
- for (let i = 0; i < mulawData.length; i++) {
82
- pcmData[i] = mulawToLinear(mulawData[i]);
83
- }
84
- return pcmData;
85
- }
86
- function mulawToLinear(mulawByte) {
87
- const inverted = mulawByte ^ 255;
88
- const sign = inverted & 128;
89
- const segment = (inverted & 112) >> 4;
90
- const step = inverted & 15;
91
- let linear;
92
- if (segment === 0) {
93
- linear = (step << 1) + 1;
94
- } else {
95
- linear = (step << 1) + 1 + 32 << segment + 2;
96
- }
97
- linear -= 33;
98
- return sign ? -linear : linear;
99
- }
100
-
101
- // src/encoders/mulaw.ts
102
- var BIAS = 132;
103
- var CLIP = 32635;
104
- var encodeTable = [
105
- 0,
106
- 0,
107
- 1,
108
- 1,
109
- 2,
110
- 2,
111
- 2,
112
- 2,
113
- 3,
114
- 3,
115
- 3,
116
- 3,
117
- 3,
118
- 3,
119
- 3,
120
- 3,
121
- 4,
122
- 4,
123
- 4,
124
- 4,
125
- 4,
126
- 4,
127
- 4,
128
- 4,
129
- 4,
130
- 4,
131
- 4,
132
- 4,
133
- 4,
134
- 4,
135
- 4,
136
- 4,
137
- 5,
138
- 5,
139
- 5,
140
- 5,
141
- 5,
142
- 5,
143
- 5,
144
- 5,
145
- 5,
146
- 5,
147
- 5,
148
- 5,
149
- 5,
150
- 5,
151
- 5,
152
- 5,
153
- 5,
154
- 5,
155
- 5,
156
- 5,
157
- 5,
158
- 5,
159
- 5,
160
- 5,
161
- 5,
162
- 5,
163
- 5,
164
- 5,
165
- 5,
166
- 5,
167
- 5,
168
- 5,
169
- 6,
170
- 6,
171
- 6,
172
- 6,
173
- 6,
174
- 6,
175
- 6,
176
- 6,
177
- 6,
178
- 6,
179
- 6,
180
- 6,
181
- 6,
182
- 6,
183
- 6,
184
- 6,
185
- 6,
186
- 6,
187
- 6,
188
- 6,
189
- 6,
190
- 6,
191
- 6,
192
- 6,
193
- 6,
194
- 6,
195
- 6,
196
- 6,
197
- 6,
198
- 6,
199
- 6,
200
- 6,
201
- 6,
202
- 6,
203
- 6,
204
- 6,
205
- 6,
206
- 6,
207
- 6,
208
- 6,
209
- 6,
210
- 6,
211
- 6,
212
- 6,
213
- 6,
214
- 6,
215
- 6,
216
- 6,
217
- 6,
218
- 6,
219
- 6,
220
- 6,
221
- 6,
222
- 6,
223
- 6,
224
- 6,
225
- 6,
226
- 6,
227
- 6,
228
- 6,
229
- 6,
230
- 6,
231
- 6,
232
- 6,
233
- 7,
234
- 7,
235
- 7,
236
- 7,
237
- 7,
238
- 7,
239
- 7,
240
- 7,
241
- 7,
242
- 7,
243
- 7,
244
- 7,
245
- 7,
246
- 7,
247
- 7,
248
- 7,
249
- 7,
250
- 7,
251
- 7,
252
- 7,
253
- 7,
254
- 7,
255
- 7,
256
- 7,
257
- 7,
258
- 7,
259
- 7,
260
- 7,
261
- 7,
262
- 7,
263
- 7,
264
- 7,
265
- 7,
266
- 7,
267
- 7,
268
- 7,
269
- 7,
270
- 7,
271
- 7,
272
- 7,
273
- 7,
274
- 7,
275
- 7,
276
- 7,
277
- 7,
278
- 7,
279
- 7,
280
- 7,
281
- 7,
282
- 7,
283
- 7,
284
- 7,
285
- 7,
286
- 7,
287
- 7,
288
- 7,
289
- 7,
290
- 7,
291
- 7,
292
- 7,
293
- 7,
294
- 7,
295
- 7,
296
- 7,
297
- 7,
298
- 7,
299
- 7,
300
- 7,
301
- 7,
302
- 7,
303
- 7,
304
- 7,
305
- 7,
306
- 7,
307
- 7,
308
- 7,
309
- 7,
310
- 7,
311
- 7,
312
- 7,
313
- 7,
314
- 7,
315
- 7,
316
- 7,
317
- 7,
318
- 7,
319
- 7,
320
- 7,
321
- 7,
322
- 7,
323
- 7,
324
- 7,
325
- 7,
326
- 7,
327
- 7,
328
- 7,
329
- 7,
330
- 7,
331
- 7,
332
- 7,
333
- 7,
334
- 7,
335
- 7,
336
- 7,
337
- 7,
338
- 7,
339
- 7,
340
- 7,
341
- 7,
342
- 7,
343
- 7,
344
- 7,
345
- 7,
346
- 7,
347
- 7,
348
- 7,
349
- 7,
350
- 7,
351
- 7,
352
- 7,
353
- 7,
354
- 7,
355
- 7,
356
- 7,
357
- 7,
358
- 7,
359
- 7,
360
- 7
361
- ];
362
- function encodeSample(sample) {
363
- const sign = sample >> 8 & 128;
364
- if (sign !== 0) sample = -sample;
365
- sample = sample + BIAS;
366
- if (sample > CLIP) sample = CLIP;
367
- const exponent = encodeTable[sample >> 7 & 255];
368
- const mantissa = sample >> exponent + 3 & 15;
369
- return ~(sign | exponent << 4 | mantissa);
80
+ return alawmulaw.mulaw.decode(mulawData);
370
81
  }
371
82
  function pcm16ToMulaw(pcmData) {
372
- const mulawData = new Uint8Array(pcmData.length);
373
- for (let i = 0; i < pcmData.length; i++) {
374
- mulawData[i] = encodeSample(pcmData[i]);
375
- }
376
- return mulawData;
83
+ return alawmulaw.mulaw.encode(pcmData);
377
84
  }
378
85
 
379
86
  // src/helpers/bufferToInt16Array.ts
@@ -506,20 +213,52 @@ function generateFadeOutSamples(lastSampleValue, fadeDurationMs, sampleRate) {
506
213
 
507
214
  // src/helpers/resamplePcm.ts
508
215
  function resamplePcm(pcm, originalSampleRate, targetSampleRate) {
216
+ if (originalSampleRate === targetSampleRate) {
217
+ return pcm;
218
+ }
509
219
  const ratio = originalSampleRate / targetSampleRate;
510
220
  const newLength = Math.floor(pcm.length / ratio);
511
221
  const newSamples = new Int16Array(newLength);
222
+ if (ratio < 1) {
223
+ for (let i = 0; i < newSamples.length; i++) {
224
+ const exactPos = i * ratio;
225
+ const lowerIndex = Math.floor(exactPos);
226
+ const upperIndex = Math.min(lowerIndex + 1, pcm.length - 1);
227
+ const fraction = exactPos - lowerIndex;
228
+ const lowerSample = pcm[lowerIndex];
229
+ const upperSample = pcm[upperIndex];
230
+ newSamples[i] = Math.round(lowerSample + (upperSample - lowerSample) * fraction);
231
+ }
232
+ return newSamples;
233
+ }
234
+ const nyquistFreq = targetSampleRate / 2;
235
+ const cutoffFreq = nyquistFreq * 0.9;
236
+ const filteredPcm = applyLowPassFilter(pcm, originalSampleRate, cutoffFreq);
512
237
  for (let i = 0; i < newSamples.length; i++) {
513
238
  const exactPos = i * ratio;
514
239
  const lowerIndex = Math.floor(exactPos);
515
- const upperIndex = Math.min(lowerIndex + 1, pcm.length - 1);
240
+ const upperIndex = Math.min(lowerIndex + 1, filteredPcm.length - 1);
516
241
  const fraction = exactPos - lowerIndex;
517
- const lowerSample = pcm[lowerIndex];
518
- const upperSample = pcm[upperIndex];
242
+ const lowerSample = filteredPcm[lowerIndex];
243
+ const upperSample = filteredPcm[upperIndex];
519
244
  newSamples[i] = Math.round(lowerSample + (upperSample - lowerSample) * fraction);
520
245
  }
521
246
  return newSamples;
522
247
  }
248
+ function applyLowPassFilter(pcm, sampleRate, cutoffFreq) {
249
+ const filterOrder = Math.max(3, Math.floor(sampleRate / (cutoffFreq * 4)));
250
+ const filtered = new Int16Array(pcm.length);
251
+ for (let i = 0; i < pcm.length; i++) {
252
+ let sum = 0;
253
+ let count = 0;
254
+ for (let j = Math.max(0, i - filterOrder); j <= Math.min(pcm.length - 1, i + filterOrder); j++) {
255
+ sum += pcm[j];
256
+ count++;
257
+ }
258
+ filtered[i] = Math.round(sum / count);
259
+ }
260
+ return filtered;
261
+ }
523
262
 
524
263
  exports.bufferToInt16Array = bufferToInt16Array;
525
264
  exports.decodeToPcm = decodeToPcm;
package/dist/index.mjs CHANGED
@@ -1,3 +1,5 @@
1
+ import { mulaw } from 'alawmulaw';
2
+
1
3
  // src/decoders/wav.ts
2
4
  function decodeWAV(bytes) {
3
5
  const view = new DataView(bytes.buffer);
@@ -72,306 +74,11 @@ function decodeWAV(bytes) {
72
74
  };
73
75
  return result;
74
76
  }
75
-
76
- // src/decoders/mulaw.ts
77
77
  function mulawToPcm16(mulawData) {
78
- const pcmData = new Int16Array(mulawData.length);
79
- for (let i = 0; i < mulawData.length; i++) {
80
- pcmData[i] = mulawToLinear(mulawData[i]);
81
- }
82
- return pcmData;
83
- }
84
- function mulawToLinear(mulawByte) {
85
- const inverted = mulawByte ^ 255;
86
- const sign = inverted & 128;
87
- const segment = (inverted & 112) >> 4;
88
- const step = inverted & 15;
89
- let linear;
90
- if (segment === 0) {
91
- linear = (step << 1) + 1;
92
- } else {
93
- linear = (step << 1) + 1 + 32 << segment + 2;
94
- }
95
- linear -= 33;
96
- return sign ? -linear : linear;
97
- }
98
-
99
- // src/encoders/mulaw.ts
100
- var BIAS = 132;
101
- var CLIP = 32635;
102
- var encodeTable = [
103
- 0,
104
- 0,
105
- 1,
106
- 1,
107
- 2,
108
- 2,
109
- 2,
110
- 2,
111
- 3,
112
- 3,
113
- 3,
114
- 3,
115
- 3,
116
- 3,
117
- 3,
118
- 3,
119
- 4,
120
- 4,
121
- 4,
122
- 4,
123
- 4,
124
- 4,
125
- 4,
126
- 4,
127
- 4,
128
- 4,
129
- 4,
130
- 4,
131
- 4,
132
- 4,
133
- 4,
134
- 4,
135
- 5,
136
- 5,
137
- 5,
138
- 5,
139
- 5,
140
- 5,
141
- 5,
142
- 5,
143
- 5,
144
- 5,
145
- 5,
146
- 5,
147
- 5,
148
- 5,
149
- 5,
150
- 5,
151
- 5,
152
- 5,
153
- 5,
154
- 5,
155
- 5,
156
- 5,
157
- 5,
158
- 5,
159
- 5,
160
- 5,
161
- 5,
162
- 5,
163
- 5,
164
- 5,
165
- 5,
166
- 5,
167
- 6,
168
- 6,
169
- 6,
170
- 6,
171
- 6,
172
- 6,
173
- 6,
174
- 6,
175
- 6,
176
- 6,
177
- 6,
178
- 6,
179
- 6,
180
- 6,
181
- 6,
182
- 6,
183
- 6,
184
- 6,
185
- 6,
186
- 6,
187
- 6,
188
- 6,
189
- 6,
190
- 6,
191
- 6,
192
- 6,
193
- 6,
194
- 6,
195
- 6,
196
- 6,
197
- 6,
198
- 6,
199
- 6,
200
- 6,
201
- 6,
202
- 6,
203
- 6,
204
- 6,
205
- 6,
206
- 6,
207
- 6,
208
- 6,
209
- 6,
210
- 6,
211
- 6,
212
- 6,
213
- 6,
214
- 6,
215
- 6,
216
- 6,
217
- 6,
218
- 6,
219
- 6,
220
- 6,
221
- 6,
222
- 6,
223
- 6,
224
- 6,
225
- 6,
226
- 6,
227
- 6,
228
- 6,
229
- 6,
230
- 6,
231
- 7,
232
- 7,
233
- 7,
234
- 7,
235
- 7,
236
- 7,
237
- 7,
238
- 7,
239
- 7,
240
- 7,
241
- 7,
242
- 7,
243
- 7,
244
- 7,
245
- 7,
246
- 7,
247
- 7,
248
- 7,
249
- 7,
250
- 7,
251
- 7,
252
- 7,
253
- 7,
254
- 7,
255
- 7,
256
- 7,
257
- 7,
258
- 7,
259
- 7,
260
- 7,
261
- 7,
262
- 7,
263
- 7,
264
- 7,
265
- 7,
266
- 7,
267
- 7,
268
- 7,
269
- 7,
270
- 7,
271
- 7,
272
- 7,
273
- 7,
274
- 7,
275
- 7,
276
- 7,
277
- 7,
278
- 7,
279
- 7,
280
- 7,
281
- 7,
282
- 7,
283
- 7,
284
- 7,
285
- 7,
286
- 7,
287
- 7,
288
- 7,
289
- 7,
290
- 7,
291
- 7,
292
- 7,
293
- 7,
294
- 7,
295
- 7,
296
- 7,
297
- 7,
298
- 7,
299
- 7,
300
- 7,
301
- 7,
302
- 7,
303
- 7,
304
- 7,
305
- 7,
306
- 7,
307
- 7,
308
- 7,
309
- 7,
310
- 7,
311
- 7,
312
- 7,
313
- 7,
314
- 7,
315
- 7,
316
- 7,
317
- 7,
318
- 7,
319
- 7,
320
- 7,
321
- 7,
322
- 7,
323
- 7,
324
- 7,
325
- 7,
326
- 7,
327
- 7,
328
- 7,
329
- 7,
330
- 7,
331
- 7,
332
- 7,
333
- 7,
334
- 7,
335
- 7,
336
- 7,
337
- 7,
338
- 7,
339
- 7,
340
- 7,
341
- 7,
342
- 7,
343
- 7,
344
- 7,
345
- 7,
346
- 7,
347
- 7,
348
- 7,
349
- 7,
350
- 7,
351
- 7,
352
- 7,
353
- 7,
354
- 7,
355
- 7,
356
- 7,
357
- 7,
358
- 7
359
- ];
360
- function encodeSample(sample) {
361
- const sign = sample >> 8 & 128;
362
- if (sign !== 0) sample = -sample;
363
- sample = sample + BIAS;
364
- if (sample > CLIP) sample = CLIP;
365
- const exponent = encodeTable[sample >> 7 & 255];
366
- const mantissa = sample >> exponent + 3 & 15;
367
- return ~(sign | exponent << 4 | mantissa);
78
+ return mulaw.decode(mulawData);
368
79
  }
369
80
  function pcm16ToMulaw(pcmData) {
370
- const mulawData = new Uint8Array(pcmData.length);
371
- for (let i = 0; i < pcmData.length; i++) {
372
- mulawData[i] = encodeSample(pcmData[i]);
373
- }
374
- return mulawData;
81
+ return mulaw.encode(pcmData);
375
82
  }
376
83
 
377
84
  // src/helpers/bufferToInt16Array.ts
@@ -504,19 +211,51 @@ function generateFadeOutSamples(lastSampleValue, fadeDurationMs, sampleRate) {
504
211
 
505
212
  // src/helpers/resamplePcm.ts
506
213
  function resamplePcm(pcm, originalSampleRate, targetSampleRate) {
214
+ if (originalSampleRate === targetSampleRate) {
215
+ return pcm;
216
+ }
507
217
  const ratio = originalSampleRate / targetSampleRate;
508
218
  const newLength = Math.floor(pcm.length / ratio);
509
219
  const newSamples = new Int16Array(newLength);
220
+ if (ratio < 1) {
221
+ for (let i = 0; i < newSamples.length; i++) {
222
+ const exactPos = i * ratio;
223
+ const lowerIndex = Math.floor(exactPos);
224
+ const upperIndex = Math.min(lowerIndex + 1, pcm.length - 1);
225
+ const fraction = exactPos - lowerIndex;
226
+ const lowerSample = pcm[lowerIndex];
227
+ const upperSample = pcm[upperIndex];
228
+ newSamples[i] = Math.round(lowerSample + (upperSample - lowerSample) * fraction);
229
+ }
230
+ return newSamples;
231
+ }
232
+ const nyquistFreq = targetSampleRate / 2;
233
+ const cutoffFreq = nyquistFreq * 0.9;
234
+ const filteredPcm = applyLowPassFilter(pcm, originalSampleRate, cutoffFreq);
510
235
  for (let i = 0; i < newSamples.length; i++) {
511
236
  const exactPos = i * ratio;
512
237
  const lowerIndex = Math.floor(exactPos);
513
- const upperIndex = Math.min(lowerIndex + 1, pcm.length - 1);
238
+ const upperIndex = Math.min(lowerIndex + 1, filteredPcm.length - 1);
514
239
  const fraction = exactPos - lowerIndex;
515
- const lowerSample = pcm[lowerIndex];
516
- const upperSample = pcm[upperIndex];
240
+ const lowerSample = filteredPcm[lowerIndex];
241
+ const upperSample = filteredPcm[upperIndex];
517
242
  newSamples[i] = Math.round(lowerSample + (upperSample - lowerSample) * fraction);
518
243
  }
519
244
  return newSamples;
520
245
  }
246
+ function applyLowPassFilter(pcm, sampleRate, cutoffFreq) {
247
+ const filterOrder = Math.max(3, Math.floor(sampleRate / (cutoffFreq * 4)));
248
+ const filtered = new Int16Array(pcm.length);
249
+ for (let i = 0; i < pcm.length; i++) {
250
+ let sum = 0;
251
+ let count = 0;
252
+ for (let j = Math.max(0, i - filterOrder); j <= Math.min(pcm.length - 1, i + filterOrder); j++) {
253
+ sum += pcm[j];
254
+ count++;
255
+ }
256
+ filtered[i] = Math.round(sum / count);
257
+ }
258
+ return filtered;
259
+ }
521
260
 
522
261
  export { bufferToInt16Array, decodeToPcm, decodeWAV, encodePcm, generateFadeOutSamples, identifyAudioFormat, int16ArrayToBuffer, mulawToPcm16, pcm16ToMulaw, resamplePcm };
package/dist/voice.js CHANGED
@@ -1,5 +1,6 @@
1
1
  'use strict';
2
2
 
3
+ var alawmulaw = require('alawmulaw');
3
4
  var sdk = require('@deepgram/sdk');
4
5
  var elevenlabsJs = require('@elevenlabs/elevenlabs-js');
5
6
  var hume = require('hume');
@@ -13,306 +14,11 @@ var OpenAI__default = /*#__PURE__*/_interopDefault(OpenAI);
13
14
  function bufferToInt16Array(buffer) {
14
15
  return new Int16Array(buffer.buffer, buffer.byteOffset, buffer.byteLength / 2);
15
16
  }
16
-
17
- // src/decoders/mulaw.ts
18
17
  function mulawToPcm16(mulawData) {
19
- const pcmData = new Int16Array(mulawData.length);
20
- for (let i = 0; i < mulawData.length; i++) {
21
- pcmData[i] = mulawToLinear(mulawData[i]);
22
- }
23
- return pcmData;
24
- }
25
- function mulawToLinear(mulawByte) {
26
- const inverted = mulawByte ^ 255;
27
- const sign = inverted & 128;
28
- const segment = (inverted & 112) >> 4;
29
- const step = inverted & 15;
30
- let linear;
31
- if (segment === 0) {
32
- linear = (step << 1) + 1;
33
- } else {
34
- linear = (step << 1) + 1 + 32 << segment + 2;
35
- }
36
- linear -= 33;
37
- return sign ? -linear : linear;
38
- }
39
-
40
- // src/encoders/mulaw.ts
41
- var BIAS = 132;
42
- var CLIP = 32635;
43
- var encodeTable = [
44
- 0,
45
- 0,
46
- 1,
47
- 1,
48
- 2,
49
- 2,
50
- 2,
51
- 2,
52
- 3,
53
- 3,
54
- 3,
55
- 3,
56
- 3,
57
- 3,
58
- 3,
59
- 3,
60
- 4,
61
- 4,
62
- 4,
63
- 4,
64
- 4,
65
- 4,
66
- 4,
67
- 4,
68
- 4,
69
- 4,
70
- 4,
71
- 4,
72
- 4,
73
- 4,
74
- 4,
75
- 4,
76
- 5,
77
- 5,
78
- 5,
79
- 5,
80
- 5,
81
- 5,
82
- 5,
83
- 5,
84
- 5,
85
- 5,
86
- 5,
87
- 5,
88
- 5,
89
- 5,
90
- 5,
91
- 5,
92
- 5,
93
- 5,
94
- 5,
95
- 5,
96
- 5,
97
- 5,
98
- 5,
99
- 5,
100
- 5,
101
- 5,
102
- 5,
103
- 5,
104
- 5,
105
- 5,
106
- 5,
107
- 5,
108
- 6,
109
- 6,
110
- 6,
111
- 6,
112
- 6,
113
- 6,
114
- 6,
115
- 6,
116
- 6,
117
- 6,
118
- 6,
119
- 6,
120
- 6,
121
- 6,
122
- 6,
123
- 6,
124
- 6,
125
- 6,
126
- 6,
127
- 6,
128
- 6,
129
- 6,
130
- 6,
131
- 6,
132
- 6,
133
- 6,
134
- 6,
135
- 6,
136
- 6,
137
- 6,
138
- 6,
139
- 6,
140
- 6,
141
- 6,
142
- 6,
143
- 6,
144
- 6,
145
- 6,
146
- 6,
147
- 6,
148
- 6,
149
- 6,
150
- 6,
151
- 6,
152
- 6,
153
- 6,
154
- 6,
155
- 6,
156
- 6,
157
- 6,
158
- 6,
159
- 6,
160
- 6,
161
- 6,
162
- 6,
163
- 6,
164
- 6,
165
- 6,
166
- 6,
167
- 6,
168
- 6,
169
- 6,
170
- 6,
171
- 6,
172
- 7,
173
- 7,
174
- 7,
175
- 7,
176
- 7,
177
- 7,
178
- 7,
179
- 7,
180
- 7,
181
- 7,
182
- 7,
183
- 7,
184
- 7,
185
- 7,
186
- 7,
187
- 7,
188
- 7,
189
- 7,
190
- 7,
191
- 7,
192
- 7,
193
- 7,
194
- 7,
195
- 7,
196
- 7,
197
- 7,
198
- 7,
199
- 7,
200
- 7,
201
- 7,
202
- 7,
203
- 7,
204
- 7,
205
- 7,
206
- 7,
207
- 7,
208
- 7,
209
- 7,
210
- 7,
211
- 7,
212
- 7,
213
- 7,
214
- 7,
215
- 7,
216
- 7,
217
- 7,
218
- 7,
219
- 7,
220
- 7,
221
- 7,
222
- 7,
223
- 7,
224
- 7,
225
- 7,
226
- 7,
227
- 7,
228
- 7,
229
- 7,
230
- 7,
231
- 7,
232
- 7,
233
- 7,
234
- 7,
235
- 7,
236
- 7,
237
- 7,
238
- 7,
239
- 7,
240
- 7,
241
- 7,
242
- 7,
243
- 7,
244
- 7,
245
- 7,
246
- 7,
247
- 7,
248
- 7,
249
- 7,
250
- 7,
251
- 7,
252
- 7,
253
- 7,
254
- 7,
255
- 7,
256
- 7,
257
- 7,
258
- 7,
259
- 7,
260
- 7,
261
- 7,
262
- 7,
263
- 7,
264
- 7,
265
- 7,
266
- 7,
267
- 7,
268
- 7,
269
- 7,
270
- 7,
271
- 7,
272
- 7,
273
- 7,
274
- 7,
275
- 7,
276
- 7,
277
- 7,
278
- 7,
279
- 7,
280
- 7,
281
- 7,
282
- 7,
283
- 7,
284
- 7,
285
- 7,
286
- 7,
287
- 7,
288
- 7,
289
- 7,
290
- 7,
291
- 7,
292
- 7,
293
- 7,
294
- 7,
295
- 7,
296
- 7,
297
- 7,
298
- 7,
299
- 7
300
- ];
301
- function encodeSample(sample) {
302
- const sign = sample >> 8 & 128;
303
- if (sign !== 0) sample = -sample;
304
- sample = sample + BIAS;
305
- if (sample > CLIP) sample = CLIP;
306
- const exponent = encodeTable[sample >> 7 & 255];
307
- const mantissa = sample >> exponent + 3 & 15;
308
- return ~(sign | exponent << 4 | mantissa);
18
+ return alawmulaw.mulaw.decode(mulawData);
309
19
  }
310
20
  function pcm16ToMulaw(pcmData) {
311
- const mulawData = new Uint8Array(pcmData.length);
312
- for (let i = 0; i < pcmData.length; i++) {
313
- mulawData[i] = encodeSample(pcmData[i]);
314
- }
315
- return mulawData;
21
+ return alawmulaw.mulaw.encode(pcmData);
316
22
  }
317
23
 
318
24
  // src/helpers/int16ArrayToBuffer.ts
@@ -355,20 +61,52 @@ function generateFadeOutSamples(lastSampleValue, fadeDurationMs, sampleRate) {
355
61
 
356
62
  // src/helpers/resamplePcm.ts
357
63
  function resamplePcm(pcm, originalSampleRate, targetSampleRate) {
64
+ if (originalSampleRate === targetSampleRate) {
65
+ return pcm;
66
+ }
358
67
  const ratio = originalSampleRate / targetSampleRate;
359
68
  const newLength = Math.floor(pcm.length / ratio);
360
69
  const newSamples = new Int16Array(newLength);
70
+ if (ratio < 1) {
71
+ for (let i = 0; i < newSamples.length; i++) {
72
+ const exactPos = i * ratio;
73
+ const lowerIndex = Math.floor(exactPos);
74
+ const upperIndex = Math.min(lowerIndex + 1, pcm.length - 1);
75
+ const fraction = exactPos - lowerIndex;
76
+ const lowerSample = pcm[lowerIndex];
77
+ const upperSample = pcm[upperIndex];
78
+ newSamples[i] = Math.round(lowerSample + (upperSample - lowerSample) * fraction);
79
+ }
80
+ return newSamples;
81
+ }
82
+ const nyquistFreq = targetSampleRate / 2;
83
+ const cutoffFreq = nyquistFreq * 0.9;
84
+ const filteredPcm = applyLowPassFilter(pcm, originalSampleRate, cutoffFreq);
361
85
  for (let i = 0; i < newSamples.length; i++) {
362
86
  const exactPos = i * ratio;
363
87
  const lowerIndex = Math.floor(exactPos);
364
- const upperIndex = Math.min(lowerIndex + 1, pcm.length - 1);
88
+ const upperIndex = Math.min(lowerIndex + 1, filteredPcm.length - 1);
365
89
  const fraction = exactPos - lowerIndex;
366
- const lowerSample = pcm[lowerIndex];
367
- const upperSample = pcm[upperIndex];
90
+ const lowerSample = filteredPcm[lowerIndex];
91
+ const upperSample = filteredPcm[upperIndex];
368
92
  newSamples[i] = Math.round(lowerSample + (upperSample - lowerSample) * fraction);
369
93
  }
370
94
  return newSamples;
371
95
  }
96
+ function applyLowPassFilter(pcm, sampleRate, cutoffFreq) {
97
+ const filterOrder = Math.max(3, Math.floor(sampleRate / (cutoffFreq * 4)));
98
+ const filtered = new Int16Array(pcm.length);
99
+ for (let i = 0; i < pcm.length; i++) {
100
+ let sum = 0;
101
+ let count = 0;
102
+ for (let j = Math.max(0, i - filterOrder); j <= Math.min(pcm.length - 1, i + filterOrder); j++) {
103
+ sum += pcm[j];
104
+ count++;
105
+ }
106
+ filtered[i] = Math.round(sum / count);
107
+ }
108
+ return filtered;
109
+ }
372
110
 
373
111
  // src/voice/helpers.ts
374
112
  function splitTextIntoChunks(text, targetLength = 100) {
package/dist/voice.mjs CHANGED
@@ -1,3 +1,4 @@
1
+ import { mulaw } from 'alawmulaw';
1
2
  import { DeepgramClient, LiveTranscriptionEvents } from '@deepgram/sdk';
2
3
  import { ElevenLabsClient } from '@elevenlabs/elevenlabs-js';
3
4
  import { HumeClient } from 'hume';
@@ -7,306 +8,11 @@ import OpenAI from 'openai';
7
8
  function bufferToInt16Array(buffer) {
8
9
  return new Int16Array(buffer.buffer, buffer.byteOffset, buffer.byteLength / 2);
9
10
  }
10
-
11
- // src/decoders/mulaw.ts
12
11
  function mulawToPcm16(mulawData) {
13
- const pcmData = new Int16Array(mulawData.length);
14
- for (let i = 0; i < mulawData.length; i++) {
15
- pcmData[i] = mulawToLinear(mulawData[i]);
16
- }
17
- return pcmData;
18
- }
19
- function mulawToLinear(mulawByte) {
20
- const inverted = mulawByte ^ 255;
21
- const sign = inverted & 128;
22
- const segment = (inverted & 112) >> 4;
23
- const step = inverted & 15;
24
- let linear;
25
- if (segment === 0) {
26
- linear = (step << 1) + 1;
27
- } else {
28
- linear = (step << 1) + 1 + 32 << segment + 2;
29
- }
30
- linear -= 33;
31
- return sign ? -linear : linear;
32
- }
33
-
34
- // src/encoders/mulaw.ts
35
- var BIAS = 132;
36
- var CLIP = 32635;
37
- var encodeTable = [
38
- 0,
39
- 0,
40
- 1,
41
- 1,
42
- 2,
43
- 2,
44
- 2,
45
- 2,
46
- 3,
47
- 3,
48
- 3,
49
- 3,
50
- 3,
51
- 3,
52
- 3,
53
- 3,
54
- 4,
55
- 4,
56
- 4,
57
- 4,
58
- 4,
59
- 4,
60
- 4,
61
- 4,
62
- 4,
63
- 4,
64
- 4,
65
- 4,
66
- 4,
67
- 4,
68
- 4,
69
- 4,
70
- 5,
71
- 5,
72
- 5,
73
- 5,
74
- 5,
75
- 5,
76
- 5,
77
- 5,
78
- 5,
79
- 5,
80
- 5,
81
- 5,
82
- 5,
83
- 5,
84
- 5,
85
- 5,
86
- 5,
87
- 5,
88
- 5,
89
- 5,
90
- 5,
91
- 5,
92
- 5,
93
- 5,
94
- 5,
95
- 5,
96
- 5,
97
- 5,
98
- 5,
99
- 5,
100
- 5,
101
- 5,
102
- 6,
103
- 6,
104
- 6,
105
- 6,
106
- 6,
107
- 6,
108
- 6,
109
- 6,
110
- 6,
111
- 6,
112
- 6,
113
- 6,
114
- 6,
115
- 6,
116
- 6,
117
- 6,
118
- 6,
119
- 6,
120
- 6,
121
- 6,
122
- 6,
123
- 6,
124
- 6,
125
- 6,
126
- 6,
127
- 6,
128
- 6,
129
- 6,
130
- 6,
131
- 6,
132
- 6,
133
- 6,
134
- 6,
135
- 6,
136
- 6,
137
- 6,
138
- 6,
139
- 6,
140
- 6,
141
- 6,
142
- 6,
143
- 6,
144
- 6,
145
- 6,
146
- 6,
147
- 6,
148
- 6,
149
- 6,
150
- 6,
151
- 6,
152
- 6,
153
- 6,
154
- 6,
155
- 6,
156
- 6,
157
- 6,
158
- 6,
159
- 6,
160
- 6,
161
- 6,
162
- 6,
163
- 6,
164
- 6,
165
- 6,
166
- 7,
167
- 7,
168
- 7,
169
- 7,
170
- 7,
171
- 7,
172
- 7,
173
- 7,
174
- 7,
175
- 7,
176
- 7,
177
- 7,
178
- 7,
179
- 7,
180
- 7,
181
- 7,
182
- 7,
183
- 7,
184
- 7,
185
- 7,
186
- 7,
187
- 7,
188
- 7,
189
- 7,
190
- 7,
191
- 7,
192
- 7,
193
- 7,
194
- 7,
195
- 7,
196
- 7,
197
- 7,
198
- 7,
199
- 7,
200
- 7,
201
- 7,
202
- 7,
203
- 7,
204
- 7,
205
- 7,
206
- 7,
207
- 7,
208
- 7,
209
- 7,
210
- 7,
211
- 7,
212
- 7,
213
- 7,
214
- 7,
215
- 7,
216
- 7,
217
- 7,
218
- 7,
219
- 7,
220
- 7,
221
- 7,
222
- 7,
223
- 7,
224
- 7,
225
- 7,
226
- 7,
227
- 7,
228
- 7,
229
- 7,
230
- 7,
231
- 7,
232
- 7,
233
- 7,
234
- 7,
235
- 7,
236
- 7,
237
- 7,
238
- 7,
239
- 7,
240
- 7,
241
- 7,
242
- 7,
243
- 7,
244
- 7,
245
- 7,
246
- 7,
247
- 7,
248
- 7,
249
- 7,
250
- 7,
251
- 7,
252
- 7,
253
- 7,
254
- 7,
255
- 7,
256
- 7,
257
- 7,
258
- 7,
259
- 7,
260
- 7,
261
- 7,
262
- 7,
263
- 7,
264
- 7,
265
- 7,
266
- 7,
267
- 7,
268
- 7,
269
- 7,
270
- 7,
271
- 7,
272
- 7,
273
- 7,
274
- 7,
275
- 7,
276
- 7,
277
- 7,
278
- 7,
279
- 7,
280
- 7,
281
- 7,
282
- 7,
283
- 7,
284
- 7,
285
- 7,
286
- 7,
287
- 7,
288
- 7,
289
- 7,
290
- 7,
291
- 7,
292
- 7,
293
- 7
294
- ];
295
- function encodeSample(sample) {
296
- const sign = sample >> 8 & 128;
297
- if (sign !== 0) sample = -sample;
298
- sample = sample + BIAS;
299
- if (sample > CLIP) sample = CLIP;
300
- const exponent = encodeTable[sample >> 7 & 255];
301
- const mantissa = sample >> exponent + 3 & 15;
302
- return ~(sign | exponent << 4 | mantissa);
12
+ return mulaw.decode(mulawData);
303
13
  }
304
14
  function pcm16ToMulaw(pcmData) {
305
- const mulawData = new Uint8Array(pcmData.length);
306
- for (let i = 0; i < pcmData.length; i++) {
307
- mulawData[i] = encodeSample(pcmData[i]);
308
- }
309
- return mulawData;
15
+ return mulaw.encode(pcmData);
310
16
  }
311
17
 
312
18
  // src/helpers/int16ArrayToBuffer.ts
@@ -349,20 +55,52 @@ function generateFadeOutSamples(lastSampleValue, fadeDurationMs, sampleRate) {
349
55
 
350
56
  // src/helpers/resamplePcm.ts
351
57
  function resamplePcm(pcm, originalSampleRate, targetSampleRate) {
58
+ if (originalSampleRate === targetSampleRate) {
59
+ return pcm;
60
+ }
352
61
  const ratio = originalSampleRate / targetSampleRate;
353
62
  const newLength = Math.floor(pcm.length / ratio);
354
63
  const newSamples = new Int16Array(newLength);
64
+ if (ratio < 1) {
65
+ for (let i = 0; i < newSamples.length; i++) {
66
+ const exactPos = i * ratio;
67
+ const lowerIndex = Math.floor(exactPos);
68
+ const upperIndex = Math.min(lowerIndex + 1, pcm.length - 1);
69
+ const fraction = exactPos - lowerIndex;
70
+ const lowerSample = pcm[lowerIndex];
71
+ const upperSample = pcm[upperIndex];
72
+ newSamples[i] = Math.round(lowerSample + (upperSample - lowerSample) * fraction);
73
+ }
74
+ return newSamples;
75
+ }
76
+ const nyquistFreq = targetSampleRate / 2;
77
+ const cutoffFreq = nyquistFreq * 0.9;
78
+ const filteredPcm = applyLowPassFilter(pcm, originalSampleRate, cutoffFreq);
355
79
  for (let i = 0; i < newSamples.length; i++) {
356
80
  const exactPos = i * ratio;
357
81
  const lowerIndex = Math.floor(exactPos);
358
- const upperIndex = Math.min(lowerIndex + 1, pcm.length - 1);
82
+ const upperIndex = Math.min(lowerIndex + 1, filteredPcm.length - 1);
359
83
  const fraction = exactPos - lowerIndex;
360
- const lowerSample = pcm[lowerIndex];
361
- const upperSample = pcm[upperIndex];
84
+ const lowerSample = filteredPcm[lowerIndex];
85
+ const upperSample = filteredPcm[upperIndex];
362
86
  newSamples[i] = Math.round(lowerSample + (upperSample - lowerSample) * fraction);
363
87
  }
364
88
  return newSamples;
365
89
  }
90
+ function applyLowPassFilter(pcm, sampleRate, cutoffFreq) {
91
+ const filterOrder = Math.max(3, Math.floor(sampleRate / (cutoffFreq * 4)));
92
+ const filtered = new Int16Array(pcm.length);
93
+ for (let i = 0; i < pcm.length; i++) {
94
+ let sum = 0;
95
+ let count = 0;
96
+ for (let j = Math.max(0, i - filterOrder); j <= Math.min(pcm.length - 1, i + filterOrder); j++) {
97
+ sum += pcm[j];
98
+ count++;
99
+ }
100
+ filtered[i] = Math.round(sum / count);
101
+ }
102
+ return filtered;
103
+ }
366
104
 
367
105
  // src/voice/helpers.ts
368
106
  function splitTextIntoChunks(text, targetLength = 100) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pompeii-labs/audio",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "The Audio SDK from Pompeii Labs",
5
5
  "keywords": [
6
6
  "Pompeii",
@@ -44,7 +44,8 @@
44
44
  "@deepgram/sdk": "4.2.0",
45
45
  "@elevenlabs/elevenlabs-js": "2.2.0",
46
46
  "hume": "0.11.1",
47
- "openai": "4.86.2"
47
+ "openai": "4.86.2",
48
+ "alawmulaw": "^6.0.0"
48
49
  },
49
50
  "devDependencies": {
50
51
  "@types/node": "^22.16.0",