@picovoice/eagle-web 0.1.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/eagle.ts CHANGED
@@ -25,7 +25,15 @@ import {
25
25
 
26
26
  import { simd } from 'wasm-feature-detect';
27
27
 
28
- import { EagleModel, EagleProfile, EagleProfilerEnrollResult } from './types';
28
+ import {
29
+ EagleModel,
30
+ EagleProfile,
31
+ EagleProfilerEnrollResult,
32
+ PvStatus
33
+ } from './types';
34
+
35
+ import * as EagleErrors from './eagle_errors';
36
+ import { pvStatusToException } from './eagle_errors';
29
37
 
30
38
  /**
31
39
  * WebAssembly function types
@@ -74,6 +82,12 @@ type pv_eagle_frame_length_type = () => Promise<number>;
74
82
  type pv_eagle_version_type = () => Promise<number>;
75
83
  type pv_sample_rate_type = () => Promise<number>;
76
84
  type pv_status_to_string_type = (status: number) => Promise<number>;
85
+ type pv_set_sdk_type = (sdk: number) => Promise<void>;
86
+ type pv_get_error_stack_type = (
87
+ messageStack: number,
88
+ messageStackDepth: number
89
+ ) => Promise<number>;
90
+ type pv_free_error_stack_type = (messageStack: number) => Promise<void>;
77
91
 
78
92
  type EagleBaseWasmOutput = {
79
93
  memory: WebAssembly.Memory;
@@ -84,7 +98,13 @@ type EagleBaseWasmOutput = {
84
98
  sampleRate: number;
85
99
  version: string;
86
100
 
101
+ messageStackAddressAddressAddress: number;
102
+ messageStackDepthAddress: number;
103
+
87
104
  pvStatusToString: pv_status_to_string_type;
105
+ pvGetErrorStack: pv_get_error_stack_type;
106
+ pvFreeErrorStack: pv_free_error_stack_type;
107
+
88
108
  exports: any;
89
109
  };
90
110
 
@@ -122,11 +142,18 @@ class EagleBase {
122
142
  protected readonly _pvFree: pv_free_type;
123
143
  protected readonly _functionMutex: Mutex;
124
144
 
145
+ protected readonly _pvGetErrorStack: pv_get_error_stack_type;
146
+ protected readonly _pvFreeErrorStack: pv_free_error_stack_type;
147
+
148
+ protected readonly _messageStackAddressAddressAddress: number;
149
+ protected readonly _messageStackDepthAddress: number;
150
+
125
151
  protected static _sampleRate: number;
126
152
  protected static _version: string;
127
153
 
128
154
  protected static _wasm: string;
129
155
  protected static _wasmSimd: string;
156
+ protected static _sdk: string = 'web';
130
157
 
131
158
  protected static _eagleMutex = new Mutex();
132
159
 
@@ -143,6 +170,12 @@ class EagleBase {
143
170
  this._pvFree = handleWasm.pvFree;
144
171
  this._pvError = handleWasm.pvError;
145
172
 
173
+ this._pvGetErrorStack = handleWasm.pvGetErrorStack;
174
+ this._pvFreeErrorStack = handleWasm.pvFreeErrorStack;
175
+
176
+ this._messageStackAddressAddressAddress = handleWasm.messageStackAddressAddressAddress;
177
+ this._messageStackDepthAddress = handleWasm.messageStackDepthAddress;
178
+
146
179
  this._functionMutex = new Mutex();
147
180
  }
148
181
 
@@ -180,6 +213,10 @@ class EagleBase {
180
213
  }
181
214
  }
182
215
 
216
+ public static setSdk(sdk: string): void {
217
+ EagleBase._sdk = sdk;
218
+ }
219
+
183
220
  protected static async _initBaseWasm(
184
221
  wasmBase64: string,
185
222
  wasmMemorySize: number
@@ -196,6 +233,11 @@ class EagleBase {
196
233
  const pv_sample_rate = exports.pv_sample_rate as pv_sample_rate_type;
197
234
  const pv_status_to_string =
198
235
  exports.pv_status_to_string as pv_status_to_string_type;
236
+ const pv_set_sdk = exports.pv_set_sdk as pv_set_sdk_type;
237
+ const pv_get_error_stack =
238
+ exports.pv_get_error_stack as pv_get_error_stack_type;
239
+ const pv_free_error_stack =
240
+ exports.pv_free_error_stack as pv_free_error_stack_type;
199
241
 
200
242
  const sampleRate = await pv_sample_rate();
201
243
  const versionAddress = await pv_eagle_version();
@@ -204,6 +246,40 @@ class EagleBase {
204
246
  versionAddress
205
247
  );
206
248
 
249
+ const sdkEncoded = new TextEncoder().encode(this._sdk);
250
+ const sdkAddress = await aligned_alloc(
251
+ Uint8Array.BYTES_PER_ELEMENT,
252
+ (sdkEncoded.length + 1) * Uint8Array.BYTES_PER_ELEMENT
253
+ );
254
+ if (!sdkAddress) {
255
+ throw new EagleErrors.EagleOutOfMemoryError(
256
+ 'malloc failed: Cannot allocate memory'
257
+ );
258
+ }
259
+ memoryBufferUint8.set(sdkEncoded, sdkAddress);
260
+ memoryBufferUint8[sdkAddress + sdkEncoded.length] = 0;
261
+ await pv_set_sdk(sdkAddress);
262
+
263
+ const messageStackDepthAddress = await aligned_alloc(
264
+ Int32Array.BYTES_PER_ELEMENT,
265
+ Int32Array.BYTES_PER_ELEMENT
266
+ );
267
+ if (!messageStackDepthAddress) {
268
+ throw new EagleErrors.EagleOutOfMemoryError(
269
+ 'malloc failed: Cannot allocate memory'
270
+ );
271
+ }
272
+
273
+ const messageStackAddressAddressAddress = await aligned_alloc(
274
+ Int32Array.BYTES_PER_ELEMENT,
275
+ Int32Array.BYTES_PER_ELEMENT
276
+ );
277
+ if (!messageStackAddressAddressAddress) {
278
+ throw new EagleErrors.EagleOutOfMemoryError(
279
+ 'malloc failed: Cannot allocate memory'
280
+ );
281
+ }
282
+
207
283
  return {
208
284
  memory: memory,
209
285
  alignedAlloc: aligned_alloc,
@@ -213,10 +289,67 @@ class EagleBase {
213
289
  sampleRate: sampleRate,
214
290
  version: version,
215
291
 
292
+ messageStackAddressAddressAddress: messageStackAddressAddressAddress,
293
+ messageStackDepthAddress: messageStackDepthAddress,
294
+
216
295
  pvStatusToString: pv_status_to_string,
296
+ pvGetErrorStack: pv_get_error_stack,
297
+ pvFreeErrorStack: pv_free_error_stack,
298
+
217
299
  exports: exports,
218
300
  };
219
301
  }
302
+
303
+ /**
304
+ * Releases resources acquired by Eagle
305
+ */
306
+ public async release(): Promise<void> {
307
+ await this._pvFree(this._messageStackAddressAddressAddress);
308
+ await this._pvFree(this._messageStackDepthAddress);
309
+ }
310
+
311
+ protected static async getMessageStack(
312
+ pv_get_error_stack: pv_get_error_stack_type,
313
+ pv_free_error_stack: pv_free_error_stack_type,
314
+ messageStackAddressAddressAddress: number,
315
+ messageStackDepthAddress: number,
316
+ memoryBufferView: DataView,
317
+ memoryBufferUint8: Uint8Array
318
+ ): Promise<string[]> {
319
+ const status = await pv_get_error_stack(
320
+ messageStackAddressAddressAddress,
321
+ messageStackDepthAddress
322
+ );
323
+ if (status !== PvStatus.SUCCESS) {
324
+ throw pvStatusToException(status, 'Unable to get Eagle error state');
325
+ }
326
+
327
+ const messageStackAddressAddress = memoryBufferView.getInt32(
328
+ messageStackAddressAddressAddress,
329
+ true
330
+ );
331
+
332
+ const messageStackDepth = memoryBufferView.getInt32(
333
+ messageStackDepthAddress,
334
+ true
335
+ );
336
+ const messageStack: string[] = [];
337
+ for (let i = 0; i < messageStackDepth; i++) {
338
+ const messageStackAddress = memoryBufferView.getInt32(
339
+ messageStackAddressAddress + i * Int32Array.BYTES_PER_ELEMENT,
340
+ true
341
+ );
342
+ const message = arrayBufferToStringAtIndex(
343
+ memoryBufferUint8,
344
+ messageStackAddress
345
+ );
346
+ messageStack.push(message);
347
+ }
348
+
349
+ await pv_free_error_stack(messageStackAddressAddress);
350
+
351
+ return messageStack;
352
+ }
220
353
  }
221
354
 
222
355
  /**
@@ -289,7 +422,7 @@ export class EagleProfiler extends EagleBase {
289
422
  modelPath: string
290
423
  ): Promise<EagleProfiler> {
291
424
  if (!isAccessKeyValid(accessKey)) {
292
- throw new Error('Invalid AccessKey');
425
+ throw new EagleErrors.EagleInvalidArgumentError('Invalid AccessKey');
293
426
  }
294
427
 
295
428
  return new Promise<EagleProfiler>((resolve, reject) => {
@@ -339,11 +472,11 @@ export class EagleProfiler extends EagleBase {
339
472
  */
340
473
  public async enroll(pcm: Int16Array): Promise<EagleProfilerEnrollResult> {
341
474
  if (!(pcm instanceof Int16Array)) {
342
- throw new Error("The argument 'pcm' must be provided as an Int16Array");
475
+ throw new EagleErrors.EagleInvalidArgumentError("The argument 'pcm' must be provided as an Int16Array");
343
476
  }
344
477
 
345
478
  if (pcm.length > EagleProfiler._maxEnrollSamples) {
346
- throw new Error(
479
+ throw new EagleErrors.EagleInvalidArgumentError(
347
480
  `'pcm' size must be smaller than ${EagleProfiler._maxEnrollSamples}`
348
481
  );
349
482
  }
@@ -352,7 +485,7 @@ export class EagleProfiler extends EagleBase {
352
485
  this._functionMutex
353
486
  .runExclusive(async () => {
354
487
  if (this._wasmMemory === undefined) {
355
- throw new Error('Attempted to call `.enroll()` after release');
488
+ throw new EagleErrors.EagleInvalidStateError('Attempted to call `.enroll()` after release');
356
489
  }
357
490
 
358
491
  const pcmAddress = await this._alignedAlloc(
@@ -365,14 +498,14 @@ export class EagleProfiler extends EagleBase {
365
498
  Int32Array.BYTES_PER_ELEMENT
366
499
  );
367
500
  if (feedbackAddress === 0) {
368
- throw new Error('malloc failed: Cannot allocate memory');
501
+ throw new EagleErrors.EagleOutOfMemoryError('malloc failed: Cannot allocate memory');
369
502
  }
370
503
  const percentageAddress = await this._alignedAlloc(
371
504
  Int32Array.BYTES_PER_ELEMENT,
372
505
  Int32Array.BYTES_PER_ELEMENT
373
506
  );
374
507
  if (percentageAddress === 0) {
375
- throw new Error('malloc failed: Cannot allocate memory');
508
+ throw new EagleErrors.EagleOutOfMemoryError('malloc failed: Cannot allocate memory');
376
509
  }
377
510
 
378
511
  const memoryBufferInt16 = new Int16Array(this._wasmMemory.buffer);
@@ -390,14 +523,19 @@ export class EagleProfiler extends EagleBase {
390
523
  await this._pvFree(feedbackAddress);
391
524
  await this._pvFree(percentageAddress);
392
525
 
526
+ const memoryBufferView = new DataView(this._wasmMemory.buffer);
393
527
  const memoryBufferUint8 = new Uint8Array(this._wasmMemory.buffer);
394
528
 
395
- throw new Error(
396
- `enroll failed with status ${arrayBufferToStringAtIndex(
397
- memoryBufferUint8,
398
- await this._pvStatusToString(status)
399
- )}`
529
+ const messageStack = await EagleProfiler.getMessageStack(
530
+ this._pvGetErrorStack,
531
+ this._pvFreeErrorStack,
532
+ this._messageStackAddressAddressAddress,
533
+ this._messageStackDepthAddress,
534
+ memoryBufferView,
535
+ memoryBufferUint8
400
536
  );
537
+
538
+ throw pvStatusToException(status, "EagleProfiler enroll failed", messageStack);
401
539
  }
402
540
 
403
541
  const memoryBufferView = new DataView(this._wasmMemory.buffer);
@@ -437,7 +575,7 @@ export class EagleProfiler extends EagleBase {
437
575
  this._functionMutex
438
576
  .runExclusive(async () => {
439
577
  if (this._wasmMemory === undefined) {
440
- throw new Error('Attempted to call `.export()` after release');
578
+ throw new EagleErrors.EagleInvalidStateError('Attempted to call `.export()` after release');
441
579
  }
442
580
 
443
581
  const profileAddress = await this._alignedAlloc(
@@ -451,13 +589,20 @@ export class EagleProfiler extends EagleBase {
451
589
  );
452
590
  if (status !== PV_STATUS_SUCCESS) {
453
591
  await this._pvFree(profileAddress);
592
+
593
+ const memoryBufferView = new DataView(this._wasmMemory.buffer);
454
594
  const memoryBufferUint8 = new Uint8Array(this._wasmMemory.buffer);
455
- throw new Error(
456
- `export failed with status ${arrayBufferToStringAtIndex(
457
- memoryBufferUint8,
458
- await this._pvStatusToString(status)
459
- )}`
595
+
596
+ const messageStack = await EagleProfiler.getMessageStack(
597
+ this._pvGetErrorStack,
598
+ this._pvFreeErrorStack,
599
+ this._messageStackAddressAddressAddress,
600
+ this._messageStackDepthAddress,
601
+ memoryBufferView,
602
+ memoryBufferUint8
460
603
  );
604
+
605
+ throw pvStatusToException(status, "EagleProfiler export failed", messageStack);
461
606
  }
462
607
 
463
608
  const memoryBufferUint8 = new Uint8Array(this._wasmMemory.buffer);
@@ -489,18 +634,24 @@ export class EagleProfiler extends EagleBase {
489
634
  this._functionMutex
490
635
  .runExclusive(async () => {
491
636
  if (this._wasmMemory === undefined) {
492
- throw new Error('Attempted to call `.reset()` after release');
637
+ throw new EagleErrors.EagleInvalidStateError('Attempted to call `.reset()` after release');
493
638
  }
494
639
 
495
640
  const status = await this._pvEagleProfilerReset(this._objectAddress);
496
641
  if (status !== PV_STATUS_SUCCESS) {
642
+ const memoryBufferView = new DataView(this._wasmMemory.buffer);
497
643
  const memoryBufferUint8 = new Uint8Array(this._wasmMemory.buffer);
498
- throw new Error(
499
- `reset failed with status ${arrayBufferToStringAtIndex(
500
- memoryBufferUint8,
501
- await this._pvStatusToString(status)
502
- )}`
644
+
645
+ const messageStack = await EagleProfiler.getMessageStack(
646
+ this._pvGetErrorStack,
647
+ this._pvFreeErrorStack,
648
+ this._messageStackAddressAddressAddress,
649
+ this._messageStackDepthAddress,
650
+ memoryBufferView,
651
+ memoryBufferUint8
503
652
  );
653
+
654
+ throw pvStatusToException(status, "EagleProfiler reset failed", messageStack);
504
655
  }
505
656
  })
506
657
  .then(() => {
@@ -516,6 +667,7 @@ export class EagleProfiler extends EagleBase {
516
667
  * Releases resources acquired by Eagle Profiler
517
668
  */
518
669
  public async release(): Promise<void> {
670
+ await super.release();
519
671
  await this._pvEagleProfilerDelete(this._objectAddress);
520
672
  delete this._wasmMemory;
521
673
  this._wasmMemory = undefined;
@@ -550,7 +702,7 @@ export class EagleProfiler extends EagleBase {
550
702
  Int32Array.BYTES_PER_ELEMENT
551
703
  );
552
704
  if (objectAddressAddress === 0) {
553
- throw new Error('malloc failed: Cannot allocate memory');
705
+ throw new EagleErrors.EagleOutOfMemoryError('malloc failed: Cannot allocate memory');
554
706
  }
555
707
 
556
708
  const accessKeyAddress = await baseWasmOutput.alignedAlloc(
@@ -558,7 +710,7 @@ export class EagleProfiler extends EagleBase {
558
710
  (accessKey.length + 1) * Uint8Array.BYTES_PER_ELEMENT
559
711
  );
560
712
  if (accessKeyAddress === 0) {
561
- throw new Error('malloc failed: Cannot allocate memory');
713
+ throw new EagleErrors.EagleOutOfMemoryError('malloc failed: Cannot allocate memory');
562
714
  }
563
715
  for (let i = 0; i < accessKey.length; i++) {
564
716
  memoryBufferUint8[accessKeyAddress + i] = accessKey.charCodeAt(i);
@@ -571,7 +723,7 @@ export class EagleProfiler extends EagleBase {
571
723
  (modelPathEncoded.length + 1) * Uint8Array.BYTES_PER_ELEMENT
572
724
  );
573
725
  if (modelPathAddress === 0) {
574
- throw new Error('malloc failed: Cannot allocate memory');
726
+ throw new EagleErrors.EagleOutOfMemoryError('malloc failed: Cannot allocate memory');
575
727
  }
576
728
  memoryBufferUint8.set(modelPathEncoded, modelPathAddress);
577
729
  memoryBufferUint8[modelPathAddress + modelPathEncoded.length] = 0;
@@ -583,18 +735,22 @@ export class EagleProfiler extends EagleBase {
583
735
  );
584
736
  await baseWasmOutput.pvFree(accessKeyAddress);
585
737
  await baseWasmOutput.pvFree(modelPathAddress);
586
- if (status !== PV_STATUS_SUCCESS) {
587
- const msg = `'pv_eagle_profiler_init' failed with status ${arrayBufferToStringAtIndex(
588
- memoryBufferUint8,
589
- await baseWasmOutput.pvStatusToString(status)
590
- )}`;
591
738
 
592
- throw new Error(
593
- `${msg}\nDetails: ${baseWasmOutput.pvError.getErrorString()}`
739
+ const memoryBufferView = new DataView(baseWasmOutput.memory.buffer);
740
+
741
+ if (status !== PV_STATUS_SUCCESS) {
742
+ const messageStack = await EagleProfiler.getMessageStack(
743
+ baseWasmOutput.pvGetErrorStack,
744
+ baseWasmOutput.pvFreeErrorStack,
745
+ baseWasmOutput.messageStackAddressAddressAddress,
746
+ baseWasmOutput.messageStackDepthAddress,
747
+ memoryBufferView,
748
+ memoryBufferUint8
594
749
  );
750
+
751
+ throw pvStatusToException(status, "EagleProfiler init failed", messageStack, baseWasmOutput.pvError);
595
752
  }
596
753
 
597
- const memoryBufferView = new DataView(baseWasmOutput.memory.buffer);
598
754
  const objectAddress = memoryBufferView.getInt32(objectAddressAddress, true);
599
755
  await baseWasmOutput.pvFree(objectAddressAddress);
600
756
 
@@ -603,7 +759,7 @@ export class EagleProfiler extends EagleBase {
603
759
  Int32Array.BYTES_PER_ELEMENT
604
760
  );
605
761
  if (minEnrollSamplesAddress === 0) {
606
- throw new Error('malloc failed: Cannot allocate memory');
762
+ throw new EagleErrors.EagleOutOfMemoryError('malloc failed: Cannot allocate memory');
607
763
  }
608
764
 
609
765
  status = await pv_eagle_profiler_enroll_min_audio_length_samples(
@@ -611,14 +767,18 @@ export class EagleProfiler extends EagleBase {
611
767
  minEnrollSamplesAddress
612
768
  );
613
769
  if (status !== PV_STATUS_SUCCESS) {
614
- const msg = `'pv_eagle_profiler_enroll_min_audio_length_samples' failed with status ${arrayBufferToStringAtIndex(
615
- memoryBufferUint8,
616
- await baseWasmOutput.pvStatusToString(status)
617
- )}`;
618
- throw new Error(
619
- `${msg}\nDetails: ${baseWasmOutput.pvError.getErrorString()}`
770
+ const messageStack = await EagleProfiler.getMessageStack(
771
+ baseWasmOutput.pvGetErrorStack,
772
+ baseWasmOutput.pvFreeErrorStack,
773
+ baseWasmOutput.messageStackAddressAddressAddress,
774
+ baseWasmOutput.messageStackDepthAddress,
775
+ memoryBufferView,
776
+ memoryBufferUint8
620
777
  );
778
+
779
+ throw pvStatusToException(status, "EagleProfiler failed to get min enroll audio length", messageStack, baseWasmOutput.pvError);
621
780
  }
781
+
622
782
  const minEnrollSamples = memoryBufferView.getInt32(
623
783
  minEnrollSamplesAddress,
624
784
  true
@@ -630,7 +790,7 @@ export class EagleProfiler extends EagleBase {
630
790
  Int32Array.BYTES_PER_ELEMENT
631
791
  );
632
792
  if (profileSizeAddress === 0) {
633
- throw new Error('malloc failed: Cannot allocate memory');
793
+ throw new EagleErrors.EagleOutOfMemoryError('malloc failed: Cannot allocate memory');
634
794
  }
635
795
 
636
796
  status = await pv_eagle_profiler_export_size(
@@ -638,13 +798,16 @@ export class EagleProfiler extends EagleBase {
638
798
  profileSizeAddress
639
799
  );
640
800
  if (status !== PV_STATUS_SUCCESS) {
641
- const msg = `'pv_eagle_profiler_export_size' failed with status ${arrayBufferToStringAtIndex(
642
- memoryBufferUint8,
643
- await baseWasmOutput.pvStatusToString(status)
644
- )}`;
645
- throw new Error(
646
- `${msg}\nDetails: ${baseWasmOutput.pvError.getErrorString()}`
801
+ const messageStack = await EagleProfiler.getMessageStack(
802
+ baseWasmOutput.pvGetErrorStack,
803
+ baseWasmOutput.pvFreeErrorStack,
804
+ baseWasmOutput.messageStackAddressAddressAddress,
805
+ baseWasmOutput.messageStackDepthAddress,
806
+ memoryBufferView,
807
+ memoryBufferUint8
647
808
  );
809
+
810
+ throw pvStatusToException(status, "EagleProfiler failed to get export size", messageStack, baseWasmOutput.pvError);
648
811
  }
649
812
 
650
813
  const profileSize = memoryBufferView.getInt32(profileSizeAddress, true);
@@ -704,7 +867,7 @@ export class Eagle extends EagleBase {
704
867
  /**
705
868
  * Creates an instance of the Picovoice Eagle Speaker Recognition Engine.
706
869
  *
707
- * @param accessKey: AccessKey obtained from Picovoice Console (https://console.picovoice.ai/)
870
+ * @param accessKey AccessKey obtained from Picovoice Console (https://console.picovoice.ai/)
708
871
  * @param model Eagle model options.
709
872
  * @param model.base64 The model in base64 string to initialize Eagle.
710
873
  * @param model.publicPath The model path relative to the public directory.
@@ -739,11 +902,11 @@ export class Eagle extends EagleBase {
739
902
  speakerProfiles: EagleProfile[]
740
903
  ): Promise<Eagle> {
741
904
  if (!isAccessKeyValid(accessKey)) {
742
- throw new Error('Invalid AccessKey');
905
+ throw new EagleErrors.EagleInvalidArgumentError('Invalid AccessKey');
743
906
  }
744
907
 
745
908
  if (!speakerProfiles || speakerProfiles.length === 0) {
746
- throw new Error('No speaker profiles provided');
909
+ throw new EagleErrors.EagleInvalidArgumentError('No speaker profiles provided');
747
910
  }
748
911
 
749
912
  return new Promise<Eagle>((resolve, reject) => {
@@ -779,11 +942,11 @@ export class Eagle extends EagleBase {
779
942
  */
780
943
  public async process(pcm: Int16Array): Promise<number[]> {
781
944
  if (!(pcm instanceof Int16Array)) {
782
- throw new Error("The argument 'pcm' must be provided as an Int16Array");
945
+ throw new EagleErrors.EagleInvalidArgumentError("The argument 'pcm' must be provided as an Int16Array");
783
946
  }
784
947
 
785
948
  if (pcm.length !== Eagle._frameLength) {
786
- throw new Error(
949
+ throw new EagleErrors.EagleInvalidArgumentError(
787
950
  `Length of input frame (${pcm.length}) does not match required frame length (${Eagle._frameLength})`
788
951
  );
789
952
  }
@@ -792,7 +955,7 @@ export class Eagle extends EagleBase {
792
955
  this._functionMutex
793
956
  .runExclusive(async () => {
794
957
  if (this._wasmMemory === undefined) {
795
- throw new Error('Attempted to call `.process` after release');
958
+ throw new EagleErrors.EagleInvalidStateError('Attempted to call `.process` after release');
796
959
  }
797
960
 
798
961
  const pcmAddress = await this._alignedAlloc(
@@ -810,15 +973,21 @@ export class Eagle extends EagleBase {
810
973
  );
811
974
  await this._pvFree(pcmAddress);
812
975
  if (status !== PV_STATUS_SUCCESS) {
976
+ const memoryBufferView = new DataView(this._wasmMemory.buffer);
813
977
  const memoryBufferUint8 = new Uint8Array(this._wasmMemory.buffer);
814
- throw new Error(
815
- `process failed with status ${arrayBufferToStringAtIndex(
816
- memoryBufferUint8,
817
- await this._pvStatusToString(status)
818
- )}`
978
+
979
+ const messageStack = await EagleProfiler.getMessageStack(
980
+ this._pvGetErrorStack,
981
+ this._pvFreeErrorStack,
982
+ this._messageStackAddressAddressAddress,
983
+ this._messageStackDepthAddress,
984
+ memoryBufferView,
985
+ memoryBufferUint8
819
986
  );
987
+
988
+ throw pvStatusToException(status, "Eagle process failed", messageStack);
820
989
  }
821
-
990
+
822
991
  const memoryBufferView = new DataView(this._wasmMemory.buffer);
823
992
 
824
993
  const scores: number[] = [];
@@ -852,18 +1021,24 @@ export class Eagle extends EagleBase {
852
1021
  this._functionMutex
853
1022
  .runExclusive(async () => {
854
1023
  if (this._wasmMemory === undefined) {
855
- throw new Error('Attempted to call `.reset` after release');
1024
+ throw new EagleErrors.EagleInvalidStateError('Attempted to call `.reset` after release');
856
1025
  }
857
1026
 
858
1027
  const status = await this._pvEagleReset(this._objectAddress);
859
1028
  if (status !== PV_STATUS_SUCCESS) {
1029
+ const memoryBufferView = new DataView(this._wasmMemory.buffer);
860
1030
  const memoryBufferUint8 = new Uint8Array(this._wasmMemory.buffer);
861
- throw new Error(
862
- `reset failed with status ${arrayBufferToStringAtIndex(
863
- memoryBufferUint8,
864
- await this._pvStatusToString(status)
865
- )}`
1031
+
1032
+ const messageStack = await EagleProfiler.getMessageStack(
1033
+ this._pvGetErrorStack,
1034
+ this._pvFreeErrorStack,
1035
+ this._messageStackAddressAddressAddress,
1036
+ this._messageStackDepthAddress,
1037
+ memoryBufferView,
1038
+ memoryBufferUint8
866
1039
  );
1040
+
1041
+ throw pvStatusToException(status, "Eagle reset failed", messageStack);
867
1042
  }
868
1043
  })
869
1044
  .then(() => {
@@ -879,6 +1054,7 @@ export class Eagle extends EagleBase {
879
1054
  * Releases resources acquired by Eagle
880
1055
  */
881
1056
  public async release(): Promise<void> {
1057
+ await super.release();
882
1058
  await this._pvFree(this._scoresAddress);
883
1059
  await this._pvEagleDelete(this._objectAddress);
884
1060
  delete this._wasmMemory;
@@ -911,7 +1087,7 @@ export class Eagle extends EagleBase {
911
1087
  Int32Array.BYTES_PER_ELEMENT
912
1088
  );
913
1089
  if (objectAddressAddress === 0) {
914
- throw new Error('malloc failed: Cannot allocate memory');
1090
+ throw new EagleErrors.EagleOutOfMemoryError('malloc failed: Cannot allocate memory');
915
1091
  }
916
1092
 
917
1093
  const accessKeyAddress = await baseWasmOutput.alignedAlloc(
@@ -919,7 +1095,7 @@ export class Eagle extends EagleBase {
919
1095
  (accessKey.length + 1) * Uint8Array.BYTES_PER_ELEMENT
920
1096
  );
921
1097
  if (accessKeyAddress === 0) {
922
- throw new Error('malloc failed: Cannot allocate memory');
1098
+ throw new EagleErrors.EagleOutOfMemoryError('malloc failed: Cannot allocate memory');
923
1099
  }
924
1100
  for (let i = 0; i < accessKey.length; i++) {
925
1101
  memoryBufferUint8[accessKeyAddress + i] = accessKey.charCodeAt(i);
@@ -932,7 +1108,7 @@ export class Eagle extends EagleBase {
932
1108
  (modelPathEncoded.length + 1) * Uint8Array.BYTES_PER_ELEMENT
933
1109
  );
934
1110
  if (modelPathAddress === 0) {
935
- throw new Error('malloc failed: Cannot allocate memory');
1111
+ throw new EagleErrors.EagleOutOfMemoryError('malloc failed: Cannot allocate memory');
936
1112
  }
937
1113
  memoryBufferUint8.set(modelPathEncoded, modelPathAddress);
938
1114
  memoryBufferUint8[modelPathAddress + modelPathEncoded.length] = 0;
@@ -943,7 +1119,7 @@ export class Eagle extends EagleBase {
943
1119
  numSpeakers * Int32Array.BYTES_PER_ELEMENT
944
1120
  );
945
1121
  if (profilesAddressAddress === 0) {
946
- throw new Error('malloc failed: Cannot allocate memory');
1122
+ throw new EagleErrors.EagleOutOfMemoryError('malloc failed: Cannot allocate memory');
947
1123
  }
948
1124
  const profilesAddressList: number[] = [];
949
1125
  for (const profile of speakerProfiles) {
@@ -952,7 +1128,7 @@ export class Eagle extends EagleBase {
952
1128
  profile.bytes.length * Uint8Array.BYTES_PER_ELEMENT
953
1129
  );
954
1130
  if (profileAddress === 0) {
955
- throw new Error('malloc failed: Cannot allocate memory');
1131
+ throw new EagleErrors.EagleOutOfMemoryError('malloc failed: Cannot allocate memory');
956
1132
  }
957
1133
  memoryBufferUint8.set(profile.bytes, profileAddress);
958
1134
  profilesAddressList.push(profileAddress);
@@ -971,18 +1147,22 @@ export class Eagle extends EagleBase {
971
1147
  await baseWasmOutput.pvFree(accessKeyAddress);
972
1148
  await baseWasmOutput.pvFree(modelPathAddress);
973
1149
  await baseWasmOutput.pvFree(profilesAddressAddress);
974
- if (status !== PV_STATUS_SUCCESS) {
975
- const msg = `'pv_eagle_init' failed with status ${arrayBufferToStringAtIndex(
976
- memoryBufferUint8,
977
- await baseWasmOutput.pvStatusToString(status)
978
- )}`;
979
1150
 
980
- throw new Error(
981
- `${msg}\nDetails: ${baseWasmOutput.pvError.getErrorString()}`
1151
+ const memoryBufferView = new DataView(baseWasmOutput.memory.buffer);
1152
+
1153
+ if (status !== PV_STATUS_SUCCESS) {
1154
+ const messageStack = await EagleProfiler.getMessageStack(
1155
+ baseWasmOutput.pvGetErrorStack,
1156
+ baseWasmOutput.pvFreeErrorStack,
1157
+ baseWasmOutput.messageStackAddressAddressAddress,
1158
+ baseWasmOutput.messageStackDepthAddress,
1159
+ memoryBufferView,
1160
+ memoryBufferUint8
982
1161
  );
1162
+
1163
+ throw pvStatusToException(status, "Eagle init failed", messageStack, baseWasmOutput.pvError);
983
1164
  }
984
1165
 
985
- const memoryBufferView = new DataView(baseWasmOutput.memory.buffer);
986
1166
  const objectAddress = memoryBufferView.getInt32(objectAddressAddress, true);
987
1167
  await baseWasmOutput.pvFree(objectAddressAddress);
988
1168
 
@@ -991,7 +1171,7 @@ export class Eagle extends EagleBase {
991
1171
  numSpeakers * Float32Array.BYTES_PER_ELEMENT
992
1172
  );
993
1173
  if (scoresAddress === 0) {
994
- throw new Error('malloc failed: Cannot allocate memory');
1174
+ throw new EagleErrors.EagleOutOfMemoryError('malloc failed: Cannot allocate memory');
995
1175
  }
996
1176
 
997
1177
  const frameLength = await pv_eagle_frame_length();