diff --git a/.github/workflows/android-browserstack.yml b/.github/workflows/android-browserstack.yml index 912c672c..982ab9c2 100644 --- a/.github/workflows/android-browserstack.yml +++ b/.github/workflows/android-browserstack.yml @@ -10,7 +10,7 @@ on: - 'resources/audio_samples/**' - 'script/automation/browserstack.py' pull_request: - branches: [ main, 'v[0-9]+.[0-9]+' ] + branches: [ main, 'v[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+-.+', 'v[0-9]+.[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+.[0-9]+-.+' ] paths: - 'binding/android/EagleTestApp/**' - '.github/workflows/android-browserstack.yml' diff --git a/.github/workflows/android-demos.yml b/.github/workflows/android-demos.yml index 86fa298e..27ce663f 100644 --- a/.github/workflows/android-demos.yml +++ b/.github/workflows/android-demos.yml @@ -9,7 +9,7 @@ on: - 'demo/android/**' - '!demo/android/EagleDemo/README.md' pull_request: - branches: [ main, 'v[0-9]+.[0-9]+' ] + branches: [ main, 'v[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+-.+', 'v[0-9]+.[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+.[0-9]+-.+' ] paths: - '.github/workflows/android-demos.yml' - 'demo/android/**' diff --git a/.github/workflows/android-perf.yml b/.github/workflows/android-perf.yml index c3da1859..bb724e0d 100644 --- a/.github/workflows/android-perf.yml +++ b/.github/workflows/android-perf.yml @@ -10,7 +10,7 @@ on: - '.github/workflows/android-perf.yml' - 'binding/android/EagleTestApp/**' pull_request: - branches: [ main, 'v[0-9]+.[0-9]+' ] + branches: [ main, 'v[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+-.+', 'v[0-9]+.[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+.[0-9]+-.+' ] paths: - 'lib/android/**' - 'lib/common/**' diff --git a/.github/workflows/android-upload.yml b/.github/workflows/android-upload.yml index e8911353..afa3a911 100644 --- a/.github/workflows/android-upload.yml +++ b/.github/workflows/android-upload.yml @@ -8,7 +8,7 @@ on: - '.github/workflows/android-upload.yml' - 'demo/android/**/build.gradle' pull_request: - branches: [ main, 'v[0-9]+.[0-9]+' ] + branches: [ main, 'v[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+-.+', 'v[0-9]+.[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+.[0-9]+-.+' ] paths: - '.github/workflows/android-upload.yml' - 'demo/android/EagleDemo/**/build.gradle' diff --git a/.github/workflows/c-codestyle.yml b/.github/workflows/c-codestyle.yml index 1f8e6f5d..39a99f75 100644 --- a/.github/workflows/c-codestyle.yml +++ b/.github/workflows/c-codestyle.yml @@ -8,7 +8,7 @@ on: - '**/*.c' - '.github/workflows/c-codestyle.yml' pull_request: - branches: [ main, 'v[0-9]+.[0-9]+' ] + branches: [ main, 'v[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+-.+', 'v[0-9]+.[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+.[0-9]+-.+' ] paths: - '**/*.c' - '.github/workflows/c-codestyle.yml' diff --git a/.github/workflows/c-demos.yml b/.github/workflows/c-demos.yml index dedafda4..f04bdb74 100644 --- a/.github/workflows/c-demos.yml +++ b/.github/workflows/c-demos.yml @@ -15,7 +15,7 @@ on: - 'lib/windows/**' - 'resources/audio_samples/*.wav' pull_request: - branches: [ main, 'v[0-9]+.[0-9]+' ] + branches: [ main, 'v[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+-.+', 'v[0-9]+.[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+.[0-9]+-.+' ] paths: - '!demo/c/README.md' - '.github/workflows/c-demos.yml' diff --git a/.github/workflows/ios-browserstack.yml b/.github/workflows/ios-browserstack.yml index bfdd2b96..e1454300 100644 --- a/.github/workflows/ios-browserstack.yml +++ b/.github/workflows/ios-browserstack.yml @@ -9,7 +9,7 @@ on: - 'binding/ios/EagleAppTest/**' - 'resources/audio_samples/**' pull_request: - branches: [ main, 'v[0-9]+.[0-9]+' ] + branches: [ main, 'v[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+-.+', 'v[0-9]+.[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+.[0-9]+-.+' ] paths: - '.github/workflows/ios-browserstack.yml' - 'binding/ios/EagleAppTest/**' diff --git a/.github/workflows/ios-demos.yml b/.github/workflows/ios-demos.yml index 94b29795..bef91c8c 100644 --- a/.github/workflows/ios-demos.yml +++ b/.github/workflows/ios-demos.yml @@ -8,7 +8,7 @@ on: - 'demo/ios/EagleDemo/**' - '.github/workflows/ios-demos.yml' pull_request: - branches: [ main, 'v[0-9]+.[0-9]+' ] + branches: [ main, 'v[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+-.+', 'v[0-9]+.[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+.[0-9]+-.+' ] paths: - 'demo/ios/EagleDemo/**' - '.github/workflows/ios-demos.yml' diff --git a/.github/workflows/ios-perf.yml b/.github/workflows/ios-perf.yml index 1a070ef5..baa6eb91 100644 --- a/.github/workflows/ios-perf.yml +++ b/.github/workflows/ios-perf.yml @@ -9,7 +9,7 @@ on: - 'lib/common/**' - '.github/workflows/ios-perf.yml' pull_request: - branches: [ main, 'v[0-9]+.[0-9]+' ] + branches: [ main, 'v[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+-.+', 'v[0-9]+.[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+.[0-9]+-.+' ] paths: - 'lib/ios/**' - 'lib/common/**' diff --git a/.github/workflows/ios-validate.yml b/.github/workflows/ios-validate.yml index a482be51..86dc0047 100644 --- a/.github/workflows/ios-validate.yml +++ b/.github/workflows/ios-validate.yml @@ -7,7 +7,7 @@ on: - '.github/workflows/ios-validate.yml' - 'demo/ios/EagleDemo/**' pull_request: - branches: [ main, 'v[0-9]+.[0-9]+' ] + branches: [ main, 'v[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+-.+', 'v[0-9]+.[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+.[0-9]+-.+' ] paths: - '.github/workflows/ios-validate.yml' - 'demo/ios/EagleDemo/**' diff --git a/.github/workflows/java-codestyle.yml b/.github/workflows/java-codestyle.yml index 2102e0b6..0d060e1e 100644 --- a/.github/workflows/java-codestyle.yml +++ b/.github/workflows/java-codestyle.yml @@ -8,7 +8,7 @@ on: - '**/*.java' - 'resources/lint/java/**' pull_request: - branches: [ main, 'v[0-9]+.[0-9]+' ] + branches: [ main, 'v[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+-.+', 'v[0-9]+.[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+.[0-9]+-.+' ] paths: - '**/*.java' - 'resources/lint/java/**' diff --git a/.github/workflows/link-check.yml b/.github/workflows/link-check.yml index ffb82e8d..b49dcfb8 100644 --- a/.github/workflows/link-check.yml +++ b/.github/workflows/link-check.yml @@ -5,7 +5,7 @@ on: push: branches: [main] pull_request: - branches: [main, 'v[0-9]+.[0-9]+'] + branches: [ main, 'v[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+-.+', 'v[0-9]+.[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+.[0-9]+-.+' ] jobs: markdown-link-check: diff --git a/.github/workflows/nodejs-codestyle.yml b/.github/workflows/nodejs-codestyle.yml index 71eaa617..4b7adb4c 100644 --- a/.github/workflows/nodejs-codestyle.yml +++ b/.github/workflows/nodejs-codestyle.yml @@ -9,7 +9,7 @@ on: - '**/nodejs/*.ts' - '.github/workflows/nodejs-codestyle.yml' pull_request: - branches: [ main, 'v[0-9]+.[0-9]+' ] + branches: [ main, 'v[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+-.+', 'v[0-9]+.[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+.[0-9]+-.+' ] paths: - '**/nodejs/*.js' - '**/nodejs/*.ts' diff --git a/.github/workflows/nodejs-demos.yml b/.github/workflows/nodejs-demos.yml index a3282def..9dabed64 100644 --- a/.github/workflows/nodejs-demos.yml +++ b/.github/workflows/nodejs-demos.yml @@ -11,7 +11,7 @@ on: - '.github/workflows/nodejs-demos.yml' pull_request: - branches: [ main, 'v[0-9]+.[0-9]+' ] + branches: [ main, 'v[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+-.+', 'v[0-9]+.[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+.[0-9]+-.+' ] paths: - 'demo/nodejs/**' - '!demo/nodejs/README.md' diff --git a/.github/workflows/nodejs-perf.yml b/.github/workflows/nodejs-perf.yml index 2c6b87ab..051becf0 100644 --- a/.github/workflows/nodejs-perf.yml +++ b/.github/workflows/nodejs-perf.yml @@ -10,7 +10,7 @@ on: - '.github/workflows/nodejs-perf.yml' pull_request: - branches: [ main, 'v[0-9]+.[0-9]+' ] + branches: [ main, 'v[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+-.+', 'v[0-9]+.[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+.[0-9]+-.+' ] paths: - 'binding/nodejs/perf.test.js' - 'lib/node/**' @@ -66,24 +66,24 @@ jobs: include: - machine: rpi3-32 num_test_iterations: 20 - enroll_performance_threshold_sec: 2.5 - proc_performance_threshold_sec: 2.8 + enroll_performance_threshold_sec: 8.0 + proc_performance_threshold_sec: 8.0 - machine: rpi3-64 num_test_iterations: 20 - enroll_performance_threshold_sec: 2.5 - proc_performance_threshold_sec: 2.8 + enroll_performance_threshold_sec: 4.0 + proc_performance_threshold_sec: 4.0 - machine: rpi4-32 num_test_iterations: 20 - enroll_performance_threshold_sec: 1.5 - proc_performance_threshold_sec: 1.5 + enroll_performance_threshold_sec: 2.0 + proc_performance_threshold_sec: 2.5 - machine: rpi4-64 num_test_iterations: 20 enroll_performance_threshold_sec: 2.0 proc_performance_threshold_sec: 2.5 - machine: rpi5-64 num_test_iterations: 20 - enroll_performance_threshold_sec: 0.5 - proc_performance_threshold_sec: 0.6 + enroll_performance_threshold_sec: 1.0 + proc_performance_threshold_sec: 1.0 steps: - uses: actions/checkout@v3 diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index ecba6d2e..586a2523 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -11,7 +11,7 @@ on: - '.github/workflows/nodejs.yml' pull_request: - branches: [ main, 'v[0-9]+.[0-9]+' ] + branches: [ main, 'v[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+-.+', 'v[0-9]+.[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+.[0-9]+-.+' ] paths: - 'binding/nodejs/**' - '!binding/nodejs/README.md' diff --git a/.github/workflows/python-codestyle.yml b/.github/workflows/python-codestyle.yml index e4116ee7..7ea40101 100644 --- a/.github/workflows/python-codestyle.yml +++ b/.github/workflows/python-codestyle.yml @@ -7,7 +7,7 @@ on: paths: - '**/*.py' pull_request: - branches: [ main, 'v[0-9]+.[0-9]+' ] + branches: [ main, 'v[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+-.+', 'v[0-9]+.[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+.[0-9]+-.+' ] paths: - '**/*.py' diff --git a/.github/workflows/python-demos.yml b/.github/workflows/python-demos.yml index 25befca8..bf35168c 100644 --- a/.github/workflows/python-demos.yml +++ b/.github/workflows/python-demos.yml @@ -10,7 +10,7 @@ on: - '!demo/python/README.md' - 'resources/audio_samples/**' pull_request: - branches: [ main, 'v[0-9]+.[0-9]+' ] + branches: [ main, 'v[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+-.+', 'v[0-9]+.[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+.[0-9]+-.+' ] paths: - '.github/workflows/python-demos.yml' - 'demo/python/**' diff --git a/.github/workflows/python-perf.yml b/.github/workflows/python-perf.yml index 88a544a9..10958ad7 100644 --- a/.github/workflows/python-perf.yml +++ b/.github/workflows/python-perf.yml @@ -17,7 +17,7 @@ on: - 'lib/windows/**' - 'resources/audio_samples/*.wav' pull_request: - branches: [ main, 'v[0-9]+.[0-9]+' ] + branches: [ main, 'v[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+-.+', 'v[0-9]+.[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+.[0-9]+-.+' ] paths: - '.github/workflows/python-perf.yml' - 'binding/python/__init__.py' @@ -86,20 +86,20 @@ jobs: machine: [rpi3-32, rpi3-64, rpi4-32, rpi4-64] include: - machine: rpi3-32 - profiler_performance_threshold_sec: 2.5 - recognizer_performance_threshold_sec: 2.8 + profiler_performance_threshold_sec: 8.0 + recognizer_performance_threshold_sec: 8.0 - machine: rpi3-64 - profiler_performance_threshold_sec: 2.5 - recognizer_performance_threshold_sec: 2.8 + profiler_performance_threshold_sec: 4.0 + recognizer_performance_threshold_sec: 4.0 - machine: rpi4-32 - profiler_performance_threshold_sec: 1.5 - recognizer_performance_threshold_sec: 1.5 + profiler_performance_threshold_sec: 2.0 + recognizer_performance_threshold_sec: 2.5 - machine: rpi4-64 profiler_performance_threshold_sec: 2.0 recognizer_performance_threshold_sec: 2.5 - machine: rpi5-64 - profiler_performance_threshold_sec: 0.5 - recognizer_performance_threshold_sec: 0.6 + profiler_performance_threshold_sec: 1.0 + recognizer_performance_threshold_sec: 1.0 steps: - uses: actions/checkout@v3 diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index cb27ebb5..28a2d677 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -15,7 +15,7 @@ on: - 'lib/windows/**' - 'resources/audio_samples/*.wav' pull_request: - branches: [ main, 'v[0-9]+.[0-9]+' ] + branches: [ main, 'v[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+-.+', 'v[0-9]+.[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+.[0-9]+-.+' ] paths: - '.github/workflows/python.yml' - 'binding/python/**' diff --git a/.github/workflows/spell-check.yml b/.github/workflows/spell-check.yml index 00970d7e..9c8af6fb 100644 --- a/.github/workflows/spell-check.yml +++ b/.github/workflows/spell-check.yml @@ -5,7 +5,7 @@ on: push: branches: [main] pull_request: - branches: [main, 'v[0-9]+.[0-9]+'] + branches: [ main, 'v[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+-.+', 'v[0-9]+.[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+.[0-9]+-.+' ] jobs: spellcheck: diff --git a/.github/workflows/swift-codestyle.yml b/.github/workflows/swift-codestyle.yml index e8755619..c7b88ff3 100644 --- a/.github/workflows/swift-codestyle.yml +++ b/.github/workflows/swift-codestyle.yml @@ -7,7 +7,7 @@ on: paths: - '**/*.swift' pull_request: - branches: [ main, 'v[0-9]+.[0-9]+' ] + branches: [ main, 'v[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+-.+', 'v[0-9]+.[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+.[0-9]+-.+' ] paths: - '**/*.swift' diff --git a/.github/workflows/web-codestyle.yml b/.github/workflows/web-codestyle.yml index 2b4da4ff..8e3cf04d 100644 --- a/.github/workflows/web-codestyle.yml +++ b/.github/workflows/web-codestyle.yml @@ -9,7 +9,7 @@ on: - 'binding/web/*.ts' - '.github/workflows/web-codestyle.yml' pull_request: - branches: [ main, 'v[0-9]+.[0-9]+' ] + branches: [ main, 'v[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+-.+', 'v[0-9]+.[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+.[0-9]+-.+' ] paths: - 'binding/web/*.js' - 'binding/web/*.ts' diff --git a/.github/workflows/web-demos.yml b/.github/workflows/web-demos.yml index 3d9a15fa..1e6a5ef8 100644 --- a/.github/workflows/web-demos.yml +++ b/.github/workflows/web-demos.yml @@ -9,7 +9,7 @@ on: - '!demo/web/README.md' - '.github/workflows/web-demos.yml' pull_request: - branches: [ main, 'v[0-9]+.[0-9]+' ] + branches: [ main, 'v[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+-.+', 'v[0-9]+.[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+.[0-9]+-.+' ] paths: - 'demo/web/**' - '!demo/web/README.md' diff --git a/.github/workflows/web-perf.yml b/.github/workflows/web-perf.yml index c94b13b4..78f05900 100644 --- a/.github/workflows/web-perf.yml +++ b/.github/workflows/web-perf.yml @@ -9,7 +9,7 @@ on: - 'lib/common/**' - '.github/workflows/web-perf.yml' pull_request: - branches: [ main, 'v[0-9]+.[0-9]+' ] + branches: [ main, 'v[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+-.+', 'v[0-9]+.[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+.[0-9]+-.+' ] paths: - 'lib/wasm/**' - 'lib/common/**' diff --git a/.github/workflows/web.yml b/.github/workflows/web.yml index 307d675a..35edc3b7 100644 --- a/.github/workflows/web.yml +++ b/.github/workflows/web.yml @@ -12,7 +12,7 @@ on: - 'resources/audio_samples' - '.github/workflows/web.yml' pull_request: - branches: [ main, 'v[0-9]+.[0-9]+' ] + branches: [ main, 'v[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+-.+', 'v[0-9]+.[0-9]+.[0-9]+', 'v[0-9]+.[0-9]+.[0-9]+-.+' ] paths: - 'binding/web/**' - '!binding/web/README.md' diff --git a/README.md b/README.md index ad527a21..22ffcc2e 100644 --- a/README.md +++ b/README.md @@ -268,13 +268,17 @@ eagle_profiler = pveagle.create_profiler(access_key) Create a new speaker profile: ```python -def get_next_enroll_audio_data(): +def get_next_enroll_audio_frame(frame_length): + pass + +def has_next_enroll_audio_frame(frame_length): pass percentage = 0.0 -while percentage < 100.0: - percentage, error = eagle_profiler.enroll(get_next_enroll_audio_data()) +while percentage < 100.0 and has_next_enroll_audio_frame(eagle_profiler.frame_length): + percentage = eagle_profiler.enroll(get_next_enroll_audio_frame(eagle_profiler.frame_length)) +percentage = eagle_profiler.flush() ``` Export the speaker profile once enrollment is complete: @@ -291,21 +295,21 @@ eagle_profiler.delete() #### Speaker Recognition -Create an instance of the engine using the speaker profile exported before: +Create an instance of the engine: ```python eagle = pveagle.create_recognizer(access_key, speaker_profile) ``` -Process incoming audio frames: +Process audio with one or more speaker profiles from the `EagleProfiler`. ```python -def get_next_audio_frame(): +def get_next_audio_chunk(num_samples): pass while True: - score = eagle.process(get_next_audio_frame()) + scores = eagle.process(get_next_audio_chunk(eagle.min_process_samples), speaker_profiles) ``` Finally, when done be sure to explicitly release the resources: @@ -343,14 +347,14 @@ try { Create a new speaker profile: ```java -public short[] getNextEnrollAudioData() { - // get audio data +public short[] getNextAudioFrame() { + // get audio frame } EagleProfilerEnrollResult result = null; try { while (result != null && result.getPercentage() < 100.0) { - result = eagleProfiler.enroll(getNextEnrollAudioData()); + result = eagleProfiler.enroll(getNextAudioFrame()); } } catch (EagleException e) { } ``` @@ -371,7 +375,7 @@ eagleProfiler.delete(); #### Speaker Recognition -Create an instance of the engine using the speaker profile exported before: +Create an instance of the engine: ```java import ai.picovoice.eagle.*; @@ -381,7 +385,6 @@ final String accessKey = "${ACCESS_KEY}"; try { Eagle eagle = new Eagle.Builder() .setAccessKey(accessKey) - .setSpeakerProfile(speakerProfile) .build(); } catch (EagleException e) { } ``` @@ -389,14 +392,15 @@ try { Process incoming audio frames: ```java -public short[] getNextAudioFrame() { - // get audio frame +public short[] getNextProcessAudioData() { + // get audio sample } - try { + EagleProfile[] speakerProfiles = {speakerProfile}; + while (true) { - float[] scores = eagle.process(getNextAudioFrame()); + float[] scores = eagle.process(getNextProcessAudioData(), speakerProfiles); } } catch (EagleException e) { } ``` @@ -431,18 +435,14 @@ let eagleProfiler = try EagleProfiler(accessKey: accessKey) Create a new speaker profile: ```swift -func get_next_enroll_audio_data(numSamples: Int) -> [Int16] { +func get_next_audio_frame(frameLength: Int) -> [Int16] { // ... } do { - let numSamples = eagleProfiler.minEnrollSamples() - var percentage = 0.0 - var feedback: EagleProfilerEnrollFeedback? - while (percentage < 100.0) { - (percentage, feedback) = try eagleProfiler.enroll(pcm: get_next_enroll_audio_data(numSamples: numSamples)) + percentage = try eagleProfiler.enroll(pcm: get_next_audio_frame()) } } catch { } ``` @@ -461,21 +461,21 @@ eagleProfiler.delete() #### Speaker Recognition -Create an instance of the engine using the speaker profile exported before: +Create an instance of the engine: ```swift -let eagle = Eagle(accessKey: accessKey, speakerProfiles: [speakerProfile]) +let eagle = Eagle(accessKey: accessKey) ``` -Process incoming audio frames: +Process incoming audio frames using the speaker profile exported before: ```swift -func get_next_audio_frame() -> [Int16] { +func get_next_process_audio_data(numSamples: Int) -> [Int16] { // ... } do { - let profileScores = try eagle.process(pcm: get_next_audio_frame()) + let profileScores = try eagle.process(pcm: get_next_process_audio_data(eagle.minProcessSamples()), speakerProfiles: [speakerProfile]) } catch { } ``` @@ -497,12 +497,16 @@ Build an instance of the profiler: const char *access_key = "${ACCESS_KEY}"; const char *model_path = "${MODEL_PATH}"; const char *device = "best"; +const int32_t min_enrollment_chunks = 1; +const float voice_threshold = 0.3f; pv_eagle_profiler_t *eagle_profiler = NULL; pv_status_t status = pv_eagle_profiler_init( access_key, model_path, device, + min_enrollment_chunks, + voice_threshold, &eagle_profiler); if (status != PV_STATUS_SUCCESS) { // error handling logic @@ -515,24 +519,29 @@ model file available under [lib/common](./lib/common). Use `eagle_profiler` to create a new speaker profile: ```c -extern const int16_t *get_next_enroll_audio_frame(void); -extern const int32_t get_next_enroll_audio_num_samples(void); +extern const int16_t *get_next_enroll_audio_frame(int32_t frame_length); +extern const bool has_next_enroll_audio_frame(int32_t frame_length); +const int32_t frame_length = pv_eagle_profiler_frame_length(); float enroll_percentage = 0.0f; -pv_eagle_profiler_enroll_feedback_t feedback = PV_EAGLE_PROFILER_ENROLLMENT_ERROR_AUDIO_OK; -while (enroll_percentage < 100.0f) { +while (enroll_percentage < 100.0f && has_next_enroll_audio_frame(frame_length)) { status = pv_eagle_profiler_enroll( eagle_profiler, - get_next_enroll_audio_frame(), - get_next_enroll_audio_num_samples(), - &feedback, + get_next_enroll_audio_frame(frame_length), &enroll_percentage); if (status != PV_STATUS_SUCCESS) { // error handling logic } } +status = pv_eagle_profiler_flush( + eagle_profiler, + &enroll_percentage); +if (status != PV_STATUS_SUCCESS) { + // error handling logic +} + int32_t profile_size_bytes = 0; status = pv_eagle_profiler_export_size(eagle_profiler, &profile_size_bytes); void *speaker_profile = malloc(profile_size_bytes); @@ -552,7 +561,7 @@ pv_eagle_profiler_delete(eagle_profiler); #### Speaker Recognition -Create an instance of the engine using the speaker profile exported before: +Create an instance of the engine: ```c pv_eagle_t *eagle = NULL; @@ -560,24 +569,29 @@ pv_status_t status = pv_eagle_init( access_key, model_path, device, - 1, - (const void *const *) &speaker_profile, + voice_threshold, &eagle); if (status != PV_STATUS_SUCCESS) { // error handling logic } ``` -Now the `eagle` can be used to process incoming audio frames: +Now the `eagle` can be used to process incoming audio frames using the speaker profile exported before: ```c extern const int16_t *get_next_audio_frame(void); -const int32_t frame_length = pv_eagle_frame_length(); +extern const int32_t get_next_audio_num_samples(void); -float score = 0.f; +float *scores = NULL; while (true) { - const int16_t *pcm = get_next_audio_frame(); - const pv_status_t status = pv_eagle_process(eagle, pcm, &score); + const int16_t *pcm = ; + const pv_status_t status = pv_eagle_process( + eagle, + get_next_audio_frame(), + get_next_audio_num_samples(), + &speaker_profile, + 1, + &scores); if (status != PV_STATUS_SUCCESS) { // error handling logic } @@ -587,6 +601,7 @@ while (true) { Finally, when done be sure to release the acquired resources: ```c +pv_eagle_scores_delete(scores); pv_eagle_delete(handle); ``` @@ -614,7 +629,8 @@ const eagleProfiler = await EagleProfiler.create( eagleModel); ``` -Replace `${ACCESS_KEY}` with the AccessKey obtained from Picovoice Console, and the model options with the path to the model file available under [lib/common](./lib/common) or a base64 string of it. +Replace `${ACCESS_KEY}` with the AccessKey obtained from Picovoice Console, and the model options with the path to the +model file available under [lib/common](./lib/common) or a base64 string of it. Use `EagleProfiler` to create a new speaker profile: ```typescript @@ -684,24 +700,21 @@ const eagleProfiler = new EagleProfiler(accessKey); Create a new speaker profile: ```typescript -const { EnrollProgress } = require("@picovoice/eagle-node"); - function getAudioData(numSamples): Int16Array { // get audio frame of size `numSamples` } -let percentage = 0; -while (percentage < 100) { - const audioData = getAudioData(eagleProfiler.minEnrollSamples); +function hasAudioData(numSamples): Boolean { + // check if there are any remaining samples in the stream +} - const result: EnrollProgress = await eagleProfiler.enroll(audioData); - if (result.feedback === EagleProfilerEnrollFeedback.NONE) { - // audio is good! - } else { - // feedback code will tell you why audio was not used in enrollment - } - percentage = result.percentage; +let percentage = 0; +while (percentage < 100 && hasAudioData(eagleProfiler.frameLength)) { + const audioData = getAudioData(eagleProfiler.frameLength); + percentage = eagleProfiler.enroll(audioData); } + +percentage = eagleProfiler.flush(); ``` Export the speaker profile once enrollment is complete: @@ -718,16 +731,16 @@ eagleProfiler.release(); #### Speaker Recognition -Create an instance of the engine using the speaker profile exported before: +Create an instance of the engine: ```typescript const { Eagle } = require("@picovoice/eagle-node"); const accessKey = "${ACCESS_KEY}"; // Obtained from the Picovoice Console (https://console.picovoice.ai/) -const eagle = new Eagle(accessKey, speakerProfile); +const eagle = new Eagle(accessKey); ``` -Process incoming audio frames: +Process audio with one or more speaker profiles from the `EagleProfiler`: ```typescript function getAudioData(numSamples): Int16Array { @@ -735,8 +748,14 @@ function getAudioData(numSamples): Int16Array { } while (true) { - const audioData = getAudioData(eagle.frameLength); - const scores: number[] = eagle.process(audioData); + const audioData = getAudioData(eagle.minProcessSamples); + const scores: number[] | null = await eagle.process( + audioData. + speakerProfile + ); + if (scores) { + // do something with the scores + } } ``` @@ -748,6 +767,11 @@ eagle.release() ## Releases +### v3.0.0 - April 6th, 2026 + + - Improved engine performance + - Improved the enrollment and recognition process + ### v2.0.0 - December 5th, 2025 - Improved engine performance diff --git a/binding/android/Eagle/build.gradle b/binding/android/Eagle/build.gradle index 12943328..3e787873 100644 --- a/binding/android/Eagle/build.gradle +++ b/binding/android/Eagle/build.gradle @@ -10,7 +10,7 @@ buildscript { mavenCentral() } dependencies { - classpath "com.android.tools.build:gradle:4.1.3" + classpath "com.android.tools.build:gradle:4.2.2" // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } diff --git a/binding/android/Eagle/eagle/build.gradle b/binding/android/Eagle/eagle/build.gradle index f8c51d71..acdcf493 100644 --- a/binding/android/Eagle/eagle/build.gradle +++ b/binding/android/Eagle/eagle/build.gradle @@ -2,10 +2,9 @@ apply plugin: 'com.android.library' ext { PUBLISH_GROUP_ID = 'ai.picovoice' - PUBLISH_VERSION = '2.0.0' + PUBLISH_VERSION = '3.0.0' PUBLISH_ARTIFACT_ID = 'eagle-android' } - android { compileSdkVersion defaultTargetSdkVersion @@ -13,7 +12,7 @@ android { minSdkVersion 21 targetSdkVersion defaultTargetSdkVersion versionCode 1 - versionName "0.1" + versionName "1.0" consumerProguardFiles "consumer-rules.pro" } @@ -24,6 +23,10 @@ android { proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } } if (file("${rootDir}/publish-mavencentral.gradle").exists()) { diff --git a/binding/android/Eagle/eagle/src/main/java/ai/picovoice/eagle/Eagle.java b/binding/android/Eagle/eagle/src/main/java/ai/picovoice/eagle/Eagle.java index 8b028bb3..63ac7778 100644 --- a/binding/android/Eagle/eagle/src/main/java/ai/picovoice/eagle/Eagle.java +++ b/binding/android/Eagle/eagle/src/main/java/ai/picovoice/eagle/Eagle.java @@ -1,5 +1,5 @@ /* - Copyright 2023-2025 Picovoice Inc. + Copyright 2023-2026 Picovoice Inc. You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE" file accompanying this source. @@ -35,7 +35,6 @@ public class Eagle { } private long handle; - private int numSpeakers; public static void setSdk(String sdk) { Eagle._sdk = sdk; @@ -64,29 +63,22 @@ public static String[] getAvailableDevices() throws EagleException { * set to `cpu`, the engine will run on the CPU with the default number of threads. To specify * the number of threads, set this argument to `cpu:${NUM_THREADS}`, where `${NUM_THREADS}` * is the desired number of threads. - * @param speakerProfiles A list of EagleProfile objects. This can be constructed using `EagleProfiler`. + * @param voiceThreshold Sensitivity threshold for detecting voice. The value should be a number within [0, 1]. A + * higher threshold increases detection confidence values at the cost of potentially missing + * frames of voice. * @throws EagleException if there is an error while initializing Eagle. */ private Eagle( String accessKey, String modelPath, String device, - EagleProfile[] speakerProfiles) throws EagleException { - long[] profileHandles = new long[speakerProfiles.length]; - - for (int i = 0; i < speakerProfiles.length; i++) { - profileHandles[i] = speakerProfiles[i].profileNative.handle; - } - + float voiceThreshold) throws EagleException { EagleNative.setSdk(Eagle._sdk); handle = EagleNative.init( accessKey, modelPath, device, - speakerProfiles.length, - profileHandles); - - numSpeakers = speakerProfiles.length; + voiceThreshold); } /** @@ -105,37 +97,35 @@ public void delete() { * @param pcm A frame of audio samples. The number of samples per frame can be attained by calling * `.getFrameLength()`. The incoming audio needs to have a sample rate equal * to `.getSampleRate()` and be 16-bit linearly-encoded. Eagle operates on single-channel audio. - * @return A list of similarity scores for each speaker profile. A higher score indicates that the voice - * belongs to the corresponding speaker. The range is [0, 1] with 1.0 representing a perfect match. + * @param speakerProfiles A list of EagleProfile objects. This can be constructed using `EagleProfiler`. + * @return A list of similarity scores for each speaker profile or null. A higher score indicates that the voice + * belongs to the corresponding speaker. The range is [0, 1] with 1 representing a perfect match. A result + * of null indicates that there was not enough voice in the audio to recognize any speakers. * @throws EagleException if there is an error while processing audio frames. */ - public float[] process(short[] pcm) throws EagleException { + public float[] process(short[] pcm, EagleProfile[] speakerProfiles) throws EagleException { if (handle == 0) { throw new EagleInvalidStateException("Attempted to call eagle process after delete."); } - if (pcm.length != this.getFrameLength()) { + if (pcm.length < this.getMinProcessSamples()) { throw new EagleInvalidArgumentException( - String.format("Length of input frame %d does not match required frame length %d", + String.format("Length of input frame %d is less than the minimum frame length %d", pcm.length, - this.getSampleRate())); + this.getMinProcessSamples())); } - return EagleNative.process(handle, pcm, numSpeakers); - } + if (speakerProfiles == null || speakerProfiles.length == 0) { + throw new EagleInvalidArgumentException("No speaker profiles provided to Eagle"); + } - /** - * Resets the internal state of Eagle Profiler. - * It should be called before starting a new enrollment session. - * - * @throws EagleException if there is an error while resetting Eagle. - */ - public void reset() throws EagleException { - if (handle == 0) { - throw new EagleInvalidStateException("Attempted to call eagle reset after delete."); + long[] profileHandles = new long[speakerProfiles.length]; + + for (int i = 0; i < speakerProfiles.length; i++) { + profileHandles[i] = speakerProfiles[i].profileNative.handle; } - EagleNative.reset(handle); + return EagleNative.process(handle, pcm, profileHandles); } /** @@ -148,12 +138,12 @@ public String getVersion() { } /** - * Getter for number of audio samples per frame. + * Getter for minimum number of audio samples for `.process()`. * - * @return Number of audio samples per frame. + * @return Minimum number of audio samples for `.process()`. */ - public int getFrameLength() { - return EagleNative.getFrameLength(); + public int getMinProcessSamples() { + return EagleNative.getMinProcessSamples(handle); } /** @@ -173,8 +163,7 @@ public static class Builder { private String accessKey = null; private String modelPath = null; private String device = null; - - private EagleProfile[] speakerProfiles = null; + private float voiceThreshold = 0.3f; public Builder setAccessKey(String accessKey) { this.accessKey = accessKey; @@ -191,13 +180,8 @@ public Builder setDevice(String device) { return this; } - public Builder setSpeakerProfiles(EagleProfile[] speakerProfiles) { - this.speakerProfiles = speakerProfiles; - return this; - } - - public Builder setSpeakerProfile(EagleProfile speakerProfile) { - this.speakerProfiles = new EagleProfile[]{ speakerProfile }; + public Builder setVoiceThreshold(float voiceThreshold) { + this.voiceThreshold = voiceThreshold; return this; } @@ -266,11 +250,7 @@ public Eagle build(Context context) throws EagleException { device = "best"; } - if (speakerProfiles == null || speakerProfiles.length == 0) { - throw new EagleInvalidArgumentException("No speaker profiles provided to Eagle"); - } - - return new Eagle(accessKey, modelPath, device, speakerProfiles); + return new Eagle(accessKey, modelPath, device, voiceThreshold); } } diff --git a/binding/android/Eagle/eagle/src/main/java/ai/picovoice/eagle/EagleNative.java b/binding/android/Eagle/eagle/src/main/java/ai/picovoice/eagle/EagleNative.java index bc886bc2..a04fa567 100644 --- a/binding/android/Eagle/eagle/src/main/java/ai/picovoice/eagle/EagleNative.java +++ b/binding/android/Eagle/eagle/src/main/java/ai/picovoice/eagle/EagleNative.java @@ -1,5 +1,5 @@ /* - Copyright 2023-2025 Picovoice Inc. + Copyright 2023-2026 Picovoice Inc. You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE" file accompanying this source. @@ -18,8 +18,6 @@ class EagleNative { static native String getVersion(); - static native int getFrameLength(); - static native int getSampleRate(); static native void setSdk(String sdk); @@ -28,14 +26,16 @@ static native long init( String accessKey, String modelPath, String device, - int numSpeakers, - long[] speakerProfiles) throws EagleException; + float voiceThreshold) throws EagleException; static native void delete(long object); - static native float[] process(long object, short[] pcm, int numSpeakers) throws EagleException; + static native float[] process( + long object, + short[] pcm, + long[] speakerProfiles) throws EagleException; - static native void reset(long object) throws EagleException; + static native int getMinProcessSamples(long object); static native String[] listHardwareDevices() throws EagleException; diff --git a/binding/android/Eagle/eagle/src/main/java/ai/picovoice/eagle/EagleProfiler.java b/binding/android/Eagle/eagle/src/main/java/ai/picovoice/eagle/EagleProfiler.java index 48cf5a4c..13edab68 100644 --- a/binding/android/Eagle/eagle/src/main/java/ai/picovoice/eagle/EagleProfiler.java +++ b/binding/android/Eagle/eagle/src/main/java/ai/picovoice/eagle/EagleProfiler.java @@ -1,5 +1,5 @@ /* - Copyright 2023-2025 Picovoice Inc. + Copyright 2023-2026 Picovoice Inc. You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE" file accompanying this source. @@ -31,8 +31,6 @@ public class EagleProfiler { private static String defaultModelPath; private static String _sdk = "android"; - private final int minEnrollSamples; - static { System.loadLibrary("pv_eagle"); } @@ -66,18 +64,27 @@ public static String[] getAvailableDevices() throws EagleException { * set to `cpu`, the engine will run on the CPU with the default number of threads. To specify * the number of threads, set this argument to `cpu:${NUM_THREADS}`, where `${NUM_THREADS}` * is the desired number of threads. + * @param minEnrollmentChunks Minimum number of chunks to be processed before enroll returns 100%. The value should + * be a number greater than or equal to 1. A higher number results in more accurate + * profiles at the cost of needing more data to create the profile. + * @param voiceThreshold Sensitivity threshold for detecting voice. The value should be a number within [0, 1]. A + * higher threshold increases detection confidence values at the cost of potentially missing + * frames of voice. * @throws EagleException if there is an error while initializing EagleProfiler. */ private EagleProfiler( String accessKey, String modelPath, - String device) throws EagleException { + String device, + int minEnrollmentChunks, + float voiceThreshold) throws EagleException { EagleNative.setSdk(EagleProfiler._sdk); handle = EagleProfilerNative.init( accessKey, modelPath, - device); - minEnrollSamples = EagleProfilerNative.minEnrollSamples(handle); + device, + minEnrollmentChunks, + voiceThreshold); } /** @@ -102,16 +109,30 @@ public void delete() { * * @param pcm The audio needs to have a sample rate equal to `.getSampleRate()` and be * 16-bit linearly-encoded. EagleProfiler operates on single-channel audio. - * @return The percentage of completeness of the speaker enrollment process along with the feedback code - * corresponding to the last enrollment attempt. + * @return The percentage of completeness of the speaker enrollment process. * @throws EagleException if there is an error while enrolling speaker. */ - public EagleProfilerEnrollResult enroll(short[] pcm) throws EagleException { + public float enroll(short[] pcm) throws EagleException { if (handle == 0) { throw new EagleInvalidStateException("Attempted to call eagle enroll after delete."); } - return EagleProfilerNative.enroll(handle, pcm, pcm.length); + return EagleProfilerNative.enroll(handle, pcm); + } + + /** + * Marks the end of the audio stream, flushes internal state of the object, + * and returns the percentage of enrollment completed. + * + * @return The percentage of completeness of the speaker enrollment process. + * @throws EagleException if there is an error while enrolling speaker. + */ + public float flush() throws EagleException { + if (handle == 0) { + throw new EagleInvalidStateException("Attempted to call eagle flush after delete."); + } + + return EagleProfilerNative.flush(handle); } /** @@ -157,12 +178,12 @@ public int getSampleRate() { } /** - * Getter for minimum length of the input pcm required by `.enroll()`. + * Getter for number of audio samples per frame. * - * @return minimum length of the input pcm. + * @return Number of audio samples per frame. */ - public int getMinEnrollSamples() { - return this.minEnrollSamples; + public int getFrameLength() { + return EagleProfilerNative.getFrameLength(); } /** @@ -173,6 +194,8 @@ public static class Builder { private String accessKey = null; private String modelPath = null; private String device = null; + private int minEnrollmentChunks = 1; + private float voiceThreshold = 0.3f; public Builder setAccessKey(String accessKey) { this.accessKey = accessKey; @@ -189,6 +212,16 @@ public Builder setDevice(String device) { return this; } + public Builder setMinEnrollmentChunks(int minEnrollmentChunks) { + this.minEnrollmentChunks = minEnrollmentChunks; + return this; + } + + public Builder setVoiceThreshold(int voiceThreshold) { + this.voiceThreshold = voiceThreshold; + return this; + } + private static void extractPackageResources(Context context) throws EagleIOException { final Resources resources = context.getResources(); @@ -254,7 +287,7 @@ public EagleProfiler build(Context context) throws EagleException { device = "best"; } - return new EagleProfiler(accessKey, modelPath, device); + return new EagleProfiler(accessKey, modelPath, device, minEnrollmentChunks, voiceThreshold); } } diff --git a/binding/android/Eagle/eagle/src/main/java/ai/picovoice/eagle/EagleProfilerEnrollFeedback.java b/binding/android/Eagle/eagle/src/main/java/ai/picovoice/eagle/EagleProfilerEnrollFeedback.java deleted file mode 100644 index 0973ffee..00000000 --- a/binding/android/Eagle/eagle/src/main/java/ai/picovoice/eagle/EagleProfilerEnrollFeedback.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - Copyright 2023 Picovoice Inc. - - You may not use this file except in compliance with the license. A copy of the license is - located in the "LICENSE" file accompanying this source. - - Unless required by applicable law or agreed to in writing, software distributed under the - License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - express or implied. See the License for the specific language governing permissions and - limitations under the License. -*/ - -package ai.picovoice.eagle; - -/** - * Enumeration of possible enrollment feedback codes: - * - `AUDIO_OK`: The audio is good for enrollment. - * - `AUDIO_TOO_SHORT`: Audio length is insufficient for enrollment, - * i.e. it is shorter than`EagleProfiler.getMinEnrollSamples()`. - * - `UNKNOWN_SPEAKER`: There is another speaker in the audio that is different from the speaker - * being enrolled. Too much background noise may cause this error as well. - * - `NO_VOICE_FOUND`: The audio does not contain any voice, i.e. it is silent or - * has a low signal-to-noise ratio. - * - `QUALITY_ISSUE`: The audio quality is too low for enrollment due to a bad microphone - * or recording environment. - */ -public enum EagleProfilerEnrollFeedback { - AUDIO_OK, - AUDIO_TOO_SHORT, - UNKNOWN_SPEAKER, - NO_VOICE_FOUND, - QUALITY_ISSUE; -} diff --git a/binding/android/Eagle/eagle/src/main/java/ai/picovoice/eagle/EagleProfilerEnrollResult.java b/binding/android/Eagle/eagle/src/main/java/ai/picovoice/eagle/EagleProfilerEnrollResult.java deleted file mode 100644 index f76421e4..00000000 --- a/binding/android/Eagle/eagle/src/main/java/ai/picovoice/eagle/EagleProfilerEnrollResult.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - Copyright 2023 Picovoice Inc. - - You may not use this file except in compliance with the license. A copy of the license is - located in the "LICENSE" file accompanying this source. - - Unless required by applicable law or agreed to in writing, software distributed under the - License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - express or implied. See the License for the specific language governing permissions and - limitations under the License. -*/ - -package ai.picovoice.eagle; - -/** - * Representation of the feedback, given percentage and code. - */ -public class EagleProfilerEnrollResult { - - private final float percentage; - private final EagleProfilerEnrollFeedback feedback; - - public EagleProfilerEnrollResult(float percentage, int feedbackIdx) { - this.percentage = percentage; - this.feedback = EagleProfilerEnrollFeedback.values()[feedbackIdx]; - } - - public float getPercentage() { - return this.percentage; - } - - public EagleProfilerEnrollFeedback getFeedback() { - return this.feedback; - } - -} diff --git a/binding/android/Eagle/eagle/src/main/java/ai/picovoice/eagle/EagleProfilerNative.java b/binding/android/Eagle/eagle/src/main/java/ai/picovoice/eagle/EagleProfilerNative.java index 4943c32b..62280959 100644 --- a/binding/android/Eagle/eagle/src/main/java/ai/picovoice/eagle/EagleProfilerNative.java +++ b/binding/android/Eagle/eagle/src/main/java/ai/picovoice/eagle/EagleProfilerNative.java @@ -1,5 +1,5 @@ /* - Copyright 2023-2025 Picovoice Inc. + Copyright 2023-2026 Picovoice Inc. You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE" file accompanying this source. @@ -14,26 +14,29 @@ class EagleProfilerNative { - static native int getSampleRate(); - static native String getVersion(); + static native int getFrameLength(); + + static native int getSampleRate(); + static native long init( String accessKey, String modelPath, - String device) throws EagleException; + String device, + int minEnrollmentChunks, + float voiceThreshold) throws EagleException; static native void delete(long object); - static native EagleProfilerEnrollResult enroll( + static native float enroll( long handle, - short[] pcm, - int numSamples) throws EagleException; + short[] pcm) throws EagleException; + + static native float flush(long handle) throws EagleException; static native EagleProfileNative export(long handle) throws EagleException; static native void reset(long handle) throws EagleException; - static native int minEnrollSamples(long handle) throws EagleException; - } diff --git a/binding/android/EagleTestApp/eagle-test-app/build.gradle b/binding/android/EagleTestApp/eagle-test-app/build.gradle index f02e929b..2a20ebfb 100644 --- a/binding/android/EagleTestApp/eagle-test-app/build.gradle +++ b/binding/android/EagleTestApp/eagle-test-app/build.gradle @@ -120,7 +120,7 @@ dependencies { implementation 'androidx.appcompat:appcompat:1.6.1' implementation 'com.google.android.material:material:1.8.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' - implementation 'ai.picovoice:eagle-android:2.0.0' + implementation 'ai.picovoice:eagle-android:3.0.0' // Espresso UI Testing androidTestImplementation 'androidx.test.ext:junit:1.1.5' diff --git a/binding/android/EagleTestApp/eagle-test-app/src/androidTest/java/ai/picovoice/eagle/testapp/EagleTest.java b/binding/android/EagleTestApp/eagle-test-app/src/androidTest/java/ai/picovoice/eagle/testapp/EagleTest.java index 16a70277..70461589 100644 --- a/binding/android/EagleTestApp/eagle-test-app/src/androidTest/java/ai/picovoice/eagle/testapp/EagleTest.java +++ b/binding/android/EagleTestApp/eagle-test-app/src/androidTest/java/ai/picovoice/eagle/testapp/EagleTest.java @@ -1,5 +1,5 @@ /* - Copyright 2023-2025 Picovoice Inc. + Copyright 2023-2026 Picovoice Inc. You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE" file accompanying this source. @@ -32,8 +32,6 @@ import ai.picovoice.eagle.EagleException; import ai.picovoice.eagle.EagleProfile; import ai.picovoice.eagle.EagleProfiler; -import ai.picovoice.eagle.EagleProfilerEnrollFeedback; -import ai.picovoice.eagle.EagleProfilerEnrollResult; @RunWith(Enclosed.class) @@ -55,7 +53,13 @@ public void init() throws Exception { for (String path : enrollPaths) { File audioFile = new File(getAudioFilepath(path)); short[] pcm = readAudioFile(audioFile.getAbsolutePath()); - eagleProfiler.enroll(pcm); + int numFrames = pcm.length / eagleProfiler.getFrameLength(); + for (int i = 0; i < numFrames; i++) { + eagleProfiler.enroll(Arrays.copyOfRange( + pcm, + i * eagleProfiler.getFrameLength(), + (i + 1) * eagleProfiler.getFrameLength())); + } } profile = eagleProfiler.export(); @@ -140,7 +144,6 @@ public void testInitFailWithInvalidAccessKey() { .setAccessKey("") .setModelPath(defaultModelPath) .setDevice(device) - .setSpeakerProfile(profile) .build(appContext); } catch (EagleException e) { didFail = true; @@ -156,7 +159,6 @@ public void testInitFailWithMissingAccessKey() { new Eagle.Builder() .setModelPath(defaultModelPath) .setDevice(device) - .setSpeakerProfile(profile) .build(appContext); } catch (EagleException e) { didFail = true; @@ -174,7 +176,6 @@ public void testInitFailWithInvalidModelPath() { .setAccessKey(accessKey) .setModelPath(modelPath.getAbsolutePath()) .setDevice(device) - .setSpeakerProfile(profile) .build(appContext); } catch (EagleException e) { didFail = true; @@ -191,22 +192,6 @@ public void testInitFailWithInvalidDevice() { .setAccessKey(accessKey) .setModelPath(defaultModelPath) .setDevice("cloud:9") - .setSpeakerProfile(profile) - .build(appContext); - } catch (EagleException e) { - didFail = true; - } - - assertTrue(didFail); - } - - @Test - public void testInitFailWithMissingSpeakerProfile() { - boolean didFail = false; - try { - new Eagle.Builder() - .setAccessKey(accessKey) - .setDevice(device) .build(appContext); } catch (EagleException e) { didFail = true; @@ -220,7 +205,6 @@ public void getVersion() throws EagleException { Eagle eagle = new Eagle.Builder() .setAccessKey(accessKey) .setDevice(device) - .setSpeakerProfile(profile) .build(appContext); assertTrue(eagle.getVersion() != null && !eagle.getVersion().equals("")); @@ -233,7 +217,6 @@ public void getSampleRate() throws EagleException { Eagle eagle = new Eagle.Builder() .setAccessKey(accessKey) .setDevice(device) - .setSpeakerProfile(profile) .build(appContext); assertTrue(eagle.getSampleRate() > 0); @@ -246,22 +229,14 @@ public void testEagleProcess() throws Exception { Eagle eagle = new Eagle.Builder() .setAccessKey(accessKey) .setDevice(device) - .setSpeakerProfile(profile) .build(appContext); File audioFile = new File(getAudioFilepath(testPath)); short[] pcm = readAudioFile(audioFile.getAbsolutePath()); - int numFrames = pcm.length / eagle.getFrameLength(); - List scores = new ArrayList<>(); - for (int i = 0; i < numFrames; i++) { - float[] score = eagle.process(Arrays.copyOfRange( - pcm, - i * eagle.getFrameLength(), (i + 1) * eagle.getFrameLength()) - ); - scores.add(score[0]); - } + EagleProfile[] speakerProfiles = {profile}; + float[] scores = eagle.process(pcm, speakerProfiles); - assertTrue(Collections.max(scores) > 0.5); + assertTrue(scores[0] > 0.5); eagle.delete(); } @@ -270,22 +245,14 @@ public void testEagleProcessImposter() throws Exception { Eagle eagle = new Eagle.Builder() .setAccessKey(accessKey) .setDevice(device) - .setSpeakerProfile(profile) .build(appContext); File audioFile = new File(getAudioFilepath(imposterPath)); short[] pcm = readAudioFile(audioFile.getAbsolutePath()); - int numFrames = pcm.length / eagle.getFrameLength(); - List scores = new ArrayList<>(); - for (int i = 0; i < numFrames; i++) { - float[] score = eagle.process(Arrays.copyOfRange( - pcm, - i * eagle.getFrameLength(), (i + 1) * eagle.getFrameLength()) - ); - scores.add(score[0]); - } + EagleProfile[] speakerProfiles = {profile}; + float[] scores = eagle.process(pcm, speakerProfiles); - assertTrue(Collections.max(scores) < 0.5); + assertTrue(scores[0] < 0.5); eagle.delete(); } @@ -296,7 +263,6 @@ public void testErrorStack() { new Eagle.Builder() .setAccessKey("invalid") .setDevice(device) - .setSpeakerProfile(profile) .build(appContext); } catch (EagleException e) { error = e.getMessageStack(); @@ -309,7 +275,6 @@ public void testErrorStack() { new Eagle.Builder() .setAccessKey("invalid") .setDevice(device) - .setSpeakerProfile(profile) .build(appContext); } catch (EagleException e) { for (int i = 0; i < error.length; i++) { diff --git a/binding/android/EagleTestApp/eagle-test-app/src/androidTest/java/ai/picovoice/eagle/testapp/PerformanceTest.java b/binding/android/EagleTestApp/eagle-test-app/src/androidTest/java/ai/picovoice/eagle/testapp/PerformanceTest.java index 66f4a5e9..68a4f4c4 100644 --- a/binding/android/EagleTestApp/eagle-test-app/src/androidTest/java/ai/picovoice/eagle/testapp/PerformanceTest.java +++ b/binding/android/EagleTestApp/eagle-test-app/src/androidTest/java/ai/picovoice/eagle/testapp/PerformanceTest.java @@ -1,5 +1,5 @@ /* - Copyright 2023-2025 Picovoice Inc. + Copyright 2023-2026 Picovoice Inc. You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE" file accompanying this source. @@ -59,11 +59,18 @@ public void testProfilerPerformance() throws Exception { File audioFile = new File(getAudioFilepath(testPath)); short[] pcm = readAudioFile(audioFile.getAbsolutePath()); + int numFrames = pcm.length / eagleProfiler.getFrameLength(); long totalNSec = 0; for (int i = 0; i < numTestIterations + 1; i++) { long before = System.nanoTime(); - eagleProfiler.enroll(pcm); + for (int j = 0; j < numFrames; j++) { + eagleProfiler.enroll(Arrays.copyOfRange( + pcm, + j * eagleProfiler.getFrameLength(), + (j + 1) * eagleProfiler.getFrameLength())); + } + eagleProfiler.flush(); long after = System.nanoTime(); // throw away first run to account for cold start @@ -101,7 +108,14 @@ public void testProcPerformance() throws Exception { for (String path : enrollPaths) { File audioFile = new File(getAudioFilepath(path)); short[] pcm = readAudioFile(audioFile.getAbsolutePath()); - eagleProfiler.enroll(pcm); + int numFrames = pcm.length / eagleProfiler.getFrameLength(); + for (int j = 0; j < numFrames; j++) { + eagleProfiler.enroll(Arrays.copyOfRange( + pcm, + j * eagleProfiler.getFrameLength(), + (j + 1) * eagleProfiler.getFrameLength())); + } + eagleProfiler.flush(); } EagleProfile profile = eagleProfiler.export(); @@ -109,22 +123,16 @@ public void testProcPerformance() throws Exception { Eagle eagle = new Eagle.Builder() .setAccessKey(accessKey) .setDevice(device) - .setSpeakerProfile(profile) .build(appContext); File audioFile = new File(getAudioFilepath(testPath)); short[] pcm = readAudioFile(audioFile.getAbsolutePath()); - int numFrames = pcm.length / eagle.getFrameLength(); + EagleProfile[] speakerProfiles = {profile}; long totalNSec = 0; for (int i = 0; i < numTestIterations + 1; i++) { long before = System.nanoTime(); - for (int j = 0; j < numFrames; j++) { - eagle.process(Arrays.copyOfRange( - pcm, - i * eagle.getFrameLength(), (i + 1) * eagle.getFrameLength()) - ); - } + eagle.process(pcm, speakerProfiles); long after = System.nanoTime(); // throw away first run to account for cold start diff --git a/binding/android/EagleTestApp/eagle-test-app/src/main/java/ai/picovoice/eagle/testapp/MainActivity.java b/binding/android/EagleTestApp/eagle-test-app/src/main/java/ai/picovoice/eagle/testapp/MainActivity.java index 007a3c1f..589d38e0 100644 --- a/binding/android/EagleTestApp/eagle-test-app/src/main/java/ai/picovoice/eagle/testapp/MainActivity.java +++ b/binding/android/EagleTestApp/eagle-test-app/src/main/java/ai/picovoice/eagle/testapp/MainActivity.java @@ -1,5 +1,5 @@ /* - Copyright 2023 Picovoice Inc. + Copyright 2026 Picovoice Inc. You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE" file accompanying this source. @@ -117,7 +117,6 @@ public void runTest() { eagle = new Eagle.Builder() .setAccessKey(accessKey) .setModelPath(modelFile) - .setSpeakerProfile(profile) .build(getApplicationContext()); result.success = true; } catch (EagleException e) { @@ -132,8 +131,9 @@ public void runTest() { try { String audioPath = "audio_samples/speaker_1_test_utt.wav"; - ArrayList processResult = processTestAudio(eagle, audioPath); - if (processResult.size() > 0) { + EagleProfile[] speakerProfiles = {profile}; + float[] scores = processTestAudio(eagle, speakerProfiles, audioPath); + if (scores != null) { result.success = true; } else { result.success = false; @@ -224,12 +224,24 @@ private EagleProfile enrollTestSpeaker(EagleProfiler e, String audioPath) throws } short[] pcm = readAudioFile(testAudio.getAbsolutePath()); - e.enroll(pcm); + int numFrames = pcm.length / e.getFrameLength(); + for (int j = 0; j < numFrames; j++) { + e.enroll(Arrays.copyOfRange( + pcm, + j * e.getFrameLength(), + (j + 1) * e.getFrameLength())); + } + + e.flush(); return e.export(); } - private ArrayList processTestAudio(@NonNull Eagle e, String audioPath) throws Exception { + private float[] processTestAudio( + @NonNull Eagle e, + EagleProfile[] speakerProfiles, + String audioPath + ) throws Exception { File testAudio = new File(getApplicationContext().getFilesDir(), audioPath); if (!testAudio.exists()) { @@ -237,24 +249,9 @@ private ArrayList processTestAudio(@NonNull Eagle e, String audioPath) extractFile(audioPath); } - FileInputStream audioInputStream = new FileInputStream(testAudio); - - byte[] rawData = new byte[e.getFrameLength() * 2]; - short[] pcm = new short[e.getFrameLength()]; - ByteBuffer pcmBuff = ByteBuffer.wrap(rawData).order(ByteOrder.LITTLE_ENDIAN); - - audioInputStream.skip(44); - - ArrayList results = new ArrayList<>(); - while (audioInputStream.available() > 0) { - int numRead = audioInputStream.read(pcmBuff.array()); - if (numRead == e.getFrameLength() * 2) { - pcmBuff.asShortBuffer().get(pcm); - results.add(e.process(pcm)); - } - } + short[] pcm = readAudioFile(testAudio.getAbsolutePath()); - return results; + return e.process(pcm, speakerProfiles); } private void extractFile(String filepath) throws IOException { diff --git a/binding/android/README.md b/binding/android/README.md index 678aea56..75152bde 100644 --- a/binding/android/README.md +++ b/binding/android/README.md @@ -68,14 +68,12 @@ try { `EagleProfiler` is responsible for processing and enrolling PCM audio data, with the valid audio sample rate determined by `eagleProfiler.getSampleRate()`. The audio data must be 16-bit linearly-encoded and single-channel. -When passing samples to `eagleProfiler.enroll()`, the number of samples must be at -least `eagleProfiler.getMinEnrollSamples()` to ensure sufficient data for enrollment. The percentage value -obtained from this process indicates the progress of enrollment, while the feedback value can be utilized to determine -the status of the enrollment process. +When passing samples to `eagleProfiler.enroll`, the number of samples must be equal to `eagleProfiler.frameLength`. The +percentage value obtained from this process indicates the progress of enrollment. ```java -public short[] getNextEnrollAudioData() { - // get audio data +public short[] getNextAudioFrame() { + // get audio frame } EagleProfilerEnrollResult result = null; @@ -88,8 +86,8 @@ try { After the percentage reaches 100%, the enrollment process is considered complete. While it is possible to continue providing additional audio data to the profiler to improve the accuracy of the voiceprint, it is not necessary to do so. -Moreover, if the audio data submitted is unsuitable for enrollment, the feedback value will indicate the reason, and the -enrollment progress will remain unchanged. +Once all the audio from a single source has been submitted it is necessary to call `flush` before submitting any audio +from another source. ```java try { @@ -122,30 +120,35 @@ final String accessKey = "${ACCESS_KEY}"; try { Eagle eagle = new Eagle.Builder() .setAccessKey(accessKey) - .setSpeakerProfile(speakerProfile) .build(); } catch (EagleException e) { } ``` -When initialized, `eagle.getSampleRate()` specifies the valid sample rate for Eagle. The expected length of a frame, or the -number of audio samples in an input array, is defined by `eagle.getFrameLength()`. +When initialized, `eagle.getSampleRate()` specifies the valid sample rate for Eagle. The minimum length of a sample, or +the minimum +number of audio samples in an input array, is defined by `eagle.getMinProcessSamples()`. Like the profiler, Eagle is designed to work with single-channel audio that is encoded using 16-bit linear PCM. ```java -public short[] getNextAudioFrame() { - // get audio frame +public short[] getNextProcessAudioData() { + // get audio sample } try { + EagleProfile[] speakerProfiles = {speakerProfile}; + while (true) { - float[] scores = eagle.process(getNextAudioFrame()); + float[] scores = eagle.process(getNextProcessAudioData(), speakerProfiles); } } catch (EagleException e) { } ``` -The return value `scores` represents the degree of similarity between the input audio frame and the enrolled speakers. -This value is a floating-point number ranging from 0 to 1, with higher values indicating a greater degree of similarity. +The return value `scores` will be null or be an array that contains floating-point numbers that indicate the similarity +between the input audio frame and the enrolled speakers. Each value in the array corresponds to a specific enrolled +speaker, maintaining the same order as the speaker profiles provided during initialization. The values in the array +range from 0.0 to 1.0, where higher values indicate a stronger degree of similarity. A result of null indicates that +there was not enough voice in the audio to recognize any speakers. Finally, when done be sure to explicitly release the resources: diff --git a/binding/ios/Eagle-iOS.podspec b/binding/ios/Eagle-iOS.podspec index a3c9b090..bdbad160 100644 --- a/binding/ios/Eagle-iOS.podspec +++ b/binding/ios/Eagle-iOS.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = 'Eagle-iOS' s.module_name = 'Eagle' - s.version = '2.0.0' + s.version = '3.0.0' s.license = {:type => 'Apache 2.0'} s.summary = 'iOS binding for Picovoice\'s Eagle speaker recognition engine' s.description = diff --git a/binding/ios/Eagle.swift b/binding/ios/Eagle.swift index 3ee15a08..9801ed9a 100644 --- a/binding/ios/Eagle.swift +++ b/binding/ios/Eagle.swift @@ -1,5 +1,5 @@ // -// Copyright 2023-2025 Picovoice Inc. +// Copyright 2023-2026 Picovoice Inc. // You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE" // file accompanying this source. // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on @@ -14,17 +14,14 @@ import PvEagle /// It can determine audio similarity scores given a set of EagleProfiles. public class Eagle: EagleBase { - public static let frameLength = Int(pv_eagle_frame_length()) - - private var speakerCount = 0 - private var handle: OpaquePointer? + private var minProcessAudioLength: Int? + /// Constructor. /// /// - Parameters: /// - accessKey: AccessKey obtained from the Picovoice Console (https://console.picovoice.ai/) - /// - speakerProfiles: An array of EagleProfile objects obtained from EagleProfiler. /// - modelPath: Absolute path to file containing model parameters. /// - device: String representation of the device (e.g., CPU or GPU) to use. If set to `best`, the most /// suitable device is selected automatically. If set to `gpu`, the engine uses the first available GPU @@ -32,19 +29,17 @@ public class Eagle: EagleBase { /// is the index of the target GPU. If set to `cpu`, the engine will run on the CPU with the default /// number of threads. To specify the number of threads, set this argument to `cpu:${NUM_THREADS}`, /// where `${NUM_THREADS}` is the desired number of threads. + /// - voiceThreshold: Sensitivity threshold for detecting voice. The value should be a number within [0, 1]. A + /// higher threshold increases detection confidence values at the cost of potentially missing frames of voice. /// - Throws: EagleError public init( accessKey: String, - speakerProfiles: [EagleProfile], modelPath: String? = nil, - device: String? = nil + device: String? = nil, + voiceThreshold: Float = 0.3 ) throws { super.init() - if speakerProfiles.isEmpty { - throw EagleInvalidArgumentError("`speakerProfiles` must contain at least one profile") - } - var modelPathArg = modelPath if modelPath == nil { @@ -63,53 +58,31 @@ public class Eagle: EagleBase { deviceArg = "best" } - var speakerHandles: [UnsafeRawPointer?] = [] - for profile in speakerProfiles { - var profileBytes = profile.getBytes() - speakerHandles.append(&profileBytes) - } - - speakerCount = speakerProfiles.count - pv_set_sdk(Eagle.sdk) - let status = pv_eagle_init( + var status = pv_eagle_init( accessKey, modelPathArg, deviceArg, - Int32(speakerCount), - speakerHandles, + voiceThreshold, &handle) if status != PV_STATUS_SUCCESS { let messageStack = try Eagle.getMessageStack() throw Eagle.pvStatusToEagleError(status, "Eagle init failed", messageStack) } - } - /// Constructor. - /// - /// - Parameters: - /// - accessKey: AccessKey obtained from the Picovoice Console (https://console.picovoice.ai/) - /// - speakerProfile: An EagleProfile object obtained from EagleProfiler. - /// - modelPath: Absolute path to file containing model parameters. - /// - device: String representation of the device (e.g., CPU or GPU) to use. If set to `best`, the most - /// suitable device is selected automatically. If set to `gpu`, the engine uses the first available GPU - /// device. To select a specific GPU device, set this argument to `gpu:${GPU_INDEX}`, where `${GPU_INDEX}` - /// is the index of the target GPU. If set to `cpu`, the engine will run on the CPU with the default - /// number of threads. To specify the number of threads, set this argument to `cpu:${NUM_THREADS}`, - /// where `${NUM_THREADS}` is the desired number of threads. - /// - Throws: EagleError - public convenience init( - accessKey: String, - speakerProfile: EagleProfile, - modelPath: String? = nil, - device: String = "best" - ) throws { - try self.init( - accessKey: accessKey, - speakerProfiles: [speakerProfile], - modelPath: modelPath, - device: device) + var cMinAudioLengthSamples: Int32 = 0 + status = pv_eagle_process_min_audio_length_samples( + handle, + &cMinAudioLengthSamples) + if status != PV_STATUS_SUCCESS { + let messageStack = try Eagle.getMessageStack() + throw Eagle.pvStatusToEagleError( + status, + "Eagle process_min_audio_length_sample failed", + messageStack) + } + minProcessAudioLength = Int(cMinAudioLengthSamples) } deinit { @@ -124,52 +97,80 @@ public class Eagle: EagleBase { } } - /// Processes given audio data and returns its speaker likelihood scores. + /// Processes given audio data and returns its speaker likelihood scores or nil. /// /// - Parameters: - /// - pcm: An array of audio samples. The number of samples per frame can be attained - /// by calling `.frameLength`. The audio needs to have a sample rate - /// equal to `.sampleRate` and be single-channel, 16-bit linearly-encoded. + /// - pcm: An array of audio samples. The minimum number of samples per frame can be + /// attained by calling `.minProcessSamples()`. The audio needs to have a sample + /// rate equal to `.sampleRate` and be single-channel, 16-bit linearly-encoded. + /// - speakerProfiles: An array of EagleProfile objects obtained from EagleProfiler. /// - Throws: EagleError - /// - Returns: Similarity scores for each enrolled speaker. - /// The scores are in the range [0, 1] with 1 being a perfect match. - public func process(pcm: [Int16]) throws -> [Float] { + /// - Returns: A list of similarity scores for each speaker profile or null. A higher + /// score indicates that the voice belongs to the corresponding speaker. The range + /// is [0, 1] with 1 representing a perfect match. A result of null indicates that there + /// was not enough voice in the audio to recognize any speakers. + public func process( + pcm: [Int16], + speakerProfiles: [EagleProfile], + ) throws -> [Float]? { if handle == nil { throw EagleInvalidStateError("Eagle must be initialized before indexing") } - let scores = UnsafeMutableBufferPointer.allocate(capacity: speakerCount) + if speakerProfiles.isEmpty { + throw EagleInvalidArgumentError("`speakerProfiles` must contain at least one profile") + } + + let speakerHandles = UnsafeMutablePointer?>.allocate( + capacity: speakerProfiles.count) + for i in 0...allocate(capacity: profileBytes.count) + temp.initialize(from: profileBytes, count: profileBytes.count) + speakerHandles[i] = temp + } + + let rawSpeakerHandles = speakerHandles.withMemoryRebound( + to: UnsafeMutableRawPointer?.self, + capacity: speakerProfiles.count) { $0 } + + var cScores: UnsafeMutablePointer? let status = pv_eagle_process( handle, pcm, - scores.baseAddress) + Int32(pcm.count), + rawSpeakerHandles, + Int32(speakerProfiles.count), + &cScores) if status != PV_STATUS_SUCCESS { let messageStack = try Eagle.getMessageStack() throw Eagle.pvStatusToEagleError(status, "Eagle process failed", messageStack) } - return Array(scores) - } + if cScores != nil { + var scores: [Float] = [] + for i in 0.. Int { + if handle == nil { + throw EagleInvalidStateError("Eagle must be initialized before calling minProcessSamples") } + + return minProcessAudioLength! } } diff --git a/binding/ios/EagleAppTest/EagleAppTest.xcodeproj/project.pbxproj b/binding/ios/EagleAppTest/EagleAppTest.xcodeproj/project.pbxproj index b032342d..5075d108 100644 --- a/binding/ios/EagleAppTest/EagleAppTest.xcodeproj/project.pbxproj +++ b/binding/ios/EagleAppTest/EagleAppTest.xcodeproj/project.pbxproj @@ -14,6 +14,13 @@ 1E0064D427CEEA66006FF6E9 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 1E0064D227CEEA66006FF6E9 /* LaunchScreen.storyboard */; }; 1E00654627CFF260006FF6E9 /* EagleAppTestUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E0064E827CEEA66006FF6E9 /* EagleAppTestUITests.swift */; }; 1E5B7B042800D9BE00F8BDDB /* PerformanceTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E5B7B032800D9BE00F8BDDB /* PerformanceTest.swift */; }; + 3414A5D62F845E88001F1FA6 /* Eagle in Frameworks */ = {isa = PBXBuildFile; productRef = 3414A5D52F845E88001F1FA6 /* Eagle */; }; + 3414A5D92F845EA7001F1FA6 /* Eagle in Frameworks */ = {isa = PBXBuildFile; productRef = 3414A5D82F845EA7001F1FA6 /* Eagle */; }; + 3414A5DC2F845ECF001F1FA6 /* Eagle in Frameworks */ = {isa = PBXBuildFile; productRef = 3414A5DB2F845ECF001F1FA6 /* Eagle */; }; + 3414A5DE2F845EF8001F1FA6 /* Eagle in Frameworks */ = {isa = PBXBuildFile; productRef = 3414A5DD2F845EF8001F1FA6 /* Eagle */; }; + 3414A5E12F845F34001F1FA6 /* Eagle in Frameworks */ = {isa = PBXBuildFile; productRef = 3414A5E02F845F34001F1FA6 /* Eagle */; }; + 3414A5E72F846076001F1FA6 /* Eagle in Frameworks */ = {isa = PBXBuildFile; productRef = 3414A5E62F846076001F1FA6 /* Eagle */; }; + 34CEA4832F7DAE2D00ABC219 /* Eagle in Frameworks */ = {isa = PBXBuildFile; productRef = 34CEA4822F7DAE2D00ABC219 /* Eagle */; }; 36696536961DE78B3E1C06FA /* (null) in Frameworks */ = {isa = PBXBuildFile; }; C757D8CD28A1C77100F391C8 /* BaseTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C757D8CB28A1C77100F391C8 /* BaseTest.swift */; }; C790A6FB2A2012C40074FF7A /* audio_samples in Resources */ = {isa = PBXBuildFile; fileRef = C790A6FA2A2012C40074FF7A /* audio_samples */; }; @@ -63,7 +70,14 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 3414A5D62F845E88001F1FA6 /* Eagle in Frameworks */, E173C8FE2CFE43C900A0903C /* Eagle in Frameworks */, + 3414A5DC2F845ECF001F1FA6 /* Eagle in Frameworks */, + 3414A5E72F846076001F1FA6 /* Eagle in Frameworks */, + 3414A5DE2F845EF8001F1FA6 /* Eagle in Frameworks */, + 34CEA4832F7DAE2D00ABC219 /* Eagle in Frameworks */, + 3414A5E12F845F34001F1FA6 /* Eagle in Frameworks */, + 3414A5D92F845EA7001F1FA6 /* Eagle in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -237,7 +251,7 @@ ); mainGroup = 1E0064BB27CEEA65006FF6E9; packageReferences = ( - E1F352FC2D00E9790069B0E6 /* XCRemoteSwiftPackageReference "eagle" */, + 3414A5E52F846076001F1FA6 /* XCRemoteSwiftPackageReference "eagle" */, ); productRefGroup = 1E0064C527CEEA65006FF6E9 /* Products */; projectDirPath = ""; @@ -462,12 +476,14 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = 65723695GD; + DEVELOPMENT_TEAM = QW8RJJCS4H; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = EagleAppTest/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = PorcupineDemoApp; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; INFOPLIST_KEY_UIMainStoryboardFile = Main; + INFOPLIST_KEY_UIRequiredDeviceCapabilities = armv7; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; IPHONEOS_DEPLOYMENT_TARGET = 16.0; @@ -491,12 +507,14 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = 65723695GD; + DEVELOPMENT_TEAM = QW8RJJCS4H; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = EagleAppTest/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = PorcupineDemoApp; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; INFOPLIST_KEY_UIMainStoryboardFile = Main; + INFOPLIST_KEY_UIRequiredDeviceCapabilities = armv7; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; IPHONEOS_DEPLOYMENT_TARGET = 16.0; @@ -659,17 +677,46 @@ /* End XCLocalSwiftPackageReference section */ /* Begin XCRemoteSwiftPackageReference section */ - E1F352FC2D00E9790069B0E6 /* XCRemoteSwiftPackageReference "eagle" */ = { + 3414A5E52F846076001F1FA6 /* XCRemoteSwiftPackageReference "eagle" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/Picovoice/eagle"; requirement = { kind = exactVersion; - version = 2.0.0; + version = 3.0.0; }; }; /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ + 3414A5D52F845E88001F1FA6 /* Eagle */ = { + isa = XCSwiftPackageProductDependency; + productName = Eagle; + }; + 3414A5D82F845EA7001F1FA6 /* Eagle */ = { + isa = XCSwiftPackageProductDependency; + productName = Eagle; + }; + 3414A5DB2F845ECF001F1FA6 /* Eagle */ = { + isa = XCSwiftPackageProductDependency; + productName = Eagle; + }; + 3414A5DD2F845EF8001F1FA6 /* Eagle */ = { + isa = XCSwiftPackageProductDependency; + productName = Eagle; + }; + 3414A5E02F845F34001F1FA6 /* Eagle */ = { + isa = XCSwiftPackageProductDependency; + productName = Eagle; + }; + 3414A5E62F846076001F1FA6 /* Eagle */ = { + isa = XCSwiftPackageProductDependency; + package = 3414A5E52F846076001F1FA6 /* XCRemoteSwiftPackageReference "eagle" */; + productName = Eagle; + }; + 34CEA4822F7DAE2D00ABC219 /* Eagle */ = { + isa = XCSwiftPackageProductDependency; + productName = Eagle; + }; E173C8FD2CFE43C900A0903C /* Eagle */ = { isa = XCSwiftPackageProductDependency; package = E173C8FB2CFE40F000A0903C /* XCLocalSwiftPackageReference "../../../../eagle" */; diff --git a/binding/ios/EagleAppTest/EagleAppTestUITests/BaseTest.swift b/binding/ios/EagleAppTest/EagleAppTestUITests/BaseTest.swift index a53466d4..a1fc8c24 100644 --- a/binding/ios/EagleAppTest/EagleAppTestUITests/BaseTest.swift +++ b/binding/ios/EagleAppTest/EagleAppTestUITests/BaseTest.swift @@ -1,5 +1,5 @@ // -// Copyright 2023-2025 Picovoice Inc. +// Copyright 2023-2026 Picovoice Inc. // You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE" // file accompanying this source. // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on diff --git a/binding/ios/EagleAppTest/EagleAppTestUITests/EagleAppTestUITests.swift b/binding/ios/EagleAppTest/EagleAppTestUITests/EagleAppTestUITests.swift index 93d32caa..7abeca7b 100644 --- a/binding/ios/EagleAppTest/EagleAppTestUITests/EagleAppTestUITests.swift +++ b/binding/ios/EagleAppTest/EagleAppTestUITests/EagleAppTestUITests.swift @@ -1,5 +1,5 @@ // -// Copyright 2023-2025 Picovoice Inc. +// Copyright 2023-2026 Picovoice Inc. // You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE" // file accompanying this source. // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on @@ -37,31 +37,30 @@ class EagleAppTestUITests: BaseTest { } private func initEagle() throws -> Eagle { - let enrollUrls = enrollUrls() - - let eagleProfiler = try EagleProfiler(accessKey: accessKey, device: device) - for url in enrollUrls { - let pcm = try readPcmFromFile(testAudioURL: url) - (_, _) = try eagleProfiler.enroll(pcm: pcm) - } - - let profile = try eagleProfiler.export() - eagleProfiler.delete() - - return try Eagle(accessKey: accessKey, speakerProfiles: [profile], device: device) + return try Eagle( + accessKey: accessKey, + device: device + ) } func testEagleEnrollment() throws { let enrollUrls = enrollUrls() var percentage: Float = 0.0 - var feedback: EagleProfilerEnrollFeedback? let eagleProfiler = try EagleProfiler(accessKey: accessKey, device: device) for url in enrollUrls { let pcm = try readPcmFromFile(testAudioURL: url) - (percentage, feedback) = try eagleProfiler.enroll(pcm: pcm) - XCTAssertEqual(feedback, EagleProfilerEnrollFeedback.AUDIO_OK) + let numFrames = pcm.count / EagleProfiler.frameLength + + for i in 0.. 0) let profile = try eagleProfiler.export() @@ -71,42 +70,78 @@ class EagleAppTestUITests: BaseTest { } func testEagleProcess() throws { + let enrollUrls = enrollUrls() + + let eagleProfiler = try EagleProfiler( + accessKey: accessKey, + device: device) + + for url in enrollUrls { + let pcm = try readPcmFromFile(testAudioURL: url) + let numFrames = pcm.count / EagleProfiler.frameLength + + for i in 0.. 0) @@ -174,24 +198,38 @@ class EagleAppTestUITests: BaseTest { func testProcessMessageStack() throws { let enrollUrls = enrollUrls() - let eagleProfiler = try EagleProfiler(accessKey: accessKey, device: device) + let eagleProfiler = try EagleProfiler( + accessKey: accessKey, + device: device) + for url in enrollUrls { let pcm = try readPcmFromFile(testAudioURL: url) - (_, _) = try eagleProfiler.enroll(pcm: pcm) + let numFrames = pcm.count / EagleProfiler.frameLength + + for i in 0.. 0) XCTAssert("\(error.localizedDescription)".count < 1024) diff --git a/binding/ios/EagleAppTest/PerformanceTest/PerformanceTest.swift b/binding/ios/EagleAppTest/PerformanceTest/PerformanceTest.swift index 856d02f1..2fee3787 100644 --- a/binding/ios/EagleAppTest/PerformanceTest/PerformanceTest.swift +++ b/binding/ios/EagleAppTest/PerformanceTest/PerformanceTest.swift @@ -1,5 +1,5 @@ // -// Copyright 2023-2025 Picovoice Inc. +// Copyright 2023-2026 Picovoice Inc. // You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE" // file accompanying this source. // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on @@ -41,6 +41,7 @@ class PerformanceTest: XCTestCase { _ = pcm.withUnsafeMutableBytes { audioData.copyBytes(to: $0, from: 44.. EagleProfilerEnrollFeedback { - switch status { - case PV_EAGLE_PROFILER_ENROLL_FEEDBACK_AUDIO_OK: - return EagleProfilerEnrollFeedback.AUDIO_OK - case PV_EAGLE_PROFILER_ENROLL_FEEDBACK_AUDIO_TOO_SHORT: - return EagleProfilerEnrollFeedback.AUDIO_TOO_SHORT - case PV_EAGLE_PROFILER_ENROLL_FEEDBACK_UNKNOWN_SPEAKER: - return EagleProfilerEnrollFeedback.UNKNOWN_SPEAKER - case PV_EAGLE_PROFILER_ENROLL_FEEDBACK_NO_VOICE_FOUND: - return EagleProfilerEnrollFeedback.NO_VOICE_FOUND - case PV_EAGLE_PROFILER_ENROLL_FEEDBACK_QUALITY_ISSUE: - return EagleProfilerEnrollFeedback.QUALITY_ISSUE - default: - return EagleProfilerEnrollFeedback.AUDIO_OK - } - } - internal static func getMessageStack() throws -> [String] { var messageStackRef: UnsafeMutablePointer?>? var messageStackDepth: Int32 = 0 diff --git a/binding/ios/EagleProfiler.swift b/binding/ios/EagleProfiler.swift index c2a862a6..b21c5206 100644 --- a/binding/ios/EagleProfiler.swift +++ b/binding/ios/EagleProfiler.swift @@ -1,5 +1,5 @@ // -// Copyright 2023-2025 Picovoice Inc. +// Copyright 2023-2026 Picovoice Inc. // You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE" // file accompanying this source. // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on @@ -10,22 +10,15 @@ import Foundation import PvEagle -public enum EagleProfilerEnrollFeedback { - case AUDIO_OK - case AUDIO_TOO_SHORT - case UNKNOWN_SPEAKER - case NO_VOICE_FOUND - case QUALITY_ISSUE -} - /// EagleProfiler class for iOS Eagle text-independent speaker recognition engine. /// It enrolls a speaker given a set of utterances and then constructs a profile for the enrolled speaker. public class EagleProfiler: EagleBase { + public static let frameLength = Int(pv_eagle_profiler_frame_length()) + private var handle: OpaquePointer? private var speakerProfileSize: Int? - private var minEnrollAudioLength: Int? /// Constructor. /// @@ -38,11 +31,18 @@ public class EagleProfiler: EagleBase { /// is the index of the target GPU. If set to `cpu`, the engine will run on the CPU with the default /// number of threads. To specify the number of threads, set this argument to `cpu:${NUM_THREADS}`, /// where `${NUM_THREADS}` is the desired number of threads. + /// - minEnrollmentChunks: Minimum number of chunks to be processed before enroll returns 100%. The value should + /// be a number greater than or equal to 1. A higher number results in more accurate profiles at the cost of + /// needing more data to create the profile. + /// - voiceThreshold: Sensitivity threshold for detecting voice. The value should be a number within [0, 1]. A + /// higher threshold increases detection confidence values at the cost of potentially missing frames of voice. /// - Throws: EagleError public init( accessKey: String, modelPath: String? = nil, - device: String? = nil + device: String? = nil, + minEnrollmentChunks: Int = 1, + voiceThreshold: Float = 0.3 ) throws { super.init() @@ -70,6 +70,8 @@ public class EagleProfiler: EagleBase { accessKey, modelPathArg, deviceArg, + Int32(minEnrollmentChunks), + voiceThreshold, &handle) if status != PV_STATUS_SUCCESS { let messageStack = try EagleProfiler.getMessageStack() @@ -85,19 +87,6 @@ public class EagleProfiler: EagleBase { throw EagleProfiler.pvStatusToEagleError(status, "EagleProfiler speaker_profile_size failed", messageStack) } speakerProfileSize = Int(cSpeakerProfileSizeBytes) - - var cMinAudioLengthSamples: Int32 = 0 - status = pv_eagle_profiler_enroll_min_audio_length_samples( - handle, - &cMinAudioLengthSamples) - if status != PV_STATUS_SUCCESS { - let messageStack = try EagleProfiler.getMessageStack() - throw EagleProfiler.pvStatusToEagleError( - status, - "EagleProfiler enrollment_min_audio_length_sample failed", - messageStack) - } - minEnrollAudioLength = Int(cMinAudioLengthSamples) } deinit { @@ -116,23 +105,18 @@ public class EagleProfiler: EagleBase { /// - Parameters: /// - pcm: An array of audio samples. The audio needs to have a sample rate /// equal to `.sampleRate` and be single-channel, 16-bit linearly-encoded. - /// In addition it must be at least `.minEnrollSamples` samples long. + /// In addition it must be `.frameLength` samples long. /// - Throws: EagleError - /// - Returns: A tuple containing a the percentage of enrollment completed as a Float and - /// an enum representing the feedback code. - public func enroll(pcm: [Int16]) throws -> (Float, EagleProfilerEnrollFeedback) { - + /// - Returns: The percentage of enrollment completed as a Float. + public func enroll(pcm: [Int16]) throws -> Float { if handle == nil { throw EagleInvalidStateError("EagleProfiler must be initialized before enrolling") } - var cEnrollError: pv_eagle_profiler_enroll_feedback_t = PV_EAGLE_PROFILER_ENROLL_FEEDBACK_AUDIO_OK var cPercentage: Float32 = 0 let status = pv_eagle_profiler_enroll( handle, pcm, - Int32(pcm.count), - &cEnrollError, &cPercentage) if status != PV_STATUS_SUCCESS { @@ -140,10 +124,29 @@ public class EagleProfiler: EagleBase { throw EagleProfiler.pvStatusToEagleError(status, "EagleProfiler enroll failed", messageStack) } - let enrollFeedback = pvProfilerEnrollmentErrorToEnrollFeedback(cEnrollError) - let percentage = Float(cPercentage) + return Float(cPercentage) + } + + /// Marks the end of the audio stream, flushes internal state of the object + /// and returns the percentage of enrollment completed. + /// - Throws: EagleError + /// - Returns: The percentage of enrollment completed as a Float. + public func flush() throws -> Float { + if handle == nil { + throw EagleInvalidStateError("EagleProfiler must be initialized before enrolling") + } + + var cPercentage: Float32 = 0 + let status = pv_eagle_profiler_flush( + handle, + &cPercentage) - return (percentage, enrollFeedback) + if status != PV_STATUS_SUCCESS { + let messageStack = try EagleProfiler.getMessageStack() + throw EagleProfiler.pvStatusToEagleError(status, "EagleProfiler enroll failed", messageStack) + } + + return Float(cPercentage) } /// Exports the speaker profile. The exported profile can be used in `Eagle` or stored for later use. @@ -181,15 +184,4 @@ public class EagleProfiler: EagleBase { throw EagleProfiler.pvStatusToEagleError(status, "EagleProfiler reset failed", messageStack) } } - - /// Getter for the minimum length of the input pcm required by `enroll()`. - /// - Throws: EagleError - /// - Returns: Minimum number of samples required for a call to `enroll()` - public func minEnrollSamples() throws -> Int { - if handle == nil { - throw EagleInvalidStateError("EagleProfiler must be initialized before calling minEnrollSamples") - } - - return minEnrollAudioLength! - } } diff --git a/binding/ios/README.md b/binding/ios/README.md index fa3c3905..d397d5f7 100644 --- a/binding/ios/README.md +++ b/binding/ios/README.md @@ -58,36 +58,36 @@ do { } catch { } ``` -`EagleProfiler` is responsible for processing and enrolling PCM audio data, with the valid audio sample rate determined by `EagleProfiler.sampleRate`. The audio data must be 16-bit linearly-encoded and single-channel. +`EagleProfiler` is responsible for processing and enrolling PCM audio data, with the valid audio sample rate determined +by `eagleProfiler.sampleRate`. The audio data must be 16-bit linearly-encoded and single-channel. -When passing samples to `eagleProfiler.enroll()`, the number of samples must be at least `eagleProfiler.minEnrollSamples()` to ensure sufficient data for enrollment. The percentage value obtained from this process indicates the progress of enrollment, while the feedback value can be utilized to determine the status of the enrollment process. +When passing samples to `eagleProfiler.enroll`, the number of samples must be equal to `eagleProfiler.frameLength`. The +percentage value obtained from this process indicates the progress of enrollment. ```swift -func get_next_enroll_audio_data(numSamples: Int) -> [Int16] { +func get_next_audio_frame(frameLength: Int) -> [Int16] { // ... } do { - let numSamples = eagleProfiler.minEnrollSamples() - var percentage = 0.0 - var feedback: EagleProfilerEnrollFeedback? - while (percentage < 100.0) { - (percentage, feedback) = try eagleProfiler.enroll(pcm: get_next_enroll_audio_data(numSamples: numSamples)) + percentage = try eagleProfiler.enroll(pcm: get_next_audio_frame()) } } catch { } ``` After the percentage reaches 100%, the enrollment process is considered complete. While it is possible to continue providing additional audio data to the profiler to improve the accuracy of the voiceprint, it is not necessary to do so. -Moreover, if the audio data submitted is unsuitable for enrollment, the feedback value will indicate the reason, and the enrollment progress will remain unchanged. +Once all the audio from a single source has been submitted it is necessary to call `flush` before submitting any audio +from another source. ```swift let speakerProfile = try eagleProfiler.export() ``` -To reset the profiler and enroll a new speaker, the `eagleProfiler.reset()` method can be used. This method clears all previously stored data, making it possible to start a new enrollment session with a different speaker. +To reset the profiler and enroll a new speaker, the `eagleProfiler.reset()` method can be used. This method clears all +previously stored data, making it possible to start a new enrollment session with a different speaker. Finally, when done be sure to explicitly release the resources: @@ -100,25 +100,29 @@ eagleProfiler.delete() Create an instance of the engine: ```swift -let eagle = Eagle(accessKey: accessKey, speakerProfiles: [speakerProfile]) +let eagle = Eagle(accessKey: accessKey) ``` -`Eagle.sampleRate` specifies the valid sample rate for Eagle. The expected length of a frame, or the number of audio samples in an input array, is defined by `Eagle.frameLength`. +`Eagle.sampleRate` specifies the valid sample rate for Eagle. The expected length of a frame, or the number of audio +samples in an input array, is defined by `Eagle.frameLength`. Like the profiler, Eagle is designed to work with single-channel audio that is encoded using 16-bit linear PCM. ```swift -func get_next_audio_frame() -> [Int16] { +func get_next_process_audio_data(numSamples: Int) -> [Int16] { // ... } do { - let profileScores = try eagle.process(pcm: get_next_audio_frame()) + let profileScores = try eagle.process(pcm: get_next_process_audio_data(eagle.minProcessSamples()), speakerProfiles: [speakerProfile]) } catch { } ``` -The return value `profileScores` represents the degree of similarity between the input audio frame and the enrolled speakers. -This value is an array of floating-point numbers ranging from 0 to 1, with higher values indicating a greater degree of similarity. Index 0 indicates the first speaker, index 1 the second, and so on. +The return value `scores` will be null or be an array that contains floating-point numbers that indicate the similarity +between the input audio frame and the enrolled speakers. Each value in the array corresponds to a specific enrolled +speaker, maintaining the same order as the speaker profiles provided during initialization. The values in the array +range from 0.0 to 1.0, where higher values indicate a stronger degree of similarity. A result of null indicates that +there was not enough voice in the audio to recognize any speakers. Finally, when done be sure to explicitly release the resources: diff --git a/binding/nodejs/README.md b/binding/nodejs/README.md index 18ca8544..c159498f 100644 --- a/binding/nodejs/README.md +++ b/binding/nodejs/README.md @@ -59,9 +59,8 @@ const eagleProfiler = new EagleProfiler(accessKey); `EagleProfiler` is responsible for processing and enrolling PCM audio data, with the valid audio sample rate determined by `eagleProfiler.sampleRate`. The audio data must be 16-bit linearly-encoded and single-channel. -When passing samples to `eagleProfiler.enroll`, the number of samples must be at -least `eagleProfiler.minEnrollSamples` to ensure sufficient data for enrollment. The percentage value -returned from this process indicates the progress of enrollment, while the feedback value can be utilized to determine the status of the enrollment process. +When passing samples to `eagleProfiler.enroll`, the number of samples must be equal to `eagleProfiler.frameLength`. The +percentage value obtained from this process indicates the progress of enrollment. ```typescript const { EnrollProgress } = require("@picovoice/eagle-node"); @@ -70,24 +69,23 @@ function getAudioData(numSamples): Int16Array { // get audio frame of size `numSamples` } +function hasAudioData(numSamples): Boolean { + // check if there are any remaining samples in the stream +} + let percentage = 0; -while (percentage < 100) { - const audioData = getAudioData(eagleProfiler.minEnrollSamples); - - const result: EnrollProgress = await eagleProfiler.enroll(audioData); - if (result.feedback === EagleProfilerEnrollFeedback.NONE) { - // audio is good! - } else { - // feedback code will tell you why audio was not used in enrollment - } - percentage = result.percentage; +while (percentage < 100 && hasAudioData(eagleProfiler.frameLength)) { + const audioData = getAudioData(eagleProfiler.frameLength); + percentage = eagleProfiler.enroll(audioData); } + +percentage = eagleProfiler.flush(); ``` After the percentage reaches 100%, the enrollment process is considered complete. While it is possible to continue providing additional audio data to the profiler to improve the accuracy of the voiceprint, it is not necessary to do so. -Moreover, if the audio data submitted is unsuitable for enrollment, the feedback value will indicate the reason, and the -enrollment progress will remain unchanged. +Once all the audio from a single source has been submitted it is necessary to call `flush` before submitting any audio +from another source. ```typescript const speakerProfile: Uint8Array = eagleProfiler.export(); @@ -106,33 +104,38 @@ eagleProfiler.release(); ### Speaker Recognition -Create an instance of the engine with one or more speaker profiles created by the profiler: +Create an instance of the engine: ```typescript const { Eagle } = require("@picovoice/eagle-node"); const accessKey = "${ACCESS_KEY}"; // Obtained from the Picovoice Console (https://console.picovoice.ai/) -const eagle = new Eagle(accessKey, speakerProfile); +const eagle = new Eagle(accessKey); ``` -When initialized, `eagle.sampleRate` specifies the valid sample rate for Eagle. The expected length of a frame, or the -number of audio samples in an input array, is defined by `eagle.frameLength`. +When initialized, `eagle.sampleRate` specifies the valid sample rate for Eagle. The minimum length of a sample, or the +number of audio samples in an input array, is defined by `eagle.minProcessSamples`. Like the profiler, Eagle is designed to work with single-channel audio that is encoded using 16-bit linear PCM. +Process audio with one or more speaker profiles from the `EagleProfiler`. + ```typescript function getAudioData(numSamples): Int16Array { // get audio frame of size `numSamples` } while (true) { - const audioData = getAudioData(eagle.frameLength); - const scores: number[] = eagle.process(audioData); + const audioData = getAudioData(eagle.minProcessSamples); + const scores: number[] = eagle.process(audioData, speakerProfile); } ``` -The return value `scores` represents the degree of similarity between the input audio frame and the enrolled speakers. -Each value is a floating-point number ranging from 0 to 1, with higher values indicating a greater degree of similarity. +The `scores` will be null or be an array that contains floating-point numbers that indicate the similarity between the +input audio frame and the enrolled speakers. Each value in the array corresponds to a specific enrolled speaker, +maintaining the same order as the speaker profiles provided during initialization. The values in the array range from +0.0 to 1.0, where higher values indicate a stronger degree of similarity. A result of null indicates that there was not +enough voice in the audio to recognize any speakers. Finally, when done be sure to explicitly release the resources: diff --git a/binding/nodejs/package.json b/binding/nodejs/package.json index 8c42926d..0574887a 100644 --- a/binding/nodejs/package.json +++ b/binding/nodejs/package.json @@ -1,7 +1,7 @@ { "name": "@picovoice/eagle-node", - "version": "2.0.1", + "version": "3.0.0", "description": "Picovoice Eagle Node.js binding", "main": "dist/index.js", "types": "dist/types/index.d.ts", diff --git a/binding/nodejs/src/eagle.ts b/binding/nodejs/src/eagle.ts index c5055c18..bdad4e4c 100644 --- a/binding/nodejs/src/eagle.ts +++ b/binding/nodejs/src/eagle.ts @@ -1,5 +1,5 @@ // -// Copyright 2024-2025 Picovoice Inc. +// Copyright 2024-2026 Picovoice Inc. // // You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE" // file accompanying this source. @@ -24,6 +24,7 @@ import { import { EagleInputOptions, EagleOptions, + EagleProfilerOptions, EnrollProgress } from './types'; @@ -62,7 +63,6 @@ export class EagleProfiler { private readonly _version: string; private readonly _sampleRate: number; private readonly _frameLength: number; - private readonly _minEnrollSamples: number; /** * Creates an instance of Eagle Profiler. @@ -75,9 +75,15 @@ export class EagleProfiler { * `${GPU_INDEX}` is the index of the target GPU. If set to `cpu`, the engine will run on the CPU with the * default number of threads. To specify the number of threads, set this argument to `cpu:${NUM_THREADS}`, * where `${NUM_THREADS}` is the desired number of threads. + * @param {number} options.minEnrollmentChunks Minimum number of chunks to be processed before enroll returns 100%. + * The value should be a number greater than or equal to 1. A higher number results in more accurate profiles at the + * cost of needing more data to create the profile. + * @param {number} options.voiceThreshold Sensitivity threshold for detecting voice. The value should be a number + * within [0, 1]. A higher threshold increases detection confidence values at the cost of potentially missing frames + * of voice. * @param {string} options.libraryPath Path to the Eagle library (.node extension) */ - constructor(accessKey: string, options: EagleOptions = {}) { + constructor(accessKey: string, options: EagleProfilerOptions = {}) { assert(typeof accessKey === 'string'); if ( accessKey === null || @@ -90,6 +96,8 @@ export class EagleProfiler { const { modelPath = path.resolve(__dirname, DEFAULT_MODEL_PATH), device = 'best', + minEnrollmentChunks = 1, + voiceThreshold = 0.3, libraryPath = getSystemLibraryPath(), } = options; @@ -115,7 +123,9 @@ export class EagleProfiler { eagleProfilerAndStatus = pvEagle.profiler_init( accessKey, modelPath, - device); + device, + minEnrollmentChunks, + voiceThreshold); } catch (err: any) { pvStatusToException(PvStatus[err.code as keyof typeof PvStatus], err); } @@ -128,8 +138,7 @@ export class EagleProfiler { this._profiler = eagleProfilerAndStatus!.profiler; this._version = pvEagle.version(); this._sampleRate = pvEagle.sample_rate(); - this._frameLength = pvEagle.frame_length(); - this._minEnrollSamples = pvEagle.profiler_enroll_min_audio_length_samples(this._profiler).num_samples; + this._frameLength = pvEagle.profiler_frame_length(); } /** @@ -149,20 +158,12 @@ export class EagleProfiler { /** * @returns number of audio samples per frame (i.e. the length of the array provided to the enroll function) - * @see {@link process} + * @see {@link enroll} */ get frameLength(): number { return this._frameLength; } - /** - * @returns the minimum number of samples required by the enroll function - * @see {@link enroll} - */ - get minEnrollSamples(): number { - return this._minEnrollSamples; - } - /** * Enrolls a speaker. This function should be called multiple times with different utterances of the same speaker * until `percentage` reaches `100.0`, at which point a speaker voice profile can be exported using `.export()`. @@ -175,19 +176,9 @@ export class EagleProfiler { * - it should be captured in a quiet environment with no background noise * @param {Int16Array} pcm Audio data for enrollment. The audio needs to have a sample rate equal to `.sampleRate` and be * 16-bit linearly-encoded. EagleProfiler operates on single-channel audio. - * @return {EnrollProgress} The percentage of completeness of the speaker enrollment process along with the feedback code - * corresponding to the last enrollment attempt: - * - `NONE`: The audio is good for enrollment. - * - `AUDIO_TOO_SHORT`: Audio length is insufficient for enrollment, - * i.e. it is shorter than`.min_enroll_samples`. - * - `UNKNOWN_SPEAKER`: There is another speaker in the audio that is different from the speaker - * being enrolled. Too much background noise may cause this error as well. - * - `NO_VOICE_FOUND`: The audio does not contain any voice, i.e. it is silent or - * has a low signal-to-noise ratio. - * - `QUALITY_ISSUE`: The audio quality is too low for enrollment due to a bad microphone - * or recording environment. + * @return {number} The percentage of enrollment completed. */ - enroll(pcm: Int16Array): EnrollProgress { + enroll(pcm: Int16Array): number { assert(pcm instanceof Int16Array); if ( @@ -202,9 +193,9 @@ export class EagleProfiler { throw new EagleInvalidArgumentError( `PCM array provided to 'Eagle.enroll()' is undefined or null` ); - } else if (pcm.length < this._minEnrollSamples) { + } else if (pcm.length !== this.frameLength) { throw new EagleInvalidArgumentError( - `PCM size (${pcm.length}) must be greater than 'Eagle.minEnrollSamples' (${this.minEnrollSamples})` + `PCM size (${pcm.length}) must be equal to 'EagleProfiler.frameLength' (${this.frameLength})` ); } @@ -220,10 +211,36 @@ export class EagleProfiler { this.handlePvStatus(status, 'Eagle Profiler failed to process the audio frame'); } - return { - percentage: enrollStatus!.percentage, - feedback: enrollStatus!.feedback, - }; + return enrollStatus!.percentage; + } + + /** + * Marks the end of the audio stream, flushes internal state of the object, and returns the percentage of enrollment + * completed. + * @return {number} The percentage of enrollment completed. + */ + flush(): number { + if ( + this._profiler === 0 || + this._profiler === null || + this._profiler === undefined + ) { + throw new EagleInvalidStateError('Eagle Profiler is not initialized'); + } + + let enrollStatus: EnrollStatus | null = null; + try { + enrollStatus = this._pvEagle.profiler_flush(this._profiler); + } catch (err: any) { + pvStatusToException(PvStatus[err.code as keyof typeof PvStatus], err); + } + + const status = enrollStatus!.status; + if (status !== PvStatus.SUCCESS) { + this.handlePvStatus(status, 'Eagle Profiler failed to process the audio frame'); + } + + return enrollStatus!.percentage; } /** @@ -314,14 +331,11 @@ export class Eagle { private readonly _version: string; private readonly _sampleRate: number; - private readonly _frameLength: number; - - private readonly _numSpeakers: number; + private readonly _minProcessSamples: number; /** * Creates an instance of Eagle. * @param {string} accessKey AccessKey obtained from Picovoice Console (https://console.picovoice.ai/). - * @param speakerProfiles One or more Eagle speaker profiles. These can be constructed using `EagleProfiler`. * @param options Optional configuration arguments. * @param {string} options.modelPath The path to the Eagle model (.pv extension) * @param {string} options.device String representation of the device (e.g., CPU or GPU) to use for inference. @@ -330,11 +344,13 @@ export class Eagle { * `${GPU_INDEX}` is the index of the target GPU. If set to `cpu`, the engine will run on the CPU with the * default number of threads. To specify the number of threads, set this argument to `cpu:${NUM_THREADS}`, * where `${NUM_THREADS}` is the desired number of threads. + * @param {number} options.voiceThreshold Sensitivity threshold for detecting voice. The value should be a number + * within [0, 1]. A higher threshold increases detection confidence values at the cost of potentially missing frames + * of voice. * @param {string} options.libraryPath The path to the Eagle library (.node extension) */ constructor( accessKey: string, - speakerProfiles: Uint8Array[] | Uint8Array, options: EagleOptions = {}) { assert(typeof accessKey === 'string'); if ( @@ -348,6 +364,7 @@ export class Eagle { const { modelPath = path.resolve(__dirname, DEFAULT_MODEL_PATH), device = 'best', + voiceThreshold = 0.3, libraryPath = getSystemLibraryPath(), } = options; @@ -367,7 +384,6 @@ export class Eagle { this._pvEagle = pvEagle; let eagleHandleAndStatus: EagleHandleAndStatus | null = null; - const numSpeakers = !Array.isArray(speakerProfiles) ? 1 : speakerProfiles.length; try { pvEagle.set_sdk('nodejs'); @@ -375,8 +391,7 @@ export class Eagle { accessKey, modelPath, device, - numSpeakers, - !Array.isArray(speakerProfiles) ? [speakerProfiles] : speakerProfiles + voiceThreshold ); } catch (err: any) { pvStatusToException(PvStatus[err.code as keyof typeof PvStatus], err); @@ -390,8 +405,7 @@ export class Eagle { this._handle = eagleHandleAndStatus!.handle; this._version = pvEagle.version(); this._sampleRate = pvEagle.sample_rate(); - this._frameLength = pvEagle.frame_length(); - this._numSpeakers = numSpeakers; + this._minProcessSamples = pvEagle.process_min_audio_length_samples(this._handle).num_samples; } /** @@ -410,24 +424,26 @@ export class Eagle { } /** - * @returns number of audio samples per frame (i.e. the length of the array provided to the process function) + * @returns the minimum number of samples required by the process function * @see {@link process} */ - get frameLength(): number { - return this._frameLength; + get minProcessSamples(): number { + return this._minProcessSamples; } /** - * Processes a frame of audio and returns a list of similarity scores for each speaker profile. + * Processes a chunk of audio and returns a list of similarity scores for each speaker profile or null. * - * @param {Int16Array} pcm A frame of audio samples. The number of samples per frame can be attained by calling - * `.frameLength`. The incoming audio needs to have a sample rate equal to `.sampleRate` and be 16-bit + * @param {Int16Array} pcm An array of audio samples. The minimum number of samples can be attained by calling + * `.minProcessSamples`. The incoming audio needs to have a sample rate equal to `.sampleRate` and be 16-bit * linearly-encoded. Eagle operates on single-channel audio. + * @param speakerProfiles One or more Eagle speaker profiles. These can be constructed using `EagleProfiler`. * - * @return {number[]} A list of similarity scores for each speaker profile. A higher score indicates that the voice - * belongs to the corresponding speaker. The range is [0, 1] with 1.0 representing a perfect match. + * @return {number[] | null} A list of similarity scores for each speaker profile. A higher score indicates that the + * voice belongs to the corresponding speaker. The range is [0, 1] with 1.0 representing a perfect match. A result of + * null indicated that there was not enough voice in the audio to detect a speaker. */ - process(pcm: Int16Array): number[] { + process(pcm: Int16Array, speakerProfiles: Uint8Array[] | Uint8Array): number[] { assert(pcm instanceof Int16Array); if ( @@ -442,15 +458,18 @@ export class Eagle { throw new EagleInvalidArgumentError( `PCM array provided to 'Eagle.process()' is undefined or null` ); - } else if (pcm.length !== this.frameLength) { + } else if (pcm.length < this.minProcessSamples) { throw new EagleInvalidArgumentError( - `Size of frame array provided to 'Eagle.process()' (${pcm.length}) does not match the engine 'Eagle.frameLength' (${this.frameLength})` + `PCM size (${pcm.length}) must be greater than 'Eagle.minProcessSamples' (${this.minProcessSamples})` ); } let processStatus: ProcessStatus | null = null; try { - processStatus = this._pvEagle.process(this._handle, pcm, this._numSpeakers); + processStatus = this._pvEagle.process( + this._handle, + pcm, + !Array.isArray(speakerProfiles) ? [speakerProfiles] : speakerProfiles); } catch (err: any) { pvStatusToException(PvStatus[err.code as keyof typeof PvStatus], err); } @@ -463,32 +482,6 @@ export class Eagle { return processStatus!.scores; } - /** - * Resets the internal state of the engine. - * It is best to call before processing a new sequence of audio (e.g. a new voice interaction). - * This ensures that the accuracy of the engine is not affected by a change in audio context. - */ - reset(): void { - if ( - this._handle === 0 || - this._handle === null || - this._handle === undefined - ) { - throw new EagleInvalidStateError('Eagle is not initialized'); - } - - let status: number | null = null; - try { - status = this._pvEagle.reset(this._handle); - } catch (err: any) { - pvStatusToException(err.code, err); - } - - if (status && status !== PvStatus.SUCCESS) { - this.handlePvStatus(status, "Eagle failed to reset"); - } - } - /** * Releases the resources acquired by Eagle. * diff --git a/binding/nodejs/src/index.ts b/binding/nodejs/src/index.ts index 7de6cba6..8cd0e6c1 100644 --- a/binding/nodejs/src/index.ts +++ b/binding/nodejs/src/index.ts @@ -1,5 +1,5 @@ // -// Copyright 2024-2025 Picovoice Inc. +// Copyright 2024-2026 Picovoice Inc. // // You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE" // file accompanying this source. @@ -17,7 +17,6 @@ import { getInt16Frames, checkWaveFile } from './wave_util'; import { EagleInputOptions, EagleOptions, - EagleProfilerEnrollFeedback, EnrollProgress } from './types'; @@ -28,7 +27,6 @@ export { Eagle, EagleInputOptions, EagleOptions, - EagleProfilerEnrollFeedback, EnrollProgress, EagleErrors, checkWaveFile, diff --git a/binding/nodejs/src/types.ts b/binding/nodejs/src/types.ts index 70ba9d78..cab746af 100644 --- a/binding/nodejs/src/types.ts +++ b/binding/nodejs/src/types.ts @@ -1,5 +1,5 @@ /* - Copyright 2024-2025 Picovoice Inc. + Copyright 2024-2026 Picovoice Inc. You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE" file accompanying this source. Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on @@ -7,22 +7,21 @@ specific language governing permissions and limitations under the License. */ -export enum EagleProfilerEnrollFeedback { - NONE = "NONE", - AUDIO_TOO_SHORT = "AUDIO_TOO_SHORT", - UNKNOWN_SPEAKER = "UNKNOWN_SPEAKER", - NO_VOICE_FOUND = "NO_VOICE_FOUND", - QUALITY_ISSUE = "QUALITY_ISSUE", -} - export type EnrollProgress = { percentage: number; - feedback: EagleProfilerEnrollFeedback; }; export type EagleInitOptions = { modelPath?: string; device?: string; + voiceThreshold?: number; +}; + +export type EagleProfilerInitOptions = { + modelPath?: string; + device?: string; + minEnrollmentChunks?: number; + voiceThreshold?: number; }; export type EagleInputOptions = { @@ -30,3 +29,4 @@ export type EagleInputOptions = { }; export type EagleOptions = EagleInitOptions & EagleInputOptions; +export type EagleProfilerOptions = EagleProfilerInitOptions & EagleInputOptions; diff --git a/binding/nodejs/test/index.test.ts b/binding/nodejs/test/index.test.ts index 472c847a..12b31a65 100644 --- a/binding/nodejs/test/index.test.ts +++ b/binding/nodejs/test/index.test.ts @@ -34,38 +34,26 @@ const DEVICE = process.argv const getProfile = ( profiler: EagleProfiler, - audioChunks: Int16Array[], - expectedFeedback: string[] + audioChunks: Int16Array[] ): Uint8Array => { let percentage = 0; for (let i = 0; i < audioChunks.length; i++) { - const result = profiler.enroll(audioChunks[i]); - expect(result.feedback).toEqual(expectedFeedback[i]); - expect(result.percentage).toBeGreaterThan(0); - percentage = result.percentage; + for ( + let j = 0; + j < audioChunks[i].length - profiler.frameLength; + j += profiler.frameLength + ) { + percentage = profiler.enroll(audioChunks[i].slice(j, j + profiler.frameLength)); + expect(percentage).toBeGreaterThanOrEqual(0); + } + + percentage = profiler.flush(); + expect(percentage).toBeGreaterThan(0); } expect(percentage).toEqual(100); return profiler.export(); }; -const getScores = ( - eagle: Eagle, - pcm: Int16Array -): number[] => { - const allScores = []; - for ( - let i = 0; - i < pcm.length - eagle.frameLength; - i += eagle.frameLength - ) { - const score = eagle.process( - pcm.slice(i, i + eagle.frameLength) - ); - allScores.push(score[0]); - } - return allScores; -}; - let testProfile: Uint8Array; beforeAll(() => { @@ -76,8 +64,7 @@ beforeAll(() => { const inputPcm2 = loadPcm(WAV_PATH_SPEAKER_1_UTT_2); testProfile = getProfile( profiler, - [inputPcm1, inputPcm2], - ["NONE", "NONE"]); + [inputPcm1, inputPcm2]); profiler.release(); }); @@ -90,53 +77,49 @@ describe('successful processes', () => { expect(profiler.frameLength).toBeGreaterThan(0); expect(typeof profiler.version).toEqual('string'); expect(profiler.version.length).toBeGreaterThan(0); - expect(profiler.minEnrollSamples).toBeGreaterThan(0); const inputPcm1 = loadPcm(WAV_PATH_SPEAKER_1_UTT_1); const inputPcm2 = loadPcm(WAV_PATH_SPEAKER_1_UTT_2); const profile = getProfile( profiler, - [inputPcm1, inputPcm2], - ["NONE", "NONE"]); + [inputPcm1, inputPcm2]); expect(profile.byteLength).toBeGreaterThan(0); profiler.reset(); const profile2 = getProfile( profiler, - [inputPcm1, inputPcm2], - ["NONE", "NONE"]); + [inputPcm1, inputPcm2]); expect(profile2.byteLength).toEqual(profile.byteLength); profiler.release(); }); }); describe('Eagle', () => { - test('eagle process with reset', () => { - const eagle = new Eagle(ACCESS_KEY, testProfile, { + test('eagle process', () => { + const eagle = new Eagle(ACCESS_KEY, { device: DEVICE }); expect(eagle.sampleRate).toBeGreaterThan(0); - expect(eagle.frameLength).toBeGreaterThan(0); + expect(eagle.minProcessSamples).toBeGreaterThan(0); expect(typeof eagle.version).toEqual('string'); expect(eagle.version.length).toBeGreaterThan(0); const testPcm = loadPcm(WAV_PATH_SPEAKER_1_TEST_UTT); - const scores = getScores(eagle, testPcm); - expect(Math.max(...scores)).toBeGreaterThan(0.5); - eagle.reset(); + const scores = eagle.process(testPcm, testProfile); + expect(scores[0]).toBeGreaterThan(0.5); - const scores2 = getScores(eagle, testPcm); + const scores2 = eagle.process(testPcm, [testProfile]); expect(scores).toEqual(scores2); eagle.release(); }); test('eagle process imposter', () => { - const eagle = new Eagle(ACCESS_KEY, testProfile, { + const eagle = new Eagle(ACCESS_KEY, { device: DEVICE }); const imposterPcm = loadPcm(WAV_PATH_SPEAKER_2_TEST_UTT); - const imposterScores = getScores(eagle, imposterPcm); + const imposterScores = eagle.process(imposterPcm, testProfile); expect(Math.max(...imposterScores)).toBeLessThan(0.5); eagle.release(); }); @@ -153,7 +136,7 @@ describe('Defaults', () => { new EagleProfiler(''); }).toThrow(EagleErrors.EagleInvalidArgumentError); expect(() => { - new Eagle('', testProfile); + new Eagle(''); }).toThrow(EagleErrors.EagleInvalidArgumentError); }); test('Invalid device', () => { @@ -161,7 +144,7 @@ describe('Defaults', () => { new EagleProfiler(ACCESS_KEY, { device: "cloud:9" }); }).toThrow(EagleErrors.EagleInvalidArgumentError); expect(() => { - new Eagle(ACCESS_KEY, testProfile, { device: "cloud:9" }); + new Eagle(ACCESS_KEY, { device: "cloud:9" }); }).toThrow(EagleErrors.EagleInvalidArgumentError); }); }); @@ -181,13 +164,11 @@ describe('manual paths', () => { const inputPcm2 = loadPcm(WAV_PATH_SPEAKER_1_UTT_2); const profile = getProfile( profiler, - [inputPcm1, inputPcm2], - ["NONE", "NONE"] + [inputPcm1, inputPcm2] ); const eagle = new Eagle( ACCESS_KEY, - profile, { modelPath: MODEL_PATH, device: DEVICE, @@ -196,8 +177,8 @@ describe('manual paths', () => { ); const testPcm = loadPcm(WAV_PATH_SPEAKER_1_TEST_UTT); - const scores = getScores(eagle, testPcm); - expect(Math.max(...scores)).toBeGreaterThan(0.5); + const scores = eagle.process(testPcm, profile); + expect(scores[0]).toBeGreaterThan(0.5); profiler.release(); eagle.release(); }); @@ -227,7 +208,7 @@ describe('error message stack', () => { test('message stack cleared after read', () => { let error: string[] = []; try { - new Eagle('invalid', testProfile); + new Eagle('invalid'); } catch (e: any) { error = e.messageStack; } @@ -236,7 +217,7 @@ describe('error message stack', () => { expect(error.length).toBeLessThanOrEqual(8); try { - new Eagle('invalid', testProfile); + new Eagle('invalid'); } catch (e: any) { for (let i = 0; i < error.length; i++) { expect(error[i]).toEqual(e.messageStack[i]); @@ -250,7 +231,7 @@ describe('error message stack', () => { let profiler = new EagleProfiler(ACCESS_KEY, { device: DEVICE }); - const testPcm = new Int16Array(profiler.minEnrollSamples); + const testPcm = new Int16Array(profiler.frameLength); const profilerBytes = profiler; // @ts-ignore profiler._profiler = 0; @@ -278,16 +259,16 @@ describe('error message stack', () => { test('process error message', () => { let error: string[] = []; - let eagle = new Eagle(ACCESS_KEY, testProfile, { + let eagle = new Eagle(ACCESS_KEY, { device: DEVICE }); - const testPcm = new Int16Array(eagle.frameLength); + const testPcm = new Int16Array(eagle.minProcessSamples); const eagleBytes = eagle; // @ts-ignore eagle._handle = 0; try { - eagle!.process(testPcm); + eagle!.process(testPcm, testProfile); } catch (e: any) { error = e.message; } diff --git a/binding/nodejs/test/perf.test.ts b/binding/nodejs/test/perf.test.ts index 40fda098..5f57be2d 100644 --- a/binding/nodejs/test/perf.test.ts +++ b/binding/nodejs/test/perf.test.ts @@ -51,10 +51,16 @@ describe('Performance', () => { const enrollPcm = loadPcm(WAV_PATH_SPEAKER_1_TEST_UTT); for (let i = 0; i < NUM_TEST_ITERATIONS + 1; i++) { - let start = Date.now(); - profiler.enroll(enrollPcm); - if (i > 0) { - enrollPerfResults.push((Date.now() - start) / 1000); + for ( + let j = 0; + j < enrollPcm.length - profiler.frameLength + 1; + j += profiler.frameLength + ) { + let start = Date.now(); + profiler.enroll(enrollPcm.slice(j, j + profiler.frameLength)); + if (i > 0) { + enrollPerfResults.push((Date.now() - start) / 1000); + } } } @@ -76,29 +82,30 @@ describe('Performance', () => { const enrollPcm1 = loadPcm(WAV_PATH_SPEAKER_1_UTT_1); const enrollPcm2 = loadPcm(WAV_PATH_SPEAKER_1_UTT_2); for (const pcm of [enrollPcm1, enrollPcm2]) { - profiler.enroll(pcm); + for ( + let j = 0; + j < pcm.length - profiler.frameLength + 1; + j += profiler.frameLength + ) { + profiler.enroll(pcm.slice(j, j + profiler.frameLength)); + } + profiler.flush(); } const profile = profiler.export(); profiler.release(); - const eagle = new Eagle(ACCESS_KEY, profile, { + const eagle = new Eagle(ACCESS_KEY, { device: DEVICE }); const testPcm = loadPcm(WAV_PATH_SPEAKER_1_TEST_UTT); const processPerfResults: number[] = []; for (let i = 0; i < NUM_TEST_ITERATIONS + 1; i++) { - for ( - let j = 0; - j < testPcm.length - eagle.frameLength + 1; - j += eagle.frameLength - ) { - let start = Date.now(); - eagle.process(testPcm.slice(j, j + eagle.frameLength)); - if (i > 0) { - processPerfResults.push((Date.now() - start) / 1000); - } + let start = Date.now(); + eagle.process(testPcm, profile); + if (i > 0) { + processPerfResults.push((Date.now() - start) / 1000); } } diff --git a/binding/python/README.md b/binding/python/README.md index 347818b4..354780af 100644 --- a/binding/python/README.md +++ b/binding/python/README.md @@ -35,8 +35,8 @@ Signup or Login to [Picovoice Console](https://console.picovoice.ai/) to get you Eagle has two distinct steps: Enrollment and Recognition. In the enrollment step, Eagle analyzes a series of utterances from a particular speaker to learn their unique voiceprint. This step produces an `EagleProfile` object, -which can be stored and utilized during inference. During the Recognition step, Eagle compares the incoming frames of -audio to the voiceprints of all enrolled speakers in real-time to determine the similarity between them. +which can be stored and utilized during inference. During the Recognition step, Eagle compares the incoming audio to the +voiceprints of all enrolled speakers in real-time to determine the similarity between them. ### Speaker Enrollment @@ -53,26 +53,27 @@ eagle_profiler = pveagle.create_profiler(access_key) `EagleProfiler` is responsible for processing and enrolling PCM audio data, with the valid audio sample rate determined by `eagle_profiler.sample_rate`. The audio data must be 16-bit linearly-encoded and single-channel. -When passing samples to `eagle_profiler.enroll`, the number of samples must be at -least `eagle_profiler.min_enroll_samples` to ensure sufficient data for enrollment. The percentage value -obtained from this process indicates the progress of enrollment, while the feedback value can be utilized to determine -the status of the enrollment process. +When passing samples to `eagle_profiler.enroll`, the number of samples must be equal to `eagle_profiler.frame_length`. +The percentage value obtained from this process indicates the progress of enrollment. ```python -def get_next_enroll_audio_data(num_samples): +def get_next_enroll_audio_frame(frame_length): + pass + +def has_next_enroll_audio_frame(frame_length): pass percentage = 0.0 -while percentage < 100.0: - percentage, feedback = eagle_profiler.enroll(get_next_enroll_audio_data(eagle_profiler.min_enroll_samples)) - print(feedback.name) +while percentage < 100.0 and has_next_enroll_audio_frame(eagle_profiler.frame_length): + percentage = eagle_profiler.enroll(get_next_enroll_audio_frame(eagle_profiler.frame_length)) +percentage = eagle_profiler.flush() ``` After the percentage reaches 100%, the enrollment process is considered complete. While it is possible to continue providing additional audio data to the profiler to improve the accuracy of the voiceprint, it is not necessary to do so. -Moreover, if the audio data submitted is unsuitable for enrollment, the feedback value will indicate the reason, and the -enrollment progress will remain unchanged. +Once all the audio from a single source has been submitted it is necessary to call `flush` before submitting any audio +from another source. ```python speaker_profile = eagle_profiler.export() @@ -93,30 +94,33 @@ eagle_profiler.delete() ### Speaker Recognition -Create an instance of the engine with one or more speaker profiles from the `EagleProfiler`: +Create an instance of the engine: ```python -eagle = pveagle.create_recognizer(access_key, speaker_profile) +eagle = pveagle.create_recognizer(access_key) ``` -When initialized, `eagle.sample_rate` specifies the valid sample rate for Eagle. The expected length of a frame, or the -number of audio samples in an input array, is defined by `eagle.frame_length`. +When initialized, `eagle.sample_rate` specifies the valid sample rate for Eagle. The minimum number of audio samples in +an input array, is defined by `eagle.min_process_samples`. Like the profiler, Eagle is designed to work with single-channel audio that is encoded using 16-bit linear PCM. +Process audio with one or more speaker profiles from the `EagleProfiler`. + ```python -def get_next_audio_frame(): +def get_next_audio_chunk(num_samples): pass while True: - scores = eagle.process(get_next_audio_frame()) + scores = eagle.process(get_next_audio_chunk(eagle.min_process_samples), speaker_profiles) ``` -The `scores` array contains floating-point numbers that indicate the similarity between the input audio frame and the -enrolled speakers. Each value in the array corresponds to a specific enrolled speaker, maintaining the same order as the -speaker profiles provided during initialization. The values in the array range from 0.0 to 1.0, where higher values -indicate a stronger degree of similarity. +The `scores` will be None or be an array that contains floating-point numbers that indicate the similarity between the +input audio frame and the enrolled speakers. Each value in the array corresponds to a specific enrolled speaker, +maintaining the same order as the speaker profiles provided during initialization. The values in the array range from +0.0 to 1.0, where higher values indicate a stronger degree of similarity. A result of None indicates that there was not +enough voice in the audio to recognize any speakers. Finally, when done be sure to explicitly release the resources: diff --git a/binding/python/_eagle.py b/binding/python/_eagle.py index 9dd51225..fbbf30d7 100644 --- a/binding/python/_eagle.py +++ b/binding/python/_eagle.py @@ -1,5 +1,5 @@ # -# Copyright 2023-2025 Picovoice Inc. +# Copyright 2023-2026 Picovoice Inc. # # You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE" # file accompanying this source. @@ -10,11 +10,24 @@ # import os -from ctypes import * +from ctypes import ( + POINTER, + Structure, + byref, + c_byte, + c_char_p, + c_float, + c_int, + c_int16, + c_int32, + c_void_p, + cast, + cdll +) from enum import Enum from typing import ( - Sequence, - Tuple + Optional, + Sequence ) @@ -161,22 +174,9 @@ def from_bytes(cls, profile: bytes) -> "EagleProfile": @staticmethod def _to_bytes(ptr: c_void_p, size: int) -> bytes: - # noinspection PyTypeChecker return bytes(cast(ptr, POINTER(c_byte * size)).contents) -class EagleProfilerEnrollFeedback(Enum): - """ - Enumeration of possible enrollment feedback codes. - """ - - AUDIO_OK = 0 - AUDIO_TOO_SHORT = 1 - UNKNOWN_SPEAKER = 2 - NO_VOICE_FOUND = 3 - QUALITY_ISSUE = 4 - - class EagleProfiler(object): """ Python binding for the profiler of the Eagle speaker recognition engine. @@ -191,6 +191,8 @@ def __init__( access_key: str, model_path: str, device: str, + min_enrollment_chunks: int, + voice_threshold: float, library_path: str) -> None: """ Constructor. @@ -203,6 +205,11 @@ def __init__( of the target GPU. If set to`cpu`, the engine will run on the CPU with the default number of threads. To specify the number of threads, set this argument to `cpu:${NUM_THREADS}`, where `${NUM_THREADS}` is the desired number of threads. + :param min_enrollment_chunks: Minimum number of chunks to be processed before enroll returns 100%. The value + should be a number greater than or equal to 1. A higher number results in more accurate profiles at the cost of + needing more data to create the profile. + :param voice_threshold: Sensitivity threshold for detecting voice. The value should be a number within [0, 1]. A + higher threshold increases detection confidence values at the cost of potentially missing frames of voice. :param library_path: Absolute path to Eagle's dynamic library. """ @@ -215,6 +222,12 @@ def __init__( if not isinstance(device, str) or len(device) == 0: raise EagleInvalidArgumentError("`device` should be a non-empty string.") + if min_enrollment_chunks < 1: + raise EagleInvalidArgumentError("`min_enrollment_chunks` should be at least 1") + + if voice_threshold < 0.0 or voice_threshold > 1.0: + raise EagleInvalidArgumentError("`voice_threshold` should be between 0 and 1") + if not os.path.exists(library_path): raise EagleIOError("Could not find Eagle's dynamic library at `%s`." % library_path) @@ -245,6 +258,8 @@ def __init__( c_char_p, c_char_p, c_char_p, + c_int32, + c_float, POINTER(POINTER(self.CEagleProfiler)), ] init_func.restype = PicovoiceStatuses @@ -253,6 +268,8 @@ def __init__( access_key.encode("utf-8"), model_path.encode("utf-8"), device.encode("utf-8"), + min_enrollment_chunks, + voice_threshold, byref(self._eagle_profiler), ) if status is not PicovoiceStatuses.SUCCESS: @@ -277,22 +294,6 @@ def __init__( ) self._profile_size = profile_size.value - enroll_min_audio_length_sample_func = library.pv_eagle_profiler_enroll_min_audio_length_samples - enroll_min_audio_length_sample_func.argtypes = [ - POINTER(self.CEagleProfiler), - POINTER(c_int32), - ] - enroll_min_audio_length_sample_func.restype = PicovoiceStatuses - - min_enroll_samples = c_int32() - status = enroll_min_audio_length_sample_func(self._eagle_profiler, byref(min_enroll_samples)) - if status is not PicovoiceStatuses.SUCCESS: - raise _PICOVOICE_STATUS_TO_EXCEPTION[status]( - message="Failed to get min audio length sample", - message_stack=self._get_error_stack(), - ) - self._min_enroll_samples = min_enroll_samples.value - self._delete_func = library.pv_eagle_profiler_delete self._delete_func.argtypes = [POINTER(self.CEagleProfiler)] self._delete_func.restype = None @@ -301,12 +302,17 @@ def __init__( self._enroll_func.argtypes = [ POINTER(self.CEagleProfiler), POINTER(c_int16), - c_int32, - POINTER(c_int), POINTER(c_float), ] self._enroll_func.restype = PicovoiceStatuses + self._flush_func = library.pv_eagle_profiler_flush + self._flush_func.argtypes = [ + POINTER(self.CEagleProfiler), + POINTER(c_float), + ] + self._flush_func.restype = PicovoiceStatuses + self._reset_func = library.pv_eagle_profiler_reset self._reset_func.argtypes = [POINTER(self.CEagleProfiler)] self._reset_func.restype = PicovoiceStatuses @@ -320,14 +326,14 @@ def __init__( self._sample_rate = library.pv_sample_rate() - self._frame_length = library.pv_eagle_frame_length() + self._frame_length = library.pv_eagle_profiler_frame_length() version_func = library.pv_eagle_version version_func.argtypes = [] version_func.restype = c_char_p self._version = version_func().decode("utf-8") - def enroll(self, pcm: Sequence[int]) -> Tuple[float, EagleProfilerEnrollFeedback]: + def enroll(self, pcm: Sequence[int]) -> float: """ Enrolls a speaker. This function should be called multiple times with different utterances of the same speaker until `percentage` reaches `100.0`. Any further enrollment can be used to improve the speaker voice profile. @@ -340,38 +346,48 @@ def enroll(self, pcm: Sequence[int]) -> Tuple[float, EagleProfilerEnrollFeedback :param pcm: Audio data. The audio needs to have a sample rate equal to `.sample_rate` and be 16-bit linearly-encoded. EagleProfiler operates on single-channel audio. - :return: The percentage of completeness of the speaker enrollment process along with the feedback code - corresponding to the last enrollment attempt: - - `AUDIO_OK`: The audio is good for enrollment. - - `AUDIO_TOO_SHORT`: Audio length is insufficient for enrollment, - i.e. it is shorter than`.min_enroll_samples`. - - `UNKNOWN_SPEAKER`: There is another speaker in the audio that is different from the speaker - being enrolled. Too much background noise may cause this error as well. - - `NO_VOICE_FOUND`: The audio does not contain any voice, i.e. it is silent or - has a low signal-to-noise ratio. - - `QUALITY_ISSUE`: The audio quality is too low for enrollment due to a bad microphone - or recording environment. + :return: The percentage of completeness of the speaker enrollment process. """ - frame_type = c_int16 * len(pcm) + if len(pcm) != self.frame_length: + raise EagleInvalidArgumentError( + "Length of input frame %d does not match required frame length %d" % (len(pcm), self.frame_length) + ) + + frame_type = c_int16 * self._frame_length c_pcm = frame_type(*pcm) - feedback_code = c_int() percentage = c_float() status = self._enroll_func( self._eagle_profiler, c_pcm, - len(c_pcm), - byref(feedback_code), byref(percentage)) - feedback = EagleProfilerEnrollFeedback(feedback_code.value) if status is not PicovoiceStatuses.SUCCESS: raise _PICOVOICE_STATUS_TO_EXCEPTION[status]( message="Enrollment failed", message_stack=self._get_error_stack(), ) - return percentage.value, feedback + return percentage.value + + def flush(self) -> float: + """ + Marks the end of the audio stream, flushes internal state of the object, + and returns the percentage of enrollment completed. + :return: The percentage of completeness of the speaker enrollment process. + """ + + percentage = c_float() + status = self._flush_func( + self._eagle_profiler, + byref(percentage)) + if status is not PicovoiceStatuses.SUCCESS: + raise _PICOVOICE_STATUS_TO_EXCEPTION[status]( + message="Enrollment failed", + message_stack=self._get_error_stack(), + ) + + return percentage.value def export(self) -> EagleProfile: """ @@ -415,12 +431,12 @@ def delete(self) -> None: self._delete_func(self._eagle_profiler) @property - def min_enroll_samples(self) -> int: + def frame_length(self) -> int: """ - The minimum length of the input pcm required by `.enroll()`. + Number of audio samples per frame expected by EagleProfiler (i.e. length of the array passed into `.enroll()`) """ - return self._min_enroll_samples + return self._frame_length @property def sample_rate(self) -> int: @@ -468,8 +484,8 @@ def __init__( access_key: str, model_path: str, device: str, - library_path: str, - speaker_profiles: Sequence[EagleProfile]) -> None: + voice_threshold: float, + library_path: str) -> None: """ Constructor. @@ -481,8 +497,9 @@ def __init__( of the target GPU. If set to`cpu`, the engine will run on the CPU with the default number of threads. To specify the number of threads, set this argument to `cpu:${NUM_THREADS}`, where `${NUM_THREADS}` is the desired number of threads. + :param voice_threshold: Sensitivity threshold for detecting voice. The value should be a number within [0, 1]. A + higher threshold increases detection confidence values at the cost of potentially missing frames of voice. :param library_path: Absolute path to Eagle's dynamic library. - :param speaker_profiles: A list of EagleProfile objects. This can be constructed using `EagleProfiler`. """ if len(access_key) == 0: @@ -494,12 +511,12 @@ def __init__( if not isinstance(device, str) or len(device) == 0: raise EagleInvalidArgumentError("`device` should be a non-empty string.") + if voice_threshold < 0.0 or voice_threshold > 1.0: + raise EagleInvalidArgumentError("`voice_threshold` should be between 0 and 1") + if not os.path.exists(library_path): raise EagleIOError("Could not find Eagle's dynamic library at `%s`." % library_path) - if len(speaker_profiles) == 0: - raise EagleInvalidArgumentError("Eagle requires at least one speaker profile.") - library = cdll.LoadLibrary(library_path) set_sdk_func = library.pv_set_sdk @@ -527,22 +544,16 @@ def __init__( c_char_p, c_char_p, c_char_p, - c_int32, - POINTER(c_void_p), + c_float, POINTER(POINTER(self.CEagle)), ] init_func.restype = PicovoiceStatuses - profile_bytes = (c_void_p * len(speaker_profiles))() - for i, profile in enumerate(speaker_profiles): - profile_bytes[i] = profile.handle - status = init_func( access_key.encode("utf-8"), model_path.encode("utf-8"), device.encode("utf-8"), - len(speaker_profiles), - profile_bytes, + voice_threshold, byref(self._eagle), ) if status is not PicovoiceStatuses.SUCCESS: @@ -555,71 +566,87 @@ def __init__( self._delete_func.argtypes = [POINTER(self.CEagle)] self._delete_func.restype = None + process_min_audio_length_samples_func = library.pv_eagle_process_min_audio_length_samples + process_min_audio_length_samples_func.argtypes = [ + POINTER(self.CEagle), + POINTER(c_int32), + ] + process_min_audio_length_samples_func.restype = PicovoiceStatuses + + min_process_samples = c_int32() + status = process_min_audio_length_samples_func(self._eagle, byref(min_process_samples)) + if status is not PicovoiceStatuses.SUCCESS: + raise _PICOVOICE_STATUS_TO_EXCEPTION[status]( + message="Failed to get min audio length sample", + message_stack=self._get_error_stack(), + ) + self._min_process_samples = min_process_samples.value + self._process_func = library.pv_eagle_process self._process_func.argtypes = [ POINTER(self.CEagle), POINTER(c_int16), - POINTER(c_float), + c_int32, + POINTER(c_void_p), + c_int32, + POINTER(POINTER(c_float)), ] self._process_func.restype = PicovoiceStatuses - self._scores = (c_float * len(speaker_profiles))() - - self._reset_func = library.pv_eagle_reset - self._reset_func.argtypes = [POINTER(self.CEagle)] - self._reset_func.restype = PicovoiceStatuses + self._scores_delete_func = library.pv_eagle_scores_delete + self._scores_delete_func.argtypes = [POINTER(c_float)] self._sample_rate = library.pv_sample_rate() - self._frame_length = library.pv_eagle_frame_length() - version_func = library.pv_eagle_version version_func.argtypes = [] version_func.restype = c_char_p self._version = version_func().decode("utf-8") - def process(self, pcm: Sequence[int]) -> Sequence[float]: + def process(self, pcm: Sequence[int], speaker_profiles: Sequence[EagleProfile]) -> Optional[Sequence[float]]: """ Processes a frame of audio and returns a list of similarity scores for each speaker profile. :param pcm: A frame of audio samples. The number of samples per frame can be attained by calling `.frame_length`. The incoming audio needs to have a sample rate equal to `.sample_rate` and be 16-bit linearly-encoded. Eagle operates on single-channel audio. - :return: A list of similarity scores for each speaker profile. A higher score indicates that the voice - belongs to the corresponding speaker. The range is [0, 1] with 1.0 representing a perfect match. + :param speaker_profiles: A list of EagleProfile objects. This can be constructed using `EagleProfiler`. + :return: A list of similarity scores for each speaker profile or None. A higher score indicates that the voice + belongs to the corresponding speaker. The range is [0, 1] with 1 representing a perfect match. A result of None + indicates that there was not enough voice in the audio to recognize any speakers. """ - if len(pcm) != self.frame_length: - raise EagleInvalidArgumentError( - "Length of input frame %d does not match required frame length %d" % (len(pcm), self.frame_length) - ) + if len(speaker_profiles) == 0: + raise EagleInvalidArgumentError("Eagle requires at least one speaker profile.") - frame_type = c_int16 * self.frame_length + profile_bytes = (c_void_p * len(speaker_profiles))() + for i, profile in enumerate(speaker_profiles): + profile_bytes[i] = profile.handle + + frame_type = c_int16 * len(pcm) pcm = frame_type(*pcm) - status = self._process_func(self._eagle, pcm, self._scores) + scores = POINTER(c_float)() + status = self._process_func( + self._eagle, + pcm, + len(pcm), + profile_bytes, + len(speaker_profiles), + byref(scores)) if status is not PicovoiceStatuses.SUCCESS: raise _PICOVOICE_STATUS_TO_EXCEPTION[status]( message="Process failed", message_stack=self._get_error_stack(), ) - # noinspection PyTypeChecker - return [float(score) for score in self._scores] + if scores is None: + return None - def reset(self) -> None: - """ - Resets the internal state of the Eagle engine. It is best to call before processing a new sequence of audio - (e.g. a new voice interaction). This ensures that the accuracy of the engine is not affected by a change - in audio context. - """ + result = [float(scores[i]) for i in range(len(speaker_profiles))] + self._scores_delete_func(scores) - status = self._reset_func(self._eagle) - if status is not PicovoiceStatuses.SUCCESS: - raise _PICOVOICE_STATUS_TO_EXCEPTION[status]( - message="Reset failed", - message_stack=self._get_error_stack(), - ) + return result def delete(self) -> None: """ @@ -629,20 +656,20 @@ def delete(self) -> None: self._delete_func(self._eagle) @property - def sample_rate(self) -> int: + def min_process_samples(self) -> int: """ - Audio sample rate accepted by Eagle. + The minimum length of the input pcm required by `.process()`. """ - return self._sample_rate + return self._min_process_samples @property - def frame_length(self) -> int: + def sample_rate(self) -> int: """ - Number of audio samples per frame expected by Eagle (i.e. length of the array passed into `.process()`) + Audio sample rate accepted by Eagle. """ - return self._frame_length + return self._sample_rate @property def version(self) -> str: @@ -700,7 +727,6 @@ def list_hardware_devices(library_path: str) -> Sequence[str]: "Eagle", "EagleProfile", "EagleProfiler", - "EagleProfilerEnrollFeedback", "EagleActivationError", "EagleActivationLimitError", "EagleActivationRefusedError", diff --git a/binding/python/_factory.py b/binding/python/_factory.py index 586288e0..7dbafc9f 100644 --- a/binding/python/_factory.py +++ b/binding/python/_factory.py @@ -1,5 +1,5 @@ # -# Copyright 2023-2025 Picovoice Inc. +# Copyright 2023-2026 Picovoice Inc. # # You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE" # file accompanying this source. @@ -11,13 +11,11 @@ from typing import ( Optional, - Sequence, - Union + Sequence ) from ._eagle import ( Eagle, - EagleProfile, EagleProfiler, list_hardware_devices ) @@ -29,9 +27,9 @@ def create_recognizer( access_key: str, - speaker_profiles: Union[Sequence[EagleProfile], EagleProfile], model_path: Optional[str] = None, device: Optional[str] = None, + voice_threshold: float = 0.3, library_path: Optional[str] = None) -> Eagle: """ Factory method for the recognizer component of the Eagle speaker recognition engine. @@ -47,6 +45,8 @@ def create_recognizer( of the target GPU. If set to`cpu`, the engine will run on the CPU with the default number of threads. To specify the number of threads, set this argument to `cpu:${NUM_THREADS}`, where `${NUM_THREADS}` is the desired number of threads. + :param voice_threshold: Sensitivity threshold for detecting voice. The value should be a number within [0, 1]. A + higher threshold increases detection confidence values at the cost of potentially missing frames of voice. :param library_path: Absolute path to Eagle's dynamic library. If not set it will be set to the default location. :return: An instance of Eagle speaker recognition object. @@ -61,14 +61,11 @@ def create_recognizer( if library_path is None: library_path = default_library_path() - if isinstance(speaker_profiles, EagleProfile): - speaker_profiles = [speaker_profiles] - return Eagle( access_key=access_key, - speaker_profiles=speaker_profiles, model_path=model_path, device=device, + voice_threshold=voice_threshold, library_path=library_path) @@ -76,6 +73,8 @@ def create_profiler( access_key: str, model_path: Optional[str] = None, device: Optional[str] = None, + min_enrollment_chunks: int = 1, + voice_threshold: float = 0.3, library_path: Optional[str] = None) -> EagleProfiler: """ Factory method for the profiler component of the Eagle speaker recognition engine. @@ -89,6 +88,11 @@ def create_profiler( of the target GPU. If set to`cpu`, the engine will run on the CPU with the default number of threads. To specify the number of threads, set this argument to `cpu:${NUM_THREADS}`, where `${NUM_THREADS}` is the desired number of threads. + :param min_enrollment_chunks: Minimum number of chunks to be processed before enroll returns 100%. The value should + be a number greater than or equal to 1. A higher number results in more accurate profiles at the cost of needing + more data to create the profile. + :param voice_threshold: Sensitivity threshold for detecting voice. The value should be a number within [0, 1]. A + higher threshold increases detection confidence values at the cost of potentially missing frames of voice. :param library_path: Absolute path to Eagle's dynamic library. If not set it will be set to the default location. :return: An instance of EagleProfiler object. @@ -107,6 +111,8 @@ def create_profiler( access_key=access_key, model_path=model_path, device=device, + min_enrollment_chunks=min_enrollment_chunks, + voice_threshold=voice_threshold, library_path=library_path, ) diff --git a/binding/python/setup.py b/binding/python/setup.py index ac097376..f4a60c6b 100644 --- a/binding/python/setup.py +++ b/binding/python/setup.py @@ -1,5 +1,5 @@ # -# Copyright 2023-2025 Picovoice Inc. +# Copyright 2023-2026 Picovoice Inc. # # You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE" # file accompanying this source. @@ -42,7 +42,7 @@ setuptools.setup( name="pveagle", - version="2.0.1", + version="3.0.0", author="Picovoice", author_email="hello@picovoice.ai", description="Eagle Speaker Recognition Engine", diff --git a/binding/python/test_eagle.py b/binding/python/test_eagle.py index 7f093023..f7b6127e 100644 --- a/binding/python/test_eagle.py +++ b/binding/python/test_eagle.py @@ -1,5 +1,5 @@ # -# Copyright 2023-2025 Picovoice Inc. +# Copyright 2023-2026 Picovoice Inc. # # You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE" # file accompanying this source. @@ -15,13 +15,16 @@ import sys import unittest import wave -from typing import Sequence +from typing import ( + Optional, + Sequence +) from _eagle import ( Eagle, EagleError, + EagleProfile, EagleProfiler, - EagleProfilerEnrollFeedback, list_hardware_devices ) @@ -42,6 +45,7 @@ class EagleTestCase(unittest.TestCase): device: str eagle: Eagle eagle_profiler: EagleProfiler + profile: EagleProfile @staticmethod def load_wav_resource(path: str) -> Sequence[int]: @@ -56,20 +60,26 @@ def setUpClass(cls) -> None: model_path=default_model_path("../.."), device=cls.device, library_path=default_library_path("../.."), + min_enrollment_chunks=1, + voice_threshold=0.3 ) + fl = cls.eagle_profiler.frame_length for path in cls.ENROLL_PATHS: pcm = cls.load_wav_resource(path) - _ = cls.eagle_profiler.enroll(pcm) + for i in range(len(pcm) // fl): + _ = cls.eagle_profiler.enroll(pcm[i * fl:(i + 1) * fl]) + _ = cls.eagle_profiler.flush() - profile = cls.eagle_profiler.export() + cls.profile = cls.eagle_profiler.export() + cls.eagle_profiler.reset() cls.eagle = Eagle( access_key=cls.access_key, model_path=default_model_path("../.."), device=cls.device, library_path=default_library_path("../.."), - speaker_profiles=[profile], + voice_threshold=0.3 ) @classmethod @@ -78,37 +88,30 @@ def tearDownClass(cls) -> None: cls.eagle_profiler.delete() def test_eagle_enrollment(self) -> None: + fl = self.eagle_profiler.frame_length percentage = 0.0 for path in self.ENROLL_PATHS: pcm = self.load_wav_resource(path) - percentage, error = self.eagle_profiler.enroll(pcm) - self.assertEqual(error, EagleProfilerEnrollFeedback.AUDIO_OK) + for i in range(len(pcm) // fl): + _ = self.eagle_profiler.enroll(pcm[i * fl:(i + 1) * fl]) + percentage = self.eagle_profiler.flush() self.assertGreater(percentage, 0) profile = self.eagle_profiler.export() + self.eagle_profiler.reset() self.assertGreater(profile.size, 0) def test_eagle_process(self) -> None: pcm = self.load_wav_resource(self.TEST_PATH) - num_frames = len(pcm) // self.eagle.frame_length - scores = [] - for i in range(num_frames): - score = self.eagle.process(pcm=pcm[i * self.eagle.frame_length: (i + 1) * self.eagle.frame_length]) - scores.append(score[0]) + scores = self.eagle.process(pcm=pcm, speaker_profiles=[self.profile]) - self.assertGreater(max(scores), 0.5) - self.eagle.reset() + self.assertGreater(scores[0], 0.5) def test_eagle_process_imposter(self) -> None: pcm = self.load_wav_resource(self.IMPOSTER_PATH) - num_frames = len(pcm) // self.eagle.frame_length - scores = [] - for i in range(num_frames): - score = self.eagle.process(pcm=pcm[i * self.eagle.frame_length: (i + 1) * self.eagle.frame_length]) - scores.append(score[0]) + scores = self.eagle.process(pcm=pcm, speaker_profiles=[self.profile]) - self.assertLess(max(scores), 0.5) - self.eagle.reset() + self.assertLess(scores[0], 0.5) def test_version(self) -> None: eagle_version = self.eagle.version @@ -120,20 +123,17 @@ def test_version(self) -> None: self.assertGreater(len(eagle_profile_version), 0) def test_frame_length(self) -> None: - self.assertGreater(self.eagle.frame_length, 0) + self.assertGreater(self.eagle_profiler.frame_length, 0) def test_message_stack(self): - relative_path = "../.." - profile = self.eagle_profiler.export() - error = None try: eagle = Eagle( access_key="invalid", - model_path=default_model_path(relative_path), + model_path=default_model_path("../.."), device=self.device, - library_path=default_library_path(relative_path), - speaker_profiles=[profile], + library_path=default_library_path("../.."), + voice_threshold=0.3 ) self.assertIsNone(eagle) except EagleError as e: @@ -145,10 +145,10 @@ def test_message_stack(self): try: eagle = Eagle( access_key="invalid", - model_path=default_model_path(relative_path), + model_path=default_model_path("../.."), device=self.device, - library_path=default_library_path(relative_path), - speaker_profiles=[profile], + library_path=default_library_path("../.."), + voice_threshold=0.3 ) self.assertIsNone(eagle) except EagleError as e: @@ -156,13 +156,13 @@ def test_message_stack(self): self.assertListEqual(list(error), list(e.message_stack)) def test_enroll_export_message_stack(self): - relative_path = "../.." - profiler = EagleProfiler( access_key=self.access_key, - model_path=default_model_path(relative_path), + model_path=default_model_path("../.."), device=self.device, - library_path=default_library_path(relative_path), + library_path=default_library_path("../.."), + min_enrollment_chunks=1, + voice_threshold=0.3 ) test_pcm = [0] * 512 @@ -186,23 +186,20 @@ def test_enroll_export_message_stack(self): profiler._eagle_profiler = address def test_process_message_stack(self): - relative_path = "../.." - profile = self.eagle_profiler.export() - eagle = Eagle( access_key=self.access_key, - model_path=default_model_path(relative_path), + model_path=default_model_path("../.."), device=self.device, - library_path=default_library_path(relative_path), - speaker_profiles=[profile], + library_path=default_library_path("../.."), + voice_threshold=0.3 ) - test_pcm = [0] * eagle.frame_length + test_pcm = [0] * eagle.min_process_samples address = eagle._eagle eagle._eagle = None try: - res = eagle.process(test_pcm) + res = eagle.process(test_pcm, speaker_profiles=[self.profile]) self.assertEqual(len(res), -1) except EagleError as e: self.assertGreater(len(e.message_stack), 0) diff --git a/binding/python/test_eagle_perf.py b/binding/python/test_eagle_perf.py index 104f89f4..1149d417 100644 --- a/binding/python/test_eagle_perf.py +++ b/binding/python/test_eagle_perf.py @@ -1,5 +1,5 @@ # -# Copyright 2023-2025 Picovoice Inc. +# Copyright 2023-2026 Picovoice Inc. # # You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE" # file accompanying this source. @@ -46,15 +46,20 @@ def test_performance_profiler(self) -> None: access_key=self.access_key, model_path=default_model_path("../.."), device=self.device, + min_enrollment_chunks=1, + voice_threshold=0.3, library_path=default_library_path("../.."), ) pcm = self.load_wav_resource(self.TEST_PATH) + num_frames = len(pcm) // eagle_profiler.frame_length perf_results = list() for i in range(self.num_test_iterations + 1): start = perf_counter() - _ = eagle_profiler.enroll(pcm) + num_frames = len(pcm) // eagle_profiler.frame_length + for n in range(num_frames): + _ = eagle_profiler.enroll(pcm[n * eagle_profiler.frame_length: (n + 1) * eagle_profiler.frame_length]) if i > 0: perf_results.append(perf_counter() - start) @@ -70,12 +75,17 @@ def test_performance_recognizer(self) -> None: access_key=self.access_key, model_path=default_model_path("../.."), device=self.device, + min_enrollment_chunks=1, + voice_threshold=0.3, library_path=default_library_path("../.."), ) for path in self.ENROLL_PATHS: pcm = self.load_wav_resource(path) - _ = eagle_profiler.enroll(pcm) + num_frames = len(pcm) // eagle_profiler.frame_length + for n in range(num_frames): + _ = eagle_profiler.enroll(pcm[n * eagle_profiler.frame_length: (n + 1) * eagle_profiler.frame_length]) + _ = eagle_profiler.flush() profile = eagle_profiler.export() @@ -84,19 +94,16 @@ def test_performance_recognizer(self) -> None: model_path=default_model_path("../.."), device=self.device, library_path=default_library_path("../.."), - speaker_profiles=[profile], + voice_threshold=0.3, ) pcm = self.load_wav_resource(self.TEST_PATH) - num_frames = len(pcm) // eagle.frame_length - perf_results = list() for _ in range(self.num_test_iterations + 1): - for n in range(num_frames): - start = perf_counter() - _ = eagle.process(pcm=pcm[n * eagle.frame_length: (n + 1) * eagle.frame_length]) - perf_results.append(perf_counter() - start) + start = perf_counter() + _ = eagle.process(pcm, speaker_profiles=[profile]) + perf_results.append(perf_counter() - start) eagle.delete() diff --git a/binding/web/README.md b/binding/web/README.md index 233d888e..21f80daa 100644 --- a/binding/web/README.md +++ b/binding/web/README.md @@ -93,9 +93,8 @@ const eagleProfiler = await EagleProfilerWorker.create( `EagleProfiler` is responsible for processing and enrolling PCM audio data, with the valid audio sample rate determined by `eagleProfiler.sampleRate`. The audio data must be 16-bit linearly-encoded and single-channel. -When passing samples to `eagleProfiler.enroll`, the number of samples must be at -least `eagleProfiler.minEnrollSamples` to ensure sufficient data for enrollment. The percentage value -returned from this process indicates the progress of enrollment, while the feedback value can be utilized to determine the status of the enrollment process. +When passing samples to `eagleProfiler.enroll`, the number of samples must be equal to `eagleProfiler.frameLength`. The +percentage value returned from this process indicates the progress of enrollment. ```typescript function getAudioData(numSamples): Int16Array { @@ -104,22 +103,14 @@ function getAudioData(numSamples): Int16Array { let percentage = 0; while (percentage < 100) { - const audioData = getAudioData(eagleProfiler.minEnrollSamples); + const audioData = getAudioData(eagleProfiler.frameLength); - const result: EagleProfilerEnrollResult = await eagleProfiler.enroll(audioData); - if (result.feedback === EagleProfilerEnrollFeedback.AUDIO_OK) { - // audio is good! - } else { - // feedback code will tell you why audio was not used in enrollment - } - percentage = result.percentage; + percentage = EagleProfilerEnrollResult = await eagleProfiler.enroll(audioData); } ``` After the percentage reaches 100%, the enrollment process is considered complete. While it is possible to continue providing additional audio data to the profiler to improve the accuracy of the voiceprint, it is not necessary to do so. -Moreover, if the audio data submitted is unsuitable for enrollment, the feedback value will indicate the reason, and the -enrollment progress will remain unchanged. ```typescript const speakerProfile: EagleProfile = eagleProfiler.export(); @@ -141,40 +132,47 @@ eagleProfiler.terminate(); ### Speaker Recognition -Create an instance of the engine with one or more speaker profiles created by the `EagleProfiler`: +Create an instance of the engine: ```typescript // Main thread const eagle = await Eagle.create( ${ACCESS_KEY}, - eagleModel, - speakerProfile); + eagleModel); // or, on a worker thread const eagle = await EagleWorker.create( ${ACCESS_KEY}, - eagleModel, - speakerProfile); + eagleModel); ``` When initialized, `eagle.sampleRate` specifies the valid sample rate for Eagle. The expected length of a frame, or the -number of audio samples in an input array, is defined by `eagle.frameLength`. +minimum number of audio samples in an input array, is defined by `eagle.minProcessSamples`. Like the profiler, Eagle is designed to work with single-channel audio that is encoded using 16-bit linear PCM. +Process the audio data with one or more speaker profiles created by the `EagleProfiler`: + ```typescript function getAudioData(numSamples): Int16Array { // get audio frame of size `numSamples` } while (true) { - const audioData = getAudioData(eagle.frameLength); - const scores: number[] = await eagle.process(audioData); + const audioData = getAudioData(eagle.minProcessSamples); + const scores: number[] | null = await eagle.process( + audioData, + speakerProfile + ); + if (scores) { + // do something with the scores + } } ``` The return value `scores` represents the degree of similarity between the input audio frame and the enrolled speakers. Each value is a floating-point number ranging from 0 to 1, with higher values indicating a greater degree of similarity. +A return value of null indicates that there was not enough voice in the sample to detect a speaker. Finally, when done be sure to explicitly release the resources: diff --git a/binding/web/package.json b/binding/web/package.json index 1cb4bd1e..96cbb324 100644 --- a/binding/web/package.json +++ b/binding/web/package.json @@ -3,7 +3,7 @@ "description": "Eagle Speaker Recognition engine for web browsers (via WebAssembly)", "author": "Picovoice Inc", "license": "Apache-2.0", - "version": "2.0.0", + "version": "3.0.0", "keywords": [ "eagle", "web", diff --git a/binding/web/src/eagle.ts b/binding/web/src/eagle.ts index 5dbae048..5ecabe7d 100644 --- a/binding/web/src/eagle.ts +++ b/binding/web/src/eagle.ts @@ -1,5 +1,5 @@ /* - Copyright 2023-2025 Picovoice Inc. + Copyright 2023-2026 Picovoice Inc. You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE" file accompanying this source. @@ -29,7 +29,6 @@ import { EagleModel, EagleOptions, EagleProfile, - EagleProfilerEnrollResult, EagleProfilerOptions, PvStatus } from './types'; @@ -44,20 +43,21 @@ type pv_eagle_profiler_init_type = ( accessKey: number, modelPath: number, device: number, + min_enrollment_chunks, + voice_threshold: number, object: number ) => Promise; type pv_eagle_profiler_delete_type = (object: number) => Promise; type pv_eagle_profiler_enroll_type = ( object: number, pcm: number, - numSamples: number, - feedback: number, percentage: number ) => Promise; -type pv_eagle_profiler_enroll_min_audio_length_samples_type = ( +type pv_eagle_profiler_flush_type = ( object: number, - numSamples: number -) => number; + percentage: number +) => Promise; +type pv_eagle_profiler_frame_length_type = () => number; type pv_eagle_profiler_export_type = ( object: number, speakerProfile: number @@ -71,18 +71,25 @@ type pv_eagle_init_type = ( accessKey: number, modelPath: number, device: number, - numSpeakers: number, - speakerProfiles: number, + voiceThreshold: number, object: number ) => Promise; type pv_eagle_delete_type = (object: number) => Promise; type pv_eagle_process_type = ( object: number, pcm: number, + pcmLength: number, + speakerProfiles: number, + numSpeakers: number, scores: number ) => Promise; -type pv_eagle_reset_type = (object: number) => Promise; -type pv_eagle_frame_length_type = () => number; +type pv_eagle_scores_delete_type = ( + scores: number +) => Promise; +type pv_eagle_process_min_audio_length_samples_type = ( + object: number, + numSamples: number +) => number; type pv_eagle_version_type = () => number; type pv_eagle_list_hardware_devices_type = ( hardwareDevices: number, @@ -103,10 +110,10 @@ type pv_free_error_stack_type = (messageStack: number) => void; type EagleModule = EmscriptenModule & { _pv_free: (address: number) => void; - _pv_eagle_profiler_enroll_min_audio_length_samples: pv_eagle_profiler_enroll_min_audio_length_samples_type _pv_eagle_profiler_export: pv_eagle_profiler_export_type _pv_eagle_profiler_export_size: pv_eagle_profiler_export_size_type - _pv_eagle_frame_length: pv_eagle_frame_length_type + _pv_eagle_profiler_frame_length: pv_eagle_profiler_frame_length_type + _pv_eagle_process_min_audio_length_samples: pv_eagle_process_min_audio_length_samples_type _pv_eagle_version: pv_eagle_version_type _pv_eagle_list_hardware_devices: pv_eagle_list_hardware_devices_type; _pv_eagle_free_hardware_devices: pv_eagle_free_hardware_devices_type; @@ -133,33 +140,31 @@ type EagleBaseWasmOutput = { }; type EagleProfilerWasmOutput = EagleBaseWasmOutput & { - minEnrollSamples: number; + frameLength: number; profileSize: number; objectAddress: number; - feedbackAddress: number; percentageAddress: number; profileAddress: number; pv_eagle_profiler_enroll: pv_eagle_profiler_enroll_type; + pv_eagle_profiler_flush: pv_eagle_profiler_flush_type; pv_eagle_profiler_reset: pv_eagle_profiler_reset_type; pv_eagle_profiler_delete: pv_eagle_profiler_delete_type; }; type EagleWasmOutput = EagleBaseWasmOutput & { - frameLength: number; - numSpeakers: number; + minProcessSamples: number; objectAddress: number; - scoresAddress: number; + scoresAddressAddress: number; pv_eagle_process: pv_eagle_process_type; - pv_eagle_reset: pv_eagle_reset_type; + pv_eagle_scores_delete: pv_eagle_scores_delete_type; pv_eagle_delete: pv_eagle_delete_type; }; const PV_STATUS_SUCCESS = 10000; -const MAX_PCM_LENGTH_SEC = 60 * 15; class EagleBase { protected _module?: EagleModule; @@ -365,38 +370,36 @@ class EagleBase { */ export class EagleProfiler extends EagleBase { private readonly _pv_eagle_profiler_enroll: pv_eagle_profiler_enroll_type; + private readonly _pv_eagle_profiler_flush: pv_eagle_profiler_flush_type; private readonly _pv_eagle_profiler_reset: pv_eagle_profiler_reset_type; private readonly _pv_eagle_profiler_delete: pv_eagle_profiler_delete_type; private readonly _objectAddress: number; - private readonly _feedbackAddress: number; private readonly _percentageAddress: number; - private readonly _maxEnrollSamples: number; - private readonly _minEnrollSamples: number; + private readonly _frameLength: number; private readonly _profileSize: number; private constructor(handleWasm: EagleProfilerWasmOutput) { super(handleWasm); - this._minEnrollSamples = handleWasm.minEnrollSamples; + this._frameLength = handleWasm.frameLength; this._profileSize = handleWasm.profileSize; - this._maxEnrollSamples = MAX_PCM_LENGTH_SEC * this._sampleRate; this._pv_eagle_profiler_enroll = handleWasm.pv_eagle_profiler_enroll; + this._pv_eagle_profiler_flush = handleWasm.pv_eagle_profiler_flush; this._pv_eagle_profiler_reset = handleWasm.pv_eagle_profiler_reset; this._pv_eagle_profiler_delete = handleWasm.pv_eagle_profiler_delete; this._objectAddress = handleWasm.objectAddress; - this._feedbackAddress = handleWasm.feedbackAddress; this._percentageAddress = handleWasm.percentageAddress; } /** - * The minimum length of the input pcm required by `.enroll()`. + * The length of the input pcm required by `.enroll()`. */ - get minEnrollSamples(): number { - return this._minEnrollSamples; + get frameLength(): number { + return this._frameLength; } /** @@ -416,6 +419,8 @@ export class EagleProfiler extends EagleBase { * GPU device, set this argument to `gpu:${GPU_INDEX}`, where `${GPU_INDEX}` is the index of the target GPU. If set to * `cpu`, the engine will run on the CPU with the default number of threads. To specify the number of threads, set this * argument to `cpu:${NUM_THREADS}`, where `${NUM_THREADS}` is the desired number of threads. + * @param options.minEnrollmentChunks Minimum number of chunks to be processed before enroll returns 100% + * @param options.voiceThreshold Sensitivity threshold for detecting voice. * * @return An instance of the Eagle Profiler. */ @@ -441,7 +446,11 @@ export class EagleProfiler extends EagleBase { throw new EagleErrors.EagleInvalidArgumentError('Invalid AccessKey'); } - let { device = "best" } = options; + let { + device = "best", + minEnrollmentChunks = 1, // eslint-disable-line + voiceThreshold = 0.3, // eslint-disable-line + } = options; const isSimd = await simd(); if (!isSimd) { @@ -470,6 +479,8 @@ export class EagleProfiler extends EagleBase { accessKey.trim(), modelPath.trim(), device, + minEnrollmentChunks, + voiceThreshold, sabDefined ? this._wasmPThread : this._wasmSimd, sabDefined ? this._wasmPThreadLib : this._wasmSimdLib, sabDefined ? createModulePThread : createModuleSimd @@ -498,32 +509,22 @@ export class EagleProfiler extends EagleBase { * @param pcm Audio data for enrollment. The audio needs to have a sample rate equal to `.sampleRate` and be * 16-bit linearly-encoded. EagleProfiler operates on single-channel audio. * - * @return The percentage of completeness of the speaker enrollment process along with the feedback code - * corresponding to the last enrollment attempt: - * - `AUDIO_OK`: The audio is good for enrollment. - * - `AUDIO_TOO_SHORT`: Audio length is insufficient for enrollment, - * i.e. it is shorter than`.min_enroll_samples`. - * - `UNKNOWN_SPEAKER`: There is another speaker in the audio that is different from the speaker - * being enrolled. Too much background noise may cause this error as well. - * - `NO_VOICE_FOUND`: The audio does not contain any voice, i.e. it is silent or - * has a low signal-to-noise ratio. - * - `QUALITY_ISSUE`: The audio quality is too low for enrollment due to a bad microphone - * or recording environment. + * @return The percentage of completeness of the speaker enrollment process. */ - public async enroll(pcm: Int16Array): Promise { + public async enroll(pcm: Int16Array): Promise { if (!(pcm instanceof Int16Array)) { throw new EagleErrors.EagleInvalidArgumentError( "The argument 'pcm' must be provided as an Int16Array" ); } - if (pcm.length > this._maxEnrollSamples) { + if (pcm.length !== this.frameLength) { throw new EagleErrors.EagleInvalidArgumentError( - `'pcm' size must be smaller than ${this._maxEnrollSamples}` + `'pcm' size must be equal to ${this.frameLength}` ); } - return new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { this._functionMutex .runExclusive(async () => { if (this._module === undefined) { @@ -543,8 +544,6 @@ export class EagleProfiler extends EagleBase { const status = await this._pv_eagle_profiler_enroll( this._objectAddress, pcmAddress, - pcm.length, - this._feedbackAddress, this._percentageAddress ); this._module._pv_free(pcmAddress); @@ -566,18 +565,68 @@ export class EagleProfiler extends EagleBase { ); } - const feedback = - this._module.HEAP32[ - this._feedbackAddress / Int32Array.BYTES_PER_ELEMENT + const percentage = + this._module.HEAPF32[ + this._percentageAddress / Float32Array.BYTES_PER_ELEMENT ]; + + return percentage; + }) + .then((result: number) => { + resolve(result); + }) + .catch((error: any) => { + reject(error); + }); + }); + } + + /** + * Marks the end of the audio stream, flushes internal state of the object, and returns the percentage of enrollment + * completed. + * + * @return The percentage of completeness of the speaker enrollment process. + */ + public async flush(): Promise { + return new Promise((resolve, reject) => { + this._functionMutex + .runExclusive(async () => { + if (this._module === undefined) { + throw new EagleErrors.EagleInvalidStateError( + 'Attempted to call `.flush()` after release' + ); + } + + const status = await this._pv_eagle_profiler_flush( + this._objectAddress, + this._percentageAddress + ); + + if (status !== PV_STATUS_SUCCESS) { + const messageStack = await EagleProfiler.getMessageStack( + this._module._pv_get_error_stack, + this._module._pv_free_error_stack, + this._messageStackAddressAddressAddress, + this._messageStackDepthAddress, + this._module.HEAP32, + this._module.HEAPU8 + ); + + throw pvStatusToException( + status, + 'EagleProfiler flush failed', + messageStack + ); + } + const percentage = this._module.HEAPF32[ this._percentageAddress / Float32Array.BYTES_PER_ELEMENT ]; - return { feedback, percentage }; + return percentage; }) - .then((result: EagleProfilerEnrollResult) => { + .then((result: number) => { resolve(result); }) .catch((error: any) => { @@ -706,6 +755,8 @@ export class EagleProfiler extends EagleBase { accessKey: string, modelPath: string, device: string, + minEnrollmentChunks: number, + voiceThreshold: number, wasmBase64: string, wasmLibBase64: string, createModuleFunc: any @@ -720,13 +771,19 @@ export class EagleProfiler extends EagleBase { this.wrapAsyncFunction( baseWasmOutput.module, 'pv_eagle_profiler_init', - 4 + 6 ); const pv_eagle_profiler_enroll: pv_eagle_profiler_enroll_type = this.wrapAsyncFunction( baseWasmOutput.module, 'pv_eagle_profiler_enroll', - 5 + 3 + ); + const pv_eagle_profiler_flush: pv_eagle_profiler_flush_type = + this.wrapAsyncFunction( + baseWasmOutput.module, + 'pv_eagle_profiler_flush', + 2 ); const pv_eagle_profiler_reset: pv_eagle_profiler_reset_type = @@ -797,7 +854,9 @@ export class EagleProfiler extends EagleBase { accessKeyAddress, modelPathAddress, deviceAddress, - objectAddressAddress + minEnrollmentChunks, + voiceThreshold, + objectAddressAddress, ); baseWasmOutput.module._pv_free(accessKeyAddress); baseWasmOutput.module._pv_free(modelPathAddress); @@ -821,20 +880,8 @@ export class EagleProfiler extends EagleBase { ]; baseWasmOutput.module._pv_free(objectAddressAddress); - const minEnrollSamplesAddress = baseWasmOutput.module._malloc( - Int32Array.BYTES_PER_ELEMENT - ); - if (minEnrollSamplesAddress === 0) { - throw new EagleErrors.EagleOutOfMemoryError( - 'malloc failed: Cannot allocate memory' - ); - } - - status = - baseWasmOutput.module._pv_eagle_profiler_enroll_min_audio_length_samples( - objectAddress, - minEnrollSamplesAddress - ); + const frameLength = + baseWasmOutput.module._pv_eagle_profiler_frame_length(); if (status !== PV_STATUS_SUCCESS) { const messageStack = await EagleProfiler.getMessageStack( baseWasmOutput.module._pv_get_error_stack, @@ -852,12 +899,6 @@ export class EagleProfiler extends EagleBase { ); } - const minEnrollSamples = - baseWasmOutput.module.HEAP32[ - minEnrollSamplesAddress / Int32Array.BYTES_PER_ELEMENT - ]; - baseWasmOutput.module._pv_free(minEnrollSamplesAddress); - const profileSizeAddress = baseWasmOutput.module._malloc( Int32Array.BYTES_PER_ELEMENT ); @@ -894,15 +935,6 @@ export class EagleProfiler extends EagleBase { ]; baseWasmOutput.module._pv_free(profileSizeAddress); - const feedbackAddress = baseWasmOutput.module._malloc( - Int32Array.BYTES_PER_ELEMENT - ); - if (feedbackAddress === 0) { - throw new EagleErrors.EagleOutOfMemoryError( - 'malloc failed: Cannot allocate memory' - ); - } - const percentageAddress = baseWasmOutput.module._malloc( Int32Array.BYTES_PER_ELEMENT ); @@ -923,15 +955,15 @@ export class EagleProfiler extends EagleBase { return { ...baseWasmOutput, - minEnrollSamples: minEnrollSamples, + frameLength: frameLength, profileSize: profileSize, objectAddress: objectAddress, - feedbackAddress: feedbackAddress, percentageAddress: percentageAddress, profileAddress: profileAddress, pv_eagle_profiler_enroll: pv_eagle_profiler_enroll, + pv_eagle_profiler_flush: pv_eagle_profiler_flush, pv_eagle_profiler_reset: pv_eagle_profiler_reset, pv_eagle_profiler_delete: pv_eagle_profiler_delete, }; @@ -944,34 +976,32 @@ export class EagleProfiler extends EagleBase { */ export class Eagle extends EagleBase { private readonly _pv_eagle_process: pv_eagle_process_type; - private readonly _pv_eagle_reset: pv_eagle_reset_type; + private readonly _pv_eagle_scores_delete: pv_eagle_scores_delete_type; private readonly _pv_eagle_delete: pv_eagle_delete_type; private readonly _objectAddress: number; - private readonly _scoresAddress: number; + private readonly _scoresAddressAddress: number; - private readonly _frameLength: number; - private readonly _numSpeakers: number; + private readonly _minProcessSamples: number; private constructor(handleWasm: EagleWasmOutput) { super(handleWasm); - this._frameLength = handleWasm.frameLength; - this._numSpeakers = handleWasm.numSpeakers; + this._minProcessSamples = handleWasm.minProcessSamples; this._pv_eagle_process = handleWasm.pv_eagle_process; - this._pv_eagle_reset = handleWasm.pv_eagle_reset; + this._pv_eagle_scores_delete = handleWasm.pv_eagle_scores_delete; this._pv_eagle_delete = handleWasm.pv_eagle_delete; this._objectAddress = handleWasm.objectAddress; - this._scoresAddress = handleWasm.scoresAddress; + this._scoresAddressAddress = handleWasm.scoresAddressAddress; } /** * Number of audio samples per frame expected by Eagle (i.e. length of the array passed into `.process()`) */ - get frameLength(): number { - return this._frameLength; + get minProcessSamples(): number { + return this._minProcessSamples; } /** @@ -985,20 +1015,19 @@ export class Eagle extends EagleBase { * Set to a different name to use multiple models across `eagle` instances. * @param model.forceWrite Flag to overwrite the model in storage even if it exists. * @param model.version Version of the model file. Increment to update the model file in storage. - * @param speakerProfiles One or more Eagle speaker profiles. These can be constructed using `EagleProfiler`. * @param options Optional configuration arguments. * @param options.device String representation of the device (e.g., CPU or GPU) to use. If set to `best`, the most * suitable device is selected automatically. If set to `gpu`, the engine uses the first available GPU device. To select a specific * GPU device, set this argument to `gpu:${GPU_INDEX}`, where `${GPU_INDEX}` is the index of the target GPU. If set to * `cpu`, the engine will run on the CPU with the default number of threads. To specify the number of threads, set this * argument to `cpu:${NUM_THREADS}`, where `${NUM_THREADS}` is the desired number of threads. + * @param options.voiceThreshold Sensitivity threshold for detecting voice. * * @return An instance of the Eagle engine. */ public static async create( accessKey: string, model: EagleModel, - speakerProfiles: EagleProfile[] | EagleProfile, options: EagleOptions = {} ): Promise { const customWritePath = model.customWritePath @@ -1009,7 +1038,6 @@ export class Eagle extends EagleBase { return Eagle._init( accessKey, modelPath, - !Array.isArray(speakerProfiles) ? [speakerProfiles] : speakerProfiles, options ); } @@ -1017,20 +1045,16 @@ export class Eagle extends EagleBase { public static async _init( accessKey: string, modelPath: string, - speakerProfiles: EagleProfile[], options: EagleOptions = {} ): Promise { if (!isAccessKeyValid(accessKey)) { throw new EagleErrors.EagleInvalidArgumentError('Invalid AccessKey'); } - if (!speakerProfiles || speakerProfiles.length === 0) { - throw new EagleErrors.EagleInvalidArgumentError( - 'No speaker profiles provided' - ); - } - - let { device = "best" } = options; + let { + device = "best", + voiceThreshold = 0.3 // eslint-disable-line + } = options; const isSimd = await simd(); if (!isSimd) { @@ -1059,7 +1083,7 @@ export class Eagle extends EagleBase { accessKey.trim(), modelPath.trim(), device, - speakerProfiles, + voiceThreshold, sabDefined ? this._wasmPThread : this._wasmSimd, sabDefined ? this._wasmPThreadLib : this._wasmSimdLib, sabDefined ? createModulePThread : createModuleSimd @@ -1076,29 +1100,41 @@ export class Eagle extends EagleBase { } /** - * Processes a frame of audio and returns a list of similarity scores for each speaker profile. + * Processes audio and returns a list of similarity scores for each speaker profile. * - * @param pcm A frame of audio samples. The number of samples per frame can be attained by calling - * `.frameLength`. The incoming audio needs to have a sample rate equal to `.sampleRate` and be 16-bit + * @param pcm Array of audio samples. The minimum number of samples per frame can be attained by calling + * `.minProcessSamples`. The incoming audio needs to have a sample rate equal to `.sampleRate` and be 16-bit * linearly-encoded. Eagle operates on single-channel audio. + * @param speakerProfiles One or more Eagle speaker profiles. These can be constructed using `EagleProfiler`. * * @return A list of similarity scores for each speaker profile. A higher score indicates that the voice * belongs to the corresponding speaker. The range is [0, 1] with 1.0 representing a perfect match. */ - public async process(pcm: Int16Array): Promise { + public async process( + pcm: Int16Array, + speakerProfiles: EagleProfile[] | EagleProfile, + ): Promise { if (!(pcm instanceof Int16Array)) { throw new EagleErrors.EagleInvalidArgumentError( "The argument 'pcm' must be provided as an Int16Array" ); } - if (pcm.length !== this._frameLength) { + if (pcm.length < this._minProcessSamples) { + throw new EagleErrors.EagleInvalidArgumentError( + `Length of input sample (${pcm.length}) is not greater than minimum sample length (${this._minProcessSamples})` + ); + } + + const profiles = !Array.isArray(speakerProfiles) ? [speakerProfiles] : speakerProfiles; + + if (!profiles || profiles.length === 0) { throw new EagleErrors.EagleInvalidArgumentError( - `Length of input frame (${pcm.length}) does not match required frame length (${this._frameLength})` + 'No speaker profiles provided' ); } - return new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { this._functionMutex .runExclusive(async () => { if (this._module === undefined) { @@ -1116,11 +1152,46 @@ export class Eagle extends EagleBase { pcmAddress / Int16Array.BYTES_PER_ELEMENT ); + const numSpeakers = profiles.length; + const profilesAddressAddress = this._module._malloc( + numSpeakers * Int32Array.BYTES_PER_ELEMENT + ); + if (profilesAddressAddress === 0) { + throw new EagleErrors.EagleOutOfMemoryError( + 'malloc failed: Cannot allocate memory' + ); + } + const profilesAddressList: number[] = []; + for (const profile of profiles) { + const profileAddress = this._module._malloc( + profile.bytes.length * Uint8Array.BYTES_PER_ELEMENT + ); + if (profileAddress === 0) { + throw new EagleErrors.EagleOutOfMemoryError( + 'malloc failed: Cannot allocate memory' + ); + } + this._module.HEAPU8.set(profile.bytes, profileAddress); + profilesAddressList.push(profileAddress); + } + this._module.HEAP32.set( + new Int32Array(profilesAddressList), + profilesAddressAddress / Int32Array.BYTES_PER_ELEMENT + ); + const status = await this._pv_eagle_process( this._objectAddress, pcmAddress, - this._scoresAddress + pcm.length, + profilesAddressAddress, + profiles.length, + this._scoresAddressAddress ); + + for (let i = 0; i < profiles.length; i++) { + this._module._pv_free(profilesAddressList[i]); + } + this._module._pv_free(profilesAddressAddress); this._module._pv_free(pcmAddress); if (status !== PV_STATUS_SUCCESS) { @@ -1140,61 +1211,23 @@ export class Eagle extends EagleBase { ); } - const scores: number[] = []; - for (let i = 0; i < this._numSpeakers; i++) { - scores.push( - this._module.HEAPF32[ - this._scoresAddress / Float32Array.BYTES_PER_ELEMENT + i - ] - ); - } + const scoresAddress = this._module.HEAP32[this._scoresAddressAddress / Int32Array.BYTES_PER_ELEMENT]; - return scores; - }) - .then((result: number[]) => { - resolve(result); - }) - .catch((error: any) => { - reject(error); - }); - }); - } + if (scoresAddress) { + const scores: number[] = []; + for (let i = 0; i < profiles.length; i++) { + scores[i] = this._module.HEAPF32[(scoresAddress / Float32Array.BYTES_PER_ELEMENT) + i]; + } + this._pv_eagle_scores_delete(scoresAddress); + this._module.HEAP32[this._scoresAddressAddress / Int32Array.BYTES_PER_ELEMENT] = 0; - /** - * Resets the internal state of the engine. - * It is best to call before processing a new sequence of audio (e.g. a new voice interaction). - * This ensures that the accuracy of the engine is not affected by a change in audio context. - */ - public async reset(): Promise { - return new Promise((resolve, reject) => { - this._functionMutex - .runExclusive(async () => { - if (this._module === undefined) { - throw new EagleErrors.EagleInvalidStateError( - 'Attempted to call `.reset` after release' - ); - } - - const status = await this._pv_eagle_reset(this._objectAddress); - if (status !== PV_STATUS_SUCCESS) { - const messageStack = await Eagle.getMessageStack( - this._module._pv_get_error_stack, - this._module._pv_free_error_stack, - this._messageStackAddressAddressAddress, - this._messageStackDepthAddress, - this._module.HEAP32, - this._module.HEAPU8 - ); - - throw pvStatusToException( - status, - 'Eagle reset failed', - messageStack - ); + return scores; + } else { + return null; } }) - .then(() => { - resolve(); + .then((result: number[] | null) => { + resolve(result); }) .catch((error: any) => { reject(error); @@ -1342,7 +1375,7 @@ export class Eagle extends EagleBase { accessKey: string, modelPath: string, device: string, - speakerProfiles: EagleProfile[], + voiceThreshold: number, wasmBase64: string, wasmLibBase64: string, createModuleFunc: any @@ -1356,16 +1389,16 @@ export class Eagle extends EagleBase { const pv_eagle_init: pv_eagle_init_type = this.wrapAsyncFunction( baseWasmOutput.module, 'pv_eagle_init', - 6 + 5 ); const pv_eagle_process: pv_eagle_process_type = this.wrapAsyncFunction( baseWasmOutput.module, 'pv_eagle_process', - 3 + 5 ); - const pv_eagle_reset: pv_eagle_reset_type = this.wrapAsyncFunction( + const pv_eagle_scores_delete: pv_eagle_scores_delete_type = this.wrapAsyncFunction( baseWasmOutput.module, - 'pv_eagle_reset', + 'pv_eagle_scores_delete', 1 ); const pv_eagle_delete: pv_eagle_delete_type = this.wrapAsyncFunction( @@ -1424,44 +1457,16 @@ export class Eagle extends EagleBase { } baseWasmOutput.module.HEAPU8[deviceAddress + device.length] = 0; - const numSpeakers = speakerProfiles.length; - const profilesAddressAddress = baseWasmOutput.module._malloc( - numSpeakers * Int32Array.BYTES_PER_ELEMENT - ); - if (profilesAddressAddress === 0) { - throw new EagleErrors.EagleOutOfMemoryError( - 'malloc failed: Cannot allocate memory' - ); - } - const profilesAddressList: number[] = []; - for (const profile of speakerProfiles) { - const profileAddress = baseWasmOutput.module._malloc( - profile.bytes.length * Uint8Array.BYTES_PER_ELEMENT - ); - if (profileAddress === 0) { - throw new EagleErrors.EagleOutOfMemoryError( - 'malloc failed: Cannot allocate memory' - ); - } - baseWasmOutput.module.HEAPU8.set(profile.bytes, profileAddress); - profilesAddressList.push(profileAddress); - } - baseWasmOutput.module.HEAP32.set( - new Int32Array(profilesAddressList), - profilesAddressAddress / Int32Array.BYTES_PER_ELEMENT - ); - const status = await pv_eagle_init( + let status = await pv_eagle_init( accessKeyAddress, modelPathAddress, deviceAddress, - numSpeakers, - profilesAddressAddress, + voiceThreshold, objectAddressAddress ); baseWasmOutput.module._pv_free(accessKeyAddress); baseWasmOutput.module._pv_free(modelPathAddress); baseWasmOutput.module._pv_free(deviceAddress); - baseWasmOutput.module._pv_free(profilesAddressAddress); if (status !== PV_STATUS_SUCCESS) { const messageStack = await Eagle.getMessageStack( @@ -1482,26 +1487,58 @@ export class Eagle extends EagleBase { ]; baseWasmOutput.module._pv_free(objectAddressAddress); - const scoresAddress = baseWasmOutput.module._malloc( - Float32Array.BYTES_PER_ELEMENT * numSpeakers + const scoresAddressAddress = baseWasmOutput.module._malloc(Int32Array.BYTES_PER_ELEMENT); + if (scoresAddressAddress === 0) { + throw new EagleErrors.EagleOutOfMemoryError( + 'malloc failed: Cannot allocate memory' + ); + } + + const minProcessSamplesAddress = baseWasmOutput.module._malloc( + Int32Array.BYTES_PER_ELEMENT ); - if (scoresAddress === 0) { + if (minProcessSamplesAddress === 0) { throw new EagleErrors.EagleOutOfMemoryError( 'malloc failed: Cannot allocate memory' ); } - const frameLength = baseWasmOutput.module._pv_eagle_frame_length(); + status = + baseWasmOutput.module._pv_eagle_process_min_audio_length_samples( + objectAddress, + minProcessSamplesAddress + ); + if (status !== PV_STATUS_SUCCESS) { + const messageStack = await EagleProfiler.getMessageStack( + baseWasmOutput.module._pv_get_error_stack, + baseWasmOutput.module._pv_free_error_stack, + baseWasmOutput.messageStackAddressAddressAddress, + baseWasmOutput.messageStackDepthAddress, + baseWasmOutput.module.HEAP32, + baseWasmOutput.module.HEAPU8 + ); + + throw pvStatusToException( + status, + 'EagleProfiler failed to get min process audio length', + messageStack + ); + } + + const minProcessSamples = + baseWasmOutput.module.HEAP32[ + minProcessSamplesAddress / Int32Array.BYTES_PER_ELEMENT + ]; + baseWasmOutput.module._pv_free(minProcessSamplesAddress); return { ...baseWasmOutput, - frameLength: frameLength, - numSpeakers: numSpeakers, + minProcessSamples: minProcessSamples, objectAddress: objectAddress, - scoresAddress: scoresAddress, + scoresAddressAddress: scoresAddressAddress, pv_eagle_process: pv_eagle_process, - pv_eagle_reset: pv_eagle_reset, + pv_eagle_scores_delete: pv_eagle_scores_delete, pv_eagle_delete: pv_eagle_delete, }; } diff --git a/binding/web/src/eagle_profiler_worker.ts b/binding/web/src/eagle_profiler_worker.ts index d469d4c3..c0103ac8 100644 --- a/binding/web/src/eagle_profiler_worker.ts +++ b/binding/web/src/eagle_profiler_worker.ts @@ -1,5 +1,5 @@ /* - Copyright 2023-2025 Picovoice Inc. + Copyright 2023-2026 Picovoice Inc. You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE" file accompanying this source. @@ -14,9 +14,9 @@ import PvWorker from 'web-worker:./eagle_profiler_worker_handler.ts'; import { EagleModel, EagleProfile, - EagleProfilerEnrollResult, EagleProfilerOptions, EagleProfilerWorkerEnrollResponse, + EagleProfilerWorkerFlushResponse, EagleProfilerWorkerExportResponse, EagleProfilerWorkerInitResponse, EagleProfilerWorkerReleaseResponse, @@ -28,7 +28,7 @@ import { pvStatusToException } from "./eagle_errors"; export class EagleProfilerWorker { private readonly _worker: Worker; - private readonly _minEnrollSamples: number; + private readonly _frameLength: number; private readonly _sampleRate: number; private readonly _version: string; @@ -41,21 +41,21 @@ export class EagleProfilerWorker { private constructor( worker: Worker, - minEnrollSamples: number, + frameLength: number, sampleRate: number, version: string ) { this._worker = worker; - this._minEnrollSamples = minEnrollSamples; + this._frameLength = frameLength; this._sampleRate = sampleRate; this._version = version; } /** - * The minimum length of the input pcm required by `.enroll()`. + * The length of the input pcm required by `.enroll()`. */ - get minEnrollSamples(): number { - return this._minEnrollSamples; + get frameLength(): number { + return this._frameLength; } /** @@ -133,6 +133,8 @@ export class EagleProfilerWorker { * GPU device, set this argument to `gpu:${GPU_INDEX}`, where `${GPU_INDEX}` is the index of the target GPU. If set to * `cpu`, the engine will run on the CPU with the default number of threads. To specify the number of threads, set this * argument to `cpu:${NUM_THREADS}`, where `${NUM_THREADS}` is the desired number of threads. + * @param options.minEnrollmentChunks Minimum number of chunks to be processed before enroll returns 100% + * @param options.voiceThreshold Sensitivity threshold for detecting voice. * * @return An instance of the Eagle Profiler. */ @@ -159,7 +161,7 @@ export class EagleProfilerWorker { resolve( new EagleProfilerWorker( worker, - event.data.minEnrollSamples, + event.data.frameLength, event.data.sampleRate, event.data.version ) @@ -216,20 +218,10 @@ export class EagleProfilerWorker { * @param pcm Audio data for enrollment. The audio needs to have a sample rate equal to `.sampleRate` and be * 16-bit linearly-encoded. EagleProfiler operates on single-channel audio. * - * @return The percentage of completeness of the speaker enrollment process along with the feedback code - * corresponding to the last enrollment attempt: - * - `AUDIO_OK`: The audio is good for enrollment. - * - `AUDIO_TOO_SHORT`: Audio length is insufficient for enrollment, - * i.e. it is shorter than`.min_enroll_samples`. - * - `UNKNOWN_SPEAKER`: There is another speaker in the audio that is different from the speaker - * being enrolled. Too much background noise may cause this error as well. - * - `NO_VOICE_FOUND`: The audio does not contain any voice, i.e. it is silent or - * has a low signal-to-noise ratio. - * - `QUALITY_ISSUE`: The audio quality is too low for enrollment due to a bad microphone - * or recording environment. + * @return The percentage of completeness of the speaker enrollment process. */ - public enroll(pcm: Int16Array): Promise { - const returnPromise: Promise = new Promise( + public enroll(pcm: Int16Array): Promise { + const returnPromise: Promise = new Promise( (resolve, reject) => { this._worker.onmessage = ( event: MessageEvent @@ -269,6 +261,52 @@ export class EagleProfilerWorker { return returnPromise; } + /** + * Marks the end of the audio stream, flushes internal state of the object, and returns the percentage of enrollment + * completed. + * + * @return The percentage of completeness of the speaker enrollment process. + */ + public flush(): Promise { + const returnPromise: Promise = new Promise( + (resolve, reject) => { + this._worker.onmessage = ( + event: MessageEvent + ): void => { + switch (event.data.command) { + case 'ok': + resolve(event.data.result); + break; + case 'failed': + case 'error': + reject( + pvStatusToException( + event.data.status, + event.data.shortMessage, + event.data.messageStack + ) + ); + break; + default: + reject( + pvStatusToException( + PvStatus.RUNTIME_ERROR, + // @ts-ignore + `Unrecognized command: ${event.data.command}` + ) + ); + } + }; + } + ); + + this._worker.postMessage({ + command: 'flush', + }); + + return returnPromise; + } + /** * Exports the speaker profile of the current session. * Will throw error if the profile is not ready. diff --git a/binding/web/src/eagle_profiler_worker_handler.ts b/binding/web/src/eagle_profiler_worker_handler.ts index 1cd998fc..9e37523c 100644 --- a/binding/web/src/eagle_profiler_worker_handler.ts +++ b/binding/web/src/eagle_profiler_worker_handler.ts @@ -1,5 +1,5 @@ /* - Copyright 2023-2025 Picovoice Inc. + Copyright 2023-2026 Picovoice Inc. You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE" file accompanying this source. Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on @@ -13,6 +13,7 @@ import { EagleProfiler } from './eagle'; import { EagleProfilerWorkerEnrollRequest, + EagleProfilerWorkerFlushRequest, EagleProfilerWorkerInitRequest, EagleProfilerWorkerRequest, PvStatus, @@ -44,7 +45,7 @@ const initRequest = async ( ); return { command: 'ok', - minEnrollSamples: profiler.minEnrollSamples, + frameLength: profiler.frameLength, sampleRate: profiler.sampleRate, version: profiler.version, }; @@ -100,6 +101,40 @@ const enrollRequest = async ( } }; +const flushRequest = async ( + request: EagleProfilerWorkerFlushRequest // eslint-disable-line +): Promise => { + if (profiler === null) { + return { + command: 'error', + status: PvStatus.INVALID_STATE, + shortMessage: 'Eagle profiler not initialized', + }; + } + try { + const result = await profiler.flush(); + return { + command: 'ok', + result, + }; + } catch (e: any) { + if (e instanceof EagleError) { + return { + command: 'error', + status: e.status, + shortMessage: e.shortMessage, + messageStack: e.messageStack + }; + } else { + return { + command: 'error', + status: PvStatus.RUNTIME_ERROR, + shortMessage: e.message + }; + } + } +}; + const exportRequest = async (): Promise => { if (profiler === null) { return { @@ -187,6 +222,9 @@ self.onmessage = async function ( case 'enroll': self.postMessage(await enrollRequest(event.data)); break; + case 'flush': + self.postMessage(await flushRequest(event.data)); + break; case 'export': { const exportMsg = await exportRequest(); self.postMessage(exportMsg, [exportMsg.profile.bytes.buffer]); diff --git a/binding/web/src/eagle_worker.ts b/binding/web/src/eagle_worker.ts index eeda9acb..d189d04f 100644 --- a/binding/web/src/eagle_worker.ts +++ b/binding/web/src/eagle_worker.ts @@ -1,5 +1,5 @@ /* - Copyright 2023-2025 Picovoice Inc. + Copyright 2023-2026 Picovoice Inc. You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE" file accompanying this source. @@ -17,7 +17,6 @@ import { EagleWorkerProcessResponse, EagleWorkerInitResponse, EagleWorkerReleaseResponse, - EagleWorkerResetResponse, EagleProfile, PvStatus, } from './types'; @@ -26,7 +25,7 @@ import { pvStatusToException } from "./eagle_errors"; export class EagleWorker { private readonly _worker: Worker; - private readonly _frameLength: number; + private readonly _minProcessSamples: number; private readonly _sampleRate: number; private readonly _version: string; @@ -39,12 +38,12 @@ export class EagleWorker { private constructor( worker: Worker, - frameLength: number, + minProcessSamples: number, sampleRate: number, version: string ) { this._worker = worker; - this._frameLength = frameLength; + this._minProcessSamples = minProcessSamples; this._sampleRate = sampleRate; this._version = version; } @@ -52,8 +51,8 @@ export class EagleWorker { /** * Number of audio samples per frame expected by Eagle (i.e. length of the array passed into `.process()`) */ - get frameLength(): number { - return this._frameLength; + get minProcessSamples(): number { + return this._minProcessSamples; } /** @@ -125,20 +124,19 @@ export class EagleWorker { * Set to a different name to use multiple models across `eagle` instances. * @param model.forceWrite Flag to overwrite the model in storage even if it exists. * @param model.version Version of the model file. Increment to update the model file in storage. - * @param speakerProfiles One or more Eagle speaker profiles. These can be constructed using `EagleProfiler`. * @param options Optional configuration arguments. * @param options.device String representation of the device (e.g., CPU or GPU) to use. If set to `best`, the most * suitable device is selected automatically. If set to `gpu`, the engine uses the first available GPU device. To select a specific * GPU device, set this argument to `gpu:${GPU_INDEX}`, where `${GPU_INDEX}` is the index of the target GPU. If set to * `cpu`, the engine will run on the CPU with the default number of threads. To specify the number of threads, set this * argument to `cpu:${NUM_THREADS}`, where `${NUM_THREADS}` is the desired number of threads. + * @param options.voiceThreshold Sensitivity threshold for detecting voice. * * @return An instance of the Eagle engine. */ public static async create( accessKey: string, model: EagleModel, - speakerProfiles: EagleProfile[] | EagleProfile, options: EagleOptions = {} ): Promise { const customWritePath = model.customWritePath @@ -159,7 +157,7 @@ export class EagleWorker { resolve( new EagleWorker( worker, - event.data.frameLength, + event.data.minProcessSamples, event.data.sampleRate, event.data.version ) @@ -192,9 +190,6 @@ export class EagleWorker { command: 'init', accessKey: accessKey, modelPath: modelPath, - speakerProfiles: !Array.isArray(speakerProfiles) - ? [speakerProfiles] - : speakerProfiles, options: options, wasmSimd: this._wasmSimd, wasmSimdLib: this._wasmSimdLib, @@ -212,11 +207,15 @@ export class EagleWorker { * @param pcm A frame of audio samples. The number of samples per frame can be attained by calling * `.frameLength`. The incoming audio needs to have a sample rate equal to `.sampleRate` and be 16-bit * linearly-encoded. Eagle operates on single-channel audio. + * @param speakerProfiles One or more Eagle speaker profiles. These can be constructed using `EagleProfiler`. * * @return A list of similarity scores for each speaker profile. A higher score indicates that the voice * belongs to the corresponding speaker. The range is [0, 1] with 1.0 representing a perfect match. */ - public process(pcm: Int16Array): Promise { + public process( + pcm: Int16Array, + speakerProfiles: EagleProfile[] | EagleProfile, + ): Promise { const returnPromise: Promise = new Promise((resolve, reject) => { this._worker.onmessage = ( event: MessageEvent @@ -249,48 +248,9 @@ export class EagleWorker { this._worker.postMessage({ command: 'process', inputFrame: pcm, - }); - - return returnPromise; - } - - /** - * Resets the internal state of the engine. - * It is best to call before processing a new sequence of audio (e.g. a new voice interaction). - * This ensures that the accuracy of the engine is not affected by a change in audio context. - */ - public async reset(): Promise { - const returnPromise: Promise = new Promise((resolve, reject) => { - this._worker.onmessage = ( - event: MessageEvent - ): void => { - switch (event.data.command) { - case 'ok': - resolve(); - break; - case 'failed': - case 'error': - reject( - pvStatusToException( - event.data.status, - event.data.shortMessage, - event.data.messageStack - ) - ); - break; - default: - reject( - pvStatusToException( - PvStatus.RUNTIME_ERROR, - // @ts-ignore - `Unrecognized command: ${event.data.command}` - ) - ); - } - }; - }); - this._worker.postMessage({ - command: 'reset', + speakerProfiles: !Array.isArray(speakerProfiles) + ? [speakerProfiles] + : speakerProfiles, }); return returnPromise; diff --git a/binding/web/src/eagle_worker_handler.ts b/binding/web/src/eagle_worker_handler.ts index 70356356..f9bce8b7 100644 --- a/binding/web/src/eagle_worker_handler.ts +++ b/binding/web/src/eagle_worker_handler.ts @@ -1,5 +1,5 @@ /* - Copyright 2023-2025 Picovoice Inc. + Copyright 2023-2026 Picovoice Inc. You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE" file accompanying this source. Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on @@ -38,12 +38,11 @@ const initRequest = async (request: EagleWorkerInitRequest): Promise => { eagle = await Eagle._init( request.accessKey, request.modelPath, - request.speakerProfiles, request.options ); return { command: 'ok', - frameLength: eagle.frameLength, + minProcessSamples: eagle.minProcessSamples, sampleRate: eagle.sampleRate, version: eagle.version, }; @@ -76,7 +75,10 @@ const processRequest = async ( }; } try { - const scores = await eagle.process(request.inputFrame); + const scores = await eagle.process( + request.inputFrame, + request.speakerProfiles + ); return { command: 'ok', scores, @@ -99,37 +101,6 @@ const processRequest = async ( } }; -const resetRequest = async (): Promise => { - if (eagle === null) { - return { - command: 'error', - status: PvStatus.INVALID_STATE, - shortMessage: 'Eagle has not been initialized', - }; - } - try { - await eagle.reset(); - return { - command: 'ok', - }; - } catch (e: any) { - if (e instanceof EagleError) { - return { - command: 'error', - status: e.status, - shortMessage: e.shortMessage, - messageStack: e.messageStack - }; - } else { - return { - command: 'error', - status: PvStatus.RUNTIME_ERROR, - shortMessage: e.message - }; - } - } -}; - const releaseRequest = async (): Promise => { if (eagle !== null) { await eagle.release(); @@ -154,9 +125,6 @@ self.onmessage = async function ( case 'process': self.postMessage(await processRequest(event.data)); break; - case 'reset': - self.postMessage(await resetRequest()); - break; case 'release': self.postMessage(await releaseRequest()); break; diff --git a/binding/web/src/index.ts b/binding/web/src/index.ts index a8b44df0..2cb8204e 100644 --- a/binding/web/src/index.ts +++ b/binding/web/src/index.ts @@ -7,8 +7,6 @@ import { EagleModel, EagleOptions, EagleProfile, - EagleProfilerEnrollFeedback, - EagleProfilerEnrollResult, EagleProfilerOptions, EagleProfilerWorkerEnrollRequest, EagleProfilerWorkerEnrollResponse, @@ -66,8 +64,6 @@ export { EagleOptions, EagleProfile, EagleProfiler, - EagleProfilerEnrollFeedback, - EagleProfilerEnrollResult, EagleProfilerOptions, EagleProfilerWorker, EagleProfilerWorkerEnrollRequest, diff --git a/binding/web/src/types.ts b/binding/web/src/types.ts index e76c3253..cb361b43 100644 --- a/binding/web/src/types.ts +++ b/binding/web/src/types.ts @@ -1,5 +1,5 @@ /* - Copyright 2023-2025 Picovoice Inc. + Copyright 2023-2026 Picovoice Inc. You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE" file accompanying this source. @@ -31,14 +31,6 @@ export enum PvStatus { */ export type EagleModel = PvModel; -export enum EagleProfilerEnrollFeedback { - AUDIO_OK = 0, - AUDIO_TOO_SHORT, - UNKNOWN_SPEAKER, - NO_VOICE_FOUND, - QUALITY_ISSUE, -} - export type EagleProfile = { /** Buffer containing the speaker profile. */ bytes: Uint8Array; @@ -47,16 +39,17 @@ export type EagleProfile = { export type EagleOptions = { /** @defaultValue `best` */ device?: string; + /** @defaultValue `0.3` */ + voiceThreshold?: number; }; export type EagleProfilerOptions = { /** @defaultValue `best` */ device?: string; -}; - -export type EagleProfilerEnrollResult = { - feedback: EagleProfilerEnrollFeedback; - percentage: number; + /** @defaultValue `1` */ + minEnrollmentChunks?: number; + /** @defaultValue `0.3` */ + voiceThreshold?: number; }; export type EagleProfilerWorkerInitRequest = { @@ -76,6 +69,10 @@ export type EagleProfilerWorkerEnrollRequest = { inputFrame: Int16Array; }; +export type EagleProfilerWorkerFlushRequest = { + command: 'flush'; +}; + export type EagleProfilerWorkerExportRequest = { command: 'export'; }; @@ -91,6 +88,7 @@ export type EagleProfilerWorkerReleaseRequest = { export type EagleProfilerWorkerRequest = | EagleProfilerWorkerInitRequest | EagleProfilerWorkerEnrollRequest + | EagleProfilerWorkerFlushRequest | EagleProfilerWorkerExportRequest | EagleProfilerWorkerResetRequest | EagleProfilerWorkerReleaseRequest; @@ -106,7 +104,7 @@ export type EagleProfilerWorkerInitResponse = | EagleProfilerWorkerFailureResponse | { command: 'ok'; - minEnrollSamples: number; + frameLength: number; sampleRate: number; version: string; }; @@ -115,7 +113,14 @@ export type EagleProfilerWorkerEnrollResponse = | EagleProfilerWorkerFailureResponse | { command: 'ok'; - result: EagleProfilerEnrollResult; + result: number; + }; + +export type EagleProfilerWorkerFlushResponse = + | EagleProfilerWorkerFailureResponse + | { + command: 'ok'; + result: number; }; export type EagleProfilerWorkerExportResponse = @@ -140,6 +145,7 @@ export type EagleProfilerWorkerReleaseResponse = export type EagleProfilerWorkerResponse = | EagleProfilerWorkerInitResponse | EagleProfilerWorkerEnrollResponse + | EagleProfilerWorkerFlushResponse | EagleProfilerWorkerExportResponse | EagleProfilerWorkerResetResponse | EagleProfilerWorkerReleaseResponse; @@ -148,7 +154,6 @@ export type EagleWorkerInitRequest = { command: 'init'; accessKey: string; modelPath: string; - speakerProfiles: EagleProfile[]; options: EagleOptions; wasmSimd: string; wasmSimdLib: string; @@ -160,6 +165,7 @@ export type EagleWorkerInitRequest = { export type EagleWorkerProcessRequest = { command: 'process'; inputFrame: Int16Array; + speakerProfiles: EagleProfile[]; }; export type EagleWorkerResetRequest = { @@ -187,7 +193,7 @@ export type EagleWorkerInitResponse = | EagleWorkerFailureResponse | { command: 'ok'; - frameLength: number; + minProcessSamples: number; sampleRate: number; version: string; }; diff --git a/binding/web/test/eagle.test.ts b/binding/web/test/eagle.test.ts index 7b5eeea7..f2fb0bb4 100644 --- a/binding/web/test/eagle.test.ts +++ b/binding/web/test/eagle.test.ts @@ -2,7 +2,6 @@ import { Eagle, EagleProfile, EagleProfiler, - EagleProfilerEnrollFeedback, EagleProfilerWorker, EagleWorker, } from '../'; @@ -18,34 +17,35 @@ let testProfile: EagleProfile; const getProfile = async ( profiler, - audioChunks, - expectedFeedback + audioChunks ): Promise => { let percentage = 0; for (let i = 0; i < audioChunks.length; i++) { - const result = await profiler.enroll(audioChunks[i]); - expect(result.feedback).to.eq(expectedFeedback[i]); - expect(result.percentage).to.be.gt(0); - percentage = result.percentage; + for ( + let j = 0; + j < audioChunks[i].length - profiler.frameLength + 1; + j += profiler.frameLength + ) { + percentage = await profiler.enroll( + audioChunks[i].slice(j, j + profiler.frameLength), + ); + } + percentage = await profiler.flush(); } + expect(percentage).to.be.eq(100); return await profiler.export(); }; -const getScores = async (eagle, pcm): Promise => { - const allScores: number[] = []; - for ( - let i = 0; - i < pcm.length - eagle.frameLength + 1; - i += eagle.frameLength - ) { - const scores = await eagle.process(pcm.slice(i, i + eagle.frameLength)); - allScores.push(scores[0]); - } - - return allScores; -}; +const getScores = async ( + eagle, + pcm, + speakerProfiles +): Promise => await eagle.process( + pcm, + speakerProfiles +); before(() => { cy.getFramesFromFile('audio_samples/speaker_1_utt_1.wav').then( @@ -62,11 +62,7 @@ before(() => { ); testProfile = await getProfile( profiler, - [inputPcm1, inputPcm2], - [ - EagleProfilerEnrollFeedback.AUDIO_OK, - EagleProfilerEnrollFeedback.AUDIO_OK, - ] + [inputPcm1, inputPcm2] ); profiler.release(); } @@ -89,7 +85,7 @@ describe('Eagle Profiler', async function () { { device: DEVICE } ); expect(profiler.sampleRate).to.be.gt(0); - expect(profiler.minEnrollSamples).to.be.gt(0); + expect(profiler.frameLength).to.be.gt(0); expect(typeof profiler.version).to.eq('string'); expect(profiler.version).length.to.be.gt(0); await profiler.release(); @@ -110,7 +106,7 @@ describe('Eagle Profiler', async function () { ); expect(profiler.sampleRate).to.be.gt(0); - expect(profiler.minEnrollSamples).to.be.gt(0); + expect(profiler.frameLength).to.be.gt(0); expect(typeof profiler.version).to.eq('string'); expect(profiler.version).length.to.be.gt(0); await profiler.release(); @@ -136,22 +132,14 @@ describe('Eagle Profiler', async function () { const profile = await getProfile( profiler, - [inputPcm1, inputPcm2], - [ - EagleProfilerEnrollFeedback.AUDIO_OK, - EagleProfilerEnrollFeedback.AUDIO_OK, - ] + [inputPcm1, inputPcm2] ); expect(profile.bytes.length).to.be.gt(0); await profiler.reset(); const profile2 = await getProfile( profiler, - [inputPcm1, inputPcm2], - [ - EagleProfilerEnrollFeedback.AUDIO_OK, - EagleProfilerEnrollFeedback.AUDIO_OK, - ] + [inputPcm1, inputPcm2] ); expect(profile2.bytes.length).to.be.eq(profile.bytes.length); await profiler.release(); @@ -221,7 +209,7 @@ describe('Eagle Profiler', async function () { { device: DEVICE } ); - const testPcm = new Int16Array(eagle.minEnrollSamples); + const testPcm = new Int16Array(eagle.frameLength); // @ts-ignore const objectAddress = eagle._objectAddress; @@ -269,11 +257,10 @@ describe('Eagle', function () { publicPath: '/test/eagle_params.pv', forceWrite: true, }, - testProfile, { device: DEVICE } ); expect(eagle.sampleRate).to.be.gt(0); - expect(eagle.frameLength).to.be.gt(0); + expect(eagle.minProcessSamples).to.be.gt(0); expect(typeof eagle.version).to.eq('string'); expect(eagle.version).length.to.be.gt(0); await eagle.release(); @@ -286,11 +273,10 @@ describe('Eagle', function () { base64: eagleParams, forceWrite: true, }, - testProfile, { device: DEVICE } ); expect(eagle.sampleRate).to.be.gt(0); - expect(eagle.frameLength).to.be.gt(0); + expect(eagle.minProcessSamples).to.be.gt(0); expect(typeof eagle.version).to.eq('string'); expect(eagle.version).length.to.be.gt(0); await eagle.release(); @@ -302,7 +288,6 @@ describe('Eagle', function () { const eagle = await instance.create( "invalidAccessKey", { base64: eagleParams, forceWrite: true }, - testProfile, { device: DEVICE } ); await eagle.release(); @@ -318,7 +303,6 @@ describe('Eagle', function () { const eagle = await instance.create( "invalidAccessKey", { base64: eagleParams, forceWrite: true }, - testProfile, { device: DEVICE } ); await eagle.release(); @@ -334,7 +318,6 @@ describe('Eagle', function () { const eagle = await instance.create( ACCESS_KEY, { base64: eagleParams, forceWrite: true }, - testProfile, { device: "cloud:9" } ); expect(eagle).to.be.undefined; @@ -346,7 +329,7 @@ describe('Eagle', function () { expect(messageStack.length).to.be.lte(8); }); - it(`eagle process with reset (${instanceString})`, () => { + it(`eagle process (${instanceString})`, () => { cy.getFramesFromFile('audio_samples/speaker_1_test_utt.wav').then( async testPcm => { try { @@ -356,15 +339,13 @@ describe('Eagle', function () { publicPath: '/test/eagle_params.pv', forceWrite: true, }, - testProfile, { device: DEVICE } ); - const scores = await getScores(eagle, testPcm); + const scores = await getScores(eagle, testPcm, testProfile); - expect(Math.max(...scores)).to.be.gt(0.5); - await eagle.reset(); + expect(scores[0]).to.be.gt(0.5); - const scores2 = await getScores(eagle, testPcm); + const scores2 = await getScores(eagle, testPcm, testProfile); expect(scores2).to.be.deep.eq(scores); await eagle.release(); @@ -385,12 +366,11 @@ describe('Eagle', function () { publicPath: '/test/eagle_params.pv', forceWrite: true, }, - testProfile, { device: DEVICE } ); - const scores = await getScores(eagle, testPcm); + const scores = await getScores(eagle, testPcm, testProfile); - expect(Math.max(...scores)).to.be.lt(0.5); + expect(scores[0]).to.be.lt(0.5); await eagle.release(); } catch (e) { expect(e).to.be.undefined; @@ -412,10 +392,9 @@ describe('Eagle', function () { const eagle = await Eagle.create( ACCESS_KEY, { base64: eagleParams, forceWrite: true }, - testProfile, { device: DEVICE } ); - const testPcm = new Int16Array(eagle.frameLength); + const testPcm = new Int16Array(eagle.minProcessSamples); // @ts-ignore const objectAddress = eagle._objectAddress; @@ -423,7 +402,7 @@ describe('Eagle', function () { eagle._objectAddress = 0; try { - await eagle.process(testPcm); + await eagle.process(testPcm, testProfile); } catch (e: any) { error = e; } diff --git a/binding/web/test/eagle_perf.test.ts b/binding/web/test/eagle_perf.test.ts index ef9ba03c..3fba5bec 100644 --- a/binding/web/test/eagle_perf.test.ts +++ b/binding/web/test/eagle_perf.test.ts @@ -25,11 +25,19 @@ async function testEnrollPerformance( ); for (let i = 0; i < NUM_TEST_ITERATIONS + 1; i++) { - let start = Date.now(); - await profiler.enroll(inputPcm); - if (i > 0) { - enrollPerfResults.push((Date.now() - start) / 1000); + for ( + let j = 0; + j < inputPcm.length - profiler.frameLength + 1; + j += profiler.frameLength + ) { + let start = Date.now(); + await profiler.enroll(inputPcm.slice(j, j + profiler.frameLength)); + if (i > 0) { + enrollPerfResults.push((Date.now() - start) / 1000); + } } + + await profiler.flush(); } if (profiler instanceof EagleProfilerWorker) { @@ -61,7 +69,13 @@ async function testProcessPerformance( { device: DEVICE } ); for (const pcm of enrollPcm) { - await profiler.enroll(pcm); + for ( + let j = 0; + j < pcm.length - profiler.frameLength + 1; + j += profiler.frameLength + ) { + await profiler.enroll(pcm.slice(j, j + profiler.frameLength)); + } } const profile = await profiler.export(); profiler.release(); @@ -71,22 +85,15 @@ async function testProcessPerformance( { publicPath: '/test/eagle_params.pv', forceWrite: true, - }, - profile + } ); const processPerfResults: number[] = []; for (let i = 0; i < NUM_TEST_ITERATIONS + 1; i++) { - for ( - let j = 0; - j < testPcm.length - eagle.frameLength + 1; - j += eagle.frameLength - ) { - let start = Date.now(); - await eagle.process(testPcm.slice(j, j + eagle.frameLength)); - if (i > 0) { - processPerfResults.push((Date.now() - start) / 1000); - } + let start = Date.now(); + await eagle.process(testPcm, profile); + if (i > 0) { + processPerfResults.push((Date.now() - start) / 1000); } } diff --git a/demo/android/EagleDemo/eagle-demo-app/build.gradle b/demo/android/EagleDemo/eagle-demo-app/build.gradle index d739720a..e87e742d 100644 --- a/demo/android/EagleDemo/eagle-demo-app/build.gradle +++ b/demo/android/EagleDemo/eagle-demo-app/build.gradle @@ -67,6 +67,6 @@ dependencies { implementation 'androidx.appcompat:appcompat:1.4.2' implementation 'com.google.android.material:material:1.6.1' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' - implementation 'ai.picovoice:eagle-android:2.0.0' + implementation 'ai.picovoice:eagle-android:3.0.0' implementation 'ai.picovoice:android-voice-processor:1.0.2' } diff --git a/demo/android/EagleDemo/eagle-demo-app/src/main/java/ai/picovoice/eagledemo/MainActivity.java b/demo/android/EagleDemo/eagle-demo-app/src/main/java/ai/picovoice/eagledemo/MainActivity.java index 1256dd5b..19021334 100644 --- a/demo/android/EagleDemo/eagle-demo-app/src/main/java/ai/picovoice/eagledemo/MainActivity.java +++ b/demo/android/EagleDemo/eagle-demo-app/src/main/java/ai/picovoice/eagledemo/MainActivity.java @@ -1,5 +1,5 @@ /* - Copyright 2023 Picovoice Inc. + Copyright 2026 Picovoice Inc. You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE" file accompanying this source. @@ -45,15 +45,13 @@ import ai.picovoice.eagle.EagleInvalidArgumentException; import ai.picovoice.eagle.EagleProfile; import ai.picovoice.eagle.EagleProfiler; -import ai.picovoice.eagle.EagleProfilerEnrollFeedback; -import ai.picovoice.eagle.EagleProfilerEnrollResult; public class MainActivity extends AppCompatActivity { private static final String ACCESS_KEY = "${YOUR_ACCESS_KEY_HERE}"; private final VoiceProcessor voiceProcessor = VoiceProcessor.getInstance(); private final List progressBarIds = new ArrayList<>(); - private final ArrayList enrollmentPcm = new ArrayList<>(); + private final ArrayList processPcm = new ArrayList<>(); private final List profiles = new ArrayList<>(); private final boolean enableDump = false; private Eagle eagle = null; @@ -73,15 +71,21 @@ private void setUIState(UIState state) { switch (state) { case IDLE: - if (profiles.size() == 0) { + if (profiles.isEmpty()) { recordingTextView.setText("Enroll a speaker to start testing Eagle"); } else { recordingTextView.setText( "- Press 'ENROLL' to add more speakers\n- 'TEST' to test voice recognition"); + + for (Integer id : progressBarIds) { + ProgressBar progressBar = findViewById(id); + progressBar.setProgress(100); + } } + enrollButton.setEnabled(true); enrollProgress.setVisibility(View.GONE); - testButton.setEnabled(profiles.size() > 0); + testButton.setEnabled(!profiles.isEmpty()); break; case ENROLLING: errorText.setVisibility(View.INVISIBLE); @@ -97,6 +101,11 @@ private void setUIState(UIState state) { testButton.setEnabled(false); break; case TESTING: + for (Integer id : progressBarIds) { + ProgressBar progressBar = findViewById(id); + progressBar.setProgress(0); + } + errorText.setVisibility(View.INVISIBLE); recordingTextView.setText("Identifying speaker..."); enrollButton.setEnabled(false); @@ -179,25 +188,9 @@ private void startEnrolling() { return; } - final int frameLength = 1024; - enrollmentPcm.clear(); + final int frameLength = eagleProfiler.getFrameLength(); - voiceProcessor.addFrameListener(frame -> { - for (short sample : frame) { - enrollmentPcm.add(sample); - } - if (enrollmentPcm.size() > eagleProfiler.getMinEnrollSamples()) { - short[] enrollFrame = new short[enrollmentPcm.size()]; - for (int i = 0; i < enrollmentPcm.size(); i++) { - enrollFrame[i] = enrollmentPcm.get(i); - } - enrollmentPcm.clear(); - if (enableDump) { - eagleDump.add(enrollFrame); - } - enrollSpeaker(enrollFrame); - } - }); + voiceProcessor.addFrameListener(this::enrollSpeaker); try { voiceProcessor.start(frameLength, eagleProfiler.getSampleRate()); @@ -207,38 +200,61 @@ private void startEnrolling() { } private void startTesting() { + processPcm.clear(); + int minProcessSamples = eagle.getMinProcessSamples(); + voiceProcessor.addFrameListener(frame -> { - try { - synchronized (voiceProcessor) { - if (eagle == null) { - return; - } - float[] scores = eagle.process(frame); - for (int i = 0; i < scores.length; i++) { - float alpha = 0.25f; - smoothScores[i] = alpha * smoothScores[i] + (1 - alpha) * scores[i]; - } - if (enableDump) { - eagleDump.add(frame); - } + for (short sample : frame) { + processPcm.add(sample); + } + if (processPcm.size() > minProcessSamples) { + short[] processFrame = new short[processPcm.size()]; + for (int i = 0; i < processPcm.size(); i++) { + processFrame[i] = processPcm.get(i); + } + processPcm.clear(); + if (enableDump) { + eagleDump.add(processFrame); } - runOnUiThread(() -> { - if (progressBarIds.size() == 0) { - return; - } - for (int i = 0; i < smoothScores.length; i++) { - ProgressBar progressBar = findViewById(progressBarIds.get(i)); - progressBar.setProgress(Math.round(smoothScores[i] * 100)); + try { + synchronized (voiceProcessor) { + if (eagle == null) { + return; + } + + EagleProfile[] e = new EagleProfile[profiles.size()]; + for (int i = 0; i < profiles.size(); i++) { + e[i] = profiles.get(i); + } + + float[] scores = eagle.process(processFrame, e); + if (scores != null) { + System.arraycopy(scores, 0, smoothScores, 0, profiles.size()); + } else { + for (int i = 0; i < profiles.size(); i++) { + smoothScores[i] = 0.0f; + } + } } - }); - } catch (EagleException e) { - runOnUiThread(() -> displayError("Failed to process audio\n" + e.getMessage())); + runOnUiThread(() -> { + if (progressBarIds.isEmpty()) { + return; + } + + for (int i = 0; i < smoothScores.length; i++) { + ProgressBar progressBar = findViewById(progressBarIds.get(i)); + progressBar.setProgress(Math.round(smoothScores[i] * 100)); + } + }); + } catch (EagleException e) { + runOnUiThread(() -> displayError("Failed to process audio\n" + e.getMessage())); + } } }); try { - voiceProcessor.start(eagle.getFrameLength(), eagleProfiler.getSampleRate()); + voiceProcessor.start(eagle.getMinProcessSamples(), eagleProfiler.getSampleRate()); } catch (VoiceProcessorException e) { displayError("Failed to start recording\n" + e.getMessage()); } @@ -248,6 +264,7 @@ private void stop() { try { voiceProcessor.stop(); voiceProcessor.clearFrameListeners(); + setUIState(UIState.IDLE); } catch (VoiceProcessorException e) { displayError("Failed to stop recording\n" + e.getMessage()); } @@ -308,7 +325,6 @@ public void onEnrollClick(View view) { requestRecordPermission(); } } else { - setUIState(UIState.IDLE); stop(); } } @@ -319,13 +335,7 @@ public void onTestClick(View view) { if (testButton.isChecked()) { try { - EagleProfile[] e = new EagleProfile[profiles.size()]; - for (int i = 0; i < profiles.size(); i++) { - e[i] = profiles.get(i); - } - eagle = new Eagle.Builder() - .setSpeakerProfiles(e) .setAccessKey(ACCESS_KEY) .build(getApplicationContext()); @@ -350,11 +360,6 @@ public void onTestClick(View view) { eagle.delete(); eagle = null; } - - for (Integer id : progressBarIds) { - ProgressBar progressBar = findViewById(id); - progressBar.setProgress(100); - } } } @@ -380,23 +385,6 @@ public void onResetClick(View view) { setUIState(UIState.IDLE); } - private String getFeedback(EagleProfilerEnrollFeedback feedback) { - switch (feedback) { - case AUDIO_OK: - return "Enrolling speaker.."; - case AUDIO_TOO_SHORT: - return "Insufficient audio length"; - case UNKNOWN_SPEAKER: - return "Different speaker in audio"; - case NO_VOICE_FOUND: - return "Unable to detect voice in audio"; - case QUALITY_ISSUE: - return "Audio quality too low to use for enrollment"; - default: - return "Unrecognized feedback"; - } - } - @SuppressLint("DefaultLocale") private void createSpeaker() { runOnUiThread(() -> { @@ -431,24 +419,19 @@ private void createSpeaker() { @SuppressLint("DefaultLocale") private void enrollSpeaker(short[] enrollFrame) { - try { - EagleProfilerEnrollResult result = eagleProfiler.enroll(enrollFrame); - - if (result.getFeedback() == EagleProfilerEnrollFeedback.AUDIO_OK && result.getPercentage() == 100) { - stop(); + float percentage = eagleProfiler.enroll(enrollFrame); + if (percentage == 100) { EagleProfile profile = eagleProfiler.export(); + eagleProfiler.reset(); profiles.add(profile); runOnUiThread(() -> { - if (progressBarIds.size() == 0) { + if (progressBarIds.isEmpty()) { return; } - ProgressBar progressBar = findViewById(progressBarIds.get(progressBarIds.size() - 1)); - progressBar.setProgress(Math.round(result.getPercentage())); - ToggleButton enrollButton = findViewById(R.id.enrollButton); enrollButton.performClick(); }); @@ -457,16 +440,14 @@ private void enrollSpeaker(short[] enrollFrame) { eagleDump.saveFile(String.format("eagle_enroll_speaker_%d.wav", profiles.size())); } } else { - String finalMessage = String.format( - "%s. Keep speaking until the enrollment percentage reaches 100%%.", - getFeedback(result.getFeedback())); + String finalMessage = "Keep speaking until the enrollment percentage reaches 100%."; runOnUiThread(() -> { - if (progressBarIds.size() == 0) { + if (progressBarIds.isEmpty()) { return; } ProgressBar progressBar = findViewById(progressBarIds.get(progressBarIds.size() - 1)); - progressBar.setProgress(Math.round(result.getPercentage())); + progressBar.setProgress(Math.round(percentage)); TextView recordingTextView = findViewById(R.id.recordingTextView); recordingTextView.setText(finalMessage); diff --git a/demo/c/eagle_demo_file.c b/demo/c/eagle_demo_file.c index 96192807..9e7a6903 100644 --- a/demo/c/eagle_demo_file.c +++ b/demo/c/eagle_demo_file.c @@ -91,6 +91,8 @@ static struct option long_options[] = { {"library_path", required_argument, NULL, 'l'}, {"model_path", required_argument, NULL, 'm'}, {"device", required_argument, NULL, 'y'}, + {"voice_threshold", required_argument, NULL, 'v'}, + {"min_enrollment_chunks", required_argument, NULL, 'c'}, {"enroll", required_argument, NULL, 'e'}, {"test", required_argument, NULL, 't'}, {"show_inference_devices", no_argument, NULL, 'i'}, @@ -102,7 +104,8 @@ void (*pv_free_error_stack_func)(char **) = NULL; static void print_usage(const char *program_name) { fprintf(stdout, "Usage: %s [-e OUTPUT_PROFILE_PATH | -t INPUT_PROFILE_PATH ] " - "[-l LIBRARY_PATH -m MODEL_PATH -a ACCESS_KEY -y DEVICE WAV_AUDIO_PATH_1 WAV_AUDIO_PATH_2 ...]\n" + "[-l LIBRARY_PATH -m MODEL_PATH -a ACCESS_KEY -v VOICE_THRESHOLD " + "-c MIN_ENROLLMENT_CHUNKS -y DEVICE WAV_AUDIO_PATH_1 WAV_AUDIO_PATH_2 ...]\n" " %s [-i, --show_inference_devices] -l LIBRARY_PATH", program_name, program_name); @@ -195,6 +198,8 @@ void speaker_enrollment( const char *access_key, const char *model_path, const char *device, + int32_t min_enrollment_chunks, + float voice_threshold, void *eagle_library, const char *output_profile_path, int32_t num_audio_paths, @@ -210,6 +215,8 @@ void speaker_enrollment( const char *, const char *, const char *, + int32_t, + float, pv_eagle_profiler_t **) = load_symbol(eagle_library, "pv_eagle_profiler_init"); if (!pv_eagle_profiler_init_func) { print_dl_error("Failed to load 'pv_eagle_profiler_init'"); @@ -223,28 +230,26 @@ void speaker_enrollment( exit(EXIT_FAILURE); } - const char *(*pv_eagle_profiler_enroll_feedback_to_string_func)(pv_eagle_profiler_enroll_feedback_t) - = load_symbol(eagle_library, "pv_eagle_profiler_enroll_feedback_to_string"); - if (!pv_eagle_profiler_enroll_feedback_to_string_func) { - print_dl_error("Failed to load 'pv_eagle_profiler_enroll_feedback_to_string'"); - exit(EXIT_FAILURE); - } - pv_status_t (*pv_eagle_profiler_enroll_func)( pv_eagle_profiler_t *, const int16_t *, - int32_t, - pv_eagle_profiler_enroll_feedback_t *, float *) = load_symbol(eagle_library, "pv_eagle_profiler_enroll"); if (!pv_eagle_profiler_enroll_func) { print_dl_error("Failed to load 'pv_eagle_profiler_enroll'"); exit(EXIT_FAILURE); } - pv_status_t (*pv_eagle_profiler_enroll_min_audio_length_samples_func)(const pv_eagle_profiler_t *, int32_t *) - = load_symbol(eagle_library, "pv_eagle_profiler_enroll_min_audio_length_samples"); - if (!pv_eagle_profiler_enroll_min_audio_length_samples_func) { - print_dl_error("Failed to load 'pv_eagle_profiler_enroll_min_audio_length_samples'"); + pv_status_t (*pv_eagle_profiler_flush_func)( + pv_eagle_profiler_t *, + float *) = load_symbol(eagle_library, "pv_eagle_profiler_flush"); + if (!pv_eagle_profiler_enroll_func) { + print_dl_error("Failed to load 'pv_eagle_profiler_flush'"); + exit(EXIT_FAILURE); + } + + int32_t (*pv_eagle_profiler_frame_length_func)() = load_symbol(eagle_library, "pv_eagle_profiler_frame_length"); + if (!pv_eagle_profiler_frame_length_func) { + print_dl_error("Failed to load 'pv_eagle_profiler_frame_length'"); exit(EXIT_FAILURE); } @@ -286,6 +291,8 @@ void speaker_enrollment( access_key, model_path, device, + min_enrollment_chunks, + voice_threshold, &eagle_profiler); if (eagle_profiler_status != PV_STATUS_SUCCESS) { fprintf(stderr, "Failed to create an instance of eagle profiler"); @@ -306,6 +313,13 @@ void speaker_enrollment( exit(EXIT_FAILURE); } + const int32_t frame_length = pv_eagle_profiler_frame_length_func(); + int16_t *pcm = calloc(frame_length, sizeof(int16_t)); + if (!pcm) { + fprintf(stderr, "Failed to allocate pcm memory.\n"); + exit(EXIT_FAILURE); + } + double total_cpu_time_usec = 0; double total_processed_time_usec = 0; float enroll_percentage = 0.0f; @@ -349,28 +363,49 @@ void speaker_enrollment( exit(EXIT_FAILURE); } - size_t num_enroll_samples = wav_audio_file.totalPCMFrameCount; - int16_t *enroll_pcm = calloc(num_enroll_samples, sizeof(int16_t)); - if (!enroll_pcm) { - fprintf(stderr, "Failed to allocate memory for enrollment audio.\n"); - exit(EXIT_FAILURE); + while ((int32_t) drwav_read_pcm_frames_s16(&wav_audio_file, frame_length, pcm) == frame_length) { + struct timeval before; + gettimeofday(&before, NULL); + + eagle_profiler_status = pv_eagle_profiler_enroll_func( + eagle_profiler, + pcm, + &enroll_percentage); + if (eagle_profiler_status != PV_STATUS_SUCCESS) { + fprintf(stderr, "Failed to enroll audio: %s", pv_status_to_string_func(eagle_profiler_status)); + error_status = pv_get_error_stack_func(&message_stack, &message_stack_depth); + if (error_status != PV_STATUS_SUCCESS) { + fprintf( + stderr, + ".\nUnable to get Eagle error state with '%s'.\n", + pv_status_to_string_func(error_status)); + exit(EXIT_FAILURE); + } + + if (message_stack_depth > 0) { + fprintf(stderr, ":\n"); + print_error_message(message_stack, message_stack_depth); + pv_free_error_stack_func(message_stack); + } + exit(EXIT_FAILURE); + } + + struct timeval after; + gettimeofday(&after, NULL); + + total_cpu_time_usec += (double) (after.tv_sec - before.tv_sec) * 1e6 + + (double) (after.tv_usec - before.tv_usec); + total_processed_time_usec += + ((double) frame_length * 1e6) / pv_sample_rate_func(); } - drwav_read_pcm_frames_s16(&wav_audio_file, num_enroll_samples, enroll_pcm); drwav_uninit(&wav_audio_file); - struct timeval before; - gettimeofday(&before, NULL); - - pv_eagle_profiler_enroll_feedback_t feedback = PV_EAGLE_PROFILER_ENROLL_FEEDBACK_AUDIO_OK; - eagle_profiler_status = pv_eagle_profiler_enroll_func( + eagle_profiler_status = pv_eagle_profiler_flush_func( eagle_profiler, - enroll_pcm, - (int32_t) num_enroll_samples, - &feedback, &enroll_percentage); if (eagle_profiler_status != PV_STATUS_SUCCESS) { - fprintf(stderr, "Failed to enroll audio: %s", pv_status_to_string_func(eagle_profiler_status)); + fprintf(stderr, "Failed to flush audio: %s", pv_status_to_string_func(eagle_profiler_status)); error_status = pv_get_error_stack_func(&message_stack, &message_stack_depth); if (error_status != PV_STATUS_SUCCESS) { fprintf( @@ -387,22 +422,14 @@ void speaker_enrollment( } exit(EXIT_FAILURE); } - struct timeval after; - gettimeofday(&after, NULL); - total_cpu_time_usec += (double) (after.tv_sec - before.tv_sec) * 1e6 + - (double) (after.tv_usec - before.tv_usec); - total_processed_time_usec += - ((double) num_enroll_samples * 1e6) / pv_sample_rate_func(); - - fprintf(stdout, "Enrolled audio file %s [Enrollment percentage: %.2f%% - Enrollment feedback: %s]\n", + fprintf(stdout, "Enrolled audio file %s [Enrollment percentage: %.2f%%]\n", wav_audio_path, - enroll_percentage, - pv_eagle_profiler_enroll_feedback_to_string_func(feedback)); - - free(enroll_pcm); + enroll_percentage); } + free(pcm); + if (enroll_percentage < 100.0f) { fprintf(stderr, "Failed to create speaker profile. Insufficient enrollment percentage: %.2f%%. Please add more audio files for enrollment.\n", enroll_percentage); exit(EXIT_FAILURE); @@ -495,6 +522,7 @@ void speaker_recognition( const char *access_key, const char *model_path, const char *device, + float voice_threshold, void *eagle_library, const char *input_profile_path, int32_t num_audio_paths, @@ -510,8 +538,7 @@ void speaker_recognition( const char *, const char *, const char *, - int32_t, - const void *const *, + float, pv_eagle_t **) = load_symbol(eagle_library, "pv_eagle_init"); if (!pv_eagle_init_func) { print_dl_error("Failed to load 'pv_eagle_init'"); @@ -527,16 +554,19 @@ void speaker_recognition( pv_status_t (*pv_eagle_process_func)( pv_eagle_t *, const int16_t *, - float *) = load_symbol(eagle_library, "pv_eagle_process"); + int32_t, + void **, + int32_t, + float **) = load_symbol(eagle_library, "pv_eagle_process"); if (!pv_eagle_process_func) { print_dl_error("Failed to load 'pv_eagle_process'"); exit(EXIT_FAILURE); } - int32_t (*pv_eagle_reset_func)(pv_eagle_t *) - = load_symbol(eagle_library, "pv_eagle_reset"); - if (!pv_eagle_reset_func) { - print_dl_error("Failed to load 'pv_eagle_reset'"); + void (*pv_eagle_scores_delete_func)( + float *) = load_symbol(eagle_library, "pv_eagle_scores_delete"); + if (!pv_eagle_process_func) { + print_dl_error("Failed to load 'pv_eagle_scores_delete'"); exit(EXIT_FAILURE); } @@ -546,12 +576,6 @@ void speaker_recognition( exit(EXIT_FAILURE); } - int32_t (*pv_eagle_frame_length_func)() = load_symbol(eagle_library, "pv_eagle_frame_length"); - if (!pv_eagle_frame_length_func) { - print_dl_error("Failed to load 'pv_eagle_frame_length'"); - exit(EXIT_FAILURE); - } - FILE *input_profile_file = NULL; #if defined(_WIN32) || defined(_WIN64) @@ -593,8 +617,7 @@ void speaker_recognition( access_key, model_path, device, - 1, - (const void *const *) &speaker_profile, + voice_threshold, &eagle); if (eagle_status != PV_STATUS_SUCCESS) { fprintf(stderr, "Failed to create an instance of eagle with '%s'", pv_status_to_string_func(eagle_status)); @@ -615,11 +638,6 @@ void speaker_recognition( exit(EXIT_FAILURE); } - int16_t *pcm = calloc(pv_eagle_frame_length_func(), sizeof(int16_t)); - if (!pcm) { - fprintf(stderr, "Failed to allocate pcm memory.\n"); - exit(EXIT_FAILURE); - } double total_cpu_time_usec = 0; double total_processed_time_usec = 0; @@ -662,44 +680,57 @@ void speaker_recognition( } fprintf(stdout, "audio file: %s\n", wav_audio_path); - while ((int32_t) drwav_read_pcm_frames_s16(&wav_audio_file, pv_eagle_frame_length_func(), pcm) == - pv_eagle_frame_length_func()) { - struct timeval before; - gettimeofday(&before, NULL); - float score = 0.f; - eagle_status = pv_eagle_process_func(eagle, pcm, &score); - if (eagle_status != PV_STATUS_SUCCESS) { - fprintf(stderr, "Failed to process audio with '%s'", pv_status_to_string_func(eagle_status)); - error_status = pv_get_error_stack_func(&message_stack, &message_stack_depth); - if (error_status != PV_STATUS_SUCCESS) { - fprintf( - stderr, - ".\nUnable to get Eagle error state with '%s'.\n", - pv_status_to_string_func(error_status)); - exit(EXIT_FAILURE); - } + size_t num_process_samples = wav_audio_file.totalPCMFrameCount; + int16_t *process_pcm = calloc(num_process_samples, sizeof(int16_t)); + if (!process_pcm) { + fprintf(stderr, "Failed to allocate memory for process audio.\n"); + exit(EXIT_FAILURE); + } - if (message_stack_depth > 0) { - fprintf(stderr, ":\n"); - print_error_message(message_stack, message_stack_depth); - pv_free_error_stack_func(message_stack); - } + drwav_read_pcm_frames_s16(&wav_audio_file, num_process_samples, process_pcm); + drwav_uninit(&wav_audio_file); + + struct timeval before; + gettimeofday(&before, NULL); + + float *scores = NULL; + eagle_status = pv_eagle_process_func(eagle, process_pcm, num_process_samples, &speaker_profile, 1, &scores); + if (eagle_status != PV_STATUS_SUCCESS) { + fprintf(stderr, "Failed to process audio with '%s'", pv_status_to_string_func(eagle_status)); + error_status = pv_get_error_stack_func(&message_stack, &message_stack_depth); + if (error_status != PV_STATUS_SUCCESS) { + fprintf( + stderr, + ".\nUnable to get Eagle error state with '%s'.\n", + pv_status_to_string_func(error_status)); exit(EXIT_FAILURE); } - fprintf(stdout, "score: %.2f\n", score); - - struct timeval after; - gettimeofday(&after, NULL); + if (message_stack_depth > 0) { + fprintf(stderr, ":\n"); + print_error_message(message_stack, message_stack_depth); + pv_free_error_stack_func(message_stack); + } + exit(EXIT_FAILURE); + } - total_cpu_time_usec += (double) (after.tv_sec - before.tv_sec) * 1e6 + - (double) (after.tv_usec - before.tv_usec); - total_processed_time_usec += - (pv_eagle_frame_length_func() * 1e6) / pv_sample_rate_func(); + if (scores != NULL) { + fprintf(stdout, "score: %.2f\n", *scores); + pv_eagle_scores_delete_func(scores); + } else { + fprintf(stdout, "No Voice Detected\n"); } - drwav_uninit(&wav_audio_file); + struct timeval after; + gettimeofday(&after, NULL); + + free(process_pcm); + + total_cpu_time_usec += (double) (after.tv_sec - before.tv_sec) * 1e6 + + (double) (after.tv_usec - before.tv_usec); + total_processed_time_usec += + (num_process_samples * 1e6) / pv_sample_rate_func(); } const double real_time_factor = @@ -708,7 +739,6 @@ void speaker_recognition( fprintf(stdout, "\n"); - free(pcm); pv_eagle_delete_func(eagle); } @@ -720,6 +750,8 @@ int picovoice_main(int argc, char *argv[]) { bool show_inference_devices = false; const char *input_profile_path = NULL; const char *output_profile_path = NULL; + float voice_threshold = 0.3f; + int32_t min_enrollment_chunks = 1; int c; while ((c = getopt_long(argc, argv, "a:l:m:y:ie:t:", long_options, NULL)) != -1) { @@ -739,6 +771,12 @@ int picovoice_main(int argc, char *argv[]) { case 'a': access_key = optarg; break; + case 'v': + voice_threshold = atof(optarg); + break; + case 'c': + min_enrollment_chunks = atoi(optarg); + break; case 'e': output_profile_path = optarg; break; @@ -797,9 +835,9 @@ int picovoice_main(int argc, char *argv[]) { exit(EXIT_FAILURE); } - int32_t (*pv_eagle_frame_length_func)() = load_symbol(eagle_library, "pv_eagle_frame_length"); - if (!pv_eagle_frame_length_func) { - print_dl_error("Failed to load 'pv_eagle_frame_length'"); + int32_t (*pv_eagle_profiler_frame_length_func)() = load_symbol(eagle_library, "pv_eagle_profiler_frame_length"); + if (!pv_eagle_profiler_frame_length_func) { + print_dl_error("Failed to load 'pv_eagle_profiler_frame_length'"); exit(EXIT_FAILURE); } @@ -828,6 +866,8 @@ int picovoice_main(int argc, char *argv[]) { access_key, model_path, device, + min_enrollment_chunks, + voice_threshold, eagle_library, output_profile_path, num_audio_paths, @@ -837,6 +877,7 @@ int picovoice_main(int argc, char *argv[]) { access_key, model_path, device, + voice_threshold, eagle_library, input_profile_path, num_audio_paths, diff --git a/demo/c/eagle_demo_mic.c b/demo/c/eagle_demo_mic.c index 3011d4be..db69c1d7 100644 --- a/demo/c/eagle_demo_mic.c +++ b/demo/c/eagle_demo_mic.c @@ -91,6 +91,8 @@ static struct option long_options[] = { {"library_path", required_argument, NULL, 'l'}, {"model_path", required_argument, NULL, 'm'}, {"device", required_argument, NULL, 'y'}, + {"voice_threshold", required_argument, NULL, 'v'}, + {"min_enrollment_chunks", required_argument, NULL, 'c'}, {"enroll", required_argument, NULL, 'e'}, {"test", required_argument, NULL, 't'}, {"show_audio_devices", no_argument, NULL, 's'}, @@ -103,7 +105,8 @@ void (*pv_free_error_stack_func)(char **) = NULL; static void print_usage(const char *program_name) { fprintf(stdout, "Usage: %s [-e OUTPUT_PROFILE_PATH | -t INPUT_PROFILE_PATH] " - "[-l LIBRARY_PATH -m MODEL_PATH -a ACCESS_KEY -d AUDIO_DEVICE_INDEX -y DEVICE]\n" + "[-l LIBRARY_PATH -m MODEL_PATH -a ACCESS_KEY -v VOICE_THRESHOLD " + "-c MIN_ENROLLMENT_CHUNKS -d AUDIO_DEVICE_INDEX -y DEVICE]\n" " %s [-s, --show_audio_devices]\n" " %s [-i, --show_inference_devices] -l LIBRARY_PATH\n", program_name, @@ -221,6 +224,8 @@ void speaker_enrollment( const char *access_key, const char *model_path, const char *device, + int32_t min_enrollment_chunks, + float voice_threshold, const char *output_profile_path, void *eagle_library, pv_recorder_t *recorder) { @@ -241,6 +246,8 @@ void speaker_enrollment( const char *, const char *, const char *, + int32_t, + float, pv_eagle_profiler_t **) = load_symbol(eagle_library, "pv_eagle_profiler_init"); if (!pv_eagle_profiler_init_func) { print_dl_error("Failed to load 'pv_eagle_profiler_init'"); @@ -254,30 +261,26 @@ void speaker_enrollment( exit(EXIT_FAILURE); } - const char *(*pv_eagle_profiler_enroll_feedback_to_string_func)( - pv_eagle_profiler_enroll_feedback_t) = load_symbol(eagle_library, - "pv_eagle_profiler_enroll_feedback_to_string"); - if (!pv_eagle_profiler_enroll_feedback_to_string_func) { - print_dl_error("Failed to load 'pv_eagle_profiler_enroll_feedback_to_string'"); - exit(EXIT_FAILURE); - } - pv_status_t (*pv_eagle_profiler_enroll_func)( pv_eagle_profiler_t *, const int16_t *, - int32_t, - pv_eagle_profiler_enroll_feedback_t *, float *) = load_symbol(eagle_library, "pv_eagle_profiler_enroll"); if (!pv_eagle_profiler_enroll_func) { print_dl_error("Failed to load 'pv_eagle_profiler_enroll'"); exit(EXIT_FAILURE); } - pv_status_t (*pv_eagle_profiler_enroll_min_audio_length_samples_func)( - const pv_eagle_profiler_t *, - int32_t *) = load_symbol(eagle_library, "pv_eagle_profiler_enroll_min_audio_length_samples"); - if (!pv_eagle_profiler_enroll_min_audio_length_samples_func) { - print_dl_error("Failed to load 'pv_eagle_profiler_enroll_min_audio_length_samples'"); + pv_status_t (*pv_eagle_profiler_flush_func)( + pv_eagle_profiler_t *, + float *) = load_symbol(eagle_library, "pv_eagle_profiler_flush"); + if (!pv_eagle_profiler_enroll_func) { + print_dl_error("Failed to load 'pv_eagle_profiler_flush'"); + exit(EXIT_FAILURE); + } + + int32_t (*pv_eagle_profiler_frame_length_func)() = load_symbol(eagle_library, "pv_eagle_profiler_frame_length"); + if (!pv_eagle_profiler_frame_length_func) { + print_dl_error("Failed to load 'pv_eagle_profiler_frame_length'"); exit(EXIT_FAILURE); } @@ -304,12 +307,6 @@ void speaker_enrollment( exit(EXIT_FAILURE); } - int32_t (*pv_eagle_frame_length_func)() = load_symbol(eagle_library, "pv_eagle_frame_length"); - if (!pv_eagle_frame_length_func) { - print_dl_error("Failed to load 'pv_eagle_frame_length'"); - exit(EXIT_FAILURE); - } - char **message_stack = NULL; int32_t message_stack_depth = 0; pv_status_t error_status = PV_STATUS_RUNTIME_ERROR; @@ -319,6 +316,8 @@ void speaker_enrollment( access_key, model_path, device, + min_enrollment_chunks, + voice_threshold, &eagle_profiler); if (eagle_profiler_status != PV_STATUS_SUCCESS) { fprintf(stderr, "Failed to create an instance of eagle profiler"); @@ -339,30 +338,8 @@ void speaker_enrollment( exit(EXIT_FAILURE); } - int32_t num_enroll_samples = 0; - eagle_profiler_status = pv_eagle_profiler_enroll_min_audio_length_samples_func( - eagle_profiler, &num_enroll_samples); - if (eagle_profiler_status != PV_STATUS_SUCCESS) { - fprintf(stderr, "Failed to get minimum number of enrollment samples"); - error_status = pv_get_error_stack_func(&message_stack, &message_stack_depth); - if (error_status != PV_STATUS_SUCCESS) { - fprintf( - stderr, - ".\nUnable to get Eagle error state with '%s'.\n", - pv_status_to_string_func(error_status)); - exit(EXIT_FAILURE); - } - - if (message_stack_depth > 0) { - fprintf(stderr, ":\n"); - print_error_message(message_stack, message_stack_depth); - pv_free_error_stack_func(message_stack); - } - exit(EXIT_FAILURE); - } - - - int16_t *enroll_pcm = (int16_t *) malloc(num_enroll_samples * sizeof(int16_t)); + const int32_t frame_length = pv_eagle_profiler_frame_length_func(); + int16_t *enroll_pcm = (int16_t *) malloc(frame_length * sizeof(int16_t)); if (!enroll_pcm) { fprintf(stderr, "Failed to allocate pcm memory.\n"); exit(EXIT_FAILURE); @@ -371,34 +348,23 @@ void speaker_enrollment( fprintf(stdout, "Starting enrollment. Keep talking to the device until the progress reaches 100%%.\n"); float enroll_percentage = 0.0f; - pv_eagle_profiler_enroll_feedback_t feedback = PV_EAGLE_PROFILER_ENROLL_FEEDBACK_AUDIO_OK; - const int32_t frame_length = pv_eagle_frame_length_func(); + + pv_recorder_status_t recorder_status = pv_recorder_start(recorder); + if (recorder_status != PV_RECORDER_STATUS_SUCCESS) { + fprintf(stderr, "Failed to start device with %s.\n", pv_recorder_status_to_string(recorder_status)); + exit(EXIT_FAILURE); + } while ((enroll_percentage < 100.0f) && (!is_interrupted)) { - pv_recorder_status_t recorder_status = pv_recorder_start(recorder); + recorder_status = pv_recorder_read(recorder, enroll_pcm); if (recorder_status != PV_RECORDER_STATUS_SUCCESS) { - fprintf(stderr, "Failed to start device with %s.\n", pv_recorder_status_to_string(recorder_status)); - exit(EXIT_FAILURE); - } - for (int32_t i = 0; i < num_enroll_samples; i += frame_length) { - int16_t *pcm = &enroll_pcm[i]; - recorder_status = pv_recorder_read(recorder, pcm); - if (recorder_status != PV_RECORDER_STATUS_SUCCESS) { - fprintf(stderr, "Failed to read audio with %s.\n", pv_recorder_status_to_string(recorder_status)); - exit(EXIT_FAILURE); - } - } - recorder_status = pv_recorder_stop(recorder); - if (recorder_status != PV_RECORDER_STATUS_SUCCESS) { - fprintf(stderr, "Failed to stop device with %s.\n", pv_recorder_status_to_string(recorder_status)); + fprintf(stderr, "Failed to read audio with %s.\n", pv_recorder_status_to_string(recorder_status)); exit(EXIT_FAILURE); } eagle_profiler_status = pv_eagle_profiler_enroll_func( eagle_profiler, enroll_pcm, - num_enroll_samples, - &feedback, &enroll_percentage); if (eagle_profiler_status != PV_STATUS_SUCCESS) { fprintf(stderr, "Failed to enroll audio"); @@ -418,14 +384,39 @@ void speaker_enrollment( } exit(EXIT_FAILURE); } - if (feedback != PV_EAGLE_PROFILER_ENROLL_FEEDBACK_AUDIO_OK) { - fprintf(stdout, "\nEnrollment audio feedback: %s\n", - pv_eagle_profiler_enroll_feedback_to_string_func(feedback)); - } fprintf(stdout, "\rEnrollment progress: %.2f%%", enroll_percentage); fflush(stdout); } - fprintf(stdout, "\n"); + + recorder_status = pv_recorder_stop(recorder); + if (recorder_status != PV_RECORDER_STATUS_SUCCESS) { + fprintf(stderr, "Failed to stop device with %s.\n", pv_recorder_status_to_string(recorder_status)); + exit(EXIT_FAILURE); + } + + eagle_profiler_status = pv_eagle_profiler_flush_func( + eagle_profiler, + &enroll_percentage); + if (eagle_profiler_status != PV_STATUS_SUCCESS) { + fprintf(stderr, "Failed to flush audio"); + error_status = pv_get_error_stack_func(&message_stack, &message_stack_depth); + if (error_status != PV_STATUS_SUCCESS) { + fprintf( + stderr, + ".\nUnable to get Eagle error state with '%s'.\n", + pv_status_to_string_func(error_status)); + exit(EXIT_FAILURE); + } + + if (message_stack_depth > 0) { + fprintf(stderr, ":\n"); + print_error_message(message_stack, message_stack_depth); + pv_free_error_stack_func(message_stack); + } + exit(EXIT_FAILURE); + } + fprintf(stdout, "\rEnrollment progress: %.2f%%\n", enroll_percentage); + fflush(stdout); if (is_interrupted) { fprintf(stdout, "Enrollment interrupted.\n"); @@ -504,6 +495,7 @@ void speaker_recognition( const char *access_key, const char *model_path, const char *device, + float voice_threshold, const char *input_profile_path, void *eagle_library, pv_recorder_t *recorder) { @@ -524,8 +516,7 @@ void speaker_recognition( const char *, const char *, const char *, - int32_t, - const void *const *, + float, pv_eagle_t **) = load_symbol(eagle_library, "pv_eagle_init"); if (!pv_eagle_init_func) { print_dl_error("Failed to load 'pv_eagle_init'"); @@ -541,25 +532,35 @@ void speaker_recognition( pv_status_t (*pv_eagle_process_func)( pv_eagle_t *, const int16_t *, - float *) = load_symbol(eagle_library, "pv_eagle_process"); + int32_t, + void **, + int32_t, + float **) = load_symbol(eagle_library, "pv_eagle_process"); if (!pv_eagle_process_func) { print_dl_error("Failed to load 'pv_eagle_process'"); exit(EXIT_FAILURE); } - int32_t (*pv_eagle_reset_func)( - pv_eagle_t *) = load_symbol(eagle_library, "pv_eagle_reset"); - if (!pv_eagle_reset_func) { - print_dl_error("Failed to load 'pv_eagle_reset'"); + void (*pv_eagle_scores_delete_func)( + float *) = load_symbol(eagle_library, "pv_eagle_scores_delete"); + if (!pv_eagle_process_func) { + print_dl_error("Failed to load 'pv_eagle_scores_delete'"); exit(EXIT_FAILURE); } - pv_status_t (*pv_eagle_frame_length_func)() = load_symbol(eagle_library, "pv_eagle_frame_length"); - if (!pv_eagle_frame_length_func) { - print_dl_error("Failed to load 'pv_eagle_frame_length'"); + pv_status_t (*pv_eagle_process_min_audio_length_samples_func)( + const pv_eagle_t *, + int32_t *) = load_symbol(eagle_library, "pv_eagle_process_min_audio_length_samples"); + if (!pv_eagle_process_min_audio_length_samples_func) { + print_dl_error("Failed to load 'pv_eagle_process_min_audio_length_samples'"); exit(EXIT_FAILURE); } + int32_t (*pv_eagle_profiler_frame_length_func)() = load_symbol(eagle_library, "pv_eagle_profiler_frame_length"); + if (!pv_eagle_profiler_frame_length_func) { + print_dl_error("Failed to load 'pv_eagle_profiler_frame_length'"); + exit(EXIT_FAILURE); + } FILE *input_profile_file = NULL; @@ -602,8 +603,7 @@ void speaker_recognition( access_key, model_path, device, - 1, - (const void *const *) &speaker_profile, + voice_threshold, &eagle); if (eagle_status != PV_STATUS_SUCCESS) { fprintf(stderr, "Failed to create an instance of eagle with '%s'", pv_status_to_string_func(eagle_status)); @@ -630,23 +630,48 @@ void speaker_recognition( exit(EXIT_FAILURE); } - float score = 0.0f; - const int32_t frame_length = pv_eagle_frame_length_func(); - int16_t *pcm = (int16_t *) calloc(frame_length, sizeof(int16_t)); - if (!pcm) { + int32_t num_process_samples = 0; + eagle_status = pv_eagle_process_min_audio_length_samples_func( + eagle, &num_process_samples); + if (eagle_status != PV_STATUS_SUCCESS) { + fprintf(stderr, "Failed to get minimum number of process samples"); + error_status = pv_get_error_stack_func(&message_stack, &message_stack_depth); + if (error_status != PV_STATUS_SUCCESS) { + fprintf( + stderr, + ".\nUnable to get Eagle error state with '%s'.\n", + pv_status_to_string_func(error_status)); + exit(EXIT_FAILURE); + } + + if (message_stack_depth > 0) { + fprintf(stderr, ":\n"); + print_error_message(message_stack, message_stack_depth); + pv_free_error_stack_func(message_stack); + } + exit(EXIT_FAILURE); + } + + const int32_t frame_length = pv_eagle_profiler_frame_length_func(); + int16_t *process_pcm = (int16_t *) malloc(num_process_samples * sizeof(int16_t)); + if (!process_pcm) { fprintf(stderr, "Failed to allocate pcm memory.\n"); exit(EXIT_FAILURE); } fprintf(stdout, "Listening... (press Ctrl+C to stop)\n"); while (!is_interrupted) { - recorder_status = pv_recorder_read(recorder, pcm); - if (recorder_status != PV_RECORDER_STATUS_SUCCESS) { - fprintf(stderr, "Failed to read with %s.\n", pv_recorder_status_to_string(recorder_status)); - exit(EXIT_FAILURE); + for (int32_t i = 0; i < num_process_samples; i += frame_length) { + int16_t *pcm = &process_pcm[i]; + recorder_status = pv_recorder_read(recorder, pcm); + if (recorder_status != PV_RECORDER_STATUS_SUCCESS) { + fprintf(stderr, "Failed to read audio with %s.\n", pv_recorder_status_to_string(recorder_status)); + exit(EXIT_FAILURE); + } } - eagle_status = pv_eagle_process_func(eagle, pcm, &score); + float *score = NULL; + eagle_status = pv_eagle_process_func(eagle, process_pcm, num_process_samples, &speaker_profile, 1, &score); if (eagle_status != PV_STATUS_SUCCESS) { fprintf(stderr, "Failed to process audio with %s", pv_status_to_string_func(eagle_status)); error_status = pv_get_error_stack_func(&message_stack, &message_stack_depth); @@ -666,8 +691,14 @@ void speaker_recognition( exit(EXIT_FAILURE); } - fprintf(stdout, "\r[score: %.2f]", score); - fflush(stdout); + if (score != NULL) { + fprintf(stdout, "\r[score: %.2f] ", *score); + fflush(stdout); + pv_eagle_scores_delete_func(score); + } else { + fprintf(stdout, "\rNo Voice Detected"); + fflush(stdout); + } } fprintf(stdout, "\n"); @@ -677,7 +708,7 @@ void speaker_recognition( exit(1); } - free(pcm); + free(process_pcm); free(speaker_profile); pv_eagle_delete_func(eagle); } @@ -693,6 +724,8 @@ int picovoice_main(int argc, char *argv[]) { const char *input_profile_path = NULL; const char *output_profile_path = NULL; int32_t device_index = -1; + float voice_threshold = 0.3f; + int32_t min_enrollment_chunks = 1; int c; while ((c = getopt_long(argc, argv, "sa:d:l:m:y:ie:t:", long_options, NULL)) != -1) { @@ -718,6 +751,12 @@ int picovoice_main(int argc, char *argv[]) { case 'y': device = optarg; break; + case 'v': + voice_threshold = atof(optarg); + break; + case 'c': + min_enrollment_chunks = atoi(optarg); + break; case 'i': show_inference_devices = true; break; @@ -763,9 +802,9 @@ int picovoice_main(int argc, char *argv[]) { exit(EXIT_FAILURE); } - int32_t (*pv_eagle_frame_length_func)() = load_symbol(eagle_library, "pv_eagle_frame_length"); - if (!pv_eagle_frame_length_func) { - print_dl_error("Failed to load 'pv_eagle_frame_length'"); + int32_t (*pv_eagle_profiler_frame_length_func)() = load_symbol(eagle_library, "pv_eagle_profiler_frame_length"); + if (!pv_eagle_profiler_frame_length_func) { + print_dl_error("Failed to load 'pv_eagle_profiler_frame_length'"); exit(EXIT_FAILURE); } @@ -789,7 +828,7 @@ int picovoice_main(int argc, char *argv[]) { fprintf(stdout, "v%s\n\n", pv_eagle_version_func()); - const int32_t frame_length = pv_eagle_frame_length_func(); + const int32_t frame_length = pv_eagle_profiler_frame_length_func(); pv_recorder_t *recorder = NULL; pv_recorder_status_t recorder_status = pv_recorder_init(frame_length, device_index, 100, &recorder); if (recorder_status != PV_RECORDER_STATUS_SUCCESS) { @@ -804,6 +843,8 @@ int picovoice_main(int argc, char *argv[]) { access_key, model_path, device, + min_enrollment_chunks, + voice_threshold, output_profile_path, eagle_library, recorder); @@ -812,6 +853,7 @@ int picovoice_main(int argc, char *argv[]) { access_key, model_path, device, + voice_threshold, input_profile_path, eagle_library, recorder); diff --git a/demo/ios/EagleDemo/EagleDemo.xcodeproj/project.pbxproj b/demo/ios/EagleDemo/EagleDemo.xcodeproj/project.pbxproj index c37cfdd6..ba856b1b 100644 --- a/demo/ios/EagleDemo/EagleDemo.xcodeproj/project.pbxproj +++ b/demo/ios/EagleDemo/EagleDemo.xcodeproj/project.pbxproj @@ -10,6 +10,8 @@ 02447A8D26D94F75004A6CE9 /* EagleDemoApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02447A8C26D94F75004A6CE9 /* EagleDemoApp.swift */; }; 02447A8F26D94F75004A6CE9 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02447A8E26D94F75004A6CE9 /* ContentView.swift */; }; 02447A9126D94F7C004A6CE9 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 02447A9026D94F7C004A6CE9 /* Assets.xcassets */; }; + 3414A5E42F845FBE001F1FA6 /* Eagle in Frameworks */ = {isa = PBXBuildFile; productRef = 3414A5E32F845FBE001F1FA6 /* Eagle */; }; + 3414A5EA2F84607C001F1FA6 /* Eagle in Frameworks */ = {isa = PBXBuildFile; productRef = 3414A5E92F84607C001F1FA6 /* Eagle */; }; C76A41602703B17000DB57D6 /* ViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C76A415F2703B17000DB57D6 /* ViewModel.swift */; }; E19F4D222CF51CB20097F2C5 /* Eagle in Frameworks */ = {isa = PBXBuildFile; productRef = E19F4D212CF51CB20097F2C5 /* Eagle */; }; E19F4D252CF51CC40097F2C5 /* ios_voice_processor in Frameworks */ = {isa = PBXBuildFile; productRef = E19F4D242CF51CC40097F2C5 /* ios_voice_processor */; }; @@ -32,7 +34,9 @@ files = ( E1F352FB2D00E8E30069B0E6 /* Eagle in Frameworks */, E19F4D252CF51CC40097F2C5 /* ios_voice_processor in Frameworks */, + 3414A5EA2F84607C001F1FA6 /* Eagle in Frameworks */, E19F4D222CF51CB20097F2C5 /* Eagle in Frameworks */, + 3414A5E42F845FBE001F1FA6 /* Eagle in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -112,7 +116,7 @@ mainGroup = 02447A8026D94F74004A6CE9; packageReferences = ( E19F4D232CF51CC40097F2C5 /* XCRemoteSwiftPackageReference "ios-voice-processor" */, - E1F352F92D00E8E30069B0E6 /* XCRemoteSwiftPackageReference "eagle" */, + 3414A5E82F84607C001F1FA6 /* XCRemoteSwiftPackageReference "eagle" */, ); productRefGroup = 02447A8A26D94F75004A6CE9 /* Products */; projectDirPath = ""; @@ -271,7 +275,7 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_ASSET_PATHS = ""; - DEVELOPMENT_TEAM = 65723695GD; + DEVELOPMENT_TEAM = QW8RJJCS4H; ENABLE_PREVIEWS = YES; INFOPLIST_FILE = EagleDemo/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 16.0; @@ -279,7 +283,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = ai.picovoice.EagleDemo; + PRODUCT_BUNDLE_IDENTIFIER = ai.picovoice.EagleDemo2; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -293,7 +297,7 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_ASSET_PATHS = ""; - DEVELOPMENT_TEAM = 65723695GD; + DEVELOPMENT_TEAM = QW8RJJCS4H; ENABLE_PREVIEWS = YES; INFOPLIST_FILE = EagleDemo/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 16.0; @@ -301,7 +305,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = ai.picovoice.EagleDemo; + PRODUCT_BUNDLE_IDENTIFIER = ai.picovoice.EagleDemo2; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -331,14 +335,15 @@ }; /* End XCConfigurationList section */ -/* Begin XCLocalSwiftPackageReference section */ - 1E4229AF2ED53B530052E028 /* XCLocalSwiftPackageReference "../../../../eagle" */ = { - isa = XCLocalSwiftPackageReference; - relativePath = ../../../../eagle; - }; -/* End XCLocalSwiftPackageReference section */ - /* Begin XCRemoteSwiftPackageReference section */ + 3414A5E82F84607C001F1FA6 /* XCRemoteSwiftPackageReference "eagle" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/Picovoice/eagle"; + requirement = { + kind = exactVersion; + version = 3.0.0; + }; + }; E19F4D232CF51CC40097F2C5 /* XCRemoteSwiftPackageReference "ios-voice-processor" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/Picovoice/ios-voice-processor"; @@ -358,6 +363,15 @@ /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ + 3414A5E32F845FBE001F1FA6 /* Eagle */ = { + isa = XCSwiftPackageProductDependency; + productName = Eagle; + }; + 3414A5E92F84607C001F1FA6 /* Eagle */ = { + isa = XCSwiftPackageProductDependency; + package = 3414A5E82F84607C001F1FA6 /* XCRemoteSwiftPackageReference "eagle" */; + productName = Eagle; + }; E19F4D212CF51CB20097F2C5 /* Eagle */ = { isa = XCSwiftPackageProductDependency; productName = Eagle; diff --git a/demo/ios/EagleDemo/EagleDemo/ViewModel.swift b/demo/ios/EagleDemo/EagleDemo/ViewModel.swift index f588994e..b6cf0672 100644 --- a/demo/ios/EagleDemo/EagleDemo/ViewModel.swift +++ b/demo/ios/EagleDemo/EagleDemo/ViewModel.swift @@ -33,7 +33,7 @@ class ViewModel: ObservableObject { private var profiles: [EagleProfile] = [] - private var enrollPcmBuffer: [Int16] = [] + private var processPcmBuffer: [Int16] = [] @Published var scores: [Float] = [] @Published var enrollPercentage: Float = 0 @@ -57,21 +57,6 @@ class ViewModel: ObservableObject { self.state = UIState.INTRO } - private func setEnrollFeedback(feedback: EagleProfilerEnrollFeedback) { - switch feedback { - case EagleProfilerEnrollFeedback.AUDIO_TOO_SHORT: - enrollFeedback = "Insufficient audio length" - case EagleProfilerEnrollFeedback.UNKNOWN_SPEAKER: - enrollFeedback = "Different speaker detected in audio" - case EagleProfilerEnrollFeedback.NO_VOICE_FOUND: - enrollFeedback = "Unable to detect voice in audio" - case EagleProfilerEnrollFeedback.QUALITY_ISSUE: - enrollFeedback = "Audio quality too low to use for enrollment" - default: - enrollFeedback = "" - } - } - private func initProfiler() { do { try eagleProfiler = EagleProfiler(accessKey: accessKey) @@ -104,25 +89,18 @@ class ViewModel: ObservableObject { guard let eagleProfiler = self.eagleProfiler else { return } - self.enrollPcmBuffer.append(contentsOf: pcm) - do { - let minEnrollSamples = try eagleProfiler.minEnrollSamples() - if self.enrollPcmBuffer.count >= minEnrollSamples { - let enrollFrame = Array(self.enrollPcmBuffer[0..= 100.0 { - try self.stopEnroll(export: true) - } - DispatchQueue.main.async { - self.enrollPercentage = percentage - self.setEnrollFeedback(feedback: feedback) - } + do { + let percentage = try eagleProfiler.enroll(pcm: pcm) + if percentage >= 100.0 { + try self.stopEnroll(export: true) + } - try self.appendToDumpFile(pcm: enrollFrame) + DispatchQueue.main.async { + self.enrollPercentage = percentage } + + try self.appendToDumpFile(pcm: pcm) } catch { self.errorMessage = "Failed to process pcm frames for enrollment." try? self.stopEnroll() @@ -137,7 +115,7 @@ class ViewModel: ObservableObject { do { try VoiceProcessor.instance.start( - frameLength: UInt32(512), + frameLength: UInt32(EagleProfiler.frameLength), sampleRate: UInt32(EagleProfiler.sampleRate)) } catch { errorMessage = "\(error)" @@ -179,21 +157,34 @@ class ViewModel: ObservableObject { private func initEagle() { do { - try eagle = Eagle(accessKey: accessKey, speakerProfiles: profiles) + try eagle = Eagle(accessKey: accessKey) statusText = "" self.testErrorListener = VoiceProcessorErrorListener({ error in self.errorMessage = "\(error)" }) self.testListener = VoiceProcessorFrameListener({ pcm in + self.processPcmBuffer.append(contentsOf: pcm) do { - let profileScores = try self.eagle.process(pcm: pcm) - - DispatchQueue.main.async { - self.scores = profileScores + let minProcessSamples = try self.eagle.minProcessSamples() + if self.processPcmBuffer.count >= minProcessSamples { + let processFrame = Array(self.processPcmBuffer[0..', 'AccessKey obtained from Picovoice Console (https://console.picovoice.ai/)') .option('-l, --library_path [value]', 'Absolute path to dynamic library. Default: using the library provided by `pveagle`') .option('-m, --model_path [value]', 'Absolute path to Eagle model. Default: using the model provided by `pveagle`') .option('-y, --device [value]', 'Device to run inference on (`best`, `cpu:{num_threads}` or `gpu:{gpu_index}`). Default: selects best device for Eagle inference') + .option('-v, --voice_threshold [value]', 'Sensitivity threshold for detecting voice.', 0.3) + .option('-c, --min_enrollment_chunks [value]', 'Minimum number of chunks to be processed before enroll returns 100', 1) .option('--enroll', 'Enroll a new speaker profile') .option('--test', "Evaluate Eagle's performance using the provided speaker profiles.") .option('--enroll_audio_paths ', 'Absolute path(s) to enrollment audio files') @@ -53,15 +46,19 @@ if (process.argv.length < 1) { program.parse(process.argv); function printResults(scores, labels) { - let result = '\rscores -> '; + if (scores) { + let result = '\rscores -> '; - let formattedResults = []; - for (let i = 0; i < labels.length; i++) { - formattedResults.push(`\`${labels[i]}\`: ${scores[i].toFixed(2)}`); - } - result += formattedResults.join(', '); + let formattedResults = []; + for (let i = 0; i < labels.length; i++) { + formattedResults.push(`\`${labels[i]}\`: ${scores[i].toFixed(2)}`); + } + result += formattedResults.join(', '); - process.stdout.write(`${result}\n`); + process.stdout.write(`${result}\n`); + } else { + process.stdout.write("No Voice Detected\n"); + } } let isInterrupted = false; @@ -71,6 +68,8 @@ async function fileDemo() { const libraryFilePath = program["library_file_path"]; const modelFilePath = program["model_file_path"]; const device = program["device"]; + const voice_threshold = Number(program["voice_threshold"]) + const minEnrollmentChunks = Number(program["min_enrollment_chunks"]) const enroll = program["enroll"]; const test = program["test"]; const enrollAudioPaths = program["enroll_audio_paths"]; @@ -120,6 +119,8 @@ async function fileDemo() { eagleProfiler = new EagleProfiler(accessKey, { modelPath: modelFilePath, device: device, + minEnrollmentChunks: minEnrollmentChunks, + voice_threshold: voice_threshold, libraryPath: libraryFilePath }); console.log(`Eagle version: ${eagleProfiler.version}`); @@ -148,21 +149,14 @@ async function fileDemo() { let frames = getInt16Frames(inputWaveFile, eagleProfiler.frameLength); for (let frame of frames) { audioData.push(frame); - if (audioData.length * eagleProfiler.frameLength >= eagleProfiler.minEnrollSamples) { - const enrollFrames = new Int16Array(audioData.length * eagleProfiler.frameLength); - for (let i = 0; i < audioData.length; i++) { - enrollFrames.set(audioData[i], i * eagleProfiler.frameLength); - } - audioData = []; - const { percentage, feedback } = eagleProfiler.enroll(enrollFrames); - feedbackMessage = FEEDBACK_TO_DESCRIPTIVE_MSG[feedback]; - enrollPercentage = percentage; - } + enrollPercentage = eagleProfiler.enroll(frame); } + enrollPercentage = eagleProfiler.flush(); + readline.clearLine(process.stdout, 0) readline.cursorTo(process.stdout, 0, null) - console.log(`Enrolled audio file ${audioPath} [Enrollment percentage: ${enrollPercentage}% - Enrollment feedback: ${feedbackMessage}]`); + console.log(`Enrolled audio file ${audioPath} [Enrollment percentage: ${enrollPercentage}%]`); } process.stdout.write(`\n`); @@ -213,9 +207,10 @@ async function fileDemo() { let eagle; try { - eagle = new Eagle(accessKey, profiles, { + eagle = new Eagle(accessKey, { modelPath: modelFilePath, device: device, + voice_threshold: voice_threshold, libraryPath: libraryFilePath }); @@ -238,11 +233,9 @@ async function fileDemo() { process.exit(); } - let frames = getInt16Frames(inputWaveFile, eagle.frameLength); - for (let frame of frames) { - const scores = eagle.process(frame); - printResults(scores, speakerLabels); - } + let samples = inputWaveFile.getSamples(false, Int16Array); + const scores = eagle.process(samples, profiles); + printResults(scores, speakerLabels); process.stdout.write("\nStopping..."); } catch (e) { diff --git a/demo/nodejs/package.json b/demo/nodejs/package.json index 28d200ed..a9e59b4f 100644 --- a/demo/nodejs/package.json +++ b/demo/nodejs/package.json @@ -1,6 +1,6 @@ { "name": "@picovoice/eagle-node-demo", - "version": "2.0.1", + "version": "3.0.0", "description": "Picovoice Eagle Node.js file-based and microphone demos", "scripts": { "file": "node file.js", @@ -24,7 +24,7 @@ "author": "Picovoice Inc.", "license": "Apache-2.0", "dependencies": { - "@picovoice/eagle-node": "2.0.1", + "@picovoice/eagle-node": "3.0.0", "@picovoice/pvrecorder-node": "^1.2.6", "commander": "^6.1.0", "readline": "^1.3.0", diff --git a/demo/nodejs/yarn.lock b/demo/nodejs/yarn.lock index f7373d70..9500af30 100644 --- a/demo/nodejs/yarn.lock +++ b/demo/nodejs/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@picovoice/eagle-node@2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@picovoice/eagle-node/-/eagle-node-2.0.1.tgz#ccde7c05b50551654a5f52e2f30f3eb3303ed721" - integrity sha512-g+IOQgIORph3kbttZwpy6whL9nni/+89hLrDx2d4Up4FCFbfeo/vsyrulD5lAA3lHNSBotUeDedP/tRyJr38cw== +"@picovoice/eagle-node@3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@picovoice/eagle-node/-/eagle-node-3.0.0.tgz#d34ee511a86fa5161ae41e0ceda533ab499608a3" + integrity sha512-XUDqLNAL6cmuzjGZm5JQgohJVlaJMlPdgB6a+Hnfg9sjtaGMFHGanignn1bUsnoyTPBIcsawDqkIcbW3ue8E/A== "@picovoice/pvrecorder-node@^1.2.6": version "1.2.6" diff --git a/demo/python/eagle_demo_file.py b/demo/python/eagle_demo_file.py index 929a8a44..a355ae94 100644 --- a/demo/python/eagle_demo_file.py +++ b/demo/python/eagle_demo_file.py @@ -18,14 +18,6 @@ import pveagle -FEEDBACK_TO_DESCRIPTIVE_MSG = { - pveagle.EagleProfilerEnrollFeedback.AUDIO_OK: 'Good audio', - pveagle.EagleProfilerEnrollFeedback.AUDIO_TOO_SHORT: 'Insufficient audio length', - pveagle.EagleProfilerEnrollFeedback.UNKNOWN_SPEAKER: 'Different speaker in audio', - pveagle.EagleProfilerEnrollFeedback.NO_VOICE_FOUND: 'No voice found in audio', - pveagle.EagleProfilerEnrollFeedback.QUALITY_ISSUE: 'Low audio quality due to bad microphone or environment' -} - def read_file(file_name, sample_rate): with wave.open(file_name, mode="rb") as wav_file: @@ -48,9 +40,8 @@ def read_file(file_name, sample_rate): return frames[::channels] -def print_result(time, scores, labels): - result = 'time: %4.2f sec | scores -> ' % time - result += ', '.join('`%s`: %.2f' % (label, score) for label, score in zip(labels, scores)) +def print_result(scores, labels): + result = ', '.join('`%s`: %.2f' % (label, score) for label, score in zip(labels, scores)) print(result) @@ -76,6 +67,11 @@ def main(): '--device', help='Device to run inference on (`best`, `cpu:{num_threads}` or `gpu:{gpu_index}`). ' 'Default: automatically selects best device for `pveagle`') + common_parser.add_argument( + '--voice_threshold', + help="Sensitivity threshold for detecting voice.", + type=float, + default=0.3) subparsers = parser.add_subparsers(dest='command') @@ -89,6 +85,11 @@ def main(): '--output_profile_path', required=True, help='Absolute path to save the speaker profile') + enroll.add_argument( + '--min_enrollment_chunks', + help='Minimum number of chunks to be processed before enroll returns 100', + type=int, + default=1) test = subparsers.add_parser('test', parents=[common_parser]) test.add_argument( @@ -121,6 +122,8 @@ def main(): access_key=args.access_key, model_path=args.model_path, device=args.device, + min_enrollment_chunks=args.min_enrollment_chunks, + voice_threshold=args.voice_threshold, library_path=args.library_path) except pveagle.EagleError as e: print("Failed to initialize EagleProfiler: ", e) @@ -132,10 +135,10 @@ def main(): enroll_percentage = 0.0 for audio_path in args.enroll_audio_paths: audio = read_file(audio_path, eagle_profiler.sample_rate) - enroll_percentage, feedback = eagle_profiler.enroll(audio) - print('Enrolled audio file %s [Enrollment percentage: %.2f%% - Enrollment feedback: %s]' - % (audio_path, enroll_percentage, FEEDBACK_TO_DESCRIPTIVE_MSG[feedback])) - + for frame in range(len(audio) // eagle_profiler.frame_length): + frame = audio[frame * eagle_profiler.frame_length:(frame + 1) * eagle_profiler.frame_length] + _ = eagle_profiler.enroll(frame) + enroll_percentage = eagle_profiler.flush() if enroll_percentage < 100.0: print('Failed to create speaker profile. Insufficient enrollment percentage: %.2f%%. ' 'Please add more audio files for enrollment.' % enroll_percentage) @@ -166,8 +169,8 @@ def main(): access_key=args.access_key, model_path=args.model_path, device=args.device, - library_path=args.library_path, - speaker_profiles=speaker_profiles) + voice_threshold=args.voice_threshold, + library_path=args.library_path) except pveagle.EagleActivationLimitError: print('AccessKey has reached its processing limit.') except pveagle.EagleError as e: @@ -186,16 +189,11 @@ def main(): try: audio = read_file(args.test_audio_path, eagle.sample_rate) - num_frames = len(audio) // eagle.frame_length - frame_to_second = eagle.frame_length / eagle.sample_rate - for i in range(num_frames): - frame = audio[i * eagle.frame_length:(i + 1) * eagle.frame_length] - scores = eagle.process(frame) - time = i * frame_to_second - if csv_file is not None: - result_writer.writerow([time, *scores]) - else: - print_result(time, scores, speaker_labels) + scores = eagle.process(audio, speaker_profiles=speaker_profiles) + if csv_file is not None: + result_writer.writerow([*scores]) + else: + print_result(scores, speaker_labels) if csv_file is not None: print('Test result is saved to %s' % args.csv_output_path) diff --git a/demo/python/eagle_demo_mic.py b/demo/python/eagle_demo_mic.py index 4ccc0309..9bcf3ad9 100644 --- a/demo/python/eagle_demo_mic.py +++ b/demo/python/eagle_demo_mic.py @@ -22,14 +22,6 @@ PV_RECORDER_FRAME_LENGTH = 512 -FEEDBACK_TO_DESCRIPTIVE_MSG = { - pveagle.EagleProfilerEnrollFeedback.AUDIO_OK: 'Good audio', - pveagle.EagleProfilerEnrollFeedback.AUDIO_TOO_SHORT: 'Insufficient audio length', - pveagle.EagleProfilerEnrollFeedback.UNKNOWN_SPEAKER: 'Different speaker in audio', - pveagle.EagleProfilerEnrollFeedback.NO_VOICE_FOUND: 'No voice found in audio', - pveagle.EagleProfilerEnrollFeedback.QUALITY_ISSUE: 'Low audio quality due to bad microphone or environment' -} - class EnrollmentAnimation(threading.Thread): def __init__(self, sleep_time_sec=0.1): @@ -116,6 +108,11 @@ def main(): common_parser.add_argument( '--output_audio_path', help='If provided, all recorded audio data will be saved to the given .wav file') + common_parser.add_argument( + '--voice_threshold', + help="Sensitivity threshold for detecting voice.", + type=float, + default=0.3) subparsers = parser.add_subparsers(dest='command') @@ -124,6 +121,11 @@ def main(): '--output_profile_path', required=True, help='Absolute path to output file for the created profile') + enroll.add_argument( + '--min_enrollment_chunks', + help='Minimum number of chunks to be processed before enroll returns 100%', + type=int, + default=1) test = subparsers.add_parser( 'test', @@ -152,6 +154,8 @@ def main(): access_key=args.access_key, model_path=args.model_path, device=args.device, + min_enrollment_chunks=args.min_enrollment_chunks, + voice_threshold=args.voice_threshold, library_path=args.library_path) except pveagle.EagleError as e: print("Failed to initialize Eagle: %s" % e) @@ -160,7 +164,6 @@ def main(): print('Eagle version: %s' % eagle_profiler.version) recorder = PvRecorder(frame_length=PV_RECORDER_FRAME_LENGTH, device_index=args.audio_device_index) print("Recording audio from '%s'" % recorder.selected_device) - num_enroll_frames = eagle_profiler.min_enroll_samples // PV_RECORDER_FRAME_LENGTH sample_rate = eagle_profiler.sample_rate enrollment_animation = EnrollmentAnimation() print('Please keep speaking until the enrollment percentage reaches 100%') @@ -174,19 +177,16 @@ def main(): enroll_percentage = 0.0 enrollment_animation.start() + recorder.start() while enroll_percentage < 100.0: - enroll_pcm = list() - recorder.start() - for _ in range(num_enroll_frames): - input_frame = recorder.read() - if args.output_audio_path is not None: - enroll_audio_file.writeframes(struct.pack('%dh' % len(input_frame), *input_frame)) - enroll_pcm.extend(input_frame) - recorder.stop() - - enroll_percentage, feedback = eagle_profiler.enroll(enroll_pcm) + input_frame = recorder.read() + if args.output_audio_path is not None: + enroll_audio_file.writeframes(struct.pack('%dh' % len(input_frame), *input_frame)) + enroll_percentage = eagle_profiler.enroll(input_frame) enrollment_animation.percentage = enroll_percentage - enrollment_animation.feedback = ' - %s' % FEEDBACK_TO_DESCRIPTIVE_MSG[feedback] + enroll_percentage = eagle_profiler.flush() + enrollment_animation.percentage = enroll_percentage + recorder.stop() speaker_profile = eagle_profiler.export() enrollment_animation.stop() @@ -222,12 +222,13 @@ def main(): access_key=args.access_key, model_path=args.model_path, device=args.device, - library_path=args.library_path, - speaker_profiles=profiles) + voice_threshold=args.voice_threshold, + library_path=args.library_path) - recorder = PvRecorder(device_index=args.audio_device_index, frame_length=eagle.frame_length) + recorder = PvRecorder(device_index=args.audio_device_index, frame_length=PV_RECORDER_FRAME_LENGTH) recorder.start() + num_process_frames = eagle.min_process_samples // PV_RECORDER_FRAME_LENGTH with contextlib.ExitStack() as file_stack: if args.output_audio_path is not None: test_audio_file = file_stack.enter_context(wave.open(args.output_audio_path, 'wb')) @@ -237,11 +238,18 @@ def main(): print('Listening for audio... (press Ctrl+C to stop)') while True: - pcm = recorder.read() - if args.output_audio_path is not None: - test_audio_file.writeframes(struct.pack('%dh' % len(pcm), *pcm)) - scores = eagle.process(pcm) - print_result(scores, speaker_labels) + process_pcm = list() + recorder.start() + for _ in range(num_process_frames): + input_frame = recorder.read() + if args.output_audio_path is not None: + enroll_audio_file.writeframes(struct.pack('%dh' % len(input_frame), *input_frame)) + process_pcm.extend(input_frame) + recorder.stop() + + scores = eagle.process(process_pcm, speaker_profiles=profiles) + if scores: + print_result(scores, speaker_labels) except KeyboardInterrupt: print('\nStopping...') diff --git a/demo/python/requirements.txt b/demo/python/requirements.txt index 9ec0747c..f0e26ee6 100644 --- a/demo/python/requirements.txt +++ b/demo/python/requirements.txt @@ -1,2 +1,2 @@ -pveagle==2.0.1 +pveagle==3.0.0 pvrecorder==1.2.4 diff --git a/demo/python/setup.py b/demo/python/setup.py index 555ddc1a..a5d8bf69 100644 --- a/demo/python/setup.py +++ b/demo/python/setup.py @@ -27,7 +27,7 @@ setuptools.setup( name="pveagledemo", - version="2.0.1", + version="3.0.0", author="Picovoice", author_email="hello@picovoice.ai", description="Eagle Speaker Recognition Engine demos", diff --git a/demo/web/index.html b/demo/web/index.html index 025ea7b2..abea9733 100644 --- a/demo/web/index.html +++ b/demo/web/index.html @@ -73,7 +73,6 @@

Eagle Web Demo

Stop Test -
diff --git a/demo/web/package.json b/demo/web/package.json index 1b7d498b..933a6f4a 100644 --- a/demo/web/package.json +++ b/demo/web/package.json @@ -17,7 +17,7 @@ "author": "Picovoice Inc", "license": "Apache-2.0", "dependencies": { - "@picovoice/eagle-web": "2.0.0", + "@picovoice/eagle-web": "3.0.0", "@picovoice/web-voice-processor": "~4.0.8", "mime-types": "^2.1.35" }, diff --git a/demo/web/scripts/eagle.js b/demo/web/scripts/eagle.js index a9343a17..63469883 100644 --- a/demo/web/scripts/eagle.js +++ b/demo/web/scripts/eagle.js @@ -38,18 +38,20 @@ window.onload = function () { return; } - try { - const result = await profiler.enroll(audioFrame); - updateSpeakerProgress( - speakerProfiles.length + 1, - result.feedback, - result.percentage, - ); - percentage = result.percentage; - } catch (e) { - writeMessage(`Failed to enroll using '${f.name}'. Error: ${e}`); - return; + for (let j = 0; j + profiler.frameLength < audioFrame.length; j += profiler.frameLength) { + try { + percentage = await profiler.enroll(audioFrame.slice(j, j + profiler.frameLength)); + updateSpeakerProgress( + speakerProfiles.length + 1, + percentage, + ); + } catch (e) { + writeMessage(`Failed to enroll using '${f.name}'. Error: ${e}`); + return; + } } + + percentage = await profiler.flush(); } if (percentage < 100) { @@ -99,54 +101,43 @@ const micEnrollEngine = { onmessage: async (event) => { switch (event.data.command) { case "process": - audioData.push(event.data.inputFrame); - if (ENABLE_AUDIO_DUMP) { dumpAudio = dumpAudio.concat(event.data.inputFrame); } - if (audioData.length * 512 >= profiler.minEnrollSamples) { - let result; + let percentage = 0.0; + try { + percentage = await profiler.enroll(event.data.inputFrame); + } catch (e) { + writeMessage(`Failed to enroll. Error: ${e}`); + return; + } + + updateSpeakerProgress( + speakerProfiles.length + 1, + percentage, + ); + if (percentage === 100) { + await window.WebVoiceProcessor.WebVoiceProcessor.unsubscribe( + micEnrollEngine, + ); + clearInterval(timer); + micEnrollStopUI(); try { - const frames = new Int16Array(audioData.length * 512); - for (let i = 0; i < audioData.length; i++) { - frames.set(audioData[i], i * 512); - } - audioData = []; - result = await profiler.enroll(frames); + const profile = await profiler.export(); + speakerProfiles.push(profile); + enrollSuccessUI(); + writeMessage( + `Enrollment for Speaker ${speakerProfiles.length} complete! ` + + `You can begin testing or enroll another speaker.`, + ); } catch (e) { - writeMessage(`Failed to enroll. Error: ${e}`); - return; + writeMessage(`Failed to enroll speaker. Error: ${e}`); } - updateSpeakerProgress( - speakerProfiles.length + 1, - result.feedback, - result.percentage, - ); - if (result.percentage === 100) { - await window.WebVoiceProcessor.WebVoiceProcessor.unsubscribe( - micEnrollEngine, - ); - clearInterval(timer); - micEnrollStopUI(); - - try { - const profile = await profiler.export(); - speakerProfiles.push(profile); - enrollSuccessUI(); - writeMessage( - `Enrollment for Speaker ${speakerProfiles.length} complete! ` + - `You can begin testing or enroll another speaker.`, - ); - } catch (e) { - writeMessage(`Failed to enroll speaker. Error: ${e}`); - } - - if (ENABLE_AUDIO_DUMP) { - downloadDumpAudio("enroll.pcm"); - } + if (ENABLE_AUDIO_DUMP) { + downloadDumpAudio("enroll.pcm"); } } break; @@ -195,11 +186,8 @@ function writeMessage(message) { document.getElementById("status").innerHTML = message; } -function updateSpeakerProgress(speakerId, feedback, progress) { - const feedbackMsg = getFeedbackMessage(feedback); - console.log(progress, feedbackMsg); - document.getElementById(`speaker${speakerId}Feedback`).innerHTML = - ` ${feedbackMsg}`; +function updateSpeakerProgress(speakerId, progress) { + console.log(progress); document.getElementById(`speaker${speakerId}Progress`).value = progress; } @@ -207,21 +195,6 @@ function updateSpeakerScore(speakerId, score) { document.getElementById(`speaker${speakerId}Progress`).value = score * 100; } -function getFeedbackMessage(feedback) { - switch (feedback) { - case EagleWeb.EagleProfilerEnrollFeedback.AUDIO_TOO_SHORT: - return "Insufficient audio length"; - case EagleWeb.EagleProfilerEnrollFeedback.UNKNOWN_SPEAKER: - return "Different speaker detected in audio"; - case EagleWeb.EagleProfilerEnrollFeedback.NO_VOICE_FOUND: - return "Unable to detect voice in audio"; - case EagleWeb.EagleProfilerEnrollFeedback.QUALITY_ISSUE: - return "Audio quality too low to use for enrollment"; - default: - return "Enrolling speaker..."; - } -} - function updateSpeakerTable() { const speakerTable = document.getElementById("speakersTable"); while (speakerTable.lastElementChild) { @@ -250,7 +223,6 @@ function createSpeakerRow(i, initialProgress) { function newEnrollmentUI() { updateSpeakerTable(); document.getElementById("testContainer").style.display = "block"; - document.getElementById("feedbackText").innerHTML = ""; document .getElementById("speakersTable") .append(createSpeakerRow(speakerProfiles.length + 1, 0)); @@ -320,18 +292,34 @@ const micTestEngine = { let scores; switch (event.data.command) { case "process": + audioData.push(event.data.inputFrame); + if (ENABLE_AUDIO_DUMP) { dumpAudio = dumpAudio.concat(event.data.inputFrame); } - try { - scores = await eagle.process(event.data.inputFrame); - } catch (e) { - writeMessage(`Failed to enroll. Error: ${e}`); - return; - } - for (let i = 0; i < scores.length; i++) { - updateSpeakerScore(i + 1, scores[i]); + if (audioData.length * 512 >= eagle.minProcessSamples) { + try { + const frames = new Int16Array(audioData.length * 512); + for (let i = 0; i < audioData.length; i++) { + frames.set(audioData[i], i * 512); + } + audioData = []; + scores = await eagle.process(frames, speakerProfiles); + } catch (e) { + writeMessage(`Failed to process. Error: ${e}`); + return; + } + + if (scores) { + for (let i = 0; i < scores.length; i++) { + updateSpeakerScore(i + 1, scores[i]); + } + } else { + for (let i = 0; i < speakerProfiles.length; i++) { + updateSpeakerScore(i + 1, 0); + } + } } break; } @@ -345,7 +333,6 @@ async function startEagle(accessKey) { eagle = await EagleWeb.EagleWorker.create( accessKey, eagleModel, - speakerProfiles, ); } catch (e) { writeMessage(`Failed to initialize Eagle. Error: ${e}`); diff --git a/demo/web/yarn.lock b/demo/web/yarn.lock index 6ff0141f..824806cd 100644 --- a/demo/web/yarn.lock +++ b/demo/web/yarn.lock @@ -96,10 +96,10 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.4.2.tgz#1860473de7dfa1546767448f333db80cb0ff2161" integrity sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ== -"@picovoice/eagle-web@2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@picovoice/eagle-web/-/eagle-web-2.0.0.tgz#1253b30ee74b0eacc4e2e9a57f4372aadb9529e4" - integrity sha512-hifG0nkTbb9HyzPdm3rwiqZafq/CjPBOWatRNWDArbor4doUpLXCvRATNB7zYG5GRaoo7l/c+MExnaLBWgC2cA== +"@picovoice/eagle-web@3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@picovoice/eagle-web/-/eagle-web-3.0.0.tgz#6742ad51f421b3fdb5ae2ae86790d6bcd12d8752" + integrity sha512-yuXzftoX6tB00OMfbjezbn/5UA/v9kz8j9Yo6Y8xAZWT+3h3NIZmW3GUYCsMMORnGV3F1bGrbenKZgNDrkyLqA== dependencies: "@picovoice/web-utils" "=1.4.3" diff --git a/include/picovoice.h b/include/picovoice.h index 7e3fffc1..c7e93544 100644 --- a/include/picovoice.h +++ b/include/picovoice.h @@ -1,5 +1,5 @@ /* - Copyright 2018-2025 Picovoice Inc. + Copyright 2018-2026 Picovoice Inc. You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE" file accompanying this source. diff --git a/include/pv_eagle.h b/include/pv_eagle.h index 97db4822..6d868aa9 100644 --- a/include/pv_eagle.h +++ b/include/pv_eagle.h @@ -1,5 +1,5 @@ /* - Copyright 2021-2025 Picovoice Inc. + Copyright 2021-2026 Picovoice Inc. You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE" file accompanying this source. @@ -38,6 +38,11 @@ typedef struct pv_eagle_profiler pv_eagle_profiler_t; * To select a specific GPU device, set this argument to `gpu:${GPU_INDEX}`, where `${GPU_INDEX}` is the index of the * target GPU. If set to `cpu`, the engine will run on the CPU with the default number of threads. To specify the * number of threads, set this argument to `cpu:${NUM_THREADS}`, where `${NUM_THREADS}` is the desired number of threads. + * @param min_enrollment_chunks Minimum number of chunks to be processed before enroll returns 100%. The value should be + * a number greater than or equal to 1. A higher number results in more accurate profiles at the cost of needing more + * data to create the profile. + * @param voice_threshold Sensitivity threshold for detecting voice. The value should be a number within [0, 1]. A + * higher threshold increases detection confidence values at the cost of potentially missing frames of voice. * @param[out] object EagleProfiler object. * @return Status code. Returns `PV_STATUS_OUT_OF_MEMORY`, `PV_STATUS_IO_ERROR`, `PV_STATUS_INVALID_ARGUMENT`, * `PV_STATUS_RUNTIME_ERROR`, `PV_STATUS_ACTIVATION_ERROR`, `PV_STATUS_ACTIVATION_LIMIT_REACHED`, @@ -47,6 +52,8 @@ PV_API pv_status_t pv_eagle_profiler_init( const char *access_key, const char *model_path, const char *device, + int32_t min_enrollment_chunks, + float voice_threshold, pv_eagle_profiler_t **object); /** @@ -57,49 +64,26 @@ PV_API pv_status_t pv_eagle_profiler_init( PV_API void pv_eagle_profiler_delete(pv_eagle_profiler_t *object); /** - * Enrollment feedback codes. - */ -typedef enum { - PV_EAGLE_PROFILER_ENROLL_FEEDBACK_AUDIO_OK = 0, - PV_EAGLE_PROFILER_ENROLL_FEEDBACK_AUDIO_TOO_SHORT, - PV_EAGLE_PROFILER_ENROLL_FEEDBACK_UNKNOWN_SPEAKER, - PV_EAGLE_PROFILER_ENROLL_FEEDBACK_NO_VOICE_FOUND, - PV_EAGLE_PROFILER_ENROLL_FEEDBACK_QUALITY_ISSUE, -} pv_eagle_profiler_enroll_feedback_t; - -/** - * Provides string representations of EagleProfiler enrollment feedback codes. + * Resets the EagleProfiler object and removes all enrollment data. It must be called before enrolling a new speaker. * - * @param feedback Feedback code. - * @return String representation. + * @param object EagleProfiler object. + * @return status code. Returns `PV_STATUS_INVALID_ARGUMENT` on failure. */ -PV_API const char *pv_eagle_profiler_enroll_feedback_to_string(pv_eagle_profiler_enroll_feedback_t feedback); +PV_API pv_status_t pv_eagle_profiler_reset(pv_eagle_profiler_t *object); /** * Enrolls a speaker. This function should be called multiple times with different utterances of the same speaker * until `percentage` reaches `100.0`. Any further enrollment can be used to improve the speaker voice profile. - * The minimum number of required samples can be obtained by calling `pv_eagle_profile_min_enroll_audio_length()`. * The audio data used for enrollment should satisfy the following requirements: - * - only one speaker should be present in the audio - * - the speaker should be speaking in a normal voice - * - the audio should contain no speech from other speakers and no other sounds (e.g. music), - * - it should be captured in a quiet environment with no background noise, + * - Only one speaker should be present in the audio. + * - The speaker should be speaking in a normal voice. + * - The audio should contain no speech from other speakers and no other sounds (e.g. music). + * - It should be captured in a quiet environment with no background noise. * * @param object EagleProfiler object. - * @param pcm Audio data. The required sample rate can be attained by calling `pv_sample_rate()`. The required audio - * format is 16-bit linearly-encoded single-channel PCM. The minimum audio length required for enrollment can be attained - * by calling `pv_eagle_profiler_enroll_min_audio_length_samples()`. - * @param num_samples Number of audio samples in `pcm`. - * @param[out] feedback Feedback code. If enrollment process fails because of a bad input audio, this will be set to - * a proper feedback code indicating the cause of failure: - * - `PV_EAGLE_PROFILER_ENROLL_FEEDBACK_AUDIO_TOO_SHORT`: The audio is too short, - * i.e. it contains less than the minimum number of required samples. - * - `PV_EAGLE_PROFILER_ENROLL_FEEDBACK_UNKNOWN_SPEAKER`: The speaker is unknown, - * i.e. the speaker is not the same as the one enrolled in the previous enrollment. - * - `PV_EAGLE_PROFILER_ENROLL_FEEDBACK_NO_VOICE_FOUND`: The audio does not contain any speech. - * - `PV_EAGLE_PROFILER_ENROLL_FEEDBACK_QUALITY_ISSUE`: - * The audio is too noisy or the speaker is speaking in a low voice. -* Otherwise, it will be set to `PV_EAGLE_PROFILER_ENROLL_FEEDBACK_AUDIO_OK` + * @param pcm A frame of audio samples. The number of samples per frame can be attained by calling + * `pv_eagle_frame_length()`. The incoming audio needs to have a sample rate equal to `pv_sample_rate()` and be + * 16-bit linearly-encoded. Eagle operates on single-channel audio. * @param[out] percentage Percentage of enrollment completed. * @return Status code. Returns `PV_STATUS_OUT_OF_MEMORY`, `PV_STATUS_INVALID_ARGUMENT`, * `PV_STATUS_RUNTIME_ERROR`, `PV_STATUS_ACTIVATION_ERROR`, `PV_STATUS_ACTIVATION_LIMIT_REACHED`, @@ -108,20 +92,21 @@ PV_API const char *pv_eagle_profiler_enroll_feedback_to_string(pv_eagle_profiler PV_API pv_status_t pv_eagle_profiler_enroll( pv_eagle_profiler_t *object, const int16_t *pcm, - int32_t num_samples, - pv_eagle_profiler_enroll_feedback_t *feedback, float *percentage); /** - * Getter for the minimum length of the input pcm required by `pv_eagle_profiler_enroll()`. + * Marks the end of the audio stream, flushes internal state of the object, and returns the percentage of enrollment + * completed. * * @param object EagleProfiler object. - * @param[out] num_samples Number of samples. - * @return Status code. Returns `PV_STATUS_INVALID_ARGUMENT` on failure. + * @param[out] percentage Percentage of enrollment completed. + * @return Status code. Returns `PV_STATUS_OUT_OF_MEMORY`, `PV_STATUS_INVALID_ARGUMENT`, + * `PV_STATUS_RUNTIME_ERROR`, `PV_STATUS_ACTIVATION_ERROR`, `PV_STATUS_ACTIVATION_LIMIT_REACHED`, + * `PV_STATUS_ACTIVATION_THROTTLED`, or `PV_STATUS_ACTIVATION_REFUSED` on failure. */ -PV_API pv_status_t pv_eagle_profiler_enroll_min_audio_length_samples( - const pv_eagle_profiler_t *object, - int32_t *num_samples); +PV_API pv_status_t pv_eagle_profiler_flush( + pv_eagle_profiler_t *object, + float *percentage); /** * Determines size required for the speaker profile buffer when exporting the speaker profile. @@ -136,7 +121,7 @@ PV_API pv_status_t pv_eagle_profiler_export_size( /** * Exports the speaker profile to a buffer. - * The exported profile can be used in `pv_eagle_init()` or stored for later use. + * The exported profile can be used in `pv_eagle_process()` or stored for later use. * * @param object EagleProfiler object. * @param[out] speaker_profile Buffer where the speaker profile will be stored. Must be pre-allocated with a size @@ -149,12 +134,11 @@ PV_API pv_status_t pv_eagle_profiler_export( void *speaker_profile); /** - * Resets the EagleProfiler object and removes all enrollment data. It must be called before enrolling a new speaker. + * Getter for number of audio samples per frame. * - * @param object EagleProfiler object. - * @return status code. Returns `PV_STATUS_INVALID_ARGUMENT` on failure. + * @return Frame length. */ -PV_API pv_status_t pv_eagle_profiler_reset(pv_eagle_profiler_t *object); +PV_API int32_t pv_eagle_profiler_frame_length(void); /** * Forward declaration for Eagle Text-Independent Speaker Recognition engine. It processes incoming audio in consecutive @@ -172,8 +156,8 @@ typedef struct pv_eagle pv_eagle_t; * To select a specific GPU device, set this argument to `gpu:${GPU_INDEX}`, where `${GPU_INDEX}` is the index of the * target GPU. If set to `cpu`, the engine will run on the CPU with the default number of threads. To specify the * number of threads, set this argument to `cpu:${NUM_THREADS}`, where `${NUM_THREADS}` is the desired number of threads. - * @param num_speakers Number of speakers. - * @param speaker_profiles Speaker profiles. This can be created using the EagleProfiler object and its related functions. + * @param voice_threshold Sensitivity threshold for detecting voice. The value should be a number within [0, 1]. A + * higher threshold increases detection confidence values at the cost of potentially missing frames of voice. * @param[out] object Constructed instance of Eagle. * @return Status code. Returns `PV_STATUS_OUT_OF_MEMORY`, `PV_STATUS_IO_ERROR`, `PV_STATUS_INVALID_ARGUMENT`, * `PV_STATUS_RUNTIME_ERROR`, `PV_STATUS_ACTIVATION_ERROR`, `PV_STATUS_ACTIVATION_LIMIT_REACHED`, @@ -183,8 +167,7 @@ PV_API pv_status_t pv_eagle_init( const char *access_key, const char *model_path, const char *device, - int32_t num_speakers, - const void *const *speaker_profiles, + float voice_threshold, pv_eagle_t **object); /** @@ -194,15 +177,29 @@ PV_API pv_status_t pv_eagle_init( */ PV_API void pv_eagle_delete(pv_eagle_t *object); +/** + * Getter for the minimum length of the input pcm required by `pv_eagle_process()`. + * + * @param object Eagle object. + * @param[out] num_samples Number of samples. + * @return Status code. Returns `PV_STATUS_INVALID_ARGUMENT` on failure. + */ +PV_API pv_status_t pv_eagle_process_min_audio_length_samples( + const pv_eagle_t *object, + int32_t *num_samples); + /** * Processes a frame of the incoming audio. * * @param object Eagle object. - * @param pcm A frame of audio samples. The number of samples per frame can be attained by calling - * `pv_eagle_frame_length()`. The incoming audio needs to have a sample rate equal to `pv_sample_rate()` and be - * 16-bit linearly-encoded. Eagle operates on single-channel audio. - * @param[out] scores Similarity scores for each enrolled speaker. Must be pre-allocated with a size equal to - * the number of enrolled speakers. The scores are in the range [0, 1] with 1 being a perfect match. + * @param pcm Audio data. The required sample rate can be attained by calling `pv_sample_rate()`. The required audio + * format is 16-bit linearly-encoded single-channel PCM. The minimum audio length required for processing can be attained + * by calling `pv_eagle_process_min_audio_length_samples()`. + * @param num_samples Number of audio samples in `pcm`. + * @param speaker_profiles Speaker profiles. This can be created using the EagleProfiler object and its related functions. + * @param num_speakers Number of speakers. + * @param[out] scores Similarity scores for each enrolled speaker. The scores are in the range [0, 1] with 1 being + * maximum confidence in a perfect match. `scores` must be freed using `pv_eagle_scores_delete()`. * @return Status code. Returns `PV_STATUS_OUT_OF_MEMORY`, `PV_STATUS_INVALID_ARGUMENT`, * `PV_STATUS_RUNTIME_ERROR`, `PV_STATUS_ACTIVATION_ERROR`, `PV_STATUS_ACTIVATION_LIMIT_REACHED`, * `PV_STATUS_ACTIVATION_THROTTLED`, or `PV_STATUS_ACTIVATION_REFUSED` on failure. @@ -210,21 +207,17 @@ PV_API void pv_eagle_delete(pv_eagle_t *object); PV_API pv_status_t pv_eagle_process( pv_eagle_t *object, const int16_t *pcm, - float *scores); - -/** - * Resets the internal state of the Eagle engine. It must be called before processing a new sequence of audio frames. - * @param object Eagle object. - * @return Status code. Returns `PV_STATUS_INVALID_ARGUMENT` on failure. - */ -PV_API pv_status_t pv_eagle_reset(pv_eagle_t *object); + int32_t num_samples, + void **speaker_profiles, + int32_t num_speakers, + float **scores); /** - * Getter for number of audio samples per frame. + * Deletes scores returned from `pv_eagle_process()` * - * @return Frame length. + * @param scores scores array returned from `pv_eagle_process()` */ -PV_API int32_t pv_eagle_frame_length(void); +PV_API void pv_eagle_scores_delete(float *scores); /** * Getter for version. @@ -256,7 +249,7 @@ PV_API pv_status_t pv_eagle_list_hardware_devices( PV_API void pv_eagle_free_hardware_devices( char **hardware_devices, int32_t num_hardware_devices); - + #ifdef __cplusplus } diff --git a/lib/android/arm64-v8a/libpv_eagle.so b/lib/android/arm64-v8a/libpv_eagle.so index d43a2192..c5d8eeb6 100755 Binary files a/lib/android/arm64-v8a/libpv_eagle.so and b/lib/android/arm64-v8a/libpv_eagle.so differ diff --git a/lib/android/armeabi-v7a/libpv_eagle.so b/lib/android/armeabi-v7a/libpv_eagle.so index 4b1c7465..5a719ef6 100755 Binary files a/lib/android/armeabi-v7a/libpv_eagle.so and b/lib/android/armeabi-v7a/libpv_eagle.so differ diff --git a/lib/android/x86/libpv_eagle.so b/lib/android/x86/libpv_eagle.so index 9524f928..2ce21ef4 100755 Binary files a/lib/android/x86/libpv_eagle.so and b/lib/android/x86/libpv_eagle.so differ diff --git a/lib/android/x86_64/libpv_eagle.so b/lib/android/x86_64/libpv_eagle.so index d5c78c5a..77f273da 100755 Binary files a/lib/android/x86_64/libpv_eagle.so and b/lib/android/x86_64/libpv_eagle.so differ diff --git a/lib/common/eagle_params.pv b/lib/common/eagle_params.pv index 59c37dd5..a9b518b5 100644 Binary files a/lib/common/eagle_params.pv and b/lib/common/eagle_params.pv differ diff --git a/lib/ios/PvEagle.xcframework/ios-arm64/PvEagle.framework/Headers/picovoice.h b/lib/ios/PvEagle.xcframework/ios-arm64/PvEagle.framework/Headers/picovoice.h index 5dd48f9d..edd627cf 100644 --- a/lib/ios/PvEagle.xcframework/ios-arm64/PvEagle.framework/Headers/picovoice.h +++ b/lib/ios/PvEagle.xcframework/ios-arm64/PvEagle.framework/Headers/picovoice.h @@ -1,5 +1,5 @@ /* - Copyright 2018-2025 Picovoice Inc. + Copyright 2018-2026 Picovoice Inc. You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE" file accompanying this source. @@ -79,6 +79,10 @@ PV_API void pv_free_error_stack(char **message_stack); PV_API void pv_set_sdk(const char *sdk); +PV_API const char *pv_get_sdk(void); + +PV_API void pv_free(void *p); + #ifdef __cplusplus } diff --git a/lib/ios/PvEagle.xcframework/ios-arm64/PvEagle.framework/Headers/pv_eagle.h b/lib/ios/PvEagle.xcframework/ios-arm64/PvEagle.framework/Headers/pv_eagle.h index 97db4822..6d868aa9 100644 --- a/lib/ios/PvEagle.xcframework/ios-arm64/PvEagle.framework/Headers/pv_eagle.h +++ b/lib/ios/PvEagle.xcframework/ios-arm64/PvEagle.framework/Headers/pv_eagle.h @@ -1,5 +1,5 @@ /* - Copyright 2021-2025 Picovoice Inc. + Copyright 2021-2026 Picovoice Inc. You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE" file accompanying this source. @@ -38,6 +38,11 @@ typedef struct pv_eagle_profiler pv_eagle_profiler_t; * To select a specific GPU device, set this argument to `gpu:${GPU_INDEX}`, where `${GPU_INDEX}` is the index of the * target GPU. If set to `cpu`, the engine will run on the CPU with the default number of threads. To specify the * number of threads, set this argument to `cpu:${NUM_THREADS}`, where `${NUM_THREADS}` is the desired number of threads. + * @param min_enrollment_chunks Minimum number of chunks to be processed before enroll returns 100%. The value should be + * a number greater than or equal to 1. A higher number results in more accurate profiles at the cost of needing more + * data to create the profile. + * @param voice_threshold Sensitivity threshold for detecting voice. The value should be a number within [0, 1]. A + * higher threshold increases detection confidence values at the cost of potentially missing frames of voice. * @param[out] object EagleProfiler object. * @return Status code. Returns `PV_STATUS_OUT_OF_MEMORY`, `PV_STATUS_IO_ERROR`, `PV_STATUS_INVALID_ARGUMENT`, * `PV_STATUS_RUNTIME_ERROR`, `PV_STATUS_ACTIVATION_ERROR`, `PV_STATUS_ACTIVATION_LIMIT_REACHED`, @@ -47,6 +52,8 @@ PV_API pv_status_t pv_eagle_profiler_init( const char *access_key, const char *model_path, const char *device, + int32_t min_enrollment_chunks, + float voice_threshold, pv_eagle_profiler_t **object); /** @@ -57,49 +64,26 @@ PV_API pv_status_t pv_eagle_profiler_init( PV_API void pv_eagle_profiler_delete(pv_eagle_profiler_t *object); /** - * Enrollment feedback codes. - */ -typedef enum { - PV_EAGLE_PROFILER_ENROLL_FEEDBACK_AUDIO_OK = 0, - PV_EAGLE_PROFILER_ENROLL_FEEDBACK_AUDIO_TOO_SHORT, - PV_EAGLE_PROFILER_ENROLL_FEEDBACK_UNKNOWN_SPEAKER, - PV_EAGLE_PROFILER_ENROLL_FEEDBACK_NO_VOICE_FOUND, - PV_EAGLE_PROFILER_ENROLL_FEEDBACK_QUALITY_ISSUE, -} pv_eagle_profiler_enroll_feedback_t; - -/** - * Provides string representations of EagleProfiler enrollment feedback codes. + * Resets the EagleProfiler object and removes all enrollment data. It must be called before enrolling a new speaker. * - * @param feedback Feedback code. - * @return String representation. + * @param object EagleProfiler object. + * @return status code. Returns `PV_STATUS_INVALID_ARGUMENT` on failure. */ -PV_API const char *pv_eagle_profiler_enroll_feedback_to_string(pv_eagle_profiler_enroll_feedback_t feedback); +PV_API pv_status_t pv_eagle_profiler_reset(pv_eagle_profiler_t *object); /** * Enrolls a speaker. This function should be called multiple times with different utterances of the same speaker * until `percentage` reaches `100.0`. Any further enrollment can be used to improve the speaker voice profile. - * The minimum number of required samples can be obtained by calling `pv_eagle_profile_min_enroll_audio_length()`. * The audio data used for enrollment should satisfy the following requirements: - * - only one speaker should be present in the audio - * - the speaker should be speaking in a normal voice - * - the audio should contain no speech from other speakers and no other sounds (e.g. music), - * - it should be captured in a quiet environment with no background noise, + * - Only one speaker should be present in the audio. + * - The speaker should be speaking in a normal voice. + * - The audio should contain no speech from other speakers and no other sounds (e.g. music). + * - It should be captured in a quiet environment with no background noise. * * @param object EagleProfiler object. - * @param pcm Audio data. The required sample rate can be attained by calling `pv_sample_rate()`. The required audio - * format is 16-bit linearly-encoded single-channel PCM. The minimum audio length required for enrollment can be attained - * by calling `pv_eagle_profiler_enroll_min_audio_length_samples()`. - * @param num_samples Number of audio samples in `pcm`. - * @param[out] feedback Feedback code. If enrollment process fails because of a bad input audio, this will be set to - * a proper feedback code indicating the cause of failure: - * - `PV_EAGLE_PROFILER_ENROLL_FEEDBACK_AUDIO_TOO_SHORT`: The audio is too short, - * i.e. it contains less than the minimum number of required samples. - * - `PV_EAGLE_PROFILER_ENROLL_FEEDBACK_UNKNOWN_SPEAKER`: The speaker is unknown, - * i.e. the speaker is not the same as the one enrolled in the previous enrollment. - * - `PV_EAGLE_PROFILER_ENROLL_FEEDBACK_NO_VOICE_FOUND`: The audio does not contain any speech. - * - `PV_EAGLE_PROFILER_ENROLL_FEEDBACK_QUALITY_ISSUE`: - * The audio is too noisy or the speaker is speaking in a low voice. -* Otherwise, it will be set to `PV_EAGLE_PROFILER_ENROLL_FEEDBACK_AUDIO_OK` + * @param pcm A frame of audio samples. The number of samples per frame can be attained by calling + * `pv_eagle_frame_length()`. The incoming audio needs to have a sample rate equal to `pv_sample_rate()` and be + * 16-bit linearly-encoded. Eagle operates on single-channel audio. * @param[out] percentage Percentage of enrollment completed. * @return Status code. Returns `PV_STATUS_OUT_OF_MEMORY`, `PV_STATUS_INVALID_ARGUMENT`, * `PV_STATUS_RUNTIME_ERROR`, `PV_STATUS_ACTIVATION_ERROR`, `PV_STATUS_ACTIVATION_LIMIT_REACHED`, @@ -108,20 +92,21 @@ PV_API const char *pv_eagle_profiler_enroll_feedback_to_string(pv_eagle_profiler PV_API pv_status_t pv_eagle_profiler_enroll( pv_eagle_profiler_t *object, const int16_t *pcm, - int32_t num_samples, - pv_eagle_profiler_enroll_feedback_t *feedback, float *percentage); /** - * Getter for the minimum length of the input pcm required by `pv_eagle_profiler_enroll()`. + * Marks the end of the audio stream, flushes internal state of the object, and returns the percentage of enrollment + * completed. * * @param object EagleProfiler object. - * @param[out] num_samples Number of samples. - * @return Status code. Returns `PV_STATUS_INVALID_ARGUMENT` on failure. + * @param[out] percentage Percentage of enrollment completed. + * @return Status code. Returns `PV_STATUS_OUT_OF_MEMORY`, `PV_STATUS_INVALID_ARGUMENT`, + * `PV_STATUS_RUNTIME_ERROR`, `PV_STATUS_ACTIVATION_ERROR`, `PV_STATUS_ACTIVATION_LIMIT_REACHED`, + * `PV_STATUS_ACTIVATION_THROTTLED`, or `PV_STATUS_ACTIVATION_REFUSED` on failure. */ -PV_API pv_status_t pv_eagle_profiler_enroll_min_audio_length_samples( - const pv_eagle_profiler_t *object, - int32_t *num_samples); +PV_API pv_status_t pv_eagle_profiler_flush( + pv_eagle_profiler_t *object, + float *percentage); /** * Determines size required for the speaker profile buffer when exporting the speaker profile. @@ -136,7 +121,7 @@ PV_API pv_status_t pv_eagle_profiler_export_size( /** * Exports the speaker profile to a buffer. - * The exported profile can be used in `pv_eagle_init()` or stored for later use. + * The exported profile can be used in `pv_eagle_process()` or stored for later use. * * @param object EagleProfiler object. * @param[out] speaker_profile Buffer where the speaker profile will be stored. Must be pre-allocated with a size @@ -149,12 +134,11 @@ PV_API pv_status_t pv_eagle_profiler_export( void *speaker_profile); /** - * Resets the EagleProfiler object and removes all enrollment data. It must be called before enrolling a new speaker. + * Getter for number of audio samples per frame. * - * @param object EagleProfiler object. - * @return status code. Returns `PV_STATUS_INVALID_ARGUMENT` on failure. + * @return Frame length. */ -PV_API pv_status_t pv_eagle_profiler_reset(pv_eagle_profiler_t *object); +PV_API int32_t pv_eagle_profiler_frame_length(void); /** * Forward declaration for Eagle Text-Independent Speaker Recognition engine. It processes incoming audio in consecutive @@ -172,8 +156,8 @@ typedef struct pv_eagle pv_eagle_t; * To select a specific GPU device, set this argument to `gpu:${GPU_INDEX}`, where `${GPU_INDEX}` is the index of the * target GPU. If set to `cpu`, the engine will run on the CPU with the default number of threads. To specify the * number of threads, set this argument to `cpu:${NUM_THREADS}`, where `${NUM_THREADS}` is the desired number of threads. - * @param num_speakers Number of speakers. - * @param speaker_profiles Speaker profiles. This can be created using the EagleProfiler object and its related functions. + * @param voice_threshold Sensitivity threshold for detecting voice. The value should be a number within [0, 1]. A + * higher threshold increases detection confidence values at the cost of potentially missing frames of voice. * @param[out] object Constructed instance of Eagle. * @return Status code. Returns `PV_STATUS_OUT_OF_MEMORY`, `PV_STATUS_IO_ERROR`, `PV_STATUS_INVALID_ARGUMENT`, * `PV_STATUS_RUNTIME_ERROR`, `PV_STATUS_ACTIVATION_ERROR`, `PV_STATUS_ACTIVATION_LIMIT_REACHED`, @@ -183,8 +167,7 @@ PV_API pv_status_t pv_eagle_init( const char *access_key, const char *model_path, const char *device, - int32_t num_speakers, - const void *const *speaker_profiles, + float voice_threshold, pv_eagle_t **object); /** @@ -194,15 +177,29 @@ PV_API pv_status_t pv_eagle_init( */ PV_API void pv_eagle_delete(pv_eagle_t *object); +/** + * Getter for the minimum length of the input pcm required by `pv_eagle_process()`. + * + * @param object Eagle object. + * @param[out] num_samples Number of samples. + * @return Status code. Returns `PV_STATUS_INVALID_ARGUMENT` on failure. + */ +PV_API pv_status_t pv_eagle_process_min_audio_length_samples( + const pv_eagle_t *object, + int32_t *num_samples); + /** * Processes a frame of the incoming audio. * * @param object Eagle object. - * @param pcm A frame of audio samples. The number of samples per frame can be attained by calling - * `pv_eagle_frame_length()`. The incoming audio needs to have a sample rate equal to `pv_sample_rate()` and be - * 16-bit linearly-encoded. Eagle operates on single-channel audio. - * @param[out] scores Similarity scores for each enrolled speaker. Must be pre-allocated with a size equal to - * the number of enrolled speakers. The scores are in the range [0, 1] with 1 being a perfect match. + * @param pcm Audio data. The required sample rate can be attained by calling `pv_sample_rate()`. The required audio + * format is 16-bit linearly-encoded single-channel PCM. The minimum audio length required for processing can be attained + * by calling `pv_eagle_process_min_audio_length_samples()`. + * @param num_samples Number of audio samples in `pcm`. + * @param speaker_profiles Speaker profiles. This can be created using the EagleProfiler object and its related functions. + * @param num_speakers Number of speakers. + * @param[out] scores Similarity scores for each enrolled speaker. The scores are in the range [0, 1] with 1 being + * maximum confidence in a perfect match. `scores` must be freed using `pv_eagle_scores_delete()`. * @return Status code. Returns `PV_STATUS_OUT_OF_MEMORY`, `PV_STATUS_INVALID_ARGUMENT`, * `PV_STATUS_RUNTIME_ERROR`, `PV_STATUS_ACTIVATION_ERROR`, `PV_STATUS_ACTIVATION_LIMIT_REACHED`, * `PV_STATUS_ACTIVATION_THROTTLED`, or `PV_STATUS_ACTIVATION_REFUSED` on failure. @@ -210,21 +207,17 @@ PV_API void pv_eagle_delete(pv_eagle_t *object); PV_API pv_status_t pv_eagle_process( pv_eagle_t *object, const int16_t *pcm, - float *scores); - -/** - * Resets the internal state of the Eagle engine. It must be called before processing a new sequence of audio frames. - * @param object Eagle object. - * @return Status code. Returns `PV_STATUS_INVALID_ARGUMENT` on failure. - */ -PV_API pv_status_t pv_eagle_reset(pv_eagle_t *object); + int32_t num_samples, + void **speaker_profiles, + int32_t num_speakers, + float **scores); /** - * Getter for number of audio samples per frame. + * Deletes scores returned from `pv_eagle_process()` * - * @return Frame length. + * @param scores scores array returned from `pv_eagle_process()` */ -PV_API int32_t pv_eagle_frame_length(void); +PV_API void pv_eagle_scores_delete(float *scores); /** * Getter for version. @@ -256,7 +249,7 @@ PV_API pv_status_t pv_eagle_list_hardware_devices( PV_API void pv_eagle_free_hardware_devices( char **hardware_devices, int32_t num_hardware_devices); - + #ifdef __cplusplus } diff --git a/lib/ios/PvEagle.xcframework/ios-arm64/PvEagle.framework/Info.plist b/lib/ios/PvEagle.xcframework/ios-arm64/PvEagle.framework/Info.plist index 247505db..066777df 100644 Binary files a/lib/ios/PvEagle.xcframework/ios-arm64/PvEagle.framework/Info.plist and b/lib/ios/PvEagle.xcframework/ios-arm64/PvEagle.framework/Info.plist differ diff --git a/lib/ios/PvEagle.xcframework/ios-arm64/PvEagle.framework/PvEagle b/lib/ios/PvEagle.xcframework/ios-arm64/PvEagle.framework/PvEagle index 2a69c64f..a0ef5d1d 100755 Binary files a/lib/ios/PvEagle.xcframework/ios-arm64/PvEagle.framework/PvEagle and b/lib/ios/PvEagle.xcframework/ios-arm64/PvEagle.framework/PvEagle differ diff --git a/lib/ios/PvEagle.xcframework/ios-arm64_x86_64-simulator/PvEagle.framework/Headers/picovoice.h b/lib/ios/PvEagle.xcframework/ios-arm64_x86_64-simulator/PvEagle.framework/Headers/picovoice.h index 38f044b5..edd627cf 100644 --- a/lib/ios/PvEagle.xcframework/ios-arm64_x86_64-simulator/PvEagle.framework/Headers/picovoice.h +++ b/lib/ios/PvEagle.xcframework/ios-arm64_x86_64-simulator/PvEagle.framework/Headers/picovoice.h @@ -1,5 +1,5 @@ /* - Copyright 2018-2023 Picovoice Inc. + Copyright 2018-2026 Picovoice Inc. You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE" file accompanying this source. @@ -79,6 +79,10 @@ PV_API void pv_free_error_stack(char **message_stack); PV_API void pv_set_sdk(const char *sdk); +PV_API const char *pv_get_sdk(void); + +PV_API void pv_free(void *p); + #ifdef __cplusplus } diff --git a/lib/ios/PvEagle.xcframework/ios-arm64_x86_64-simulator/PvEagle.framework/Headers/pv_eagle.h b/lib/ios/PvEagle.xcframework/ios-arm64_x86_64-simulator/PvEagle.framework/Headers/pv_eagle.h index 97db4822..6d868aa9 100644 --- a/lib/ios/PvEagle.xcframework/ios-arm64_x86_64-simulator/PvEagle.framework/Headers/pv_eagle.h +++ b/lib/ios/PvEagle.xcframework/ios-arm64_x86_64-simulator/PvEagle.framework/Headers/pv_eagle.h @@ -1,5 +1,5 @@ /* - Copyright 2021-2025 Picovoice Inc. + Copyright 2021-2026 Picovoice Inc. You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE" file accompanying this source. @@ -38,6 +38,11 @@ typedef struct pv_eagle_profiler pv_eagle_profiler_t; * To select a specific GPU device, set this argument to `gpu:${GPU_INDEX}`, where `${GPU_INDEX}` is the index of the * target GPU. If set to `cpu`, the engine will run on the CPU with the default number of threads. To specify the * number of threads, set this argument to `cpu:${NUM_THREADS}`, where `${NUM_THREADS}` is the desired number of threads. + * @param min_enrollment_chunks Minimum number of chunks to be processed before enroll returns 100%. The value should be + * a number greater than or equal to 1. A higher number results in more accurate profiles at the cost of needing more + * data to create the profile. + * @param voice_threshold Sensitivity threshold for detecting voice. The value should be a number within [0, 1]. A + * higher threshold increases detection confidence values at the cost of potentially missing frames of voice. * @param[out] object EagleProfiler object. * @return Status code. Returns `PV_STATUS_OUT_OF_MEMORY`, `PV_STATUS_IO_ERROR`, `PV_STATUS_INVALID_ARGUMENT`, * `PV_STATUS_RUNTIME_ERROR`, `PV_STATUS_ACTIVATION_ERROR`, `PV_STATUS_ACTIVATION_LIMIT_REACHED`, @@ -47,6 +52,8 @@ PV_API pv_status_t pv_eagle_profiler_init( const char *access_key, const char *model_path, const char *device, + int32_t min_enrollment_chunks, + float voice_threshold, pv_eagle_profiler_t **object); /** @@ -57,49 +64,26 @@ PV_API pv_status_t pv_eagle_profiler_init( PV_API void pv_eagle_profiler_delete(pv_eagle_profiler_t *object); /** - * Enrollment feedback codes. - */ -typedef enum { - PV_EAGLE_PROFILER_ENROLL_FEEDBACK_AUDIO_OK = 0, - PV_EAGLE_PROFILER_ENROLL_FEEDBACK_AUDIO_TOO_SHORT, - PV_EAGLE_PROFILER_ENROLL_FEEDBACK_UNKNOWN_SPEAKER, - PV_EAGLE_PROFILER_ENROLL_FEEDBACK_NO_VOICE_FOUND, - PV_EAGLE_PROFILER_ENROLL_FEEDBACK_QUALITY_ISSUE, -} pv_eagle_profiler_enroll_feedback_t; - -/** - * Provides string representations of EagleProfiler enrollment feedback codes. + * Resets the EagleProfiler object and removes all enrollment data. It must be called before enrolling a new speaker. * - * @param feedback Feedback code. - * @return String representation. + * @param object EagleProfiler object. + * @return status code. Returns `PV_STATUS_INVALID_ARGUMENT` on failure. */ -PV_API const char *pv_eagle_profiler_enroll_feedback_to_string(pv_eagle_profiler_enroll_feedback_t feedback); +PV_API pv_status_t pv_eagle_profiler_reset(pv_eagle_profiler_t *object); /** * Enrolls a speaker. This function should be called multiple times with different utterances of the same speaker * until `percentage` reaches `100.0`. Any further enrollment can be used to improve the speaker voice profile. - * The minimum number of required samples can be obtained by calling `pv_eagle_profile_min_enroll_audio_length()`. * The audio data used for enrollment should satisfy the following requirements: - * - only one speaker should be present in the audio - * - the speaker should be speaking in a normal voice - * - the audio should contain no speech from other speakers and no other sounds (e.g. music), - * - it should be captured in a quiet environment with no background noise, + * - Only one speaker should be present in the audio. + * - The speaker should be speaking in a normal voice. + * - The audio should contain no speech from other speakers and no other sounds (e.g. music). + * - It should be captured in a quiet environment with no background noise. * * @param object EagleProfiler object. - * @param pcm Audio data. The required sample rate can be attained by calling `pv_sample_rate()`. The required audio - * format is 16-bit linearly-encoded single-channel PCM. The minimum audio length required for enrollment can be attained - * by calling `pv_eagle_profiler_enroll_min_audio_length_samples()`. - * @param num_samples Number of audio samples in `pcm`. - * @param[out] feedback Feedback code. If enrollment process fails because of a bad input audio, this will be set to - * a proper feedback code indicating the cause of failure: - * - `PV_EAGLE_PROFILER_ENROLL_FEEDBACK_AUDIO_TOO_SHORT`: The audio is too short, - * i.e. it contains less than the minimum number of required samples. - * - `PV_EAGLE_PROFILER_ENROLL_FEEDBACK_UNKNOWN_SPEAKER`: The speaker is unknown, - * i.e. the speaker is not the same as the one enrolled in the previous enrollment. - * - `PV_EAGLE_PROFILER_ENROLL_FEEDBACK_NO_VOICE_FOUND`: The audio does not contain any speech. - * - `PV_EAGLE_PROFILER_ENROLL_FEEDBACK_QUALITY_ISSUE`: - * The audio is too noisy or the speaker is speaking in a low voice. -* Otherwise, it will be set to `PV_EAGLE_PROFILER_ENROLL_FEEDBACK_AUDIO_OK` + * @param pcm A frame of audio samples. The number of samples per frame can be attained by calling + * `pv_eagle_frame_length()`. The incoming audio needs to have a sample rate equal to `pv_sample_rate()` and be + * 16-bit linearly-encoded. Eagle operates on single-channel audio. * @param[out] percentage Percentage of enrollment completed. * @return Status code. Returns `PV_STATUS_OUT_OF_MEMORY`, `PV_STATUS_INVALID_ARGUMENT`, * `PV_STATUS_RUNTIME_ERROR`, `PV_STATUS_ACTIVATION_ERROR`, `PV_STATUS_ACTIVATION_LIMIT_REACHED`, @@ -108,20 +92,21 @@ PV_API const char *pv_eagle_profiler_enroll_feedback_to_string(pv_eagle_profiler PV_API pv_status_t pv_eagle_profiler_enroll( pv_eagle_profiler_t *object, const int16_t *pcm, - int32_t num_samples, - pv_eagle_profiler_enroll_feedback_t *feedback, float *percentage); /** - * Getter for the minimum length of the input pcm required by `pv_eagle_profiler_enroll()`. + * Marks the end of the audio stream, flushes internal state of the object, and returns the percentage of enrollment + * completed. * * @param object EagleProfiler object. - * @param[out] num_samples Number of samples. - * @return Status code. Returns `PV_STATUS_INVALID_ARGUMENT` on failure. + * @param[out] percentage Percentage of enrollment completed. + * @return Status code. Returns `PV_STATUS_OUT_OF_MEMORY`, `PV_STATUS_INVALID_ARGUMENT`, + * `PV_STATUS_RUNTIME_ERROR`, `PV_STATUS_ACTIVATION_ERROR`, `PV_STATUS_ACTIVATION_LIMIT_REACHED`, + * `PV_STATUS_ACTIVATION_THROTTLED`, or `PV_STATUS_ACTIVATION_REFUSED` on failure. */ -PV_API pv_status_t pv_eagle_profiler_enroll_min_audio_length_samples( - const pv_eagle_profiler_t *object, - int32_t *num_samples); +PV_API pv_status_t pv_eagle_profiler_flush( + pv_eagle_profiler_t *object, + float *percentage); /** * Determines size required for the speaker profile buffer when exporting the speaker profile. @@ -136,7 +121,7 @@ PV_API pv_status_t pv_eagle_profiler_export_size( /** * Exports the speaker profile to a buffer. - * The exported profile can be used in `pv_eagle_init()` or stored for later use. + * The exported profile can be used in `pv_eagle_process()` or stored for later use. * * @param object EagleProfiler object. * @param[out] speaker_profile Buffer where the speaker profile will be stored. Must be pre-allocated with a size @@ -149,12 +134,11 @@ PV_API pv_status_t pv_eagle_profiler_export( void *speaker_profile); /** - * Resets the EagleProfiler object and removes all enrollment data. It must be called before enrolling a new speaker. + * Getter for number of audio samples per frame. * - * @param object EagleProfiler object. - * @return status code. Returns `PV_STATUS_INVALID_ARGUMENT` on failure. + * @return Frame length. */ -PV_API pv_status_t pv_eagle_profiler_reset(pv_eagle_profiler_t *object); +PV_API int32_t pv_eagle_profiler_frame_length(void); /** * Forward declaration for Eagle Text-Independent Speaker Recognition engine. It processes incoming audio in consecutive @@ -172,8 +156,8 @@ typedef struct pv_eagle pv_eagle_t; * To select a specific GPU device, set this argument to `gpu:${GPU_INDEX}`, where `${GPU_INDEX}` is the index of the * target GPU. If set to `cpu`, the engine will run on the CPU with the default number of threads. To specify the * number of threads, set this argument to `cpu:${NUM_THREADS}`, where `${NUM_THREADS}` is the desired number of threads. - * @param num_speakers Number of speakers. - * @param speaker_profiles Speaker profiles. This can be created using the EagleProfiler object and its related functions. + * @param voice_threshold Sensitivity threshold for detecting voice. The value should be a number within [0, 1]. A + * higher threshold increases detection confidence values at the cost of potentially missing frames of voice. * @param[out] object Constructed instance of Eagle. * @return Status code. Returns `PV_STATUS_OUT_OF_MEMORY`, `PV_STATUS_IO_ERROR`, `PV_STATUS_INVALID_ARGUMENT`, * `PV_STATUS_RUNTIME_ERROR`, `PV_STATUS_ACTIVATION_ERROR`, `PV_STATUS_ACTIVATION_LIMIT_REACHED`, @@ -183,8 +167,7 @@ PV_API pv_status_t pv_eagle_init( const char *access_key, const char *model_path, const char *device, - int32_t num_speakers, - const void *const *speaker_profiles, + float voice_threshold, pv_eagle_t **object); /** @@ -194,15 +177,29 @@ PV_API pv_status_t pv_eagle_init( */ PV_API void pv_eagle_delete(pv_eagle_t *object); +/** + * Getter for the minimum length of the input pcm required by `pv_eagle_process()`. + * + * @param object Eagle object. + * @param[out] num_samples Number of samples. + * @return Status code. Returns `PV_STATUS_INVALID_ARGUMENT` on failure. + */ +PV_API pv_status_t pv_eagle_process_min_audio_length_samples( + const pv_eagle_t *object, + int32_t *num_samples); + /** * Processes a frame of the incoming audio. * * @param object Eagle object. - * @param pcm A frame of audio samples. The number of samples per frame can be attained by calling - * `pv_eagle_frame_length()`. The incoming audio needs to have a sample rate equal to `pv_sample_rate()` and be - * 16-bit linearly-encoded. Eagle operates on single-channel audio. - * @param[out] scores Similarity scores for each enrolled speaker. Must be pre-allocated with a size equal to - * the number of enrolled speakers. The scores are in the range [0, 1] with 1 being a perfect match. + * @param pcm Audio data. The required sample rate can be attained by calling `pv_sample_rate()`. The required audio + * format is 16-bit linearly-encoded single-channel PCM. The minimum audio length required for processing can be attained + * by calling `pv_eagle_process_min_audio_length_samples()`. + * @param num_samples Number of audio samples in `pcm`. + * @param speaker_profiles Speaker profiles. This can be created using the EagleProfiler object and its related functions. + * @param num_speakers Number of speakers. + * @param[out] scores Similarity scores for each enrolled speaker. The scores are in the range [0, 1] with 1 being + * maximum confidence in a perfect match. `scores` must be freed using `pv_eagle_scores_delete()`. * @return Status code. Returns `PV_STATUS_OUT_OF_MEMORY`, `PV_STATUS_INVALID_ARGUMENT`, * `PV_STATUS_RUNTIME_ERROR`, `PV_STATUS_ACTIVATION_ERROR`, `PV_STATUS_ACTIVATION_LIMIT_REACHED`, * `PV_STATUS_ACTIVATION_THROTTLED`, or `PV_STATUS_ACTIVATION_REFUSED` on failure. @@ -210,21 +207,17 @@ PV_API void pv_eagle_delete(pv_eagle_t *object); PV_API pv_status_t pv_eagle_process( pv_eagle_t *object, const int16_t *pcm, - float *scores); - -/** - * Resets the internal state of the Eagle engine. It must be called before processing a new sequence of audio frames. - * @param object Eagle object. - * @return Status code. Returns `PV_STATUS_INVALID_ARGUMENT` on failure. - */ -PV_API pv_status_t pv_eagle_reset(pv_eagle_t *object); + int32_t num_samples, + void **speaker_profiles, + int32_t num_speakers, + float **scores); /** - * Getter for number of audio samples per frame. + * Deletes scores returned from `pv_eagle_process()` * - * @return Frame length. + * @param scores scores array returned from `pv_eagle_process()` */ -PV_API int32_t pv_eagle_frame_length(void); +PV_API void pv_eagle_scores_delete(float *scores); /** * Getter for version. @@ -256,7 +249,7 @@ PV_API pv_status_t pv_eagle_list_hardware_devices( PV_API void pv_eagle_free_hardware_devices( char **hardware_devices, int32_t num_hardware_devices); - + #ifdef __cplusplus } diff --git a/lib/ios/PvEagle.xcframework/ios-arm64_x86_64-simulator/PvEagle.framework/Info.plist b/lib/ios/PvEagle.xcframework/ios-arm64_x86_64-simulator/PvEagle.framework/Info.plist index 450d2d73..35475b25 100644 Binary files a/lib/ios/PvEagle.xcframework/ios-arm64_x86_64-simulator/PvEagle.framework/Info.plist and b/lib/ios/PvEagle.xcframework/ios-arm64_x86_64-simulator/PvEagle.framework/Info.plist differ diff --git a/lib/ios/PvEagle.xcframework/ios-arm64_x86_64-simulator/PvEagle.framework/PvEagle b/lib/ios/PvEagle.xcframework/ios-arm64_x86_64-simulator/PvEagle.framework/PvEagle index 55aec8ac..8ccb8dcc 100755 Binary files a/lib/ios/PvEagle.xcframework/ios-arm64_x86_64-simulator/PvEagle.framework/PvEagle and b/lib/ios/PvEagle.xcframework/ios-arm64_x86_64-simulator/PvEagle.framework/PvEagle differ diff --git a/lib/linux/x86_64/libpv_eagle.so b/lib/linux/x86_64/libpv_eagle.so index 357208e9..e974cf74 100755 Binary files a/lib/linux/x86_64/libpv_eagle.so and b/lib/linux/x86_64/libpv_eagle.so differ diff --git a/lib/mac/arm64/libpv_eagle.dylib b/lib/mac/arm64/libpv_eagle.dylib index fd18b5bf..9b9c8553 100755 Binary files a/lib/mac/arm64/libpv_eagle.dylib and b/lib/mac/arm64/libpv_eagle.dylib differ diff --git a/lib/mac/x86_64/libpv_eagle.dylib b/lib/mac/x86_64/libpv_eagle.dylib index f09dafa2..124cea97 100755 Binary files a/lib/mac/x86_64/libpv_eagle.dylib and b/lib/mac/x86_64/libpv_eagle.dylib differ diff --git a/lib/node/linux/x86_64/pv_eagle.node b/lib/node/linux/x86_64/pv_eagle.node index e8d785dd..9c9154dc 100755 Binary files a/lib/node/linux/x86_64/pv_eagle.node and b/lib/node/linux/x86_64/pv_eagle.node differ diff --git a/lib/node/mac/arm64/pv_eagle.node b/lib/node/mac/arm64/pv_eagle.node index b5b8835e..3db892b8 100755 Binary files a/lib/node/mac/arm64/pv_eagle.node and b/lib/node/mac/arm64/pv_eagle.node differ diff --git a/lib/node/mac/x86_64/pv_eagle.node b/lib/node/mac/x86_64/pv_eagle.node index c6a9fc56..a4529610 100755 Binary files a/lib/node/mac/x86_64/pv_eagle.node and b/lib/node/mac/x86_64/pv_eagle.node differ diff --git a/lib/node/raspberry-pi/cortex-a53-aarch64/pv_eagle.node b/lib/node/raspberry-pi/cortex-a53-aarch64/pv_eagle.node index f8291a5c..078fe968 100755 Binary files a/lib/node/raspberry-pi/cortex-a53-aarch64/pv_eagle.node and b/lib/node/raspberry-pi/cortex-a53-aarch64/pv_eagle.node differ diff --git a/lib/node/raspberry-pi/cortex-a53/pv_eagle.node b/lib/node/raspberry-pi/cortex-a53/pv_eagle.node index 052ce062..f30805be 100755 Binary files a/lib/node/raspberry-pi/cortex-a53/pv_eagle.node and b/lib/node/raspberry-pi/cortex-a53/pv_eagle.node differ diff --git a/lib/node/raspberry-pi/cortex-a72-aarch64/pv_eagle.node b/lib/node/raspberry-pi/cortex-a72-aarch64/pv_eagle.node index 998ac8dc..473d5105 100755 Binary files a/lib/node/raspberry-pi/cortex-a72-aarch64/pv_eagle.node and b/lib/node/raspberry-pi/cortex-a72-aarch64/pv_eagle.node differ diff --git a/lib/node/raspberry-pi/cortex-a72/pv_eagle.node b/lib/node/raspberry-pi/cortex-a72/pv_eagle.node index 1a0f532f..aca1e221 100755 Binary files a/lib/node/raspberry-pi/cortex-a72/pv_eagle.node and b/lib/node/raspberry-pi/cortex-a72/pv_eagle.node differ diff --git a/lib/node/raspberry-pi/cortex-a76-aarch64/pv_eagle.node b/lib/node/raspberry-pi/cortex-a76-aarch64/pv_eagle.node index b5f24fcf..a4e0f526 100755 Binary files a/lib/node/raspberry-pi/cortex-a76-aarch64/pv_eagle.node and b/lib/node/raspberry-pi/cortex-a76-aarch64/pv_eagle.node differ diff --git a/lib/node/raspberry-pi/cortex-a76/pv_eagle.node b/lib/node/raspberry-pi/cortex-a76/pv_eagle.node index a3a77ae6..a05db32c 100755 Binary files a/lib/node/raspberry-pi/cortex-a76/pv_eagle.node and b/lib/node/raspberry-pi/cortex-a76/pv_eagle.node differ diff --git a/lib/node/windows/amd64/pv_eagle.node b/lib/node/windows/amd64/pv_eagle.node index 6999b59c..081b1c29 100644 Binary files a/lib/node/windows/amd64/pv_eagle.node and b/lib/node/windows/amd64/pv_eagle.node differ diff --git a/lib/node/windows/amd64/pv_ypu_impl_cuda_eagle.dll b/lib/node/windows/amd64/pv_ypu_impl_cuda_eagle.dll index 82fa06ac..c0f6b887 100644 Binary files a/lib/node/windows/amd64/pv_ypu_impl_cuda_eagle.dll and b/lib/node/windows/amd64/pv_ypu_impl_cuda_eagle.dll differ diff --git a/lib/node/windows/arm64/pv_eagle.node b/lib/node/windows/arm64/pv_eagle.node index 2c3bec1a..cce8cd40 100644 Binary files a/lib/node/windows/arm64/pv_eagle.node and b/lib/node/windows/arm64/pv_eagle.node differ diff --git a/lib/raspberry-pi/cortex-a53-aarch64/libpv_eagle.so b/lib/raspberry-pi/cortex-a53-aarch64/libpv_eagle.so index c4bb02ac..c55ba105 100755 Binary files a/lib/raspberry-pi/cortex-a53-aarch64/libpv_eagle.so and b/lib/raspberry-pi/cortex-a53-aarch64/libpv_eagle.so differ diff --git a/lib/raspberry-pi/cortex-a53/libpv_eagle.so b/lib/raspberry-pi/cortex-a53/libpv_eagle.so index f66e16ba..df69d1eb 100755 Binary files a/lib/raspberry-pi/cortex-a53/libpv_eagle.so and b/lib/raspberry-pi/cortex-a53/libpv_eagle.so differ diff --git a/lib/raspberry-pi/cortex-a72-aarch64/libpv_eagle.so b/lib/raspberry-pi/cortex-a72-aarch64/libpv_eagle.so index 88f8c58b..6e2be79b 100755 Binary files a/lib/raspberry-pi/cortex-a72-aarch64/libpv_eagle.so and b/lib/raspberry-pi/cortex-a72-aarch64/libpv_eagle.so differ diff --git a/lib/raspberry-pi/cortex-a72/libpv_eagle.so b/lib/raspberry-pi/cortex-a72/libpv_eagle.so index 5627abd5..2d9ab968 100755 Binary files a/lib/raspberry-pi/cortex-a72/libpv_eagle.so and b/lib/raspberry-pi/cortex-a72/libpv_eagle.so differ diff --git a/lib/raspberry-pi/cortex-a76-aarch64/libpv_eagle.so b/lib/raspberry-pi/cortex-a76-aarch64/libpv_eagle.so index 43f39a4b..bfda410f 100755 Binary files a/lib/raspberry-pi/cortex-a76-aarch64/libpv_eagle.so and b/lib/raspberry-pi/cortex-a76-aarch64/libpv_eagle.so differ diff --git a/lib/raspberry-pi/cortex-a76/libpv_eagle.so b/lib/raspberry-pi/cortex-a76/libpv_eagle.so index 22693a3e..f5f42864 100755 Binary files a/lib/raspberry-pi/cortex-a76/libpv_eagle.so and b/lib/raspberry-pi/cortex-a76/libpv_eagle.so differ diff --git a/lib/wasm/pv_eagle_pthread.js b/lib/wasm/pv_eagle_pthread.js index 5d184dcd..208031d0 100644 --- a/lib/wasm/pv_eagle_pthread.js +++ b/lib/wasm/pv_eagle_pthread.js @@ -6,7 +6,7 @@ var pv_eagle_pthread = (() => { function(moduleArg = {}) { var moduleRtn; -function GROWABLE_HEAP_I8(){if(wasmMemory.buffer!=HEAP8.buffer){updateMemoryViews()}return HEAP8}function GROWABLE_HEAP_U8(){if(wasmMemory.buffer!=HEAP8.buffer){updateMemoryViews()}return HEAPU8}function GROWABLE_HEAP_I32(){if(wasmMemory.buffer!=HEAP8.buffer){updateMemoryViews()}return HEAP32}function GROWABLE_HEAP_U32(){if(wasmMemory.buffer!=HEAP8.buffer){updateMemoryViews()}return HEAPU32}function GROWABLE_HEAP_F64(){if(wasmMemory.buffer!=HEAP8.buffer){updateMemoryViews()}return HEAPF64}var Module=moduleArg;var readyPromiseResolve,readyPromiseReject;var readyPromise=new Promise((resolve,reject)=>{readyPromiseResolve=resolve;readyPromiseReject=reject});var ENVIRONMENT_IS_WEB=typeof window=="object";var ENVIRONMENT_IS_WORKER=typeof importScripts=="function";var ENVIRONMENT_IS_NODE=typeof process=="object"&&typeof process.versions=="object"&&typeof process.versions.node=="string";var ENVIRONMENT_IS_PTHREAD=ENVIRONMENT_IS_WORKER&&self.name=="em-pthread";function _typeof$2(o){null;return _typeof$2="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(o){return typeof o}:function(o){return o&&"function"==typeof Symbol&&o.constructor===Symbol&&o!==Symbol.prototype?"symbol":typeof o},_typeof$2(o)}function toPrimitive(t,r){if("object"!=_typeof$2(t)||!t)return t;var e=t[Symbol.toPrimitive];if(void 0!==e){var i=e.call(t,r||"default");if("object"!=_typeof$2(i))return i;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===r?String:Number)(t)}function toPropertyKey(t){var i=toPrimitive(t,"string");return"symbol"==_typeof$2(i)?i:i+""}function _defineProperty(e,r,t){return(r=toPropertyKey(r))in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function asyncGeneratorStep(n,t,e,r,o,a,c){try{var i=n[a](c),u=i.value}catch(n){return void e(n)}i.done?t(u):Promise.resolve(u).then(r,o)}function _asyncToGenerator(n){return function(){var t=this,e=arguments;return new Promise(function(r,o){var a=n.apply(t,e);function _next(n){asyncGeneratorStep(a,r,o,_next,_throw,"next",n)}function _throw(n){asyncGeneratorStep(a,r,o,_next,_throw,"throw",n)}_next(void 0)})}}function getDefaultExportFromCjs(x){return x&&x.__esModule&&Object.prototype.hasOwnProperty.call(x,"default")?x["default"]:x}var regeneratorRuntime$3={exports:{}};var _typeof$1={exports:{}};var _typeof_1=_typeof$1.exports;(function(module){function _typeof(o){null;return module.exports=_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(o){return typeof o}:function(o){return o&&"function"==typeof Symbol&&o.constructor===Symbol&&o!==Symbol.prototype?"symbol":typeof o},module.exports.__esModule=true,module.exports["default"]=module.exports,_typeof(o)}module.exports=_typeof,module.exports.__esModule=true,module.exports["default"]=module.exports})(_typeof$1);var _typeofExports=_typeof$1.exports;var _typeof=getDefaultExportFromCjs(_typeofExports);var regeneratorRuntime$1=regeneratorRuntime$3.exports;(function(module){var _typeof=_typeofExports["default"];function _regeneratorRuntime(){"use strict";module.exports=_regeneratorRuntime=function _regeneratorRuntime(){return e},module.exports.__esModule=true,module.exports["default"]=module.exports;var t,e={},r=Object.prototype,n=r.hasOwnProperty,o=Object.defineProperty||function(t,e,r){t[e]=r.value},i="function"==typeof Symbol?Symbol:{},a=i.iterator||"@@iterator",c=i.asyncIterator||"@@asyncIterator",u=i.toStringTag||"@@toStringTag";function define(t,e,r){return Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}),t[e]}try{define({},"")}catch(t){define=function define(t,e,r){return t[e]=r}}function wrap(t,e,r,n){var i=e&&e.prototype instanceof Generator?e:Generator,a=Object.create(i.prototype),c=new Context(n||[]);return o(a,"_invoke",{value:makeInvokeMethod(t,r,c)}),a}function tryCatch(t,e,r){try{return{type:"normal",arg:t.call(e,r)}}catch(t){return{type:"throw",arg:t}}}e.wrap=wrap;var h="suspendedStart",l="suspendedYield",f="executing",s="completed",y={};function Generator(){}function GeneratorFunction(){}function GeneratorFunctionPrototype(){}var p={};define(p,a,function(){return this});var d=Object.getPrototypeOf,v=d&&d(d(values([])));v&&v!==r&&n.call(v,a)&&(p=v);var g=GeneratorFunctionPrototype.prototype=Generator.prototype=Object.create(p);function defineIteratorMethods(t){["next","throw","return"].forEach(function(e){define(t,e,function(t){return this._invoke(e,t)})})}function AsyncIterator(t,e){function invoke(r,o,i,a){var c=tryCatch(t[r],t,o);if("throw"!==c.type){var u=c.arg,h=u.value;return h&&"object"==_typeof(h)&&n.call(h,"__await")?e.resolve(h.__await).then(function(t){invoke("next",t,i,a)},function(t){invoke("throw",t,i,a)}):e.resolve(h).then(function(t){u.value=t,i(u)},function(t){return invoke("throw",t,i,a)})}a(c.arg)}var r;o(this,"_invoke",{value:function value(t,n){function callInvokeWithMethodAndArg(){return new e(function(e,r){invoke(t,n,e,r)})}return r=r?r.then(callInvokeWithMethodAndArg,callInvokeWithMethodAndArg):callInvokeWithMethodAndArg()}})}function makeInvokeMethod(e,r,n){var o=h;return function(i,a){if(o===f)throw Error("Generator is already running");if(o===s){if("throw"===i)throw a;return{value:t,done:!0}}for(n.method=i,n.arg=a;;){var c=n.delegate;if(c){var u=maybeInvokeDelegate(c,n);if(u){if(u===y)continue;return u}}if("next"===n.method)n.sent=n._sent=n.arg;else if("throw"===n.method){if(o===h)throw o=s,n.arg;n.dispatchException(n.arg)}else"return"===n.method&&n.abrupt("return",n.arg);o=f;var p=tryCatch(e,r,n);if("normal"===p.type){if(o=n.done?s:l,p.arg===y)continue;return{value:p.arg,done:n.done}}"throw"===p.type&&(o=s,n.method="throw",n.arg=p.arg)}}}function maybeInvokeDelegate(e,r){var n=r.method,o=e.iterator[n];if(o===t)return r.delegate=null,"throw"===n&&e.iterator["return"]&&(r.method="return",r.arg=t,maybeInvokeDelegate(e,r),"throw"===r.method)||"return"!==n&&(r.method="throw",r.arg=new TypeError("The iterator does not provide a '"+n+"' method")),y;var i=tryCatch(o,e.iterator,r.arg);if("throw"===i.type)return r.method="throw",r.arg=i.arg,r.delegate=null,y;var a=i.arg;return a?a.done?(r[e.resultName]=a.value,r.next=e.nextLoc,"return"!==r.method&&(r.method="next",r.arg=t),r.delegate=null,y):a:(r.method="throw",r.arg=new TypeError("iterator result is not an object"),r.delegate=null,y)}function pushTryEntry(t){var e={tryLoc:t[0]};1 in t&&(e.catchLoc=t[1]),2 in t&&(e.finallyLoc=t[2],e.afterLoc=t[3]),this.tryEntries.push(e)}function resetTryEntry(t){var e=t.completion||{};e.type="normal",delete e.arg,t.completion=e}function Context(t){this.tryEntries=[{tryLoc:"root"}],t.forEach(pushTryEntry,this),this.reset(!0)}function values(e){if(e||""===e){var r=e[a];if(r)return r.call(e);if("function"==typeof e.next)return e;if(!isNaN(e.length)){var o=-1,i=function next(){for(;++o=0;--o){var i=this.tryEntries[o],a=i.completion;if("root"===i.tryLoc)return handle("end");if(i.tryLoc<=this.prev){var c=n.call(i,"catchLoc"),u=n.call(i,"finallyLoc");if(c&&u){if(this.prev=0;--r){var o=this.tryEntries[r];if(o.tryLoc<=this.prev&&n.call(o,"finallyLoc")&&this.prev=0;--e){var r=this.tryEntries[e];if(r.finallyLoc===t)return this.complete(r.completion,r.afterLoc),resetTryEntry(r),y}},catch:function _catch(t){for(var e=this.tryEntries.length-1;e>=0;--e){var r=this.tryEntries[e];if(r.tryLoc===t){var n=r.completion;if("throw"===n.type){var o=n.arg;resetTryEntry(r)}return o}}throw Error("illegal catch attempt")},delegateYield:function delegateYield(e,r,n){return this.delegate={iterator:values(e),resultName:r,nextLoc:n},"next"===this.method&&(this.arg=t),y}},e}module.exports=_regeneratorRuntime,module.exports.__esModule=true,module.exports["default"]=module.exports})(regeneratorRuntime$3);var regeneratorRuntimeExports=regeneratorRuntime$3.exports;var regeneratorRuntime$2=getDefaultExportFromCjs(regeneratorRuntimeExports);var runtime=regeneratorRuntimeExports();var regenerator=runtime;try{regeneratorRuntime=runtime}catch(accidentalStrictMode){if(typeof globalThis==="object"){globalThis.regeneratorRuntime=runtime}else{Function("r","regeneratorRuntime = r")(runtime)}}var _regeneratorRuntime=getDefaultExportFromCjs(regenerator);const BROWSER_ALIASES_MAP={"Amazon Silk":"amazon_silk","Android Browser":"android",Bada:"bada",BlackBerry:"blackberry",Chrome:"chrome",Chromium:"chromium",Electron:"electron",Epiphany:"epiphany",Firefox:"firefox",Focus:"focus",Generic:"generic","Google Search":"google_search",Googlebot:"googlebot","Internet Explorer":"ie","K-Meleon":"k_meleon",Maxthon:"maxthon","Microsoft Edge":"edge","MZ Browser":"mz","NAVER Whale Browser":"naver",Opera:"opera","Opera Coast":"opera_coast",PhantomJS:"phantomjs",Puffin:"puffin",QupZilla:"qupzilla",QQ:"qq",QQLite:"qqlite",Safari:"safari",Sailfish:"sailfish","Samsung Internet for Android":"samsung_internet",SeaMonkey:"seamonkey",Sleipnir:"sleipnir",Swing:"swing",Tizen:"tizen","UC Browser":"uc",Vivaldi:"vivaldi","WebOS Browser":"webos",WeChat:"wechat","Yandex Browser":"yandex",Roku:"roku"};const BROWSER_MAP={amazon_silk:"Amazon Silk",android:"Android Browser",bada:"Bada",blackberry:"BlackBerry",chrome:"Chrome",chromium:"Chromium",electron:"Electron",epiphany:"Epiphany",firefox:"Firefox",focus:"Focus",generic:"Generic",googlebot:"Googlebot",google_search:"Google Search",ie:"Internet Explorer",k_meleon:"K-Meleon",maxthon:"Maxthon",edge:"Microsoft Edge",mz:"MZ Browser",naver:"NAVER Whale Browser",opera:"Opera",opera_coast:"Opera Coast",phantomjs:"PhantomJS",puffin:"Puffin",qupzilla:"QupZilla",qq:"QQ Browser",qqlite:"QQ Browser Lite",safari:"Safari",sailfish:"Sailfish",samsung_internet:"Samsung Internet for Android",seamonkey:"SeaMonkey",sleipnir:"Sleipnir",swing:"Swing",tizen:"Tizen",uc:"UC Browser",vivaldi:"Vivaldi",webos:"WebOS Browser",wechat:"WeChat",yandex:"Yandex Browser"};const PLATFORMS_MAP={tablet:"tablet",mobile:"mobile",desktop:"desktop",tv:"tv"};const OS_MAP={WindowsPhone:"Windows Phone",Windows:"Windows",MacOS:"macOS",iOS:"iOS",Android:"Android",WebOS:"WebOS",BlackBerry:"BlackBerry",Bada:"Bada",Tizen:"Tizen",Linux:"Linux",ChromeOS:"Chrome OS",PlayStation4:"PlayStation 4",Roku:"Roku"};const ENGINE_MAP={EdgeHTML:"EdgeHTML",Blink:"Blink",Trident:"Trident",Presto:"Presto",Gecko:"Gecko",WebKit:"WebKit"};class Utils{static getFirstMatch(regexp,ua){const match=ua.match(regexp);return match&&match.length>0&&match[1]||""}static getSecondMatch(regexp,ua){const match=ua.match(regexp);return match&&match.length>1&&match[2]||""}static matchAndReturnConst(regexp,ua,_const){if(regexp.test(ua)){return _const}return void 0}static getWindowsVersionName(version){switch(version){case"NT":return"NT";case"XP":return"XP";case"NT 5.0":return"2000";case"NT 5.1":return"XP";case"NT 5.2":return"2003";case"NT 6.0":return"Vista";case"NT 6.1":return"7";case"NT 6.2":return"8";case"NT 6.3":return"8.1";case"NT 10.0":return"10";default:return undefined}}static getMacOSVersionName(version){const v=version.split(".").splice(0,2).map(s=>parseInt(s,10)||0);v.push(0);if(v[0]!==10)return undefined;switch(v[1]){case 5:return"Leopard";case 6:return"Snow Leopard";case 7:return"Lion";case 8:return"Mountain Lion";case 9:return"Mavericks";case 10:return"Yosemite";case 11:return"El Capitan";case 12:return"Sierra";case 13:return"High Sierra";case 14:return"Mojave";case 15:return"Catalina";default:return undefined}}static getAndroidVersionName(version){const v=version.split(".").splice(0,2).map(s=>parseInt(s,10)||0);v.push(0);if(v[0]===1&&v[1]<5)return undefined;if(v[0]===1&&v[1]<6)return"Cupcake";if(v[0]===1&&v[1]>=6)return"Donut";if(v[0]===2&&v[1]<2)return"Eclair";if(v[0]===2&&v[1]===2)return"Froyo";if(v[0]===2&&v[1]>2)return"Gingerbread";if(v[0]===3)return"Honeycomb";if(v[0]===4&&v[1]<1)return"Ice Cream Sandwich";if(v[0]===4&&v[1]<4)return"Jelly Bean";if(v[0]===4&&v[1]>=4)return"KitKat";if(v[0]===5)return"Lollipop";if(v[0]===6)return"Marshmallow";if(v[0]===7)return"Nougat";if(v[0]===8)return"Oreo";if(v[0]===9)return"Pie";return undefined}static getVersionPrecision(version){return version.split(".").length}static compareVersions(versionA,versionB,isLoose=false){const versionAPrecision=Utils.getVersionPrecision(versionA);const versionBPrecision=Utils.getVersionPrecision(versionB);let precision=Math.max(versionAPrecision,versionBPrecision);let lastPrecision=0;const chunks=Utils.map([versionA,versionB],version=>{const delta=precision-Utils.getVersionPrecision(version);const _version=version+new Array(delta+1).join(".0");return Utils.map(_version.split("."),chunk=>new Array(20-chunk.length).join("0")+chunk).reverse()});if(isLoose){lastPrecision=precision-Math.min(versionAPrecision,versionBPrecision)}precision-=1;while(precision>=lastPrecision){if(chunks[0][precision]>chunks[1][precision]){return 1}if(chunks[0][precision]===chunks[1][precision]){if(precision===lastPrecision){return 0}precision-=1}else if(chunks[0][precision]{result[key]=assigner[key]})}}return obj}static getBrowserAlias(browserName){return BROWSER_ALIASES_MAP[browserName]}static getBrowserTypeByAlias(browserAlias){return BROWSER_MAP[browserAlias]||""}}const commonVersionIdentifier=/version\/(\d+(\.?_?\d+)+)/i;const browsersList=[{test:[/googlebot/i],describe(ua){const browser={name:"Googlebot"};const version=Utils.getFirstMatch(/googlebot\/(\d+(\.\d+))/i,ua)||Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/opera/i],describe(ua){const browser={name:"Opera"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua)||Utils.getFirstMatch(/(?:opera)[\s/](\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/opr\/|opios/i],describe(ua){const browser={name:"Opera"};const version=Utils.getFirstMatch(/(?:opr|opios)[\s/](\S+)/i,ua)||Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/SamsungBrowser/i],describe(ua){const browser={name:"Samsung Internet for Android"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua)||Utils.getFirstMatch(/(?:SamsungBrowser)[\s/](\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/Whale/i],describe(ua){const browser={name:"NAVER Whale Browser"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua)||Utils.getFirstMatch(/(?:whale)[\s/](\d+(?:\.\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/MZBrowser/i],describe(ua){const browser={name:"MZ Browser"};const version=Utils.getFirstMatch(/(?:MZBrowser)[\s/](\d+(?:\.\d+)+)/i,ua)||Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/focus/i],describe(ua){const browser={name:"Focus"};const version=Utils.getFirstMatch(/(?:focus)[\s/](\d+(?:\.\d+)+)/i,ua)||Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/swing/i],describe(ua){const browser={name:"Swing"};const version=Utils.getFirstMatch(/(?:swing)[\s/](\d+(?:\.\d+)+)/i,ua)||Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/coast/i],describe(ua){const browser={name:"Opera Coast"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua)||Utils.getFirstMatch(/(?:coast)[\s/](\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/opt\/\d+(?:.?_?\d+)+/i],describe(ua){const browser={name:"Opera Touch"};const version=Utils.getFirstMatch(/(?:opt)[\s/](\d+(\.?_?\d+)+)/i,ua)||Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/yabrowser/i],describe(ua){const browser={name:"Yandex Browser"};const version=Utils.getFirstMatch(/(?:yabrowser)[\s/](\d+(\.?_?\d+)+)/i,ua)||Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/ucbrowser/i],describe(ua){const browser={name:"UC Browser"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua)||Utils.getFirstMatch(/(?:ucbrowser)[\s/](\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/Maxthon|mxios/i],describe(ua){const browser={name:"Maxthon"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua)||Utils.getFirstMatch(/(?:Maxthon|mxios)[\s/](\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/epiphany/i],describe(ua){const browser={name:"Epiphany"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua)||Utils.getFirstMatch(/(?:epiphany)[\s/](\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/puffin/i],describe(ua){const browser={name:"Puffin"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua)||Utils.getFirstMatch(/(?:puffin)[\s/](\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/sleipnir/i],describe(ua){const browser={name:"Sleipnir"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua)||Utils.getFirstMatch(/(?:sleipnir)[\s/](\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/k-meleon/i],describe(ua){const browser={name:"K-Meleon"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua)||Utils.getFirstMatch(/(?:k-meleon)[\s/](\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/micromessenger/i],describe(ua){const browser={name:"WeChat"};const version=Utils.getFirstMatch(/(?:micromessenger)[\s/](\d+(\.?_?\d+)+)/i,ua)||Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/qqbrowser/i],describe(ua){const browser={name:/qqbrowserlite/i.test(ua)?"QQ Browser Lite":"QQ Browser"};const version=Utils.getFirstMatch(/(?:qqbrowserlite|qqbrowser)[/](\d+(\.?_?\d+)+)/i,ua)||Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/msie|trident/i],describe(ua){const browser={name:"Internet Explorer"};const version=Utils.getFirstMatch(/(?:msie |rv:)(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/\sedg\//i],describe(ua){const browser={name:"Microsoft Edge"};const version=Utils.getFirstMatch(/\sedg\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/edg([ea]|ios)/i],describe(ua){const browser={name:"Microsoft Edge"};const version=Utils.getSecondMatch(/edg([ea]|ios)\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/vivaldi/i],describe(ua){const browser={name:"Vivaldi"};const version=Utils.getFirstMatch(/vivaldi\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/seamonkey/i],describe(ua){const browser={name:"SeaMonkey"};const version=Utils.getFirstMatch(/seamonkey\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/sailfish/i],describe(ua){const browser={name:"Sailfish"};const version=Utils.getFirstMatch(/sailfish\s?browser\/(\d+(\.\d+)?)/i,ua);if(version){browser.version=version}return browser}},{test:[/silk/i],describe(ua){const browser={name:"Amazon Silk"};const version=Utils.getFirstMatch(/silk\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/phantom/i],describe(ua){const browser={name:"PhantomJS"};const version=Utils.getFirstMatch(/phantomjs\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/slimerjs/i],describe(ua){const browser={name:"SlimerJS"};const version=Utils.getFirstMatch(/slimerjs\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/blackberry|\bbb\d+/i,/rim\stablet/i],describe(ua){const browser={name:"BlackBerry"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua)||Utils.getFirstMatch(/blackberry[\d]+\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/(web|hpw)[o0]s/i],describe(ua){const browser={name:"WebOS Browser"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua)||Utils.getFirstMatch(/w(?:eb)?[o0]sbrowser\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/bada/i],describe(ua){const browser={name:"Bada"};const version=Utils.getFirstMatch(/dolfin\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/tizen/i],describe(ua){const browser={name:"Tizen"};const version=Utils.getFirstMatch(/(?:tizen\s?)?browser\/(\d+(\.?_?\d+)+)/i,ua)||Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/qupzilla/i],describe(ua){const browser={name:"QupZilla"};const version=Utils.getFirstMatch(/(?:qupzilla)[\s/](\d+(\.?_?\d+)+)/i,ua)||Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/firefox|iceweasel|fxios/i],describe(ua){const browser={name:"Firefox"};const version=Utils.getFirstMatch(/(?:firefox|iceweasel|fxios)[\s/](\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/electron/i],describe(ua){const browser={name:"Electron"};const version=Utils.getFirstMatch(/(?:electron)\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/MiuiBrowser/i],describe(ua){const browser={name:"Miui"};const version=Utils.getFirstMatch(/(?:MiuiBrowser)[\s/](\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/chromium/i],describe(ua){const browser={name:"Chromium"};const version=Utils.getFirstMatch(/(?:chromium)[\s/](\d+(\.?_?\d+)+)/i,ua)||Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/chrome|crios|crmo/i],describe(ua){const browser={name:"Chrome"};const version=Utils.getFirstMatch(/(?:chrome|crios|crmo)\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/GSA/i],describe(ua){const browser={name:"Google Search"};const version=Utils.getFirstMatch(/(?:GSA)\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test(parser){const notLikeAndroid=!parser.test(/like android/i);const butAndroid=parser.test(/android/i);return notLikeAndroid&&butAndroid},describe(ua){const browser={name:"Android Browser"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/playstation 4/i],describe(ua){const browser={name:"PlayStation 4"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/safari|applewebkit/i],describe(ua){const browser={name:"Safari"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/.*/i],describe(ua){const regexpWithoutDeviceSpec=/^(.*)\/(.*) /;const regexpWithDeviceSpec=/^(.*)\/(.*)[ \t]\((.*)/;const hasDeviceSpec=ua.search("\\(")!==-1;const regexp=hasDeviceSpec?regexpWithDeviceSpec:regexpWithoutDeviceSpec;return{name:Utils.getFirstMatch(regexp,ua),version:Utils.getSecondMatch(regexp,ua)}}}];var osParsersList=[{test:[/Roku\/DVP/],describe(ua){const version=Utils.getFirstMatch(/Roku\/DVP-(\d+\.\d+)/i,ua);return{name:OS_MAP.Roku,version:version}}},{test:[/windows phone/i],describe(ua){const version=Utils.getFirstMatch(/windows phone (?:os)?\s?(\d+(\.\d+)*)/i,ua);return{name:OS_MAP.WindowsPhone,version:version}}},{test:[/windows /i],describe(ua){const version=Utils.getFirstMatch(/Windows ((NT|XP)( \d\d?.\d)?)/i,ua);const versionName=Utils.getWindowsVersionName(version);return{name:OS_MAP.Windows,version:version,versionName:versionName}}},{test:[/Macintosh(.*?) FxiOS(.*?)\//],describe(ua){const result={name:OS_MAP.iOS};const version=Utils.getSecondMatch(/(Version\/)(\d[\d.]+)/,ua);if(version){result.version=version}return result}},{test:[/macintosh/i],describe(ua){const version=Utils.getFirstMatch(/mac os x (\d+(\.?_?\d+)+)/i,ua).replace(/[_\s]/g,".");const versionName=Utils.getMacOSVersionName(version);const os={name:OS_MAP.MacOS,version:version};if(versionName){os.versionName=versionName}return os}},{test:[/(ipod|iphone|ipad)/i],describe(ua){const version=Utils.getFirstMatch(/os (\d+([_\s]\d+)*) like mac os x/i,ua).replace(/[_\s]/g,".");return{name:OS_MAP.iOS,version:version}}},{test(parser){const notLikeAndroid=!parser.test(/like android/i);const butAndroid=parser.test(/android/i);return notLikeAndroid&&butAndroid},describe(ua){const version=Utils.getFirstMatch(/android[\s/-](\d+(\.\d+)*)/i,ua);const versionName=Utils.getAndroidVersionName(version);const os={name:OS_MAP.Android,version:version};if(versionName){os.versionName=versionName}return os}},{test:[/(web|hpw)[o0]s/i],describe(ua){const version=Utils.getFirstMatch(/(?:web|hpw)[o0]s\/(\d+(\.\d+)*)/i,ua);const os={name:OS_MAP.WebOS};if(version&&version.length){os.version=version}return os}},{test:[/blackberry|\bbb\d+/i,/rim\stablet/i],describe(ua){const version=Utils.getFirstMatch(/rim\stablet\sos\s(\d+(\.\d+)*)/i,ua)||Utils.getFirstMatch(/blackberry\d+\/(\d+([_\s]\d+)*)/i,ua)||Utils.getFirstMatch(/\bbb(\d+)/i,ua);return{name:OS_MAP.BlackBerry,version:version}}},{test:[/bada/i],describe(ua){const version=Utils.getFirstMatch(/bada\/(\d+(\.\d+)*)/i,ua);return{name:OS_MAP.Bada,version:version}}},{test:[/tizen/i],describe(ua){const version=Utils.getFirstMatch(/tizen[/\s](\d+(\.\d+)*)/i,ua);return{name:OS_MAP.Tizen,version:version}}},{test:[/linux/i],describe(){return{name:OS_MAP.Linux}}},{test:[/CrOS/],describe(){return{name:OS_MAP.ChromeOS}}},{test:[/PlayStation 4/],describe(ua){const version=Utils.getFirstMatch(/PlayStation 4[/\s](\d+(\.\d+)*)/i,ua);return{name:OS_MAP.PlayStation4,version:version}}}];var platformParsersList=[{test:[/googlebot/i],describe(){return{type:"bot",vendor:"Google"}}},{test:[/huawei/i],describe(ua){const model=Utils.getFirstMatch(/(can-l01)/i,ua)&&"Nova";const platform={type:PLATFORMS_MAP.mobile,vendor:"Huawei"};if(model){platform.model=model}return platform}},{test:[/nexus\s*(?:7|8|9|10).*/i],describe(){return{type:PLATFORMS_MAP.tablet,vendor:"Nexus"}}},{test:[/ipad/i],describe(){return{type:PLATFORMS_MAP.tablet,vendor:"Apple",model:"iPad"}}},{test:[/Macintosh(.*?) FxiOS(.*?)\//],describe(){return{type:PLATFORMS_MAP.tablet,vendor:"Apple",model:"iPad"}}},{test:[/kftt build/i],describe(){return{type:PLATFORMS_MAP.tablet,vendor:"Amazon",model:"Kindle Fire HD 7"}}},{test:[/silk/i],describe(){return{type:PLATFORMS_MAP.tablet,vendor:"Amazon"}}},{test:[/tablet(?! pc)/i],describe(){return{type:PLATFORMS_MAP.tablet}}},{test(parser){const iDevice=parser.test(/ipod|iphone/i);const likeIDevice=parser.test(/like (ipod|iphone)/i);return iDevice&&!likeIDevice},describe(ua){const model=Utils.getFirstMatch(/(ipod|iphone)/i,ua);return{type:PLATFORMS_MAP.mobile,vendor:"Apple",model:model}}},{test:[/nexus\s*[0-6].*/i,/galaxy nexus/i],describe(){return{type:PLATFORMS_MAP.mobile,vendor:"Nexus"}}},{test:[/[^-]mobi/i],describe(){return{type:PLATFORMS_MAP.mobile}}},{test(parser){return parser.getBrowserName(true)==="blackberry"},describe(){return{type:PLATFORMS_MAP.mobile,vendor:"BlackBerry"}}},{test(parser){return parser.getBrowserName(true)==="bada"},describe(){return{type:PLATFORMS_MAP.mobile}}},{test(parser){return parser.getBrowserName()==="windows phone"},describe(){return{type:PLATFORMS_MAP.mobile,vendor:"Microsoft"}}},{test(parser){const osMajorVersion=Number(String(parser.getOSVersion()).split(".")[0]);return parser.getOSName(true)==="android"&&osMajorVersion>=3},describe(){return{type:PLATFORMS_MAP.tablet}}},{test(parser){return parser.getOSName(true)==="android"},describe(){return{type:PLATFORMS_MAP.mobile}}},{test(parser){return parser.getOSName(true)==="macos"},describe(){return{type:PLATFORMS_MAP.desktop,vendor:"Apple"}}},{test(parser){return parser.getOSName(true)==="windows"},describe(){return{type:PLATFORMS_MAP.desktop}}},{test(parser){return parser.getOSName(true)==="linux"},describe(){return{type:PLATFORMS_MAP.desktop}}},{test(parser){return parser.getOSName(true)==="playstation 4"},describe(){return{type:PLATFORMS_MAP.tv}}},{test(parser){return parser.getOSName(true)==="roku"},describe(){return{type:PLATFORMS_MAP.tv}}}];var enginesParsersList=[{test(parser){return parser.getBrowserName(true)==="microsoft edge"},describe(ua){const isBlinkBased=/\sedg\//i.test(ua);if(isBlinkBased){return{name:ENGINE_MAP.Blink}}const version=Utils.getFirstMatch(/edge\/(\d+(\.?_?\d+)+)/i,ua);return{name:ENGINE_MAP.EdgeHTML,version:version}}},{test:[/trident/i],describe(ua){const engine={name:ENGINE_MAP.Trident};const version=Utils.getFirstMatch(/trident\/(\d+(\.?_?\d+)+)/i,ua);if(version){engine.version=version}return engine}},{test(parser){return parser.test(/presto/i)},describe(ua){const engine={name:ENGINE_MAP.Presto};const version=Utils.getFirstMatch(/presto\/(\d+(\.?_?\d+)+)/i,ua);if(version){engine.version=version}return engine}},{test(parser){const isGecko=parser.test(/gecko/i);const likeGecko=parser.test(/like gecko/i);return isGecko&&!likeGecko},describe(ua){const engine={name:ENGINE_MAP.Gecko};const version=Utils.getFirstMatch(/gecko\/(\d+(\.?_?\d+)+)/i,ua);if(version){engine.version=version}return engine}},{test:[/(apple)?webkit\/537\.36/i],describe(){return{name:ENGINE_MAP.Blink}}},{test:[/(apple)?webkit/i],describe(ua){const engine={name:ENGINE_MAP.WebKit};const version=Utils.getFirstMatch(/webkit\/(\d+(\.?_?\d+)+)/i,ua);if(version){engine.version=version}return engine}}];class Parser{constructor(UA,skipParsing=false){if(UA===void 0||UA===null||UA===""){throw new Error("UserAgent parameter can't be empty")}this._ua=UA;this.parsedResult={};if(skipParsing!==true){this.parse()}}getUA(){return this._ua}test(regex){return regex.test(this._ua)}parseBrowser(){this.parsedResult.browser={};const browserDescriptor=Utils.find(browsersList,_browser=>{if(typeof _browser.test==="function"){return _browser.test(this)}if(_browser.test instanceof Array){return _browser.test.some(condition=>this.test(condition))}throw new Error("Browser's test function is not valid")});if(browserDescriptor){this.parsedResult.browser=browserDescriptor.describe(this.getUA())}return this.parsedResult.browser}getBrowser(){if(this.parsedResult.browser){return this.parsedResult.browser}return this.parseBrowser()}getBrowserName(toLowerCase){if(toLowerCase){return String(this.getBrowser().name).toLowerCase()||""}return this.getBrowser().name||""}getBrowserVersion(){return this.getBrowser().version}getOS(){if(this.parsedResult.os){return this.parsedResult.os}return this.parseOS()}parseOS(){this.parsedResult.os={};const os=Utils.find(osParsersList,_os=>{if(typeof _os.test==="function"){return _os.test(this)}if(_os.test instanceof Array){return _os.test.some(condition=>this.test(condition))}throw new Error("Browser's test function is not valid")});if(os){this.parsedResult.os=os.describe(this.getUA())}return this.parsedResult.os}getOSName(toLowerCase){const{name:name}=this.getOS();if(toLowerCase){return String(name).toLowerCase()||""}return name||""}getOSVersion(){return this.getOS().version}getPlatform(){if(this.parsedResult.platform){return this.parsedResult.platform}return this.parsePlatform()}getPlatformType(toLowerCase=false){const{type:type}=this.getPlatform();if(toLowerCase){return String(type).toLowerCase()||""}return type||""}parsePlatform(){this.parsedResult.platform={};const platform=Utils.find(platformParsersList,_platform=>{if(typeof _platform.test==="function"){return _platform.test(this)}if(_platform.test instanceof Array){return _platform.test.some(condition=>this.test(condition))}throw new Error("Browser's test function is not valid")});if(platform){this.parsedResult.platform=platform.describe(this.getUA())}return this.parsedResult.platform}getEngine(){if(this.parsedResult.engine){return this.parsedResult.engine}return this.parseEngine()}getEngineName(toLowerCase){if(toLowerCase){return String(this.getEngine().name).toLowerCase()||""}return this.getEngine().name||""}parseEngine(){this.parsedResult.engine={};const engine=Utils.find(enginesParsersList,_engine=>{if(typeof _engine.test==="function"){return _engine.test(this)}if(_engine.test instanceof Array){return _engine.test.some(condition=>this.test(condition))}throw new Error("Browser's test function is not valid")});if(engine){this.parsedResult.engine=engine.describe(this.getUA())}return this.parsedResult.engine}parse(){this.parseBrowser();this.parseOS();this.parsePlatform();this.parseEngine();return this}getResult(){return Utils.assign({},this.parsedResult)}satisfies(checkTree){const platformsAndOSes={};let platformsAndOSCounter=0;const browsers={};let browsersCounter=0;const allDefinitions=Object.keys(checkTree);allDefinitions.forEach(key=>{const currentDefinition=checkTree[key];if(typeof currentDefinition==="string"){browsers[key]=currentDefinition;browsersCounter+=1}else if(typeof currentDefinition==="object"){platformsAndOSes[key]=currentDefinition;platformsAndOSCounter+=1}});if(platformsAndOSCounter>0){const platformsAndOSNames=Object.keys(platformsAndOSes);const OSMatchingDefinition=Utils.find(platformsAndOSNames,name=>this.isOS(name));if(OSMatchingDefinition){const osResult=this.satisfies(platformsAndOSes[OSMatchingDefinition]);if(osResult!==void 0){return osResult}}const platformMatchingDefinition=Utils.find(platformsAndOSNames,name=>this.isPlatform(name));if(platformMatchingDefinition){const platformResult=this.satisfies(platformsAndOSes[platformMatchingDefinition]);if(platformResult!==void 0){return platformResult}}}if(browsersCounter>0){const browserNames=Object.keys(browsers);const matchingDefinition=Utils.find(browserNames,name=>this.isBrowser(name,true));if(matchingDefinition!==void 0){return this.compareVersion(browsers[matchingDefinition])}}return undefined}isBrowser(browserName,includingAlias=false){const defaultBrowserName=this.getBrowserName().toLowerCase();let browserNameLower=browserName.toLowerCase();const alias=Utils.getBrowserTypeByAlias(browserNameLower);if(includingAlias&&alias){browserNameLower=alias.toLowerCase()}return browserNameLower===defaultBrowserName}compareVersion(version){let expectedResults=[0];let comparableVersion=version;let isLoose=false;const currentBrowserVersion=this.getBrowserVersion();if(typeof currentBrowserVersion!=="string"){return void 0}if(version[0]===">"||version[0]==="<"){comparableVersion=version.substr(1);if(version[1]==="="){isLoose=true;comparableVersion=version.substr(2)}else{expectedResults=[]}if(version[0]===">"){expectedResults.push(1)}else{expectedResults.push(-1)}}else if(version[0]==="="){comparableVersion=version.substr(1)}else if(version[0]==="~"){isLoose=true;comparableVersion=version.substr(1)}return expectedResults.indexOf(Utils.compareVersions(currentBrowserVersion,comparableVersion,isLoose))>-1}isOS(osName){return this.getOSName(true)===String(osName).toLowerCase()}isPlatform(platformType){return this.getPlatformType(true)===String(platformType).toLowerCase()}isEngine(engineName){return this.getEngineName(true)===String(engineName).toLowerCase()}is(anything,includingAlias=false){return this.isBrowser(anything,includingAlias)||this.isOS(anything)||this.isPlatform(anything)}some(anythings=[]){return anythings.some(anything=>this.is(anything))}}class Bowser{static getParser(UA,skipParsing=false){if(typeof UA!=="string"){throw new Error("UserAgent should be a string")}return new Parser(UA,skipParsing)}static parse(UA){return new Parser(UA).getResult()}static get BROWSER_MAP(){return BROWSER_MAP}static get ENGINE_MAP(){return ENGINE_MAP}static get OS_MAP(){return OS_MAP}static get PLATFORMS_MAP(){return PLATFORMS_MAP}}function _classCallCheck(a,n){if(!(a instanceof n))throw new TypeError("Cannot call a class as a function")}function _defineProperties(e,r){for(var t=0;t=this._data.length){return undefined}var res=this._data.slice(this._pos,this._pos+bytes);this._pos+=bytes;return res}},{key:"set",value:function set(pos,data){this._pos=pos;this._data=data}},{key:"clear",value:function clear(){this._pos=0;this._data=new Uint8Array}}])}();var PvFileIDB=function(_PvFile){function PvFileIDB(path,meta,db,mode){var _this;_classCallCheck(this,PvFileIDB);_this=_callSuper$1(this,PvFileIDB);_this._pageSize=512*1024;_this._pagePtr=0;_this._pageOffset=0;_this._path=path;_this._meta=meta;_this._db=db;_this._mode=mode;_this._cache=new PvCache;return _this}_inherits(PvFileIDB,_PvFile);return _createClass(PvFileIDB,[{key:"pageSize",get:function get(){return this._pageSize}},{key:"close",value:function(){var _close=_asyncToGenerator(_regeneratorRuntime.mark(function _callee(){return _regeneratorRuntime.wrap(function _callee$(_context){while(1)switch(_context.prev=_context.next){case 0:this._db.close();case 1:case"end":return _context.stop()}},_callee,this)}));function close(){return _close.apply(this,arguments)}return close}()},{key:"read",value:function(){var _read=_asyncToGenerator(_regeneratorRuntime.mark(function _callee2(size,count){var _this2=this;return _regeneratorRuntime.wrap(function _callee2$(_context2){while(1)switch(_context2.prev=_context2.next){case 0:return _context2.abrupt("return",new Promise(function(resolve,reject){if(!_this2.exists()){reject(new Error("'".concat(_this2._path,"' doesn't exist.")));return}if(_this2._isEOF){var err=new Error("EOF");err.name="EndOfFile";reject(err);return}var copied=0;var maxToCopy=Math.min(size*count,_this2._meta.size);var totalElems=maxToCopy-maxToCopy%size;var buffer=new Uint8Array(totalElems);var res=_this2._cache.get(totalElems);if(res){copied+=res.length;_this2._pageOffset+=res.length;if(_this2._pageOffset===_this2._pageSize){_this2._pagePtr+=1;_this2._pageOffset=0}if(totalElems===copied){resolve(res);return}buffer.set(res)}var keyRange=IDBKeyRange.bound("".concat(_this2._path,"-").concat(PvFileIDB.createPage(_this2._pagePtr)),"".concat(_this2._path,"-").concat(PvFileIDB.createPage(_this2._pagePtr+Math.floor(totalElems/_this2._pageSize)+1)));var store=_this2._store;var req=store.openCursor(keyRange);req.onsuccess=function(){var cursor=req.result;if(!cursor||_this2._isEOF){return}var toCopy=Math.min(totalElems-copied,cursor.value.length-_this2._pageOffset);buffer.set(cursor.value.slice(_this2._pageOffset,_this2._pageOffset+toCopy),copied);copied+=toCopy;_this2._pageOffset+=toCopy;if(_this2._pageOffset===_this2._pageSize){_this2._pagePtr+=1;_this2._pageOffset=0}if(copied1&&_args4[1]!==undefined?_args4[1]:1;return _context4.abrupt("return",new Promise(function(){var _ref=_asyncToGenerator(_regeneratorRuntime.mark(function _callee3(resolve,reject){var _store$transaction3;var store,getCurrentPage,last,newContent,newSize,newMeta,pages,i,keyRange,_store$transaction4;return _regeneratorRuntime.wrap(function _callee3$(_context3){while(1)switch(_context3.prev=_context3.next){case 0:if(!(_this3._mode==="readonly")){_context3.next=3;break}reject(new Error("Instance is readonly mode only."));return _context3.abrupt("return");case 3:if(!(typeof version!=="number"&&version<=0)){_context3.next=6;break}reject(new Error("Version should be a positive number"));return _context3.abrupt("return");case 6:store=_this3._store;getCurrentPage=function getCurrentPage(){return new Promise(function(res){var req=store.get("".concat(_this3._path,"-").concat(PvFileIDB.createPage(_this3._pagePtr)));req.onsuccess=function(){if(req.result!==undefined){res(req.result.slice(0,_this3._pageOffset))}else{res(new Uint8Array(0))}}})};_context3.next=10;return getCurrentPage();case 10:last=_context3.sent;newContent=new Uint8Array(last.length+content.length);newContent.set(last);newContent.set(content,last.length);newSize=_this3._pagePtr*_this3._pageSize+newContent.length;newMeta={size:newSize,numPages:Math.ceil(newSize/_this3._pageSize),version:version,pageSize:_this3._pageSize};store.put(newMeta,_this3._path);pages=Math.ceil(newContent.length/_this3._pageSize);for(i=0;i=this._meta.numPages-1&&this._pageOffset>=this._meta.size%this._pageSize}},{key:"_store",get:function get(){return this._db.transaction(PV_FILE_STORE,this._mode).objectStore(PV_FILE_STORE)}}],[{key:"open",value:function open(path,mode){if(!self.indexedDB){var error=new Error("IndexedDB is not supported");error.name="IndexedDBNotSupported";throw error}return new Promise(function(){var _ref3=_asyncToGenerator(_regeneratorRuntime.mark(function _callee7(resolve,reject){var db,req,_error2;return _regeneratorRuntime.wrap(function _callee7$(_context7){while(1)switch(_context7.prev=_context7.next){case 0:_context7.prev=0;_context7.next=3;return getDB();case 3:db=_context7.sent;req=db.transaction(PV_FILE_STORE,"readwrite").objectStore(PV_FILE_STORE).get(path);req.onerror=function(){reject(req.error)};req.onsuccess=function(){var meta=req.result;var dbMode=mode.includes("r")?"readonly":"readwrite";if(meta===undefined&&dbMode==="readonly"){var _error=new Error("'".concat(path,"' doesn't exist."));_error.name="FileNotExists";reject(_error);return}var fileIDB=new PvFileIDB(path,meta,db,dbMode);if(mode.includes("a")){fileIDB.seek(0,2)}resolve(fileIDB)};_context7.next=12;break;case 9:_context7.prev=9;_context7.t0=_context7["catch"](0);if(_context7.t0.name==="InvalidStateError"){_error2=new Error("IndexedDB is not supported");_error2.name="IndexedDBNotSupported";reject(_error2)}else{reject(_context7.t0)}case 12:case"end":return _context7.stop()}},_callee7,null,[[0,9]])}));return function(_x8,_x9){return _ref3.apply(this,arguments)}}())}},{key:"createPage",value:function createPage(page){return("00000"+page).slice(-6)}}])}(PvFile);function _callSuper(t,o,e){return o=_getPrototypeOf(o),_possibleConstructorReturn(t,_isNativeReflectConstruct()?Reflect.construct(o,e||[],_getPrototypeOf(t).constructor):o.apply(t,e))}function _isNativeReflectConstruct(){try{var t=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch(t){}return(_isNativeReflectConstruct=function _isNativeReflectConstruct(){return!!t})()}var PvFileMem=function(_PvFile){function PvFileMem(path,meta,db,mode){var _this;_classCallCheck(this,PvFileMem);_this=_callSuper(this,PvFileMem);_this._pos=0;_this._path=path;_this._meta=meta;_this._mode=mode;return _this}_inherits(PvFileMem,_PvFile);return _createClass(PvFileMem,[{key:"close",value:function close(){return}},{key:"read",value:function read(size,count){if(!this.exists()){throw new Error("'".concat(this._path,"' doesn't exist."))}if(this._isEOF){var err=new Error("EOF");err.name="EndOfFile";throw err}var toCopy=Math.min(size*count,this._file.length-this._pos);var totalElems=toCopy-toCopy%size;var buffer=new Uint8Array(totalElems);buffer.set(this._file.slice(this._pos,this._pos+totalElems),0);this._pos+=totalElems;return buffer}},{key:"write",value:function write(content){var version=arguments.length>1&&arguments[1]!==undefined?arguments[1]:1;var newFile=new Uint8Array(this._pos+content.length);if(this._file!==undefined){newFile.set(this._file.slice(0,this._pos));newFile.set(content,this._pos)}else{newFile.set(content)}this._file=newFile;this._pos+=content.length}},{key:"seek",value:function seek(offset,whence){if(!this.exists()&&this._mode==="readonly"){throw new Error("'".concat(this._path,"' doesn't exist."))}if(!this.exists()){throw new Error("'".concat(this._path,"' doesn't exist."))}if(offset<0){var err=new Error("EOF");err.name="EndOfFile";throw err}var newOffset;if(whence===0){newOffset=Math.min(offset,this._file.length)}else if(whence===1){newOffset=Math.min(this._pos+offset,this._file.length)}else if(whence===2){newOffset=Math.min(this._file.length+offset,this._file.length)}else{throw new Error("Invalid operation: ".concat(whence,"."))}this._pos=newOffset}},{key:"tell",value:function tell(){if(!this.exists()){return-1}return this._pos}},{key:"remove",value:function(){var _remove=_asyncToGenerator(_regeneratorRuntime.mark(function _callee(){return _regeneratorRuntime.wrap(function _callee$(_context){while(1)switch(_context.prev=_context.next){case 0:if(this.exists()){_context.next=2;break}throw new Error("ENOENT");case 2:PvFileMem._memFiles["delete"](this._path);this._pos=0;case 4:case"end":return _context.stop()}},_callee,this)}));function remove(){return _remove.apply(this,arguments)}return remove}()},{key:"exists",value:function exists(){return this._file!==undefined}},{key:"_isEOF",get:function get(){return this._pos>=this._file.length}},{key:"_file",get:function get(){return PvFileMem._memFiles.get(this._path)},set:function set(content){PvFileMem._memFiles.set(this._path,content)}}],[{key:"open",value:function open(path,mode){var file=PvFileMem._memFiles.get(path);var dbMode=mode.includes("r")?"readonly":"readwrite";if(file===undefined&&dbMode==="readonly"){var error=new Error("'".concat(path,"' doesn't exist."));error.name="FileNotExists";throw error}var fileMem=new PvFileMem(path,undefined,undefined,dbMode);if(mode.includes("a")){fileMem.seek(0,2)}return fileMem}}])}(PvFile);PvFileMem._memFiles=new Map;function unsignedAddress(address){if(address<0){return address>>>0}return address}function _arrayWithHoles(r){if(Array.isArray(r))return r}function _iterableToArrayLimit(r,l){var t=null==r?null:"undefined"!=typeof Symbol&&r[Symbol.iterator]||r["@@iterator"];if(null!=t){var e,n,i,u,a=[],f=!0,o=!1;try{if(i=(t=t.call(r)).next,0===l){if(Object(t)!==t)return;f=!1}else for(;!(f=(e=i.call(t)).done)&&(a.push(e.value),a.length!==l);f=!0);}catch(r){o=!0,n=r}finally{try{if(!f&&null!=t["return"]&&(u=t["return"](),Object(u)!==u))return}finally{if(o)throw n}}return a}}function _arrayLikeToArray$2(r,a){(null==a||a>r.length)&&(a=r.length);for(var e=0,n=Array(a);e=r.length?{done:!0}:{done:!1,value:r[_n++]}},e:function e(r){throw r},f:F}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,a=!0,u=!1;return{s:function s(){t=t.call(r)},n:function n(){var r=t.next();return a=r.done,r},e:function e(r){u=!0,o=r},f:function f(){try{a||null==t["return"]||t["return"]()}finally{if(u)throw o}}}}function _unsupportedIterableToArray$1(r,a){if(r){if("string"==typeof r)return _arrayLikeToArray$1(r,a);var t={}.toString.call(r).slice(8,-1);return"Object"===t&&r.constructor&&(t=r.constructor.name),"Map"===t||"Set"===t?Array.from(r):"Arguments"===t||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t)?_arrayLikeToArray$1(r,a):void 0}}function _arrayLikeToArray$1(r,a){(null==a||a>r.length)&&(a=r.length);for(var e=0,n=Array(a);e=16){this.endComputePass();this.flushCommandEncoder()}}},{key:"endComputePass",value:function endComputePass(){if(this._passEncoder){this._passEncoder.end();this._passEncoder=null}}},{key:"getBuffer",value:function getBuffer(sizeBytes,usage){var mappedAtCreation=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var label=arguments.length>3?arguments[3]:undefined;var key=this.getBufferKey(sizeBytes,usage);if(this.bufferReusePool.has(key)){var buffers=this.bufferReusePool.get(key);if(buffers&&buffers.length>0){return buffers.pop()}}return this.device.createBuffer({size:sizeBytes*Uint8Array.BYTES_PER_ELEMENT,usage:usage,mappedAtCreation:mappedAtCreation,label:label})}},{key:"scheduleUniformBufferForRelease",value:function scheduleUniformBufferForRelease(buffer){this._uniformBuffersPendingRelease.push(buffer)}},{key:"releaseBuffer",value:function releaseBuffer(buffer){var clearBuffer=arguments.length>1&&arguments[1]!==undefined?arguments[1]:true;if(clearBuffer){this.endComputePass();this.commandEncoder.clearBuffer(buffer,0,buffer.size)}var key=this.getBufferKey(buffer.size,buffer.usage);if(!this.bufferReusePool.has(key)){this.bufferReusePool.set(key,[])}this.bufferReusePool.get(key).push(buffer)}},{key:"sync",value:function(){var _sync=_asyncToGenerator(_regeneratorRuntime.mark(function _callee(){var _this=this;var _iterator,_step,k,buffers,_iterator3,_step3,b,_loop,_i,_Object$entries;return _regeneratorRuntime.wrap(function _callee$(_context3){while(1)switch(_context3.prev=_context3.next){case 0:this.endComputePass();this.flushCommandEncoder();_context3.next=4;return this.device.queue.onSubmittedWorkDone();case 4:_iterator=_createForOfIteratorHelper$1(this.bufferReusePool.keys());try{for(_iterator.s();!(_step=_iterator.n()).done;){k=_step.value;buffers=this.bufferReusePool.get(k);if(buffers&&buffers.length>0){_iterator3=_createForOfIteratorHelper$1(buffers);try{for(_iterator3.s();!(_step3=_iterator3.n()).done;){b=_step3.value;b===null||b===void 0||b.destroy()}}catch(err){_iterator3.e(err)}finally{_iterator3.f()}}}}catch(err){_iterator.e(err)}finally{_iterator.f()}this.bufferReusePool.clear();_loop=_regeneratorRuntime.mark(function _loop(){var _Object$entries$_i,shaderName,timestampBuffers,_iterator2,_step2,_loop2;return _regeneratorRuntime.wrap(function _loop$(_context2){while(1)switch(_context2.prev=_context2.next){case 0:_Object$entries$_i=_slicedToArray(_Object$entries[_i],2),shaderName=_Object$entries$_i[0],timestampBuffers=_Object$entries$_i[1];if(!_this.shaderTimes[shaderName]){_this.shaderTimes[shaderName]=[]}_iterator2=_createForOfIteratorHelper$1(timestampBuffers);_context2.prev=3;_loop2=_regeneratorRuntime.mark(function _loop2(){var timestampBuffer;return _regeneratorRuntime.wrap(function _loop2$(_context){while(1)switch(_context.prev=_context.next){case 0:timestampBuffer=_step2.value;timestampBuffer.mapAsync(GPUMapMode.READ).then(function(){var times=new BigInt64Array(timestampBuffer.getMappedRange());var timeDif=times[1]-times[0];timestampBuffer.unmap();timestampBuffer.destroy();_this.shaderTimes[shaderName].push(timeDif)});case 2:case"end":return _context.stop()}},_loop2)});_iterator2.s();case 6:if((_step2=_iterator2.n()).done){_context2.next=10;break}return _context2.delegateYield(_loop2(),"t0",8);case 8:_context2.next=6;break;case 10:_context2.next=15;break;case 12:_context2.prev=12;_context2.t1=_context2["catch"](3);_iterator2.e(_context2.t1);case 15:_context2.prev=15;_iterator2.f();return _context2.finish(15);case 18:case"end":return _context2.stop()}},_loop,null,[[3,12,15,18]])});_i=0,_Object$entries=Object.entries(this.timestampBuffers);case 9:if(!(_i<_Object$entries.length)){_context3.next=14;break}return _context3.delegateYield(_loop(),"t0",11);case 11:_i++;_context3.next=9;break;case 14:this.timestampBuffers={};case 15:case"end":return _context3.stop()}},_callee,this)}));function sync(){return _sync.apply(this,arguments)}return sync}()},{key:"reportShaderTimes",value:function reportShaderTimes(){for(var _i2=0,_Object$entries2=Object.entries(this.shaderTimes);_i2<_Object$entries2.length;_i2++){var _Object$entries2$_i=_slicedToArray(_Object$entries2[_i2],2),shaderName=_Object$entries2$_i[0],shaderTimes=_Object$entries2$_i[1];var timeSum=0n;var _iterator4=_createForOfIteratorHelper$1(shaderTimes),_step4;try{for(_iterator4.s();!(_step4=_iterator4.n()).done;){var shaderTime=_step4.value;timeSum=timeSum+shaderTime}}catch(err){_iterator4.e(err)}finally{_iterator4.f()}var totalSeconds=Number(timeSum)*1e-9;var avgSeconds=(totalSeconds/shaderTimes.length).toFixed(7);console.log("".concat(shaderName,", ").concat(totalSeconds.toFixed(5),", ").concat(avgSeconds))}this.shaderTimes={}}},{key:"flushCommandEncoder",value:function flushCommandEncoder(){var _this2=this;this.device.queue.submit([this.commandEncoder.finish()]);this._commandEncoder=null;this._numCommandsEncoded=0;this._stageBuffersPendingMap.forEach(function(buffer){buffer.destroy()});this._stageBuffersPendingMap=[];this._uniformBuffersPendingRelease.forEach(function(buffer){_this2.releaseBuffer(buffer,false)});this._uniformBuffersPendingRelease=[]}},{key:"writeBuffer",value:function writeBuffer(sizeBytes,offset,srcArray,dstBuffer){var stagingBuffer=this.getBuffer(sizeBytes,GPUBufferUsage.MAP_WRITE|GPUBufferUsage.COPY_SRC,true);new Uint8Array(stagingBuffer.getMappedRange()).set(srcArray);stagingBuffer.unmap();this._stageBuffersPendingMap.push(stagingBuffer);this.endComputePass();this.commandEncoder.copyBufferToBuffer(stagingBuffer,0,dstBuffer,offset,sizeBytes);this.numCommandsEncoded++}},{key:"dispatchComputerShader",value:function dispatchComputerShader(bindGroup,pipeline,shaderName,workgroupCountX,workgroupCountY,workgroupCountZ){if(this.isTimerEnabled){var querySet=this.device.createQuerySet({type:"timestamp",count:2});var timestampWrites={querySet:querySet,beginningOfPassWriteIndex:0,endOfPassWriteIndex:1};this.endComputePass();this._passEncoder=this.commandEncoder.beginComputePass({timestampWrites:timestampWrites});this._passEncoder.setBindGroup(0,bindGroup);this._passEncoder.setPipeline(pipeline);this._passEncoder.dispatchWorkgroups(workgroupCountX,workgroupCountY,workgroupCountZ);this.endComputePass();var size=2*BigInt64Array.BYTES_PER_ELEMENT;var resolveBuffer=this.device.createBuffer({size:size,usage:GPUBufferUsage.QUERY_RESOLVE|GPUBufferUsage.COPY_SRC});this.commandEncoder.resolveQuerySet(querySet,0,2,resolveBuffer,0);var resultBuffer=this.device.createBuffer({size:size,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ});this.commandEncoder.copyBufferToBuffer(resolveBuffer,0,resultBuffer,0,size);if(!this.timestampBuffers[shaderName]){this.timestampBuffers[shaderName]=[]}this.timestampBuffers[shaderName].push(resultBuffer);this.numCommandsEncoded+=3}else{if(!this._passEncoder){this._passEncoder=this.commandEncoder.beginComputePass()}this._passEncoder.setBindGroup(0,bindGroup);this._passEncoder.setPipeline(pipeline);this._passEncoder.dispatchWorkgroups(workgroupCountX,workgroupCountY,workgroupCountZ);this.numCommandsEncoded++}}}])}();var PV_PICOLLM_WEBGPU_DEFAULT_WORKGROUP_SIZE=256;var gpuDevices=new Map;var gpuBuffers=new Map;var emptyShader="\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main_empty() {}\n";var shaderEntryPoint="main";var PRECOMPUTE_ENCODING_SHADER_NAME="pv_picollm_attention_precompute_encoding_shader";var attentionPrecomputeEncodingShaderSource="\nstruct argsStruct {\n dimension: u32,\n steps: u32,\n theta: f32,\n encoding_offset: u32,\n rope_scale: f32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar encoding: array;\n\n@group(0) @binding(2)\nvar rope_scales: array;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(\n @builtin(local_invocation_id) local_id: vec3,\n @builtin(workgroup_id) workgroup_id: vec3,\n @builtin(num_workgroups) num_workgroups: vec3\n) {\n let ts = workgroup_id.x;\n let ds = local_id.x;\n \n for (var t = ts; t < args.steps; t += num_workgroups.x) {\n for (var d = ds; d < (args.dimension / 2u); d += workgroup_size_x) {\n let f = 2u * d;\n let x = f32(t) / (f32(rope_scales[f >> 1]) * pow(args.theta, f32(f) / f32(args.dimension)));\n let encoding_idx = args.encoding_offset + (t * args.dimension) + f;\n encoding[encoding_idx] = cos(x) * args.rope_scale;\n encoding[encoding_idx + 1] = sin(x) * args.rope_scale;\n }\n }\n}\n\n".concat(emptyShader);var loadAttentionPrecomputeEncodingShader=function loadAttentionPrecomputeEncodingShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"attention precompute encoding bind group layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"attention precompute encoding pipeline layout",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"attention precompute encoding shader module",code:attentionPrecomputeEncodingShaderSource});var computePipeline=device.createComputePipeline({label:"attention precompute encoding pipeline",layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint,constants:{workgroup_size_x:PV_PICOLLM_WEBGPU_DEFAULT_WORKGROUP_SIZE}}});return{computePipeline:computePipeline}};var ENCODE_ROPE_INTERLEAVED_SHADER_NAME="pv_picollm_attention_encode_rope_interleaved_shader";var attentionEncodeRopeInterleavedShaderSource="\nstruct argsStruct { \n n: u32,\n num_heads: u32,\n head_dimension: u32,\n rope_dimension: u32,\n position: u32,\n encoding_offset: u32,\n x_offset: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar encoding: array;\n\n@group(0) @binding(2)\nvar x: array;\n \noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(\n @builtin(local_invocation_id) local_id: vec3,\n @builtin(workgroup_id) workgroup_id: vec3,\n @builtin(num_workgroups) num_workgroups: vec3\n) {\n let ts = workgroup_id.x;\n let h = workgroup_id.y;\n let ds = local_id.x;\n\n for (var t = ts; t < args.n; t += num_workgroups.x) {\n let x_start = args.x_offset + (t * args.num_heads + h) * args.head_dimension;\n let encoding_start = args.encoding_offset + ((t + args.position) * args.rope_dimension); \n for (var d = ds; d < (args.head_dimension / 2u); d += workgroup_size_x) {\n let i = 2u * d;\n let x_idx = x_start + i;\n let encoding_idx = encoding_start + i;\n \n let re = x[x_idx];\n let im = x[x_idx + 1];\n x[x_idx] = (re * encoding[encoding_idx]) - (im * encoding[encoding_idx + 1]);\n x[x_idx + 1] = (re * encoding[encoding_idx + 1]) + (im * encoding[encoding_idx]);\n }\n }\n}\n\n".concat(emptyShader);var loadAttentionEncodeRopeInterleavedShader=function loadAttentionEncodeRopeInterleavedShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"attention encode rope interleave bind group layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"attention encode rope interleave pipeline layout",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"attention encode rope interleave shader module",code:attentionEncodeRopeInterleavedShaderSource});var computePipeline=device.createComputePipeline({label:"attention encode rope interleave pipeline",layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint,constants:{workgroup_size_x:PV_PICOLLM_WEBGPU_DEFAULT_WORKGROUP_SIZE}}});return{computePipeline:computePipeline}};var ENCODE_SHADER_NAME="pv_picollm_attention_encode_shader";var attentionEncodeShaderSource="\nstruct argsStruct { \n n: u32,\n num_heads: u32,\n head_dimension: u32,\n rope_dimension: u32,\n position: u32,\n encoding_offset: u32,\n x_offset: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar encoding: array;\n\n@group(0) @binding(2)\nvar x: array;\n \noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(\n @builtin(local_invocation_id) local_id: vec3,\n @builtin(workgroup_id) workgroup_id: vec3,\n @builtin(num_workgroups) num_workgroups: vec3\n) {\n let ts = workgroup_id.x;\n let h = workgroup_id.y;\n let ds = local_id.x;\n\n for (var t = ts; t < args.n; t += num_workgroups.x) {\n let half_rope = (args.rope_dimension / 2);\n let xr_start = args.x_offset + ((t * args.num_heads + h) * args.head_dimension);\n let xi_start = xr_start + half_rope;\n let encoding_start = args.encoding_offset + ((t + args.position) * args.rope_dimension); \n for (var d = ds; d < half_rope; d += workgroup_size_x) {\n let xr_idx = xr_start + d;\n let xi_idx = xi_start + d;\n let encoding_idx = encoding_start + (2 * d);\n\n let re = x[xr_idx];\n let im = x[xi_idx];\n x[xr_idx] = (re * encoding[encoding_idx]) - (im * encoding[encoding_idx + 1]);\n x[xi_idx] = (re * encoding[encoding_idx + 1]) + (im * encoding[encoding_idx]);\n }\n }\n}\n\n".concat(emptyShader);var loadAttentionEncodeShader=function loadAttentionEncodeShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"attention encode bind layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"attention encode pipeline layout",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"attention encode shader",code:attentionEncodeShaderSource});var computePipeline=device.createComputePipeline({label:"attention encode pipeline",layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint,constants:{workgroup_size_x:PV_PICOLLM_WEBGPU_DEFAULT_WORKGROUP_SIZE}}});return{computePipeline:computePipeline}};var DOT_PRODUCT_SHADER_NAME="pv_picollm_attention_dot_product_shader";var attentionDotProductShaderSource="\nstruct argsStruct { \n n: u32,\n tq: u32,\n head_dimension: u32,\n num_heads: u32,\n num_kv_heads: u32,\n window_length: u32,\n start: u32,\n norm: f32,\n length1: u32,\n num_keys: u32,\n query_offset: u32,\n keys_offset: u32,\n key_intercepts_offset: u32,\n key_slopes_offset: u32,\n scores_offset: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar query: array;\n\n@group(0) @binding(2)\nvar keys: array;\n\n@group(0) @binding(3)\nvar key_intercepts: array;\n\n@group(0) @binding(4)\nvar key_slopes: array;\n\n@group(0) @binding(5)\nvar scores: array;\n \noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= args.num_heads) {\n return;\n }\n\n let head = global_id.x / (args.num_heads / args.num_kv_heads);\n \n let head_offset = head * args.window_length;\n let start_index = head_offset + args.start;\n \n let keys_local_a = args.keys_offset + (start_index * args.head_dimension);\n let key_intercepts_local_a = args.key_intercepts_offset + start_index; \n let key_slopes_local_a = args.key_slopes_offset + start_index;\n \n let keys_local_b = args.keys_offset + (head_offset * args.head_dimension);\n let key_intercepts_local_b = args.key_intercepts_offset + head_offset; \n let key_slopes_local_b = args.key_slopes_offset + head_offset;\n \n let scores_local = args.scores_offset + (global_id.x * args.num_keys);\n let query_local = args.query_offset + (((global_id.x * args.n) + args.tq) * args.head_dimension);\n \n for (var i = 0u; i < args.head_dimension; i++) { \n for (var k = 0u; k < args.num_keys; k++) {\n if (k < args.length1) { \n let key_idx = keys_local_a + (k * args.head_dimension) + i;\n let key_val = f32(extractBits(keys[key_idx / 4], (i * 8u) % 32u, 8u));\n let tmp = query[query_local + i] * (key_intercepts[key_intercepts_local_a + k] + (key_slopes[key_slopes_local_a + k] * key_val));\n scores[scores_local + k] += tmp;\n }\n else {\n let j = k - args.length1;\n let key_idx = keys_local_b + (j * args.head_dimension) + i;\n let key_val = f32(extractBits(keys[key_idx / 4], (i * 8u) % 32u, 8u));\n let tmp = query[query_local + i] * (key_intercepts[key_intercepts_local_b + j] + (key_slopes[key_slopes_local_b + j] * key_val));\n scores[scores_local + k] += tmp;\n }\n } \n }\n \n for (var k = 0u; k < args.num_keys; k++) {\n scores[scores_local + k] *= args.norm;\n }\n}\n\n".concat(emptyShader);var loadAttentionDotProductShader=function loadAttentionDotProductShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"attention dot product bind group layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:3,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:4,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:5,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"attention dot product pipeline layout",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"attention dot product shader module",code:attentionDotProductShaderSource});var computePipeline=device.createComputePipeline({label:"attention dot product pipeline",layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint}});return{computePipeline:computePipeline}};var SOFTMAX_SHADER_NAME="pv_picollm_attention_softmax_shader";var attentionSoftmaxShaderSource="\nstruct argsStruct { \n num_heads: u32,\n num_keys: u32,\n scores_offset: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar scores: array;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= args.num_heads) {\n return;\n }\n\n let scores_start = args.scores_offset + (global_id.x * args.num_keys);\n \n var max_index: u32 = 0;\n for (var i = 1u; i < args.num_keys; i++) {\n if (scores[scores_start + i] > scores[scores_start + max_index]) {\n max_index = i;\n }\n }\n let max: f32 = scores[scores_start + max_index];\n\n var sum: f32 = 0.0;\n for (var i = 0u; i < args.num_keys; i++) {\n scores[scores_start + i] = exp(scores[scores_start + i] - max);\n sum += scores[scores_start + i];\n }\n\n for (var i = 0u; i < args.num_keys; i++) {\n scores[scores_start + i] /= sum;\n }\n}\n\n".concat(emptyShader);var loadAttentionSoftmaxShader=function loadAttentionSoftmaxShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"attention softmax bind group layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"attention softmax pipeline layout",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"attention softmax shader module",code:attentionSoftmaxShaderSource});var computePipeline=device.createComputePipeline({label:"attention softmax pipeline",layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint}});return{computePipeline:computePipeline}};var FIR_SHADER_NAME="pv_picollm_attention_fir_shader";var attentionFirShaderSource="\nstruct argsStruct { \n length1: u32,\n length2: u32,\n tq: u32,\n head_dimension: u32,\n num_heads: u32,\n num_kv_heads: u32,\n window_length: u32,\n start: u32,\n values_offset: u32,\n value_intercepts_offset: u32,\n value_slopes_offset: u32,\n scores_offset: u32,\n output_offset: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar values: array;\n\n@group(0) @binding(2)\nvar value_intercepts: array;\n\n@group(0) @binding(3)\nvar value_slopes: array;\n\n@group(0) @binding(4)\nvar scores: array;\n\n@group(0) @binding(5)\nvar output: array;\n \noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= args.num_heads) {\n return;\n }\n\n let head = global_id.x / (args.num_heads / args.num_kv_heads);\n\n let head_offset = head * args.window_length;\n let start_index = head_offset + args.start;\n\n let values_local_a = args.values_offset + (start_index * args.head_dimension);\n let value_intercepts_local_a = args.value_intercepts_offset + start_index;\n let value_slopes_local_a = args.value_slopes_offset + start_index;\n let values_local_b = args.values_offset + (head_offset * args.head_dimension);\n let value_intercepts_local_b = args.value_intercepts_offset + head_offset;\n let value_slopes_local_b = args.value_slopes_offset + head_offset;\n let scores_local = args.scores_offset + (global_id.x * (args.length1 + args.length2));\n let output_local = args.output_offset + (((args.tq * args.num_heads) + global_id.x) * args.head_dimension);\n\n for (var i = 0u; i < args.head_dimension; i++) {\n var tmp: f32 = 0.0;\n for (var k = 0u; k < args.length1; k++) {\n let value_idx = values_local_a + (k * args.head_dimension) + i;\n let value_val = f32(extractBits(values[value_idx / 4], (i * 8u) % 32u, 8u));\n tmp += scores[scores_local + k] * (value_intercepts[value_intercepts_local_a + k] + (value_slopes[value_slopes_local_a + k] * value_val)); \n }\n for (var k = 0u; k < args.length2; k++) {\n let value_idx = values_local_b + (k * args.head_dimension) + i;\n let value_val = f32(extractBits(values[value_idx / 4], (i * 8u) % 32u, 8u));\n tmp += scores[scores_local + args.length1 + k] * (value_intercepts[value_intercepts_local_b + k] + (value_slopes[value_slopes_local_b + k] * value_val)); \n }\n output[output_local + i] = tmp;\n }\n}\n\n".concat(emptyShader);var loadAttentionFirShader=function loadAttentionFirShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"attention fir bind group layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:3,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:4,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:5,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"attention fir pipeline layout",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"attention fir shader module",code:attentionFirShaderSource});var computePipeline=device.createComputePipeline({label:"attention fir pipeline",layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint}});return{computePipeline:computePipeline}};var UPDATE_KV_SHADER_NAME="pv_picollm_attention_update_kv_shader";var attentionUpdateKvShaderSource="\nstruct argsStruct {\n n: u32,\n num_kv_heads: u32,\n window_length: u32,\n position: u32,\n head_dimension: u32,\n tf_offset: u32,\n kv_offset: u32,\n kv_intercepts_offset: u32,\n kv_slopes_offset: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar tf: array;\n\n@group(0) @binding(2)\nvar kv: array;\n\n@group(0) @binding(3)\nvar kv_intercepts: array;\n\n@group(0) @binding(4)\nvar kv_slopes: array;\n \noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) { \n if (global_id.x >= args.num_kv_heads) {\n return;\n }\n \n for (var i = 0u; i < args.n; i++) {\n let index = (global_id.x * args.window_length) + ((args.position + i) % args.window_length);\n let tf_start = args.tf_offset + (((i * args.num_kv_heads) + global_id.x) * args.head_dimension);\n let kv_start = args.kv_offset + ((index * args.head_dimension) / 4);\n let kv_intercepts_start = args.kv_intercepts_offset + index;\n let kv_slopes_start = args.kv_slopes_offset + index;\n \n var xmax = tf[tf_start]; \n var xmin = tf[tf_start]; \n \n for (var j = 1u; j < args.head_dimension; j++) {\n xmax = max(xmax, tf[tf_start + j]);\n xmin = min(xmin, tf[tf_start + j]);\n }\n\n kv_intercepts[kv_intercepts_start] = xmin;\n kv_slopes[kv_slopes_start] = f32(xmax - xmin) / 255.0;\n\n for (var j = 0u; j < args.head_dimension; j++) {\n let kv_idx = kv_start + (j / 4);\n let kv_val = u32(round((tf[tf_start + j] - xmin) / kv_slopes[kv_slopes_start])); \n kv[kv_idx] = insertBits(kv[kv_idx], extractBits(kv_val, 0u, 8u), (j * 8u) % 32u, 8u); \n }\n }\n}\n\n".concat(emptyShader);var loadAttentionUpdateKvShader=function loadAttentionUpdateKvShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"attention update kv bind group layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}},{binding:3,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}},{binding:4,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"attention update kv pipeline layout",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"attention update kv shader module",code:attentionUpdateKvShaderSource});var computePipeline=device.createComputePipeline({label:"attention update kv pipeline",layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint}});return{computePipeline:computePipeline}};var TRANSPOSE_QUERY_SHADER_NAME="pv_picollm_attention_transpose_query_shader";var attentionTransposeQueryShaderSource="\nstruct argsStruct {\n n: u32,\n num_heads: u32,\n head_dimension: u32,\n tf_offset: u32,\n hf_offset: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar tf: array;\n\n@group(0) @binding(2)\nvar hf: array;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(\n @builtin(workgroup_id) workgroup_id : vec3,\n @builtin(local_invocation_id) local_id : vec3\n) {\n\n if (workgroup_id.x >= args.num_heads || workgroup_id.y >= args.n || local_id.x >= args.head_dimension) {\n return;\n }\n \n let tf_idx = args.tf_offset + (workgroup_id.y * args.num_heads * args.head_dimension) + (workgroup_id.x * args.head_dimension) + local_id.x; \n let hf_idx = args.hf_offset + (workgroup_id.x * args.n * args.head_dimension) + (workgroup_id.y * args.head_dimension) + local_id.x; \n hf[hf_idx] = tf[tf_idx];\n}\n\n".concat(emptyShader);var loadAttentionTransposeQueryShader=function loadAttentionTransposeQueryShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"attention transpose query bind group layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"attention transpose query pipeline layout",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"attention transpose query shader module",code:attentionTransposeQueryShaderSource});var computePipeline=device.createComputePipeline({label:"attention transpose query pipeline",layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint,constants:{workgroup_size_x:PV_PICOLLM_WEBGPU_DEFAULT_WORKGROUP_SIZE}}});return{computePipeline:computePipeline}};var attentionShaders=_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty({},PRECOMPUTE_ENCODING_SHADER_NAME,loadAttentionPrecomputeEncodingShader),ENCODE_ROPE_INTERLEAVED_SHADER_NAME,loadAttentionEncodeRopeInterleavedShader),ENCODE_SHADER_NAME,loadAttentionEncodeShader),DOT_PRODUCT_SHADER_NAME,loadAttentionDotProductShader),SOFTMAX_SHADER_NAME,loadAttentionSoftmaxShader),FIR_SHADER_NAME,loadAttentionFirShader),UPDATE_KV_SHADER_NAME,loadAttentionUpdateKvShader),TRANSPOSE_QUERY_SHADER_NAME,loadAttentionTransposeQueryShader);var SILU_SHADER_NAME="pv_picollm_feed_forward_silu_shader";var feedForwardSiluShaderSource="\nstruct argsStruct {\n n: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar x: array;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= args.n) {\n return;\n }\n x[global_id.x] = x[global_id.x] / (1.0 + exp(-x[global_id.x]));\n}\n\n".concat(emptyShader);var loadFeedForwardSiluShader=function loadFeedForwardSiluShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"ff silu bind group layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"ff silu pipeline layout",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"ff silu shader module",code:feedForwardSiluShaderSource});var computePipeline=device.createComputePipeline({label:"ff silu pipline",layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint,constants:{workgroup_size_x:PV_PICOLLM_WEBGPU_DEFAULT_WORKGROUP_SIZE}}});return{computePipeline:computePipeline}};var GELU_SHADER_NAME="pv_picollm_feed_forward_gelu_shader";var feedForwardGeluShaderSource="\nstruct argsStruct {\n n: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar x: array;\n\nconst a1: f32 = 0.254829592;\nconst a2: f32 = -0.284496736;\nconst a3: f32 = 1.421413741;\nconst a4: f32 = -1.453152027;\nconst a5: f32 = 1.061405429;\nconst p: f32 = 0.3275911;\n\n// A&S formula 7.1.26\nfn erf(x: f32) -> f32 { \n var sign: f32 = 1.0;\n if (x < 0) {\n sign = -1.0;\n }\n var x_abs: f32 = abs(x);\n \n let t: f32 = 1.0 / fma(p, x_abs, 1.0);\n let y: f32 = 1.0 - (((((a5 * t + a4) * t) + a3) * t + a2) * t + a1) * t * exp(-x_abs * x_abs);\n\n return sign * y;\n}\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= args.n) {\n return;\n }\n x[global_id.x] = 0.5 * x[global_id.x] * (1.0 + erf(x[global_id.x] * 0.7071067811865475));\n}\n\n".concat(emptyShader);var loadFeedForwardGeluShader=function loadFeedForwardGeluShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"ff gelu bind group layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"ff gelu pipeline layout",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"ff gelu shader module",code:feedForwardGeluShaderSource});var computePipeline=device.createComputePipeline({label:"ff gelu pipeline",layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint,constants:{workgroup_size_x:PV_PICOLLM_WEBGPU_DEFAULT_WORKGROUP_SIZE}}});return{computePipeline:computePipeline}};var ALMOST_GELU_SHADER_NAME="pv_picollm_feed_forward_almost_gelu_shader";var feedForwardAlmostGeluShaderSource="\nstruct argsStruct {\n n: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar x: array;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= args.n) {\n return;\n }\n x[global_id.x] = 0.5 * x[global_id.x] * (1 + tanh(0.7978845608028654 * (x[global_id.x] + (0.044715f * x[global_id.x] * x[global_id.x] * x[global_id.x]))));\n}\n\n".concat(emptyShader);var loadFeedForwardAlmostGeluShader=function loadFeedForwardAlmostGeluShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"ff almost gelu bind group layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"ff almost gelu pipeline layout",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"ff almost gelu shader module",code:feedForwardAlmostGeluShaderSource});var computePipeline=device.createComputePipeline({label:"ff almost gelu pipeline",layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint,constants:{workgroup_size_x:PV_PICOLLM_WEBGPU_DEFAULT_WORKGROUP_SIZE}}});return{computePipeline:computePipeline}};var MULTIPLY_BUFFERS_SHADER_NAME="pv_picollm_feed_forward_multiply_buffers_shader";var feedForwardMultiplyBuffersShaderSource="\nstruct argsStruct {\n n: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar x: array;\n\n@group(0) @binding(2)\nvar y: array;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= args.n) {\n return;\n }\n y[global_id.x] *= x[global_id.x];\n}\n\n".concat(emptyShader);var loadFeedForwardMultiplyBuffersShader=function loadFeedForwardMultiplyBuffersShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"ff multiply buffers bind group layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"ff multiply buffers pipeline layout",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"ff multiply buffers shader module",code:feedForwardMultiplyBuffersShaderSource});var computePipeline=device.createComputePipeline({label:"ff multiply buffers pipeline",layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint,constants:{workgroup_size_x:PV_PICOLLM_WEBGPU_DEFAULT_WORKGROUP_SIZE}}});return{computePipeline:computePipeline}};var feedForwardShaders=_defineProperty(_defineProperty(_defineProperty(_defineProperty({},SILU_SHADER_NAME,loadFeedForwardSiluShader),GELU_SHADER_NAME,loadFeedForwardGeluShader),ALMOST_GELU_SHADER_NAME,loadFeedForwardAlmostGeluShader),MULTIPLY_BUFFERS_SHADER_NAME,loadFeedForwardMultiplyBuffersShader);var FORWARD_SHADER_NAME$1="pv_picollm_gate_forward_shader";var gateForwardShaderSource="\n\nstruct pv_picollm_gate_ix_t {\n i: u32,\n x: f32,\n}\n\n@group(0) @binding(0)\nvar y: array;\n\n@group(0) @binding(1)\nvar indices: array;\n\n@group(0) @binding(2)\nvar weights: array;\n\noverride n: u32 = 0;\noverride k: u32 = 0;\noverride num_experts: u32 = 0;\n\noverride y_offset: u32 = 0;\noverride indices_offset: u32 = 0;\noverride weights_offset: u32 = 0;\n\nvar ixs: array;\n \noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(\n @builtin(global_invocation_id) global_id : vec3\n) {\n if (global_id.x >= n) {\n return;\n }\n \n var y_start: u32 = y_offset + global_id.x * num_experts;\n for (var j = 0u; j < num_experts; j++) {\n ixs[j].i = j;\n ixs[j].x = y[y_start + j];\n }\n\n for (var i = 0u; i < num_experts - 1; i++) {\n for (var j = 0u; j < num_experts - i - 1; j++) {\n if (ixs[j].x < ixs[j + 1].x) {\n let tmp = ixs[j];\n ixs[j] = ixs[j + 1];\n ixs[j + 1] = tmp;\n }\n }\n }\n\n for (var j = 0u; j < k; j++) {\n indices[indices_offset + (global_id.x * k) + j] = ixs[j].i;\n weights[weights_offset + (global_id.x * k) + j] = ixs[j].x;\n }\n\n var max_weight: f32 = weights[weights_offset + (global_id.x * k)];\n for (var j = 1u; j < k; j++) {\n max_weight = max(max_weight, weights[weights_offset + (global_id.x * k) + j]);\n }\n\n var sum_weight: f32 = 0.0;\n for (var j = 0u; j < k; j++) {\n weights[weights_offset + (global_id.x * k) + j] = exp(weights[weights_offset + (global_id.x * k) + j] - max_weight);\n sum_weight += weights[weights_offset + (global_id.x * k) + j];\n }\n\n for (var j = 0u; j < k; j++) {\n weights[weights_offset + (global_id.x * k) + j] /= sum_weight;\n }\n}\n\n".concat(emptyShader);var loadGateForwardShader=function loadGateForwardShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"gate forward bind group layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"gate forward pipeline",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"gate forward shader module",code:gateForwardShaderSource});var computePipeline=device.createComputePipeline({layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint,constants:{num_experts:1}}});return{computePipeline:computePipeline,pipelineLayout:pipelineLayout,shaderModule:shaderModule}};var gateForwardShader=_defineProperty({},FORWARD_SHADER_NAME$1,loadGateForwardShader);var ADD_TO_BUFFER_SHADER_NAME$1="pv_picollm_moe_transformer_add_to_buffer_shader";var moeTransformerAddToBufferShaderSource="\nstruct argsStruct {\n n: u32, \n x_offset: u32,\n buffer_offset: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar x: array;\n\n@group(0) @binding(2)\nvar buffer: array;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= args.n) {\n return;\n }\n\n buffer[args.buffer_offset + global_id.x] += x[args.x_offset + global_id.x]; \n}\n\n".concat(emptyShader);var loadMoeTransformerAddToBufferShader=function loadMoeTransformerAddToBufferShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"moe transformer add to buffer bind group layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"moe transformer add to buffer pipeline",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"moe transformer add to buffer shader module",code:moeTransformerAddToBufferShaderSource});var computePipeline=device.createComputePipeline({label:"moe transformer add to buffer pipeline",layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint}});return{computePipeline:computePipeline}};var MULTIPLY_WEIGHT_AND_ADD_TO_BUFFER_SHADER_NAME="pv_picollm_moe_transformer_multiply_weight_and_add_to_buffer_shader";var moeTransformerMultiplyWeightAndToBufferShaderSource="\nstruct argsStruct {\n n: u32, \n weights_index: u32,\n y_index: u32,\n weights_offset: u32,\n x_offset: u32,\n y_offset: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar weights: array;\n\n@group(0) @binding(2)\nvar x: array;\n\n@group(0) @binding(3)\nvar y: array;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= args.n) {\n return;\n }\n \n y[args.y_offset + args.y_index + global_id.x] += weights[args.weights_index] + x[args.x_offset + global_id.x]; \n}\n\n".concat(emptyShader);var loadMoeTransformerMultiplyWeightAndAddToBufferShader=function loadMoeTransformerMultiplyWeightAndAddToBufferShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"moe transformer multiply weight and add to buffer bind group layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:3,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"moe transformer multiply weight and add to buffer pipeline",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"moe transformer multiply weight and add to buffer shader module",code:moeTransformerMultiplyWeightAndToBufferShaderSource});var computePipeline=device.createComputePipeline({label:"moe transformer multiply weight and add to buffer pipeline",layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint}});return{computePipeline:computePipeline}};var ADD_BUFFERS_SHADER_NAME$1="pv_picollm_moe_transformer_add_buffers_shader";var moeTransformerAddBuffersShaderSource="\nstruct argsStruct {\n n: u32, \n buffer1_offset: u32,\n buffer2_offset: u32,\n y_offset: u32, \n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar buffer1: array;\n\n@group(0) @binding(2)\nvar buffer2: array;\n\n@group(0) @binding(3)\nvar y: array;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= args.n) {\n return;\n }\n \n y[args.y_offset + global_id.x] = buffer1[args.buffer1_offset + global_id.x] + buffer2[args.buffer2_offset + global_id.x]; \n}\n\n".concat(emptyShader);var loadMoeTransformerAddBuffersShader=function loadMoeTransformerAddBuffersShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"moe transformer add buffers bind group layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:3,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"moe transformer add buffers pipeline layout",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"moe transformer add buffers shader module",code:moeTransformerAddBuffersShaderSource});var computePipeline=device.createComputePipeline({label:"moe transformer add buffers pipeline",layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint}});return{computePipeline:computePipeline}};var moeTransformerForwardShaders=_defineProperty(_defineProperty(_defineProperty({},ADD_TO_BUFFER_SHADER_NAME$1,loadMoeTransformerAddToBufferShader),MULTIPLY_WEIGHT_AND_ADD_TO_BUFFER_SHADER_NAME,loadMoeTransformerMultiplyWeightAndAddToBufferShader),ADD_BUFFERS_SHADER_NAME$1,loadMoeTransformerAddBuffersShader);var sdataReduce="\n for (var s: u32 = workgroup_size_x / 2; s > 0; s >>= 1) {\n if tid < s {\n sdata[tid] += sdata[tid + s];\n }\n workgroupBarrier();\n }\n";var dividePadFunction="\n fn divide_pad(a: u32, b: u32) -> u32 { \n return (a + b - 1) / b;\n }\n";var FORWARD_MULTI_BUFFER_SHADER_NAME$1="pv_picollm_norm_forward_multi_buffer_shader";var FORWARD_SINGLE_BUFFER_SHADER_NAME$1="pv_picollm_norm_forward_single_buffer_shader";var normForwardShaderSource=function normForwardShaderSource(isMulti){return"\nstruct argsStruct {\n n: u32,\n dimension: u32,\n remainder: u32,\n remainder_start: u32, \n eps: f32, \n x_offset: u32,\n y_offset: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar weight: array;\n\n".concat(isMulti?"\n@group(0) @binding(2)\nvar x: array;\n\n@group(0) @binding(3) \nvar y: array;\n":" \n@group(0) @binding(2)\nvar x: array;\n","\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\nvar sdata: array, workgroup_size_x>;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(\n @builtin(local_invocation_id) local_id: vec3,\n @builtin(workgroup_id) workgroup_id: vec3\n) {\n let tid = local_id.x;\n let m = workgroup_id.x;\n let block_size = workgroup_size_x;\n \n var power_vec: vec4;\n let x_start: u32 = args.x_offset + (m * args.dimension);\n let skip = tid * 4;\n let shift = (block_size * 4);\n for (var j = 0u; j + skip < args.remainder_start; j += shift) {\n let local_index = x_start + j + skip; \n\n let x_vec = vec4(\n x[local_index],\n x[local_index + 1],\n x[local_index + 2],\n x[local_index + 3]);\n \n power_vec += x_vec * x_vec; \n } \n \n if (tid == 0 && args.remainder > 0) {\n var remainder_vec = vec4(0.0, 0.0, 0.0, 0.0);\n let x_idx = x_start + args.remainder_start;\n for (var j = 0u; j < args.remainder; j++) { \n remainder_vec[j] = x[x_idx + j];\n } \n power_vec += remainder_vec * remainder_vec;\n }\n \n sdata[tid] = power_vec;\n workgroupBarrier();\n\n ").concat(sdataReduce,"\n \n let power = sdata[0].x + sdata[0].y + sdata[0].z + sdata[0].w;\n let norm: vec4 = vec4(1.0 / sqrt((power / f32(args.dimension)) + args.eps));\n \n let y_start: u32 = args.y_offset + (m * args.dimension);\n for (var j = 0u; j + skip < args.remainder_start; j += shift) {\n let local_index = j + skip;\n let x_idx = x_start + local_index;\n let x_vec = vec4(\n x[x_idx],\n x[x_idx + 1],\n x[x_idx + 2],\n x[x_idx + 3]);\n \n let weight_vec = vec4(\n weight[local_index],\n weight[local_index + 1],\n weight[local_index + 2],\n weight[local_index + 3]);\n let y_vec = x_vec * norm * weight_vec;\n \n let y_idx = y_start + local_index;\n").concat(isMulti?" \n y[y_idx] = y_vec.x;\n y[y_idx + 1] = y_vec.y;\n y[y_idx + 2] = y_vec.z;\n y[y_idx + 3] = y_vec.w;\n":" \n x[y_idx] = y_vec.x;\n x[y_idx + 1] = y_vec.y;\n x[y_idx + 2] = y_vec.z;\n x[y_idx + 3] = y_vec.w;\n"," \n }\n \n if (tid == 0 && args.remainder > 0) {\n let x_idx = x_start + args.remainder_start;\n let weight_idx = args.remainder_start; \n let y_idx = y_start + args.remainder_start;\n for (var j = 0u; j < args.remainder; j++) {\n").concat(isMulti?" \n y[y_idx + j] = x[x_idx + j] * norm[j] * weight[weight_idx + j];\n":" \n x[y_idx + j] = x[x_idx + j] * norm[j] * weight[weight_idx + j];\n"," \n } \n }\n}\n\n").concat(emptyShader)};var loadNormForwardShader=function loadNormForwardShader(device,isMulti){var entries=[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}}];if(isMulti){entries.push({binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}});entries.push({binding:3,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}})}else{entries.push({binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}})}var bindGroupLayout=device.createBindGroupLayout({label:"norm forward ".concat(isMulti?"multi":"single"," buffer bind group layout"),entries:entries});var pipelineLayout=device.createPipelineLayout({label:"norm forward ".concat(isMulti?"multi":"single"," buffer pipeline layout"),bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"norm forward ".concat(isMulti?"multi":"single"," buffer shader module"),code:normForwardShaderSource(isMulti)});var computePipeline=device.createComputePipeline({label:"norm forward ".concat(isMulti?"multi":"single"," buffer pipeline"),layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint,constants:{workgroup_size_x:PV_PICOLLM_WEBGPU_DEFAULT_WORKGROUP_SIZE}}});return{computePipeline:computePipeline}};var normForwardShader=_defineProperty(_defineProperty({},FORWARD_SINGLE_BUFFER_SHADER_NAME$1,function(device){return loadNormForwardShader(device,false)}),FORWARD_MULTI_BUFFER_SHADER_NAME$1,function(device){return loadNormForwardShader(device,true)});var FORWARD_MULTI_BUFFER_SHADER_NAME="pv_picollm_norm_layer_forward_multi_buffer_shader";var normLayerForwardMultiBufferShaderSource="\nstruct argsStruct {\n n: u32,\n dimension: u32,\n eps: f32,\n weight_offset: u32,\n bias_offset: u32,\n x_offset: u32,\n y_offset: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar weight: array;\n\n@group(0) @binding(2)\nvar bias: array;\n\n@group(0) @binding(3)\nvar x: array;\n\n@group(0) @binding(4)\nvar y: array;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= args.n) {\n return;\n }\n \n let x_start: u32 = args.x_offset + (global_id.x * args.dimension);\n\n var mean: f32 = 0.0;\n for (var j = 0u; j < args.dimension; j++) {\n mean += x[x_start + j];\n }\n mean /= f32(args.dimension);\n\n var mean2: f32 = 0.0;\n for (var j = 0u; j < args.dimension; j++) {\n mean2 += (x[x_start + j] - mean) * (x[x_start + j] - mean);\n }\n mean2 /= f32(args.dimension);\n\n var norm: f32 = 1.0 / sqrt(mean2 + args.eps);\n\n var y_start = args.y_offset + (global_id.x * args.dimension);\n for (var j = 0u; j < args.dimension; j++) {\n y[y_start + j] = ((x[x_start + j] - mean) * norm * weight[args.weight_offset + j]) + bias[args.bias_offset + j];\n }\n}\n\n".concat(emptyShader);var loadNormLayerForwardMultiBufferShader=function loadNormLayerForwardMultiBufferShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"norm layer forward multi buffer bind group layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:3,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:4,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"norm layer forward multi buffer pipeline layout",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"norm layer forward multi buffer shader module",code:normLayerForwardMultiBufferShaderSource});var computePipeline=device.createComputePipeline({label:"norm layer forward multi buffer pipeline",layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint,constants:{workgroup_size_x:PV_PICOLLM_WEBGPU_DEFAULT_WORKGROUP_SIZE}}});return{computePipeline:computePipeline}};var FORWARD_SINGLE_BUFFER_SHADER_NAME="pv_picollm_norm_layer_forward_single_buffer_shader";var normLayerForwardSingleBufferShaderSource="\nstruct argsStruct {\n n: u32,\n dimension: u32,\n eps: f32,\n weight_offset: u32,\n bias_offset: u32,\n x_offset: u32,\n y_offset: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar weight: array;\n\n@group(0) @binding(2)\nvar bias: array;\n\n@group(0) @binding(3)\nvar y: array;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= args.n) {\n return;\n }\n \n let x_start: u32 = args.x_offset + (global_id.x * args.dimension);\n\n var mean: f32 = 0.0;\n for (var j = 0u; j < args.dimension; j++) {\n mean += y[x_start + j];\n }\n mean /= f32(args.dimension);\n\n var mean2: f32 = 0.0;\n for (var j = 0u; j < args.dimension; j++) {\n mean2 += (y[x_start + j] - mean) * (y[x_start + j] - mean);\n }\n mean2 /= f32(args.dimension);\n\n var norm: f32 = 1.0 / sqrt(mean2 + args.eps);\n\n var y_start = args.y_offset + (global_id.x * args.dimension);\n for (var j = 0u; j < args.dimension; j++) {\n y[y_start + j] = ((y[x_start + j] - mean) * norm * weight[args.weight_offset + j]) + bias[args.bias_offset + j];\n }\n}\n\n".concat(emptyShader);var loadNormLayerForwardSingleBufferShader=function loadNormLayerForwardSingleBufferShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"norm layer forward single buffer bind group layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:3,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"norm layer forward single buffer pipeline layout",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"norm layer forward single buffer shader module",code:normLayerForwardSingleBufferShaderSource});var computePipeline=device.createComputePipeline({label:"norm layer forward single buffer pipeline",layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint,constants:{workgroup_size_x:PV_PICOLLM_WEBGPU_DEFAULT_WORKGROUP_SIZE}}});return{computePipeline:computePipeline}};var normLayerForwardShader=_defineProperty(_defineProperty({},FORWARD_SINGLE_BUFFER_SHADER_NAME,loadNormLayerForwardSingleBufferShader),FORWARD_MULTI_BUFFER_SHADER_NAME,loadNormLayerForwardMultiBufferShader);var ADD_TO_BUFFER_SHADER_NAME="pv_picollm_transformer_add_to_buffer_shader";var transformerAddToBufferShaderSource="\nstruct argsStruct {\n n: u32,\n x_offset: u32,\n buffer_offset: u32, \n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar x: array;\n\n@group(0) @binding(2)\nvar buffer: array;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= args.n) {\n return;\n }\n \n buffer[args.buffer_offset + global_id.x] += x[args.x_offset + global_id.x]; \n}\n\n".concat(emptyShader);var loadTransformerAddToBufferShader=function loadTransformerAddToBufferShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"transformer add to buffer bind group layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"transformer add to buffer pipeline layout",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"transformer add to buffer shader module",code:transformerAddToBufferShaderSource});var computePipeline=device.createComputePipeline({label:"transformer add to buffer compute",layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint,constants:{workgroup_size_x:PV_PICOLLM_WEBGPU_DEFAULT_WORKGROUP_SIZE}}});return{computePipeline:computePipeline}};var ADD_BUFFERS_SHADER_NAME="pv_picollm_transformer_add_buffers_shader";var transformerAddBuffersShaderSource="\n\nstruct argsStruct {\n n: u32,\n buffer1_offset: u32,\n buffer2_offset: u32,\n y_offset: u32, \n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar buffer1: array;\n\n@group(0) @binding(2)\nvar buffer2: array;\n\n@group(0) @binding(3)\nvar y: array;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= args.n) {\n return;\n }\n \n y[args.y_offset + global_id.x] = buffer1[args.buffer1_offset + global_id.x] + buffer2[args.buffer2_offset + global_id.x]; \n}\n\n".concat(emptyShader);var loadTransformerAddBuffersShader=function loadTransformerAddBuffersShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"transformer add buffers bind group layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:3,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"transformer add buffers pipeline layout",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"transformer add buffers shader module",code:transformerAddBuffersShaderSource});var computePipeline=device.createComputePipeline({label:"transformer add buffers pipeline",layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint,constants:{workgroup_size_x:PV_PICOLLM_WEBGPU_DEFAULT_WORKGROUP_SIZE}}});return{computePipeline:computePipeline}};var transformerForwardShaders=_defineProperty(_defineProperty({},ADD_TO_BUFFER_SHADER_NAME,loadTransformerAddToBufferShader),ADD_BUFFERS_SHADER_NAME,loadTransformerAddBuffersShader);var FORWARD_SHADER_NAME="pv_picollm_weight_float_forward_shader";var weightFloatForwardShaderSource="\n\nstruct argsStruct {\n nr: u32,\n nc: u32,\n w_offset: u32,\n x_offset: u32,\n y_offset: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar w: array;\n\n@group(0) @binding(2)\nvar x: array;\n\n@group(0) @binding(3)\nvar y: array;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(\n @builtin(workgroup_id) workgroup_id : vec3,\n @builtin(local_invocation_id) local_id : vec3\n) {\n if (local_id.x >= args.nr) {\n return;\n }\n let x_start: u32 = args.x_offset + (workgroup_id.x * args.nc);\n let y_idx: u32 = local_id.x + args.y_offset + (workgroup_id.x * args.nr);\n \n let w_start: u32 = args.w_offset + (local_id.x * args.nc);\n for (var j = 0u; j < args.nc; j++) {\n y[y_idx] += w[w_start + j] * x[x_start + j]; \n }\n}\n\n".concat(emptyShader);var loadWeightFloatForwardShader=function loadWeightFloatForwardShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"weight float forward bind group layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:3,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"weight float forward pipeline layout",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"weight float forward shader module",code:weightFloatForwardShaderSource});var computePipeline=device.createComputePipeline({label:"weight float forward pipeline",layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint,constants:{workgroup_size_x:PV_PICOLLM_WEBGPU_DEFAULT_WORKGROUP_SIZE}}});return{computePipeline:computePipeline}};var weightFloatForwardShader=_defineProperty({},FORWARD_SHADER_NAME,loadWeightFloatForwardShader);var rowsPerBlock=16;var columnsPerBlock=8;var preprocessDim=16;var weightBlockSize=256;var unpackBlock128BitDepth3="\nvar unpacked: array;\n\nfn unpack_block_128_bit_depth_3(packed_offset: u32) {\n let val_0 = blocks[packed_offset]; \n unpacked[0] = extractBits(val_0, 0u, 3u);\n unpacked[1] = extractBits(val_0, 3u, 3u);\n unpacked[2] = extractBits(val_0, 6u, 3u);\n unpacked[3] = extractBits(val_0, 9u, 3u);\n unpacked[4] = extractBits(val_0, 12u, 3u);\n unpacked[5] = extractBits(val_0, 15u, 3u);\n unpacked[6] = extractBits(val_0, 18u, 3u);\n unpacked[7] = extractBits(val_0, 21u, 3u);\n unpacked[8] = extractBits(val_0, 24u, 3u);\n unpacked[9] = extractBits(val_0, 27u, 3u);\n unpacked[10] = extractBits(val_0, 30u, 2u);\n \n let val_1 = blocks[packed_offset + 1];\n unpacked[10] = insertBits(unpacked[10], extractBits(val_1, 0u, 1u), 2u, 1u);\n unpacked[11] = extractBits(val_1, 1u, 3u);\n unpacked[12] = extractBits(val_1, 4u, 3u);\n unpacked[13] = extractBits(val_1, 7u, 3u);\n unpacked[14] = extractBits(val_1, 10u, 3u);\n unpacked[15] = extractBits(val_1, 13u, 3u);\n unpacked[16] = extractBits(val_1, 16u, 3u);\n unpacked[17] = extractBits(val_1, 19u, 3u);\n unpacked[18] = extractBits(val_1, 22u, 3u);\n unpacked[19] = extractBits(val_1, 25u, 3u);\n unpacked[20] = extractBits(val_1, 28u, 3u);\n unpacked[21] = extractBits(val_1, 31u, 1u);\n \n let val_2 = blocks[packed_offset + 2];\n unpacked[21] = insertBits(unpacked[21], extractBits(val_2, 0u, 2u), 1u, 2u); \n unpacked[22] = extractBits(val_2, 2u, 3u);\n unpacked[23] = extractBits(val_2, 5u, 3u);\n unpacked[24] = extractBits(val_2, 8u, 3u);\n unpacked[25] = extractBits(val_2, 11u, 3u);\n unpacked[26] = extractBits(val_2, 14u, 3u);\n unpacked[27] = extractBits(val_2, 17u, 3u);\n unpacked[28] = extractBits(val_2, 20u, 3u);\n unpacked[29] = extractBits(val_2, 23u, 3u);\n unpacked[30] = extractBits(val_2, 26u, 3u);\n unpacked[31] = extractBits(val_2, 29u, 3u);\n \n let val_3 = blocks[packed_offset + 3]; \n unpacked[32] = extractBits(val_3, 0u, 3u);\n unpacked[33] = extractBits(val_3, 3u, 3u);\n unpacked[34] = extractBits(val_3, 6u, 3u);\n unpacked[35] = extractBits(val_3, 9u, 3u);\n unpacked[36] = extractBits(val_3, 12u, 3u);\n unpacked[37] = extractBits(val_3, 15u, 3u);\n unpacked[38] = extractBits(val_3, 18u, 3u);\n unpacked[39] = extractBits(val_3, 21u, 3u);\n unpacked[40] = extractBits(val_3, 24u, 3u);\n unpacked[41] = extractBits(val_3, 27u, 3u);\n unpacked[42] = extractBits(val_3, 30u, 2u);\n \n let val_4 = blocks[packed_offset + 4];\n unpacked[42] = insertBits(unpacked[42], extractBits(val_4, 0u, 1u), 2u, 1u);\n unpacked[43] = extractBits(val_4, 1u, 3u);\n unpacked[44] = extractBits(val_4, 4u, 3u);\n unpacked[45] = extractBits(val_4, 7u, 3u);\n unpacked[46] = extractBits(val_4, 10u, 3u);\n unpacked[47] = extractBits(val_4, 13u, 3u);\n unpacked[48] = extractBits(val_4, 16u, 3u);\n unpacked[49] = extractBits(val_4, 19u, 3u);\n unpacked[50] = extractBits(val_4, 22u, 3u);\n unpacked[51] = extractBits(val_4, 25u, 3u);\n unpacked[52] = extractBits(val_4, 28u, 3u);\n unpacked[53] = extractBits(val_4, 31u, 1u);\n \n let val_5 = blocks[packed_offset + 5];\n unpacked[53] = insertBits(unpacked[53], extractBits(val_5, 0u, 2u), 1u, 2u); \n unpacked[54] = extractBits(val_5, 2u, 3u);\n unpacked[55] = extractBits(val_5, 5u, 3u);\n unpacked[56] = extractBits(val_5, 8u, 3u);\n unpacked[57] = extractBits(val_5, 11u, 3u);\n unpacked[58] = extractBits(val_5, 14u, 3u);\n unpacked[59] = extractBits(val_5, 17u, 3u);\n unpacked[60] = extractBits(val_5, 20u, 3u);\n unpacked[61] = extractBits(val_5, 23u, 3u);\n unpacked[62] = extractBits(val_5, 26u, 3u);\n unpacked[63] = extractBits(val_5, 29u, 3u);\n \n let val_6 = blocks[packed_offset + 6];\n unpacked[64] = extractBits(val_6, 0u, 3u);\n unpacked[65] = extractBits(val_6, 3u, 3u);\n unpacked[66] = extractBits(val_6, 6u, 3u);\n unpacked[67] = extractBits(val_6, 9u, 3u);\n unpacked[68] = extractBits(val_6, 12u, 3u);\n unpacked[69] = extractBits(val_6, 15u, 3u);\n unpacked[70] = extractBits(val_6, 18u, 3u);\n unpacked[71] = extractBits(val_6, 21u, 3u);\n unpacked[72] = extractBits(val_6, 24u, 3u);\n unpacked[73] = extractBits(val_6, 27u, 3u);\n unpacked[74] = extractBits(val_6, 30u, 2u);\n \n let val_7 = blocks[packed_offset + 7];\n unpacked[74] = insertBits(unpacked[74], extractBits(val_7, 0u, 1u), 2u, 1u);\n unpacked[75] = extractBits(val_7, 1u, 3u);\n unpacked[76] = extractBits(val_7, 4u, 3u);\n unpacked[77] = extractBits(val_7, 7u, 3u);\n unpacked[78] = extractBits(val_7, 10u, 3u);\n unpacked[79] = extractBits(val_7, 13u, 3u);\n unpacked[80] = extractBits(val_7, 16u, 3u);\n unpacked[81] = extractBits(val_7, 19u, 3u);\n unpacked[82] = extractBits(val_7, 22u, 3u);\n unpacked[83] = extractBits(val_7, 25u, 3u);\n unpacked[84] = extractBits(val_7, 28u, 3u);\n unpacked[85] = extractBits(val_7, 31u, 1u);\n \n let val_8 = blocks[packed_offset + 8];\n unpacked[85] = insertBits(unpacked[85], extractBits(val_8, 0u, 2u), 1u, 2u); \n unpacked[86] = extractBits(val_8, 2u, 3u);\n unpacked[87] = extractBits(val_8, 5u, 3u);\n unpacked[88] = extractBits(val_8, 8u, 3u);\n unpacked[89] = extractBits(val_8, 11u, 3u);\n unpacked[90] = extractBits(val_8, 14u, 3u);\n unpacked[91] = extractBits(val_8, 17u, 3u);\n unpacked[92] = extractBits(val_8, 20u, 3u);\n unpacked[93] = extractBits(val_8, 23u, 3u);\n unpacked[94] = extractBits(val_8, 26u, 3u);\n unpacked[95] = extractBits(val_8, 29u, 3u);\n \n let val_9 = blocks[packed_offset + 9];\n unpacked[96] = extractBits(val_9, 0u, 3u);\n unpacked[97] = extractBits(val_9, 3u, 3u);\n unpacked[98] = extractBits(val_9, 6u, 3u);\n unpacked[99] = extractBits(val_9, 9u, 3u);\n unpacked[100] = extractBits(val_9, 12u, 3u);\n unpacked[101] = extractBits(val_9, 15u, 3u);\n unpacked[102] = extractBits(val_9, 18u, 3u);\n unpacked[103] = extractBits(val_9, 21u, 3u);\n unpacked[104] = extractBits(val_9, 24u, 3u);\n unpacked[105] = extractBits(val_9, 27u, 3u);\n unpacked[106] = extractBits(val_9, 30u, 2u);\n \n let val_10 = blocks[packed_offset + 10];\n unpacked[106] = insertBits(unpacked[106], extractBits(val_10, 0u, 1u), 2u, 1u);\n unpacked[107] = extractBits(val_10, 1u, 3u);\n unpacked[108] = extractBits(val_10, 4u, 3u);\n unpacked[109] = extractBits(val_10, 7u, 3u);\n unpacked[110] = extractBits(val_10, 10u, 3u);\n unpacked[111] = extractBits(val_10, 13u, 3u);\n unpacked[112] = extractBits(val_10, 16u, 3u);\n unpacked[113] = extractBits(val_10, 19u, 3u);\n unpacked[114] = extractBits(val_10, 22u, 3u);\n unpacked[115] = extractBits(val_10, 25u, 3u);\n unpacked[116] = extractBits(val_10, 28u, 3u);\n unpacked[117] = extractBits(val_10, 31u, 1u);\n \n let val_11 = blocks[packed_offset + 11];\n unpacked[117] = insertBits(unpacked[117], extractBits(val_11, 0u, 2u), 1u, 2u); \n unpacked[118] = extractBits(val_11, 2u, 3u);\n unpacked[119] = extractBits(val_11, 5u, 3u);\n unpacked[120] = extractBits(val_11, 8u, 3u);\n unpacked[121] = extractBits(val_11, 11u, 3u);\n unpacked[122] = extractBits(val_11, 14u, 3u);\n unpacked[123] = extractBits(val_11, 17u, 3u);\n unpacked[124] = extractBits(val_11, 20u, 3u);\n unpacked[125] = extractBits(val_11, 23u, 3u);\n unpacked[126] = extractBits(val_11, 26u, 3u);\n unpacked[127] = extractBits(val_11, 29u, 3u);\n}\n";var unpackBlock128BitDepth5="\nvar unpacked: array;\n\nfn unpack_block_128_bit_depth_5(packed_offset: u32) { \n let val_0 = blocks[packed_offset];\n unpacked[0] = extractBits(val_0, 0u, 5u);\n unpacked[1] = extractBits(val_0, 5u, 5u);\n unpacked[2] = extractBits(val_0, 10u, 5u);\n unpacked[3] = extractBits(val_0, 15u, 5u);\n unpacked[4] = extractBits(val_0, 20u, 5u);\n unpacked[5] = extractBits(val_0, 25u, 5u);\n unpacked[6] = extractBits(val_0, 30u, 2u);\n \n let val_1 = blocks[packed_offset + 1];\n unpacked[6] = insertBits(unpacked[6], extractBits(val_1, 0u, 3u), 2u, 3u); \n unpacked[7] = extractBits(val_1, 3u, 5u);\n unpacked[8] = extractBits(val_1, 8u, 5u);\n unpacked[9] = extractBits(val_1, 13u, 5u);\n unpacked[10] = extractBits(val_1, 18u, 5u);\n unpacked[11] = extractBits(val_1, 23u, 5u);\n unpacked[12] = extractBits(val_1, 28u, 4u);\n \n let val_2 = blocks[packed_offset + 2];\n unpacked[12] = insertBits(unpacked[12], extractBits(val_2, 0u, 1u), 4u, 1u);\n unpacked[13] = extractBits(val_2, 1u, 5u);\n unpacked[14] = extractBits(val_2, 6u, 5u);\n unpacked[15] = extractBits(val_2, 11u, 5u);\n unpacked[16] = extractBits(val_2, 16u, 5u);\n unpacked[17] = extractBits(val_2, 21u, 5u);\n unpacked[18] = extractBits(val_2, 26u, 5u);\n unpacked[19] = extractBits(val_2, 31u, 1u);\n \n let val_3 = blocks[packed_offset + 3];\n unpacked[19] = insertBits(unpacked[19], extractBits(val_3, 0u, 4u), 1u, 4u);\n unpacked[20] = extractBits(val_3, 4u, 5u);\n unpacked[21] = extractBits(val_3, 9u, 5u);\n unpacked[22] = extractBits(val_3, 14u, 5u);\n unpacked[23] = extractBits(val_3, 19u, 5u);\n unpacked[24] = extractBits(val_3, 24u, 5u);\n unpacked[25] = extractBits(val_3, 29u, 3u);\n \n let val_4 = blocks[packed_offset + 4];\n unpacked[25] = insertBits(unpacked[25], extractBits(val_4, 0u, 2u), 3u, 2u);\n unpacked[26] = extractBits(val_4, 2u, 5u);\n unpacked[27] = extractBits(val_4, 7u, 5u);\n unpacked[28] = extractBits(val_4, 12u, 5u);\n unpacked[29] = extractBits(val_4, 17u, 5u);\n unpacked[30] = extractBits(val_4, 22u, 5u);\n unpacked[31] = extractBits(val_4, 27u, 5u);\n \n let val_5 = blocks[packed_offset + 5];\n unpacked[32] = extractBits(val_5, 0u, 5u);\n unpacked[33] = extractBits(val_5, 5u, 5u);\n unpacked[34] = extractBits(val_5, 10u, 5u);\n unpacked[35] = extractBits(val_5, 15u, 5u);\n unpacked[36] = extractBits(val_5, 20u, 5u);\n unpacked[37] = extractBits(val_5, 25u, 5u);\n unpacked[38] = extractBits(val_5, 30u, 2u);\n\n let val_6 = blocks[packed_offset + 6];\n unpacked[38] = insertBits(unpacked[38], extractBits(val_6, 0u, 3u), 2u, 3u);\n unpacked[39] = extractBits(val_6, 3u, 5u);\n unpacked[40] = extractBits(val_6, 8u, 5u);\n unpacked[41] = extractBits(val_6, 13u, 5u);\n unpacked[42] = extractBits(val_6, 18u, 5u);\n unpacked[43] = extractBits(val_6, 23u, 5u);\n unpacked[44] = extractBits(val_6, 28u, 4u);\n\n let val_7 = blocks[packed_offset + 7];\n unpacked[44] = insertBits(unpacked[44], extractBits(val_7, 0u, 1u), 4u, 1u);\n unpacked[45] = extractBits(val_7, 1u, 5u);\n unpacked[46] = extractBits(val_7, 6u, 5u);\n unpacked[47] = extractBits(val_7, 11u, 5u);\n unpacked[48] = extractBits(val_7, 16u, 5u);\n unpacked[49] = extractBits(val_7, 21u, 5u);\n unpacked[50] = extractBits(val_7, 26u, 5u);\n unpacked[51] = extractBits(val_7, 31u, 1u);\n\n let val_8 = blocks[packed_offset + 8];\n unpacked[51] = insertBits(unpacked[51], extractBits(val_8, 0u, 4u), 1u, 4u);\n unpacked[52] = extractBits(val_8, 4u, 5u);\n unpacked[53] = extractBits(val_8, 9u, 5u);\n unpacked[54] = extractBits(val_8, 14u, 5u);\n unpacked[55] = extractBits(val_8, 19u, 5u);\n unpacked[56] = extractBits(val_8, 24u, 5u);\n unpacked[57] = extractBits(val_8, 29u, 3u);\n \n let val_9 = blocks[packed_offset + 9];\n unpacked[57] = insertBits(unpacked[57], extractBits(val_9, 0u, 2u), 3u, 2u);\n unpacked[58] = extractBits(val_9, 2u, 5u);\n unpacked[59] = extractBits(val_9, 7u, 5u);\n unpacked[60] = extractBits(val_9, 12u, 5u);\n unpacked[61] = extractBits(val_9, 17u, 5u);\n unpacked[62] = extractBits(val_9, 22u, 5u);\n unpacked[63] = extractBits(val_9, 27u, 5u);\n \n let val_10 = blocks[packed_offset + 10];\n unpacked[64] = extractBits(val_10, 0u, 5u);\n unpacked[65] = extractBits(val_10, 5u, 5u);\n unpacked[66] = extractBits(val_10, 10u, 5u);\n unpacked[67] = extractBits(val_10, 15u, 5u);\n unpacked[68] = extractBits(val_10, 20u, 5u);\n unpacked[69] = extractBits(val_10, 25u, 5u);\n unpacked[70] = extractBits(val_10, 30u, 2u);\n\n let val_11 = blocks[packed_offset + 11];\n unpacked[70] = insertBits(unpacked[70], extractBits(val_11, 0u, 3u), 2u, 3u);\n unpacked[71] = extractBits(val_11, 3u, 5u);\n unpacked[72] = extractBits(val_11, 8u, 5u);\n unpacked[73] = extractBits(val_11, 13u, 5u);\n unpacked[74] = extractBits(val_11, 18u, 5u);\n unpacked[75] = extractBits(val_11, 23u, 5u);\n unpacked[76] = extractBits(val_11, 28u, 4u);\n\n let val_12 = blocks[packed_offset + 12];\n unpacked[76] = insertBits(unpacked[76], extractBits(val_12, 0u, 1u), 4u, 1u);\n unpacked[77] = extractBits(val_12, 1u, 5u);\n unpacked[78] = extractBits(val_12, 6u, 5u);\n unpacked[79] = extractBits(val_12, 11u, 5u);\n unpacked[80] = extractBits(val_12, 16u, 5u);\n unpacked[81] = extractBits(val_12, 21u, 5u);\n unpacked[82] = extractBits(val_12, 26u, 5u);\n unpacked[83] = extractBits(val_12, 31u, 1u);\n\n let val_13 = blocks[packed_offset + 13];\n unpacked[83] = insertBits(unpacked[83], extractBits(val_13, 0u, 4u), 1u, 4u);\n unpacked[84] = extractBits(val_13, 4u, 5u);\n unpacked[85] = extractBits(val_13, 9u, 5u);\n unpacked[86] = extractBits(val_13, 14u, 5u);\n unpacked[87] = extractBits(val_13, 19u, 5u);\n unpacked[88] = extractBits(val_13, 24u, 5u);\n unpacked[89] = extractBits(val_13, 29u, 3u);\n \n let val_14 = blocks[packed_offset + 14];\n unpacked[89] = insertBits(unpacked[89], extractBits(val_14, 0u, 2u), 3u, 2u);\n unpacked[90] = extractBits(val_14, 2u, 5u);\n unpacked[91] = extractBits(val_14, 7u, 5u);\n unpacked[92] = extractBits(val_14, 12u, 5u);\n unpacked[93] = extractBits(val_14, 17u, 5u);\n unpacked[94] = extractBits(val_14, 22u, 5u);\n unpacked[95] = extractBits(val_14, 27u, 5u);\n\n let val_15 = blocks[packed_offset + 15];\n unpacked[96] = extractBits(val_15, 0u, 5u);\n unpacked[97] = extractBits(val_15, 5u, 5u);\n unpacked[98] = extractBits(val_15, 10u, 5u);\n unpacked[99] = extractBits(val_15, 15u, 5u);\n unpacked[100] = extractBits(val_15, 20u, 5u);\n unpacked[101] = extractBits(val_15, 25u, 5u);\n unpacked[102] = extractBits(val_15, 30u, 2u);\n\n let val_16 = blocks[packed_offset + 16];\n unpacked[102] = insertBits(unpacked[102], extractBits(val_16, 0u, 3u), 2u, 3u);\n unpacked[103] = extractBits(val_16, 3u, 5u);\n unpacked[104] = extractBits(val_16, 8u, 5u);\n unpacked[105] = extractBits(val_16, 13u, 5u);\n unpacked[106] = extractBits(val_16, 18u, 5u);\n unpacked[107] = extractBits(val_16, 23u, 5u);\n unpacked[108] = extractBits(val_16, 28u, 4u);\n\n let val_17 = blocks[packed_offset + 17];\n unpacked[108] = insertBits(unpacked[108], extractBits(val_17, 0u, 1u), 4u, 1u);\n unpacked[109] = extractBits(val_17, 1u, 5u);\n unpacked[110] = extractBits(val_17, 6u, 5u);\n unpacked[111] = extractBits(val_17, 11u, 5u);\n unpacked[112] = extractBits(val_17, 16u, 5u);\n unpacked[113] = extractBits(val_17, 21u, 5u);\n unpacked[114] = extractBits(val_17, 26u, 5u);\n unpacked[115] = extractBits(val_17, 31u, 1u);\n \n let val_18 = blocks[packed_offset + 18];\n unpacked[115] = insertBits(unpacked[115], extractBits(val_18, 0u, 4u), 1u, 4u);\n unpacked[116] = extractBits(val_18, 4u, 5u);\n unpacked[117] = extractBits(val_18, 9u, 5u);\n unpacked[118] = extractBits(val_18, 14u, 5u);\n unpacked[119] = extractBits(val_18, 19u, 5u);\n unpacked[120] = extractBits(val_18, 24u, 5u);\n unpacked[121] = extractBits(val_18, 29u, 3u);\n\n let val_19 = blocks[packed_offset + 19];\n unpacked[121] = insertBits(unpacked[121], extractBits(val_19, 0u, 2u), 3u, 2u);\n unpacked[122] = extractBits(val_19, 2u, 5u);\n unpacked[123] = extractBits(val_19, 7u, 5u);\n unpacked[124] = extractBits(val_19, 12u, 5u);\n unpacked[125] = extractBits(val_19, 17u, 5u);\n unpacked[126] = extractBits(val_19, 22u, 5u);\n unpacked[127] = extractBits(val_19, 27u, 5u);\n}\n";var unpackBlock128BitDepth6="\nvar unpacked: array;\n\nfn unpack_block_128_bit_depth_6(packed_offset: u32) {\n let val_0 = blocks[packed_offset];\n unpacked[0] = extractBits(val_0, 0u, 6u);\n unpacked[1] = extractBits(val_0, 6u, 6u);\n unpacked[2] = extractBits(val_0, 12u, 6u);\n unpacked[3] = extractBits(val_0, 18u, 6u);\n unpacked[4] = extractBits(val_0, 24u, 6u);\n unpacked[5] = extractBits(val_0, 30u, 2u);\n \n let val_1 = blocks[packed_offset + 1];\n unpacked[5] = insertBits(unpacked[5], extractBits(val_1, 0u, 4u), 2u, 4u);\n unpacked[6] = extractBits(val_1, 4u, 6u);\n unpacked[7] = extractBits(val_1, 10u, 6u);\n unpacked[8] = extractBits(val_1, 16u, 6u);\n unpacked[9] = extractBits(val_1, 22u, 6u);\n unpacked[10] = extractBits(val_1, 28u, 4u);\n \n let val_2 = blocks[packed_offset + 2];\n unpacked[10] = insertBits(unpacked[10], extractBits(val_2, 0u, 2u), 4u, 2u);\n unpacked[11] = extractBits(val_2, 2u, 6u);\n unpacked[12] = extractBits(val_2, 8u, 6u);\n unpacked[13] = extractBits(val_2, 14u, 6u);\n unpacked[14] = extractBits(val_2, 20u, 6u);\n unpacked[15] = extractBits(val_2, 26u, 6u);\n \n let val_3 = blocks[packed_offset + 3];\n unpacked[16] = extractBits(val_3, 0u, 6u);\n unpacked[17] = extractBits(val_3, 6u, 6u);\n unpacked[18] = extractBits(val_3, 12u, 6u);\n unpacked[19] = extractBits(val_3, 18u, 6u);\n unpacked[20] = extractBits(val_3, 24u, 6u);\n unpacked[21] = extractBits(val_3, 30u, 2u);\n \n let val_4 = blocks[packed_offset + 4];\n unpacked[21] = insertBits(unpacked[21], extractBits(val_4, 0u, 4u), 2u, 4u);\n unpacked[22] = extractBits(val_4, 4u, 6u);\n unpacked[23] = extractBits(val_4, 10u, 6u);\n unpacked[24] = extractBits(val_4, 16u, 6u);\n unpacked[25] = extractBits(val_4, 22u, 6u);\n unpacked[26] = extractBits(val_4, 28u, 4u);\n\n let val_5 = blocks[packed_offset + 5];\n unpacked[26] = insertBits(unpacked[26], extractBits(val_5, 0u, 2u), 4u, 2u);\n unpacked[27] = extractBits(val_5, 2u, 6u);\n unpacked[28] = extractBits(val_5, 8u, 6u);\n unpacked[29] = extractBits(val_5, 14u, 6u);\n unpacked[30] = extractBits(val_5, 20u, 6u);\n unpacked[31] = extractBits(val_5, 26u, 6u);\n\n let val_6 = blocks[packed_offset + 6];\n unpacked[32] = extractBits(val_6, 0u, 6u);\n unpacked[33] = extractBits(val_6, 6u, 6u);\n unpacked[34] = extractBits(val_6, 12u, 6u);\n unpacked[35] = extractBits(val_6, 18u, 6u);\n unpacked[36] = extractBits(val_6, 24u, 6u);\n unpacked[37] = extractBits(val_6, 30u, 2u);\n\n let val_7 = blocks[packed_offset + 7];\n unpacked[37] = insertBits(unpacked[37], extractBits(val_7, 0u, 4u), 2u, 4u);\n unpacked[38] = extractBits(val_7, 4u, 6u);\n unpacked[39] = extractBits(val_7, 10u, 6u);\n unpacked[40] = extractBits(val_7, 16u, 6u);\n unpacked[41] = extractBits(val_7, 22u, 6u);\n unpacked[42] = extractBits(val_7, 28u, 4u);\n \n let val_8 = blocks[packed_offset + 8];\n unpacked[42] = insertBits(unpacked[42], extractBits(val_8, 0u, 2u), 4u, 2u);\n unpacked[43] = extractBits(val_8, 2u, 6u);\n unpacked[44] = extractBits(val_8, 8u, 6u);\n unpacked[45] = extractBits(val_8, 14u, 6u);\n unpacked[46] = extractBits(val_8, 20u, 6u);\n unpacked[47] = extractBits(val_8, 26u, 6u);\n\n let val_9 = blocks[packed_offset + 9];\n unpacked[48] = extractBits(val_9, 0u, 6u);\n unpacked[49] = extractBits(val_9, 6u, 6u);\n unpacked[50] = extractBits(val_9, 12u, 6u);\n unpacked[51] = extractBits(val_9, 18u, 6u);\n unpacked[52] = extractBits(val_9, 24u, 6u);\n unpacked[53] = extractBits(val_9, 30u, 2u);\n\n let val_10 = blocks[packed_offset + 10];\n unpacked[53] = insertBits(unpacked[53], extractBits(val_10, 0u, 4u), 2u, 4u);\n unpacked[54] = extractBits(val_10, 4u, 6u);\n unpacked[55] = extractBits(val_10, 10u, 6u);\n unpacked[56] = extractBits(val_10, 16u, 6u);\n unpacked[57] = extractBits(val_10, 22u, 6u);\n unpacked[58] = extractBits(val_10, 28u, 4u);\n\n let val_11 = blocks[packed_offset + 11];\n unpacked[58] = insertBits(unpacked[58], extractBits(val_11, 0u, 2u), 4u, 2u);\n unpacked[59] = extractBits(val_11, 2u, 6u);\n unpacked[60] = extractBits(val_11, 8u, 6u);\n unpacked[61] = extractBits(val_11, 14u, 6u);\n unpacked[62] = extractBits(val_11, 20u, 6u);\n unpacked[63] = extractBits(val_11, 26u, 6u);\n \n let val_12 = blocks[packed_offset + 12];\n unpacked[64] = extractBits(val_12, 0u, 6u);\n unpacked[65] = extractBits(val_12, 6u, 6u);\n unpacked[66] = extractBits(val_12, 12u, 6u);\n unpacked[67] = extractBits(val_12, 18u, 6u);\n unpacked[68] = extractBits(val_12, 24u, 6u);\n unpacked[69] = extractBits(val_12, 30u, 2u);\n\n let val_13 = blocks[packed_offset + 13];\n unpacked[69] = insertBits(unpacked[69], extractBits(val_13, 0u, 4u), 2u, 4u);\n unpacked[70] = extractBits(val_13, 4u, 6u);\n unpacked[71] = extractBits(val_13, 10u, 6u);\n unpacked[72] = extractBits(val_13, 16u, 6u);\n unpacked[73] = extractBits(val_13, 22u, 6u);\n unpacked[74] = extractBits(val_13, 28u, 4u);\n\n let val_14 = blocks[packed_offset + 14];\n unpacked[74] = insertBits(unpacked[74], extractBits(val_14, 0u, 2u), 4u, 2u);\n unpacked[75] = extractBits(val_14, 2u, 6u);\n unpacked[76] = extractBits(val_14, 8u, 6u);\n unpacked[77] = extractBits(val_14, 14u, 6u);\n unpacked[78] = extractBits(val_14, 20u, 6u);\n unpacked[79] = extractBits(val_14, 26u, 6u);\n\n let val_15 = blocks[packed_offset + 15];\n unpacked[80] = extractBits(val_15, 0u, 6u);\n unpacked[81] = extractBits(val_15, 6u, 6u);\n unpacked[82] = extractBits(val_15, 12u, 6u);\n unpacked[83] = extractBits(val_15, 18u, 6u);\n unpacked[84] = extractBits(val_15, 24u, 6u);\n unpacked[85] = extractBits(val_15, 30u, 2u);\n \n let val_16 = blocks[packed_offset + 16];\n unpacked[85] = insertBits(unpacked[85], extractBits(val_16, 0u, 4u), 2u, 4u);\n unpacked[86] = extractBits(val_16, 4u, 6u);\n unpacked[87] = extractBits(val_16, 10u, 6u);\n unpacked[88] = extractBits(val_16, 16u, 6u);\n unpacked[89] = extractBits(val_16, 22u, 6u);\n unpacked[90] = extractBits(val_16, 28u, 4u);\n\n let val_17 = blocks[packed_offset + 17];\n unpacked[90] = insertBits(unpacked[90], extractBits(val_17, 0u, 2u), 4u, 2u);\n unpacked[91] = extractBits(val_17, 2u, 6u);\n unpacked[92] = extractBits(val_17, 8u, 6u);\n unpacked[93] = extractBits(val_17, 14u, 6u);\n unpacked[94] = extractBits(val_17, 20u, 6u);\n unpacked[95] = extractBits(val_17, 26u, 6u);\n\n let val_18 = blocks[packed_offset + 18];\n unpacked[96] = extractBits(val_18, 0u, 6u);\n unpacked[97] = extractBits(val_18, 6u, 6u);\n unpacked[98] = extractBits(val_18, 12u, 6u);\n unpacked[99] = extractBits(val_18, 18u, 6u);\n unpacked[100] = extractBits(val_18, 24u, 6u);\n unpacked[101] = extractBits(val_18, 30u, 2u);\n\n let val_19 = blocks[packed_offset + 19];\n unpacked[101] = insertBits(unpacked[101], extractBits(val_19, 0u, 4u), 2u, 4u);\n unpacked[102] = extractBits(val_19, 4u, 6u);\n unpacked[103] = extractBits(val_19, 10u, 6u);\n unpacked[104] = extractBits(val_19, 16u, 6u);\n unpacked[105] = extractBits(val_19, 22u, 6u);\n unpacked[106] = extractBits(val_19, 28u, 4u);\n \n let val_20 = blocks[packed_offset + 20];\n unpacked[106] = insertBits(unpacked[106], extractBits(val_20, 0u, 2u), 4u, 2u);\n unpacked[107] = extractBits(val_20, 2u, 6u);\n unpacked[108] = extractBits(val_20, 8u, 6u);\n unpacked[109] = extractBits(val_20, 14u, 6u);\n unpacked[110] = extractBits(val_20, 20u, 6u);\n unpacked[111] = extractBits(val_20, 26u, 6u);\n\n let val_21 = blocks[packed_offset + 21];\n unpacked[112] = extractBits(val_21, 0u, 6u);\n unpacked[113] = extractBits(val_21, 6u, 6u);\n unpacked[114] = extractBits(val_21, 12u, 6u);\n unpacked[115] = extractBits(val_21, 18u, 6u);\n unpacked[116] = extractBits(val_21, 24u, 6u);\n unpacked[117] = extractBits(val_21, 30u, 2u);\n\n let val_22 = blocks[packed_offset + 22];\n unpacked[117] = insertBits(unpacked[117], extractBits(val_22, 0u, 4u), 2u, 4u);\n unpacked[118] = extractBits(val_22, 4u, 6u);\n unpacked[119] = extractBits(val_22, 10u, 6u);\n unpacked[120] = extractBits(val_22, 16u, 6u);\n unpacked[121] = extractBits(val_22, 22u, 6u);\n unpacked[122] = extractBits(val_22, 28u, 4u);\n\n let val_23 = blocks[packed_offset + 23];\n unpacked[122] = insertBits(unpacked[122], extractBits(val_23, 0u, 2u), 4u, 2u);\n unpacked[123] = extractBits(val_23, 2u, 6u);\n unpacked[124] = extractBits(val_23, 8u, 6u);\n unpacked[125] = extractBits(val_23, 14u, 6u);\n unpacked[126] = extractBits(val_23, 20u, 6u);\n unpacked[127] = extractBits(val_23, 26u, 6u);\n}\n";var unpackBlock128BitDepth7="\nvar unpacked: array;\n\nfn unpack_block_128_bit_depth_7(packed_offset: u32) {\n let val_0 = blocks[packed_offset];\n unpacked[0] = extractBits(val_0, 0u, 7u);\n unpacked[1] = extractBits(val_0, 7u, 7u);\n unpacked[2] = extractBits(val_0, 14u, 7u);\n unpacked[3] = extractBits(val_0, 21u, 7u);\n unpacked[4] = extractBits(val_0, 28u, 4u);\n \n let val_1 = blocks[packed_offset + 1];\n unpacked[4] = insertBits(unpacked[4], extractBits(val_1, 0u, 3u), 4u, 3u);\n unpacked[5] = extractBits(val_1, 3u, 7u);\n unpacked[6] = extractBits(val_1, 10u, 7u);\n unpacked[7] = extractBits(val_1, 17u, 7u);\n unpacked[8] = extractBits(val_1, 24u, 7u);\n unpacked[9] = extractBits(val_1, 31u, 1u);\n \n let val_2 = blocks[packed_offset + 2];\n unpacked[9] = insertBits(unpacked[9], extractBits(val_2, 0u, 6u), 1u, 6u);\n unpacked[10] = extractBits(val_2, 6u, 7u);\n unpacked[11] = extractBits(val_2, 13u, 7u);\n unpacked[12] = extractBits(val_2, 20u, 7u);\n unpacked[13] = extractBits(val_2, 27u, 5u);\n \n let val_3 = blocks[packed_offset + 3];\n unpacked[13] = insertBits(unpacked[13], extractBits(val_3, 0u, 2u), 5u, 2u);\n unpacked[14] = extractBits(val_3, 2u, 7u);\n unpacked[15] = extractBits(val_3, 9u, 7u);\n unpacked[16] = extractBits(val_3, 16u, 7u);\n unpacked[17] = extractBits(val_3, 23u, 7u);\n unpacked[18] = extractBits(val_3, 30u, 2u);\n \n let val_4 = blocks[packed_offset + 4];\n unpacked[18] = insertBits(unpacked[18], extractBits(val_4, 0u, 5u), 2u, 5u);\n unpacked[19] = extractBits(val_4, 5u, 7u);\n unpacked[20] = extractBits(val_4, 12u, 7u);\n unpacked[21] = extractBits(val_4, 19u, 7u);\n unpacked[22] = extractBits(val_4, 26u, 6u);\n \n let val_5 = blocks[packed_offset + 5];\n unpacked[22] = insertBits(unpacked[22], extractBits(val_5, 0u, 1u), 6u, 1u);\n unpacked[23] = extractBits(val_5, 1u, 7u);\n unpacked[24] = extractBits(val_5, 8u, 7u);\n unpacked[25] = extractBits(val_5, 15u, 7u);\n unpacked[26] = extractBits(val_5, 22u, 7u);\n unpacked[27] = extractBits(val_5, 29u, 3u);\n \n let val_6 = blocks[packed_offset + 6];\n unpacked[27] = insertBits(unpacked[27], extractBits(val_6, 0u, 4u), 3u, 4u);\n unpacked[28] = extractBits(val_6, 4u, 7u);\n unpacked[29] = extractBits(val_6, 11u, 7u);\n unpacked[30] = extractBits(val_6, 18u, 7u);\n unpacked[31] = extractBits(val_6, 25u, 7u);\n \n let val_7 = blocks[packed_offset + 7];\n unpacked[32] = extractBits(val_7, 0u, 7u);\n unpacked[33] = extractBits(val_7, 7u, 7u);\n unpacked[34] = extractBits(val_7, 14u, 7u);\n unpacked[35] = extractBits(val_7, 21u, 7u);\n unpacked[36] = extractBits(val_7, 28u, 4u);\n \n let val_8 = blocks[packed_offset + 8];\n unpacked[36] = insertBits(unpacked[36], extractBits(val_8, 0u, 3u), 4u, 3u);\n unpacked[37] = extractBits(val_8, 3u, 7u);\n unpacked[38] = extractBits(val_8, 10u, 7u);\n unpacked[39] = extractBits(val_8, 17u, 7u);\n unpacked[40] = extractBits(val_8, 24u, 7u);\n unpacked[41] = extractBits(val_8, 31u, 1u);\n \n let val_9 = blocks[packed_offset + 9];\n unpacked[41] = insertBits(unpacked[41], extractBits(val_9, 0u, 6u), 1u, 6u);\n unpacked[42] = extractBits(val_9, 6u, 7u);\n unpacked[43] = extractBits(val_9, 13u, 7u);\n unpacked[44] = extractBits(val_9, 20u, 7u);\n unpacked[45] = extractBits(val_9, 27u, 5u);\n \n let val_10 = blocks[packed_offset + 10];\n unpacked[45] = insertBits(unpacked[45], extractBits(val_10, 0u, 2u), 5u, 2u);\n unpacked[46] = extractBits(val_10, 2u, 7u);\n unpacked[47] = extractBits(val_10, 9u, 7u);\n unpacked[48] = extractBits(val_10, 16u, 7u);\n unpacked[49] = extractBits(val_10, 23u, 7u);\n unpacked[50] = extractBits(val_10, 30u, 2u);\n \n let val_11 = blocks[packed_offset + 11];\n unpacked[50] = insertBits(unpacked[50], extractBits(val_11, 0u, 5u), 2u, 5u);\n unpacked[51] = extractBits(val_11, 5u, 7u);\n unpacked[52] = extractBits(val_11, 12u, 7u);\n unpacked[53] = extractBits(val_11, 19u, 7u);\n unpacked[54] = extractBits(val_11, 26u, 6u);\n \n let val_12 = blocks[packed_offset + 12];\n unpacked[54] = insertBits(unpacked[54], extractBits(val_12, 0u, 1u), 6u, 1u);\n unpacked[55] = extractBits(val_12, 1u, 7u);\n unpacked[56] = extractBits(val_12, 8u, 7u);\n unpacked[57] = extractBits(val_12, 15u, 7u);\n unpacked[58] = extractBits(val_12, 22u, 7u);\n unpacked[59] = extractBits(val_12, 29u, 3u);\n \n let val_13 = blocks[packed_offset + 13];\n unpacked[59] = insertBits(unpacked[59], extractBits(val_13, 0u, 4u), 3u, 4u);\n unpacked[60] = extractBits(val_13, 4u, 7u);\n unpacked[61] = extractBits(val_13, 11u, 7u);\n unpacked[62] = extractBits(val_13, 18u, 7u);\n unpacked[63] = extractBits(val_13, 25u, 7u);\n \n let val_14 = blocks[packed_offset + 14];\n unpacked[64] = extractBits(val_14, 0u, 7u);\n unpacked[65] = extractBits(val_14, 7u, 7u);\n unpacked[66] = extractBits(val_14, 14u, 7u);\n unpacked[67] = extractBits(val_14, 21u, 7u);\n unpacked[68] = extractBits(val_14, 28u, 4u);\n \n let val_15 = blocks[packed_offset + 15];\n unpacked[68] = insertBits(unpacked[68], extractBits(val_15, 0u, 3u), 4u, 3u);\n unpacked[69] = extractBits(val_15, 3u, 7u);\n unpacked[70] = extractBits(val_15, 10u, 7u);\n unpacked[71] = extractBits(val_15, 17u, 7u);\n unpacked[72] = extractBits(val_15, 24u, 7u);\n unpacked[73] = extractBits(val_15, 31u, 1u);\n \n let val_16 = blocks[packed_offset + 16];\n unpacked[73] = insertBits(unpacked[73], extractBits(val_16, 0u, 6u), 1u, 6u);\n unpacked[74] = extractBits(val_16, 6u, 7u);\n unpacked[75] = extractBits(val_16, 13u, 7u);\n unpacked[76] = extractBits(val_16, 20u, 7u);\n unpacked[77] = extractBits(val_16, 27u, 5u);\n \n let val_17 = blocks[packed_offset + 17];\n unpacked[77] = insertBits(unpacked[77], extractBits(val_17, 0u, 2u), 5u, 2u);\n unpacked[78] = extractBits(val_17, 2u, 7u);\n unpacked[79] = extractBits(val_17, 9u, 7u);\n unpacked[80] = extractBits(val_17, 16u, 7u);\n unpacked[81] = extractBits(val_17, 23u, 7u);\n unpacked[82] = extractBits(val_17, 30u, 2u);\n \n let val_18 = blocks[packed_offset + 18];\n unpacked[82] = insertBits(unpacked[82], extractBits(val_18, 0u, 5u), 2u, 5u);\n unpacked[83] = extractBits(val_18, 5u, 7u);\n unpacked[84] = extractBits(val_18, 12u, 7u);\n unpacked[85] = extractBits(val_18, 19u, 7u);\n unpacked[86] = extractBits(val_18, 26u, 6u);\n \n let val_19 = blocks[packed_offset + 19];\n unpacked[86] = insertBits(unpacked[86], extractBits(val_19, 0u, 1u), 6u, 1u);\n unpacked[87] = extractBits(val_19, 1u, 7u);\n unpacked[88] = extractBits(val_19, 8u, 7u);\n unpacked[89] = extractBits(val_19, 15u, 7u);\n unpacked[90] = extractBits(val_19, 22u, 7u);\n unpacked[91] = extractBits(val_19, 29u, 3u);\n \n let val_20 = blocks[packed_offset + 20];\n unpacked[91] = insertBits(unpacked[91], extractBits(val_20, 0u, 4u), 3u, 4u);\n unpacked[92] = extractBits(val_20, 4u, 7u);\n unpacked[93] = extractBits(val_20, 11u, 7u);\n unpacked[94] = extractBits(val_20, 18u, 7u);\n unpacked[95] = extractBits(val_20, 25u, 7u);\n \n let val_21 = blocks[packed_offset + 21];\n unpacked[96] = extractBits(val_21, 0u, 7u);\n unpacked[97] = extractBits(val_21, 7u, 7u);\n unpacked[98] = extractBits(val_21, 14u, 7u);\n unpacked[99] = extractBits(val_21, 21u, 7u);\n unpacked[100] = extractBits(val_21, 28u, 4u);\n \n let val_22 = blocks[packed_offset + 22];\n unpacked[100] = insertBits(unpacked[100], extractBits(val_22, 0u, 3u), 4u, 3u);\n unpacked[101] = extractBits(val_22, 3u, 7u);\n unpacked[102] = extractBits(val_22, 10u, 7u);\n unpacked[103] = extractBits(val_22, 17u, 7u);\n unpacked[104] = extractBits(val_22, 24u, 7u);\n unpacked[105] = extractBits(val_22, 31u, 1u);\n \n let val_23 = blocks[packed_offset + 23];\n unpacked[105] = insertBits(unpacked[105], extractBits(val_23, 0u, 6u), 1u, 6u);\n unpacked[106] = extractBits(val_23, 6u, 7u);\n unpacked[107] = extractBits(val_23, 13u, 7u);\n unpacked[108] = extractBits(val_23, 20u, 7u);\n unpacked[109] = extractBits(val_23, 27u, 5u);\n \n let val_24 = blocks[packed_offset + 24];\n unpacked[109] = insertBits(unpacked[109], extractBits(val_24, 0u, 2u), 5u, 2u);\n unpacked[110] = extractBits(val_24, 2u, 7u);\n unpacked[111] = extractBits(val_24, 9u, 7u);\n unpacked[112] = extractBits(val_24, 16u, 7u);\n unpacked[113] = extractBits(val_24, 23u, 7u);\n unpacked[114] = extractBits(val_24, 30u, 2u);\n \n let val_25 = blocks[packed_offset + 25];\n unpacked[114] = insertBits(unpacked[114], extractBits(val_25, 0u, 5u), 2u, 5u);\n unpacked[115] = extractBits(val_25, 5u, 7u);\n unpacked[116] = extractBits(val_25, 12u, 7u);\n unpacked[117] = extractBits(val_25, 19u, 7u);\n unpacked[118] = extractBits(val_25, 26u, 6u);\n \n let val_26 = blocks[packed_offset + 26];\n unpacked[118] = insertBits(unpacked[118], extractBits(val_26, 0u, 1u), 6u, 1u);\n unpacked[119] = extractBits(val_26, 1u, 7u);\n unpacked[120] = extractBits(val_26, 8u, 7u);\n unpacked[121] = extractBits(val_26, 15u, 7u);\n unpacked[122] = extractBits(val_26, 22u, 7u);\n unpacked[123] = extractBits(val_26, 29u, 3u);\n \n let val_27 = blocks[packed_offset + 27];\n unpacked[123] = insertBits(unpacked[123], extractBits(val_27, 0u, 4u), 3u, 4u);\n unpacked[124] = extractBits(val_27, 4u, 7u);\n unpacked[125] = extractBits(val_27, 11u, 7u);\n unpacked[126] = extractBits(val_27, 18u, 7u);\n unpacked[127] = extractBits(val_27, 25u, 7u); \n}\n";var fromFP510Function="\n\nconst exponents: array = array(\n 2.9103830456733704e-11, \n 5.820766091346741e-11, \n 1.1641532182693481e-10, \n 2.3283064365386963e-10,\n 4.656612873077393e-10, \n 9.313225746154785e-10, \n 1.862645149230957e-09, \n 3.725290298461914e-09,\n 7.450580596923828e-09, \n 1.4901161193847656e-08, \n 2.9802322387695312e-08, \n 5.960464477539063e-08,\n 1.1920928955078125e-07, \n 2.384185791015625e-07, \n 4.76837158203125e-07, \n 9.5367431640625e-07,\n 1.9073486328125e-06, \n 3.814697265625e-06, \n 7.62939453125e-06, \n 1.52587890625e-05, \n 3.0517578125e-05,\n 6.103515625e-05, \n 0.0001220703125, \n 0.000244140625, \n 0.00048828125, \n 0.0009765625, \n 0.001953125, \n 0.00390625,\n 0.0078125, \n 0.015625, \n 0.03125, \n 0.0625);\n\nfn from_fp510(x: u32) -> f32 {\n let exponent = f32(exponents[extractBits(x, 10u, 5u)]); \n let fractional = f32(extractBits(x, 0u, 10u)); \n let abs = exponent * fractional;\n return abs * (1.0 - (2.0 * f32(extractBits(x, 15u, 1u))));\n}\n";var preprocessBlocks3BitShaderSource="\n\nstruct argsStruct {\n nbr: u32,\n nbc: u32,\n blocks_offset: u32\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar blocks: array;\n\n".concat(unpackBlock128BitDepth3,"\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= args.nbr || global_id.y >= args.nbc) {\n return;\n }\n \n let blocks_start: u32 = args.blocks_offset + ((global_id.x * args.nbc + global_id.y) * 12u); \n unpack_block_128_bit_depth_3(blocks_start); \n \n let b01: u32 = blocks_start;\n let b2: u32 = blocks_start + 8u;\n \n for (var r = 0u; r < ").concat(rowsPerBlock,"u; r++) {\n let unpacked_idx = r * ").concat(columnsPerBlock,"u;\n let b01_idx = b01 + (r / 2u);\n let b2_idx = b2 + (r / 4u);\n\n blocks[b01_idx] = insertBits(blocks[b01_idx], extractBits(unpacked[unpacked_idx], 0u, 2u), (r * 16u) % 32u, 16u);\n blocks[b2_idx] = insertBits(blocks[b2_idx], extractBits(unpacked[unpacked_idx], 2u, 1u), (r * 8u) % 32u, 8u); \n }\n \n for (var c = 1u; c < ").concat(columnsPerBlock,"u; c++) {\n for (var r = 0u; r < ").concat(rowsPerBlock,"u; r++) {\n let unpacked_idx = r * ").concat(columnsPerBlock,"u + c;\n let b01_idx = b01 + (r / 2u);\n let b2_idx = b2 + (r / 4u);\n \n blocks[b01_idx] = insertBits(blocks[b01_idx], extractBits(unpacked[unpacked_idx], 0u, 2u), ((r * 16u) % 32u) + (2u * c), 2u);\n blocks[b2_idx] = insertBits(blocks[b2_idx], extractBits(unpacked[unpacked_idx], 2u, 1u), ((r * 8u) % 32u) + c, 1u); \n }\n }\n}\n\n").concat(emptyShader);var preprocessBlocks5BitShaderSource="\n\nstruct argsStruct {\n nbr: u32,\n nbc: u32,\n blocks_offset: u32\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar blocks: array;\n\n".concat(unpackBlock128BitDepth5,"\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= args.nbr || global_id.y >= args.nbc) {\n return;\n }\n\n let blocks_start: u32 = args.blocks_offset + ((global_id.x * args.nbc + global_id.y) * 20u);\n unpack_block_128_bit_depth_5(blocks_start); \n \n let b03: u32 = blocks_start;\n let b4: u32 = blocks_start + 16u;\n\n for (var r = 0u; r < ").concat(rowsPerBlock,"u; r++) {\n let unpacked_idx = r * ").concat(columnsPerBlock,"u;\n let b03_idx = b03 + r;\n let b4_idx = b4 + (r / 4u);\n \n blocks[b03_idx] = insertBits(blocks[b03_idx], extractBits(unpacked[unpacked_idx], 0u, 4u), 0u, 32u);\n blocks[b4_idx] = insertBits(blocks[b4_idx], extractBits(unpacked[unpacked_idx], 4u, 1u), (r * 8u) % 32u, 8u);\n }\n \n for (var c = 1u; c < ").concat(columnsPerBlock,"u; c++) {\n for (var r = 0u; r < ").concat(rowsPerBlock,"u; r++) {\n let unpacked_idx = r * ").concat(columnsPerBlock,"u + c;\n let b03_idx = b03 + r;\n let b4_idx = b4 + (r / 4u);\n \n blocks[b03_idx] = insertBits(blocks[b03_idx], extractBits(unpacked[unpacked_idx], 0u, 4u), 4 * c, 4u);\n blocks[b4_idx] = insertBits(blocks[b4_idx], extractBits(unpacked[unpacked_idx], 4u, 1u), ((r * 8u) % 32u) + c, 1u);\n }\n } \n}\n\n").concat(emptyShader);var preprocessBlocks6BitShaderSource="\n\nstruct argsStruct {\n nbr: u32,\n nbc: u32,\n blocks_offset: u32\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar blocks: array;\n\n".concat(unpackBlock128BitDepth6,"\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= args.nbr || global_id.y >= args.nbc) {\n return;\n }\n \n let blocks_start: u32 = args.blocks_offset + ((global_id.x * args.nbc + global_id.y) * 24u);\n unpack_block_128_bit_depth_6(blocks_start);\n \n let b03: u32 = blocks_start;\n let b45: u32 = blocks_start + 16u; \n for (var r = 0u; r < ").concat(rowsPerBlock,"u; r++) {\n let unpacked_idx = r * ").concat(columnsPerBlock,"u;\n let b03_idx = b03 + r;\n let b45_idx = b45 + (r / 2u);\n \n blocks[b03_idx] = insertBits(blocks[b03_idx], extractBits(unpacked[unpacked_idx], 0u, 4u), 0u, 32u);\n blocks[b45_idx] = insertBits(blocks[b45_idx], extractBits(unpacked[unpacked_idx], 4u, 2u), ((r * 16u) % 32u), 16u);\n }\n\n for (var c = 1u; c < ").concat(columnsPerBlock,"u; c++) {\n for (var r = 0u; r < ").concat(rowsPerBlock,"u; r++) {\n let unpacked_idx = r * ").concat(columnsPerBlock,"u + c;\n let b03_idx = b03 + r;\n let b45_idx = b45 + (r / 2u);\n \n blocks[b03_idx] = insertBits(blocks[b03_idx], extractBits(unpacked[unpacked_idx], 0u, 4u), 4 * c, 4u);\n blocks[b45_idx] = insertBits(blocks[b45_idx], extractBits(unpacked[unpacked_idx], 4u, 2u), ((r * 16u) % 32u) + (2 * c), 2u);\n }\n }\n}\n\n").concat(emptyShader);var preprocessBlocks7BitShaderSource="\n\nstruct argsStruct {\n nbr: u32,\n nbc: u32,\n blocks_offset: u32\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar blocks: array;\n\n".concat(unpackBlock128BitDepth7,"\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= args.nbr || global_id.y >= args.nbc) {\n return;\n }\n \n let blocks_start: u32 = args.blocks_offset + ((global_id.x * args.nbc + global_id.y) * 28u);\n unpack_block_128_bit_depth_7(blocks_start);\n \n let b03: u32 = blocks_start;\n let b45: u32 = blocks_start + 16u;\n let b6: u32 = blocks_start + 24u; \n for (var r = 0u; r < ").concat(rowsPerBlock,"u; r++) {\n let unpacked_idx = r * ").concat(columnsPerBlock,"u;\n let b03_idx = b03 + r;\n let b45_idx = b45 + (r / 2u);\n let b6_idx = b6 + (r / 4u);\n \n blocks[b03_idx] = insertBits(blocks[b03_idx], extractBits(unpacked[unpacked_idx], 0u, 4u), 0, 32u);\n blocks[b45_idx] = insertBits(blocks[b45_idx], extractBits(unpacked[unpacked_idx], 4u, 2u), ((r * 16u) % 32u), 16u);\n blocks[b6_idx] = insertBits(blocks[b6_idx], extractBits(unpacked[unpacked_idx], 6u, 1u), ((r * 8u) % 32u), 8u);\n }\n \n for (var c = 1u; c < ").concat(columnsPerBlock,"u; c++) {\n for (var r = 0u; r < ").concat(rowsPerBlock,"u; r++) {\n let unpacked_idx = r * ").concat(columnsPerBlock,"u + c;\n let b03_idx = b03 + r;\n let b45_idx = b45 + (r / 2u);\n let b6_idx = b6 + (r / 4u);\n \n blocks[b03_idx] = insertBits(blocks[b03_idx], extractBits(unpacked[unpacked_idx], 0u, 4u), 4 * c, 4u);\n blocks[b45_idx] = insertBits(blocks[b45_idx], extractBits(unpacked[unpacked_idx], 4u, 2u), ((r * 16u) % 32u) + (2 * c), 2u);\n blocks[b6_idx] = insertBits(blocks[b6_idx], extractBits(unpacked[unpacked_idx], 6u, 1u), ((r * 8u) % 32u) + c, 1u);\n }\n }\n}\n\n").concat(emptyShader);var preprocessShaderSources={3:preprocessBlocks3BitShaderSource,5:preprocessBlocks5BitShaderSource,6:preprocessBlocks6BitShaderSource,7:preprocessBlocks7BitShaderSource};var preprocessShaderNames={3:"pv_picollm_weight_block_mixed_16x8_preprocess_blocks_3bit_shader",5:"pv_picollm_weight_block_mixed_16x8_preprocess_blocks_5bit_shader",6:"pv_picollm_weight_block_mixed_16x8_preprocess_blocks_6bit_shader",7:"pv_picollm_weight_block_mixed_16x8_preprocess_blocks_7bit_shader"};var BM=8;var BN=32;var TM=2;var TN=16;var TC=rowsPerBlock*BM*BN/(TM*TN);var constantSnippet="\nconst BM = ".concat(BM,"u;\nconst BN = ").concat(BN,"u;\n\nconst TM = ").concat(TM,"u;\nconst TN = ").concat(TN,"u;\n\nconst TC = ").concat(TC,"u;\n\nconst ROW_PER_BLOCK = ").concat(rowsPerBlock,"u;\nconst COL_PER_BLOCK = ").concat(columnsPerBlock,"u;\n\nconst VEC_COL_PER_BLOCK = COL_PER_BLOCK / 4u;\n\nconst block_size: u32 = (COL_PER_BLOCK * ROW_PER_BLOCK * bit_depth) / 32u;\n\n");var forwardMultipleInputArgsSnippet="\nstruct argsStruct {\n n: u32,\n m: u32,\n total_nbc: u32,\n k: u32,\n x_offset: u32,\n metas_offset: u32,\n blocks_offset: u32,\n y_offset: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar x: array>;\n\n@group(0) @binding(2)\nvar metas: array;\n\n@group(0) @binding(3)\nvar blocks: array;\n\n@group(0) @binding(4)\nvar y: array;\n";var forwardMultipleSharedPrivateMemSnippet="\nvar shared_x: array, BN * VEC_COL_PER_BLOCK>;\nvar shared_ab: array;\nvar shared_w: array, BM * ROW_PER_BLOCK * VEC_COL_PER_BLOCK>;\n\nvar local_x: array, TN * VEC_COL_PER_BLOCK>;\nvar local_x_sums: array;\nvar local_results: array;\n";var forwardMultipleLocalVarSnippet="\n let tid = local_id.x;\n let bm_idx = workgroup_id.x;\n let bn_idx = workgroup_id.y;\n\n let local_bm_idx = bm_idx * BM;\n let local_bn_idx = bn_idx * BN;\n \n let n_idx = tid % (BN / TN);\n let k_idx = tid / (BN / TN) / (BM * ROW_PER_BLOCK / TM);\n let m_idx = tid / (BN / TN) % (BM * ROW_PER_BLOCK / TM);\n";var forwardMultipleLoadW1Bit="\n let b0 = blocks[src + (row / 4u)];\n\n let b0_offset_base = (row * 8u) % 32u;\n for (var c = 0u; c < VEC_COL_PER_BLOCK; c++) {\n let b0_offset = b0_offset_base + (c * 4u); \n shared_w[dst + c] = vec4(\n f32(extractBits(b0, b0_offset, 1u)), \n f32(extractBits(b0, b0_offset + 1, 1u)),\n f32(extractBits(b0, b0_offset + 2, 1u)),\n f32(extractBits(b0, b0_offset + 3, 1u)));\n }\n";var forwardMultipleLoadW2Bit="\n let b01 = blocks[src + (row / 2u)];\n \n let b01_offset_base = (row * 16u) % 32u;\n for (var c = 0u; c < VEC_COL_PER_BLOCK; c++) { \n let b01_offset = b01_offset_base + (c * 8u);\n shared_w[dst + c] = vec4(\n f32(extractBits(b01, b01_offset, 2u)), \n f32(extractBits(b01, b01_offset + 2, 2u)),\n f32(extractBits(b01, b01_offset + 4, 2u)),\n f32(extractBits(b01, b01_offset + 6, 2u)));\n } \n";var forwardMultipleLoadW3Bit="\n let b01 = blocks[src + (row / 2u)];\n let b2 = blocks[src + 8u + (row / 4u)]; \n\n let b01_offset_base = (row * 16u) % 32u;\n let b2_offset_base = (row * 8u) % 32u;\n for (var c = 0u; c < VEC_COL_PER_BLOCK; c++) {\n let b01_offset = b01_offset_base + (c * 8u);\n let b2_offset = b2_offset_base + (c * 4u);\n\n shared_w[dst + c] = vec4(\n f32(insertBits(extractBits(b01, b01_offset, 2u), extractBits(b2, b2_offset, 1u), 2u, 1u)), \n f32(insertBits(extractBits(b01, b01_offset + 2, 2u), extractBits(b2, b2_offset + 1, 1u), 2u, 1u)),\n f32(insertBits(extractBits(b01, b01_offset + 4, 2u), extractBits(b2, b2_offset + 2, 1u), 2u, 1u)),\n f32(insertBits(extractBits(b01, b01_offset + 6, 2u), extractBits(b2, b2_offset + 3, 1u), 2u, 1u))); \n }\n";var forwardMultipleLoadW4Bit="\n let b03 = blocks[src + row];\n \n for (var c = 0u; c < VEC_COL_PER_BLOCK; c++) {\n let b03_offset = (c * 16u); \n shared_w[dst + c] = vec4(\n f32(extractBits(b03, b03_offset, 4u)), \n f32(extractBits(b03, b03_offset + 4, 4u)),\n f32(extractBits(b03, b03_offset + 8, 4u)),\n f32(extractBits(b03, b03_offset + 12, 4u)));\n }\n";var forwardMultipleLoadW5Bit="\n let b03 = blocks[src + row];\n let b4 = blocks[src + 16u + (row / 4u)];\n \n let b4_offset_base = (row * 8u) % 32u;\n for (var c = 0u; c < VEC_COL_PER_BLOCK; c++) {\n let b03_offset = (c * 16u);\n let b4_offset = b4_offset_base + (c * 4u);\n shared_w[dst + c] = vec4(\n f32(insertBits(extractBits(b03, b03_offset, 4u), extractBits(b4, b4_offset, 1u), 4u, 1u)), \n f32(insertBits(extractBits(b03, b03_offset + 4, 4u), extractBits(b4, b4_offset + 1, 1u), 4u, 1u)),\n f32(insertBits(extractBits(b03, b03_offset + 8, 4u), extractBits(b4, b4_offset + 2, 1u), 4u, 1u)),\n f32(insertBits(extractBits(b03, b03_offset + 12, 4u), extractBits(b4, b4_offset + 3, 1u), 4u, 1u)));\n }\n";var forwardMultipleLoadW6Bit="\n let b03 = blocks[src + row];\n let b45 = blocks[src + 16u + (row / 2u)];\n \n let b45_offset_base = (row * 16u) % 32u;\n for (var c = 0u; c < VEC_COL_PER_BLOCK; c++) { \n let b03_offset = (c * 16u);\n let b45_offset = b45_offset_base + (c * 8u);\n shared_w[dst + c] = vec4(\n f32(insertBits(extractBits(b03, b03_offset, 4u), extractBits(b45, b45_offset, 2u), 4u, 2u)), \n f32(insertBits(extractBits(b03, b03_offset + 4, 4u), extractBits(b45, b45_offset + 2, 2u), 4u, 2u)),\n f32(insertBits(extractBits(b03, b03_offset + 8, 4u), extractBits(b45, b45_offset + 4, 2u), 4u, 2u)),\n f32(insertBits(extractBits(b03, b03_offset + 12, 4u), extractBits(b45, b45_offset + 6, 2u), 4u, 2u)));\n }\n";var forwardMultipleLoadW7Bit="\n let b03 = blocks[src + row];\n let b45 = blocks[src + 16u + (row / 2u)];\n let b6 = blocks[src + 24u + (row / 4u)];\n \n let b45_offset_base = (row * 16u) % 32u;\n let b6_offset_base = (row * 8u) % 32u;\n for (var c = 0u; c < VEC_COL_PER_BLOCK; c++) {\n let b03_offset = (c * 16u);\n let b45_offset = b45_offset_base + (c * 8u);\n let b6_offset = b6_offset_base + (c * 4u);\n \n shared_w[dst + c] = vec4(\n f32(insertBits(insertBits(extractBits(b03, b03_offset, 4u), extractBits(b45, b45_offset, 2u), 4u, 2u), extractBits(b6, b6_offset, 1u), 6u, 1u)), \n f32(insertBits(insertBits(extractBits(b03, b03_offset + 4, 4u), extractBits(b45, b45_offset + 2, 2u), 4u, 2u), extractBits(b6, b6_offset + 1, 1u), 6u, 1u)),\n f32(insertBits(insertBits(extractBits(b03, b03_offset + 8, 4u), extractBits(b45, b45_offset + 4, 2u), 4u, 2u), extractBits(b6, b6_offset + 2, 1u), 6u, 1u)),\n f32(insertBits(insertBits(extractBits(b03, b03_offset + 12, 4u), extractBits(b45, b45_offset + 6, 2u), 4u, 2u), extractBits(b6, b6_offset + 3, 1u), 6u, 1u)));\n }\n";var forwardMultipleLoadW8Bit="\n let b07_offset = src + (row * 2);\n \n for (var c = 0u; c < VEC_COL_PER_BLOCK; c++) {\n let b07 = blocks[b07_offset + c];\n shared_w[dst + c] = vec4(\n f32(extractBits(b07, 0u, 8u)), \n f32(extractBits(b07, 8u, 8u)),\n f32(extractBits(b07, 16u, 8u)),\n f32(extractBits(b07, 24u, 8u)));\n }\n";var forwardLoadWBitDepthSnippets={1:forwardMultipleLoadW1Bit,2:forwardMultipleLoadW2Bit,3:forwardMultipleLoadW3Bit,4:forwardMultipleLoadW4Bit,5:forwardMultipleLoadW5Bit,6:forwardMultipleLoadW6Bit,7:forwardMultipleLoadW7Bit,8:forwardMultipleLoadW8Bit};var forwardMultipleLoadXSnippet="\n let total_work_x = VEC_COL_PER_BLOCK * BN;\n for (var local_idx = 0u; local_idx < divide_pad(total_work_x, TC); local_idx++) {\n let idx = local_idx * TC + tid;\n if (idx < total_work_x) { \n let n_load_idx = local_bn_idx + idx / VEC_COL_PER_BLOCK;\n let inner_idx = idx % VEC_COL_PER_BLOCK;\n \n if (bk_idx < args.k && n_load_idx < args.n) { \n let x_idx = (args.x_offset / 4u) + ((bk_idx * args.n + n_load_idx) * VEC_COL_PER_BLOCK + inner_idx); \n shared_x[idx] = x[x_idx];\n } else {\n shared_x[idx] = vec4(0.0);\n }\n }\n }\n";var forwardMultipleLoadABSnippet="\n let total_work_ab = BM * 2;\n for (var local_idx = 0u; local_idx < divide_pad(total_work_ab, TC); local_idx++) {\n let idx = local_idx * TC + tid;\n if (idx < total_work_ab) {\n let m_load_idx = local_bm_idx + idx / 2; \n let inner_idx = (idx % 2) * 16u;\n \n if (m_load_idx < args.m && bk_idx < args.k) {\n let ab_bits = extractBits(metas[args.metas_offset + (m_load_idx * args.k + bk_idx)], inner_idx, 16u);\n shared_ab[idx] = from_fp510(ab_bits); \n } else {\n shared_ab[idx] = 0.0;\n }\n }\n }\n";var forwardMultipleLoadWSnippet=function forwardMultipleLoadWSnippet(bitDepth){return"\n let total_work_w = BM * ROW_PER_BLOCK;\n for (var local_idx = 0u; local_idx < divide_pad(total_work_w, TC); local_idx++) {\n let idx = local_idx * TC + tid;\n if (idx < total_work_w) {\n let m_load_idx = local_bm_idx + idx / ROW_PER_BLOCK;\n let row = idx % ROW_PER_BLOCK;\n let dst = idx * VEC_COL_PER_BLOCK;\n\n if (m_load_idx < args.m) {\n let src = args.blocks_offset + (m_load_idx * args.k + bk_idx) * block_size;\n ".concat(forwardLoadWBitDepthSnippets[bitDepth],"\n } else { \n for (var c = 0u; c < VEC_COL_PER_BLOCK; c++) {\n shared_w[dst + c] = vec4(0.0);\n }\n }\n }\n }\n")};var forwardMultipleCopyXSnippet="\nfor (var tn_idx = 0u; tn_idx < TN; tn_idx++) { \n var x_sum_vec = vec4(0.0); \n let local_x_idx = tn_idx * VEC_COL_PER_BLOCK;\n let shared_x_idx = (n_idx * TN + tn_idx) * VEC_COL_PER_BLOCK + (k_idx * VEC_COL_PER_BLOCK);\n for (var c = 0u; c < VEC_COL_PER_BLOCK; c++) {\n local_x[local_x_idx + c] = shared_x[shared_x_idx + c];\n x_sum_vec += local_x[local_x_idx + c];\n }\n local_x_sums[tn_idx] = x_sum_vec.x + x_sum_vec.y + x_sum_vec.z + x_sum_vec.w; \n}\n";var forwardMultipleComputeResultsSnippet="\n for (var tm_idx = 0u; tm_idx < TM; tm_idx++) { \n let shared_ab_idx = ((m_idx * TM + tm_idx) / ROW_PER_BLOCK + k_idx) * 2;\n let alpha = shared_ab[shared_ab_idx];\n let beta = shared_ab[shared_ab_idx + 1]; \n let shared_w_idx = ((m_idx * TM + tm_idx) + k_idx) * VEC_COL_PER_BLOCK;\n \n for (var tn_idx = 0u; tn_idx < TN; tn_idx++) { \n let local_x_idx = tn_idx * VEC_COL_PER_BLOCK;\n \n var swx_vec = vec4(0.0); \n for (var c = 0u; c < VEC_COL_PER_BLOCK; c++) { \n swx_vec += shared_w[shared_w_idx + c] * local_x[local_x_idx + c];\n }\n let swx = swx_vec.x + swx_vec.y + swx_vec.z + swx_vec.w;\n \n let kappa = alpha * local_x_sums[tn_idx]; \n let results_idx = tm_idx * TN + tn_idx;\n local_results[results_idx] += kappa + (beta * swx);\n }\n }\n";var forwardMultipleWriteResultsSnippet="\nfor (var tm_idx = 0u; tm_idx < TM; tm_idx++) {\n let row = local_bm_idx * ROW_PER_BLOCK + (m_idx * TM + tm_idx); \n for (var tn_idx = 0u; tn_idx < TN; tn_idx++) { \n let col = local_bn_idx + (n_idx * TN + tn_idx);\n if (row < args.m * ROW_PER_BLOCK && col < args.n) {\n let y_idx = args.y_offset + ((row / ROW_PER_BLOCK) * args.n + col) * ROW_PER_BLOCK + (row % ROW_PER_BLOCK);\n let results_idx = tm_idx * TN + tn_idx;\n \n y[y_idx] += local_results[results_idx];\n }\n }\n}\n";var forwardMultipleShaderSources=function forwardMultipleShaderSources(bitDepth){return"\n\n".concat(forwardMultipleInputArgsSnippet,"\n\n").concat(constantSnippet,"\n\n").concat(forwardMultipleSharedPrivateMemSnippet,"\n\n").concat(fromFP510Function,"\n\n").concat(dividePadFunction,"\n\nconst bit_depth: u32 = ").concat(bitDepth,"u;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n \n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(\n @builtin(local_invocation_id) local_id: vec3,\n @builtin(workgroup_id) workgroup_id: vec3\n) {\n ").concat(forwardMultipleLocalVarSnippet,"\n \n for (var bk_idx = 0u; bk_idx < args.k; bk_idx++) { \n ").concat(forwardMultipleLoadXSnippet,"\n ").concat(forwardMultipleLoadABSnippet," \n ").concat(forwardMultipleLoadWSnippet(bitDepth)," \n workgroupBarrier();\n \n ").concat(forwardMultipleCopyXSnippet,"\n ").concat(forwardMultipleComputeResultsSnippet,"\n workgroupBarrier();\n }\n \n ").concat(forwardMultipleWriteResultsSnippet,"\n}\n\n").concat(emptyShader,"\n")};var forwardShuffleXShaderSource="\nstruct argsStruct {\n n: u32,\n shape1: u32,\n x_offset: u32,\n indices_offset: u32, \n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar x: array;\n\n@group(0) @binding(2)\nvar indices: array;\n\n@group(0) @binding(3)\nvar y: array;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= args.n || global_id.y >= args.shape1) {\n return;\n } \n\n let b = global_id.x;\n let i = global_id.y;\n \n let c = i / 8u;\n let j = i % 8u;\n y[((c * args.n) + b) * 8 + j] = x[args.x_offset + (b * args.shape1) + indices[args.indices_offset + i]];\n}\n\n".concat(emptyShader,"\n");var forwardSingleReduceYShaderSource="\nstruct argsStruct {\n nvr: u32,\n nbc: u32, \n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar x: array>;\n\n@group(0) @binding(2)\nvar y: array>;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) { \n if (global_id.x > args.nvr) {\n return;\n }\n\n let x_start = global_id.x * args.nbc;\n var sum: vec4 = vec4(0.0, 0.0, 0.0, 0.0);\n for (var i = 0u; i < args.nbc; i++) {\n sum += x[x_start + i]; \n }\n y[global_id.x] += sum;\n}\n\n".concat(emptyShader);var forwardShuffleYShaderSource="\nstruct argsStruct {\n n: u32,\n shape0: u32, \n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar x: array;\n\n@group(0) @binding(2)\nvar y: array;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= args.n || global_id.y >= args.shape0) {\n return;\n } \n \n let b = global_id.x;\n let i = global_id.y;\n \n let r = i / 16u;\n let j = i % 16u;\n y[(b * args.shape0) + (r * 16) + j] = x[(((r * args.n) + b) * 16) + j];\n}\n\n".concat(emptyShader);var addBiasShaderSource="\nstruct argsStruct {\n dimension: u32\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar bias: array;\n\n@group(0) @binding(2)\nvar y: array;\n\n".concat(fromFP510Function,"\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) { \n y[(global_id.x * args.dimension) + global_id.y] += bias[global_id.y];\n}\n\n").concat(emptyShader);var forwardSingleBitDepth1ShaderSource="\n\nstruct argsStruct {\n n: u32,\n nbr: u32,\n total_nbc: u32,\n bit_depth_nbc: u32,\n x_offset: u32,\n metas_offset: u32,\n blocks_offset: u32,\n y_offset: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar x: array>;\n\n@group(0) @binding(2)\nvar metas: array;\n\n@group(0) @binding(3)\nvar blocks: array;\n\n@group(0) @binding(4)\nvar y: array>;\n\n".concat(fromFP510Function,"\n\nconst block_size: u32 = 4u;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= (args.nbr * 4) || global_id.y >= args.bit_depth_nbc) {\n return;\n }\n\n let r = global_id.x * 4u;\n let c = global_id.y * ").concat(columnsPerBlock,";\n let br = global_id.x / 4u; \n let bc = global_id.y;\n let br_offset = global_id.x % 4u;\n \n let row_metas_start: u32 = args.metas_offset + (br * args.bit_depth_nbc);\n let row_blocks_start: u32 = args.blocks_offset + (br * args.bit_depth_nbc * block_size); \n \n let alpha = from_fp510(extractBits(metas[row_metas_start + bc], 0, 16u)); \n let beta = from_fp510(extractBits(metas[row_metas_start + bc], 16u, 16u));\n \n let x_start = ((args.x_offset + c) / 4u);\n \n var b0_start = row_blocks_start + br_offset + (bc * block_size);\n var b0_offset = 0u;\n \n var res: array, 2u>;\n var x_sum: f32 = 0.0;\n \n for (var j = 0u; j < ").concat(columnsPerBlock,"; j+=4) {\n \n var b0 = blocks[b0_start];\n \n let w0_0 = f32(extractBits(b0, b0_offset + j, 1u)); \n let w0_1 = f32(extractBits(b0, b0_offset + j + 1, 1u)); \n let w0_2 = f32(extractBits(b0, b0_offset + j + 2, 1u));\n let w0_3 = f32(extractBits(b0, b0_offset + j + 3, 1u));\n \n b0_offset = 8u;\n \n let w1_0 = f32(extractBits(b0, b0_offset + j, 1u)); \n let w1_1 = f32(extractBits(b0, b0_offset + j + 1, 1u)); \n let w1_2 = f32(extractBits(b0, b0_offset + j + 2, 1u));\n let w1_3 = f32(extractBits(b0, b0_offset + j + 3, 1u));\n \n b0_offset = 16u;\n \n let w2_0 = f32(extractBits(b0, b0_offset + j, 1u)); \n let w2_1 = f32(extractBits(b0, b0_offset + j + 1, 1u)); \n let w2_2 = f32(extractBits(b0, b0_offset + j + 2, 1u));\n let w2_3 = f32(extractBits(b0, b0_offset + j + 3, 1u));\n \n b0_offset = 24u;\n \n let w3_0 = f32(extractBits(b0, b0_offset + j, 1u)); \n let w3_1 = f32(extractBits(b0, b0_offset + j + 1, 1u)); \n let w3_2 = f32(extractBits(b0, b0_offset + j + 2, 1u));\n let w3_3 = f32(extractBits(b0, b0_offset + j + 3, 1u));\n \n b0_offset = 0u;\n \n let m = mat4x4(\n w0_0, w1_0, w2_0, w3_0,\n w0_1, w1_1, w2_1, w3_1, \n w0_2, w1_2, w2_2, w3_2,\n w0_3, w1_3, w2_3, w3_3);\n\n let x_idx = (j / 4u);\n let x_vec = x[x_start + x_idx];\n res[x_idx] = m * x_vec;\n \n x_sum += x_vec.x + x_vec.y + x_vec.z + x_vec.w; \n }\n \n let swx = res[0] + res[1];\n let kappa = alpha * x_sum;\n \n let y_start = (args.y_offset + (r * args.total_nbc)) / 4u;\n y[y_start + bc] += (swx * beta) + vec4(kappa);\n}\n\n").concat(emptyShader);var forwardSingleBitDepth2ShaderSource="\n\nstruct argsStruct {\n n: u32,\n nbr: u32,\n total_nbc: u32,\n bit_depth_nbc: u32,\n x_offset: u32,\n metas_offset: u32,\n blocks_offset: u32,\n y_offset: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar x: array>;\n\n@group(0) @binding(2)\nvar metas: array;\n\n@group(0) @binding(3)\nvar blocks: array;\n\n@group(0) @binding(4)\nvar y: array>;\n\n".concat(fromFP510Function,"\n\nconst block_size: u32 = 8u;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= (args.nbr * 4) || global_id.y >= args.bit_depth_nbc) {\n return;\n }\n\n let r = global_id.x * 4u;\n let c = global_id.y * ").concat(columnsPerBlock,";\n let br = global_id.x / 4u; \n let bc = global_id.y;\n let br_offset = global_id.x % 4u;\n \n let row_metas_start: u32 = args.metas_offset + (br * args.bit_depth_nbc);\n let row_blocks_start: u32 = args.blocks_offset + (br * args.bit_depth_nbc * block_size); \n \n let alpha = from_fp510(extractBits(metas[row_metas_start + bc], 0, 16u)); \n let beta = from_fp510(extractBits(metas[row_metas_start + bc], 16u, 16u));\n \n let x_start = ((args.x_offset + c) / 4u);\n \n var b01_start = row_blocks_start + (br_offset * 2u) + (bc * block_size);\n var b01_offset = 0u;\n \n var res: array, 2u>;\n var x_sum: f32 = 0.0;\n \n for (var j = 0u; j < ").concat(columnsPerBlock,"; j+=4) {\n \n var b01 = blocks[b01_start];\n \n let w0_0 = f32(extractBits(b01, b01_offset + (2u * j), 2u)); \n let w0_1 = f32(extractBits(b01, b01_offset + (2u * (j + 1)), 2u)); \n let w0_2 = f32(extractBits(b01, b01_offset + (2u * (j + 2)), 2u));\n let w0_3 = f32(extractBits(b01, b01_offset + (2u * (j + 3)), 2u));\n \n b01_offset = 16u;\n \n let w1_0 = f32(extractBits(b01, b01_offset + (2u * j), 2u)); \n let w1_1 = f32(extractBits(b01, b01_offset + (2u * (j + 1)), 2u)); \n let w1_2 = f32(extractBits(b01, b01_offset + (2u * (j + 2)), 2u));\n let w1_3 = f32(extractBits(b01, b01_offset + (2u * (j + 3)), 2u));\n \n b01_offset = 0u; \n b01 = blocks[b01_start + 1u];\n \n let w2_0 = f32(extractBits(b01, b01_offset + (2u * j), 2u)); \n let w2_1 = f32(extractBits(b01, b01_offset + (2u * (j + 1)), 2u)); \n let w2_2 = f32(extractBits(b01, b01_offset + (2u * (j + 2)), 2u));\n let w2_3 = f32(extractBits(b01, b01_offset + (2u * (j + 3)), 2u));\n \n b01_offset = 16u;\n \n let w3_0 = f32(extractBits(b01, b01_offset + (2u * j), 2u)); \n let w3_1 = f32(extractBits(b01, b01_offset + (2u * (j + 1)), 2u)); \n let w3_2 = f32(extractBits(b01, b01_offset + (2u * (j + 2)), 2u));\n let w3_3 = f32(extractBits(b01, b01_offset + (2u * (j + 3)), 2u));\n \n b01_offset = 0u;\n \n let m = mat4x4(\n w0_0, w1_0, w2_0, w3_0,\n w0_1, w1_1, w2_1, w3_1, \n w0_2, w1_2, w2_2, w3_2,\n w0_3, w1_3, w2_3, w3_3);\n\n let x_idx = (j / 4u);\n let x_vec = x[x_start + x_idx];\n res[x_idx] = m * x_vec;\n \n x_sum += x_vec.x + x_vec.y + x_vec.z + x_vec.w; \n }\n \n let swx = res[0] + res[1];\n let kappa = alpha * x_sum;\n \n let y_start = (args.y_offset + (r * args.total_nbc)) / 4u;\n y[y_start + bc] += (swx * beta) + vec4(kappa);\n}\n\n").concat(emptyShader);var forwardSingleBitDepth3ShaderSource="\n\nstruct argsStruct {\n n: u32,\n nbr: u32,\n total_nbc: u32,\n bit_depth_nbc: u32,\n x_offset: u32,\n metas_offset: u32,\n blocks_offset: u32,\n y_offset: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar x: array>;\n\n@group(0) @binding(2)\nvar metas: array;\n\n@group(0) @binding(3)\nvar blocks: array;\n\n@group(0) @binding(4)\nvar y: array>;\n\n".concat(fromFP510Function,"\n\nconst block_size: u32 = 12u;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id : vec3) {\n if (global_id.x >= (args.nbr * 4) || global_id.y >= args.bit_depth_nbc) {\n return;\n }\n \n let r = global_id.x * 4u;\n let c = global_id.y * ").concat(columnsPerBlock,";\n let br = global_id.x / 4u; \n let bc = global_id.y;\n let br_offset = global_id.x % 4u;\n \n let row_metas_start: u32 = args.metas_offset + (br * args.bit_depth_nbc);\n let row_blocks_start: u32 = args.blocks_offset + (br * args.bit_depth_nbc * block_size); \n \n let alpha = from_fp510(extractBits(metas[row_metas_start + bc], 0, 16u)); \n let beta = from_fp510(extractBits(metas[row_metas_start + bc], 16u, 16u));\n\n let x_start = ((args.x_offset + c) / 4u);\n \n var b01_start = row_blocks_start + (br_offset * 2u) + (bc * block_size);\n var b2_start = row_blocks_start + br_offset + (bc * block_size) + 8u;\n var b01_offset = 0u;\n var b2_offset = 0u;\n\n var res: array, 2u>;\n var x_sum: f32 = 0.0;\n \n for (var j = 0u; j < ").concat(columnsPerBlock,"; j+=4) { \n \n var b01 = blocks[b01_start];\n var b2 = blocks[b2_start];\n \n var b01_bits = extractBits(b01, b01_offset + (2u * j), 2u);\n var b2_bit = extractBits(b2, b2_offset + j, 1u);\n let w0_0 = f32(insertBits(b01_bits, b2_bit, 2u, 1u));\n \n b01_bits = extractBits(b01, b01_offset + (2u * (j + 1)), 2u);\n b2_bit = extractBits(b2, b2_offset + (j + 1), 1u);\n let w0_1 = f32(insertBits(b01_bits, b2_bit, 2u, 1u));\n \n b01_bits = extractBits(b01, b01_offset + (2u * (j + 2)), 2u);\n b2_bit = extractBits(b2, b2_offset + (j + 2), 1u);\n let w0_2 = f32(insertBits(b01_bits, b2_bit, 2u, 1u));\n \n b01_bits = extractBits(b01, b01_offset + (2u * (j + 3)), 2u);\n b2_bit = extractBits(b2, b2_offset + (j + 3), 1u);\n let w0_3 = f32(insertBits(b01_bits, b2_bit, 2u, 1u));\n \n b01_offset = 16u;\n b2_offset = 8u;\n \n b01_bits = extractBits(b01, b01_offset + (2u * j), 2u);\n b2_bit = extractBits(b2, b2_offset + j, 1u); \n let w1_0 = f32(insertBits(b01_bits, b2_bit, 2u, 1u));\n \n b01_bits = extractBits(b01, b01_offset + (2u * (j + 1)), 2u);\n b2_bit = extractBits(b2, b2_offset + (j + 1), 1u);\n let w1_1 = f32(insertBits(b01_bits, b2_bit, 2u, 1u));\n \n b01_bits = extractBits(b01, b01_offset + (2u * (j + 2)), 2u);\n b2_bit = extractBits(b2, b2_offset + (j + 2), 1u);\n let w1_2 = f32(insertBits(b01_bits, b2_bit, 2u, 1u));\n \n b01_bits = extractBits(b01, b01_offset + (2u * (j + 3)), 2u);\n b2_bit = extractBits(b2, b2_offset + (j + 3), 1u);\n let w1_3 = f32(insertBits(b01_bits, b2_bit, 2u, 1u));\n \n b01_offset = 0u;\n b2_offset = 16u; \n b01 = blocks[b01_start + 1u];\n \n b01_bits = extractBits(b01, b01_offset + (2u * j), 2u);\n b2_bit = extractBits(b2, b2_offset + j, 1u); \n let w2_0 = f32(insertBits(b01_bits, b2_bit, 2u, 1u));\n \n b01_bits = extractBits(b01, b01_offset + (2u * (j + 1)), 2u);\n b2_bit = extractBits(b2, b2_offset + (j + 1), 1u);\n let w2_1 = f32(insertBits(b01_bits, b2_bit, 2u, 1u));\n \n b01_bits = extractBits(b01, b01_offset + (2u * (j + 2)), 2u);\n b2_bit = extractBits(b2, b2_offset + (j + 2), 1u);\n let w2_2 = f32(insertBits(b01_bits, b2_bit, 2u, 1u));\n \n b01_bits = extractBits(b01, b01_offset + (2u * (j + 3)), 2u);\n b2_bit = extractBits(b2, b2_offset + (j + 3), 1u);\n let w2_3 = f32(insertBits(b01_bits, b2_bit, 2u, 1u));\n \n b01_offset = 16u;\n b2_offset = 24u; \n \n b01_bits = extractBits(b01, b01_offset + (2u * j), 2u);\n b2_bit = extractBits(b2, b2_offset + j, 1u); \n let w3_0 = f32(insertBits(b01_bits, b2_bit, 2u, 1u));\n \n b01_bits = extractBits(b01, b01_offset + (2u * (j + 1)), 2u);\n b2_bit = extractBits(b2, b2_offset + (j + 1), 1u);\n let w3_1 = f32(insertBits(b01_bits, b2_bit, 2u, 1u));\n \n b01_bits = extractBits(b01, b01_offset + (2u * (j + 2)), 2u);\n b2_bit = extractBits(b2, b2_offset + (j + 2), 1u);\n let w3_2 = f32(insertBits(b01_bits, b2_bit, 2u, 1u));\n \n b01_bits = extractBits(b01, b01_offset + (2u * (j + 3)), 2u);\n b2_bit = extractBits(b2, b2_offset + (j + 3), 1u);\n let w3_3 = f32(insertBits(b01_bits, b2_bit, 2u, 1u));\n \n b01_offset = 0u;\n b2_offset = 0u; \n \n let m = mat4x4(\n w0_0, w1_0, w2_0, w3_0,\n w0_1, w1_1, w2_1, w3_1, \n w0_2, w1_2, w2_2, w3_2,\n w0_3, w1_3, w2_3, w3_3);\n \n let x_idx = (j / 4u);\n let x_vec = x[x_start + x_idx];\n res[x_idx] = m * x_vec;\n \n x_sum += x_vec.x + x_vec.y + x_vec.z + x_vec.w;\n }\n\n let swx = res[0] + res[1];\n let kappa = alpha * x_sum;\n \n let y_start = (args.y_offset + (r * args.total_nbc)) / 4u;\n y[y_start + bc] += (swx * beta) + vec4(kappa);\n}\n\n").concat(emptyShader);var forwardSingleBitDepth4ShaderSource="\n\nstruct argsStruct {\n n: u32,\n nbr: u32,\n total_nbc: u32,\n bit_depth_nbc: u32,\n x_offset: u32,\n metas_offset: u32,\n blocks_offset: u32,\n y_offset: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar x: array>;\n\n@group(0) @binding(2)\nvar metas: array;\n\n@group(0) @binding(3)\nvar blocks: array;\n\n@group(0) @binding(4)\nvar y: array>;\n\n".concat(fromFP510Function,"\n\nconst block_size: u32 = 16u;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= (args.nbr * 4) || global_id.y >= args.bit_depth_nbc) {\n return;\n }\n \n let r = global_id.x * 4u;\n let c = global_id.y * ").concat(columnsPerBlock,";\n let br = global_id.x / 4u; \n let bc = global_id.y;\n let br_offset = global_id.x % 4u;\n \n let row_metas_start: u32 = args.metas_offset + (br * args.bit_depth_nbc);\n let row_blocks_start: u32 = args.blocks_offset + (br * args.bit_depth_nbc * block_size); \n \n let alpha = from_fp510(extractBits(metas[row_metas_start + bc], 0, 16u)); \n let beta = from_fp510(extractBits(metas[row_metas_start + bc], 16u, 16u));\n \n let x_start = ((args.x_offset + c) / 4u);\n \n var b03_start = row_blocks_start + (br_offset * 4u) + (bc * block_size); \n\n var res: array, 2u>;\n var x_sum: f32 = 0.0;\n\n for (var j = 0u; j < ").concat(columnsPerBlock,"; j+=4) {\n \n var b03 = blocks[b03_start]; \n \n let w0_0 = f32(extractBits(b03, 4u * j, 4u)); \n let w0_1 = f32(extractBits(b03, 4u * (j + 1), 4u)); \n let w0_2 = f32(extractBits(b03, 4u * (j + 2), 4u));\n let w0_3 = f32(extractBits(b03, 4u * (j + 3), 4u));\n \n b03 = blocks[b03_start + 1];\n \n let w1_0 = f32(extractBits(b03, 4u * j, 4u)); \n let w1_1 = f32(extractBits(b03, 4u * (j + 1), 4u)); \n let w1_2 = f32(extractBits(b03, 4u * (j + 2), 4u));\n let w1_3 = f32(extractBits(b03, 4u * (j + 3), 4u));\n \n b03 = blocks[b03_start + 2];\n \n let w2_0 = f32(extractBits(b03, 4u * j, 4u)); \n let w2_1 = f32(extractBits(b03, 4u * (j + 1), 4u)); \n let w2_2 = f32(extractBits(b03, 4u * (j + 2), 4u));\n let w2_3 = f32(extractBits(b03, 4u * (j + 3), 4u));\n \n b03 = blocks[b03_start + 3];\n \n let w3_0 = f32(extractBits(b03, 4u * j, 4u)); \n let w3_1 = f32(extractBits(b03, 4u * (j + 1), 4u)); \n let w3_2 = f32(extractBits(b03, 4u * (j + 2), 4u));\n let w3_3 = f32(extractBits(b03, 4u * (j + 3), 4u));\n \n let m = mat4x4(\n w0_0, w1_0, w2_0, w3_0,\n w0_1, w1_1, w2_1, w3_1, \n w0_2, w1_2, w2_2, w3_2,\n w0_3, w1_3, w2_3, w3_3);\n\n let x_idx = (j / 4u);\n let x_vec = x[x_start + x_idx];\n res[x_idx] = m * x_vec;\n \n x_sum += x_vec.x + x_vec.y + x_vec.z + x_vec.w;\n }\n let swx = res[0] + res[1];\n let kappa = alpha * x_sum;\n \n let y_start = (args.y_offset + (r * args.total_nbc)) / 4u;\n y[y_start + bc] += (swx * beta) + vec4(kappa);\n}\n\n").concat(emptyShader);var forwardSingleBitDepth5ShaderSource="\n\nstruct argsStruct {\n n: u32,\n nbr: u32,\n total_nbc: u32,\n bit_depth_nbc: u32,\n x_offset: u32,\n metas_offset: u32,\n blocks_offset: u32,\n y_offset: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar x: array>;\n\n@group(0) @binding(2)\nvar metas: array;\n\n@group(0) @binding(3)\nvar blocks: array;\n\n@group(0) @binding(4)\nvar y: array>;\n\n".concat(fromFP510Function,"\n\nconst block_size: u32 = 20u;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= (args.nbr * 4) || global_id.y >= args.bit_depth_nbc) {\n return;\n }\n \n let r = global_id.x * 4u;\n let c = global_id.y * ").concat(columnsPerBlock,";\n let br = global_id.x / 4u; \n let bc = global_id.y;\n let br_offset = global_id.x % 4u;\n \n let row_metas_start: u32 = args.metas_offset + (br * args.bit_depth_nbc);\n let row_blocks_start: u32 = args.blocks_offset + (br * args.bit_depth_nbc * block_size); \n \n let alpha = from_fp510(extractBits(metas[row_metas_start + bc], 0, 16u)); \n let beta = from_fp510(extractBits(metas[row_metas_start + bc], 16u, 16u));\n \n let x_start = ((args.x_offset + c) / 4u);\n \n var b03_start = row_blocks_start + (br_offset * 4u) + (bc * block_size);\n var b4_start = row_blocks_start + br_offset + (bc * block_size) + 16u;\n \n var b4_offset = 0u;\n \n var res: array, 2u>;\n var x_sum: f32 = 0.0;\n \n for (var j = 0u; j < ").concat(columnsPerBlock,"; j+=4) {\n \n var b03 = blocks[b03_start];\n var b4 = blocks[b4_start];\n \n var b03_bits = extractBits(b03, 4u * j, 4u);\n var b4_bit = extractBits(b4, b4_offset + j, 1u); \n let w0_0 = f32(insertBits(b03_bits, b4_bit, 4u, 1u));\n \n b03_bits = extractBits(b03, 4u * (j + 1), 4u);\n b4_bit = extractBits(b4, b4_offset + (j + 1), 1u);\n let w0_1 = f32(insertBits(b03_bits, b4_bit, 4u, 1u));\n \n b03_bits = extractBits(b03, 4u * (j + 2), 4u);\n b4_bit = extractBits(b4, b4_offset + (j + 2), 1u);\n let w0_2 = f32(insertBits(b03_bits, b4_bit, 4u, 1u));\n \n b03_bits = extractBits(b03, 4u * (j + 3), 4u);\n b4_bit = extractBits(b4, b4_offset + (j + 3), 1u);\n let w0_3 = f32(insertBits(b03_bits, b4_bit, 4u, 1u));\n \n b03 = blocks[b03_start + 1];\n b4_offset = 8u;\n \n b03_bits = extractBits(b03, 4u * j, 4u);\n b4_bit = extractBits(b4, b4_offset + j, 1u); \n let w1_0 = f32(insertBits(b03_bits, b4_bit, 4u, 1u));\n \n b03_bits = extractBits(b03, 4u * (j + 1), 4u);\n b4_bit = extractBits(b4, b4_offset + (j + 1), 1u);\n let w1_1 = f32(insertBits(b03_bits, b4_bit, 4u, 1u));\n \n b03_bits = extractBits(b03, 4u * (j + 2), 4u);\n b4_bit = extractBits(b4, b4_offset + (j + 2), 1u);\n let w1_2 = f32(insertBits(b03_bits, b4_bit, 4u, 1u));\n \n b03_bits = extractBits(b03, 4u * (j + 3), 4u);\n b4_bit = extractBits(b4, b4_offset + (j + 3), 1u);\n let w1_3 = f32(insertBits(b03_bits, b4_bit, 4u, 1u));\n \n b03 = blocks[b03_start + 2];\n b4_offset = 16u;\n \n b03_bits = extractBits(b03, 4u * j, 4u);\n b4_bit = extractBits(b4, b4_offset + j, 1u); \n let w2_0 = f32(insertBits(b03_bits, b4_bit, 4u, 1u));\n \n b03_bits = extractBits(b03, 4u * (j + 1), 4u);\n b4_bit = extractBits(b4, b4_offset + (j + 1), 1u);\n let w2_1 = f32(insertBits(b03_bits, b4_bit, 4u, 1u));\n \n b03_bits = extractBits(b03, 4u * (j + 2), 4u);\n b4_bit = extractBits(b4, b4_offset + (j + 2), 1u);\n let w2_2 = f32(insertBits(b03_bits, b4_bit, 4u, 1u));\n \n b03_bits = extractBits(b03, 4u * (j + 3), 4u);\n b4_bit = extractBits(b4, b4_offset + (j + 3), 1u);\n let w2_3 = f32(insertBits(b03_bits, b4_bit, 4u, 1u));\n \n b03 = blocks[b03_start + 3];\n b4_offset = 24u;\n \n b03_bits = extractBits(b03, 4u * j, 4u);\n b4_bit = extractBits(b4, b4_offset + j, 1u); \n let w3_0 = f32(insertBits(b03_bits, b4_bit, 4u, 1u));\n \n b03_bits = extractBits(b03, 4u * (j + 1), 4u);\n b4_bit = extractBits(b4, b4_offset + (j + 1), 1u);\n let w3_1 = f32(insertBits(b03_bits, b4_bit, 4u, 1u));\n \n b03_bits = extractBits(b03, 4u * (j + 2), 4u);\n b4_bit = extractBits(b4, b4_offset + (j + 2), 1u);\n let w3_2 = f32(insertBits(b03_bits, b4_bit, 4u, 1u));\n \n b03_bits = extractBits(b03, 4u * (j + 3), 4u);\n b4_bit = extractBits(b4, b4_offset + (j + 3), 1u);\n let w3_3 = f32(insertBits(b03_bits, b4_bit, 4u, 1u));\n \n b4_offset = 0u;\n \n let m = mat4x4(\n w0_0, w1_0, w2_0, w3_0,\n w0_1, w1_1, w2_1, w3_1, \n w0_2, w1_2, w2_2, w3_2,\n w0_3, w1_3, w2_3, w3_3);\n\n let x_idx = (j / 4u);\n let x_vec = x[x_start + x_idx];\n res[x_idx] = m * x_vec;\n \n x_sum += x_vec.x + x_vec.y + x_vec.z + x_vec.w;\n }\n let swx = res[0] + res[1];\n let kappa = alpha * x_sum;\n \n let y_start = (args.y_offset + (r * args.total_nbc)) / 4u;\n y[y_start + bc] += (swx * beta) + vec4(kappa);\n}\n\n").concat(emptyShader);var forwardSingleBitDepth6ShaderSource="\n\nstruct argsStruct {\n n: u32,\n nbr: u32,\n total_nbc: u32,\n bit_depth_nbc: u32,\n x_offset: u32,\n metas_offset: u32,\n blocks_offset: u32,\n y_offset: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar x: array>;\n\n@group(0) @binding(2)\nvar metas: array;\n\n@group(0) @binding(3)\nvar blocks: array;\n\n@group(0) @binding(4)\nvar y: array>;\n\n".concat(fromFP510Function,"\n\nconst block_size: u32 = 24u;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= (args.nbr * 4) || global_id.y >= args.bit_depth_nbc) {\n return;\n }\n \n let r = global_id.x * 4u;\n let c = global_id.y * ").concat(columnsPerBlock,";\n let br = global_id.x / 4u; \n let bc = global_id.y;\n let br_offset = global_id.x % 4u;\n \n let row_metas_start: u32 = args.metas_offset + (br * args.bit_depth_nbc);\n let row_blocks_start: u32 = args.blocks_offset + (br * args.bit_depth_nbc * block_size); \n \n let alpha = from_fp510(extractBits(metas[row_metas_start + bc], 0, 16u)); \n let beta = from_fp510(extractBits(metas[row_metas_start + bc], 16u, 16u));\n \n let x_start = ((args.x_offset + c) / 4u);\n \n var b03_start = row_blocks_start + (br_offset * 4u) + (bc * block_size);\n var b45_start = row_blocks_start + (br_offset * 2u) + (bc * block_size) + 16u;\n \n var b45_offset = 0u;\n \n var res: array, 2u>;\n var x_sum: f32 = 0.0;\n \n for (var j = 0u; j < ").concat(columnsPerBlock,"; j+=4) {\n \n var b03 = blocks[b03_start];\n var b45 = blocks[b45_start];\n \n var b03_bits = extractBits(b03, 4u * j, 4u);\n var b45_bits = extractBits(b45, b45_offset + (j * 2), 2u);\n let w0_0 = f32(insertBits(b03_bits, b45_bits, 4u, 2u));\n \n b03_bits = extractBits(b03, 4u * (j + 1), 4u);\n b45_bits = extractBits(b45, b45_offset + (2u * (j + 1)), 2u);\n let w0_1 = f32(insertBits(b03_bits, b45_bits, 4u, 2u));\n \n b03_bits = extractBits(b03, 4u * (j + 2), 4u);\n b45_bits = extractBits(b45, b45_offset + (2u * (j + 2)), 2u);\n let w0_2 = f32(insertBits(b03_bits, b45_bits, 4u, 2u));\n \n b03_bits = extractBits(b03, 4u * (j + 3), 4u);\n b45_bits = extractBits(b45, b45_offset + (2u * (j + 3)), 2u);\n let w0_3 = f32(insertBits(b03_bits, b45_bits, 4u, 2u));\n \n b03 = blocks[b03_start + 1];\n b45_offset = 16u;\n \n b03_bits = extractBits(b03, 4u * j, 4u);\n b45_bits = extractBits(b45, b45_offset + (j * 2), 2u);\n let w1_0 = f32(insertBits(b03_bits, b45_bits, 4u, 2u));\n \n b03_bits = extractBits(b03, 4u * (j + 1), 4u);\n b45_bits = extractBits(b45, b45_offset + (2u * (j + 1)), 2u);\n let w1_1 = f32(insertBits(b03_bits, b45_bits, 4u, 2u));\n \n b03_bits = extractBits(b03, 4u * (j + 2), 4u);\n b45_bits = extractBits(b45, b45_offset + (2u * (j + 2)), 2u);\n let w1_2 = f32(insertBits(b03_bits, b45_bits, 4u, 2u));\n \n b03_bits = extractBits(b03, 4u * (j + 3), 4u);\n b45_bits = extractBits(b45, b45_offset + (2u * (j + 3)), 2u);\n let w1_3 = f32(insertBits(b03_bits, b45_bits, 4u, 2u)); \n \n b03 = blocks[b03_start + 2];\n b45 = blocks[b45_start + 1];\n b45_offset = 0u;\n \n b03_bits = extractBits(b03, 4u * j, 4u);\n b45_bits = extractBits(b45, b45_offset + (j * 2), 2u);\n let w2_0 = f32(insertBits(b03_bits, b45_bits, 4u, 2u));\n \n b03_bits = extractBits(b03, 4u * (j + 1), 4u);\n b45_bits = extractBits(b45, b45_offset + (2u * (j + 1)), 2u);\n let w2_1 = f32(insertBits(b03_bits, b45_bits, 4u, 2u));\n \n b03_bits = extractBits(b03, 4u * (j + 2), 4u);\n b45_bits = extractBits(b45, b45_offset + (2u * (j + 2)), 2u);\n let w2_2 = f32(insertBits(b03_bits, b45_bits, 4u, 2u));\n \n b03_bits = extractBits(b03, 4u * (j + 3), 4u);\n b45_bits = extractBits(b45, b45_offset + (2u * (j + 3)), 2u);\n let w2_3 = f32(insertBits(b03_bits, b45_bits, 4u, 2u));\n \n b03 = blocks[b03_start + 3];\n b45_offset = 16u;\n \n b03_bits = extractBits(b03, 4u * j, 4u);\n b45_bits = extractBits(b45, b45_offset + (j * 2), 2u);\n let w3_0 = f32(insertBits(b03_bits, b45_bits, 4u, 2u));\n \n b03_bits = extractBits(b03, 4u * (j + 1), 4u);\n b45_bits = extractBits(b45, b45_offset + (2u * (j + 1)), 2u);\n let w3_1 = f32(insertBits(b03_bits, b45_bits, 4u, 2u));\n \n b03_bits = extractBits(b03, 4u * (j + 2), 4u);\n b45_bits = extractBits(b45, b45_offset + (2u * (j + 2)), 2u);\n let w3_2 = f32(insertBits(b03_bits, b45_bits, 4u, 2u));\n \n b03_bits = extractBits(b03, 4u * (j + 3), 4u);\n b45_bits = extractBits(b45, b45_offset + (2u * (j + 3)), 2u);\n let w3_3 = f32(insertBits(b03_bits, b45_bits, 4u, 2u));\n \n b45_offset = 0u;\n \n let m = mat4x4(\n w0_0, w1_0, w2_0, w3_0,\n w0_1, w1_1, w2_1, w3_1, \n w0_2, w1_2, w2_2, w3_2,\n w0_3, w1_3, w2_3, w3_3);\n\n let x_idx = (j / 4u);\n let x_vec = x[x_start + x_idx];\n res[x_idx] = m * x_vec;\n \n x_sum += x_vec.x + x_vec.y + x_vec.z + x_vec.w;\n }\n let swx = res[0] + res[1];\n let kappa = alpha * x_sum;\n \n let y_start = (args.y_offset + (r * args.total_nbc)) / 4u;\n y[y_start + bc] += (swx * beta) + vec4(kappa);\n}\n\n").concat(emptyShader);var forwardSingleBitDepth7ShaderSource="\n\nstruct argsStruct {\n n: u32,\n nbr: u32,\n total_nbc: u32,\n bit_depth_nbc: u32,\n x_offset: u32,\n metas_offset: u32,\n blocks_offset: u32,\n y_offset: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar x: array>;\n\n@group(0) @binding(2)\nvar metas: array;\n\n@group(0) @binding(3)\nvar blocks: array;\n\n@group(0) @binding(4)\nvar y: array>;\n\n".concat(fromFP510Function,"\n\nconst block_size: u32 = 28u;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= (args.nbr * 4) || global_id.y >= args.bit_depth_nbc) {\n return;\n }\n \n let r = global_id.x * 4u;\n let c = global_id.y * ").concat(columnsPerBlock,";\n let br = global_id.x / 4u; \n let bc = global_id.y;\n let br_offset = global_id.x % 4u;\n \n let row_metas_start: u32 = args.metas_offset + (br * args.bit_depth_nbc);\n let row_blocks_start: u32 = args.blocks_offset + (br * args.bit_depth_nbc * block_size); \n \n let alpha = from_fp510(extractBits(metas[row_metas_start + bc], 0, 16u)); \n let beta = from_fp510(extractBits(metas[row_metas_start + bc], 16u, 16u));\n \n let x_start = ((args.x_offset + c) / 4u);\n \n var b03_start = row_blocks_start + (br_offset * 4u) + (bc * block_size);\n var b45_start = row_blocks_start + (br_offset * 2u) + (bc * block_size) + 16u;\n var b6_start = row_blocks_start + br_offset + (bc * block_size) + 24u;\n \n var b45_offset = 0u;\n var b6_offset = 0u;\n \n var res: array, 2u>;\n var x_sum: f32 = 0.0;\n \n for (var j = 0u; j < ").concat(columnsPerBlock,"; j+=4) {\n \n var b03 = blocks[b03_start];\n var b45 = blocks[b45_start];\n var b6 = blocks[b6_start];\n \n var b03_bits = extractBits(b03, 4u * j, 4u);\n var b45_bits = extractBits(b45, b45_offset + (j * 2), 2u);\n var b6_bit = extractBits(b6, b6_offset + j, 1u);\n let w0_0 = f32(insertBits(insertBits(b03_bits, b45_bits, 4u, 2u), b6_bit, 6u, 1u));\n \n b03_bits = extractBits(b03, 4u * (j + 1), 4u);\n b45_bits = extractBits(b45, b45_offset + (2u * (j + 1)), 2u);\n b6_bit = extractBits(b6, b6_offset + j + 1, 1u);\n let w0_1 = f32(insertBits(insertBits(b03_bits, b45_bits, 4u, 2u), b6_bit, 6u, 1u));\n \n b03_bits = extractBits(b03, 4u * (j + 2), 4u);\n b45_bits = extractBits(b45, b45_offset + (2u * (j + 2)), 2u);\n b6_bit = extractBits(b6, b6_offset + j + 2, 1u);\n let w0_2 = f32(insertBits(insertBits(b03_bits, b45_bits, 4u, 2u), b6_bit, 6u, 1u)); \n \n b03_bits = extractBits(b03, 4u * (j + 3), 4u);\n b45_bits = extractBits(b45, b45_offset + (2u * (j + 3)), 2u);\n b6_bit = extractBits(b6, b6_offset + j + 3, 1u);\n let w0_3 = f32(insertBits(insertBits(b03_bits, b45_bits, 4u, 2u), b6_bit, 6u, 1u));\n \n b03 = blocks[b03_start + 1];\n b45_offset = 16u;\n b6_offset = 8u;\n \n b03_bits = extractBits(b03, 4u * j, 4u);\n b45_bits = extractBits(b45, b45_offset + (j * 2), 2u);\n b6_bit = extractBits(b6, b6_offset + j, 1u);\n let w1_0 = f32(insertBits(insertBits(b03_bits, b45_bits, 4u, 2u), b6_bit, 6u, 1u));\n \n b03_bits = extractBits(b03, 4u * (j + 1), 4u);\n b45_bits = extractBits(b45, b45_offset + (2u * (j + 1)), 2u);\n b6_bit = extractBits(b6, b6_offset + j + 1, 1u);\n let w1_1 = f32(insertBits(insertBits(b03_bits, b45_bits, 4u, 2u), b6_bit, 6u, 1u));\n \n b03_bits = extractBits(b03, 4u * (j + 2), 4u);\n b45_bits = extractBits(b45, b45_offset + (2u * (j + 2)), 2u);\n b6_bit = extractBits(b6, b6_offset + j + 2, 1u);\n let w1_2 = f32(insertBits(insertBits(b03_bits, b45_bits, 4u, 2u), b6_bit, 6u, 1u)); \n \n b03_bits = extractBits(b03, 4u * (j + 3), 4u);\n b45_bits = extractBits(b45, b45_offset + (2u * (j + 3)), 2u);\n b6_bit = extractBits(b6, b6_offset + j + 3, 1u);\n let w1_3 = f32(insertBits(insertBits(b03_bits, b45_bits, 4u, 2u), b6_bit, 6u, 1u));\n \n b03 = blocks[b03_start + 2];\n b45 = blocks[b45_start + 1];\n b45_offset = 0u;\n b6_offset = 16u;\n\n b03_bits = extractBits(b03, 4u * j, 4u);\n b45_bits = extractBits(b45, b45_offset + (j * 2), 2u);\n b6_bit = extractBits(b6, b6_offset + j, 1u);\n let w2_0 = f32(insertBits(insertBits(b03_bits, b45_bits, 4u, 2u), b6_bit, 6u, 1u));\n \n b03_bits = extractBits(b03, 4u * (j + 1), 4u);\n b45_bits = extractBits(b45, b45_offset + (2u * (j + 1)), 2u);\n b6_bit = extractBits(b6, b6_offset + j + 1, 1u);\n let w2_1 = f32(insertBits(insertBits(b03_bits, b45_bits, 4u, 2u), b6_bit, 6u, 1u));\n \n b03_bits = extractBits(b03, 4u * (j + 2), 4u);\n b45_bits = extractBits(b45, b45_offset + (2u * (j + 2)), 2u);\n b6_bit = extractBits(b6, b6_offset + j + 2, 1u);\n let w2_2 = f32(insertBits(insertBits(b03_bits, b45_bits, 4u, 2u), b6_bit, 6u, 1u)); \n \n b03_bits = extractBits(b03, 4u * (j + 3), 4u);\n b45_bits = extractBits(b45, b45_offset + (2u * (j + 3)), 2u);\n b6_bit = extractBits(b6, b6_offset + j + 3, 1u);\n let w2_3 = f32(insertBits(insertBits(b03_bits, b45_bits, 4u, 2u), b6_bit, 6u, 1u));\n \n b03 = blocks[b03_start + 3];\n b45_offset = 16u;\n b6_offset = 24u;\n \n b03_bits = extractBits(b03, 4u * j, 4u);\n b45_bits = extractBits(b45, b45_offset + (j * 2), 2u);\n b6_bit = extractBits(b6, b6_offset + j, 1u);\n let w3_0 = f32(insertBits(insertBits(b03_bits, b45_bits, 4u, 2u), b6_bit, 6u, 1u));\n \n b03_bits = extractBits(b03, 4u * (j + 1), 4u);\n b45_bits = extractBits(b45, b45_offset + (2u * (j + 1)), 2u);\n b6_bit = extractBits(b6, b6_offset + j + 1, 1u);\n let w3_1 = f32(insertBits(insertBits(b03_bits, b45_bits, 4u, 2u), b6_bit, 6u, 1u));\n \n b03_bits = extractBits(b03, 4u * (j + 2), 4u);\n b45_bits = extractBits(b45, b45_offset + (2u * (j + 2)), 2u);\n b6_bit = extractBits(b6, b6_offset + j + 2, 1u);\n let w3_2 = f32(insertBits(insertBits(b03_bits, b45_bits, 4u, 2u), b6_bit, 6u, 1u)); \n \n b03_bits = extractBits(b03, 4u * (j + 3), 4u);\n b45_bits = extractBits(b45, b45_offset + (2u * (j + 3)), 2u);\n b6_bit = extractBits(b6, b6_offset + j + 3, 1u);\n let w3_3 = f32(insertBits(insertBits(b03_bits, b45_bits, 4u, 2u), b6_bit, 6u, 1u));\n \n b45_offset = 0u;\n b6_offset = 0u;\n \n let m = mat4x4(\n w0_0, w1_0, w2_0, w3_0,\n w0_1, w1_1, w2_1, w3_1, \n w0_2, w1_2, w2_2, w3_2,\n w0_3, w1_3, w2_3, w3_3);\n\n let x_idx = (j / 4u);\n let x_vec = x[x_start + x_idx];\n res[x_idx] = m * x_vec;\n \n x_sum += x_vec.x + x_vec.y + x_vec.z + x_vec.w;\n }\n\n let swx = res[0] + res[1];\n let kappa = alpha * x_sum;\n \n let y_start = (args.y_offset + (r * args.total_nbc)) / 4u;\n y[y_start + bc] += (swx * beta) + vec4(kappa);\n}\n\n").concat(emptyShader);var forwardSingleBitDepth8ShaderSource="\n\nstruct argsStruct {\n n: u32,\n nbr: u32,\n total_nbc: u32,\n bit_depth_nbc: u32,\n x_offset: u32,\n metas_offset: u32,\n blocks_offset: u32,\n y_offset: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar x: array>;\n\n@group(0) @binding(2)\nvar metas: array;\n\n@group(0) @binding(3)\nvar blocks: array;\n\n@group(0) @binding(4)\nvar y: array>;\n\n".concat(fromFP510Function,"\n\nconst block_size: u32 = 32u;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= (args.nbr * 4) || global_id.y >= args.bit_depth_nbc) {\n return;\n }\n \n let r = global_id.x * 4u;\n let c = global_id.y * ").concat(columnsPerBlock,";\n let br = global_id.x / 4u; \n let bc = global_id.y;\n let br_offset = global_id.x % 4u;\n \n let row_metas_start: u32 = args.metas_offset + (br * args.bit_depth_nbc);\n let row_blocks_start: u32 = args.blocks_offset + (br * args.bit_depth_nbc * block_size); \n \n let alpha = from_fp510(extractBits(metas[row_metas_start + bc], 0, 16u)); \n let beta = from_fp510(extractBits(metas[row_metas_start + bc], 16u, 16u));\n \n let x_start = ((args.x_offset + c) / 4u);\n \n var b07_start = row_blocks_start + (br_offset * 8u) + (bc * block_size); \n\n var res: array, 2u>;\n var x_sum: f32 = 0.0;\n\n for (var j = 0u; j < 2; j++) {\n \n var b07 = blocks[b07_start + j];\n \n let w0_0 = f32(extractBits(b07, 0u, 8u)); \n let w0_1 = f32(extractBits(b07, 8u, 8u)); \n let w0_2 = f32(extractBits(b07, 16u, 8u));\n let w0_3 = f32(extractBits(b07, 24u, 8u));\n \n b07 = blocks[b07_start + 2 + j];\n \n let w1_0 = f32(extractBits(b07, 0u, 8u)); \n let w1_1 = f32(extractBits(b07, 8u, 8u)); \n let w1_2 = f32(extractBits(b07, 16u, 8u));\n let w1_3 = f32(extractBits(b07, 24u, 8u));\n \n b07 = blocks[b07_start + 4 + j];\n \n let w2_0 = f32(extractBits(b07, 0u, 8u)); \n let w2_1 = f32(extractBits(b07, 8u, 8u)); \n let w2_2 = f32(extractBits(b07, 16u, 8u));\n let w2_3 = f32(extractBits(b07, 24u, 8u));\n \n b07 = blocks[b07_start + 6 + j];\n \n let w3_0 = f32(extractBits(b07, 0u, 8u)); \n let w3_1 = f32(extractBits(b07, 8u, 8u)); \n let w3_2 = f32(extractBits(b07, 16u, 8u));\n let w3_3 = f32(extractBits(b07, 24u, 8u));\n \n let m = mat4x4(\n w0_0, w1_0, w2_0, w3_0,\n w0_1, w1_1, w2_1, w3_1, \n w0_2, w1_2, w2_2, w3_2,\n w0_3, w1_3, w2_3, w3_3);\n\n let x_vec = x[x_start + j];\n res[j] = m * x_vec;\n \n x_sum += x_vec.x + x_vec.y + x_vec.z + x_vec.w;\n }\n let swx = res[0] + res[1];\n let kappa = alpha * x_sum;\n \n let y_start = (args.y_offset + (r * args.total_nbc)) / 4u;\n y[y_start + bc] += (swx * beta) + vec4(kappa);\n}\n\n").concat(emptyShader);var forwardSingleShaderSources={1:forwardSingleBitDepth1ShaderSource,2:forwardSingleBitDepth2ShaderSource,3:forwardSingleBitDepth3ShaderSource,4:forwardSingleBitDepth4ShaderSource,5:forwardSingleBitDepth5ShaderSource,6:forwardSingleBitDepth6ShaderSource,7:forwardSingleBitDepth7ShaderSource,8:forwardSingleBitDepth8ShaderSource};var forwardSingleShaderNames={1:"pv_picollm_weight_block_mixed_16x8_forward_single_bit_depth_1_shader",2:"pv_picollm_weight_block_mixed_16x8_forward_single_bit_depth_2_shader",3:"pv_picollm_weight_block_mixed_16x8_forward_single_bit_depth_3_shader",4:"pv_picollm_weight_block_mixed_16x8_forward_single_bit_depth_4_shader",5:"pv_picollm_weight_block_mixed_16x8_forward_single_bit_depth_5_shader",6:"pv_picollm_weight_block_mixed_16x8_forward_single_bit_depth_6_shader",7:"pv_picollm_weight_block_mixed_16x8_forward_single_bit_depth_7_shader",8:"pv_picollm_weight_block_mixed_16x8_forward_single_bit_depth_8_shader"};var forwardShaderSources={1:forwardMultipleShaderSources(1),2:forwardMultipleShaderSources(2),3:forwardMultipleShaderSources(3),4:forwardMultipleShaderSources(4),5:forwardMultipleShaderSources(5),6:forwardMultipleShaderSources(6),7:forwardMultipleShaderSources(7),8:forwardMultipleShaderSources(8)};var forwardShaderNames={1:"pv_picollm_weight_block_mixed_16x8_forward_multiple_bit_depth_1_shader",2:"pv_picollm_weight_block_mixed_16x8_forward_multiple_bit_depth_2_shader",3:"pv_picollm_weight_block_mixed_16x8_forward_multiple_bit_depth_3_shader",4:"pv_picollm_weight_block_mixed_16x8_forward_multiple_bit_depth_4_shader",5:"pv_picollm_weight_block_mixed_16x8_forward_multiple_bit_depth_5_shader",6:"pv_picollm_weight_block_mixed_16x8_forward_multiple_bit_depth_6_shader",7:"pv_picollm_weight_block_mixed_16x8_forward_multiple_bit_depth_7_shader",8:"pv_picollm_weight_block_mixed_16x8_forward_multiple_bit_depth_8_shader"};var forwardShuffleXShaderName="pv_picollm_weight_block_mixed_16x8_forward_shuffle_x_shader";var forwardShuffleYShaderName="pv_picollm_weight_block_mixed_16x8_forward_shuffle_y_shader";var addBiasShaderName="pv_picollm_weight_block_mixed_16x8_add_bias_shader";var forwardSingleReduceYShaderName="pv_picollm_weight_block_mixed_16x8_forward_single_reduce_y_shader";var _weightBlockMixed16x;var loadPreprocessBlocksShader=function loadPreprocessBlocksShader(device,bitDepth){var bindGroupLayout=device.createBindGroupLayout({label:"weight preprocess blocks ".concat(bitDepth," bind group layout"),entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"weight preprocess blocks ".concat(bitDepth," pipeline layout"),bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"weight preprocess blocks ".concat(bitDepth," shader module"),code:preprocessShaderSources[bitDepth]});var computePipeline=device.createComputePipeline({label:"weight preprocess blocks ".concat(bitDepth," pipeline"),layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint,constants:{workgroup_size_x:preprocessDim,workgroup_size_y:preprocessDim}}});return{computePipeline:computePipeline}};var loadForwardShuffleXShader=function loadForwardShuffleXShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"weight shuffle x bind group layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:3,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"weight shuffle x pipeline layout",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"weight shuffle x shader module",code:forwardShuffleXShaderSource});var computePipeline=device.createComputePipeline({label:"weight shuffle x pipeline",layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint,constants:{workgroup_size_y:PV_PICOLLM_WEBGPU_DEFAULT_WORKGROUP_SIZE}}});return{computePipeline:computePipeline}};var loadForwardSingleReduceYShader=function loadForwardSingleReduceYShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"weight single reduce y bind group layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"weight single reduce y pipeline layout",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"weight single reduce y shader module",code:forwardSingleReduceYShaderSource});var computePipeline=device.createComputePipeline({label:"weight single reduce y pipeline",layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint,constants:{workgroup_size_x:PV_PICOLLM_WEBGPU_DEFAULT_WORKGROUP_SIZE}}});return{computePipeline:computePipeline}};var loadForwardShuffleYShader=function loadForwardShuffleYShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"weight shuffle y bind group layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"weight shuffle y pipeline layout",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"weight shuffle y shader module",code:forwardShuffleYShaderSource});var computePipeline=device.createComputePipeline({label:"weight shuffle y pipeline",layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint}});return{computePipeline:computePipeline}};var loadForwardSingleShader=function loadForwardSingleShader(device,bitDepth){var entries=[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:3,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:4,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}];var bindGroupLayout=device.createBindGroupLayout({label:"weight forward single ".concat(bitDepth," bind group layout"),entries:entries});var pipelineLayout=device.createPipelineLayout({label:"weight forward single ".concat(bitDepth," pipeline layout"),bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"weight forward single ".concat(bitDepth," shader module"),code:forwardSingleShaderSources[bitDepth]});var computePipeline=device.createComputePipeline({label:"weight forward single ".concat(bitDepth," pipeline"),layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint,constants:{workgroup_size_x:weightBlockSize,workgroup_size_y:1}}});return{computePipeline:computePipeline}};var loadForwardShader=function loadForwardShader(device,bitDepth){var entries=[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:3,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:4,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}];var bindGroupLayout=device.createBindGroupLayout({label:"weight forward multi ".concat(bitDepth," bind group layout"),entries:entries});var pipelineLayout=device.createPipelineLayout({label:"weight forward multi ".concat(bitDepth," pipeline layout"),bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"weight forward multi ".concat(bitDepth," shader module"),code:forwardShaderSources[bitDepth]});var computePipeline=device.createComputePipeline({label:"weight forward multi ".concat(bitDepth," pipeline"),layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint,constants:{workgroup_size_x:TC}}});return{computePipeline:computePipeline}};var loadAddBiasShader=function loadAddBiasShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"weight add bias bind group layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"weight add bias pipeline layout",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"weight add bias shader module",code:addBiasShaderSource});var computePipeline=device.createComputePipeline({label:"weight add bias pipeline",layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint}});return{computePipeline:computePipeline}};var weightBlockMixed16x8Shaders=(_weightBlockMixed16x={},_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_weightBlockMixed16x,preprocessShaderNames[3],function(device){return loadPreprocessBlocksShader(device,3)}),preprocessShaderNames[5],function(device){return loadPreprocessBlocksShader(device,5)}),preprocessShaderNames[6],function(device){return loadPreprocessBlocksShader(device,6)}),preprocessShaderNames[7],function(device){return loadPreprocessBlocksShader(device,7)}),forwardShuffleXShaderName,loadForwardShuffleXShader),forwardShuffleYShaderName,loadForwardShuffleYShader),forwardSingleReduceYShaderName,loadForwardSingleReduceYShader),forwardSingleShaderNames[1],function(device){return loadForwardSingleShader(device,1)}),forwardSingleShaderNames[2],function(device){return loadForwardSingleShader(device,2)}),forwardSingleShaderNames[3],function(device){return loadForwardSingleShader(device,3)}),_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_weightBlockMixed16x,forwardSingleShaderNames[4],function(device){return loadForwardSingleShader(device,4)}),forwardSingleShaderNames[5],function(device){return loadForwardSingleShader(device,5)}),forwardSingleShaderNames[6],function(device){return loadForwardSingleShader(device,6)}),forwardSingleShaderNames[7],function(device){return loadForwardSingleShader(device,7)}),forwardSingleShaderNames[8],function(device){return loadForwardSingleShader(device,8)}),forwardShaderNames[1],function(device){return loadForwardShader(device,1)}),forwardShaderNames[2],function(device){return loadForwardShader(device,2)}),forwardShaderNames[3],function(device){return loadForwardShader(device,3)}),forwardShaderNames[4],function(device){return loadForwardShader(device,4)}),forwardShaderNames[5],function(device){return loadForwardShader(device,5)}),_defineProperty(_defineProperty(_defineProperty(_defineProperty(_weightBlockMixed16x,forwardShaderNames[6],function(device){return loadForwardShader(device,6)}),forwardShaderNames[7],function(device){return loadForwardShader(device,7)}),forwardShaderNames[8],function(device){return loadForwardShader(device,8)}),addBiasShaderName,loadAddBiasShader));function ownKeys$1(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);r&&(o=o.filter(function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable})),t.push.apply(t,o)}return t}function _objectSpread$1(e){for(var r=1;r=r.length?{done:!0}:{done:!1,value:r[_n++]}},e:function e(r){throw r},f:F}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,a=!0,u=!1;return{s:function s(){t=t.call(r)},n:function n(){var r=t.next();return a=r.done,r},e:function e(r){u=!0,o=r},f:function f(){try{a||null==t["return"]||t["return"]()}finally{if(u)throw o}}}}function _unsupportedIterableToArray(r,a){if(r){if("string"==typeof r)return _arrayLikeToArray(r,a);var t={}.toString.call(r).slice(8,-1);return"Object"===t&&r.constructor&&(t=r.constructor.name),"Map"===t||"Set"===t?Array.from(r):"Arguments"===t||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t)?_arrayLikeToArray(r,a):void 0}}function _arrayLikeToArray(r,a){(null==a||a>r.length)&&(a=r.length);for(var e=0,n=Array(a);e1&&_args[1]!==undefined?_args[1]:{};time=_args.length>2&&_args[2]!==undefined?_args[2]:5e3;controller=new AbortController;config=_objectSpread(_objectSpread({},options),{},{signal:controller.signal});timeout=setTimeout(function(){controller.abort()},time);_context.next=7;return fetch(uri,config);case 7:response=_context.sent;clearTimeout(timeout);return _context.abrupt("return",response);case 10:case"end":return _context.stop()}},_callee)}));return _fetchWithTimeout.apply(this,arguments)}function open(_x2,_x3){return _open.apply(this,arguments)}function _open(){_open=_asyncToGenerator(_regeneratorRuntime.mark(function _callee2(path,mode){var error;return _regeneratorRuntime.wrap(function _callee2$(_context2){while(1)switch(_context2.prev=_context2.next){case 0:_context2.prev=0;_context2.next=3;return PvFileIDB.open(path,mode);case 3:return _context2.abrupt("return",_context2.sent);case 6:_context2.prev=6;_context2.t0=_context2["catch"](0);if(_context2.t0.name==="IndexedDBNotSupported"){console.warn("IndexedDB is not supported. Fallback to in-memory storage.")}else if(_context2.t0.name!=="FileNotExists"){console.warn("Unable to access IndexedDB (".concat(_context2.t0.toString(),"). Fallback to in-memory storage."))}if(!(typeof WorkerGlobalScope!=="undefined"&&self instanceof WorkerGlobalScope)){_context2.next=16;break}if(!(_context2.t0.name==="FileNotExists")){_context2.next=12;break}throw _context2.t0;case 12:console.error("In-memory storage cannot be used inside a worker.");error=new Error("Failed to start PvFile: ".concat(_context2.t0.toString()));error.name="PvFileNotSupported";throw error;case 16:return _context2.abrupt("return",PvFileMem.open(path,mode));case 17:case"end":return _context2.stop()}},_callee2,null,[[0,6]])}));return _open.apply(this,arguments)}var moduleOverrides=Object.assign({},Module);var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var readAsync,readBinary;if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(typeof document!="undefined"&&document.currentScript){scriptDirectory=document.currentScript.src}if(_scriptName){scriptDirectory=_scriptName}if(scriptDirectory.startsWith("blob:")){scriptDirectory=""}else{scriptDirectory=scriptDirectory.substr(0,scriptDirectory.replace(/[?#].*/,"").lastIndexOf("/")+1)}{if(ENVIRONMENT_IS_WORKER){readBinary=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=url=>{if(isFileURI(url)){return new Promise((reject,resolve)=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=()=>{if(xhr.status==200||xhr.status==0&&xhr.response){resolve(xhr.response)}reject(xhr.status)};xhr.onerror=reject;xhr.send(null)})}return fetch(url,{credentials:"same-origin"}).then(response=>{if(response.ok){return response.arrayBuffer()}return Promise.reject(new Error(response.status+" : "+response.url))})}}}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.error.bind(console);Object.assign(Module,moduleOverrides);moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];if(ENVIRONMENT_IS_PTHREAD){var wasmPromiseResolve;var wasmPromiseReject;var initializedJS=false;function threadPrintErr(...args){var text=args.join(" ");console.error(text)}if(!Module["printErr"])err=threadPrintErr;function threadAlert(...args){var text=args.join(" ");postMessage({cmd:"alert",text:text,threadId:_pthread_self()})}self.alert=threadAlert;Module["instantiateWasm"]=(info,receiveInstance)=>new Promise((resolve,reject)=>{wasmPromiseResolve=module=>{var instance=new WebAssembly.Instance(module,getWasmImports());receiveInstance(instance);resolve()};wasmPromiseReject=reject});self.onunhandledrejection=e=>{throw e.reason||e};function handleMessage(e){try{var msgData=e["data"];var cmd=msgData["cmd"];if(cmd==="load"){let messageQueue=[];self.onmessage=e=>messageQueue.push(e);self.startWorker=instance=>{postMessage({cmd:"loaded"});for(let msg of messageQueue){handleMessage(msg)}self.onmessage=handleMessage};for(const handler of msgData["handlers"]){if(!Module[handler]||Module[handler].proxy){Module[handler]=(...args)=>{postMessage({cmd:"callHandler",handler:handler,args:args})};if(handler=="print")out=Module[handler];if(handler=="printErr")err=Module[handler]}}wasmMemory=msgData["wasmMemory"];updateMemoryViews();wasmPromiseResolve(msgData["wasmModule"])}else if(cmd==="run"){__emscripten_thread_init(msgData["pthread_ptr"],0,0,1,0,0);__emscripten_thread_mailbox_await(msgData["pthread_ptr"]);establishStackSpace();PThread.receiveObjectTransfer(msgData);PThread.threadInitTLS();if(!initializedJS){initializedJS=true}try{invokeEntryPoint(msgData["start_routine"],msgData["arg"])}catch(ex){if(ex!="unwind"){throw ex}}}else if(cmd==="cancel"){if(_pthread_self()){__emscripten_thread_exit(-1)}}else if(msgData.target==="setimmediate"){}else if(cmd==="checkMailbox"){if(initializedJS){checkMailbox()}}else if(cmd){err(`worker: received unknown command ${cmd}`);err(msgData)}}catch(ex){__emscripten_thread_crashed();throw ex}}self.onmessage=handleMessage}var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var wasmMemory;var wasmModule;var ABORT=false;var EXITSTATUS;var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAP64,HEAPU64,HEAPF64;function updateMemoryViews(){var b=wasmMemory.buffer;Module["HEAP8"]=HEAP8=new Int8Array(b);Module["HEAP16"]=HEAP16=new Int16Array(b);Module["HEAPU8"]=HEAPU8=new Uint8Array(b);Module["HEAPU16"]=HEAPU16=new Uint16Array(b);Module["HEAP32"]=HEAP32=new Int32Array(b);Module["HEAPU32"]=HEAPU32=new Uint32Array(b);Module["HEAPF32"]=HEAPF32=new Float32Array(b);Module["HEAPF64"]=HEAPF64=new Float64Array(b);Module["HEAP64"]=HEAP64=new BigInt64Array(b);Module["HEAPU64"]=HEAPU64=new BigUint64Array(b)}if(!ENVIRONMENT_IS_PTHREAD){if(Module["wasmMemory"]){wasmMemory=Module["wasmMemory"]}else{var INITIAL_MEMORY=Module["INITIAL_MEMORY"]||67108864;wasmMemory=new WebAssembly.Memory({initial:INITIAL_MEMORY/65536,maximum:4294967296/65536,shared:true});if(!(wasmMemory.buffer instanceof SharedArrayBuffer)){err("requested a shared WebAssembly.Memory but the returned buffer is not a SharedArrayBuffer, indicating that while the browser has SharedArrayBuffer it does not have WebAssembly threads support - you may need to set a flag");if(ENVIRONMENT_IS_NODE){err("(on node you may need: --experimental-wasm-threads --experimental-wasm-bulk-memory and/or recent version)")}throw Error("bad memory")}}updateMemoryViews()}var __ATPRERUN__=[];var __ATINIT__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;if(ENVIRONMENT_IS_PTHREAD)return;callRuntimeCallbacks(__ATINIT__)}function postRun(){if(ENVIRONMENT_IS_PTHREAD)return;if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnInit(cb){__ATINIT__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;Module["monitorRunDependencies"]?.(runDependencies)}function removeRunDependency(id){runDependencies--;Module["monitorRunDependencies"]?.(runDependencies);if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}function abort(what){Module["onAbort"]?.(what);what="Aborted("+what+")";err(what);ABORT=true;EXITSTATUS=1;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);readyPromiseReject(e);throw e}var dataURIPrefix="data:application/octet-stream;base64,";var isDataURI=filename=>filename.startsWith(dataURIPrefix);var isFileURI=filename=>filename.startsWith("file://");function findWasmBinary(){var f="pv_eagle_pthread.wasm";if(!isDataURI(f)){return locateFile(f)}return f}var wasmBinaryFile;function getBinarySync(file){if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}function getBinaryPromise(binaryFile){if(!wasmBinary){return readAsync(binaryFile).then(response=>new Uint8Array(response),()=>getBinarySync(binaryFile))}return Promise.resolve().then(()=>getBinarySync(binaryFile))}function instantiateArrayBuffer(binaryFile,imports,receiver){return getBinaryPromise(binaryFile).then(binary=>WebAssembly.instantiate(binary,imports)).then(receiver,reason=>{err(`failed to asynchronously prepare wasm: ${reason}`);abort(reason)})}function instantiateAsync(binary,binaryFile,imports,callback){if(!binary&&typeof WebAssembly.instantiateStreaming=="function"&&!isDataURI(binaryFile)&&!isFileURI(binaryFile)&&typeof fetch=="function"){return fetch(binaryFile,{credentials:"same-origin"}).then(response=>{var result=WebAssembly.instantiateStreaming(response,imports);return result.then(callback,function(reason){err(`wasm streaming compile failed: ${reason}`);err("falling back to ArrayBuffer instantiation");return instantiateArrayBuffer(binaryFile,imports,callback)})})}return instantiateArrayBuffer(binaryFile,imports,callback)}function getWasmImports(){assignWasmImports();return{a:wasmImports}}function createWasm(){var info=getWasmImports();function receiveInstance(instance,module){wasmExports=instance.exports;wasmExports=Asyncify.instrumentWasmExports(wasmExports);wasmExports=applySignatureConversions(wasmExports);registerTLSInit(wasmExports["aa"]);wasmTable=wasmExports["S"];addOnInit(wasmExports["y"]);wasmModule=module;removeRunDependency("wasm-instantiate");return wasmExports}addRunDependency("wasm-instantiate");function receiveInstantiationResult(result){receiveInstance(result["instance"],result["module"])}if(Module["instantiateWasm"]){try{return Module["instantiateWasm"](info,receiveInstance)}catch(e){err(`Module.instantiateWasm callback failed with error: ${e}`);readyPromiseReject(e)}}if(!wasmBinaryFile)wasmBinaryFile=findWasmBinary();instantiateAsync(wasmBinary,wasmBinaryFile,info,receiveInstantiationResult).catch(readyPromiseReject);return{}}function ExitStatus(status){this.name="ExitStatus";this.message=`Program terminated with exit(${status})`;this.status=status}var terminateWorker=worker=>{worker.terminate();worker.onmessage=e=>{}};var killThread=pthread_ptr=>{var worker=PThread.pthreads[pthread_ptr];delete PThread.pthreads[pthread_ptr];terminateWorker(worker);__emscripten_thread_free_data(pthread_ptr);PThread.runningWorkers.splice(PThread.runningWorkers.indexOf(worker),1);worker.pthread_ptr=0};var cancelThread=pthread_ptr=>{var worker=PThread.pthreads[pthread_ptr];worker.postMessage({cmd:"cancel"})};var cleanupThread=pthread_ptr=>{var worker=PThread.pthreads[pthread_ptr];PThread.returnWorkerToPool(worker)};var spawnThread=threadParams=>{var worker=PThread.getNewWorker();if(!worker){return 6}PThread.runningWorkers.push(worker);PThread.pthreads[threadParams.pthread_ptr]=worker;worker.pthread_ptr=threadParams.pthread_ptr;var msg={cmd:"run",start_routine:threadParams.startRoutine,arg:threadParams.arg,pthread_ptr:threadParams.pthread_ptr};worker.postMessage(msg,threadParams.transferList);return 0};var runtimeKeepaliveCounter=0;var keepRuntimeAlive=()=>noExitRuntime||runtimeKeepaliveCounter>0;var stackSave=()=>_emscripten_stack_get_current();var stackRestore=val=>__emscripten_stack_restore(val);var stackAlloc=sz=>__emscripten_stack_alloc(sz);var proxyToMainThread=(funcIndex,emAsmAddr,sync,...callArgs)=>{var serializedNumCallArgs=callArgs.length*2;var sp=stackSave();var args=stackAlloc(serializedNumCallArgs*8);var b=args>>>3;for(var i=0;i>>0]=arg}}var rtn=__emscripten_run_on_main_thread_js(funcIndex,emAsmAddr,serializedNumCallArgs,args,sync);stackRestore(sp);return rtn};function _proc_exit(code){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(0,0,1,code);EXITSTATUS=code;if(!keepRuntimeAlive()){PThread.terminateAllThreads();Module["onExit"]?.(code);ABORT=true}quit_(code,new ExitStatus(code))}var handleException=e=>{if(e instanceof ExitStatus||e=="unwind"){return EXITSTATUS}quit_(1,e)};function exitOnMainThread(returnCode){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(1,0,0,returnCode);_exit(returnCode)}var exitJS=(status,implicit)=>{EXITSTATUS=status;if(ENVIRONMENT_IS_PTHREAD){exitOnMainThread(status);throw"unwind"}_proc_exit(status)};var _exit=exitJS;var PThread={unusedWorkers:[],runningWorkers:[],tlsInitFunctions:[],pthreads:{},init(){if(ENVIRONMENT_IS_PTHREAD){PThread.initWorker()}else{PThread.initMainThread()}},initMainThread(){var pthreadPoolSize=navigator.hardwareConcurrency;while(pthreadPoolSize--){PThread.allocateUnusedWorker()}addOnPreRun(()=>{addRunDependency("loading-workers");PThread.loadWasmModuleToAllWorkers(()=>removeRunDependency("loading-workers"))})},initWorker(){noExitRuntime=false},setExitStatus:status=>EXITSTATUS=status,terminateAllThreads__deps:["$terminateWorker"],terminateAllThreads:()=>{for(var worker of PThread.runningWorkers){terminateWorker(worker)}for(var worker of PThread.unusedWorkers){terminateWorker(worker)}PThread.unusedWorkers=[];PThread.runningWorkers=[];PThread.pthreads=[]},returnWorkerToPool:worker=>{var pthread_ptr=worker.pthread_ptr;delete PThread.pthreads[pthread_ptr];PThread.unusedWorkers.push(worker);PThread.runningWorkers.splice(PThread.runningWorkers.indexOf(worker),1);worker.pthread_ptr=0;__emscripten_thread_free_data(pthread_ptr)},receiveObjectTransfer(data){},threadInitTLS(){PThread.tlsInitFunctions.forEach(f=>f())},loadWasmModuleToWorker:worker=>new Promise(onFinishedLoading=>{worker.onmessage=e=>{var d=e["data"];var cmd=d["cmd"];if(d["targetThread"]&&d["targetThread"]!=_pthread_self()){var targetWorker=PThread.pthreads[d["targetThread"]];if(targetWorker){targetWorker.postMessage(d,d["transferList"])}else{err(`Internal error! Worker sent a message "${cmd}" to target pthread ${d["targetThread"]}, but that thread no longer exists!`)}return}if(cmd==="checkMailbox"){checkMailbox()}else if(cmd==="spawnThread"){spawnThread(d)}else if(cmd==="cleanupThread"){cleanupThread(d["thread"])}else if(cmd==="killThread"){killThread(d["thread"])}else if(cmd==="cancelThread"){cancelThread(d["thread"])}else if(cmd==="loaded"){worker.loaded=true;onFinishedLoading(worker)}else if(cmd==="alert"){alert(`Thread ${d["threadId"]}: ${d["text"]}`)}else if(d.target==="setimmediate"){worker.postMessage(d)}else if(cmd==="callHandler"){Module[d["handler"]](...d["args"])}else if(cmd){err(`worker sent an unknown command ${cmd}`)}};worker.onerror=e=>{var message="worker sent an error!";err(`${message} ${e.filename}:${e.lineno}: ${e.message}`);throw e};var handlers=[];var knownHandlers=["onExit","onAbort","print","printErr"];for(var handler of knownHandlers){if(Module.propertyIsEnumerable(handler)){handlers.push(handler)}}worker.postMessage({cmd:"load",handlers:handlers,wasmMemory:wasmMemory,wasmModule:wasmModule})}),loadWasmModuleToAllWorkers(onMaybeReady){if(ENVIRONMENT_IS_PTHREAD){return onMaybeReady()}let pthreadPoolReady=Promise.all(PThread.unusedWorkers.map(PThread.loadWasmModuleToWorker));pthreadPoolReady.then(onMaybeReady)},allocateUnusedWorker(){var worker;var workerOptions={type:"module",name:"em-pthread"};var pthreadMainJs=_scriptName;if(Module["mainScriptUrlOrBlob"]){pthreadMainJs=Module["mainScriptUrlOrBlob"];if(typeof pthreadMainJs!="string"){pthreadMainJs=URL.createObjectURL(pthreadMainJs)}}worker=new Worker(pthreadMainJs,workerOptions);PThread.unusedWorkers.push(worker)},getNewWorker(){if(PThread.unusedWorkers.length==0){PThread.allocateUnusedWorker();PThread.loadWasmModuleToWorker(PThread.unusedWorkers[0])}return PThread.unusedWorkers.pop()}};var callRuntimeCallbacks=callbacks=>{while(callbacks.length>0){callbacks.shift()(Module)}};var establishStackSpace=()=>{var pthread_ptr=_pthread_self();var stackHigh=GROWABLE_HEAP_U32()[pthread_ptr+52>>>2>>>0];var stackSize=GROWABLE_HEAP_U32()[pthread_ptr+56>>>2>>>0];var stackLow=stackHigh-stackSize;_emscripten_stack_set_limits(stackHigh,stackLow);stackRestore(stackHigh)};var invokeEntryPoint=(ptr,arg)=>{runtimeKeepaliveCounter=0;var result=(a1=>dynCall_ii(ptr,a1))(arg);function finish(result){if(keepRuntimeAlive()){PThread.setExitStatus(result)}else{__emscripten_thread_exit(result)}}finish(result)};var noExitRuntime=Module["noExitRuntime"]||true;var registerTLSInit=tlsInitFunc=>PThread.tlsInitFunctions.push(tlsInitFunc);function pthreadCreateProxied(pthread_ptr,attr,startRoutine,arg){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(2,0,1,pthread_ptr,attr,startRoutine,arg);return ___pthread_create_js(pthread_ptr,attr,startRoutine,arg)}function ___pthread_create_js(pthread_ptr,attr,startRoutine,arg){pthread_ptr>>>=0;attr>>>=0;startRoutine>>>=0;arg>>>=0;if(typeof SharedArrayBuffer=="undefined"){err("Current environment does not support SharedArrayBuffer, pthreads are not available!");return 6}var transferList=[];var error=0;if(ENVIRONMENT_IS_PTHREAD&&(transferList.length===0||error)){return pthreadCreateProxied(pthread_ptr,attr,startRoutine,arg)}if(error)return error;var threadParams={startRoutine:startRoutine,pthread_ptr:pthread_ptr,arg:arg,transferList:transferList};if(ENVIRONMENT_IS_PTHREAD){threadParams.cmd="spawnThread";postMessage(threadParams,transferList);return 0}return spawnThread(threadParams)}function __emscripten_init_main_thread_js(tb){tb>>>=0;__emscripten_thread_init(tb,!ENVIRONMENT_IS_WORKER,1,!ENVIRONMENT_IS_WEB,65536,false);PThread.threadInitTLS()}var maybeExit=()=>{if(!keepRuntimeAlive()){try{if(ENVIRONMENT_IS_PTHREAD)__emscripten_thread_exit(EXITSTATUS);else _exit(EXITSTATUS)}catch(e){handleException(e)}}};var callUserCallback=func=>{if(ABORT){return}try{func();maybeExit()}catch(e){handleException(e)}};function __emscripten_thread_mailbox_await(pthread_ptr){pthread_ptr>>>=0;if(typeof Atomics.waitAsync==="function"){var wait=Atomics.waitAsync(GROWABLE_HEAP_I32(),pthread_ptr>>>2,pthread_ptr);wait.value.then(checkMailbox);var waitingAsync=pthread_ptr+128;Atomics.store(GROWABLE_HEAP_I32(),waitingAsync>>>2,1)}}var checkMailbox=()=>{var pthread_ptr=_pthread_self();if(pthread_ptr){__emscripten_thread_mailbox_await(pthread_ptr);callUserCallback(__emscripten_check_mailbox)}};function __emscripten_notify_mailbox_postmessage(targetThreadId,currThreadId,mainThreadId){targetThreadId>>>=0;currThreadId>>>=0;mainThreadId>>>=0;if(targetThreadId==currThreadId){setTimeout(checkMailbox)}else if(ENVIRONMENT_IS_PTHREAD){postMessage({targetThread:targetThreadId,cmd:"checkMailbox"})}else{var worker=PThread.pthreads[targetThreadId];if(!worker){return}worker.postMessage({cmd:"checkMailbox"})}}var proxiedJSCallArgs=[];function __emscripten_receive_on_main_thread_js(funcIndex,emAsmAddr,callingThread,numCallArgs,args){emAsmAddr>>>=0;callingThread>>>=0;args>>>=0;numCallArgs/=2;proxiedJSCallArgs.length=numCallArgs;var b=args>>>3;for(var i=0;i>>0]}}var func=proxiedFunctionTable[funcIndex];PThread.currentProxiedOperationCallerThread=callingThread;var rtn=func(...proxiedJSCallArgs);PThread.currentProxiedOperationCallerThread=0;return rtn}function __emscripten_thread_cleanup(thread){thread>>>=0;if(!ENVIRONMENT_IS_PTHREAD)cleanupThread(thread);else postMessage({cmd:"cleanupThread",thread:thread})}function __emscripten_thread_set_strongref(thread){thread>>>=0}var warnOnce=text=>{warnOnce.shown||={};if(!warnOnce.shown[text]){warnOnce.shown[text]=1;err(text)}};var _emscripten_check_blocking_allowed=()=>{};var runtimeKeepalivePush=()=>{runtimeKeepaliveCounter+=1};var _emscripten_exit_with_live_runtime=()=>{runtimeKeepalivePush();throw"unwind"};var getHeapMax=()=>4294901760;function _emscripten_get_heap_max(){return getHeapMax()}var _emscripten_get_now;_emscripten_get_now=()=>performance.timeOrigin+performance.now();var _emscripten_num_logical_cores=()=>navigator["hardwareConcurrency"];var growMemory=size=>{var b=wasmMemory.buffer;var pages=(size-b.byteLength+65535)/65536;try{wasmMemory.grow(pages);updateMemoryViews();return 1}catch(e){}};function _emscripten_resize_heap(requestedSize){requestedSize>>>=0;var oldSize=GROWABLE_HEAP_U8().length;if(requestedSize<=oldSize){return false}var maxHeapSize=getHeapMax();if(requestedSize>maxHeapSize){return false}var alignUp=(x,multiple)=>x+(multiple-x%multiple)%multiple;for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignUp(Math.max(requestedSize,overGrownHeapSize),65536));var replacement=growMemory(newSize);if(replacement){return true}}return false}var printCharBuffers=[null,[],[]];var UTF8Decoder=typeof TextDecoder!="undefined"?new TextDecoder:undefined;var UTF8ArrayToString=(heapOrArray,idx,maxBytesToRead)=>{idx>>>=0;var endIdx=idx+maxBytesToRead;var endPtr=idx;while(heapOrArray[endPtr]&&!(endPtr>=endIdx))++endPtr;if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.buffer instanceof SharedArrayBuffer?heapOrArray.slice(idx,endPtr):heapOrArray.subarray(idx,endPtr))}var str="";while(idx>10,56320|ch&1023)}}return str};var printChar=(stream,curr)=>{var buffer=printCharBuffers[stream];if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer,0));buffer.length=0}else{buffer.push(curr)}};var UTF8ToString=(ptr,maxBytesToRead)=>{ptr>>>=0;return ptr?UTF8ArrayToString(GROWABLE_HEAP_U8(),ptr,maxBytesToRead):""};function _fd_write(fd,iov,iovcnt,pnum){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(3,0,1,fd,iov,iovcnt,pnum);iov>>>=0;iovcnt>>>=0;pnum>>>=0;var num=0;for(var i=0;i>>2>>>0];var len=GROWABLE_HEAP_U32()[iov+4>>>2>>>0];iov+=8;for(var j=0;j>>0])}num+=len}GROWABLE_HEAP_U32()[pnum>>>2>>>0]=num;return 0}function _pv_console_log_wasm(index){console.log(arrayBufferToStringAtIndex(Module.HEAPU8,index))}var _pv_file_close_wasm=async function(fileAddress,statusAddress){statusAddress=unsignedAddress(statusAddress);return Asyncify.handleAsync(async()=>{try{const file=await PvFile.getPtr(fileAddress);await file.close();setInt(statusAddress,0)}catch(e){console.error("pvFileCloseWasm",e);setInt(statusAddress,-1)}})};_pv_file_close_wasm.isAsync=true;var _pv_file_open_wasm=async function(fileAddress,pathAddress,modeAddress,statusAddress){pathAddress=unsignedAddress(pathAddress);modeAddress=unsignedAddress(modeAddress);statusAddress=unsignedAddress(statusAddress);return Asyncify.handleAsync(async()=>{const path=arrayBufferToStringAtIndex(Module.HEAPU8,pathAddress);const mode=arrayBufferToStringAtIndex(Module.HEAPU8,modeAddress);try{const file=await open(path,mode);PvFile.setPtr(fileAddress,file);setInt(statusAddress,0)}catch(e){if(e.name!=="FileNotExists"){console.error("pvFileOpenWasm",e)}setInt(statusAddress,-1)}})};_pv_file_open_wasm.isAsync=true;var _pv_file_read_wasm=async function(fileAddress,contentAddress,size,count,numReadAddress){contentAddress=unsignedAddress(contentAddress);numReadAddress=unsignedAddress(numReadAddress);return Asyncify.handleAsync(async()=>{try{const file=PvFile.getPtr(fileAddress);const content=await file.read(size,count);Module.HEAPU8.set(content,contentAddress);setInt(numReadAddress,content.length/size)}catch(e){console.error("pvFileReadWasm",e);setInt(numReadAddress,-1)}})};_pv_file_read_wasm.isAsync=true;var _pv_file_write_wasm=function(fileAddress,contentAddress,size,count,numWriteAddress){contentAddress=unsignedAddress(contentAddress);numWriteAddress=unsignedAddress(numWriteAddress);return Asyncify.handleAsync(async()=>{try{const file=PvFile.getPtr(fileAddress);const content=new Uint8Array(size*count);content.set(Module.HEAPU8.slice(contentAddress,contentAddress+size*count),0);await file.write(content);setInt(numWriteAddress,content.length/size)}catch(e){console.error("pvFileWriteWasm",e);setInt(numWriteAddress,-1)}})};var _pv_https_request_wasm=async function(httpMethodAddress,serverNameAddress,endpointAddress,headerAddress,bodyAddress,timeoutMs,responseAddressAddress,responseSizeAddress,responseCodeAddress){httpMethodAddress=unsignedAddress(httpMethodAddress);serverNameAddress=unsignedAddress(serverNameAddress);endpointAddress=unsignedAddress(endpointAddress);headerAddress=unsignedAddress(headerAddress);bodyAddress=unsignedAddress(bodyAddress);responseAddressAddress=unsignedAddress(responseAddressAddress);responseSizeAddress=unsignedAddress(responseSizeAddress);responseCodeAddress=unsignedAddress(responseCodeAddress);return Asyncify.handleAsync(async()=>{const httpMethod=arrayBufferToStringAtIndex(Module.HEAPU8,httpMethodAddress);const serverName=arrayBufferToStringAtIndex(Module.HEAPU8,serverNameAddress);const endpoint=arrayBufferToStringAtIndex(Module.HEAPU8,endpointAddress);const header=arrayBufferToStringAtIndex(Module.HEAPU8,headerAddress);const body=arrayBufferToStringAtIndex(Module.HEAPU8,bodyAddress);const headerObject=stringHeaderToObject(header);const options={method:httpMethod};if(body.length>0){options.body=body}if(Object.keys(headerObject).length>0){options.headers=headerObject}let response;let responseText;let statusCode;try{response=await fetchWithTimeout("https://"+serverName+endpoint,options,timeoutMs);statusCode=response.status}catch(error){console.error("pvHttpsRequestWasm",`Failed to fetch: ${error}`);return}try{responseText=await response.text()}catch(error){console.error("pvHttpsRequestWasm",`Failed to get response text: ${error}`);return}const responseAddress=Module._malloc((responseText.length+1)*Int8Array.BYTES_PER_ELEMENT);if(responseAddress===0){console.error("pvMallocError","pvHttpsRequestWasm: cannot allocate memory for response");setInt(responseAddressAddress,0);return}setInt(responseSizeAddress,responseText.length+1);setInt(responseAddressAddress,responseAddress);for(let i=0;i{try{return func()}catch(e){abort(e)}};var sigToWasmTypes=sig=>{var typeNames={i:"i32",j:"i64",f:"f32",d:"f64",e:"externref",p:"i32"};var type={parameters:[],results:sig[0]=="v"?[]:[typeNames[sig[0]]]};for(var i=1;i{runtimeKeepaliveCounter-=1};var Asyncify={instrumentWasmImports(imports){var importPattern=/^(pv_https_request_wasm|pv_file_open_wasm|pv_file_close_wasm|pv_file_read_wasm|pv_file_write_wasm|pv_file_remove_wasm|pv_sleep_wasm|pv_xpu_webgpu_device_init_wasm|pv_xpu_webgpu_device_info_wasm|pv_xpu_webgpu_device_mem_copy_from_xpu_wasm|pv_xpu_webgpu_device_wait_wasm|pv_xpu_webgpu_timer_stop_wasm|invoke_.*|__asyncjs__.*)$/;for(let[x,original]of Object.entries(imports)){if(typeof original=="function"){let isAsyncifyImport=original.isAsync||importPattern.test(x)}}},instrumentWasmExports(exports){var ret={};for(let[x,original]of Object.entries(exports)){if(typeof original=="function"){ret[x]=(...args)=>{Asyncify.exportCallStack.push(x);try{return original(...args)}finally{if(!ABORT){var y=Asyncify.exportCallStack.pop();Asyncify.maybeStopUnwind()}}}}else{ret[x]=original}}return ret},State:{Normal:0,Unwinding:1,Rewinding:2,Disabled:3},state:0,StackSize:4096,currData:null,handleSleepReturnValue:0,exportCallStack:[],callStackNameToId:{},callStackIdToName:{},callStackId:0,asyncPromiseHandlers:null,sleepCallbacks:[],getCallStackId(funcName){var id=Asyncify.callStackNameToId[funcName];if(id===undefined){id=Asyncify.callStackId++;Asyncify.callStackNameToId[funcName]=id;Asyncify.callStackIdToName[id]=funcName}return id},maybeStopUnwind(){if(Asyncify.currData&&Asyncify.state===Asyncify.State.Unwinding&&Asyncify.exportCallStack.length===0){Asyncify.state=Asyncify.State.Normal;runtimeKeepalivePush();runAndAbortIfError(_asyncify_stop_unwind);if(typeof Fibers!="undefined"){Fibers.trampoline()}}},whenDone(){return new Promise((resolve,reject)=>{Asyncify.asyncPromiseHandlers={resolve:resolve,reject:reject}})},allocateData(){var ptr=_malloc(12+Asyncify.StackSize);Asyncify.setDataHeader(ptr,ptr+12,Asyncify.StackSize);Asyncify.setDataRewindFunc(ptr);return ptr},setDataHeader(ptr,stack,stackSize){GROWABLE_HEAP_U32()[ptr>>>2>>>0]=stack;GROWABLE_HEAP_U32()[ptr+4>>>2>>>0]=stack+stackSize},setDataRewindFunc(ptr){var bottomOfCallStack=Asyncify.exportCallStack[0];var rewindId=Asyncify.getCallStackId(bottomOfCallStack);GROWABLE_HEAP_I32()[ptr+8>>>2>>>0]=rewindId},getDataRewindFuncName(ptr){var id=GROWABLE_HEAP_I32()[ptr+8>>>2>>>0];var name=Asyncify.callStackIdToName[id];return name},getDataRewindFunc(name){var func=wasmExports[name];return func},doRewind(ptr){var name=Asyncify.getDataRewindFuncName(ptr);var func=Asyncify.getDataRewindFunc(name);runtimeKeepalivePop();return func()},handleSleep(startAsync){if(ABORT)return;if(Asyncify.state===Asyncify.State.Normal){var reachedCallback=false;var reachedAfterCallback=false;startAsync((handleSleepReturnValue=0)=>{if(ABORT)return;Asyncify.handleSleepReturnValue=handleSleepReturnValue;reachedCallback=true;if(!reachedAfterCallback){return}Asyncify.state=Asyncify.State.Rewinding;runAndAbortIfError(()=>_asyncify_start_rewind(Asyncify.currData));if(typeof Browser!="undefined"&&Browser.mainLoop.func){Browser.mainLoop.resume()}var asyncWasmReturnValue,isError=false;try{asyncWasmReturnValue=Asyncify.doRewind(Asyncify.currData)}catch(err){asyncWasmReturnValue=err;isError=true}var handled=false;if(!Asyncify.currData){var asyncPromiseHandlers=Asyncify.asyncPromiseHandlers;if(asyncPromiseHandlers){Asyncify.asyncPromiseHandlers=null;(isError?asyncPromiseHandlers.reject:asyncPromiseHandlers.resolve)(asyncWasmReturnValue);handled=true}}if(isError&&!handled){throw asyncWasmReturnValue}});reachedAfterCallback=true;if(!reachedCallback){Asyncify.state=Asyncify.State.Unwinding;Asyncify.currData=Asyncify.allocateData();if(typeof Browser!="undefined"&&Browser.mainLoop.func){Browser.mainLoop.pause()}runAndAbortIfError(()=>_asyncify_start_unwind(Asyncify.currData))}}else if(Asyncify.state===Asyncify.State.Rewinding){Asyncify.state=Asyncify.State.Normal;runAndAbortIfError(_asyncify_stop_rewind);_free(Asyncify.currData);Asyncify.currData=null;Asyncify.sleepCallbacks.forEach(callUserCallback)}else{abort(`invalid state: ${Asyncify.state}`)}return Asyncify.handleSleepReturnValue},handleAsync(startAsync){return Asyncify.handleSleep(wakeUp=>{startAsync().then(wakeUp)})}};var uleb128Encode=(n,target)=>{if(n<128){target.push(n)}else{target.push(n%128|128,n>>7)}};var generateFuncType=(sig,target)=>{var sigRet=sig.slice(0,1);var sigParam=sig.slice(1);var typeCodes={i:127,p:127,j:126,f:125,d:124,e:111};target.push(96);uleb128Encode(sigParam.length,target);for(var i=0;i{if(typeof WebAssembly.Function=="function"){return new WebAssembly.Function(sigToWasmTypes(sig),func)}var typeSectionBody=[1];generateFuncType(sig,typeSectionBody);var bytes=[0,97,115,109,1,0,0,0,1];uleb128Encode(typeSectionBody.length,bytes);bytes.push(...typeSectionBody);bytes.push(2,7,1,1,101,1,102,0,0,7,5,1,1,102,0,0);var module=new WebAssembly.Module(new Uint8Array(bytes));var instance=new WebAssembly.Instance(module,{e:{f:func}});var wrappedFunc=instance.exports["f"];return wrappedFunc};var wasmTableMirror=[];var wasmTable;var getWasmTableEntry=funcPtr=>{var func=wasmTableMirror[funcPtr];if(!func){if(funcPtr>=wasmTableMirror.length)wasmTableMirror.length=funcPtr+1;wasmTableMirror[funcPtr]=func=wasmTable.get(funcPtr)}return func};var updateTableMap=(offset,count)=>{if(functionsInTableMap){for(var i=offset;i{if(!functionsInTableMap){functionsInTableMap=new WeakMap;updateTableMap(0,wasmTable.length)}return functionsInTableMap.get(func)||0};var freeTableIndexes=[];var getEmptyTableSlot=()=>{if(freeTableIndexes.length){return freeTableIndexes.pop()}try{wasmTable.grow(1)}catch(err){if(!(err instanceof RangeError)){throw err}throw"Unable to grow wasm table. Set ALLOW_TABLE_GROWTH."}return wasmTable.length-1};var setWasmTableEntry=(idx,func)=>{wasmTable.set(idx,func);wasmTableMirror[idx]=wasmTable.get(idx)};var addFunction=(func,sig)=>{var rtn=getFunctionAddress(func);if(rtn){return rtn}var ret=getEmptyTableSlot();try{setWasmTableEntry(ret,func)}catch(err){if(!(err instanceof TypeError)){throw err}var wrapped=convertJsFunctionToWasm(func,sig);setWasmTableEntry(ret,wrapped)}functionsInTableMap.set(func,ret);return ret};var getCFunc=ident=>{var func=Module["_"+ident];return func};var writeArrayToMemory=(array,buffer)=>{GROWABLE_HEAP_I8().set(array,buffer>>>0)};var lengthBytesUTF8=str=>{var len=0;for(var i=0;i=55296&&c<=57343){len+=4;++i}else{len+=3}}return len};var stringToUTF8Array=(str,heap,outIdx,maxBytesToWrite)=>{outIdx>>>=0;if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++>>>0]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++>>>0]=192|u>>6;heap[outIdx++>>>0]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++>>>0]=224|u>>12;heap[outIdx++>>>0]=128|u>>6&63;heap[outIdx++>>>0]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++>>>0]=240|u>>18;heap[outIdx++>>>0]=128|u>>12&63;heap[outIdx++>>>0]=128|u>>6&63;heap[outIdx++>>>0]=128|u&63}}heap[outIdx>>>0]=0;return outIdx-startIdx};var stringToUTF8=(str,outPtr,maxBytesToWrite)=>stringToUTF8Array(str,GROWABLE_HEAP_U8(),outPtr,maxBytesToWrite);var stringToUTF8OnStack=str=>{var size=lengthBytesUTF8(str)+1;var ret=stackAlloc(size);stringToUTF8(str,ret,size);return ret};var ccall=(ident,returnType,argTypes,args,opts)=>{var toC={string:str=>{var ret=0;if(str!==null&&str!==undefined&&str!==0){ret=stringToUTF8OnStack(str)}return ret},array:arr=>{var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string"){return UTF8ToString(ret)}if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i{var numericArgs=!argTypes||argTypes.every(type=>type==="number"||type==="boolean");var numericRet=returnType!=="string";if(numericRet&&numericArgs&&!opts){return getCFunc(ident)}return(...args)=>ccall(ident,returnType,argTypes,args,opts)};Module["cwrap"]=cwrap;PThread.init();xpu_cpu_support();var proxiedFunctionTable=[_proc_exit,exitOnMainThread,pthreadCreateProxied,_fd_write];var wasmImports;function assignWasmImports(){wasmImports={u:___pthread_create_js,h:__emscripten_init_main_thread_js,q:__emscripten_notify_mailbox_postmessage,v:__emscripten_receive_on_main_thread_js,e:__emscripten_thread_cleanup,g:__emscripten_thread_mailbox_await,j:__emscripten_thread_set_strongref,f:_emscripten_check_blocking_allowed,i:_emscripten_exit_with_live_runtime,r:_emscripten_get_heap_max,b:_emscripten_get_now,s:_emscripten_num_logical_cores,p:_emscripten_resize_heap,t:_exit,c:_fd_write,a:wasmMemory,d:_pv_console_log_wasm,n:_pv_file_close_wasm,o:_pv_file_open_wasm,m:_pv_file_read_wasm,l:_pv_file_write_wasm,k:_pv_https_request_wasm,w:_pv_time_wasm,x:_pv_xpu_get_max_workers_wasm}}var wasmExports=createWasm();var ___wasm_call_ctors=()=>(___wasm_call_ctors=wasmExports["y"])();var _pv_eagle_init=Module["_pv_eagle_init"]=(a0,a1,a2,a3,a4,a5)=>(_pv_eagle_init=Module["_pv_eagle_init"]=wasmExports["z"])(a0,a1,a2,a3,a4,a5);var _pv_eagle_delete=Module["_pv_eagle_delete"]=a0=>(_pv_eagle_delete=Module["_pv_eagle_delete"]=wasmExports["A"])(a0);var _free=a0=>(_free=wasmExports["B"])(a0);var _malloc=Module["_malloc"]=a0=>(_malloc=Module["_malloc"]=wasmExports["C"])(a0);var _pv_eagle_process=Module["_pv_eagle_process"]=(a0,a1,a2)=>(_pv_eagle_process=Module["_pv_eagle_process"]=wasmExports["D"])(a0,a1,a2);var _pv_sample_rate=Module["_pv_sample_rate"]=()=>(_pv_sample_rate=Module["_pv_sample_rate"]=wasmExports["E"])();var _pv_eagle_frame_length=Module["_pv_eagle_frame_length"]=()=>(_pv_eagle_frame_length=Module["_pv_eagle_frame_length"]=wasmExports["F"])();var _pv_eagle_reset=Module["_pv_eagle_reset"]=a0=>(_pv_eagle_reset=Module["_pv_eagle_reset"]=wasmExports["G"])(a0);var _pv_eagle_version=Module["_pv_eagle_version"]=()=>(_pv_eagle_version=Module["_pv_eagle_version"]=wasmExports["H"])();var _pv_eagle_profiler_init=Module["_pv_eagle_profiler_init"]=(a0,a1,a2,a3)=>(_pv_eagle_profiler_init=Module["_pv_eagle_profiler_init"]=wasmExports["I"])(a0,a1,a2,a3);var _pv_eagle_profiler_delete=Module["_pv_eagle_profiler_delete"]=a0=>(_pv_eagle_profiler_delete=Module["_pv_eagle_profiler_delete"]=wasmExports["J"])(a0);var _pv_eagle_profiler_enroll=Module["_pv_eagle_profiler_enroll"]=(a0,a1,a2,a3,a4)=>(_pv_eagle_profiler_enroll=Module["_pv_eagle_profiler_enroll"]=wasmExports["K"])(a0,a1,a2,a3,a4);var _pv_eagle_profiler_enroll_min_audio_length_samples=Module["_pv_eagle_profiler_enroll_min_audio_length_samples"]=(a0,a1)=>(_pv_eagle_profiler_enroll_min_audio_length_samples=Module["_pv_eagle_profiler_enroll_min_audio_length_samples"]=wasmExports["L"])(a0,a1);var _pv_eagle_profiler_enroll_feedback_to_string=Module["_pv_eagle_profiler_enroll_feedback_to_string"]=a0=>(_pv_eagle_profiler_enroll_feedback_to_string=Module["_pv_eagle_profiler_enroll_feedback_to_string"]=wasmExports["M"])(a0);var _pv_eagle_profiler_export_size=Module["_pv_eagle_profiler_export_size"]=(a0,a1)=>(_pv_eagle_profiler_export_size=Module["_pv_eagle_profiler_export_size"]=wasmExports["N"])(a0,a1);var _pv_eagle_profiler_export=Module["_pv_eagle_profiler_export"]=(a0,a1)=>(_pv_eagle_profiler_export=Module["_pv_eagle_profiler_export"]=wasmExports["O"])(a0,a1);var _pv_eagle_profiler_reset=Module["_pv_eagle_profiler_reset"]=a0=>(_pv_eagle_profiler_reset=Module["_pv_eagle_profiler_reset"]=wasmExports["P"])(a0);var _pv_eagle_list_hardware_devices=Module["_pv_eagle_list_hardware_devices"]=(a0,a1)=>(_pv_eagle_list_hardware_devices=Module["_pv_eagle_list_hardware_devices"]=wasmExports["Q"])(a0,a1);var _pv_eagle_free_hardware_devices=Module["_pv_eagle_free_hardware_devices"]=(a0,a1)=>(_pv_eagle_free_hardware_devices=Module["_pv_eagle_free_hardware_devices"]=wasmExports["R"])(a0,a1);var _pv_log_enable=Module["_pv_log_enable"]=()=>(_pv_log_enable=Module["_pv_log_enable"]=wasmExports["T"])();var _pv_log_disable=Module["_pv_log_disable"]=()=>(_pv_log_disable=Module["_pv_log_disable"]=wasmExports["U"])();var _aligned_alloc=Module["_aligned_alloc"]=(a0,a1)=>(_aligned_alloc=Module["_aligned_alloc"]=wasmExports["V"])(a0,a1);var _pv_get_sdk=Module["_pv_get_sdk"]=()=>(_pv_get_sdk=Module["_pv_get_sdk"]=wasmExports["W"])();var _pv_status_to_string=Module["_pv_status_to_string"]=a0=>(_pv_status_to_string=Module["_pv_status_to_string"]=wasmExports["X"])(a0);var _pv_set_sdk=Module["_pv_set_sdk"]=a0=>(_pv_set_sdk=Module["_pv_set_sdk"]=wasmExports["Y"])(a0);var _pv_free=Module["_pv_free"]=a0=>(_pv_free=Module["_pv_free"]=wasmExports["Z"])(a0);var _pv_get_error_stack=Module["_pv_get_error_stack"]=(a0,a1)=>(_pv_get_error_stack=Module["_pv_get_error_stack"]=wasmExports["_"])(a0,a1);var _pv_free_error_stack=Module["_pv_free_error_stack"]=a0=>(_pv_free_error_stack=Module["_pv_free_error_stack"]=wasmExports["$"])(a0);var __emscripten_tls_init=()=>(__emscripten_tls_init=wasmExports["aa"])();var _pthread_self=()=>(_pthread_self=wasmExports["ba"])();var __emscripten_memcpy_bulkmem=Module["__emscripten_memcpy_bulkmem"]=(a0,a1,a2)=>(__emscripten_memcpy_bulkmem=Module["__emscripten_memcpy_bulkmem"]=wasmExports["ca"])(a0,a1,a2);var __emscripten_memset_bulkmem=Module["__emscripten_memset_bulkmem"]=(a0,a1,a2)=>(__emscripten_memset_bulkmem=Module["__emscripten_memset_bulkmem"]=wasmExports["da"])(a0,a1,a2);var ___get_tp=Module["___get_tp"]=()=>(___get_tp=Module["___get_tp"]=wasmExports["ea"])();var __emscripten_thread_supports_atomics_wait=Module["__emscripten_thread_supports_atomics_wait"]=()=>(__emscripten_thread_supports_atomics_wait=Module["__emscripten_thread_supports_atomics_wait"]=wasmExports["fa"])();var __emscripten_thread_init=(a0,a1,a2,a3,a4,a5)=>(__emscripten_thread_init=wasmExports["ga"])(a0,a1,a2,a3,a4,a5);var ___set_thread_state=Module["___set_thread_state"]=(a0,a1,a2,a3)=>(___set_thread_state=Module["___set_thread_state"]=wasmExports["ha"])(a0,a1,a2,a3);var _emscripten_is_main_runtime_thread=Module["_emscripten_is_main_runtime_thread"]=()=>(_emscripten_is_main_runtime_thread=Module["_emscripten_is_main_runtime_thread"]=wasmExports["ia"])();var _emscripten_is_main_browser_thread=Module["_emscripten_is_main_browser_thread"]=()=>(_emscripten_is_main_browser_thread=Module["_emscripten_is_main_browser_thread"]=wasmExports["ja"])();var __emscripten_thread_crashed=()=>(__emscripten_thread_crashed=wasmExports["ka"])();var _emscripten_stack_get_base=Module["_emscripten_stack_get_base"]=()=>(_emscripten_stack_get_base=Module["_emscripten_stack_get_base"]=wasmExports["la"])();var _emscripten_stack_get_end=Module["_emscripten_stack_get_end"]=()=>(_emscripten_stack_get_end=Module["_emscripten_stack_get_end"]=wasmExports["ma"])();var __emscripten_run_on_main_thread_js=(a0,a1,a2,a3,a4)=>(__emscripten_run_on_main_thread_js=wasmExports["na"])(a0,a1,a2,a3,a4);var __emscripten_thread_free_data=a0=>(__emscripten_thread_free_data=wasmExports["oa"])(a0);var __emscripten_thread_exit=a0=>(__emscripten_thread_exit=wasmExports["pa"])(a0);var __emscripten_check_mailbox=()=>(__emscripten_check_mailbox=wasmExports["qa"])();var _emscripten_stack_init=Module["_emscripten_stack_init"]=()=>(_emscripten_stack_init=Module["_emscripten_stack_init"]=wasmExports["ra"])();var _emscripten_stack_set_limits=(a0,a1)=>(_emscripten_stack_set_limits=wasmExports["sa"])(a0,a1);var _emscripten_stack_get_free=Module["_emscripten_stack_get_free"]=()=>(_emscripten_stack_get_free=Module["_emscripten_stack_get_free"]=wasmExports["ta"])();var __emscripten_wasm_worker_initialize=Module["__emscripten_wasm_worker_initialize"]=(a0,a1)=>(__emscripten_wasm_worker_initialize=Module["__emscripten_wasm_worker_initialize"]=wasmExports["ua"])(a0,a1);var __emscripten_stack_restore=a0=>(__emscripten_stack_restore=wasmExports["va"])(a0);var __emscripten_stack_alloc=a0=>(__emscripten_stack_alloc=wasmExports["wa"])(a0);var _emscripten_stack_get_current=()=>(_emscripten_stack_get_current=wasmExports["xa"])();var dynCall_ii=Module["dynCall_ii"]=(a0,a1)=>(dynCall_ii=Module["dynCall_ii"]=wasmExports["ya"])(a0,a1);var _asyncify_start_unwind=a0=>(_asyncify_start_unwind=wasmExports["za"])(a0);var _asyncify_stop_unwind=()=>(_asyncify_stop_unwind=wasmExports["Aa"])();var _asyncify_start_rewind=a0=>(_asyncify_start_rewind=wasmExports["Ba"])(a0);var _asyncify_stop_rewind=()=>(_asyncify_stop_rewind=wasmExports["Ca"])();function applySignatureConversions(wasmExports){wasmExports=Object.assign({},wasmExports);var makeWrapper_pp=f=>a0=>f(a0)>>>0;var makeWrapper_p=f=>()=>f()>>>0;wasmExports["C"]=makeWrapper_pp(wasmExports["C"]);wasmExports["ba"]=makeWrapper_p(wasmExports["ba"]);wasmExports["emscripten_main_runtime_thread_id"]=makeWrapper_p(wasmExports["emscripten_main_runtime_thread_id"]);wasmExports["la"]=makeWrapper_p(wasmExports["la"]);wasmExports["ma"]=makeWrapper_p(wasmExports["ma"]);wasmExports["wa"]=makeWrapper_pp(wasmExports["wa"]);wasmExports["xa"]=makeWrapper_p(wasmExports["xa"]);return wasmExports}Module["addFunction"]=addFunction;var calledRun;dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function run(){if(runDependencies>0){return}if(ENVIRONMENT_IS_PTHREAD){readyPromiseResolve(Module);initRuntime();startWorker(Module);return}preRun();if(runDependencies>0){return}function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();readyPromiseResolve(Module);Module["onRuntimeInitialized"]?.();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("")},1);doRun()},1)}else{doRun()}}if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}run();moduleRtn=readyPromise; +function GROWABLE_HEAP_I8(){if(wasmMemory.buffer!=HEAP8.buffer){updateMemoryViews()}return HEAP8}function GROWABLE_HEAP_U8(){if(wasmMemory.buffer!=HEAP8.buffer){updateMemoryViews()}return HEAPU8}function GROWABLE_HEAP_I32(){if(wasmMemory.buffer!=HEAP8.buffer){updateMemoryViews()}return HEAP32}function GROWABLE_HEAP_U32(){if(wasmMemory.buffer!=HEAP8.buffer){updateMemoryViews()}return HEAPU32}function GROWABLE_HEAP_F64(){if(wasmMemory.buffer!=HEAP8.buffer){updateMemoryViews()}return HEAPF64}var Module=moduleArg;var readyPromiseResolve,readyPromiseReject;var readyPromise=new Promise((resolve,reject)=>{readyPromiseResolve=resolve;readyPromiseReject=reject});var ENVIRONMENT_IS_WEB=typeof window=="object";var ENVIRONMENT_IS_WORKER=typeof importScripts=="function";var ENVIRONMENT_IS_NODE=typeof process=="object"&&typeof process.versions=="object"&&typeof process.versions.node=="string";var ENVIRONMENT_IS_PTHREAD=ENVIRONMENT_IS_WORKER&&self.name=="em-pthread";function _typeof$2(o){null;return _typeof$2="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(o){return typeof o}:function(o){return o&&"function"==typeof Symbol&&o.constructor===Symbol&&o!==Symbol.prototype?"symbol":typeof o},_typeof$2(o)}function toPrimitive(t,r){if("object"!=_typeof$2(t)||!t)return t;var e=t[Symbol.toPrimitive];if(void 0!==e){var i=e.call(t,r||"default");if("object"!=_typeof$2(i))return i;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===r?String:Number)(t)}function toPropertyKey(t){var i=toPrimitive(t,"string");return"symbol"==_typeof$2(i)?i:i+""}function _defineProperty(e,r,t){return(r=toPropertyKey(r))in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function asyncGeneratorStep(n,t,e,r,o,a,c){try{var i=n[a](c),u=i.value}catch(n){return void e(n)}i.done?t(u):Promise.resolve(u).then(r,o)}function _asyncToGenerator(n){return function(){var t=this,e=arguments;return new Promise(function(r,o){var a=n.apply(t,e);function _next(n){asyncGeneratorStep(a,r,o,_next,_throw,"next",n)}function _throw(n){asyncGeneratorStep(a,r,o,_next,_throw,"throw",n)}_next(void 0)})}}function getDefaultExportFromCjs(x){return x&&x.__esModule&&Object.prototype.hasOwnProperty.call(x,"default")?x["default"]:x}var regeneratorRuntime$3={exports:{}};var _typeof$1={exports:{}};var _typeof_1=_typeof$1.exports;(function(module){function _typeof(o){null;return module.exports=_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(o){return typeof o}:function(o){return o&&"function"==typeof Symbol&&o.constructor===Symbol&&o!==Symbol.prototype?"symbol":typeof o},module.exports.__esModule=true,module.exports["default"]=module.exports,_typeof(o)}module.exports=_typeof,module.exports.__esModule=true,module.exports["default"]=module.exports})(_typeof$1);var _typeofExports=_typeof$1.exports;var _typeof=getDefaultExportFromCjs(_typeofExports);var regeneratorRuntime$1=regeneratorRuntime$3.exports;(function(module){var _typeof=_typeofExports["default"];function _regeneratorRuntime(){"use strict";module.exports=_regeneratorRuntime=function _regeneratorRuntime(){return e},module.exports.__esModule=true,module.exports["default"]=module.exports;var t,e={},r=Object.prototype,n=r.hasOwnProperty,o=Object.defineProperty||function(t,e,r){t[e]=r.value},i="function"==typeof Symbol?Symbol:{},a=i.iterator||"@@iterator",c=i.asyncIterator||"@@asyncIterator",u=i.toStringTag||"@@toStringTag";function define(t,e,r){return Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}),t[e]}try{define({},"")}catch(t){define=function define(t,e,r){return t[e]=r}}function wrap(t,e,r,n){var i=e&&e.prototype instanceof Generator?e:Generator,a=Object.create(i.prototype),c=new Context(n||[]);return o(a,"_invoke",{value:makeInvokeMethod(t,r,c)}),a}function tryCatch(t,e,r){try{return{type:"normal",arg:t.call(e,r)}}catch(t){return{type:"throw",arg:t}}}e.wrap=wrap;var h="suspendedStart",l="suspendedYield",f="executing",s="completed",y={};function Generator(){}function GeneratorFunction(){}function GeneratorFunctionPrototype(){}var p={};define(p,a,function(){return this});var d=Object.getPrototypeOf,v=d&&d(d(values([])));v&&v!==r&&n.call(v,a)&&(p=v);var g=GeneratorFunctionPrototype.prototype=Generator.prototype=Object.create(p);function defineIteratorMethods(t){["next","throw","return"].forEach(function(e){define(t,e,function(t){return this._invoke(e,t)})})}function AsyncIterator(t,e){function invoke(r,o,i,a){var c=tryCatch(t[r],t,o);if("throw"!==c.type){var u=c.arg,h=u.value;return h&&"object"==_typeof(h)&&n.call(h,"__await")?e.resolve(h.__await).then(function(t){invoke("next",t,i,a)},function(t){invoke("throw",t,i,a)}):e.resolve(h).then(function(t){u.value=t,i(u)},function(t){return invoke("throw",t,i,a)})}a(c.arg)}var r;o(this,"_invoke",{value:function value(t,n){function callInvokeWithMethodAndArg(){return new e(function(e,r){invoke(t,n,e,r)})}return r=r?r.then(callInvokeWithMethodAndArg,callInvokeWithMethodAndArg):callInvokeWithMethodAndArg()}})}function makeInvokeMethod(e,r,n){var o=h;return function(i,a){if(o===f)throw Error("Generator is already running");if(o===s){if("throw"===i)throw a;return{value:t,done:!0}}for(n.method=i,n.arg=a;;){var c=n.delegate;if(c){var u=maybeInvokeDelegate(c,n);if(u){if(u===y)continue;return u}}if("next"===n.method)n.sent=n._sent=n.arg;else if("throw"===n.method){if(o===h)throw o=s,n.arg;n.dispatchException(n.arg)}else"return"===n.method&&n.abrupt("return",n.arg);o=f;var p=tryCatch(e,r,n);if("normal"===p.type){if(o=n.done?s:l,p.arg===y)continue;return{value:p.arg,done:n.done}}"throw"===p.type&&(o=s,n.method="throw",n.arg=p.arg)}}}function maybeInvokeDelegate(e,r){var n=r.method,o=e.iterator[n];if(o===t)return r.delegate=null,"throw"===n&&e.iterator["return"]&&(r.method="return",r.arg=t,maybeInvokeDelegate(e,r),"throw"===r.method)||"return"!==n&&(r.method="throw",r.arg=new TypeError("The iterator does not provide a '"+n+"' method")),y;var i=tryCatch(o,e.iterator,r.arg);if("throw"===i.type)return r.method="throw",r.arg=i.arg,r.delegate=null,y;var a=i.arg;return a?a.done?(r[e.resultName]=a.value,r.next=e.nextLoc,"return"!==r.method&&(r.method="next",r.arg=t),r.delegate=null,y):a:(r.method="throw",r.arg=new TypeError("iterator result is not an object"),r.delegate=null,y)}function pushTryEntry(t){var e={tryLoc:t[0]};1 in t&&(e.catchLoc=t[1]),2 in t&&(e.finallyLoc=t[2],e.afterLoc=t[3]),this.tryEntries.push(e)}function resetTryEntry(t){var e=t.completion||{};e.type="normal",delete e.arg,t.completion=e}function Context(t){this.tryEntries=[{tryLoc:"root"}],t.forEach(pushTryEntry,this),this.reset(!0)}function values(e){if(e||""===e){var r=e[a];if(r)return r.call(e);if("function"==typeof e.next)return e;if(!isNaN(e.length)){var o=-1,i=function next(){for(;++o=0;--o){var i=this.tryEntries[o],a=i.completion;if("root"===i.tryLoc)return handle("end");if(i.tryLoc<=this.prev){var c=n.call(i,"catchLoc"),u=n.call(i,"finallyLoc");if(c&&u){if(this.prev=0;--r){var o=this.tryEntries[r];if(o.tryLoc<=this.prev&&n.call(o,"finallyLoc")&&this.prev=0;--e){var r=this.tryEntries[e];if(r.finallyLoc===t)return this.complete(r.completion,r.afterLoc),resetTryEntry(r),y}},catch:function _catch(t){for(var e=this.tryEntries.length-1;e>=0;--e){var r=this.tryEntries[e];if(r.tryLoc===t){var n=r.completion;if("throw"===n.type){var o=n.arg;resetTryEntry(r)}return o}}throw Error("illegal catch attempt")},delegateYield:function delegateYield(e,r,n){return this.delegate={iterator:values(e),resultName:r,nextLoc:n},"next"===this.method&&(this.arg=t),y}},e}module.exports=_regeneratorRuntime,module.exports.__esModule=true,module.exports["default"]=module.exports})(regeneratorRuntime$3);var regeneratorRuntimeExports=regeneratorRuntime$3.exports;var regeneratorRuntime$2=getDefaultExportFromCjs(regeneratorRuntimeExports);var runtime=regeneratorRuntimeExports();var regenerator=runtime;try{regeneratorRuntime=runtime}catch(accidentalStrictMode){if(typeof globalThis==="object"){globalThis.regeneratorRuntime=runtime}else{Function("r","regeneratorRuntime = r")(runtime)}}var _regeneratorRuntime=getDefaultExportFromCjs(regenerator);const BROWSER_ALIASES_MAP={"Amazon Silk":"amazon_silk","Android Browser":"android",Bada:"bada",BlackBerry:"blackberry",Chrome:"chrome",Chromium:"chromium",Electron:"electron",Epiphany:"epiphany",Firefox:"firefox",Focus:"focus",Generic:"generic","Google Search":"google_search",Googlebot:"googlebot","Internet Explorer":"ie","K-Meleon":"k_meleon",Maxthon:"maxthon","Microsoft Edge":"edge","MZ Browser":"mz","NAVER Whale Browser":"naver",Opera:"opera","Opera Coast":"opera_coast",PhantomJS:"phantomjs",Puffin:"puffin",QupZilla:"qupzilla",QQ:"qq",QQLite:"qqlite",Safari:"safari",Sailfish:"sailfish","Samsung Internet for Android":"samsung_internet",SeaMonkey:"seamonkey",Sleipnir:"sleipnir",Swing:"swing",Tizen:"tizen","UC Browser":"uc",Vivaldi:"vivaldi","WebOS Browser":"webos",WeChat:"wechat","Yandex Browser":"yandex",Roku:"roku"};const BROWSER_MAP={amazon_silk:"Amazon Silk",android:"Android Browser",bada:"Bada",blackberry:"BlackBerry",chrome:"Chrome",chromium:"Chromium",electron:"Electron",epiphany:"Epiphany",firefox:"Firefox",focus:"Focus",generic:"Generic",googlebot:"Googlebot",google_search:"Google Search",ie:"Internet Explorer",k_meleon:"K-Meleon",maxthon:"Maxthon",edge:"Microsoft Edge",mz:"MZ Browser",naver:"NAVER Whale Browser",opera:"Opera",opera_coast:"Opera Coast",phantomjs:"PhantomJS",puffin:"Puffin",qupzilla:"QupZilla",qq:"QQ Browser",qqlite:"QQ Browser Lite",safari:"Safari",sailfish:"Sailfish",samsung_internet:"Samsung Internet for Android",seamonkey:"SeaMonkey",sleipnir:"Sleipnir",swing:"Swing",tizen:"Tizen",uc:"UC Browser",vivaldi:"Vivaldi",webos:"WebOS Browser",wechat:"WeChat",yandex:"Yandex Browser"};const PLATFORMS_MAP={tablet:"tablet",mobile:"mobile",desktop:"desktop",tv:"tv"};const OS_MAP={WindowsPhone:"Windows Phone",Windows:"Windows",MacOS:"macOS",iOS:"iOS",Android:"Android",WebOS:"WebOS",BlackBerry:"BlackBerry",Bada:"Bada",Tizen:"Tizen",Linux:"Linux",ChromeOS:"Chrome OS",PlayStation4:"PlayStation 4",Roku:"Roku"};const ENGINE_MAP={EdgeHTML:"EdgeHTML",Blink:"Blink",Trident:"Trident",Presto:"Presto",Gecko:"Gecko",WebKit:"WebKit"};class Utils{static getFirstMatch(regexp,ua){const match=ua.match(regexp);return match&&match.length>0&&match[1]||""}static getSecondMatch(regexp,ua){const match=ua.match(regexp);return match&&match.length>1&&match[2]||""}static matchAndReturnConst(regexp,ua,_const){if(regexp.test(ua)){return _const}return void 0}static getWindowsVersionName(version){switch(version){case"NT":return"NT";case"XP":return"XP";case"NT 5.0":return"2000";case"NT 5.1":return"XP";case"NT 5.2":return"2003";case"NT 6.0":return"Vista";case"NT 6.1":return"7";case"NT 6.2":return"8";case"NT 6.3":return"8.1";case"NT 10.0":return"10";default:return undefined}}static getMacOSVersionName(version){const v=version.split(".").splice(0,2).map(s=>parseInt(s,10)||0);v.push(0);if(v[0]!==10)return undefined;switch(v[1]){case 5:return"Leopard";case 6:return"Snow Leopard";case 7:return"Lion";case 8:return"Mountain Lion";case 9:return"Mavericks";case 10:return"Yosemite";case 11:return"El Capitan";case 12:return"Sierra";case 13:return"High Sierra";case 14:return"Mojave";case 15:return"Catalina";default:return undefined}}static getAndroidVersionName(version){const v=version.split(".").splice(0,2).map(s=>parseInt(s,10)||0);v.push(0);if(v[0]===1&&v[1]<5)return undefined;if(v[0]===1&&v[1]<6)return"Cupcake";if(v[0]===1&&v[1]>=6)return"Donut";if(v[0]===2&&v[1]<2)return"Eclair";if(v[0]===2&&v[1]===2)return"Froyo";if(v[0]===2&&v[1]>2)return"Gingerbread";if(v[0]===3)return"Honeycomb";if(v[0]===4&&v[1]<1)return"Ice Cream Sandwich";if(v[0]===4&&v[1]<4)return"Jelly Bean";if(v[0]===4&&v[1]>=4)return"KitKat";if(v[0]===5)return"Lollipop";if(v[0]===6)return"Marshmallow";if(v[0]===7)return"Nougat";if(v[0]===8)return"Oreo";if(v[0]===9)return"Pie";return undefined}static getVersionPrecision(version){return version.split(".").length}static compareVersions(versionA,versionB,isLoose=false){const versionAPrecision=Utils.getVersionPrecision(versionA);const versionBPrecision=Utils.getVersionPrecision(versionB);let precision=Math.max(versionAPrecision,versionBPrecision);let lastPrecision=0;const chunks=Utils.map([versionA,versionB],version=>{const delta=precision-Utils.getVersionPrecision(version);const _version=version+new Array(delta+1).join(".0");return Utils.map(_version.split("."),chunk=>new Array(20-chunk.length).join("0")+chunk).reverse()});if(isLoose){lastPrecision=precision-Math.min(versionAPrecision,versionBPrecision)}precision-=1;while(precision>=lastPrecision){if(chunks[0][precision]>chunks[1][precision]){return 1}if(chunks[0][precision]===chunks[1][precision]){if(precision===lastPrecision){return 0}precision-=1}else if(chunks[0][precision]{result[key]=assigner[key]})}}return obj}static getBrowserAlias(browserName){return BROWSER_ALIASES_MAP[browserName]}static getBrowserTypeByAlias(browserAlias){return BROWSER_MAP[browserAlias]||""}}const commonVersionIdentifier=/version\/(\d+(\.?_?\d+)+)/i;const browsersList=[{test:[/googlebot/i],describe(ua){const browser={name:"Googlebot"};const version=Utils.getFirstMatch(/googlebot\/(\d+(\.\d+))/i,ua)||Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/opera/i],describe(ua){const browser={name:"Opera"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua)||Utils.getFirstMatch(/(?:opera)[\s/](\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/opr\/|opios/i],describe(ua){const browser={name:"Opera"};const version=Utils.getFirstMatch(/(?:opr|opios)[\s/](\S+)/i,ua)||Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/SamsungBrowser/i],describe(ua){const browser={name:"Samsung Internet for Android"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua)||Utils.getFirstMatch(/(?:SamsungBrowser)[\s/](\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/Whale/i],describe(ua){const browser={name:"NAVER Whale Browser"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua)||Utils.getFirstMatch(/(?:whale)[\s/](\d+(?:\.\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/MZBrowser/i],describe(ua){const browser={name:"MZ Browser"};const version=Utils.getFirstMatch(/(?:MZBrowser)[\s/](\d+(?:\.\d+)+)/i,ua)||Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/focus/i],describe(ua){const browser={name:"Focus"};const version=Utils.getFirstMatch(/(?:focus)[\s/](\d+(?:\.\d+)+)/i,ua)||Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/swing/i],describe(ua){const browser={name:"Swing"};const version=Utils.getFirstMatch(/(?:swing)[\s/](\d+(?:\.\d+)+)/i,ua)||Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/coast/i],describe(ua){const browser={name:"Opera Coast"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua)||Utils.getFirstMatch(/(?:coast)[\s/](\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/opt\/\d+(?:.?_?\d+)+/i],describe(ua){const browser={name:"Opera Touch"};const version=Utils.getFirstMatch(/(?:opt)[\s/](\d+(\.?_?\d+)+)/i,ua)||Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/yabrowser/i],describe(ua){const browser={name:"Yandex Browser"};const version=Utils.getFirstMatch(/(?:yabrowser)[\s/](\d+(\.?_?\d+)+)/i,ua)||Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/ucbrowser/i],describe(ua){const browser={name:"UC Browser"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua)||Utils.getFirstMatch(/(?:ucbrowser)[\s/](\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/Maxthon|mxios/i],describe(ua){const browser={name:"Maxthon"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua)||Utils.getFirstMatch(/(?:Maxthon|mxios)[\s/](\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/epiphany/i],describe(ua){const browser={name:"Epiphany"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua)||Utils.getFirstMatch(/(?:epiphany)[\s/](\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/puffin/i],describe(ua){const browser={name:"Puffin"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua)||Utils.getFirstMatch(/(?:puffin)[\s/](\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/sleipnir/i],describe(ua){const browser={name:"Sleipnir"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua)||Utils.getFirstMatch(/(?:sleipnir)[\s/](\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/k-meleon/i],describe(ua){const browser={name:"K-Meleon"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua)||Utils.getFirstMatch(/(?:k-meleon)[\s/](\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/micromessenger/i],describe(ua){const browser={name:"WeChat"};const version=Utils.getFirstMatch(/(?:micromessenger)[\s/](\d+(\.?_?\d+)+)/i,ua)||Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/qqbrowser/i],describe(ua){const browser={name:/qqbrowserlite/i.test(ua)?"QQ Browser Lite":"QQ Browser"};const version=Utils.getFirstMatch(/(?:qqbrowserlite|qqbrowser)[/](\d+(\.?_?\d+)+)/i,ua)||Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/msie|trident/i],describe(ua){const browser={name:"Internet Explorer"};const version=Utils.getFirstMatch(/(?:msie |rv:)(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/\sedg\//i],describe(ua){const browser={name:"Microsoft Edge"};const version=Utils.getFirstMatch(/\sedg\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/edg([ea]|ios)/i],describe(ua){const browser={name:"Microsoft Edge"};const version=Utils.getSecondMatch(/edg([ea]|ios)\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/vivaldi/i],describe(ua){const browser={name:"Vivaldi"};const version=Utils.getFirstMatch(/vivaldi\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/seamonkey/i],describe(ua){const browser={name:"SeaMonkey"};const version=Utils.getFirstMatch(/seamonkey\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/sailfish/i],describe(ua){const browser={name:"Sailfish"};const version=Utils.getFirstMatch(/sailfish\s?browser\/(\d+(\.\d+)?)/i,ua);if(version){browser.version=version}return browser}},{test:[/silk/i],describe(ua){const browser={name:"Amazon Silk"};const version=Utils.getFirstMatch(/silk\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/phantom/i],describe(ua){const browser={name:"PhantomJS"};const version=Utils.getFirstMatch(/phantomjs\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/slimerjs/i],describe(ua){const browser={name:"SlimerJS"};const version=Utils.getFirstMatch(/slimerjs\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/blackberry|\bbb\d+/i,/rim\stablet/i],describe(ua){const browser={name:"BlackBerry"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua)||Utils.getFirstMatch(/blackberry[\d]+\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/(web|hpw)[o0]s/i],describe(ua){const browser={name:"WebOS Browser"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua)||Utils.getFirstMatch(/w(?:eb)?[o0]sbrowser\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/bada/i],describe(ua){const browser={name:"Bada"};const version=Utils.getFirstMatch(/dolfin\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/tizen/i],describe(ua){const browser={name:"Tizen"};const version=Utils.getFirstMatch(/(?:tizen\s?)?browser\/(\d+(\.?_?\d+)+)/i,ua)||Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/qupzilla/i],describe(ua){const browser={name:"QupZilla"};const version=Utils.getFirstMatch(/(?:qupzilla)[\s/](\d+(\.?_?\d+)+)/i,ua)||Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/firefox|iceweasel|fxios/i],describe(ua){const browser={name:"Firefox"};const version=Utils.getFirstMatch(/(?:firefox|iceweasel|fxios)[\s/](\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/electron/i],describe(ua){const browser={name:"Electron"};const version=Utils.getFirstMatch(/(?:electron)\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/MiuiBrowser/i],describe(ua){const browser={name:"Miui"};const version=Utils.getFirstMatch(/(?:MiuiBrowser)[\s/](\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/chromium/i],describe(ua){const browser={name:"Chromium"};const version=Utils.getFirstMatch(/(?:chromium)[\s/](\d+(\.?_?\d+)+)/i,ua)||Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/chrome|crios|crmo/i],describe(ua){const browser={name:"Chrome"};const version=Utils.getFirstMatch(/(?:chrome|crios|crmo)\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/GSA/i],describe(ua){const browser={name:"Google Search"};const version=Utils.getFirstMatch(/(?:GSA)\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test(parser){const notLikeAndroid=!parser.test(/like android/i);const butAndroid=parser.test(/android/i);return notLikeAndroid&&butAndroid},describe(ua){const browser={name:"Android Browser"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/playstation 4/i],describe(ua){const browser={name:"PlayStation 4"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/safari|applewebkit/i],describe(ua){const browser={name:"Safari"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/.*/i],describe(ua){const regexpWithoutDeviceSpec=/^(.*)\/(.*) /;const regexpWithDeviceSpec=/^(.*)\/(.*)[ \t]\((.*)/;const hasDeviceSpec=ua.search("\\(")!==-1;const regexp=hasDeviceSpec?regexpWithDeviceSpec:regexpWithoutDeviceSpec;return{name:Utils.getFirstMatch(regexp,ua),version:Utils.getSecondMatch(regexp,ua)}}}];var osParsersList=[{test:[/Roku\/DVP/],describe(ua){const version=Utils.getFirstMatch(/Roku\/DVP-(\d+\.\d+)/i,ua);return{name:OS_MAP.Roku,version:version}}},{test:[/windows phone/i],describe(ua){const version=Utils.getFirstMatch(/windows phone (?:os)?\s?(\d+(\.\d+)*)/i,ua);return{name:OS_MAP.WindowsPhone,version:version}}},{test:[/windows /i],describe(ua){const version=Utils.getFirstMatch(/Windows ((NT|XP)( \d\d?.\d)?)/i,ua);const versionName=Utils.getWindowsVersionName(version);return{name:OS_MAP.Windows,version:version,versionName:versionName}}},{test:[/Macintosh(.*?) FxiOS(.*?)\//],describe(ua){const result={name:OS_MAP.iOS};const version=Utils.getSecondMatch(/(Version\/)(\d[\d.]+)/,ua);if(version){result.version=version}return result}},{test:[/macintosh/i],describe(ua){const version=Utils.getFirstMatch(/mac os x (\d+(\.?_?\d+)+)/i,ua).replace(/[_\s]/g,".");const versionName=Utils.getMacOSVersionName(version);const os={name:OS_MAP.MacOS,version:version};if(versionName){os.versionName=versionName}return os}},{test:[/(ipod|iphone|ipad)/i],describe(ua){const version=Utils.getFirstMatch(/os (\d+([_\s]\d+)*) like mac os x/i,ua).replace(/[_\s]/g,".");return{name:OS_MAP.iOS,version:version}}},{test(parser){const notLikeAndroid=!parser.test(/like android/i);const butAndroid=parser.test(/android/i);return notLikeAndroid&&butAndroid},describe(ua){const version=Utils.getFirstMatch(/android[\s/-](\d+(\.\d+)*)/i,ua);const versionName=Utils.getAndroidVersionName(version);const os={name:OS_MAP.Android,version:version};if(versionName){os.versionName=versionName}return os}},{test:[/(web|hpw)[o0]s/i],describe(ua){const version=Utils.getFirstMatch(/(?:web|hpw)[o0]s\/(\d+(\.\d+)*)/i,ua);const os={name:OS_MAP.WebOS};if(version&&version.length){os.version=version}return os}},{test:[/blackberry|\bbb\d+/i,/rim\stablet/i],describe(ua){const version=Utils.getFirstMatch(/rim\stablet\sos\s(\d+(\.\d+)*)/i,ua)||Utils.getFirstMatch(/blackberry\d+\/(\d+([_\s]\d+)*)/i,ua)||Utils.getFirstMatch(/\bbb(\d+)/i,ua);return{name:OS_MAP.BlackBerry,version:version}}},{test:[/bada/i],describe(ua){const version=Utils.getFirstMatch(/bada\/(\d+(\.\d+)*)/i,ua);return{name:OS_MAP.Bada,version:version}}},{test:[/tizen/i],describe(ua){const version=Utils.getFirstMatch(/tizen[/\s](\d+(\.\d+)*)/i,ua);return{name:OS_MAP.Tizen,version:version}}},{test:[/linux/i],describe(){return{name:OS_MAP.Linux}}},{test:[/CrOS/],describe(){return{name:OS_MAP.ChromeOS}}},{test:[/PlayStation 4/],describe(ua){const version=Utils.getFirstMatch(/PlayStation 4[/\s](\d+(\.\d+)*)/i,ua);return{name:OS_MAP.PlayStation4,version:version}}}];var platformParsersList=[{test:[/googlebot/i],describe(){return{type:"bot",vendor:"Google"}}},{test:[/huawei/i],describe(ua){const model=Utils.getFirstMatch(/(can-l01)/i,ua)&&"Nova";const platform={type:PLATFORMS_MAP.mobile,vendor:"Huawei"};if(model){platform.model=model}return platform}},{test:[/nexus\s*(?:7|8|9|10).*/i],describe(){return{type:PLATFORMS_MAP.tablet,vendor:"Nexus"}}},{test:[/ipad/i],describe(){return{type:PLATFORMS_MAP.tablet,vendor:"Apple",model:"iPad"}}},{test:[/Macintosh(.*?) FxiOS(.*?)\//],describe(){return{type:PLATFORMS_MAP.tablet,vendor:"Apple",model:"iPad"}}},{test:[/kftt build/i],describe(){return{type:PLATFORMS_MAP.tablet,vendor:"Amazon",model:"Kindle Fire HD 7"}}},{test:[/silk/i],describe(){return{type:PLATFORMS_MAP.tablet,vendor:"Amazon"}}},{test:[/tablet(?! pc)/i],describe(){return{type:PLATFORMS_MAP.tablet}}},{test(parser){const iDevice=parser.test(/ipod|iphone/i);const likeIDevice=parser.test(/like (ipod|iphone)/i);return iDevice&&!likeIDevice},describe(ua){const model=Utils.getFirstMatch(/(ipod|iphone)/i,ua);return{type:PLATFORMS_MAP.mobile,vendor:"Apple",model:model}}},{test:[/nexus\s*[0-6].*/i,/galaxy nexus/i],describe(){return{type:PLATFORMS_MAP.mobile,vendor:"Nexus"}}},{test:[/[^-]mobi/i],describe(){return{type:PLATFORMS_MAP.mobile}}},{test(parser){return parser.getBrowserName(true)==="blackberry"},describe(){return{type:PLATFORMS_MAP.mobile,vendor:"BlackBerry"}}},{test(parser){return parser.getBrowserName(true)==="bada"},describe(){return{type:PLATFORMS_MAP.mobile}}},{test(parser){return parser.getBrowserName()==="windows phone"},describe(){return{type:PLATFORMS_MAP.mobile,vendor:"Microsoft"}}},{test(parser){const osMajorVersion=Number(String(parser.getOSVersion()).split(".")[0]);return parser.getOSName(true)==="android"&&osMajorVersion>=3},describe(){return{type:PLATFORMS_MAP.tablet}}},{test(parser){return parser.getOSName(true)==="android"},describe(){return{type:PLATFORMS_MAP.mobile}}},{test(parser){return parser.getOSName(true)==="macos"},describe(){return{type:PLATFORMS_MAP.desktop,vendor:"Apple"}}},{test(parser){return parser.getOSName(true)==="windows"},describe(){return{type:PLATFORMS_MAP.desktop}}},{test(parser){return parser.getOSName(true)==="linux"},describe(){return{type:PLATFORMS_MAP.desktop}}},{test(parser){return parser.getOSName(true)==="playstation 4"},describe(){return{type:PLATFORMS_MAP.tv}}},{test(parser){return parser.getOSName(true)==="roku"},describe(){return{type:PLATFORMS_MAP.tv}}}];var enginesParsersList=[{test(parser){return parser.getBrowserName(true)==="microsoft edge"},describe(ua){const isBlinkBased=/\sedg\//i.test(ua);if(isBlinkBased){return{name:ENGINE_MAP.Blink}}const version=Utils.getFirstMatch(/edge\/(\d+(\.?_?\d+)+)/i,ua);return{name:ENGINE_MAP.EdgeHTML,version:version}}},{test:[/trident/i],describe(ua){const engine={name:ENGINE_MAP.Trident};const version=Utils.getFirstMatch(/trident\/(\d+(\.?_?\d+)+)/i,ua);if(version){engine.version=version}return engine}},{test(parser){return parser.test(/presto/i)},describe(ua){const engine={name:ENGINE_MAP.Presto};const version=Utils.getFirstMatch(/presto\/(\d+(\.?_?\d+)+)/i,ua);if(version){engine.version=version}return engine}},{test(parser){const isGecko=parser.test(/gecko/i);const likeGecko=parser.test(/like gecko/i);return isGecko&&!likeGecko},describe(ua){const engine={name:ENGINE_MAP.Gecko};const version=Utils.getFirstMatch(/gecko\/(\d+(\.?_?\d+)+)/i,ua);if(version){engine.version=version}return engine}},{test:[/(apple)?webkit\/537\.36/i],describe(){return{name:ENGINE_MAP.Blink}}},{test:[/(apple)?webkit/i],describe(ua){const engine={name:ENGINE_MAP.WebKit};const version=Utils.getFirstMatch(/webkit\/(\d+(\.?_?\d+)+)/i,ua);if(version){engine.version=version}return engine}}];class Parser{constructor(UA,skipParsing=false){if(UA===void 0||UA===null||UA===""){throw new Error("UserAgent parameter can't be empty")}this._ua=UA;this.parsedResult={};if(skipParsing!==true){this.parse()}}getUA(){return this._ua}test(regex){return regex.test(this._ua)}parseBrowser(){this.parsedResult.browser={};const browserDescriptor=Utils.find(browsersList,_browser=>{if(typeof _browser.test==="function"){return _browser.test(this)}if(_browser.test instanceof Array){return _browser.test.some(condition=>this.test(condition))}throw new Error("Browser's test function is not valid")});if(browserDescriptor){this.parsedResult.browser=browserDescriptor.describe(this.getUA())}return this.parsedResult.browser}getBrowser(){if(this.parsedResult.browser){return this.parsedResult.browser}return this.parseBrowser()}getBrowserName(toLowerCase){if(toLowerCase){return String(this.getBrowser().name).toLowerCase()||""}return this.getBrowser().name||""}getBrowserVersion(){return this.getBrowser().version}getOS(){if(this.parsedResult.os){return this.parsedResult.os}return this.parseOS()}parseOS(){this.parsedResult.os={};const os=Utils.find(osParsersList,_os=>{if(typeof _os.test==="function"){return _os.test(this)}if(_os.test instanceof Array){return _os.test.some(condition=>this.test(condition))}throw new Error("Browser's test function is not valid")});if(os){this.parsedResult.os=os.describe(this.getUA())}return this.parsedResult.os}getOSName(toLowerCase){const{name:name}=this.getOS();if(toLowerCase){return String(name).toLowerCase()||""}return name||""}getOSVersion(){return this.getOS().version}getPlatform(){if(this.parsedResult.platform){return this.parsedResult.platform}return this.parsePlatform()}getPlatformType(toLowerCase=false){const{type:type}=this.getPlatform();if(toLowerCase){return String(type).toLowerCase()||""}return type||""}parsePlatform(){this.parsedResult.platform={};const platform=Utils.find(platformParsersList,_platform=>{if(typeof _platform.test==="function"){return _platform.test(this)}if(_platform.test instanceof Array){return _platform.test.some(condition=>this.test(condition))}throw new Error("Browser's test function is not valid")});if(platform){this.parsedResult.platform=platform.describe(this.getUA())}return this.parsedResult.platform}getEngine(){if(this.parsedResult.engine){return this.parsedResult.engine}return this.parseEngine()}getEngineName(toLowerCase){if(toLowerCase){return String(this.getEngine().name).toLowerCase()||""}return this.getEngine().name||""}parseEngine(){this.parsedResult.engine={};const engine=Utils.find(enginesParsersList,_engine=>{if(typeof _engine.test==="function"){return _engine.test(this)}if(_engine.test instanceof Array){return _engine.test.some(condition=>this.test(condition))}throw new Error("Browser's test function is not valid")});if(engine){this.parsedResult.engine=engine.describe(this.getUA())}return this.parsedResult.engine}parse(){this.parseBrowser();this.parseOS();this.parsePlatform();this.parseEngine();return this}getResult(){return Utils.assign({},this.parsedResult)}satisfies(checkTree){const platformsAndOSes={};let platformsAndOSCounter=0;const browsers={};let browsersCounter=0;const allDefinitions=Object.keys(checkTree);allDefinitions.forEach(key=>{const currentDefinition=checkTree[key];if(typeof currentDefinition==="string"){browsers[key]=currentDefinition;browsersCounter+=1}else if(typeof currentDefinition==="object"){platformsAndOSes[key]=currentDefinition;platformsAndOSCounter+=1}});if(platformsAndOSCounter>0){const platformsAndOSNames=Object.keys(platformsAndOSes);const OSMatchingDefinition=Utils.find(platformsAndOSNames,name=>this.isOS(name));if(OSMatchingDefinition){const osResult=this.satisfies(platformsAndOSes[OSMatchingDefinition]);if(osResult!==void 0){return osResult}}const platformMatchingDefinition=Utils.find(platformsAndOSNames,name=>this.isPlatform(name));if(platformMatchingDefinition){const platformResult=this.satisfies(platformsAndOSes[platformMatchingDefinition]);if(platformResult!==void 0){return platformResult}}}if(browsersCounter>0){const browserNames=Object.keys(browsers);const matchingDefinition=Utils.find(browserNames,name=>this.isBrowser(name,true));if(matchingDefinition!==void 0){return this.compareVersion(browsers[matchingDefinition])}}return undefined}isBrowser(browserName,includingAlias=false){const defaultBrowserName=this.getBrowserName().toLowerCase();let browserNameLower=browserName.toLowerCase();const alias=Utils.getBrowserTypeByAlias(browserNameLower);if(includingAlias&&alias){browserNameLower=alias.toLowerCase()}return browserNameLower===defaultBrowserName}compareVersion(version){let expectedResults=[0];let comparableVersion=version;let isLoose=false;const currentBrowserVersion=this.getBrowserVersion();if(typeof currentBrowserVersion!=="string"){return void 0}if(version[0]===">"||version[0]==="<"){comparableVersion=version.substr(1);if(version[1]==="="){isLoose=true;comparableVersion=version.substr(2)}else{expectedResults=[]}if(version[0]===">"){expectedResults.push(1)}else{expectedResults.push(-1)}}else if(version[0]==="="){comparableVersion=version.substr(1)}else if(version[0]==="~"){isLoose=true;comparableVersion=version.substr(1)}return expectedResults.indexOf(Utils.compareVersions(currentBrowserVersion,comparableVersion,isLoose))>-1}isOS(osName){return this.getOSName(true)===String(osName).toLowerCase()}isPlatform(platformType){return this.getPlatformType(true)===String(platformType).toLowerCase()}isEngine(engineName){return this.getEngineName(true)===String(engineName).toLowerCase()}is(anything,includingAlias=false){return this.isBrowser(anything,includingAlias)||this.isOS(anything)||this.isPlatform(anything)}some(anythings=[]){return anythings.some(anything=>this.is(anything))}}class Bowser{static getParser(UA,skipParsing=false){if(typeof UA!=="string"){throw new Error("UserAgent should be a string")}return new Parser(UA,skipParsing)}static parse(UA){return new Parser(UA).getResult()}static get BROWSER_MAP(){return BROWSER_MAP}static get ENGINE_MAP(){return ENGINE_MAP}static get OS_MAP(){return OS_MAP}static get PLATFORMS_MAP(){return PLATFORMS_MAP}}function _classCallCheck(a,n){if(!(a instanceof n))throw new TypeError("Cannot call a class as a function")}function _defineProperties(e,r){for(var t=0;t=this._data.length){return undefined}var res=this._data.slice(this._pos,this._pos+bytes);this._pos+=bytes;return res}},{key:"set",value:function set(pos,data){this._pos=pos;this._data=data}},{key:"clear",value:function clear(){this._pos=0;this._data=new Uint8Array}}])}();var PvFileIDB=function(_PvFile){function PvFileIDB(path,meta,db,mode){var _this;_classCallCheck(this,PvFileIDB);_this=_callSuper$1(this,PvFileIDB);_this._pageSize=512*1024;_this._pagePtr=0;_this._pageOffset=0;_this._path=path;_this._meta=meta;_this._db=db;_this._mode=mode;_this._cache=new PvCache;return _this}_inherits(PvFileIDB,_PvFile);return _createClass(PvFileIDB,[{key:"pageSize",get:function get(){return this._pageSize}},{key:"close",value:function(){var _close=_asyncToGenerator(_regeneratorRuntime.mark(function _callee(){return _regeneratorRuntime.wrap(function _callee$(_context){while(1)switch(_context.prev=_context.next){case 0:this._db.close();case 1:case"end":return _context.stop()}},_callee,this)}));function close(){return _close.apply(this,arguments)}return close}()},{key:"read",value:function(){var _read=_asyncToGenerator(_regeneratorRuntime.mark(function _callee2(size,count){var _this2=this;return _regeneratorRuntime.wrap(function _callee2$(_context2){while(1)switch(_context2.prev=_context2.next){case 0:return _context2.abrupt("return",new Promise(function(resolve,reject){if(!_this2.exists()){reject(new Error("'".concat(_this2._path,"' doesn't exist.")));return}if(_this2._isEOF){var err=new Error("EOF");err.name="EndOfFile";reject(err);return}var copied=0;var maxToCopy=Math.min(size*count,_this2._meta.size);var totalElems=maxToCopy-maxToCopy%size;var buffer=new Uint8Array(totalElems);var res=_this2._cache.get(totalElems);if(res){copied+=res.length;_this2._pageOffset+=res.length;if(_this2._pageOffset===_this2._pageSize){_this2._pagePtr+=1;_this2._pageOffset=0}if(totalElems===copied){resolve(res);return}buffer.set(res)}var keyRange=IDBKeyRange.bound("".concat(_this2._path,"-").concat(PvFileIDB.createPage(_this2._pagePtr)),"".concat(_this2._path,"-").concat(PvFileIDB.createPage(_this2._pagePtr+Math.floor(totalElems/_this2._pageSize)+1)));var store=_this2._store;var req=store.openCursor(keyRange);req.onsuccess=function(){var cursor=req.result;if(!cursor||_this2._isEOF){return}var toCopy=Math.min(totalElems-copied,cursor.value.length-_this2._pageOffset);buffer.set(cursor.value.slice(_this2._pageOffset,_this2._pageOffset+toCopy),copied);copied+=toCopy;_this2._pageOffset+=toCopy;if(_this2._pageOffset===_this2._pageSize){_this2._pagePtr+=1;_this2._pageOffset=0}if(copied1&&_args4[1]!==undefined?_args4[1]:1;return _context4.abrupt("return",new Promise(function(){var _ref=_asyncToGenerator(_regeneratorRuntime.mark(function _callee3(resolve,reject){var _store$transaction3;var store,getCurrentPage,last,newContent,newSize,newMeta,pages,i,keyRange,_store$transaction4;return _regeneratorRuntime.wrap(function _callee3$(_context3){while(1)switch(_context3.prev=_context3.next){case 0:if(!(_this3._mode==="readonly")){_context3.next=3;break}reject(new Error("Instance is readonly mode only."));return _context3.abrupt("return");case 3:if(!(typeof version!=="number"&&version<=0)){_context3.next=6;break}reject(new Error("Version should be a positive number"));return _context3.abrupt("return");case 6:store=_this3._store;getCurrentPage=function getCurrentPage(){return new Promise(function(res){var req=store.get("".concat(_this3._path,"-").concat(PvFileIDB.createPage(_this3._pagePtr)));req.onsuccess=function(){if(req.result!==undefined){res(req.result.slice(0,_this3._pageOffset))}else{res(new Uint8Array(0))}}})};_context3.next=10;return getCurrentPage();case 10:last=_context3.sent;newContent=new Uint8Array(last.length+content.length);newContent.set(last);newContent.set(content,last.length);newSize=_this3._pagePtr*_this3._pageSize+newContent.length;newMeta={size:newSize,numPages:Math.ceil(newSize/_this3._pageSize),version:version,pageSize:_this3._pageSize};store.put(newMeta,_this3._path);pages=Math.ceil(newContent.length/_this3._pageSize);for(i=0;i=this._meta.numPages-1&&this._pageOffset>=this._meta.size%this._pageSize}},{key:"_store",get:function get(){return this._db.transaction(PV_FILE_STORE,this._mode).objectStore(PV_FILE_STORE)}}],[{key:"open",value:function open(path,mode){if(!self.indexedDB){var error=new Error("IndexedDB is not supported");error.name="IndexedDBNotSupported";throw error}return new Promise(function(){var _ref3=_asyncToGenerator(_regeneratorRuntime.mark(function _callee7(resolve,reject){var db,req,_error2;return _regeneratorRuntime.wrap(function _callee7$(_context7){while(1)switch(_context7.prev=_context7.next){case 0:_context7.prev=0;_context7.next=3;return getDB();case 3:db=_context7.sent;req=db.transaction(PV_FILE_STORE,"readwrite").objectStore(PV_FILE_STORE).get(path);req.onerror=function(){reject(req.error)};req.onsuccess=function(){var meta=req.result;var dbMode=mode.includes("r")?"readonly":"readwrite";if(meta===undefined&&dbMode==="readonly"){var _error=new Error("'".concat(path,"' doesn't exist."));_error.name="FileNotExists";reject(_error);return}var fileIDB=new PvFileIDB(path,meta,db,dbMode);if(mode.includes("a")){fileIDB.seek(0,2)}resolve(fileIDB)};_context7.next=12;break;case 9:_context7.prev=9;_context7.t0=_context7["catch"](0);if(_context7.t0.name==="InvalidStateError"){_error2=new Error("IndexedDB is not supported");_error2.name="IndexedDBNotSupported";reject(_error2)}else{reject(_context7.t0)}case 12:case"end":return _context7.stop()}},_callee7,null,[[0,9]])}));return function(_x8,_x9){return _ref3.apply(this,arguments)}}())}},{key:"createPage",value:function createPage(page){return("00000"+page).slice(-6)}}])}(PvFile);function _callSuper(t,o,e){return o=_getPrototypeOf(o),_possibleConstructorReturn(t,_isNativeReflectConstruct()?Reflect.construct(o,e||[],_getPrototypeOf(t).constructor):o.apply(t,e))}function _isNativeReflectConstruct(){try{var t=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch(t){}return(_isNativeReflectConstruct=function _isNativeReflectConstruct(){return!!t})()}var PvFileMem=function(_PvFile){function PvFileMem(path,meta,db,mode){var _this;_classCallCheck(this,PvFileMem);_this=_callSuper(this,PvFileMem);_this._pos=0;_this._path=path;_this._meta=meta;_this._mode=mode;return _this}_inherits(PvFileMem,_PvFile);return _createClass(PvFileMem,[{key:"close",value:function close(){return}},{key:"read",value:function read(size,count){if(!this.exists()){throw new Error("'".concat(this._path,"' doesn't exist."))}if(this._isEOF){var err=new Error("EOF");err.name="EndOfFile";throw err}var toCopy=Math.min(size*count,this._file.length-this._pos);var totalElems=toCopy-toCopy%size;var buffer=new Uint8Array(totalElems);buffer.set(this._file.slice(this._pos,this._pos+totalElems),0);this._pos+=totalElems;return buffer}},{key:"write",value:function write(content){var version=arguments.length>1&&arguments[1]!==undefined?arguments[1]:1;var newFile=new Uint8Array(this._pos+content.length);if(this._file!==undefined){newFile.set(this._file.slice(0,this._pos));newFile.set(content,this._pos)}else{newFile.set(content)}this._file=newFile;this._pos+=content.length}},{key:"seek",value:function seek(offset,whence){if(!this.exists()&&this._mode==="readonly"){throw new Error("'".concat(this._path,"' doesn't exist."))}if(!this.exists()){throw new Error("'".concat(this._path,"' doesn't exist."))}if(offset<0){var err=new Error("EOF");err.name="EndOfFile";throw err}var newOffset;if(whence===0){newOffset=Math.min(offset,this._file.length)}else if(whence===1){newOffset=Math.min(this._pos+offset,this._file.length)}else if(whence===2){newOffset=Math.min(this._file.length+offset,this._file.length)}else{throw new Error("Invalid operation: ".concat(whence,"."))}this._pos=newOffset}},{key:"tell",value:function tell(){if(!this.exists()){return-1}return this._pos}},{key:"remove",value:function(){var _remove=_asyncToGenerator(_regeneratorRuntime.mark(function _callee(){return _regeneratorRuntime.wrap(function _callee$(_context){while(1)switch(_context.prev=_context.next){case 0:if(this.exists()){_context.next=2;break}throw new Error("ENOENT");case 2:PvFileMem._memFiles["delete"](this._path);this._pos=0;case 4:case"end":return _context.stop()}},_callee,this)}));function remove(){return _remove.apply(this,arguments)}return remove}()},{key:"exists",value:function exists(){return this._file!==undefined}},{key:"_isEOF",get:function get(){return this._pos>=this._file.length}},{key:"_file",get:function get(){return PvFileMem._memFiles.get(this._path)},set:function set(content){PvFileMem._memFiles.set(this._path,content)}}],[{key:"open",value:function open(path,mode){var file=PvFileMem._memFiles.get(path);var dbMode=mode.includes("r")?"readonly":"readwrite";if(file===undefined&&dbMode==="readonly"){var error=new Error("'".concat(path,"' doesn't exist."));error.name="FileNotExists";throw error}var fileMem=new PvFileMem(path,undefined,undefined,dbMode);if(mode.includes("a")){fileMem.seek(0,2)}return fileMem}}])}(PvFile);PvFileMem._memFiles=new Map;function ownKeys(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);r&&(o=o.filter(function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable})),t.push.apply(t,o)}return t}function _objectSpread(e){for(var r=1;r=r.length?{done:!0}:{done:!1,value:r[_n++]}},e:function e(r){throw r},f:F}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,a=!0,u=!1;return{s:function s(){t=t.call(r)},n:function n(){var r=t.next();return a=r.done,r},e:function e(r){u=!0,o=r},f:function f(){try{a||null==t["return"]||t["return"]()}finally{if(u)throw o}}}}function _unsupportedIterableToArray(r,a){if(r){if("string"==typeof r)return _arrayLikeToArray(r,a);var t={}.toString.call(r).slice(8,-1);return"Object"===t&&r.constructor&&(t=r.constructor.name),"Map"===t||"Set"===t?Array.from(r):"Arguments"===t||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t)?_arrayLikeToArray(r,a):void 0}}function _arrayLikeToArray(r,a){(null==a||a>r.length)&&(a=r.length);for(var e=0,n=Array(a);e>>0}return address}function arrayBufferToStringAtIndex(arrayBuffer,indexStart){var indexEnd=indexStart;while(arrayBuffer[indexEnd]!==0){indexEnd++}var utf8decoder=new TextDecoder("utf-8");var tempBuffer=new Uint8Array(arrayBuffer.slice(indexStart,indexEnd));return utf8decoder.decode(tempBuffer)}function stringHeaderToObject(stringHeader){var objectHeader={};var _iterator=_createForOfIteratorHelper(stringHeader.split("\r\n")),_step;try{for(_iterator.s();!(_step=_iterator.n()).done;){var property=_step.value;var keyValuePair=property.split(": ");if(keyValuePair[0]!==""){objectHeader[keyValuePair[0]]=keyValuePair[1]}}}catch(err){_iterator.e(err)}finally{_iterator.f()}return objectHeader}function fetchWithTimeout(_x){return _fetchWithTimeout.apply(this,arguments)}function _fetchWithTimeout(){_fetchWithTimeout=_asyncToGenerator(_regeneratorRuntime.mark(function _callee(uri){var options,time,controller,config,timeout,response,_args=arguments;return _regeneratorRuntime.wrap(function _callee$(_context){while(1)switch(_context.prev=_context.next){case 0:options=_args.length>1&&_args[1]!==undefined?_args[1]:{};time=_args.length>2&&_args[2]!==undefined?_args[2]:5e3;controller=new AbortController;config=_objectSpread(_objectSpread({},options),{},{signal:controller.signal});timeout=setTimeout(function(){controller.abort()},time);_context.next=7;return fetch(uri,config);case 7:response=_context.sent;clearTimeout(timeout);return _context.abrupt("return",response);case 10:case"end":return _context.stop()}},_callee)}));return _fetchWithTimeout.apply(this,arguments)}function open(_x2,_x3){return _open.apply(this,arguments)}function _open(){_open=_asyncToGenerator(_regeneratorRuntime.mark(function _callee2(path,mode){var error;return _regeneratorRuntime.wrap(function _callee2$(_context2){while(1)switch(_context2.prev=_context2.next){case 0:_context2.prev=0;_context2.next=3;return PvFileIDB.open(path,mode);case 3:return _context2.abrupt("return",_context2.sent);case 6:_context2.prev=6;_context2.t0=_context2["catch"](0);if(_context2.t0.name==="IndexedDBNotSupported"){console.warn("IndexedDB is not supported. Fallback to in-memory storage.")}else if(_context2.t0.name!=="FileNotExists"){console.warn("Unable to access IndexedDB (".concat(_context2.t0.toString(),"). Fallback to in-memory storage."))}if(!(typeof WorkerGlobalScope!=="undefined"&&self instanceof WorkerGlobalScope)){_context2.next=16;break}if(!(_context2.t0.name==="FileNotExists")){_context2.next=12;break}throw _context2.t0;case 12:console.error("In-memory storage cannot be used inside a worker.");error=new Error("Failed to start PvFile: ".concat(_context2.t0.toString()));error.name="PvFileNotSupported";throw error;case 16:return _context2.abrupt("return",PvFileMem.open(path,mode));case 17:case"end":return _context2.stop()}},_callee2,null,[[0,6]])}));return _open.apply(this,arguments)}var moduleOverrides=Object.assign({},Module);var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var readAsync,readBinary;if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(typeof document!="undefined"&&document.currentScript){scriptDirectory=document.currentScript.src}if(_scriptName){scriptDirectory=_scriptName}if(scriptDirectory.startsWith("blob:")){scriptDirectory=""}else{scriptDirectory=scriptDirectory.substr(0,scriptDirectory.replace(/[?#].*/,"").lastIndexOf("/")+1)}{if(ENVIRONMENT_IS_WORKER){readBinary=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=url=>{if(isFileURI(url)){return new Promise((reject,resolve)=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=()=>{if(xhr.status==200||xhr.status==0&&xhr.response){resolve(xhr.response)}reject(xhr.status)};xhr.onerror=reject;xhr.send(null)})}return fetch(url,{credentials:"same-origin"}).then(response=>{if(response.ok){return response.arrayBuffer()}return Promise.reject(new Error(response.status+" : "+response.url))})}}}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.error.bind(console);Object.assign(Module,moduleOverrides);moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];if(ENVIRONMENT_IS_PTHREAD){var wasmPromiseResolve;var wasmPromiseReject;var initializedJS=false;function threadPrintErr(...args){var text=args.join(" ");console.error(text)}if(!Module["printErr"])err=threadPrintErr;function threadAlert(...args){var text=args.join(" ");postMessage({cmd:"alert",text:text,threadId:_pthread_self()})}self.alert=threadAlert;Module["instantiateWasm"]=(info,receiveInstance)=>new Promise((resolve,reject)=>{wasmPromiseResolve=module=>{var instance=new WebAssembly.Instance(module,getWasmImports());receiveInstance(instance);resolve()};wasmPromiseReject=reject});self.onunhandledrejection=e=>{throw e.reason||e};function handleMessage(e){try{var msgData=e["data"];var cmd=msgData["cmd"];if(cmd==="load"){let messageQueue=[];self.onmessage=e=>messageQueue.push(e);self.startWorker=instance=>{postMessage({cmd:"loaded"});for(let msg of messageQueue){handleMessage(msg)}self.onmessage=handleMessage};for(const handler of msgData["handlers"]){if(!Module[handler]||Module[handler].proxy){Module[handler]=(...args)=>{postMessage({cmd:"callHandler",handler:handler,args:args})};if(handler=="print")out=Module[handler];if(handler=="printErr")err=Module[handler]}}wasmMemory=msgData["wasmMemory"];updateMemoryViews();wasmPromiseResolve(msgData["wasmModule"])}else if(cmd==="run"){__emscripten_thread_init(msgData["pthread_ptr"],0,0,1,0,0);__emscripten_thread_mailbox_await(msgData["pthread_ptr"]);establishStackSpace();PThread.receiveObjectTransfer(msgData);PThread.threadInitTLS();if(!initializedJS){initializedJS=true}try{invokeEntryPoint(msgData["start_routine"],msgData["arg"])}catch(ex){if(ex!="unwind"){throw ex}}}else if(cmd==="cancel"){if(_pthread_self()){__emscripten_thread_exit(-1)}}else if(msgData.target==="setimmediate"){}else if(cmd==="checkMailbox"){if(initializedJS){checkMailbox()}}else if(cmd){err(`worker: received unknown command ${cmd}`);err(msgData)}}catch(ex){__emscripten_thread_crashed();throw ex}}self.onmessage=handleMessage}var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var wasmMemory;var wasmModule;var ABORT=false;var EXITSTATUS;var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAP64,HEAPU64,HEAPF64;function updateMemoryViews(){var b=wasmMemory.buffer;Module["HEAP8"]=HEAP8=new Int8Array(b);Module["HEAP16"]=HEAP16=new Int16Array(b);Module["HEAPU8"]=HEAPU8=new Uint8Array(b);Module["HEAPU16"]=HEAPU16=new Uint16Array(b);Module["HEAP32"]=HEAP32=new Int32Array(b);Module["HEAPU32"]=HEAPU32=new Uint32Array(b);Module["HEAPF32"]=HEAPF32=new Float32Array(b);Module["HEAPF64"]=HEAPF64=new Float64Array(b);Module["HEAP64"]=HEAP64=new BigInt64Array(b);Module["HEAPU64"]=HEAPU64=new BigUint64Array(b)}if(!ENVIRONMENT_IS_PTHREAD){if(Module["wasmMemory"]){wasmMemory=Module["wasmMemory"]}else{var INITIAL_MEMORY=Module["INITIAL_MEMORY"]||67108864;wasmMemory=new WebAssembly.Memory({initial:INITIAL_MEMORY/65536,maximum:4294967296/65536,shared:true});if(!(wasmMemory.buffer instanceof SharedArrayBuffer)){err("requested a shared WebAssembly.Memory but the returned buffer is not a SharedArrayBuffer, indicating that while the browser has SharedArrayBuffer it does not have WebAssembly threads support - you may need to set a flag");if(ENVIRONMENT_IS_NODE){err("(on node you may need: --experimental-wasm-threads --experimental-wasm-bulk-memory and/or recent version)")}throw Error("bad memory")}}updateMemoryViews()}var __ATPRERUN__=[];var __ATINIT__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;if(ENVIRONMENT_IS_PTHREAD)return;callRuntimeCallbacks(__ATINIT__)}function postRun(){if(ENVIRONMENT_IS_PTHREAD)return;if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnInit(cb){__ATINIT__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;Module["monitorRunDependencies"]?.(runDependencies)}function removeRunDependency(id){runDependencies--;Module["monitorRunDependencies"]?.(runDependencies);if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}function abort(what){Module["onAbort"]?.(what);what="Aborted("+what+")";err(what);ABORT=true;EXITSTATUS=1;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);readyPromiseReject(e);throw e}var dataURIPrefix="data:application/octet-stream;base64,";var isDataURI=filename=>filename.startsWith(dataURIPrefix);var isFileURI=filename=>filename.startsWith("file://");function findWasmBinary(){var f="pv_eagle_pthread.wasm";if(!isDataURI(f)){return locateFile(f)}return f}var wasmBinaryFile;function getBinarySync(file){if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}function getBinaryPromise(binaryFile){if(!wasmBinary){return readAsync(binaryFile).then(response=>new Uint8Array(response),()=>getBinarySync(binaryFile))}return Promise.resolve().then(()=>getBinarySync(binaryFile))}function instantiateArrayBuffer(binaryFile,imports,receiver){return getBinaryPromise(binaryFile).then(binary=>WebAssembly.instantiate(binary,imports)).then(receiver,reason=>{err(`failed to asynchronously prepare wasm: ${reason}`);abort(reason)})}function instantiateAsync(binary,binaryFile,imports,callback){if(!binary&&typeof WebAssembly.instantiateStreaming=="function"&&!isDataURI(binaryFile)&&!isFileURI(binaryFile)&&typeof fetch=="function"){return fetch(binaryFile,{credentials:"same-origin"}).then(response=>{var result=WebAssembly.instantiateStreaming(response,imports);return result.then(callback,function(reason){err(`wasm streaming compile failed: ${reason}`);err("falling back to ArrayBuffer instantiation");return instantiateArrayBuffer(binaryFile,imports,callback)})})}return instantiateArrayBuffer(binaryFile,imports,callback)}function getWasmImports(){assignWasmImports();return{a:wasmImports}}function createWasm(){var info=getWasmImports();function receiveInstance(instance,module){wasmExports=instance.exports;wasmExports=Asyncify.instrumentWasmExports(wasmExports);wasmExports=applySignatureConversions(wasmExports);registerTLSInit(wasmExports["aa"]);wasmTable=wasmExports["Q"];addOnInit(wasmExports["x"]);wasmModule=module;removeRunDependency("wasm-instantiate");return wasmExports}addRunDependency("wasm-instantiate");function receiveInstantiationResult(result){receiveInstance(result["instance"],result["module"])}if(Module["instantiateWasm"]){try{return Module["instantiateWasm"](info,receiveInstance)}catch(e){err(`Module.instantiateWasm callback failed with error: ${e}`);readyPromiseReject(e)}}if(!wasmBinaryFile)wasmBinaryFile=findWasmBinary();instantiateAsync(wasmBinary,wasmBinaryFile,info,receiveInstantiationResult).catch(readyPromiseReject);return{}}function ExitStatus(status){this.name="ExitStatus";this.message=`Program terminated with exit(${status})`;this.status=status}var terminateWorker=worker=>{worker.terminate();worker.onmessage=e=>{}};var killThread=pthread_ptr=>{var worker=PThread.pthreads[pthread_ptr];delete PThread.pthreads[pthread_ptr];terminateWorker(worker);__emscripten_thread_free_data(pthread_ptr);PThread.runningWorkers.splice(PThread.runningWorkers.indexOf(worker),1);worker.pthread_ptr=0};var cancelThread=pthread_ptr=>{var worker=PThread.pthreads[pthread_ptr];worker.postMessage({cmd:"cancel"})};var cleanupThread=pthread_ptr=>{var worker=PThread.pthreads[pthread_ptr];PThread.returnWorkerToPool(worker)};var spawnThread=threadParams=>{var worker=PThread.getNewWorker();if(!worker){return 6}PThread.runningWorkers.push(worker);PThread.pthreads[threadParams.pthread_ptr]=worker;worker.pthread_ptr=threadParams.pthread_ptr;var msg={cmd:"run",start_routine:threadParams.startRoutine,arg:threadParams.arg,pthread_ptr:threadParams.pthread_ptr};worker.postMessage(msg,threadParams.transferList);return 0};var runtimeKeepaliveCounter=0;var keepRuntimeAlive=()=>noExitRuntime||runtimeKeepaliveCounter>0;var stackSave=()=>_emscripten_stack_get_current();var stackRestore=val=>__emscripten_stack_restore(val);var stackAlloc=sz=>__emscripten_stack_alloc(sz);var proxyToMainThread=(funcIndex,emAsmAddr,sync,...callArgs)=>{var serializedNumCallArgs=callArgs.length*2;var sp=stackSave();var args=stackAlloc(serializedNumCallArgs*8);var b=args>>>3;for(var i=0;i>>0]=arg}}var rtn=__emscripten_run_on_main_thread_js(funcIndex,emAsmAddr,serializedNumCallArgs,args,sync);stackRestore(sp);return rtn};function _proc_exit(code){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(0,0,1,code);EXITSTATUS=code;if(!keepRuntimeAlive()){PThread.terminateAllThreads();Module["onExit"]?.(code);ABORT=true}quit_(code,new ExitStatus(code))}var handleException=e=>{if(e instanceof ExitStatus||e=="unwind"){return EXITSTATUS}quit_(1,e)};function exitOnMainThread(returnCode){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(1,0,0,returnCode);_exit(returnCode)}var exitJS=(status,implicit)=>{EXITSTATUS=status;if(ENVIRONMENT_IS_PTHREAD){exitOnMainThread(status);throw"unwind"}_proc_exit(status)};var _exit=exitJS;var PThread={unusedWorkers:[],runningWorkers:[],tlsInitFunctions:[],pthreads:{},init(){if(ENVIRONMENT_IS_PTHREAD){PThread.initWorker()}else{PThread.initMainThread()}},initMainThread(){var pthreadPoolSize=navigator.hardwareConcurrency;while(pthreadPoolSize--){PThread.allocateUnusedWorker()}addOnPreRun(()=>{addRunDependency("loading-workers");PThread.loadWasmModuleToAllWorkers(()=>removeRunDependency("loading-workers"))})},initWorker(){noExitRuntime=false},setExitStatus:status=>EXITSTATUS=status,terminateAllThreads__deps:["$terminateWorker"],terminateAllThreads:()=>{for(var worker of PThread.runningWorkers){terminateWorker(worker)}for(var worker of PThread.unusedWorkers){terminateWorker(worker)}PThread.unusedWorkers=[];PThread.runningWorkers=[];PThread.pthreads=[]},returnWorkerToPool:worker=>{var pthread_ptr=worker.pthread_ptr;delete PThread.pthreads[pthread_ptr];PThread.unusedWorkers.push(worker);PThread.runningWorkers.splice(PThread.runningWorkers.indexOf(worker),1);worker.pthread_ptr=0;__emscripten_thread_free_data(pthread_ptr)},receiveObjectTransfer(data){},threadInitTLS(){PThread.tlsInitFunctions.forEach(f=>f())},loadWasmModuleToWorker:worker=>new Promise(onFinishedLoading=>{worker.onmessage=e=>{var d=e["data"];var cmd=d["cmd"];if(d["targetThread"]&&d["targetThread"]!=_pthread_self()){var targetWorker=PThread.pthreads[d["targetThread"]];if(targetWorker){targetWorker.postMessage(d,d["transferList"])}else{err(`Internal error! Worker sent a message "${cmd}" to target pthread ${d["targetThread"]}, but that thread no longer exists!`)}return}if(cmd==="checkMailbox"){checkMailbox()}else if(cmd==="spawnThread"){spawnThread(d)}else if(cmd==="cleanupThread"){cleanupThread(d["thread"])}else if(cmd==="killThread"){killThread(d["thread"])}else if(cmd==="cancelThread"){cancelThread(d["thread"])}else if(cmd==="loaded"){worker.loaded=true;onFinishedLoading(worker)}else if(cmd==="alert"){alert(`Thread ${d["threadId"]}: ${d["text"]}`)}else if(d.target==="setimmediate"){worker.postMessage(d)}else if(cmd==="callHandler"){Module[d["handler"]](...d["args"])}else if(cmd){err(`worker sent an unknown command ${cmd}`)}};worker.onerror=e=>{var message="worker sent an error!";err(`${message} ${e.filename}:${e.lineno}: ${e.message}`);throw e};var handlers=[];var knownHandlers=["onExit","onAbort","print","printErr"];for(var handler of knownHandlers){if(Module.propertyIsEnumerable(handler)){handlers.push(handler)}}worker.postMessage({cmd:"load",handlers:handlers,wasmMemory:wasmMemory,wasmModule:wasmModule})}),loadWasmModuleToAllWorkers(onMaybeReady){if(ENVIRONMENT_IS_PTHREAD){return onMaybeReady()}let pthreadPoolReady=Promise.all(PThread.unusedWorkers.map(PThread.loadWasmModuleToWorker));pthreadPoolReady.then(onMaybeReady)},allocateUnusedWorker(){var worker;var workerOptions={type:"module",name:"em-pthread"};var pthreadMainJs=_scriptName;if(Module["mainScriptUrlOrBlob"]){pthreadMainJs=Module["mainScriptUrlOrBlob"];if(typeof pthreadMainJs!="string"){pthreadMainJs=URL.createObjectURL(pthreadMainJs)}}worker=new Worker(pthreadMainJs,workerOptions);PThread.unusedWorkers.push(worker)},getNewWorker(){if(PThread.unusedWorkers.length==0){PThread.allocateUnusedWorker();PThread.loadWasmModuleToWorker(PThread.unusedWorkers[0])}return PThread.unusedWorkers.pop()}};var callRuntimeCallbacks=callbacks=>{while(callbacks.length>0){callbacks.shift()(Module)}};var establishStackSpace=()=>{var pthread_ptr=_pthread_self();var stackHigh=GROWABLE_HEAP_U32()[pthread_ptr+52>>>2>>>0];var stackSize=GROWABLE_HEAP_U32()[pthread_ptr+56>>>2>>>0];var stackLow=stackHigh-stackSize;_emscripten_stack_set_limits(stackHigh,stackLow);stackRestore(stackHigh)};var invokeEntryPoint=(ptr,arg)=>{runtimeKeepaliveCounter=0;var result=(a1=>dynCall_ii(ptr,a1))(arg);function finish(result){if(keepRuntimeAlive()){PThread.setExitStatus(result)}else{__emscripten_thread_exit(result)}}finish(result)};var noExitRuntime=Module["noExitRuntime"]||true;var registerTLSInit=tlsInitFunc=>PThread.tlsInitFunctions.push(tlsInitFunc);function pthreadCreateProxied(pthread_ptr,attr,startRoutine,arg){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(2,0,1,pthread_ptr,attr,startRoutine,arg);return ___pthread_create_js(pthread_ptr,attr,startRoutine,arg)}function ___pthread_create_js(pthread_ptr,attr,startRoutine,arg){pthread_ptr>>>=0;attr>>>=0;startRoutine>>>=0;arg>>>=0;if(typeof SharedArrayBuffer=="undefined"){err("Current environment does not support SharedArrayBuffer, pthreads are not available!");return 6}var transferList=[];var error=0;if(ENVIRONMENT_IS_PTHREAD&&(transferList.length===0||error)){return pthreadCreateProxied(pthread_ptr,attr,startRoutine,arg)}if(error)return error;var threadParams={startRoutine:startRoutine,pthread_ptr:pthread_ptr,arg:arg,transferList:transferList};if(ENVIRONMENT_IS_PTHREAD){threadParams.cmd="spawnThread";postMessage(threadParams,transferList);return 0}return spawnThread(threadParams)}function __emscripten_init_main_thread_js(tb){tb>>>=0;__emscripten_thread_init(tb,!ENVIRONMENT_IS_WORKER,1,!ENVIRONMENT_IS_WEB,65536,false);PThread.threadInitTLS()}var maybeExit=()=>{if(!keepRuntimeAlive()){try{if(ENVIRONMENT_IS_PTHREAD)__emscripten_thread_exit(EXITSTATUS);else _exit(EXITSTATUS)}catch(e){handleException(e)}}};var callUserCallback=func=>{if(ABORT){return}try{func();maybeExit()}catch(e){handleException(e)}};function __emscripten_thread_mailbox_await(pthread_ptr){pthread_ptr>>>=0;if(typeof Atomics.waitAsync==="function"){var wait=Atomics.waitAsync(GROWABLE_HEAP_I32(),pthread_ptr>>>2,pthread_ptr);wait.value.then(checkMailbox);var waitingAsync=pthread_ptr+128;Atomics.store(GROWABLE_HEAP_I32(),waitingAsync>>>2,1)}}var checkMailbox=()=>{var pthread_ptr=_pthread_self();if(pthread_ptr){__emscripten_thread_mailbox_await(pthread_ptr);callUserCallback(__emscripten_check_mailbox)}};function __emscripten_notify_mailbox_postmessage(targetThreadId,currThreadId,mainThreadId){targetThreadId>>>=0;currThreadId>>>=0;mainThreadId>>>=0;if(targetThreadId==currThreadId){setTimeout(checkMailbox)}else if(ENVIRONMENT_IS_PTHREAD){postMessage({targetThread:targetThreadId,cmd:"checkMailbox"})}else{var worker=PThread.pthreads[targetThreadId];if(!worker){return}worker.postMessage({cmd:"checkMailbox"})}}var proxiedJSCallArgs=[];function __emscripten_receive_on_main_thread_js(funcIndex,emAsmAddr,callingThread,numCallArgs,args){emAsmAddr>>>=0;callingThread>>>=0;args>>>=0;numCallArgs/=2;proxiedJSCallArgs.length=numCallArgs;var b=args>>>3;for(var i=0;i>>0]}}var func=proxiedFunctionTable[funcIndex];PThread.currentProxiedOperationCallerThread=callingThread;var rtn=func(...proxiedJSCallArgs);PThread.currentProxiedOperationCallerThread=0;return rtn}function __emscripten_thread_cleanup(thread){thread>>>=0;if(!ENVIRONMENT_IS_PTHREAD)cleanupThread(thread);else postMessage({cmd:"cleanupThread",thread:thread})}function __emscripten_thread_set_strongref(thread){thread>>>=0}var warnOnce=text=>{warnOnce.shown||={};if(!warnOnce.shown[text]){warnOnce.shown[text]=1;err(text)}};var _emscripten_check_blocking_allowed=()=>{};var runtimeKeepalivePush=()=>{runtimeKeepaliveCounter+=1};var _emscripten_exit_with_live_runtime=()=>{runtimeKeepalivePush();throw"unwind"};var getHeapMax=()=>4294901760;function _emscripten_get_heap_max(){return getHeapMax()}var _emscripten_get_now;_emscripten_get_now=()=>performance.timeOrigin+performance.now();var _emscripten_num_logical_cores=()=>navigator["hardwareConcurrency"];var growMemory=size=>{var b=wasmMemory.buffer;var pages=(size-b.byteLength+65535)/65536;try{wasmMemory.grow(pages);updateMemoryViews();return 1}catch(e){}};function _emscripten_resize_heap(requestedSize){requestedSize>>>=0;var oldSize=GROWABLE_HEAP_U8().length;if(requestedSize<=oldSize){return false}var maxHeapSize=getHeapMax();if(requestedSize>maxHeapSize){return false}var alignUp=(x,multiple)=>x+(multiple-x%multiple)%multiple;for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignUp(Math.max(requestedSize,overGrownHeapSize),65536));var replacement=growMemory(newSize);if(replacement){return true}}return false}var printCharBuffers=[null,[],[]];var UTF8Decoder=typeof TextDecoder!="undefined"?new TextDecoder:undefined;var UTF8ArrayToString=(heapOrArray,idx,maxBytesToRead)=>{idx>>>=0;var endIdx=idx+maxBytesToRead;var endPtr=idx;while(heapOrArray[endPtr]&&!(endPtr>=endIdx))++endPtr;if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.buffer instanceof SharedArrayBuffer?heapOrArray.slice(idx,endPtr):heapOrArray.subarray(idx,endPtr))}var str="";while(idx>10,56320|ch&1023)}}return str};var printChar=(stream,curr)=>{var buffer=printCharBuffers[stream];if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer,0));buffer.length=0}else{buffer.push(curr)}};var UTF8ToString=(ptr,maxBytesToRead)=>{ptr>>>=0;return ptr?UTF8ArrayToString(GROWABLE_HEAP_U8(),ptr,maxBytesToRead):""};function _fd_write(fd,iov,iovcnt,pnum){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(3,0,1,fd,iov,iovcnt,pnum);iov>>>=0;iovcnt>>>=0;pnum>>>=0;var num=0;for(var i=0;i>>2>>>0];var len=GROWABLE_HEAP_U32()[iov+4>>>2>>>0];iov+=8;for(var j=0;j>>0])}num+=len}GROWABLE_HEAP_U32()[pnum>>>2>>>0]=num;return 0}function _pv_console_log_wasm(index){console.log(arrayBufferToStringAtIndex(Module.HEAPU8,index))}var _pv_file_close_wasm=async function(fileAddress,statusAddress){statusAddress=unsignedAddress(statusAddress);return Asyncify.handleAsync(async()=>{try{const file=await PvFile.getPtr(fileAddress);await file.close();setInt(statusAddress,0)}catch(e){console.error("pvFileCloseWasm",e);setInt(statusAddress,-1)}})};_pv_file_close_wasm.isAsync=true;var _pv_file_open_wasm=async function(fileAddress,pathAddress,modeAddress,statusAddress){pathAddress=unsignedAddress(pathAddress);modeAddress=unsignedAddress(modeAddress);statusAddress=unsignedAddress(statusAddress);return Asyncify.handleAsync(async()=>{const path=arrayBufferToStringAtIndex(Module.HEAPU8,pathAddress);const mode=arrayBufferToStringAtIndex(Module.HEAPU8,modeAddress);try{const file=await open(path,mode);PvFile.setPtr(fileAddress,file);setInt(statusAddress,0)}catch(e){if(e.name!=="FileNotExists"){console.error("pvFileOpenWasm",e)}setInt(statusAddress,-1)}})};_pv_file_open_wasm.isAsync=true;var _pv_file_read_wasm=async function(fileAddress,contentAddress,size,count,numReadAddress){contentAddress=unsignedAddress(contentAddress);numReadAddress=unsignedAddress(numReadAddress);return Asyncify.handleAsync(async()=>{try{const file=PvFile.getPtr(fileAddress);const content=await file.read(size,count);Module.HEAPU8.set(content,contentAddress);setInt(numReadAddress,content.length/size)}catch(e){console.error("pvFileReadWasm",e);setInt(numReadAddress,-1)}})};_pv_file_read_wasm.isAsync=true;var _pv_https_request_wasm=async function(httpMethodAddress,serverNameAddress,endpointAddress,headerAddress,bodyAddress,timeoutMs,responseAddressAddress,responseSizeAddress,responseCodeAddress){httpMethodAddress=unsignedAddress(httpMethodAddress);serverNameAddress=unsignedAddress(serverNameAddress);endpointAddress=unsignedAddress(endpointAddress);headerAddress=unsignedAddress(headerAddress);bodyAddress=unsignedAddress(bodyAddress);responseAddressAddress=unsignedAddress(responseAddressAddress);responseSizeAddress=unsignedAddress(responseSizeAddress);responseCodeAddress=unsignedAddress(responseCodeAddress);return Asyncify.handleAsync(async()=>{const httpMethod=arrayBufferToStringAtIndex(Module.HEAPU8,httpMethodAddress);const serverName=arrayBufferToStringAtIndex(Module.HEAPU8,serverNameAddress);const endpoint=arrayBufferToStringAtIndex(Module.HEAPU8,endpointAddress);const header=arrayBufferToStringAtIndex(Module.HEAPU8,headerAddress);const body=arrayBufferToStringAtIndex(Module.HEAPU8,bodyAddress);const headerObject=stringHeaderToObject(header);const options={method:httpMethod};if(body.length>0){options.body=body}if(Object.keys(headerObject).length>0){options.headers=headerObject}let response;let responseText;let statusCode;try{response=await fetchWithTimeout("https://"+serverName+endpoint,options,timeoutMs);statusCode=response.status}catch(error){console.error("pvHttpsRequestWasm",`Failed to fetch: ${error}`);return}try{responseText=await response.text()}catch(error){console.error("pvHttpsRequestWasm",`Failed to get response text: ${error}`);return}const responseAddress=Module._malloc((responseText.length+1)*Int8Array.BYTES_PER_ELEMENT);if(responseAddress===0){console.error("pvMallocError","pvHttpsRequestWasm: cannot allocate memory for response");setInt(responseAddressAddress,0);return}setInt(responseSizeAddress,responseText.length+1);setInt(responseAddressAddress,responseAddress);for(let i=0;i{try{return func()}catch(e){abort(e)}};var sigToWasmTypes=sig=>{var typeNames={i:"i32",j:"i64",f:"f32",d:"f64",e:"externref",p:"i32"};var type={parameters:[],results:sig[0]=="v"?[]:[typeNames[sig[0]]]};for(var i=1;i{runtimeKeepaliveCounter-=1};var Asyncify={instrumentWasmImports(imports){var importPattern=/^(pv_https_request_wasm|pv_file_open_wasm|pv_file_close_wasm|pv_file_read_wasm|pv_file_write_wasm|pv_file_remove_wasm|pv_sleep_wasm|invoke_.*|__asyncjs__.*)$/;for(let[x,original]of Object.entries(imports)){if(typeof original=="function"){let isAsyncifyImport=original.isAsync||importPattern.test(x)}}},instrumentWasmExports(exports){var ret={};for(let[x,original]of Object.entries(exports)){if(typeof original=="function"){ret[x]=(...args)=>{Asyncify.exportCallStack.push(x);try{return original(...args)}finally{if(!ABORT){var y=Asyncify.exportCallStack.pop();Asyncify.maybeStopUnwind()}}}}else{ret[x]=original}}return ret},State:{Normal:0,Unwinding:1,Rewinding:2,Disabled:3},state:0,StackSize:4096,currData:null,handleSleepReturnValue:0,exportCallStack:[],callStackNameToId:{},callStackIdToName:{},callStackId:0,asyncPromiseHandlers:null,sleepCallbacks:[],getCallStackId(funcName){var id=Asyncify.callStackNameToId[funcName];if(id===undefined){id=Asyncify.callStackId++;Asyncify.callStackNameToId[funcName]=id;Asyncify.callStackIdToName[id]=funcName}return id},maybeStopUnwind(){if(Asyncify.currData&&Asyncify.state===Asyncify.State.Unwinding&&Asyncify.exportCallStack.length===0){Asyncify.state=Asyncify.State.Normal;runtimeKeepalivePush();runAndAbortIfError(_asyncify_stop_unwind);if(typeof Fibers!="undefined"){Fibers.trampoline()}}},whenDone(){return new Promise((resolve,reject)=>{Asyncify.asyncPromiseHandlers={resolve:resolve,reject:reject}})},allocateData(){var ptr=_malloc(12+Asyncify.StackSize);Asyncify.setDataHeader(ptr,ptr+12,Asyncify.StackSize);Asyncify.setDataRewindFunc(ptr);return ptr},setDataHeader(ptr,stack,stackSize){GROWABLE_HEAP_U32()[ptr>>>2>>>0]=stack;GROWABLE_HEAP_U32()[ptr+4>>>2>>>0]=stack+stackSize},setDataRewindFunc(ptr){var bottomOfCallStack=Asyncify.exportCallStack[0];var rewindId=Asyncify.getCallStackId(bottomOfCallStack);GROWABLE_HEAP_I32()[ptr+8>>>2>>>0]=rewindId},getDataRewindFuncName(ptr){var id=GROWABLE_HEAP_I32()[ptr+8>>>2>>>0];var name=Asyncify.callStackIdToName[id];return name},getDataRewindFunc(name){var func=wasmExports[name];return func},doRewind(ptr){var name=Asyncify.getDataRewindFuncName(ptr);var func=Asyncify.getDataRewindFunc(name);runtimeKeepalivePop();return func()},handleSleep(startAsync){if(ABORT)return;if(Asyncify.state===Asyncify.State.Normal){var reachedCallback=false;var reachedAfterCallback=false;startAsync((handleSleepReturnValue=0)=>{if(ABORT)return;Asyncify.handleSleepReturnValue=handleSleepReturnValue;reachedCallback=true;if(!reachedAfterCallback){return}Asyncify.state=Asyncify.State.Rewinding;runAndAbortIfError(()=>_asyncify_start_rewind(Asyncify.currData));if(typeof Browser!="undefined"&&Browser.mainLoop.func){Browser.mainLoop.resume()}var asyncWasmReturnValue,isError=false;try{asyncWasmReturnValue=Asyncify.doRewind(Asyncify.currData)}catch(err){asyncWasmReturnValue=err;isError=true}var handled=false;if(!Asyncify.currData){var asyncPromiseHandlers=Asyncify.asyncPromiseHandlers;if(asyncPromiseHandlers){Asyncify.asyncPromiseHandlers=null;(isError?asyncPromiseHandlers.reject:asyncPromiseHandlers.resolve)(asyncWasmReturnValue);handled=true}}if(isError&&!handled){throw asyncWasmReturnValue}});reachedAfterCallback=true;if(!reachedCallback){Asyncify.state=Asyncify.State.Unwinding;Asyncify.currData=Asyncify.allocateData();if(typeof Browser!="undefined"&&Browser.mainLoop.func){Browser.mainLoop.pause()}runAndAbortIfError(()=>_asyncify_start_unwind(Asyncify.currData))}}else if(Asyncify.state===Asyncify.State.Rewinding){Asyncify.state=Asyncify.State.Normal;runAndAbortIfError(_asyncify_stop_rewind);_free(Asyncify.currData);Asyncify.currData=null;Asyncify.sleepCallbacks.forEach(callUserCallback)}else{abort(`invalid state: ${Asyncify.state}`)}return Asyncify.handleSleepReturnValue},handleAsync(startAsync){return Asyncify.handleSleep(wakeUp=>{startAsync().then(wakeUp)})}};var uleb128Encode=(n,target)=>{if(n<128){target.push(n)}else{target.push(n%128|128,n>>7)}};var generateFuncType=(sig,target)=>{var sigRet=sig.slice(0,1);var sigParam=sig.slice(1);var typeCodes={i:127,p:127,j:126,f:125,d:124,e:111};target.push(96);uleb128Encode(sigParam.length,target);for(var i=0;i{if(typeof WebAssembly.Function=="function"){return new WebAssembly.Function(sigToWasmTypes(sig),func)}var typeSectionBody=[1];generateFuncType(sig,typeSectionBody);var bytes=[0,97,115,109,1,0,0,0,1];uleb128Encode(typeSectionBody.length,bytes);bytes.push(...typeSectionBody);bytes.push(2,7,1,1,101,1,102,0,0,7,5,1,1,102,0,0);var module=new WebAssembly.Module(new Uint8Array(bytes));var instance=new WebAssembly.Instance(module,{e:{f:func}});var wrappedFunc=instance.exports["f"];return wrappedFunc};var wasmTableMirror=[];var wasmTable;var getWasmTableEntry=funcPtr=>{var func=wasmTableMirror[funcPtr];if(!func){if(funcPtr>=wasmTableMirror.length)wasmTableMirror.length=funcPtr+1;wasmTableMirror[funcPtr]=func=wasmTable.get(funcPtr)}return func};var updateTableMap=(offset,count)=>{if(functionsInTableMap){for(var i=offset;i{if(!functionsInTableMap){functionsInTableMap=new WeakMap;updateTableMap(0,wasmTable.length)}return functionsInTableMap.get(func)||0};var freeTableIndexes=[];var getEmptyTableSlot=()=>{if(freeTableIndexes.length){return freeTableIndexes.pop()}try{wasmTable.grow(1)}catch(err){if(!(err instanceof RangeError)){throw err}throw"Unable to grow wasm table. Set ALLOW_TABLE_GROWTH."}return wasmTable.length-1};var setWasmTableEntry=(idx,func)=>{wasmTable.set(idx,func);wasmTableMirror[idx]=wasmTable.get(idx)};var addFunction=(func,sig)=>{var rtn=getFunctionAddress(func);if(rtn){return rtn}var ret=getEmptyTableSlot();try{setWasmTableEntry(ret,func)}catch(err){if(!(err instanceof TypeError)){throw err}var wrapped=convertJsFunctionToWasm(func,sig);setWasmTableEntry(ret,wrapped)}functionsInTableMap.set(func,ret);return ret};var getCFunc=ident=>{var func=Module["_"+ident];return func};var writeArrayToMemory=(array,buffer)=>{GROWABLE_HEAP_I8().set(array,buffer>>>0)};var lengthBytesUTF8=str=>{var len=0;for(var i=0;i=55296&&c<=57343){len+=4;++i}else{len+=3}}return len};var stringToUTF8Array=(str,heap,outIdx,maxBytesToWrite)=>{outIdx>>>=0;if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++>>>0]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++>>>0]=192|u>>6;heap[outIdx++>>>0]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++>>>0]=224|u>>12;heap[outIdx++>>>0]=128|u>>6&63;heap[outIdx++>>>0]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++>>>0]=240|u>>18;heap[outIdx++>>>0]=128|u>>12&63;heap[outIdx++>>>0]=128|u>>6&63;heap[outIdx++>>>0]=128|u&63}}heap[outIdx>>>0]=0;return outIdx-startIdx};var stringToUTF8=(str,outPtr,maxBytesToWrite)=>stringToUTF8Array(str,GROWABLE_HEAP_U8(),outPtr,maxBytesToWrite);var stringToUTF8OnStack=str=>{var size=lengthBytesUTF8(str)+1;var ret=stackAlloc(size);stringToUTF8(str,ret,size);return ret};var ccall=(ident,returnType,argTypes,args,opts)=>{var toC={string:str=>{var ret=0;if(str!==null&&str!==undefined&&str!==0){ret=stringToUTF8OnStack(str)}return ret},array:arr=>{var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string"){return UTF8ToString(ret)}if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i{var numericArgs=!argTypes||argTypes.every(type=>type==="number"||type==="boolean");var numericRet=returnType!=="string";if(numericRet&&numericArgs&&!opts){return getCFunc(ident)}return(...args)=>ccall(ident,returnType,argTypes,args,opts)};Module["cwrap"]=cwrap;PThread.init();var proxiedFunctionTable=[_proc_exit,exitOnMainThread,pthreadCreateProxied,_fd_write];var wasmImports;function assignWasmImports(){wasmImports={u:___pthread_create_js,h:__emscripten_init_main_thread_js,q:__emscripten_notify_mailbox_postmessage,v:__emscripten_receive_on_main_thread_js,d:__emscripten_thread_cleanup,g:__emscripten_thread_mailbox_await,j:__emscripten_thread_set_strongref,e:_emscripten_check_blocking_allowed,i:_emscripten_exit_with_live_runtime,r:_emscripten_get_heap_max,b:_emscripten_get_now,s:_emscripten_num_logical_cores,p:_emscripten_resize_heap,t:_exit,c:_fd_write,a:wasmMemory,f:_pv_console_log_wasm,m:_pv_file_close_wasm,o:_pv_file_open_wasm,l:_pv_file_read_wasm,k:_pv_https_request_wasm,w:_pv_time_wasm,n:_pv_ypu_get_max_workers_wasm}}var wasmExports=createWasm();var ___wasm_call_ctors=()=>(___wasm_call_ctors=wasmExports["x"])();var _pv_eagle_init=Module["_pv_eagle_init"]=(a0,a1,a2,a3,a4)=>(_pv_eagle_init=Module["_pv_eagle_init"]=wasmExports["y"])(a0,a1,a2,a3,a4);var _free=a0=>(_free=wasmExports["z"])(a0);var _pv_eagle_delete=Module["_pv_eagle_delete"]=a0=>(_pv_eagle_delete=Module["_pv_eagle_delete"]=wasmExports["A"])(a0);var _pv_eagle_process_min_audio_length_samples=Module["_pv_eagle_process_min_audio_length_samples"]=(a0,a1)=>(_pv_eagle_process_min_audio_length_samples=Module["_pv_eagle_process_min_audio_length_samples"]=wasmExports["B"])(a0,a1);var _pv_eagle_process=Module["_pv_eagle_process"]=(a0,a1,a2,a3,a4,a5)=>(_pv_eagle_process=Module["_pv_eagle_process"]=wasmExports["C"])(a0,a1,a2,a3,a4,a5);var _pv_sample_rate=Module["_pv_sample_rate"]=()=>(_pv_sample_rate=Module["_pv_sample_rate"]=wasmExports["D"])();var _pv_eagle_scores_delete=Module["_pv_eagle_scores_delete"]=a0=>(_pv_eagle_scores_delete=Module["_pv_eagle_scores_delete"]=wasmExports["E"])(a0);var _pv_eagle_profiler_init=Module["_pv_eagle_profiler_init"]=(a0,a1,a2,a3,a4,a5)=>(_pv_eagle_profiler_init=Module["_pv_eagle_profiler_init"]=wasmExports["F"])(a0,a1,a2,a3,a4,a5);var _pv_eagle_profiler_reset=Module["_pv_eagle_profiler_reset"]=a0=>(_pv_eagle_profiler_reset=Module["_pv_eagle_profiler_reset"]=wasmExports["G"])(a0);var _pv_eagle_profiler_delete=Module["_pv_eagle_profiler_delete"]=a0=>(_pv_eagle_profiler_delete=Module["_pv_eagle_profiler_delete"]=wasmExports["H"])(a0);var _pv_eagle_profiler_enroll=Module["_pv_eagle_profiler_enroll"]=(a0,a1,a2)=>(_pv_eagle_profiler_enroll=Module["_pv_eagle_profiler_enroll"]=wasmExports["I"])(a0,a1,a2);var _pv_eagle_profiler_frame_length=Module["_pv_eagle_profiler_frame_length"]=()=>(_pv_eagle_profiler_frame_length=Module["_pv_eagle_profiler_frame_length"]=wasmExports["J"])();var _pv_eagle_profiler_flush=Module["_pv_eagle_profiler_flush"]=(a0,a1)=>(_pv_eagle_profiler_flush=Module["_pv_eagle_profiler_flush"]=wasmExports["K"])(a0,a1);var _pv_eagle_profiler_export_size=Module["_pv_eagle_profiler_export_size"]=(a0,a1)=>(_pv_eagle_profiler_export_size=Module["_pv_eagle_profiler_export_size"]=wasmExports["L"])(a0,a1);var _pv_eagle_profiler_export=Module["_pv_eagle_profiler_export"]=(a0,a1)=>(_pv_eagle_profiler_export=Module["_pv_eagle_profiler_export"]=wasmExports["M"])(a0,a1);var _pv_eagle_version=Module["_pv_eagle_version"]=()=>(_pv_eagle_version=Module["_pv_eagle_version"]=wasmExports["N"])();var _pv_eagle_list_hardware_devices=Module["_pv_eagle_list_hardware_devices"]=(a0,a1)=>(_pv_eagle_list_hardware_devices=Module["_pv_eagle_list_hardware_devices"]=wasmExports["O"])(a0,a1);var _pv_eagle_free_hardware_devices=Module["_pv_eagle_free_hardware_devices"]=(a0,a1)=>(_pv_eagle_free_hardware_devices=Module["_pv_eagle_free_hardware_devices"]=wasmExports["P"])(a0,a1);var _pv_status_to_string=Module["_pv_status_to_string"]=a0=>(_pv_status_to_string=Module["_pv_status_to_string"]=wasmExports["R"])(a0);var _malloc=Module["_malloc"]=a0=>(_malloc=Module["_malloc"]=wasmExports["S"])(a0);var _pv_log_enable=Module["_pv_log_enable"]=()=>(_pv_log_enable=Module["_pv_log_enable"]=wasmExports["T"])();var _pv_log_disable=Module["_pv_log_disable"]=()=>(_pv_log_disable=Module["_pv_log_disable"]=wasmExports["U"])();var _pv_set_home_dir=Module["_pv_set_home_dir"]=a0=>(_pv_set_home_dir=Module["_pv_set_home_dir"]=wasmExports["V"])(a0);var _aligned_alloc=Module["_aligned_alloc"]=(a0,a1)=>(_aligned_alloc=Module["_aligned_alloc"]=wasmExports["W"])(a0,a1);var _pv_get_sdk=Module["_pv_get_sdk"]=()=>(_pv_get_sdk=Module["_pv_get_sdk"]=wasmExports["X"])();var _pv_set_sdk=Module["_pv_set_sdk"]=a0=>(_pv_set_sdk=Module["_pv_set_sdk"]=wasmExports["Y"])(a0);var _pv_free=Module["_pv_free"]=a0=>(_pv_free=Module["_pv_free"]=wasmExports["Z"])(a0);var _pv_get_error_stack=Module["_pv_get_error_stack"]=(a0,a1)=>(_pv_get_error_stack=Module["_pv_get_error_stack"]=wasmExports["_"])(a0,a1);var _pv_free_error_stack=Module["_pv_free_error_stack"]=a0=>(_pv_free_error_stack=Module["_pv_free_error_stack"]=wasmExports["$"])(a0);var __emscripten_tls_init=()=>(__emscripten_tls_init=wasmExports["aa"])();var _pthread_self=()=>(_pthread_self=wasmExports["ba"])();var __emscripten_memcpy_bulkmem=Module["__emscripten_memcpy_bulkmem"]=(a0,a1,a2)=>(__emscripten_memcpy_bulkmem=Module["__emscripten_memcpy_bulkmem"]=wasmExports["ca"])(a0,a1,a2);var __emscripten_memset_bulkmem=Module["__emscripten_memset_bulkmem"]=(a0,a1,a2)=>(__emscripten_memset_bulkmem=Module["__emscripten_memset_bulkmem"]=wasmExports["da"])(a0,a1,a2);var ___get_tp=Module["___get_tp"]=()=>(___get_tp=Module["___get_tp"]=wasmExports["ea"])();var __emscripten_thread_supports_atomics_wait=Module["__emscripten_thread_supports_atomics_wait"]=()=>(__emscripten_thread_supports_atomics_wait=Module["__emscripten_thread_supports_atomics_wait"]=wasmExports["fa"])();var __emscripten_thread_init=(a0,a1,a2,a3,a4,a5)=>(__emscripten_thread_init=wasmExports["ga"])(a0,a1,a2,a3,a4,a5);var ___set_thread_state=Module["___set_thread_state"]=(a0,a1,a2,a3)=>(___set_thread_state=Module["___set_thread_state"]=wasmExports["ha"])(a0,a1,a2,a3);var _emscripten_is_main_runtime_thread=Module["_emscripten_is_main_runtime_thread"]=()=>(_emscripten_is_main_runtime_thread=Module["_emscripten_is_main_runtime_thread"]=wasmExports["ia"])();var _emscripten_is_main_browser_thread=Module["_emscripten_is_main_browser_thread"]=()=>(_emscripten_is_main_browser_thread=Module["_emscripten_is_main_browser_thread"]=wasmExports["ja"])();var __emscripten_thread_crashed=()=>(__emscripten_thread_crashed=wasmExports["ka"])();var _emscripten_stack_get_base=Module["_emscripten_stack_get_base"]=()=>(_emscripten_stack_get_base=Module["_emscripten_stack_get_base"]=wasmExports["la"])();var _emscripten_stack_get_end=Module["_emscripten_stack_get_end"]=()=>(_emscripten_stack_get_end=Module["_emscripten_stack_get_end"]=wasmExports["ma"])();var __emscripten_run_on_main_thread_js=(a0,a1,a2,a3,a4)=>(__emscripten_run_on_main_thread_js=wasmExports["na"])(a0,a1,a2,a3,a4);var __emscripten_thread_free_data=a0=>(__emscripten_thread_free_data=wasmExports["oa"])(a0);var __emscripten_thread_exit=a0=>(__emscripten_thread_exit=wasmExports["pa"])(a0);var __emscripten_check_mailbox=()=>(__emscripten_check_mailbox=wasmExports["qa"])();var _emscripten_stack_init=Module["_emscripten_stack_init"]=()=>(_emscripten_stack_init=Module["_emscripten_stack_init"]=wasmExports["ra"])();var _emscripten_stack_set_limits=(a0,a1)=>(_emscripten_stack_set_limits=wasmExports["sa"])(a0,a1);var _emscripten_stack_get_free=Module["_emscripten_stack_get_free"]=()=>(_emscripten_stack_get_free=Module["_emscripten_stack_get_free"]=wasmExports["ta"])();var __emscripten_wasm_worker_initialize=Module["__emscripten_wasm_worker_initialize"]=(a0,a1)=>(__emscripten_wasm_worker_initialize=Module["__emscripten_wasm_worker_initialize"]=wasmExports["ua"])(a0,a1);var __emscripten_stack_restore=a0=>(__emscripten_stack_restore=wasmExports["va"])(a0);var __emscripten_stack_alloc=a0=>(__emscripten_stack_alloc=wasmExports["wa"])(a0);var _emscripten_stack_get_current=()=>(_emscripten_stack_get_current=wasmExports["xa"])();var dynCall_ii=Module["dynCall_ii"]=(a0,a1)=>(dynCall_ii=Module["dynCall_ii"]=wasmExports["ya"])(a0,a1);var _asyncify_start_unwind=a0=>(_asyncify_start_unwind=wasmExports["za"])(a0);var _asyncify_stop_unwind=()=>(_asyncify_stop_unwind=wasmExports["Aa"])();var _asyncify_start_rewind=a0=>(_asyncify_start_rewind=wasmExports["Ba"])(a0);var _asyncify_stop_rewind=()=>(_asyncify_stop_rewind=wasmExports["Ca"])();function applySignatureConversions(wasmExports){wasmExports=Object.assign({},wasmExports);var makeWrapper_pp=f=>a0=>f(a0)>>>0;var makeWrapper_p=f=>()=>f()>>>0;wasmExports["S"]=makeWrapper_pp(wasmExports["S"]);wasmExports["ba"]=makeWrapper_p(wasmExports["ba"]);wasmExports["emscripten_main_runtime_thread_id"]=makeWrapper_p(wasmExports["emscripten_main_runtime_thread_id"]);wasmExports["la"]=makeWrapper_p(wasmExports["la"]);wasmExports["ma"]=makeWrapper_p(wasmExports["ma"]);wasmExports["wa"]=makeWrapper_pp(wasmExports["wa"]);wasmExports["xa"]=makeWrapper_p(wasmExports["xa"]);return wasmExports}Module["addFunction"]=addFunction;var calledRun;dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function run(){if(runDependencies>0){return}if(ENVIRONMENT_IS_PTHREAD){readyPromiseResolve(Module);initRuntime();startWorker(Module);return}preRun();if(runDependencies>0){return}function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();readyPromiseResolve(Module);Module["onRuntimeInitialized"]?.();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("")},1);doRun()},1)}else{doRun()}}if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}run();moduleRtn=readyPromise; return moduleRtn; diff --git a/lib/wasm/pv_eagle_pthread.wasm b/lib/wasm/pv_eagle_pthread.wasm index 784df166..cf39a755 100755 Binary files a/lib/wasm/pv_eagle_pthread.wasm and b/lib/wasm/pv_eagle_pthread.wasm differ diff --git a/lib/wasm/pv_eagle_simd.js b/lib/wasm/pv_eagle_simd.js index 8c58a57a..a25cd9a7 100644 --- a/lib/wasm/pv_eagle_simd.js +++ b/lib/wasm/pv_eagle_simd.js @@ -6,7 +6,7 @@ var pv_eagle_simd = (() => { function(moduleArg = {}) { var moduleRtn; -var Module=moduleArg;var readyPromiseResolve,readyPromiseReject;var readyPromise=new Promise((resolve,reject)=>{readyPromiseResolve=resolve;readyPromiseReject=reject});var ENVIRONMENT_IS_WEB=typeof window=="object";var ENVIRONMENT_IS_WORKER=typeof importScripts=="function";var ENVIRONMENT_IS_NODE=typeof process=="object"&&typeof process.versions=="object"&&typeof process.versions.node=="string";function _typeof$2(o){null;return _typeof$2="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(o){return typeof o}:function(o){return o&&"function"==typeof Symbol&&o.constructor===Symbol&&o!==Symbol.prototype?"symbol":typeof o},_typeof$2(o)}function toPrimitive(t,r){if("object"!=_typeof$2(t)||!t)return t;var e=t[Symbol.toPrimitive];if(void 0!==e){var i=e.call(t,r||"default");if("object"!=_typeof$2(i))return i;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===r?String:Number)(t)}function toPropertyKey(t){var i=toPrimitive(t,"string");return"symbol"==_typeof$2(i)?i:i+""}function _defineProperty(e,r,t){return(r=toPropertyKey(r))in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function asyncGeneratorStep(n,t,e,r,o,a,c){try{var i=n[a](c),u=i.value}catch(n){return void e(n)}i.done?t(u):Promise.resolve(u).then(r,o)}function _asyncToGenerator(n){return function(){var t=this,e=arguments;return new Promise(function(r,o){var a=n.apply(t,e);function _next(n){asyncGeneratorStep(a,r,o,_next,_throw,"next",n)}function _throw(n){asyncGeneratorStep(a,r,o,_next,_throw,"throw",n)}_next(void 0)})}}function getDefaultExportFromCjs(x){return x&&x.__esModule&&Object.prototype.hasOwnProperty.call(x,"default")?x["default"]:x}var regeneratorRuntime$3={exports:{}};var _typeof$1={exports:{}};var _typeof_1=_typeof$1.exports;(function(module){function _typeof(o){null;return module.exports=_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(o){return typeof o}:function(o){return o&&"function"==typeof Symbol&&o.constructor===Symbol&&o!==Symbol.prototype?"symbol":typeof o},module.exports.__esModule=true,module.exports["default"]=module.exports,_typeof(o)}module.exports=_typeof,module.exports.__esModule=true,module.exports["default"]=module.exports})(_typeof$1);var _typeofExports=_typeof$1.exports;var _typeof=getDefaultExportFromCjs(_typeofExports);var regeneratorRuntime$1=regeneratorRuntime$3.exports;(function(module){var _typeof=_typeofExports["default"];function _regeneratorRuntime(){"use strict";module.exports=_regeneratorRuntime=function _regeneratorRuntime(){return e},module.exports.__esModule=true,module.exports["default"]=module.exports;var t,e={},r=Object.prototype,n=r.hasOwnProperty,o=Object.defineProperty||function(t,e,r){t[e]=r.value},i="function"==typeof Symbol?Symbol:{},a=i.iterator||"@@iterator",c=i.asyncIterator||"@@asyncIterator",u=i.toStringTag||"@@toStringTag";function define(t,e,r){return Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}),t[e]}try{define({},"")}catch(t){define=function define(t,e,r){return t[e]=r}}function wrap(t,e,r,n){var i=e&&e.prototype instanceof Generator?e:Generator,a=Object.create(i.prototype),c=new Context(n||[]);return o(a,"_invoke",{value:makeInvokeMethod(t,r,c)}),a}function tryCatch(t,e,r){try{return{type:"normal",arg:t.call(e,r)}}catch(t){return{type:"throw",arg:t}}}e.wrap=wrap;var h="suspendedStart",l="suspendedYield",f="executing",s="completed",y={};function Generator(){}function GeneratorFunction(){}function GeneratorFunctionPrototype(){}var p={};define(p,a,function(){return this});var d=Object.getPrototypeOf,v=d&&d(d(values([])));v&&v!==r&&n.call(v,a)&&(p=v);var g=GeneratorFunctionPrototype.prototype=Generator.prototype=Object.create(p);function defineIteratorMethods(t){["next","throw","return"].forEach(function(e){define(t,e,function(t){return this._invoke(e,t)})})}function AsyncIterator(t,e){function invoke(r,o,i,a){var c=tryCatch(t[r],t,o);if("throw"!==c.type){var u=c.arg,h=u.value;return h&&"object"==_typeof(h)&&n.call(h,"__await")?e.resolve(h.__await).then(function(t){invoke("next",t,i,a)},function(t){invoke("throw",t,i,a)}):e.resolve(h).then(function(t){u.value=t,i(u)},function(t){return invoke("throw",t,i,a)})}a(c.arg)}var r;o(this,"_invoke",{value:function value(t,n){function callInvokeWithMethodAndArg(){return new e(function(e,r){invoke(t,n,e,r)})}return r=r?r.then(callInvokeWithMethodAndArg,callInvokeWithMethodAndArg):callInvokeWithMethodAndArg()}})}function makeInvokeMethod(e,r,n){var o=h;return function(i,a){if(o===f)throw Error("Generator is already running");if(o===s){if("throw"===i)throw a;return{value:t,done:!0}}for(n.method=i,n.arg=a;;){var c=n.delegate;if(c){var u=maybeInvokeDelegate(c,n);if(u){if(u===y)continue;return u}}if("next"===n.method)n.sent=n._sent=n.arg;else if("throw"===n.method){if(o===h)throw o=s,n.arg;n.dispatchException(n.arg)}else"return"===n.method&&n.abrupt("return",n.arg);o=f;var p=tryCatch(e,r,n);if("normal"===p.type){if(o=n.done?s:l,p.arg===y)continue;return{value:p.arg,done:n.done}}"throw"===p.type&&(o=s,n.method="throw",n.arg=p.arg)}}}function maybeInvokeDelegate(e,r){var n=r.method,o=e.iterator[n];if(o===t)return r.delegate=null,"throw"===n&&e.iterator["return"]&&(r.method="return",r.arg=t,maybeInvokeDelegate(e,r),"throw"===r.method)||"return"!==n&&(r.method="throw",r.arg=new TypeError("The iterator does not provide a '"+n+"' method")),y;var i=tryCatch(o,e.iterator,r.arg);if("throw"===i.type)return r.method="throw",r.arg=i.arg,r.delegate=null,y;var a=i.arg;return a?a.done?(r[e.resultName]=a.value,r.next=e.nextLoc,"return"!==r.method&&(r.method="next",r.arg=t),r.delegate=null,y):a:(r.method="throw",r.arg=new TypeError("iterator result is not an object"),r.delegate=null,y)}function pushTryEntry(t){var e={tryLoc:t[0]};1 in t&&(e.catchLoc=t[1]),2 in t&&(e.finallyLoc=t[2],e.afterLoc=t[3]),this.tryEntries.push(e)}function resetTryEntry(t){var e=t.completion||{};e.type="normal",delete e.arg,t.completion=e}function Context(t){this.tryEntries=[{tryLoc:"root"}],t.forEach(pushTryEntry,this),this.reset(!0)}function values(e){if(e||""===e){var r=e[a];if(r)return r.call(e);if("function"==typeof e.next)return e;if(!isNaN(e.length)){var o=-1,i=function next(){for(;++o=0;--o){var i=this.tryEntries[o],a=i.completion;if("root"===i.tryLoc)return handle("end");if(i.tryLoc<=this.prev){var c=n.call(i,"catchLoc"),u=n.call(i,"finallyLoc");if(c&&u){if(this.prev=0;--r){var o=this.tryEntries[r];if(o.tryLoc<=this.prev&&n.call(o,"finallyLoc")&&this.prev=0;--e){var r=this.tryEntries[e];if(r.finallyLoc===t)return this.complete(r.completion,r.afterLoc),resetTryEntry(r),y}},catch:function _catch(t){for(var e=this.tryEntries.length-1;e>=0;--e){var r=this.tryEntries[e];if(r.tryLoc===t){var n=r.completion;if("throw"===n.type){var o=n.arg;resetTryEntry(r)}return o}}throw Error("illegal catch attempt")},delegateYield:function delegateYield(e,r,n){return this.delegate={iterator:values(e),resultName:r,nextLoc:n},"next"===this.method&&(this.arg=t),y}},e}module.exports=_regeneratorRuntime,module.exports.__esModule=true,module.exports["default"]=module.exports})(regeneratorRuntime$3);var regeneratorRuntimeExports=regeneratorRuntime$3.exports;var regeneratorRuntime$2=getDefaultExportFromCjs(regeneratorRuntimeExports);var runtime=regeneratorRuntimeExports();var regenerator=runtime;try{regeneratorRuntime=runtime}catch(accidentalStrictMode){if(typeof globalThis==="object"){globalThis.regeneratorRuntime=runtime}else{Function("r","regeneratorRuntime = r")(runtime)}}var _regeneratorRuntime=getDefaultExportFromCjs(regenerator);const BROWSER_ALIASES_MAP={"Amazon Silk":"amazon_silk","Android Browser":"android",Bada:"bada",BlackBerry:"blackberry",Chrome:"chrome",Chromium:"chromium",Electron:"electron",Epiphany:"epiphany",Firefox:"firefox",Focus:"focus",Generic:"generic","Google Search":"google_search",Googlebot:"googlebot","Internet Explorer":"ie","K-Meleon":"k_meleon",Maxthon:"maxthon","Microsoft Edge":"edge","MZ Browser":"mz","NAVER Whale Browser":"naver",Opera:"opera","Opera Coast":"opera_coast",PhantomJS:"phantomjs",Puffin:"puffin",QupZilla:"qupzilla",QQ:"qq",QQLite:"qqlite",Safari:"safari",Sailfish:"sailfish","Samsung Internet for Android":"samsung_internet",SeaMonkey:"seamonkey",Sleipnir:"sleipnir",Swing:"swing",Tizen:"tizen","UC Browser":"uc",Vivaldi:"vivaldi","WebOS Browser":"webos",WeChat:"wechat","Yandex Browser":"yandex",Roku:"roku"};const BROWSER_MAP={amazon_silk:"Amazon Silk",android:"Android Browser",bada:"Bada",blackberry:"BlackBerry",chrome:"Chrome",chromium:"Chromium",electron:"Electron",epiphany:"Epiphany",firefox:"Firefox",focus:"Focus",generic:"Generic",googlebot:"Googlebot",google_search:"Google Search",ie:"Internet Explorer",k_meleon:"K-Meleon",maxthon:"Maxthon",edge:"Microsoft Edge",mz:"MZ Browser",naver:"NAVER Whale Browser",opera:"Opera",opera_coast:"Opera Coast",phantomjs:"PhantomJS",puffin:"Puffin",qupzilla:"QupZilla",qq:"QQ Browser",qqlite:"QQ Browser Lite",safari:"Safari",sailfish:"Sailfish",samsung_internet:"Samsung Internet for Android",seamonkey:"SeaMonkey",sleipnir:"Sleipnir",swing:"Swing",tizen:"Tizen",uc:"UC Browser",vivaldi:"Vivaldi",webos:"WebOS Browser",wechat:"WeChat",yandex:"Yandex Browser"};const PLATFORMS_MAP={tablet:"tablet",mobile:"mobile",desktop:"desktop",tv:"tv"};const OS_MAP={WindowsPhone:"Windows Phone",Windows:"Windows",MacOS:"macOS",iOS:"iOS",Android:"Android",WebOS:"WebOS",BlackBerry:"BlackBerry",Bada:"Bada",Tizen:"Tizen",Linux:"Linux",ChromeOS:"Chrome OS",PlayStation4:"PlayStation 4",Roku:"Roku"};const ENGINE_MAP={EdgeHTML:"EdgeHTML",Blink:"Blink",Trident:"Trident",Presto:"Presto",Gecko:"Gecko",WebKit:"WebKit"};class Utils{static getFirstMatch(regexp,ua){const match=ua.match(regexp);return match&&match.length>0&&match[1]||""}static getSecondMatch(regexp,ua){const match=ua.match(regexp);return match&&match.length>1&&match[2]||""}static matchAndReturnConst(regexp,ua,_const){if(regexp.test(ua)){return _const}return void 0}static getWindowsVersionName(version){switch(version){case"NT":return"NT";case"XP":return"XP";case"NT 5.0":return"2000";case"NT 5.1":return"XP";case"NT 5.2":return"2003";case"NT 6.0":return"Vista";case"NT 6.1":return"7";case"NT 6.2":return"8";case"NT 6.3":return"8.1";case"NT 10.0":return"10";default:return undefined}}static getMacOSVersionName(version){const v=version.split(".").splice(0,2).map(s=>parseInt(s,10)||0);v.push(0);if(v[0]!==10)return undefined;switch(v[1]){case 5:return"Leopard";case 6:return"Snow Leopard";case 7:return"Lion";case 8:return"Mountain Lion";case 9:return"Mavericks";case 10:return"Yosemite";case 11:return"El Capitan";case 12:return"Sierra";case 13:return"High Sierra";case 14:return"Mojave";case 15:return"Catalina";default:return undefined}}static getAndroidVersionName(version){const v=version.split(".").splice(0,2).map(s=>parseInt(s,10)||0);v.push(0);if(v[0]===1&&v[1]<5)return undefined;if(v[0]===1&&v[1]<6)return"Cupcake";if(v[0]===1&&v[1]>=6)return"Donut";if(v[0]===2&&v[1]<2)return"Eclair";if(v[0]===2&&v[1]===2)return"Froyo";if(v[0]===2&&v[1]>2)return"Gingerbread";if(v[0]===3)return"Honeycomb";if(v[0]===4&&v[1]<1)return"Ice Cream Sandwich";if(v[0]===4&&v[1]<4)return"Jelly Bean";if(v[0]===4&&v[1]>=4)return"KitKat";if(v[0]===5)return"Lollipop";if(v[0]===6)return"Marshmallow";if(v[0]===7)return"Nougat";if(v[0]===8)return"Oreo";if(v[0]===9)return"Pie";return undefined}static getVersionPrecision(version){return version.split(".").length}static compareVersions(versionA,versionB,isLoose=false){const versionAPrecision=Utils.getVersionPrecision(versionA);const versionBPrecision=Utils.getVersionPrecision(versionB);let precision=Math.max(versionAPrecision,versionBPrecision);let lastPrecision=0;const chunks=Utils.map([versionA,versionB],version=>{const delta=precision-Utils.getVersionPrecision(version);const _version=version+new Array(delta+1).join(".0");return Utils.map(_version.split("."),chunk=>new Array(20-chunk.length).join("0")+chunk).reverse()});if(isLoose){lastPrecision=precision-Math.min(versionAPrecision,versionBPrecision)}precision-=1;while(precision>=lastPrecision){if(chunks[0][precision]>chunks[1][precision]){return 1}if(chunks[0][precision]===chunks[1][precision]){if(precision===lastPrecision){return 0}precision-=1}else if(chunks[0][precision]{result[key]=assigner[key]})}}return obj}static getBrowserAlias(browserName){return BROWSER_ALIASES_MAP[browserName]}static getBrowserTypeByAlias(browserAlias){return BROWSER_MAP[browserAlias]||""}}const commonVersionIdentifier=/version\/(\d+(\.?_?\d+)+)/i;const browsersList=[{test:[/googlebot/i],describe(ua){const browser={name:"Googlebot"};const version=Utils.getFirstMatch(/googlebot\/(\d+(\.\d+))/i,ua)||Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/opera/i],describe(ua){const browser={name:"Opera"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua)||Utils.getFirstMatch(/(?:opera)[\s/](\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/opr\/|opios/i],describe(ua){const browser={name:"Opera"};const version=Utils.getFirstMatch(/(?:opr|opios)[\s/](\S+)/i,ua)||Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/SamsungBrowser/i],describe(ua){const browser={name:"Samsung Internet for Android"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua)||Utils.getFirstMatch(/(?:SamsungBrowser)[\s/](\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/Whale/i],describe(ua){const browser={name:"NAVER Whale Browser"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua)||Utils.getFirstMatch(/(?:whale)[\s/](\d+(?:\.\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/MZBrowser/i],describe(ua){const browser={name:"MZ Browser"};const version=Utils.getFirstMatch(/(?:MZBrowser)[\s/](\d+(?:\.\d+)+)/i,ua)||Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/focus/i],describe(ua){const browser={name:"Focus"};const version=Utils.getFirstMatch(/(?:focus)[\s/](\d+(?:\.\d+)+)/i,ua)||Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/swing/i],describe(ua){const browser={name:"Swing"};const version=Utils.getFirstMatch(/(?:swing)[\s/](\d+(?:\.\d+)+)/i,ua)||Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/coast/i],describe(ua){const browser={name:"Opera Coast"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua)||Utils.getFirstMatch(/(?:coast)[\s/](\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/opt\/\d+(?:.?_?\d+)+/i],describe(ua){const browser={name:"Opera Touch"};const version=Utils.getFirstMatch(/(?:opt)[\s/](\d+(\.?_?\d+)+)/i,ua)||Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/yabrowser/i],describe(ua){const browser={name:"Yandex Browser"};const version=Utils.getFirstMatch(/(?:yabrowser)[\s/](\d+(\.?_?\d+)+)/i,ua)||Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/ucbrowser/i],describe(ua){const browser={name:"UC Browser"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua)||Utils.getFirstMatch(/(?:ucbrowser)[\s/](\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/Maxthon|mxios/i],describe(ua){const browser={name:"Maxthon"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua)||Utils.getFirstMatch(/(?:Maxthon|mxios)[\s/](\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/epiphany/i],describe(ua){const browser={name:"Epiphany"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua)||Utils.getFirstMatch(/(?:epiphany)[\s/](\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/puffin/i],describe(ua){const browser={name:"Puffin"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua)||Utils.getFirstMatch(/(?:puffin)[\s/](\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/sleipnir/i],describe(ua){const browser={name:"Sleipnir"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua)||Utils.getFirstMatch(/(?:sleipnir)[\s/](\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/k-meleon/i],describe(ua){const browser={name:"K-Meleon"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua)||Utils.getFirstMatch(/(?:k-meleon)[\s/](\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/micromessenger/i],describe(ua){const browser={name:"WeChat"};const version=Utils.getFirstMatch(/(?:micromessenger)[\s/](\d+(\.?_?\d+)+)/i,ua)||Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/qqbrowser/i],describe(ua){const browser={name:/qqbrowserlite/i.test(ua)?"QQ Browser Lite":"QQ Browser"};const version=Utils.getFirstMatch(/(?:qqbrowserlite|qqbrowser)[/](\d+(\.?_?\d+)+)/i,ua)||Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/msie|trident/i],describe(ua){const browser={name:"Internet Explorer"};const version=Utils.getFirstMatch(/(?:msie |rv:)(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/\sedg\//i],describe(ua){const browser={name:"Microsoft Edge"};const version=Utils.getFirstMatch(/\sedg\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/edg([ea]|ios)/i],describe(ua){const browser={name:"Microsoft Edge"};const version=Utils.getSecondMatch(/edg([ea]|ios)\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/vivaldi/i],describe(ua){const browser={name:"Vivaldi"};const version=Utils.getFirstMatch(/vivaldi\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/seamonkey/i],describe(ua){const browser={name:"SeaMonkey"};const version=Utils.getFirstMatch(/seamonkey\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/sailfish/i],describe(ua){const browser={name:"Sailfish"};const version=Utils.getFirstMatch(/sailfish\s?browser\/(\d+(\.\d+)?)/i,ua);if(version){browser.version=version}return browser}},{test:[/silk/i],describe(ua){const browser={name:"Amazon Silk"};const version=Utils.getFirstMatch(/silk\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/phantom/i],describe(ua){const browser={name:"PhantomJS"};const version=Utils.getFirstMatch(/phantomjs\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/slimerjs/i],describe(ua){const browser={name:"SlimerJS"};const version=Utils.getFirstMatch(/slimerjs\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/blackberry|\bbb\d+/i,/rim\stablet/i],describe(ua){const browser={name:"BlackBerry"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua)||Utils.getFirstMatch(/blackberry[\d]+\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/(web|hpw)[o0]s/i],describe(ua){const browser={name:"WebOS Browser"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua)||Utils.getFirstMatch(/w(?:eb)?[o0]sbrowser\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/bada/i],describe(ua){const browser={name:"Bada"};const version=Utils.getFirstMatch(/dolfin\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/tizen/i],describe(ua){const browser={name:"Tizen"};const version=Utils.getFirstMatch(/(?:tizen\s?)?browser\/(\d+(\.?_?\d+)+)/i,ua)||Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/qupzilla/i],describe(ua){const browser={name:"QupZilla"};const version=Utils.getFirstMatch(/(?:qupzilla)[\s/](\d+(\.?_?\d+)+)/i,ua)||Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/firefox|iceweasel|fxios/i],describe(ua){const browser={name:"Firefox"};const version=Utils.getFirstMatch(/(?:firefox|iceweasel|fxios)[\s/](\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/electron/i],describe(ua){const browser={name:"Electron"};const version=Utils.getFirstMatch(/(?:electron)\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/MiuiBrowser/i],describe(ua){const browser={name:"Miui"};const version=Utils.getFirstMatch(/(?:MiuiBrowser)[\s/](\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/chromium/i],describe(ua){const browser={name:"Chromium"};const version=Utils.getFirstMatch(/(?:chromium)[\s/](\d+(\.?_?\d+)+)/i,ua)||Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/chrome|crios|crmo/i],describe(ua){const browser={name:"Chrome"};const version=Utils.getFirstMatch(/(?:chrome|crios|crmo)\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/GSA/i],describe(ua){const browser={name:"Google Search"};const version=Utils.getFirstMatch(/(?:GSA)\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test(parser){const notLikeAndroid=!parser.test(/like android/i);const butAndroid=parser.test(/android/i);return notLikeAndroid&&butAndroid},describe(ua){const browser={name:"Android Browser"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/playstation 4/i],describe(ua){const browser={name:"PlayStation 4"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/safari|applewebkit/i],describe(ua){const browser={name:"Safari"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/.*/i],describe(ua){const regexpWithoutDeviceSpec=/^(.*)\/(.*) /;const regexpWithDeviceSpec=/^(.*)\/(.*)[ \t]\((.*)/;const hasDeviceSpec=ua.search("\\(")!==-1;const regexp=hasDeviceSpec?regexpWithDeviceSpec:regexpWithoutDeviceSpec;return{name:Utils.getFirstMatch(regexp,ua),version:Utils.getSecondMatch(regexp,ua)}}}];var osParsersList=[{test:[/Roku\/DVP/],describe(ua){const version=Utils.getFirstMatch(/Roku\/DVP-(\d+\.\d+)/i,ua);return{name:OS_MAP.Roku,version:version}}},{test:[/windows phone/i],describe(ua){const version=Utils.getFirstMatch(/windows phone (?:os)?\s?(\d+(\.\d+)*)/i,ua);return{name:OS_MAP.WindowsPhone,version:version}}},{test:[/windows /i],describe(ua){const version=Utils.getFirstMatch(/Windows ((NT|XP)( \d\d?.\d)?)/i,ua);const versionName=Utils.getWindowsVersionName(version);return{name:OS_MAP.Windows,version:version,versionName:versionName}}},{test:[/Macintosh(.*?) FxiOS(.*?)\//],describe(ua){const result={name:OS_MAP.iOS};const version=Utils.getSecondMatch(/(Version\/)(\d[\d.]+)/,ua);if(version){result.version=version}return result}},{test:[/macintosh/i],describe(ua){const version=Utils.getFirstMatch(/mac os x (\d+(\.?_?\d+)+)/i,ua).replace(/[_\s]/g,".");const versionName=Utils.getMacOSVersionName(version);const os={name:OS_MAP.MacOS,version:version};if(versionName){os.versionName=versionName}return os}},{test:[/(ipod|iphone|ipad)/i],describe(ua){const version=Utils.getFirstMatch(/os (\d+([_\s]\d+)*) like mac os x/i,ua).replace(/[_\s]/g,".");return{name:OS_MAP.iOS,version:version}}},{test(parser){const notLikeAndroid=!parser.test(/like android/i);const butAndroid=parser.test(/android/i);return notLikeAndroid&&butAndroid},describe(ua){const version=Utils.getFirstMatch(/android[\s/-](\d+(\.\d+)*)/i,ua);const versionName=Utils.getAndroidVersionName(version);const os={name:OS_MAP.Android,version:version};if(versionName){os.versionName=versionName}return os}},{test:[/(web|hpw)[o0]s/i],describe(ua){const version=Utils.getFirstMatch(/(?:web|hpw)[o0]s\/(\d+(\.\d+)*)/i,ua);const os={name:OS_MAP.WebOS};if(version&&version.length){os.version=version}return os}},{test:[/blackberry|\bbb\d+/i,/rim\stablet/i],describe(ua){const version=Utils.getFirstMatch(/rim\stablet\sos\s(\d+(\.\d+)*)/i,ua)||Utils.getFirstMatch(/blackberry\d+\/(\d+([_\s]\d+)*)/i,ua)||Utils.getFirstMatch(/\bbb(\d+)/i,ua);return{name:OS_MAP.BlackBerry,version:version}}},{test:[/bada/i],describe(ua){const version=Utils.getFirstMatch(/bada\/(\d+(\.\d+)*)/i,ua);return{name:OS_MAP.Bada,version:version}}},{test:[/tizen/i],describe(ua){const version=Utils.getFirstMatch(/tizen[/\s](\d+(\.\d+)*)/i,ua);return{name:OS_MAP.Tizen,version:version}}},{test:[/linux/i],describe(){return{name:OS_MAP.Linux}}},{test:[/CrOS/],describe(){return{name:OS_MAP.ChromeOS}}},{test:[/PlayStation 4/],describe(ua){const version=Utils.getFirstMatch(/PlayStation 4[/\s](\d+(\.\d+)*)/i,ua);return{name:OS_MAP.PlayStation4,version:version}}}];var platformParsersList=[{test:[/googlebot/i],describe(){return{type:"bot",vendor:"Google"}}},{test:[/huawei/i],describe(ua){const model=Utils.getFirstMatch(/(can-l01)/i,ua)&&"Nova";const platform={type:PLATFORMS_MAP.mobile,vendor:"Huawei"};if(model){platform.model=model}return platform}},{test:[/nexus\s*(?:7|8|9|10).*/i],describe(){return{type:PLATFORMS_MAP.tablet,vendor:"Nexus"}}},{test:[/ipad/i],describe(){return{type:PLATFORMS_MAP.tablet,vendor:"Apple",model:"iPad"}}},{test:[/Macintosh(.*?) FxiOS(.*?)\//],describe(){return{type:PLATFORMS_MAP.tablet,vendor:"Apple",model:"iPad"}}},{test:[/kftt build/i],describe(){return{type:PLATFORMS_MAP.tablet,vendor:"Amazon",model:"Kindle Fire HD 7"}}},{test:[/silk/i],describe(){return{type:PLATFORMS_MAP.tablet,vendor:"Amazon"}}},{test:[/tablet(?! pc)/i],describe(){return{type:PLATFORMS_MAP.tablet}}},{test(parser){const iDevice=parser.test(/ipod|iphone/i);const likeIDevice=parser.test(/like (ipod|iphone)/i);return iDevice&&!likeIDevice},describe(ua){const model=Utils.getFirstMatch(/(ipod|iphone)/i,ua);return{type:PLATFORMS_MAP.mobile,vendor:"Apple",model:model}}},{test:[/nexus\s*[0-6].*/i,/galaxy nexus/i],describe(){return{type:PLATFORMS_MAP.mobile,vendor:"Nexus"}}},{test:[/[^-]mobi/i],describe(){return{type:PLATFORMS_MAP.mobile}}},{test(parser){return parser.getBrowserName(true)==="blackberry"},describe(){return{type:PLATFORMS_MAP.mobile,vendor:"BlackBerry"}}},{test(parser){return parser.getBrowserName(true)==="bada"},describe(){return{type:PLATFORMS_MAP.mobile}}},{test(parser){return parser.getBrowserName()==="windows phone"},describe(){return{type:PLATFORMS_MAP.mobile,vendor:"Microsoft"}}},{test(parser){const osMajorVersion=Number(String(parser.getOSVersion()).split(".")[0]);return parser.getOSName(true)==="android"&&osMajorVersion>=3},describe(){return{type:PLATFORMS_MAP.tablet}}},{test(parser){return parser.getOSName(true)==="android"},describe(){return{type:PLATFORMS_MAP.mobile}}},{test(parser){return parser.getOSName(true)==="macos"},describe(){return{type:PLATFORMS_MAP.desktop,vendor:"Apple"}}},{test(parser){return parser.getOSName(true)==="windows"},describe(){return{type:PLATFORMS_MAP.desktop}}},{test(parser){return parser.getOSName(true)==="linux"},describe(){return{type:PLATFORMS_MAP.desktop}}},{test(parser){return parser.getOSName(true)==="playstation 4"},describe(){return{type:PLATFORMS_MAP.tv}}},{test(parser){return parser.getOSName(true)==="roku"},describe(){return{type:PLATFORMS_MAP.tv}}}];var enginesParsersList=[{test(parser){return parser.getBrowserName(true)==="microsoft edge"},describe(ua){const isBlinkBased=/\sedg\//i.test(ua);if(isBlinkBased){return{name:ENGINE_MAP.Blink}}const version=Utils.getFirstMatch(/edge\/(\d+(\.?_?\d+)+)/i,ua);return{name:ENGINE_MAP.EdgeHTML,version:version}}},{test:[/trident/i],describe(ua){const engine={name:ENGINE_MAP.Trident};const version=Utils.getFirstMatch(/trident\/(\d+(\.?_?\d+)+)/i,ua);if(version){engine.version=version}return engine}},{test(parser){return parser.test(/presto/i)},describe(ua){const engine={name:ENGINE_MAP.Presto};const version=Utils.getFirstMatch(/presto\/(\d+(\.?_?\d+)+)/i,ua);if(version){engine.version=version}return engine}},{test(parser){const isGecko=parser.test(/gecko/i);const likeGecko=parser.test(/like gecko/i);return isGecko&&!likeGecko},describe(ua){const engine={name:ENGINE_MAP.Gecko};const version=Utils.getFirstMatch(/gecko\/(\d+(\.?_?\d+)+)/i,ua);if(version){engine.version=version}return engine}},{test:[/(apple)?webkit\/537\.36/i],describe(){return{name:ENGINE_MAP.Blink}}},{test:[/(apple)?webkit/i],describe(ua){const engine={name:ENGINE_MAP.WebKit};const version=Utils.getFirstMatch(/webkit\/(\d+(\.?_?\d+)+)/i,ua);if(version){engine.version=version}return engine}}];class Parser{constructor(UA,skipParsing=false){if(UA===void 0||UA===null||UA===""){throw new Error("UserAgent parameter can't be empty")}this._ua=UA;this.parsedResult={};if(skipParsing!==true){this.parse()}}getUA(){return this._ua}test(regex){return regex.test(this._ua)}parseBrowser(){this.parsedResult.browser={};const browserDescriptor=Utils.find(browsersList,_browser=>{if(typeof _browser.test==="function"){return _browser.test(this)}if(_browser.test instanceof Array){return _browser.test.some(condition=>this.test(condition))}throw new Error("Browser's test function is not valid")});if(browserDescriptor){this.parsedResult.browser=browserDescriptor.describe(this.getUA())}return this.parsedResult.browser}getBrowser(){if(this.parsedResult.browser){return this.parsedResult.browser}return this.parseBrowser()}getBrowserName(toLowerCase){if(toLowerCase){return String(this.getBrowser().name).toLowerCase()||""}return this.getBrowser().name||""}getBrowserVersion(){return this.getBrowser().version}getOS(){if(this.parsedResult.os){return this.parsedResult.os}return this.parseOS()}parseOS(){this.parsedResult.os={};const os=Utils.find(osParsersList,_os=>{if(typeof _os.test==="function"){return _os.test(this)}if(_os.test instanceof Array){return _os.test.some(condition=>this.test(condition))}throw new Error("Browser's test function is not valid")});if(os){this.parsedResult.os=os.describe(this.getUA())}return this.parsedResult.os}getOSName(toLowerCase){const{name:name}=this.getOS();if(toLowerCase){return String(name).toLowerCase()||""}return name||""}getOSVersion(){return this.getOS().version}getPlatform(){if(this.parsedResult.platform){return this.parsedResult.platform}return this.parsePlatform()}getPlatformType(toLowerCase=false){const{type:type}=this.getPlatform();if(toLowerCase){return String(type).toLowerCase()||""}return type||""}parsePlatform(){this.parsedResult.platform={};const platform=Utils.find(platformParsersList,_platform=>{if(typeof _platform.test==="function"){return _platform.test(this)}if(_platform.test instanceof Array){return _platform.test.some(condition=>this.test(condition))}throw new Error("Browser's test function is not valid")});if(platform){this.parsedResult.platform=platform.describe(this.getUA())}return this.parsedResult.platform}getEngine(){if(this.parsedResult.engine){return this.parsedResult.engine}return this.parseEngine()}getEngineName(toLowerCase){if(toLowerCase){return String(this.getEngine().name).toLowerCase()||""}return this.getEngine().name||""}parseEngine(){this.parsedResult.engine={};const engine=Utils.find(enginesParsersList,_engine=>{if(typeof _engine.test==="function"){return _engine.test(this)}if(_engine.test instanceof Array){return _engine.test.some(condition=>this.test(condition))}throw new Error("Browser's test function is not valid")});if(engine){this.parsedResult.engine=engine.describe(this.getUA())}return this.parsedResult.engine}parse(){this.parseBrowser();this.parseOS();this.parsePlatform();this.parseEngine();return this}getResult(){return Utils.assign({},this.parsedResult)}satisfies(checkTree){const platformsAndOSes={};let platformsAndOSCounter=0;const browsers={};let browsersCounter=0;const allDefinitions=Object.keys(checkTree);allDefinitions.forEach(key=>{const currentDefinition=checkTree[key];if(typeof currentDefinition==="string"){browsers[key]=currentDefinition;browsersCounter+=1}else if(typeof currentDefinition==="object"){platformsAndOSes[key]=currentDefinition;platformsAndOSCounter+=1}});if(platformsAndOSCounter>0){const platformsAndOSNames=Object.keys(platformsAndOSes);const OSMatchingDefinition=Utils.find(platformsAndOSNames,name=>this.isOS(name));if(OSMatchingDefinition){const osResult=this.satisfies(platformsAndOSes[OSMatchingDefinition]);if(osResult!==void 0){return osResult}}const platformMatchingDefinition=Utils.find(platformsAndOSNames,name=>this.isPlatform(name));if(platformMatchingDefinition){const platformResult=this.satisfies(platformsAndOSes[platformMatchingDefinition]);if(platformResult!==void 0){return platformResult}}}if(browsersCounter>0){const browserNames=Object.keys(browsers);const matchingDefinition=Utils.find(browserNames,name=>this.isBrowser(name,true));if(matchingDefinition!==void 0){return this.compareVersion(browsers[matchingDefinition])}}return undefined}isBrowser(browserName,includingAlias=false){const defaultBrowserName=this.getBrowserName().toLowerCase();let browserNameLower=browserName.toLowerCase();const alias=Utils.getBrowserTypeByAlias(browserNameLower);if(includingAlias&&alias){browserNameLower=alias.toLowerCase()}return browserNameLower===defaultBrowserName}compareVersion(version){let expectedResults=[0];let comparableVersion=version;let isLoose=false;const currentBrowserVersion=this.getBrowserVersion();if(typeof currentBrowserVersion!=="string"){return void 0}if(version[0]===">"||version[0]==="<"){comparableVersion=version.substr(1);if(version[1]==="="){isLoose=true;comparableVersion=version.substr(2)}else{expectedResults=[]}if(version[0]===">"){expectedResults.push(1)}else{expectedResults.push(-1)}}else if(version[0]==="="){comparableVersion=version.substr(1)}else if(version[0]==="~"){isLoose=true;comparableVersion=version.substr(1)}return expectedResults.indexOf(Utils.compareVersions(currentBrowserVersion,comparableVersion,isLoose))>-1}isOS(osName){return this.getOSName(true)===String(osName).toLowerCase()}isPlatform(platformType){return this.getPlatformType(true)===String(platformType).toLowerCase()}isEngine(engineName){return this.getEngineName(true)===String(engineName).toLowerCase()}is(anything,includingAlias=false){return this.isBrowser(anything,includingAlias)||this.isOS(anything)||this.isPlatform(anything)}some(anythings=[]){return anythings.some(anything=>this.is(anything))}}class Bowser{static getParser(UA,skipParsing=false){if(typeof UA!=="string"){throw new Error("UserAgent should be a string")}return new Parser(UA,skipParsing)}static parse(UA){return new Parser(UA).getResult()}static get BROWSER_MAP(){return BROWSER_MAP}static get ENGINE_MAP(){return ENGINE_MAP}static get OS_MAP(){return OS_MAP}static get PLATFORMS_MAP(){return PLATFORMS_MAP}}function _classCallCheck(a,n){if(!(a instanceof n))throw new TypeError("Cannot call a class as a function")}function _defineProperties(e,r){for(var t=0;t=this._data.length){return undefined}var res=this._data.slice(this._pos,this._pos+bytes);this._pos+=bytes;return res}},{key:"set",value:function set(pos,data){this._pos=pos;this._data=data}},{key:"clear",value:function clear(){this._pos=0;this._data=new Uint8Array}}])}();var PvFileIDB=function(_PvFile){function PvFileIDB(path,meta,db,mode){var _this;_classCallCheck(this,PvFileIDB);_this=_callSuper$1(this,PvFileIDB);_this._pageSize=512*1024;_this._pagePtr=0;_this._pageOffset=0;_this._path=path;_this._meta=meta;_this._db=db;_this._mode=mode;_this._cache=new PvCache;return _this}_inherits(PvFileIDB,_PvFile);return _createClass(PvFileIDB,[{key:"pageSize",get:function get(){return this._pageSize}},{key:"close",value:function(){var _close=_asyncToGenerator(_regeneratorRuntime.mark(function _callee(){return _regeneratorRuntime.wrap(function _callee$(_context){while(1)switch(_context.prev=_context.next){case 0:this._db.close();case 1:case"end":return _context.stop()}},_callee,this)}));function close(){return _close.apply(this,arguments)}return close}()},{key:"read",value:function(){var _read=_asyncToGenerator(_regeneratorRuntime.mark(function _callee2(size,count){var _this2=this;return _regeneratorRuntime.wrap(function _callee2$(_context2){while(1)switch(_context2.prev=_context2.next){case 0:return _context2.abrupt("return",new Promise(function(resolve,reject){if(!_this2.exists()){reject(new Error("'".concat(_this2._path,"' doesn't exist.")));return}if(_this2._isEOF){var err=new Error("EOF");err.name="EndOfFile";reject(err);return}var copied=0;var maxToCopy=Math.min(size*count,_this2._meta.size);var totalElems=maxToCopy-maxToCopy%size;var buffer=new Uint8Array(totalElems);var res=_this2._cache.get(totalElems);if(res){copied+=res.length;_this2._pageOffset+=res.length;if(_this2._pageOffset===_this2._pageSize){_this2._pagePtr+=1;_this2._pageOffset=0}if(totalElems===copied){resolve(res);return}buffer.set(res)}var keyRange=IDBKeyRange.bound("".concat(_this2._path,"-").concat(PvFileIDB.createPage(_this2._pagePtr)),"".concat(_this2._path,"-").concat(PvFileIDB.createPage(_this2._pagePtr+Math.floor(totalElems/_this2._pageSize)+1)));var store=_this2._store;var req=store.openCursor(keyRange);req.onsuccess=function(){var cursor=req.result;if(!cursor||_this2._isEOF){return}var toCopy=Math.min(totalElems-copied,cursor.value.length-_this2._pageOffset);buffer.set(cursor.value.slice(_this2._pageOffset,_this2._pageOffset+toCopy),copied);copied+=toCopy;_this2._pageOffset+=toCopy;if(_this2._pageOffset===_this2._pageSize){_this2._pagePtr+=1;_this2._pageOffset=0}if(copied1&&_args4[1]!==undefined?_args4[1]:1;return _context4.abrupt("return",new Promise(function(){var _ref=_asyncToGenerator(_regeneratorRuntime.mark(function _callee3(resolve,reject){var _store$transaction3;var store,getCurrentPage,last,newContent,newSize,newMeta,pages,i,keyRange,_store$transaction4;return _regeneratorRuntime.wrap(function _callee3$(_context3){while(1)switch(_context3.prev=_context3.next){case 0:if(!(_this3._mode==="readonly")){_context3.next=3;break}reject(new Error("Instance is readonly mode only."));return _context3.abrupt("return");case 3:if(!(typeof version!=="number"&&version<=0)){_context3.next=6;break}reject(new Error("Version should be a positive number"));return _context3.abrupt("return");case 6:store=_this3._store;getCurrentPage=function getCurrentPage(){return new Promise(function(res){var req=store.get("".concat(_this3._path,"-").concat(PvFileIDB.createPage(_this3._pagePtr)));req.onsuccess=function(){if(req.result!==undefined){res(req.result.slice(0,_this3._pageOffset))}else{res(new Uint8Array(0))}}})};_context3.next=10;return getCurrentPage();case 10:last=_context3.sent;newContent=new Uint8Array(last.length+content.length);newContent.set(last);newContent.set(content,last.length);newSize=_this3._pagePtr*_this3._pageSize+newContent.length;newMeta={size:newSize,numPages:Math.ceil(newSize/_this3._pageSize),version:version,pageSize:_this3._pageSize};store.put(newMeta,_this3._path);pages=Math.ceil(newContent.length/_this3._pageSize);for(i=0;i=this._meta.numPages-1&&this._pageOffset>=this._meta.size%this._pageSize}},{key:"_store",get:function get(){return this._db.transaction(PV_FILE_STORE,this._mode).objectStore(PV_FILE_STORE)}}],[{key:"open",value:function open(path,mode){if(!self.indexedDB){var error=new Error("IndexedDB is not supported");error.name="IndexedDBNotSupported";throw error}return new Promise(function(){var _ref3=_asyncToGenerator(_regeneratorRuntime.mark(function _callee7(resolve,reject){var db,req,_error2;return _regeneratorRuntime.wrap(function _callee7$(_context7){while(1)switch(_context7.prev=_context7.next){case 0:_context7.prev=0;_context7.next=3;return getDB();case 3:db=_context7.sent;req=db.transaction(PV_FILE_STORE,"readwrite").objectStore(PV_FILE_STORE).get(path);req.onerror=function(){reject(req.error)};req.onsuccess=function(){var meta=req.result;var dbMode=mode.includes("r")?"readonly":"readwrite";if(meta===undefined&&dbMode==="readonly"){var _error=new Error("'".concat(path,"' doesn't exist."));_error.name="FileNotExists";reject(_error);return}var fileIDB=new PvFileIDB(path,meta,db,dbMode);if(mode.includes("a")){fileIDB.seek(0,2)}resolve(fileIDB)};_context7.next=12;break;case 9:_context7.prev=9;_context7.t0=_context7["catch"](0);if(_context7.t0.name==="InvalidStateError"){_error2=new Error("IndexedDB is not supported");_error2.name="IndexedDBNotSupported";reject(_error2)}else{reject(_context7.t0)}case 12:case"end":return _context7.stop()}},_callee7,null,[[0,9]])}));return function(_x8,_x9){return _ref3.apply(this,arguments)}}())}},{key:"createPage",value:function createPage(page){return("00000"+page).slice(-6)}}])}(PvFile);function _callSuper(t,o,e){return o=_getPrototypeOf(o),_possibleConstructorReturn(t,_isNativeReflectConstruct()?Reflect.construct(o,e||[],_getPrototypeOf(t).constructor):o.apply(t,e))}function _isNativeReflectConstruct(){try{var t=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch(t){}return(_isNativeReflectConstruct=function _isNativeReflectConstruct(){return!!t})()}var PvFileMem=function(_PvFile){function PvFileMem(path,meta,db,mode){var _this;_classCallCheck(this,PvFileMem);_this=_callSuper(this,PvFileMem);_this._pos=0;_this._path=path;_this._meta=meta;_this._mode=mode;return _this}_inherits(PvFileMem,_PvFile);return _createClass(PvFileMem,[{key:"close",value:function close(){return}},{key:"read",value:function read(size,count){if(!this.exists()){throw new Error("'".concat(this._path,"' doesn't exist."))}if(this._isEOF){var err=new Error("EOF");err.name="EndOfFile";throw err}var toCopy=Math.min(size*count,this._file.length-this._pos);var totalElems=toCopy-toCopy%size;var buffer=new Uint8Array(totalElems);buffer.set(this._file.slice(this._pos,this._pos+totalElems),0);this._pos+=totalElems;return buffer}},{key:"write",value:function write(content){var version=arguments.length>1&&arguments[1]!==undefined?arguments[1]:1;var newFile=new Uint8Array(this._pos+content.length);if(this._file!==undefined){newFile.set(this._file.slice(0,this._pos));newFile.set(content,this._pos)}else{newFile.set(content)}this._file=newFile;this._pos+=content.length}},{key:"seek",value:function seek(offset,whence){if(!this.exists()&&this._mode==="readonly"){throw new Error("'".concat(this._path,"' doesn't exist."))}if(!this.exists()){throw new Error("'".concat(this._path,"' doesn't exist."))}if(offset<0){var err=new Error("EOF");err.name="EndOfFile";throw err}var newOffset;if(whence===0){newOffset=Math.min(offset,this._file.length)}else if(whence===1){newOffset=Math.min(this._pos+offset,this._file.length)}else if(whence===2){newOffset=Math.min(this._file.length+offset,this._file.length)}else{throw new Error("Invalid operation: ".concat(whence,"."))}this._pos=newOffset}},{key:"tell",value:function tell(){if(!this.exists()){return-1}return this._pos}},{key:"remove",value:function(){var _remove=_asyncToGenerator(_regeneratorRuntime.mark(function _callee(){return _regeneratorRuntime.wrap(function _callee$(_context){while(1)switch(_context.prev=_context.next){case 0:if(this.exists()){_context.next=2;break}throw new Error("ENOENT");case 2:PvFileMem._memFiles["delete"](this._path);this._pos=0;case 4:case"end":return _context.stop()}},_callee,this)}));function remove(){return _remove.apply(this,arguments)}return remove}()},{key:"exists",value:function exists(){return this._file!==undefined}},{key:"_isEOF",get:function get(){return this._pos>=this._file.length}},{key:"_file",get:function get(){return PvFileMem._memFiles.get(this._path)},set:function set(content){PvFileMem._memFiles.set(this._path,content)}}],[{key:"open",value:function open(path,mode){var file=PvFileMem._memFiles.get(path);var dbMode=mode.includes("r")?"readonly":"readwrite";if(file===undefined&&dbMode==="readonly"){var error=new Error("'".concat(path,"' doesn't exist."));error.name="FileNotExists";throw error}var fileMem=new PvFileMem(path,undefined,undefined,dbMode);if(mode.includes("a")){fileMem.seek(0,2)}return fileMem}}])}(PvFile);PvFileMem._memFiles=new Map;function unsignedAddress(address){if(address<0){return address>>>0}return address}function _arrayWithHoles(r){if(Array.isArray(r))return r}function _iterableToArrayLimit(r,l){var t=null==r?null:"undefined"!=typeof Symbol&&r[Symbol.iterator]||r["@@iterator"];if(null!=t){var e,n,i,u,a=[],f=!0,o=!1;try{if(i=(t=t.call(r)).next,0===l){if(Object(t)!==t)return;f=!1}else for(;!(f=(e=i.call(t)).done)&&(a.push(e.value),a.length!==l);f=!0);}catch(r){o=!0,n=r}finally{try{if(!f&&null!=t["return"]&&(u=t["return"](),Object(u)!==u))return}finally{if(o)throw n}}return a}}function _arrayLikeToArray$2(r,a){(null==a||a>r.length)&&(a=r.length);for(var e=0,n=Array(a);e=r.length?{done:!0}:{done:!1,value:r[_n++]}},e:function e(r){throw r},f:F}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,a=!0,u=!1;return{s:function s(){t=t.call(r)},n:function n(){var r=t.next();return a=r.done,r},e:function e(r){u=!0,o=r},f:function f(){try{a||null==t["return"]||t["return"]()}finally{if(u)throw o}}}}function _unsupportedIterableToArray$1(r,a){if(r){if("string"==typeof r)return _arrayLikeToArray$1(r,a);var t={}.toString.call(r).slice(8,-1);return"Object"===t&&r.constructor&&(t=r.constructor.name),"Map"===t||"Set"===t?Array.from(r):"Arguments"===t||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t)?_arrayLikeToArray$1(r,a):void 0}}function _arrayLikeToArray$1(r,a){(null==a||a>r.length)&&(a=r.length);for(var e=0,n=Array(a);e=16){this.endComputePass();this.flushCommandEncoder()}}},{key:"endComputePass",value:function endComputePass(){if(this._passEncoder){this._passEncoder.end();this._passEncoder=null}}},{key:"getBuffer",value:function getBuffer(sizeBytes,usage){var mappedAtCreation=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var label=arguments.length>3?arguments[3]:undefined;var key=this.getBufferKey(sizeBytes,usage);if(this.bufferReusePool.has(key)){var buffers=this.bufferReusePool.get(key);if(buffers&&buffers.length>0){return buffers.pop()}}return this.device.createBuffer({size:sizeBytes*Uint8Array.BYTES_PER_ELEMENT,usage:usage,mappedAtCreation:mappedAtCreation,label:label})}},{key:"scheduleUniformBufferForRelease",value:function scheduleUniformBufferForRelease(buffer){this._uniformBuffersPendingRelease.push(buffer)}},{key:"releaseBuffer",value:function releaseBuffer(buffer){var clearBuffer=arguments.length>1&&arguments[1]!==undefined?arguments[1]:true;if(clearBuffer){this.endComputePass();this.commandEncoder.clearBuffer(buffer,0,buffer.size)}var key=this.getBufferKey(buffer.size,buffer.usage);if(!this.bufferReusePool.has(key)){this.bufferReusePool.set(key,[])}this.bufferReusePool.get(key).push(buffer)}},{key:"sync",value:function(){var _sync=_asyncToGenerator(_regeneratorRuntime.mark(function _callee(){var _this=this;var _iterator,_step,k,buffers,_iterator3,_step3,b,_loop,_i,_Object$entries;return _regeneratorRuntime.wrap(function _callee$(_context3){while(1)switch(_context3.prev=_context3.next){case 0:this.endComputePass();this.flushCommandEncoder();_context3.next=4;return this.device.queue.onSubmittedWorkDone();case 4:_iterator=_createForOfIteratorHelper$1(this.bufferReusePool.keys());try{for(_iterator.s();!(_step=_iterator.n()).done;){k=_step.value;buffers=this.bufferReusePool.get(k);if(buffers&&buffers.length>0){_iterator3=_createForOfIteratorHelper$1(buffers);try{for(_iterator3.s();!(_step3=_iterator3.n()).done;){b=_step3.value;b===null||b===void 0||b.destroy()}}catch(err){_iterator3.e(err)}finally{_iterator3.f()}}}}catch(err){_iterator.e(err)}finally{_iterator.f()}this.bufferReusePool.clear();_loop=_regeneratorRuntime.mark(function _loop(){var _Object$entries$_i,shaderName,timestampBuffers,_iterator2,_step2,_loop2;return _regeneratorRuntime.wrap(function _loop$(_context2){while(1)switch(_context2.prev=_context2.next){case 0:_Object$entries$_i=_slicedToArray(_Object$entries[_i],2),shaderName=_Object$entries$_i[0],timestampBuffers=_Object$entries$_i[1];if(!_this.shaderTimes[shaderName]){_this.shaderTimes[shaderName]=[]}_iterator2=_createForOfIteratorHelper$1(timestampBuffers);_context2.prev=3;_loop2=_regeneratorRuntime.mark(function _loop2(){var timestampBuffer;return _regeneratorRuntime.wrap(function _loop2$(_context){while(1)switch(_context.prev=_context.next){case 0:timestampBuffer=_step2.value;timestampBuffer.mapAsync(GPUMapMode.READ).then(function(){var times=new BigInt64Array(timestampBuffer.getMappedRange());var timeDif=times[1]-times[0];timestampBuffer.unmap();timestampBuffer.destroy();_this.shaderTimes[shaderName].push(timeDif)});case 2:case"end":return _context.stop()}},_loop2)});_iterator2.s();case 6:if((_step2=_iterator2.n()).done){_context2.next=10;break}return _context2.delegateYield(_loop2(),"t0",8);case 8:_context2.next=6;break;case 10:_context2.next=15;break;case 12:_context2.prev=12;_context2.t1=_context2["catch"](3);_iterator2.e(_context2.t1);case 15:_context2.prev=15;_iterator2.f();return _context2.finish(15);case 18:case"end":return _context2.stop()}},_loop,null,[[3,12,15,18]])});_i=0,_Object$entries=Object.entries(this.timestampBuffers);case 9:if(!(_i<_Object$entries.length)){_context3.next=14;break}return _context3.delegateYield(_loop(),"t0",11);case 11:_i++;_context3.next=9;break;case 14:this.timestampBuffers={};case 15:case"end":return _context3.stop()}},_callee,this)}));function sync(){return _sync.apply(this,arguments)}return sync}()},{key:"reportShaderTimes",value:function reportShaderTimes(){for(var _i2=0,_Object$entries2=Object.entries(this.shaderTimes);_i2<_Object$entries2.length;_i2++){var _Object$entries2$_i=_slicedToArray(_Object$entries2[_i2],2),shaderName=_Object$entries2$_i[0],shaderTimes=_Object$entries2$_i[1];var timeSum=0n;var _iterator4=_createForOfIteratorHelper$1(shaderTimes),_step4;try{for(_iterator4.s();!(_step4=_iterator4.n()).done;){var shaderTime=_step4.value;timeSum=timeSum+shaderTime}}catch(err){_iterator4.e(err)}finally{_iterator4.f()}var totalSeconds=Number(timeSum)*1e-9;var avgSeconds=(totalSeconds/shaderTimes.length).toFixed(7);console.log("".concat(shaderName,", ").concat(totalSeconds.toFixed(5),", ").concat(avgSeconds))}this.shaderTimes={}}},{key:"flushCommandEncoder",value:function flushCommandEncoder(){var _this2=this;this.device.queue.submit([this.commandEncoder.finish()]);this._commandEncoder=null;this._numCommandsEncoded=0;this._stageBuffersPendingMap.forEach(function(buffer){buffer.destroy()});this._stageBuffersPendingMap=[];this._uniformBuffersPendingRelease.forEach(function(buffer){_this2.releaseBuffer(buffer,false)});this._uniformBuffersPendingRelease=[]}},{key:"writeBuffer",value:function writeBuffer(sizeBytes,offset,srcArray,dstBuffer){var stagingBuffer=this.getBuffer(sizeBytes,GPUBufferUsage.MAP_WRITE|GPUBufferUsage.COPY_SRC,true);new Uint8Array(stagingBuffer.getMappedRange()).set(srcArray);stagingBuffer.unmap();this._stageBuffersPendingMap.push(stagingBuffer);this.endComputePass();this.commandEncoder.copyBufferToBuffer(stagingBuffer,0,dstBuffer,offset,sizeBytes);this.numCommandsEncoded++}},{key:"dispatchComputerShader",value:function dispatchComputerShader(bindGroup,pipeline,shaderName,workgroupCountX,workgroupCountY,workgroupCountZ){if(this.isTimerEnabled){var querySet=this.device.createQuerySet({type:"timestamp",count:2});var timestampWrites={querySet:querySet,beginningOfPassWriteIndex:0,endOfPassWriteIndex:1};this.endComputePass();this._passEncoder=this.commandEncoder.beginComputePass({timestampWrites:timestampWrites});this._passEncoder.setBindGroup(0,bindGroup);this._passEncoder.setPipeline(pipeline);this._passEncoder.dispatchWorkgroups(workgroupCountX,workgroupCountY,workgroupCountZ);this.endComputePass();var size=2*BigInt64Array.BYTES_PER_ELEMENT;var resolveBuffer=this.device.createBuffer({size:size,usage:GPUBufferUsage.QUERY_RESOLVE|GPUBufferUsage.COPY_SRC});this.commandEncoder.resolveQuerySet(querySet,0,2,resolveBuffer,0);var resultBuffer=this.device.createBuffer({size:size,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ});this.commandEncoder.copyBufferToBuffer(resolveBuffer,0,resultBuffer,0,size);if(!this.timestampBuffers[shaderName]){this.timestampBuffers[shaderName]=[]}this.timestampBuffers[shaderName].push(resultBuffer);this.numCommandsEncoded+=3}else{if(!this._passEncoder){this._passEncoder=this.commandEncoder.beginComputePass()}this._passEncoder.setBindGroup(0,bindGroup);this._passEncoder.setPipeline(pipeline);this._passEncoder.dispatchWorkgroups(workgroupCountX,workgroupCountY,workgroupCountZ);this.numCommandsEncoded++}}}])}();var PV_PICOLLM_WEBGPU_DEFAULT_WORKGROUP_SIZE=256;var gpuDevices=new Map;var gpuBuffers=new Map;var emptyShader="\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main_empty() {}\n";var shaderEntryPoint="main";var PRECOMPUTE_ENCODING_SHADER_NAME="pv_picollm_attention_precompute_encoding_shader";var attentionPrecomputeEncodingShaderSource="\nstruct argsStruct {\n dimension: u32,\n steps: u32,\n theta: f32,\n encoding_offset: u32,\n rope_scale: f32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar encoding: array;\n\n@group(0) @binding(2)\nvar rope_scales: array;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(\n @builtin(local_invocation_id) local_id: vec3,\n @builtin(workgroup_id) workgroup_id: vec3,\n @builtin(num_workgroups) num_workgroups: vec3\n) {\n let ts = workgroup_id.x;\n let ds = local_id.x;\n \n for (var t = ts; t < args.steps; t += num_workgroups.x) {\n for (var d = ds; d < (args.dimension / 2u); d += workgroup_size_x) {\n let f = 2u * d;\n let x = f32(t) / (f32(rope_scales[f >> 1]) * pow(args.theta, f32(f) / f32(args.dimension)));\n let encoding_idx = args.encoding_offset + (t * args.dimension) + f;\n encoding[encoding_idx] = cos(x) * args.rope_scale;\n encoding[encoding_idx + 1] = sin(x) * args.rope_scale;\n }\n }\n}\n\n".concat(emptyShader);var loadAttentionPrecomputeEncodingShader=function loadAttentionPrecomputeEncodingShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"attention precompute encoding bind group layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"attention precompute encoding pipeline layout",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"attention precompute encoding shader module",code:attentionPrecomputeEncodingShaderSource});var computePipeline=device.createComputePipeline({label:"attention precompute encoding pipeline",layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint,constants:{workgroup_size_x:PV_PICOLLM_WEBGPU_DEFAULT_WORKGROUP_SIZE}}});return{computePipeline:computePipeline}};var ENCODE_ROPE_INTERLEAVED_SHADER_NAME="pv_picollm_attention_encode_rope_interleaved_shader";var attentionEncodeRopeInterleavedShaderSource="\nstruct argsStruct { \n n: u32,\n num_heads: u32,\n head_dimension: u32,\n rope_dimension: u32,\n position: u32,\n encoding_offset: u32,\n x_offset: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar encoding: array;\n\n@group(0) @binding(2)\nvar x: array;\n \noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(\n @builtin(local_invocation_id) local_id: vec3,\n @builtin(workgroup_id) workgroup_id: vec3,\n @builtin(num_workgroups) num_workgroups: vec3\n) {\n let ts = workgroup_id.x;\n let h = workgroup_id.y;\n let ds = local_id.x;\n\n for (var t = ts; t < args.n; t += num_workgroups.x) {\n let x_start = args.x_offset + (t * args.num_heads + h) * args.head_dimension;\n let encoding_start = args.encoding_offset + ((t + args.position) * args.rope_dimension); \n for (var d = ds; d < (args.head_dimension / 2u); d += workgroup_size_x) {\n let i = 2u * d;\n let x_idx = x_start + i;\n let encoding_idx = encoding_start + i;\n \n let re = x[x_idx];\n let im = x[x_idx + 1];\n x[x_idx] = (re * encoding[encoding_idx]) - (im * encoding[encoding_idx + 1]);\n x[x_idx + 1] = (re * encoding[encoding_idx + 1]) + (im * encoding[encoding_idx]);\n }\n }\n}\n\n".concat(emptyShader);var loadAttentionEncodeRopeInterleavedShader=function loadAttentionEncodeRopeInterleavedShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"attention encode rope interleave bind group layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"attention encode rope interleave pipeline layout",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"attention encode rope interleave shader module",code:attentionEncodeRopeInterleavedShaderSource});var computePipeline=device.createComputePipeline({label:"attention encode rope interleave pipeline",layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint,constants:{workgroup_size_x:PV_PICOLLM_WEBGPU_DEFAULT_WORKGROUP_SIZE}}});return{computePipeline:computePipeline}};var ENCODE_SHADER_NAME="pv_picollm_attention_encode_shader";var attentionEncodeShaderSource="\nstruct argsStruct { \n n: u32,\n num_heads: u32,\n head_dimension: u32,\n rope_dimension: u32,\n position: u32,\n encoding_offset: u32,\n x_offset: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar encoding: array;\n\n@group(0) @binding(2)\nvar x: array;\n \noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(\n @builtin(local_invocation_id) local_id: vec3,\n @builtin(workgroup_id) workgroup_id: vec3,\n @builtin(num_workgroups) num_workgroups: vec3\n) {\n let ts = workgroup_id.x;\n let h = workgroup_id.y;\n let ds = local_id.x;\n\n for (var t = ts; t < args.n; t += num_workgroups.x) {\n let half_rope = (args.rope_dimension / 2);\n let xr_start = args.x_offset + ((t * args.num_heads + h) * args.head_dimension);\n let xi_start = xr_start + half_rope;\n let encoding_start = args.encoding_offset + ((t + args.position) * args.rope_dimension); \n for (var d = ds; d < half_rope; d += workgroup_size_x) {\n let xr_idx = xr_start + d;\n let xi_idx = xi_start + d;\n let encoding_idx = encoding_start + (2 * d);\n\n let re = x[xr_idx];\n let im = x[xi_idx];\n x[xr_idx] = (re * encoding[encoding_idx]) - (im * encoding[encoding_idx + 1]);\n x[xi_idx] = (re * encoding[encoding_idx + 1]) + (im * encoding[encoding_idx]);\n }\n }\n}\n\n".concat(emptyShader);var loadAttentionEncodeShader=function loadAttentionEncodeShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"attention encode bind layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"attention encode pipeline layout",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"attention encode shader",code:attentionEncodeShaderSource});var computePipeline=device.createComputePipeline({label:"attention encode pipeline",layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint,constants:{workgroup_size_x:PV_PICOLLM_WEBGPU_DEFAULT_WORKGROUP_SIZE}}});return{computePipeline:computePipeline}};var DOT_PRODUCT_SHADER_NAME="pv_picollm_attention_dot_product_shader";var attentionDotProductShaderSource="\nstruct argsStruct { \n n: u32,\n tq: u32,\n head_dimension: u32,\n num_heads: u32,\n num_kv_heads: u32,\n window_length: u32,\n start: u32,\n norm: f32,\n length1: u32,\n num_keys: u32,\n query_offset: u32,\n keys_offset: u32,\n key_intercepts_offset: u32,\n key_slopes_offset: u32,\n scores_offset: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar query: array;\n\n@group(0) @binding(2)\nvar keys: array;\n\n@group(0) @binding(3)\nvar key_intercepts: array;\n\n@group(0) @binding(4)\nvar key_slopes: array;\n\n@group(0) @binding(5)\nvar scores: array;\n \noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= args.num_heads) {\n return;\n }\n\n let head = global_id.x / (args.num_heads / args.num_kv_heads);\n \n let head_offset = head * args.window_length;\n let start_index = head_offset + args.start;\n \n let keys_local_a = args.keys_offset + (start_index * args.head_dimension);\n let key_intercepts_local_a = args.key_intercepts_offset + start_index; \n let key_slopes_local_a = args.key_slopes_offset + start_index;\n \n let keys_local_b = args.keys_offset + (head_offset * args.head_dimension);\n let key_intercepts_local_b = args.key_intercepts_offset + head_offset; \n let key_slopes_local_b = args.key_slopes_offset + head_offset;\n \n let scores_local = args.scores_offset + (global_id.x * args.num_keys);\n let query_local = args.query_offset + (((global_id.x * args.n) + args.tq) * args.head_dimension);\n \n for (var i = 0u; i < args.head_dimension; i++) { \n for (var k = 0u; k < args.num_keys; k++) {\n if (k < args.length1) { \n let key_idx = keys_local_a + (k * args.head_dimension) + i;\n let key_val = f32(extractBits(keys[key_idx / 4], (i * 8u) % 32u, 8u));\n let tmp = query[query_local + i] * (key_intercepts[key_intercepts_local_a + k] + (key_slopes[key_slopes_local_a + k] * key_val));\n scores[scores_local + k] += tmp;\n }\n else {\n let j = k - args.length1;\n let key_idx = keys_local_b + (j * args.head_dimension) + i;\n let key_val = f32(extractBits(keys[key_idx / 4], (i * 8u) % 32u, 8u));\n let tmp = query[query_local + i] * (key_intercepts[key_intercepts_local_b + j] + (key_slopes[key_slopes_local_b + j] * key_val));\n scores[scores_local + k] += tmp;\n }\n } \n }\n \n for (var k = 0u; k < args.num_keys; k++) {\n scores[scores_local + k] *= args.norm;\n }\n}\n\n".concat(emptyShader);var loadAttentionDotProductShader=function loadAttentionDotProductShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"attention dot product bind group layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:3,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:4,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:5,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"attention dot product pipeline layout",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"attention dot product shader module",code:attentionDotProductShaderSource});var computePipeline=device.createComputePipeline({label:"attention dot product pipeline",layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint}});return{computePipeline:computePipeline}};var SOFTMAX_SHADER_NAME="pv_picollm_attention_softmax_shader";var attentionSoftmaxShaderSource="\nstruct argsStruct { \n num_heads: u32,\n num_keys: u32,\n scores_offset: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar scores: array;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= args.num_heads) {\n return;\n }\n\n let scores_start = args.scores_offset + (global_id.x * args.num_keys);\n \n var max_index: u32 = 0;\n for (var i = 1u; i < args.num_keys; i++) {\n if (scores[scores_start + i] > scores[scores_start + max_index]) {\n max_index = i;\n }\n }\n let max: f32 = scores[scores_start + max_index];\n\n var sum: f32 = 0.0;\n for (var i = 0u; i < args.num_keys; i++) {\n scores[scores_start + i] = exp(scores[scores_start + i] - max);\n sum += scores[scores_start + i];\n }\n\n for (var i = 0u; i < args.num_keys; i++) {\n scores[scores_start + i] /= sum;\n }\n}\n\n".concat(emptyShader);var loadAttentionSoftmaxShader=function loadAttentionSoftmaxShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"attention softmax bind group layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"attention softmax pipeline layout",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"attention softmax shader module",code:attentionSoftmaxShaderSource});var computePipeline=device.createComputePipeline({label:"attention softmax pipeline",layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint}});return{computePipeline:computePipeline}};var FIR_SHADER_NAME="pv_picollm_attention_fir_shader";var attentionFirShaderSource="\nstruct argsStruct { \n length1: u32,\n length2: u32,\n tq: u32,\n head_dimension: u32,\n num_heads: u32,\n num_kv_heads: u32,\n window_length: u32,\n start: u32,\n values_offset: u32,\n value_intercepts_offset: u32,\n value_slopes_offset: u32,\n scores_offset: u32,\n output_offset: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar values: array;\n\n@group(0) @binding(2)\nvar value_intercepts: array;\n\n@group(0) @binding(3)\nvar value_slopes: array;\n\n@group(0) @binding(4)\nvar scores: array;\n\n@group(0) @binding(5)\nvar output: array;\n \noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= args.num_heads) {\n return;\n }\n\n let head = global_id.x / (args.num_heads / args.num_kv_heads);\n\n let head_offset = head * args.window_length;\n let start_index = head_offset + args.start;\n\n let values_local_a = args.values_offset + (start_index * args.head_dimension);\n let value_intercepts_local_a = args.value_intercepts_offset + start_index;\n let value_slopes_local_a = args.value_slopes_offset + start_index;\n let values_local_b = args.values_offset + (head_offset * args.head_dimension);\n let value_intercepts_local_b = args.value_intercepts_offset + head_offset;\n let value_slopes_local_b = args.value_slopes_offset + head_offset;\n let scores_local = args.scores_offset + (global_id.x * (args.length1 + args.length2));\n let output_local = args.output_offset + (((args.tq * args.num_heads) + global_id.x) * args.head_dimension);\n\n for (var i = 0u; i < args.head_dimension; i++) {\n var tmp: f32 = 0.0;\n for (var k = 0u; k < args.length1; k++) {\n let value_idx = values_local_a + (k * args.head_dimension) + i;\n let value_val = f32(extractBits(values[value_idx / 4], (i * 8u) % 32u, 8u));\n tmp += scores[scores_local + k] * (value_intercepts[value_intercepts_local_a + k] + (value_slopes[value_slopes_local_a + k] * value_val)); \n }\n for (var k = 0u; k < args.length2; k++) {\n let value_idx = values_local_b + (k * args.head_dimension) + i;\n let value_val = f32(extractBits(values[value_idx / 4], (i * 8u) % 32u, 8u));\n tmp += scores[scores_local + args.length1 + k] * (value_intercepts[value_intercepts_local_b + k] + (value_slopes[value_slopes_local_b + k] * value_val)); \n }\n output[output_local + i] = tmp;\n }\n}\n\n".concat(emptyShader);var loadAttentionFirShader=function loadAttentionFirShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"attention fir bind group layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:3,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:4,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:5,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"attention fir pipeline layout",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"attention fir shader module",code:attentionFirShaderSource});var computePipeline=device.createComputePipeline({label:"attention fir pipeline",layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint}});return{computePipeline:computePipeline}};var UPDATE_KV_SHADER_NAME="pv_picollm_attention_update_kv_shader";var attentionUpdateKvShaderSource="\nstruct argsStruct {\n n: u32,\n num_kv_heads: u32,\n window_length: u32,\n position: u32,\n head_dimension: u32,\n tf_offset: u32,\n kv_offset: u32,\n kv_intercepts_offset: u32,\n kv_slopes_offset: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar tf: array;\n\n@group(0) @binding(2)\nvar kv: array;\n\n@group(0) @binding(3)\nvar kv_intercepts: array;\n\n@group(0) @binding(4)\nvar kv_slopes: array;\n \noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) { \n if (global_id.x >= args.num_kv_heads) {\n return;\n }\n \n for (var i = 0u; i < args.n; i++) {\n let index = (global_id.x * args.window_length) + ((args.position + i) % args.window_length);\n let tf_start = args.tf_offset + (((i * args.num_kv_heads) + global_id.x) * args.head_dimension);\n let kv_start = args.kv_offset + ((index * args.head_dimension) / 4);\n let kv_intercepts_start = args.kv_intercepts_offset + index;\n let kv_slopes_start = args.kv_slopes_offset + index;\n \n var xmax = tf[tf_start]; \n var xmin = tf[tf_start]; \n \n for (var j = 1u; j < args.head_dimension; j++) {\n xmax = max(xmax, tf[tf_start + j]);\n xmin = min(xmin, tf[tf_start + j]);\n }\n\n kv_intercepts[kv_intercepts_start] = xmin;\n kv_slopes[kv_slopes_start] = f32(xmax - xmin) / 255.0;\n\n for (var j = 0u; j < args.head_dimension; j++) {\n let kv_idx = kv_start + (j / 4);\n let kv_val = u32(round((tf[tf_start + j] - xmin) / kv_slopes[kv_slopes_start])); \n kv[kv_idx] = insertBits(kv[kv_idx], extractBits(kv_val, 0u, 8u), (j * 8u) % 32u, 8u); \n }\n }\n}\n\n".concat(emptyShader);var loadAttentionUpdateKvShader=function loadAttentionUpdateKvShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"attention update kv bind group layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}},{binding:3,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}},{binding:4,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"attention update kv pipeline layout",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"attention update kv shader module",code:attentionUpdateKvShaderSource});var computePipeline=device.createComputePipeline({label:"attention update kv pipeline",layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint}});return{computePipeline:computePipeline}};var TRANSPOSE_QUERY_SHADER_NAME="pv_picollm_attention_transpose_query_shader";var attentionTransposeQueryShaderSource="\nstruct argsStruct {\n n: u32,\n num_heads: u32,\n head_dimension: u32,\n tf_offset: u32,\n hf_offset: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar tf: array;\n\n@group(0) @binding(2)\nvar hf: array;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(\n @builtin(workgroup_id) workgroup_id : vec3,\n @builtin(local_invocation_id) local_id : vec3\n) {\n\n if (workgroup_id.x >= args.num_heads || workgroup_id.y >= args.n || local_id.x >= args.head_dimension) {\n return;\n }\n \n let tf_idx = args.tf_offset + (workgroup_id.y * args.num_heads * args.head_dimension) + (workgroup_id.x * args.head_dimension) + local_id.x; \n let hf_idx = args.hf_offset + (workgroup_id.x * args.n * args.head_dimension) + (workgroup_id.y * args.head_dimension) + local_id.x; \n hf[hf_idx] = tf[tf_idx];\n}\n\n".concat(emptyShader);var loadAttentionTransposeQueryShader=function loadAttentionTransposeQueryShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"attention transpose query bind group layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"attention transpose query pipeline layout",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"attention transpose query shader module",code:attentionTransposeQueryShaderSource});var computePipeline=device.createComputePipeline({label:"attention transpose query pipeline",layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint,constants:{workgroup_size_x:PV_PICOLLM_WEBGPU_DEFAULT_WORKGROUP_SIZE}}});return{computePipeline:computePipeline}};var attentionShaders=_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty({},PRECOMPUTE_ENCODING_SHADER_NAME,loadAttentionPrecomputeEncodingShader),ENCODE_ROPE_INTERLEAVED_SHADER_NAME,loadAttentionEncodeRopeInterleavedShader),ENCODE_SHADER_NAME,loadAttentionEncodeShader),DOT_PRODUCT_SHADER_NAME,loadAttentionDotProductShader),SOFTMAX_SHADER_NAME,loadAttentionSoftmaxShader),FIR_SHADER_NAME,loadAttentionFirShader),UPDATE_KV_SHADER_NAME,loadAttentionUpdateKvShader),TRANSPOSE_QUERY_SHADER_NAME,loadAttentionTransposeQueryShader);var SILU_SHADER_NAME="pv_picollm_feed_forward_silu_shader";var feedForwardSiluShaderSource="\nstruct argsStruct {\n n: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar x: array;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= args.n) {\n return;\n }\n x[global_id.x] = x[global_id.x] / (1.0 + exp(-x[global_id.x]));\n}\n\n".concat(emptyShader);var loadFeedForwardSiluShader=function loadFeedForwardSiluShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"ff silu bind group layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"ff silu pipeline layout",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"ff silu shader module",code:feedForwardSiluShaderSource});var computePipeline=device.createComputePipeline({label:"ff silu pipline",layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint,constants:{workgroup_size_x:PV_PICOLLM_WEBGPU_DEFAULT_WORKGROUP_SIZE}}});return{computePipeline:computePipeline}};var GELU_SHADER_NAME="pv_picollm_feed_forward_gelu_shader";var feedForwardGeluShaderSource="\nstruct argsStruct {\n n: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar x: array;\n\nconst a1: f32 = 0.254829592;\nconst a2: f32 = -0.284496736;\nconst a3: f32 = 1.421413741;\nconst a4: f32 = -1.453152027;\nconst a5: f32 = 1.061405429;\nconst p: f32 = 0.3275911;\n\n// A&S formula 7.1.26\nfn erf(x: f32) -> f32 { \n var sign: f32 = 1.0;\n if (x < 0) {\n sign = -1.0;\n }\n var x_abs: f32 = abs(x);\n \n let t: f32 = 1.0 / fma(p, x_abs, 1.0);\n let y: f32 = 1.0 - (((((a5 * t + a4) * t) + a3) * t + a2) * t + a1) * t * exp(-x_abs * x_abs);\n\n return sign * y;\n}\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= args.n) {\n return;\n }\n x[global_id.x] = 0.5 * x[global_id.x] * (1.0 + erf(x[global_id.x] * 0.7071067811865475));\n}\n\n".concat(emptyShader);var loadFeedForwardGeluShader=function loadFeedForwardGeluShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"ff gelu bind group layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"ff gelu pipeline layout",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"ff gelu shader module",code:feedForwardGeluShaderSource});var computePipeline=device.createComputePipeline({label:"ff gelu pipeline",layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint,constants:{workgroup_size_x:PV_PICOLLM_WEBGPU_DEFAULT_WORKGROUP_SIZE}}});return{computePipeline:computePipeline}};var ALMOST_GELU_SHADER_NAME="pv_picollm_feed_forward_almost_gelu_shader";var feedForwardAlmostGeluShaderSource="\nstruct argsStruct {\n n: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar x: array;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= args.n) {\n return;\n }\n x[global_id.x] = 0.5 * x[global_id.x] * (1 + tanh(0.7978845608028654 * (x[global_id.x] + (0.044715f * x[global_id.x] * x[global_id.x] * x[global_id.x]))));\n}\n\n".concat(emptyShader);var loadFeedForwardAlmostGeluShader=function loadFeedForwardAlmostGeluShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"ff almost gelu bind group layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"ff almost gelu pipeline layout",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"ff almost gelu shader module",code:feedForwardAlmostGeluShaderSource});var computePipeline=device.createComputePipeline({label:"ff almost gelu pipeline",layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint,constants:{workgroup_size_x:PV_PICOLLM_WEBGPU_DEFAULT_WORKGROUP_SIZE}}});return{computePipeline:computePipeline}};var MULTIPLY_BUFFERS_SHADER_NAME="pv_picollm_feed_forward_multiply_buffers_shader";var feedForwardMultiplyBuffersShaderSource="\nstruct argsStruct {\n n: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar x: array;\n\n@group(0) @binding(2)\nvar y: array;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= args.n) {\n return;\n }\n y[global_id.x] *= x[global_id.x];\n}\n\n".concat(emptyShader);var loadFeedForwardMultiplyBuffersShader=function loadFeedForwardMultiplyBuffersShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"ff multiply buffers bind group layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"ff multiply buffers pipeline layout",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"ff multiply buffers shader module",code:feedForwardMultiplyBuffersShaderSource});var computePipeline=device.createComputePipeline({label:"ff multiply buffers pipeline",layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint,constants:{workgroup_size_x:PV_PICOLLM_WEBGPU_DEFAULT_WORKGROUP_SIZE}}});return{computePipeline:computePipeline}};var feedForwardShaders=_defineProperty(_defineProperty(_defineProperty(_defineProperty({},SILU_SHADER_NAME,loadFeedForwardSiluShader),GELU_SHADER_NAME,loadFeedForwardGeluShader),ALMOST_GELU_SHADER_NAME,loadFeedForwardAlmostGeluShader),MULTIPLY_BUFFERS_SHADER_NAME,loadFeedForwardMultiplyBuffersShader);var FORWARD_SHADER_NAME$1="pv_picollm_gate_forward_shader";var gateForwardShaderSource="\n\nstruct pv_picollm_gate_ix_t {\n i: u32,\n x: f32,\n}\n\n@group(0) @binding(0)\nvar y: array;\n\n@group(0) @binding(1)\nvar indices: array;\n\n@group(0) @binding(2)\nvar weights: array;\n\noverride n: u32 = 0;\noverride k: u32 = 0;\noverride num_experts: u32 = 0;\n\noverride y_offset: u32 = 0;\noverride indices_offset: u32 = 0;\noverride weights_offset: u32 = 0;\n\nvar ixs: array;\n \noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(\n @builtin(global_invocation_id) global_id : vec3\n) {\n if (global_id.x >= n) {\n return;\n }\n \n var y_start: u32 = y_offset + global_id.x * num_experts;\n for (var j = 0u; j < num_experts; j++) {\n ixs[j].i = j;\n ixs[j].x = y[y_start + j];\n }\n\n for (var i = 0u; i < num_experts - 1; i++) {\n for (var j = 0u; j < num_experts - i - 1; j++) {\n if (ixs[j].x < ixs[j + 1].x) {\n let tmp = ixs[j];\n ixs[j] = ixs[j + 1];\n ixs[j + 1] = tmp;\n }\n }\n }\n\n for (var j = 0u; j < k; j++) {\n indices[indices_offset + (global_id.x * k) + j] = ixs[j].i;\n weights[weights_offset + (global_id.x * k) + j] = ixs[j].x;\n }\n\n var max_weight: f32 = weights[weights_offset + (global_id.x * k)];\n for (var j = 1u; j < k; j++) {\n max_weight = max(max_weight, weights[weights_offset + (global_id.x * k) + j]);\n }\n\n var sum_weight: f32 = 0.0;\n for (var j = 0u; j < k; j++) {\n weights[weights_offset + (global_id.x * k) + j] = exp(weights[weights_offset + (global_id.x * k) + j] - max_weight);\n sum_weight += weights[weights_offset + (global_id.x * k) + j];\n }\n\n for (var j = 0u; j < k; j++) {\n weights[weights_offset + (global_id.x * k) + j] /= sum_weight;\n }\n}\n\n".concat(emptyShader);var loadGateForwardShader=function loadGateForwardShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"gate forward bind group layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"gate forward pipeline",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"gate forward shader module",code:gateForwardShaderSource});var computePipeline=device.createComputePipeline({layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint,constants:{num_experts:1}}});return{computePipeline:computePipeline,pipelineLayout:pipelineLayout,shaderModule:shaderModule}};var gateForwardShader=_defineProperty({},FORWARD_SHADER_NAME$1,loadGateForwardShader);var ADD_TO_BUFFER_SHADER_NAME$1="pv_picollm_moe_transformer_add_to_buffer_shader";var moeTransformerAddToBufferShaderSource="\nstruct argsStruct {\n n: u32, \n x_offset: u32,\n buffer_offset: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar x: array;\n\n@group(0) @binding(2)\nvar buffer: array;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= args.n) {\n return;\n }\n\n buffer[args.buffer_offset + global_id.x] += x[args.x_offset + global_id.x]; \n}\n\n".concat(emptyShader);var loadMoeTransformerAddToBufferShader=function loadMoeTransformerAddToBufferShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"moe transformer add to buffer bind group layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"moe transformer add to buffer pipeline",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"moe transformer add to buffer shader module",code:moeTransformerAddToBufferShaderSource});var computePipeline=device.createComputePipeline({label:"moe transformer add to buffer pipeline",layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint}});return{computePipeline:computePipeline}};var MULTIPLY_WEIGHT_AND_ADD_TO_BUFFER_SHADER_NAME="pv_picollm_moe_transformer_multiply_weight_and_add_to_buffer_shader";var moeTransformerMultiplyWeightAndToBufferShaderSource="\nstruct argsStruct {\n n: u32, \n weights_index: u32,\n y_index: u32,\n weights_offset: u32,\n x_offset: u32,\n y_offset: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar weights: array;\n\n@group(0) @binding(2)\nvar x: array;\n\n@group(0) @binding(3)\nvar y: array;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= args.n) {\n return;\n }\n \n y[args.y_offset + args.y_index + global_id.x] += weights[args.weights_index] + x[args.x_offset + global_id.x]; \n}\n\n".concat(emptyShader);var loadMoeTransformerMultiplyWeightAndAddToBufferShader=function loadMoeTransformerMultiplyWeightAndAddToBufferShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"moe transformer multiply weight and add to buffer bind group layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:3,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"moe transformer multiply weight and add to buffer pipeline",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"moe transformer multiply weight and add to buffer shader module",code:moeTransformerMultiplyWeightAndToBufferShaderSource});var computePipeline=device.createComputePipeline({label:"moe transformer multiply weight and add to buffer pipeline",layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint}});return{computePipeline:computePipeline}};var ADD_BUFFERS_SHADER_NAME$1="pv_picollm_moe_transformer_add_buffers_shader";var moeTransformerAddBuffersShaderSource="\nstruct argsStruct {\n n: u32, \n buffer1_offset: u32,\n buffer2_offset: u32,\n y_offset: u32, \n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar buffer1: array;\n\n@group(0) @binding(2)\nvar buffer2: array;\n\n@group(0) @binding(3)\nvar y: array;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= args.n) {\n return;\n }\n \n y[args.y_offset + global_id.x] = buffer1[args.buffer1_offset + global_id.x] + buffer2[args.buffer2_offset + global_id.x]; \n}\n\n".concat(emptyShader);var loadMoeTransformerAddBuffersShader=function loadMoeTransformerAddBuffersShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"moe transformer add buffers bind group layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:3,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"moe transformer add buffers pipeline layout",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"moe transformer add buffers shader module",code:moeTransformerAddBuffersShaderSource});var computePipeline=device.createComputePipeline({label:"moe transformer add buffers pipeline",layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint}});return{computePipeline:computePipeline}};var moeTransformerForwardShaders=_defineProperty(_defineProperty(_defineProperty({},ADD_TO_BUFFER_SHADER_NAME$1,loadMoeTransformerAddToBufferShader),MULTIPLY_WEIGHT_AND_ADD_TO_BUFFER_SHADER_NAME,loadMoeTransformerMultiplyWeightAndAddToBufferShader),ADD_BUFFERS_SHADER_NAME$1,loadMoeTransformerAddBuffersShader);var sdataReduce="\n for (var s: u32 = workgroup_size_x / 2; s > 0; s >>= 1) {\n if tid < s {\n sdata[tid] += sdata[tid + s];\n }\n workgroupBarrier();\n }\n";var dividePadFunction="\n fn divide_pad(a: u32, b: u32) -> u32 { \n return (a + b - 1) / b;\n }\n";var FORWARD_MULTI_BUFFER_SHADER_NAME$1="pv_picollm_norm_forward_multi_buffer_shader";var FORWARD_SINGLE_BUFFER_SHADER_NAME$1="pv_picollm_norm_forward_single_buffer_shader";var normForwardShaderSource=function normForwardShaderSource(isMulti){return"\nstruct argsStruct {\n n: u32,\n dimension: u32,\n remainder: u32,\n remainder_start: u32, \n eps: f32, \n x_offset: u32,\n y_offset: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar weight: array;\n\n".concat(isMulti?"\n@group(0) @binding(2)\nvar x: array;\n\n@group(0) @binding(3) \nvar y: array;\n":" \n@group(0) @binding(2)\nvar x: array;\n","\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\nvar sdata: array, workgroup_size_x>;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(\n @builtin(local_invocation_id) local_id: vec3,\n @builtin(workgroup_id) workgroup_id: vec3\n) {\n let tid = local_id.x;\n let m = workgroup_id.x;\n let block_size = workgroup_size_x;\n \n var power_vec: vec4;\n let x_start: u32 = args.x_offset + (m * args.dimension);\n let skip = tid * 4;\n let shift = (block_size * 4);\n for (var j = 0u; j + skip < args.remainder_start; j += shift) {\n let local_index = x_start + j + skip; \n\n let x_vec = vec4(\n x[local_index],\n x[local_index + 1],\n x[local_index + 2],\n x[local_index + 3]);\n \n power_vec += x_vec * x_vec; \n } \n \n if (tid == 0 && args.remainder > 0) {\n var remainder_vec = vec4(0.0, 0.0, 0.0, 0.0);\n let x_idx = x_start + args.remainder_start;\n for (var j = 0u; j < args.remainder; j++) { \n remainder_vec[j] = x[x_idx + j];\n } \n power_vec += remainder_vec * remainder_vec;\n }\n \n sdata[tid] = power_vec;\n workgroupBarrier();\n\n ").concat(sdataReduce,"\n \n let power = sdata[0].x + sdata[0].y + sdata[0].z + sdata[0].w;\n let norm: vec4 = vec4(1.0 / sqrt((power / f32(args.dimension)) + args.eps));\n \n let y_start: u32 = args.y_offset + (m * args.dimension);\n for (var j = 0u; j + skip < args.remainder_start; j += shift) {\n let local_index = j + skip;\n let x_idx = x_start + local_index;\n let x_vec = vec4(\n x[x_idx],\n x[x_idx + 1],\n x[x_idx + 2],\n x[x_idx + 3]);\n \n let weight_vec = vec4(\n weight[local_index],\n weight[local_index + 1],\n weight[local_index + 2],\n weight[local_index + 3]);\n let y_vec = x_vec * norm * weight_vec;\n \n let y_idx = y_start + local_index;\n").concat(isMulti?" \n y[y_idx] = y_vec.x;\n y[y_idx + 1] = y_vec.y;\n y[y_idx + 2] = y_vec.z;\n y[y_idx + 3] = y_vec.w;\n":" \n x[y_idx] = y_vec.x;\n x[y_idx + 1] = y_vec.y;\n x[y_idx + 2] = y_vec.z;\n x[y_idx + 3] = y_vec.w;\n"," \n }\n \n if (tid == 0 && args.remainder > 0) {\n let x_idx = x_start + args.remainder_start;\n let weight_idx = args.remainder_start; \n let y_idx = y_start + args.remainder_start;\n for (var j = 0u; j < args.remainder; j++) {\n").concat(isMulti?" \n y[y_idx + j] = x[x_idx + j] * norm[j] * weight[weight_idx + j];\n":" \n x[y_idx + j] = x[x_idx + j] * norm[j] * weight[weight_idx + j];\n"," \n } \n }\n}\n\n").concat(emptyShader)};var loadNormForwardShader=function loadNormForwardShader(device,isMulti){var entries=[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}}];if(isMulti){entries.push({binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}});entries.push({binding:3,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}})}else{entries.push({binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}})}var bindGroupLayout=device.createBindGroupLayout({label:"norm forward ".concat(isMulti?"multi":"single"," buffer bind group layout"),entries:entries});var pipelineLayout=device.createPipelineLayout({label:"norm forward ".concat(isMulti?"multi":"single"," buffer pipeline layout"),bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"norm forward ".concat(isMulti?"multi":"single"," buffer shader module"),code:normForwardShaderSource(isMulti)});var computePipeline=device.createComputePipeline({label:"norm forward ".concat(isMulti?"multi":"single"," buffer pipeline"),layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint,constants:{workgroup_size_x:PV_PICOLLM_WEBGPU_DEFAULT_WORKGROUP_SIZE}}});return{computePipeline:computePipeline}};var normForwardShader=_defineProperty(_defineProperty({},FORWARD_SINGLE_BUFFER_SHADER_NAME$1,function(device){return loadNormForwardShader(device,false)}),FORWARD_MULTI_BUFFER_SHADER_NAME$1,function(device){return loadNormForwardShader(device,true)});var FORWARD_MULTI_BUFFER_SHADER_NAME="pv_picollm_norm_layer_forward_multi_buffer_shader";var normLayerForwardMultiBufferShaderSource="\nstruct argsStruct {\n n: u32,\n dimension: u32,\n eps: f32,\n weight_offset: u32,\n bias_offset: u32,\n x_offset: u32,\n y_offset: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar weight: array;\n\n@group(0) @binding(2)\nvar bias: array;\n\n@group(0) @binding(3)\nvar x: array;\n\n@group(0) @binding(4)\nvar y: array;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= args.n) {\n return;\n }\n \n let x_start: u32 = args.x_offset + (global_id.x * args.dimension);\n\n var mean: f32 = 0.0;\n for (var j = 0u; j < args.dimension; j++) {\n mean += x[x_start + j];\n }\n mean /= f32(args.dimension);\n\n var mean2: f32 = 0.0;\n for (var j = 0u; j < args.dimension; j++) {\n mean2 += (x[x_start + j] - mean) * (x[x_start + j] - mean);\n }\n mean2 /= f32(args.dimension);\n\n var norm: f32 = 1.0 / sqrt(mean2 + args.eps);\n\n var y_start = args.y_offset + (global_id.x * args.dimension);\n for (var j = 0u; j < args.dimension; j++) {\n y[y_start + j] = ((x[x_start + j] - mean) * norm * weight[args.weight_offset + j]) + bias[args.bias_offset + j];\n }\n}\n\n".concat(emptyShader);var loadNormLayerForwardMultiBufferShader=function loadNormLayerForwardMultiBufferShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"norm layer forward multi buffer bind group layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:3,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:4,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"norm layer forward multi buffer pipeline layout",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"norm layer forward multi buffer shader module",code:normLayerForwardMultiBufferShaderSource});var computePipeline=device.createComputePipeline({label:"norm layer forward multi buffer pipeline",layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint,constants:{workgroup_size_x:PV_PICOLLM_WEBGPU_DEFAULT_WORKGROUP_SIZE}}});return{computePipeline:computePipeline}};var FORWARD_SINGLE_BUFFER_SHADER_NAME="pv_picollm_norm_layer_forward_single_buffer_shader";var normLayerForwardSingleBufferShaderSource="\nstruct argsStruct {\n n: u32,\n dimension: u32,\n eps: f32,\n weight_offset: u32,\n bias_offset: u32,\n x_offset: u32,\n y_offset: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar weight: array;\n\n@group(0) @binding(2)\nvar bias: array;\n\n@group(0) @binding(3)\nvar y: array;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= args.n) {\n return;\n }\n \n let x_start: u32 = args.x_offset + (global_id.x * args.dimension);\n\n var mean: f32 = 0.0;\n for (var j = 0u; j < args.dimension; j++) {\n mean += y[x_start + j];\n }\n mean /= f32(args.dimension);\n\n var mean2: f32 = 0.0;\n for (var j = 0u; j < args.dimension; j++) {\n mean2 += (y[x_start + j] - mean) * (y[x_start + j] - mean);\n }\n mean2 /= f32(args.dimension);\n\n var norm: f32 = 1.0 / sqrt(mean2 + args.eps);\n\n var y_start = args.y_offset + (global_id.x * args.dimension);\n for (var j = 0u; j < args.dimension; j++) {\n y[y_start + j] = ((y[x_start + j] - mean) * norm * weight[args.weight_offset + j]) + bias[args.bias_offset + j];\n }\n}\n\n".concat(emptyShader);var loadNormLayerForwardSingleBufferShader=function loadNormLayerForwardSingleBufferShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"norm layer forward single buffer bind group layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:3,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"norm layer forward single buffer pipeline layout",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"norm layer forward single buffer shader module",code:normLayerForwardSingleBufferShaderSource});var computePipeline=device.createComputePipeline({label:"norm layer forward single buffer pipeline",layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint,constants:{workgroup_size_x:PV_PICOLLM_WEBGPU_DEFAULT_WORKGROUP_SIZE}}});return{computePipeline:computePipeline}};var normLayerForwardShader=_defineProperty(_defineProperty({},FORWARD_SINGLE_BUFFER_SHADER_NAME,loadNormLayerForwardSingleBufferShader),FORWARD_MULTI_BUFFER_SHADER_NAME,loadNormLayerForwardMultiBufferShader);var ADD_TO_BUFFER_SHADER_NAME="pv_picollm_transformer_add_to_buffer_shader";var transformerAddToBufferShaderSource="\nstruct argsStruct {\n n: u32,\n x_offset: u32,\n buffer_offset: u32, \n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar x: array;\n\n@group(0) @binding(2)\nvar buffer: array;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= args.n) {\n return;\n }\n \n buffer[args.buffer_offset + global_id.x] += x[args.x_offset + global_id.x]; \n}\n\n".concat(emptyShader);var loadTransformerAddToBufferShader=function loadTransformerAddToBufferShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"transformer add to buffer bind group layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"transformer add to buffer pipeline layout",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"transformer add to buffer shader module",code:transformerAddToBufferShaderSource});var computePipeline=device.createComputePipeline({label:"transformer add to buffer compute",layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint,constants:{workgroup_size_x:PV_PICOLLM_WEBGPU_DEFAULT_WORKGROUP_SIZE}}});return{computePipeline:computePipeline}};var ADD_BUFFERS_SHADER_NAME="pv_picollm_transformer_add_buffers_shader";var transformerAddBuffersShaderSource="\n\nstruct argsStruct {\n n: u32,\n buffer1_offset: u32,\n buffer2_offset: u32,\n y_offset: u32, \n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar buffer1: array;\n\n@group(0) @binding(2)\nvar buffer2: array;\n\n@group(0) @binding(3)\nvar y: array;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= args.n) {\n return;\n }\n \n y[args.y_offset + global_id.x] = buffer1[args.buffer1_offset + global_id.x] + buffer2[args.buffer2_offset + global_id.x]; \n}\n\n".concat(emptyShader);var loadTransformerAddBuffersShader=function loadTransformerAddBuffersShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"transformer add buffers bind group layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:3,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"transformer add buffers pipeline layout",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"transformer add buffers shader module",code:transformerAddBuffersShaderSource});var computePipeline=device.createComputePipeline({label:"transformer add buffers pipeline",layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint,constants:{workgroup_size_x:PV_PICOLLM_WEBGPU_DEFAULT_WORKGROUP_SIZE}}});return{computePipeline:computePipeline}};var transformerForwardShaders=_defineProperty(_defineProperty({},ADD_TO_BUFFER_SHADER_NAME,loadTransformerAddToBufferShader),ADD_BUFFERS_SHADER_NAME,loadTransformerAddBuffersShader);var FORWARD_SHADER_NAME="pv_picollm_weight_float_forward_shader";var weightFloatForwardShaderSource="\n\nstruct argsStruct {\n nr: u32,\n nc: u32,\n w_offset: u32,\n x_offset: u32,\n y_offset: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar w: array;\n\n@group(0) @binding(2)\nvar x: array;\n\n@group(0) @binding(3)\nvar y: array;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(\n @builtin(workgroup_id) workgroup_id : vec3,\n @builtin(local_invocation_id) local_id : vec3\n) {\n if (local_id.x >= args.nr) {\n return;\n }\n let x_start: u32 = args.x_offset + (workgroup_id.x * args.nc);\n let y_idx: u32 = local_id.x + args.y_offset + (workgroup_id.x * args.nr);\n \n let w_start: u32 = args.w_offset + (local_id.x * args.nc);\n for (var j = 0u; j < args.nc; j++) {\n y[y_idx] += w[w_start + j] * x[x_start + j]; \n }\n}\n\n".concat(emptyShader);var loadWeightFloatForwardShader=function loadWeightFloatForwardShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"weight float forward bind group layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:3,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"weight float forward pipeline layout",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"weight float forward shader module",code:weightFloatForwardShaderSource});var computePipeline=device.createComputePipeline({label:"weight float forward pipeline",layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint,constants:{workgroup_size_x:PV_PICOLLM_WEBGPU_DEFAULT_WORKGROUP_SIZE}}});return{computePipeline:computePipeline}};var weightFloatForwardShader=_defineProperty({},FORWARD_SHADER_NAME,loadWeightFloatForwardShader);var rowsPerBlock=16;var columnsPerBlock=8;var preprocessDim=16;var weightBlockSize=256;var unpackBlock128BitDepth3="\nvar unpacked: array;\n\nfn unpack_block_128_bit_depth_3(packed_offset: u32) {\n let val_0 = blocks[packed_offset]; \n unpacked[0] = extractBits(val_0, 0u, 3u);\n unpacked[1] = extractBits(val_0, 3u, 3u);\n unpacked[2] = extractBits(val_0, 6u, 3u);\n unpacked[3] = extractBits(val_0, 9u, 3u);\n unpacked[4] = extractBits(val_0, 12u, 3u);\n unpacked[5] = extractBits(val_0, 15u, 3u);\n unpacked[6] = extractBits(val_0, 18u, 3u);\n unpacked[7] = extractBits(val_0, 21u, 3u);\n unpacked[8] = extractBits(val_0, 24u, 3u);\n unpacked[9] = extractBits(val_0, 27u, 3u);\n unpacked[10] = extractBits(val_0, 30u, 2u);\n \n let val_1 = blocks[packed_offset + 1];\n unpacked[10] = insertBits(unpacked[10], extractBits(val_1, 0u, 1u), 2u, 1u);\n unpacked[11] = extractBits(val_1, 1u, 3u);\n unpacked[12] = extractBits(val_1, 4u, 3u);\n unpacked[13] = extractBits(val_1, 7u, 3u);\n unpacked[14] = extractBits(val_1, 10u, 3u);\n unpacked[15] = extractBits(val_1, 13u, 3u);\n unpacked[16] = extractBits(val_1, 16u, 3u);\n unpacked[17] = extractBits(val_1, 19u, 3u);\n unpacked[18] = extractBits(val_1, 22u, 3u);\n unpacked[19] = extractBits(val_1, 25u, 3u);\n unpacked[20] = extractBits(val_1, 28u, 3u);\n unpacked[21] = extractBits(val_1, 31u, 1u);\n \n let val_2 = blocks[packed_offset + 2];\n unpacked[21] = insertBits(unpacked[21], extractBits(val_2, 0u, 2u), 1u, 2u); \n unpacked[22] = extractBits(val_2, 2u, 3u);\n unpacked[23] = extractBits(val_2, 5u, 3u);\n unpacked[24] = extractBits(val_2, 8u, 3u);\n unpacked[25] = extractBits(val_2, 11u, 3u);\n unpacked[26] = extractBits(val_2, 14u, 3u);\n unpacked[27] = extractBits(val_2, 17u, 3u);\n unpacked[28] = extractBits(val_2, 20u, 3u);\n unpacked[29] = extractBits(val_2, 23u, 3u);\n unpacked[30] = extractBits(val_2, 26u, 3u);\n unpacked[31] = extractBits(val_2, 29u, 3u);\n \n let val_3 = blocks[packed_offset + 3]; \n unpacked[32] = extractBits(val_3, 0u, 3u);\n unpacked[33] = extractBits(val_3, 3u, 3u);\n unpacked[34] = extractBits(val_3, 6u, 3u);\n unpacked[35] = extractBits(val_3, 9u, 3u);\n unpacked[36] = extractBits(val_3, 12u, 3u);\n unpacked[37] = extractBits(val_3, 15u, 3u);\n unpacked[38] = extractBits(val_3, 18u, 3u);\n unpacked[39] = extractBits(val_3, 21u, 3u);\n unpacked[40] = extractBits(val_3, 24u, 3u);\n unpacked[41] = extractBits(val_3, 27u, 3u);\n unpacked[42] = extractBits(val_3, 30u, 2u);\n \n let val_4 = blocks[packed_offset + 4];\n unpacked[42] = insertBits(unpacked[42], extractBits(val_4, 0u, 1u), 2u, 1u);\n unpacked[43] = extractBits(val_4, 1u, 3u);\n unpacked[44] = extractBits(val_4, 4u, 3u);\n unpacked[45] = extractBits(val_4, 7u, 3u);\n unpacked[46] = extractBits(val_4, 10u, 3u);\n unpacked[47] = extractBits(val_4, 13u, 3u);\n unpacked[48] = extractBits(val_4, 16u, 3u);\n unpacked[49] = extractBits(val_4, 19u, 3u);\n unpacked[50] = extractBits(val_4, 22u, 3u);\n unpacked[51] = extractBits(val_4, 25u, 3u);\n unpacked[52] = extractBits(val_4, 28u, 3u);\n unpacked[53] = extractBits(val_4, 31u, 1u);\n \n let val_5 = blocks[packed_offset + 5];\n unpacked[53] = insertBits(unpacked[53], extractBits(val_5, 0u, 2u), 1u, 2u); \n unpacked[54] = extractBits(val_5, 2u, 3u);\n unpacked[55] = extractBits(val_5, 5u, 3u);\n unpacked[56] = extractBits(val_5, 8u, 3u);\n unpacked[57] = extractBits(val_5, 11u, 3u);\n unpacked[58] = extractBits(val_5, 14u, 3u);\n unpacked[59] = extractBits(val_5, 17u, 3u);\n unpacked[60] = extractBits(val_5, 20u, 3u);\n unpacked[61] = extractBits(val_5, 23u, 3u);\n unpacked[62] = extractBits(val_5, 26u, 3u);\n unpacked[63] = extractBits(val_5, 29u, 3u);\n \n let val_6 = blocks[packed_offset + 6];\n unpacked[64] = extractBits(val_6, 0u, 3u);\n unpacked[65] = extractBits(val_6, 3u, 3u);\n unpacked[66] = extractBits(val_6, 6u, 3u);\n unpacked[67] = extractBits(val_6, 9u, 3u);\n unpacked[68] = extractBits(val_6, 12u, 3u);\n unpacked[69] = extractBits(val_6, 15u, 3u);\n unpacked[70] = extractBits(val_6, 18u, 3u);\n unpacked[71] = extractBits(val_6, 21u, 3u);\n unpacked[72] = extractBits(val_6, 24u, 3u);\n unpacked[73] = extractBits(val_6, 27u, 3u);\n unpacked[74] = extractBits(val_6, 30u, 2u);\n \n let val_7 = blocks[packed_offset + 7];\n unpacked[74] = insertBits(unpacked[74], extractBits(val_7, 0u, 1u), 2u, 1u);\n unpacked[75] = extractBits(val_7, 1u, 3u);\n unpacked[76] = extractBits(val_7, 4u, 3u);\n unpacked[77] = extractBits(val_7, 7u, 3u);\n unpacked[78] = extractBits(val_7, 10u, 3u);\n unpacked[79] = extractBits(val_7, 13u, 3u);\n unpacked[80] = extractBits(val_7, 16u, 3u);\n unpacked[81] = extractBits(val_7, 19u, 3u);\n unpacked[82] = extractBits(val_7, 22u, 3u);\n unpacked[83] = extractBits(val_7, 25u, 3u);\n unpacked[84] = extractBits(val_7, 28u, 3u);\n unpacked[85] = extractBits(val_7, 31u, 1u);\n \n let val_8 = blocks[packed_offset + 8];\n unpacked[85] = insertBits(unpacked[85], extractBits(val_8, 0u, 2u), 1u, 2u); \n unpacked[86] = extractBits(val_8, 2u, 3u);\n unpacked[87] = extractBits(val_8, 5u, 3u);\n unpacked[88] = extractBits(val_8, 8u, 3u);\n unpacked[89] = extractBits(val_8, 11u, 3u);\n unpacked[90] = extractBits(val_8, 14u, 3u);\n unpacked[91] = extractBits(val_8, 17u, 3u);\n unpacked[92] = extractBits(val_8, 20u, 3u);\n unpacked[93] = extractBits(val_8, 23u, 3u);\n unpacked[94] = extractBits(val_8, 26u, 3u);\n unpacked[95] = extractBits(val_8, 29u, 3u);\n \n let val_9 = blocks[packed_offset + 9];\n unpacked[96] = extractBits(val_9, 0u, 3u);\n unpacked[97] = extractBits(val_9, 3u, 3u);\n unpacked[98] = extractBits(val_9, 6u, 3u);\n unpacked[99] = extractBits(val_9, 9u, 3u);\n unpacked[100] = extractBits(val_9, 12u, 3u);\n unpacked[101] = extractBits(val_9, 15u, 3u);\n unpacked[102] = extractBits(val_9, 18u, 3u);\n unpacked[103] = extractBits(val_9, 21u, 3u);\n unpacked[104] = extractBits(val_9, 24u, 3u);\n unpacked[105] = extractBits(val_9, 27u, 3u);\n unpacked[106] = extractBits(val_9, 30u, 2u);\n \n let val_10 = blocks[packed_offset + 10];\n unpacked[106] = insertBits(unpacked[106], extractBits(val_10, 0u, 1u), 2u, 1u);\n unpacked[107] = extractBits(val_10, 1u, 3u);\n unpacked[108] = extractBits(val_10, 4u, 3u);\n unpacked[109] = extractBits(val_10, 7u, 3u);\n unpacked[110] = extractBits(val_10, 10u, 3u);\n unpacked[111] = extractBits(val_10, 13u, 3u);\n unpacked[112] = extractBits(val_10, 16u, 3u);\n unpacked[113] = extractBits(val_10, 19u, 3u);\n unpacked[114] = extractBits(val_10, 22u, 3u);\n unpacked[115] = extractBits(val_10, 25u, 3u);\n unpacked[116] = extractBits(val_10, 28u, 3u);\n unpacked[117] = extractBits(val_10, 31u, 1u);\n \n let val_11 = blocks[packed_offset + 11];\n unpacked[117] = insertBits(unpacked[117], extractBits(val_11, 0u, 2u), 1u, 2u); \n unpacked[118] = extractBits(val_11, 2u, 3u);\n unpacked[119] = extractBits(val_11, 5u, 3u);\n unpacked[120] = extractBits(val_11, 8u, 3u);\n unpacked[121] = extractBits(val_11, 11u, 3u);\n unpacked[122] = extractBits(val_11, 14u, 3u);\n unpacked[123] = extractBits(val_11, 17u, 3u);\n unpacked[124] = extractBits(val_11, 20u, 3u);\n unpacked[125] = extractBits(val_11, 23u, 3u);\n unpacked[126] = extractBits(val_11, 26u, 3u);\n unpacked[127] = extractBits(val_11, 29u, 3u);\n}\n";var unpackBlock128BitDepth5="\nvar unpacked: array;\n\nfn unpack_block_128_bit_depth_5(packed_offset: u32) { \n let val_0 = blocks[packed_offset];\n unpacked[0] = extractBits(val_0, 0u, 5u);\n unpacked[1] = extractBits(val_0, 5u, 5u);\n unpacked[2] = extractBits(val_0, 10u, 5u);\n unpacked[3] = extractBits(val_0, 15u, 5u);\n unpacked[4] = extractBits(val_0, 20u, 5u);\n unpacked[5] = extractBits(val_0, 25u, 5u);\n unpacked[6] = extractBits(val_0, 30u, 2u);\n \n let val_1 = blocks[packed_offset + 1];\n unpacked[6] = insertBits(unpacked[6], extractBits(val_1, 0u, 3u), 2u, 3u); \n unpacked[7] = extractBits(val_1, 3u, 5u);\n unpacked[8] = extractBits(val_1, 8u, 5u);\n unpacked[9] = extractBits(val_1, 13u, 5u);\n unpacked[10] = extractBits(val_1, 18u, 5u);\n unpacked[11] = extractBits(val_1, 23u, 5u);\n unpacked[12] = extractBits(val_1, 28u, 4u);\n \n let val_2 = blocks[packed_offset + 2];\n unpacked[12] = insertBits(unpacked[12], extractBits(val_2, 0u, 1u), 4u, 1u);\n unpacked[13] = extractBits(val_2, 1u, 5u);\n unpacked[14] = extractBits(val_2, 6u, 5u);\n unpacked[15] = extractBits(val_2, 11u, 5u);\n unpacked[16] = extractBits(val_2, 16u, 5u);\n unpacked[17] = extractBits(val_2, 21u, 5u);\n unpacked[18] = extractBits(val_2, 26u, 5u);\n unpacked[19] = extractBits(val_2, 31u, 1u);\n \n let val_3 = blocks[packed_offset + 3];\n unpacked[19] = insertBits(unpacked[19], extractBits(val_3, 0u, 4u), 1u, 4u);\n unpacked[20] = extractBits(val_3, 4u, 5u);\n unpacked[21] = extractBits(val_3, 9u, 5u);\n unpacked[22] = extractBits(val_3, 14u, 5u);\n unpacked[23] = extractBits(val_3, 19u, 5u);\n unpacked[24] = extractBits(val_3, 24u, 5u);\n unpacked[25] = extractBits(val_3, 29u, 3u);\n \n let val_4 = blocks[packed_offset + 4];\n unpacked[25] = insertBits(unpacked[25], extractBits(val_4, 0u, 2u), 3u, 2u);\n unpacked[26] = extractBits(val_4, 2u, 5u);\n unpacked[27] = extractBits(val_4, 7u, 5u);\n unpacked[28] = extractBits(val_4, 12u, 5u);\n unpacked[29] = extractBits(val_4, 17u, 5u);\n unpacked[30] = extractBits(val_4, 22u, 5u);\n unpacked[31] = extractBits(val_4, 27u, 5u);\n \n let val_5 = blocks[packed_offset + 5];\n unpacked[32] = extractBits(val_5, 0u, 5u);\n unpacked[33] = extractBits(val_5, 5u, 5u);\n unpacked[34] = extractBits(val_5, 10u, 5u);\n unpacked[35] = extractBits(val_5, 15u, 5u);\n unpacked[36] = extractBits(val_5, 20u, 5u);\n unpacked[37] = extractBits(val_5, 25u, 5u);\n unpacked[38] = extractBits(val_5, 30u, 2u);\n\n let val_6 = blocks[packed_offset + 6];\n unpacked[38] = insertBits(unpacked[38], extractBits(val_6, 0u, 3u), 2u, 3u);\n unpacked[39] = extractBits(val_6, 3u, 5u);\n unpacked[40] = extractBits(val_6, 8u, 5u);\n unpacked[41] = extractBits(val_6, 13u, 5u);\n unpacked[42] = extractBits(val_6, 18u, 5u);\n unpacked[43] = extractBits(val_6, 23u, 5u);\n unpacked[44] = extractBits(val_6, 28u, 4u);\n\n let val_7 = blocks[packed_offset + 7];\n unpacked[44] = insertBits(unpacked[44], extractBits(val_7, 0u, 1u), 4u, 1u);\n unpacked[45] = extractBits(val_7, 1u, 5u);\n unpacked[46] = extractBits(val_7, 6u, 5u);\n unpacked[47] = extractBits(val_7, 11u, 5u);\n unpacked[48] = extractBits(val_7, 16u, 5u);\n unpacked[49] = extractBits(val_7, 21u, 5u);\n unpacked[50] = extractBits(val_7, 26u, 5u);\n unpacked[51] = extractBits(val_7, 31u, 1u);\n\n let val_8 = blocks[packed_offset + 8];\n unpacked[51] = insertBits(unpacked[51], extractBits(val_8, 0u, 4u), 1u, 4u);\n unpacked[52] = extractBits(val_8, 4u, 5u);\n unpacked[53] = extractBits(val_8, 9u, 5u);\n unpacked[54] = extractBits(val_8, 14u, 5u);\n unpacked[55] = extractBits(val_8, 19u, 5u);\n unpacked[56] = extractBits(val_8, 24u, 5u);\n unpacked[57] = extractBits(val_8, 29u, 3u);\n \n let val_9 = blocks[packed_offset + 9];\n unpacked[57] = insertBits(unpacked[57], extractBits(val_9, 0u, 2u), 3u, 2u);\n unpacked[58] = extractBits(val_9, 2u, 5u);\n unpacked[59] = extractBits(val_9, 7u, 5u);\n unpacked[60] = extractBits(val_9, 12u, 5u);\n unpacked[61] = extractBits(val_9, 17u, 5u);\n unpacked[62] = extractBits(val_9, 22u, 5u);\n unpacked[63] = extractBits(val_9, 27u, 5u);\n \n let val_10 = blocks[packed_offset + 10];\n unpacked[64] = extractBits(val_10, 0u, 5u);\n unpacked[65] = extractBits(val_10, 5u, 5u);\n unpacked[66] = extractBits(val_10, 10u, 5u);\n unpacked[67] = extractBits(val_10, 15u, 5u);\n unpacked[68] = extractBits(val_10, 20u, 5u);\n unpacked[69] = extractBits(val_10, 25u, 5u);\n unpacked[70] = extractBits(val_10, 30u, 2u);\n\n let val_11 = blocks[packed_offset + 11];\n unpacked[70] = insertBits(unpacked[70], extractBits(val_11, 0u, 3u), 2u, 3u);\n unpacked[71] = extractBits(val_11, 3u, 5u);\n unpacked[72] = extractBits(val_11, 8u, 5u);\n unpacked[73] = extractBits(val_11, 13u, 5u);\n unpacked[74] = extractBits(val_11, 18u, 5u);\n unpacked[75] = extractBits(val_11, 23u, 5u);\n unpacked[76] = extractBits(val_11, 28u, 4u);\n\n let val_12 = blocks[packed_offset + 12];\n unpacked[76] = insertBits(unpacked[76], extractBits(val_12, 0u, 1u), 4u, 1u);\n unpacked[77] = extractBits(val_12, 1u, 5u);\n unpacked[78] = extractBits(val_12, 6u, 5u);\n unpacked[79] = extractBits(val_12, 11u, 5u);\n unpacked[80] = extractBits(val_12, 16u, 5u);\n unpacked[81] = extractBits(val_12, 21u, 5u);\n unpacked[82] = extractBits(val_12, 26u, 5u);\n unpacked[83] = extractBits(val_12, 31u, 1u);\n\n let val_13 = blocks[packed_offset + 13];\n unpacked[83] = insertBits(unpacked[83], extractBits(val_13, 0u, 4u), 1u, 4u);\n unpacked[84] = extractBits(val_13, 4u, 5u);\n unpacked[85] = extractBits(val_13, 9u, 5u);\n unpacked[86] = extractBits(val_13, 14u, 5u);\n unpacked[87] = extractBits(val_13, 19u, 5u);\n unpacked[88] = extractBits(val_13, 24u, 5u);\n unpacked[89] = extractBits(val_13, 29u, 3u);\n \n let val_14 = blocks[packed_offset + 14];\n unpacked[89] = insertBits(unpacked[89], extractBits(val_14, 0u, 2u), 3u, 2u);\n unpacked[90] = extractBits(val_14, 2u, 5u);\n unpacked[91] = extractBits(val_14, 7u, 5u);\n unpacked[92] = extractBits(val_14, 12u, 5u);\n unpacked[93] = extractBits(val_14, 17u, 5u);\n unpacked[94] = extractBits(val_14, 22u, 5u);\n unpacked[95] = extractBits(val_14, 27u, 5u);\n\n let val_15 = blocks[packed_offset + 15];\n unpacked[96] = extractBits(val_15, 0u, 5u);\n unpacked[97] = extractBits(val_15, 5u, 5u);\n unpacked[98] = extractBits(val_15, 10u, 5u);\n unpacked[99] = extractBits(val_15, 15u, 5u);\n unpacked[100] = extractBits(val_15, 20u, 5u);\n unpacked[101] = extractBits(val_15, 25u, 5u);\n unpacked[102] = extractBits(val_15, 30u, 2u);\n\n let val_16 = blocks[packed_offset + 16];\n unpacked[102] = insertBits(unpacked[102], extractBits(val_16, 0u, 3u), 2u, 3u);\n unpacked[103] = extractBits(val_16, 3u, 5u);\n unpacked[104] = extractBits(val_16, 8u, 5u);\n unpacked[105] = extractBits(val_16, 13u, 5u);\n unpacked[106] = extractBits(val_16, 18u, 5u);\n unpacked[107] = extractBits(val_16, 23u, 5u);\n unpacked[108] = extractBits(val_16, 28u, 4u);\n\n let val_17 = blocks[packed_offset + 17];\n unpacked[108] = insertBits(unpacked[108], extractBits(val_17, 0u, 1u), 4u, 1u);\n unpacked[109] = extractBits(val_17, 1u, 5u);\n unpacked[110] = extractBits(val_17, 6u, 5u);\n unpacked[111] = extractBits(val_17, 11u, 5u);\n unpacked[112] = extractBits(val_17, 16u, 5u);\n unpacked[113] = extractBits(val_17, 21u, 5u);\n unpacked[114] = extractBits(val_17, 26u, 5u);\n unpacked[115] = extractBits(val_17, 31u, 1u);\n \n let val_18 = blocks[packed_offset + 18];\n unpacked[115] = insertBits(unpacked[115], extractBits(val_18, 0u, 4u), 1u, 4u);\n unpacked[116] = extractBits(val_18, 4u, 5u);\n unpacked[117] = extractBits(val_18, 9u, 5u);\n unpacked[118] = extractBits(val_18, 14u, 5u);\n unpacked[119] = extractBits(val_18, 19u, 5u);\n unpacked[120] = extractBits(val_18, 24u, 5u);\n unpacked[121] = extractBits(val_18, 29u, 3u);\n\n let val_19 = blocks[packed_offset + 19];\n unpacked[121] = insertBits(unpacked[121], extractBits(val_19, 0u, 2u), 3u, 2u);\n unpacked[122] = extractBits(val_19, 2u, 5u);\n unpacked[123] = extractBits(val_19, 7u, 5u);\n unpacked[124] = extractBits(val_19, 12u, 5u);\n unpacked[125] = extractBits(val_19, 17u, 5u);\n unpacked[126] = extractBits(val_19, 22u, 5u);\n unpacked[127] = extractBits(val_19, 27u, 5u);\n}\n";var unpackBlock128BitDepth6="\nvar unpacked: array;\n\nfn unpack_block_128_bit_depth_6(packed_offset: u32) {\n let val_0 = blocks[packed_offset];\n unpacked[0] = extractBits(val_0, 0u, 6u);\n unpacked[1] = extractBits(val_0, 6u, 6u);\n unpacked[2] = extractBits(val_0, 12u, 6u);\n unpacked[3] = extractBits(val_0, 18u, 6u);\n unpacked[4] = extractBits(val_0, 24u, 6u);\n unpacked[5] = extractBits(val_0, 30u, 2u);\n \n let val_1 = blocks[packed_offset + 1];\n unpacked[5] = insertBits(unpacked[5], extractBits(val_1, 0u, 4u), 2u, 4u);\n unpacked[6] = extractBits(val_1, 4u, 6u);\n unpacked[7] = extractBits(val_1, 10u, 6u);\n unpacked[8] = extractBits(val_1, 16u, 6u);\n unpacked[9] = extractBits(val_1, 22u, 6u);\n unpacked[10] = extractBits(val_1, 28u, 4u);\n \n let val_2 = blocks[packed_offset + 2];\n unpacked[10] = insertBits(unpacked[10], extractBits(val_2, 0u, 2u), 4u, 2u);\n unpacked[11] = extractBits(val_2, 2u, 6u);\n unpacked[12] = extractBits(val_2, 8u, 6u);\n unpacked[13] = extractBits(val_2, 14u, 6u);\n unpacked[14] = extractBits(val_2, 20u, 6u);\n unpacked[15] = extractBits(val_2, 26u, 6u);\n \n let val_3 = blocks[packed_offset + 3];\n unpacked[16] = extractBits(val_3, 0u, 6u);\n unpacked[17] = extractBits(val_3, 6u, 6u);\n unpacked[18] = extractBits(val_3, 12u, 6u);\n unpacked[19] = extractBits(val_3, 18u, 6u);\n unpacked[20] = extractBits(val_3, 24u, 6u);\n unpacked[21] = extractBits(val_3, 30u, 2u);\n \n let val_4 = blocks[packed_offset + 4];\n unpacked[21] = insertBits(unpacked[21], extractBits(val_4, 0u, 4u), 2u, 4u);\n unpacked[22] = extractBits(val_4, 4u, 6u);\n unpacked[23] = extractBits(val_4, 10u, 6u);\n unpacked[24] = extractBits(val_4, 16u, 6u);\n unpacked[25] = extractBits(val_4, 22u, 6u);\n unpacked[26] = extractBits(val_4, 28u, 4u);\n\n let val_5 = blocks[packed_offset + 5];\n unpacked[26] = insertBits(unpacked[26], extractBits(val_5, 0u, 2u), 4u, 2u);\n unpacked[27] = extractBits(val_5, 2u, 6u);\n unpacked[28] = extractBits(val_5, 8u, 6u);\n unpacked[29] = extractBits(val_5, 14u, 6u);\n unpacked[30] = extractBits(val_5, 20u, 6u);\n unpacked[31] = extractBits(val_5, 26u, 6u);\n\n let val_6 = blocks[packed_offset + 6];\n unpacked[32] = extractBits(val_6, 0u, 6u);\n unpacked[33] = extractBits(val_6, 6u, 6u);\n unpacked[34] = extractBits(val_6, 12u, 6u);\n unpacked[35] = extractBits(val_6, 18u, 6u);\n unpacked[36] = extractBits(val_6, 24u, 6u);\n unpacked[37] = extractBits(val_6, 30u, 2u);\n\n let val_7 = blocks[packed_offset + 7];\n unpacked[37] = insertBits(unpacked[37], extractBits(val_7, 0u, 4u), 2u, 4u);\n unpacked[38] = extractBits(val_7, 4u, 6u);\n unpacked[39] = extractBits(val_7, 10u, 6u);\n unpacked[40] = extractBits(val_7, 16u, 6u);\n unpacked[41] = extractBits(val_7, 22u, 6u);\n unpacked[42] = extractBits(val_7, 28u, 4u);\n \n let val_8 = blocks[packed_offset + 8];\n unpacked[42] = insertBits(unpacked[42], extractBits(val_8, 0u, 2u), 4u, 2u);\n unpacked[43] = extractBits(val_8, 2u, 6u);\n unpacked[44] = extractBits(val_8, 8u, 6u);\n unpacked[45] = extractBits(val_8, 14u, 6u);\n unpacked[46] = extractBits(val_8, 20u, 6u);\n unpacked[47] = extractBits(val_8, 26u, 6u);\n\n let val_9 = blocks[packed_offset + 9];\n unpacked[48] = extractBits(val_9, 0u, 6u);\n unpacked[49] = extractBits(val_9, 6u, 6u);\n unpacked[50] = extractBits(val_9, 12u, 6u);\n unpacked[51] = extractBits(val_9, 18u, 6u);\n unpacked[52] = extractBits(val_9, 24u, 6u);\n unpacked[53] = extractBits(val_9, 30u, 2u);\n\n let val_10 = blocks[packed_offset + 10];\n unpacked[53] = insertBits(unpacked[53], extractBits(val_10, 0u, 4u), 2u, 4u);\n unpacked[54] = extractBits(val_10, 4u, 6u);\n unpacked[55] = extractBits(val_10, 10u, 6u);\n unpacked[56] = extractBits(val_10, 16u, 6u);\n unpacked[57] = extractBits(val_10, 22u, 6u);\n unpacked[58] = extractBits(val_10, 28u, 4u);\n\n let val_11 = blocks[packed_offset + 11];\n unpacked[58] = insertBits(unpacked[58], extractBits(val_11, 0u, 2u), 4u, 2u);\n unpacked[59] = extractBits(val_11, 2u, 6u);\n unpacked[60] = extractBits(val_11, 8u, 6u);\n unpacked[61] = extractBits(val_11, 14u, 6u);\n unpacked[62] = extractBits(val_11, 20u, 6u);\n unpacked[63] = extractBits(val_11, 26u, 6u);\n \n let val_12 = blocks[packed_offset + 12];\n unpacked[64] = extractBits(val_12, 0u, 6u);\n unpacked[65] = extractBits(val_12, 6u, 6u);\n unpacked[66] = extractBits(val_12, 12u, 6u);\n unpacked[67] = extractBits(val_12, 18u, 6u);\n unpacked[68] = extractBits(val_12, 24u, 6u);\n unpacked[69] = extractBits(val_12, 30u, 2u);\n\n let val_13 = blocks[packed_offset + 13];\n unpacked[69] = insertBits(unpacked[69], extractBits(val_13, 0u, 4u), 2u, 4u);\n unpacked[70] = extractBits(val_13, 4u, 6u);\n unpacked[71] = extractBits(val_13, 10u, 6u);\n unpacked[72] = extractBits(val_13, 16u, 6u);\n unpacked[73] = extractBits(val_13, 22u, 6u);\n unpacked[74] = extractBits(val_13, 28u, 4u);\n\n let val_14 = blocks[packed_offset + 14];\n unpacked[74] = insertBits(unpacked[74], extractBits(val_14, 0u, 2u), 4u, 2u);\n unpacked[75] = extractBits(val_14, 2u, 6u);\n unpacked[76] = extractBits(val_14, 8u, 6u);\n unpacked[77] = extractBits(val_14, 14u, 6u);\n unpacked[78] = extractBits(val_14, 20u, 6u);\n unpacked[79] = extractBits(val_14, 26u, 6u);\n\n let val_15 = blocks[packed_offset + 15];\n unpacked[80] = extractBits(val_15, 0u, 6u);\n unpacked[81] = extractBits(val_15, 6u, 6u);\n unpacked[82] = extractBits(val_15, 12u, 6u);\n unpacked[83] = extractBits(val_15, 18u, 6u);\n unpacked[84] = extractBits(val_15, 24u, 6u);\n unpacked[85] = extractBits(val_15, 30u, 2u);\n \n let val_16 = blocks[packed_offset + 16];\n unpacked[85] = insertBits(unpacked[85], extractBits(val_16, 0u, 4u), 2u, 4u);\n unpacked[86] = extractBits(val_16, 4u, 6u);\n unpacked[87] = extractBits(val_16, 10u, 6u);\n unpacked[88] = extractBits(val_16, 16u, 6u);\n unpacked[89] = extractBits(val_16, 22u, 6u);\n unpacked[90] = extractBits(val_16, 28u, 4u);\n\n let val_17 = blocks[packed_offset + 17];\n unpacked[90] = insertBits(unpacked[90], extractBits(val_17, 0u, 2u), 4u, 2u);\n unpacked[91] = extractBits(val_17, 2u, 6u);\n unpacked[92] = extractBits(val_17, 8u, 6u);\n unpacked[93] = extractBits(val_17, 14u, 6u);\n unpacked[94] = extractBits(val_17, 20u, 6u);\n unpacked[95] = extractBits(val_17, 26u, 6u);\n\n let val_18 = blocks[packed_offset + 18];\n unpacked[96] = extractBits(val_18, 0u, 6u);\n unpacked[97] = extractBits(val_18, 6u, 6u);\n unpacked[98] = extractBits(val_18, 12u, 6u);\n unpacked[99] = extractBits(val_18, 18u, 6u);\n unpacked[100] = extractBits(val_18, 24u, 6u);\n unpacked[101] = extractBits(val_18, 30u, 2u);\n\n let val_19 = blocks[packed_offset + 19];\n unpacked[101] = insertBits(unpacked[101], extractBits(val_19, 0u, 4u), 2u, 4u);\n unpacked[102] = extractBits(val_19, 4u, 6u);\n unpacked[103] = extractBits(val_19, 10u, 6u);\n unpacked[104] = extractBits(val_19, 16u, 6u);\n unpacked[105] = extractBits(val_19, 22u, 6u);\n unpacked[106] = extractBits(val_19, 28u, 4u);\n \n let val_20 = blocks[packed_offset + 20];\n unpacked[106] = insertBits(unpacked[106], extractBits(val_20, 0u, 2u), 4u, 2u);\n unpacked[107] = extractBits(val_20, 2u, 6u);\n unpacked[108] = extractBits(val_20, 8u, 6u);\n unpacked[109] = extractBits(val_20, 14u, 6u);\n unpacked[110] = extractBits(val_20, 20u, 6u);\n unpacked[111] = extractBits(val_20, 26u, 6u);\n\n let val_21 = blocks[packed_offset + 21];\n unpacked[112] = extractBits(val_21, 0u, 6u);\n unpacked[113] = extractBits(val_21, 6u, 6u);\n unpacked[114] = extractBits(val_21, 12u, 6u);\n unpacked[115] = extractBits(val_21, 18u, 6u);\n unpacked[116] = extractBits(val_21, 24u, 6u);\n unpacked[117] = extractBits(val_21, 30u, 2u);\n\n let val_22 = blocks[packed_offset + 22];\n unpacked[117] = insertBits(unpacked[117], extractBits(val_22, 0u, 4u), 2u, 4u);\n unpacked[118] = extractBits(val_22, 4u, 6u);\n unpacked[119] = extractBits(val_22, 10u, 6u);\n unpacked[120] = extractBits(val_22, 16u, 6u);\n unpacked[121] = extractBits(val_22, 22u, 6u);\n unpacked[122] = extractBits(val_22, 28u, 4u);\n\n let val_23 = blocks[packed_offset + 23];\n unpacked[122] = insertBits(unpacked[122], extractBits(val_23, 0u, 2u), 4u, 2u);\n unpacked[123] = extractBits(val_23, 2u, 6u);\n unpacked[124] = extractBits(val_23, 8u, 6u);\n unpacked[125] = extractBits(val_23, 14u, 6u);\n unpacked[126] = extractBits(val_23, 20u, 6u);\n unpacked[127] = extractBits(val_23, 26u, 6u);\n}\n";var unpackBlock128BitDepth7="\nvar unpacked: array;\n\nfn unpack_block_128_bit_depth_7(packed_offset: u32) {\n let val_0 = blocks[packed_offset];\n unpacked[0] = extractBits(val_0, 0u, 7u);\n unpacked[1] = extractBits(val_0, 7u, 7u);\n unpacked[2] = extractBits(val_0, 14u, 7u);\n unpacked[3] = extractBits(val_0, 21u, 7u);\n unpacked[4] = extractBits(val_0, 28u, 4u);\n \n let val_1 = blocks[packed_offset + 1];\n unpacked[4] = insertBits(unpacked[4], extractBits(val_1, 0u, 3u), 4u, 3u);\n unpacked[5] = extractBits(val_1, 3u, 7u);\n unpacked[6] = extractBits(val_1, 10u, 7u);\n unpacked[7] = extractBits(val_1, 17u, 7u);\n unpacked[8] = extractBits(val_1, 24u, 7u);\n unpacked[9] = extractBits(val_1, 31u, 1u);\n \n let val_2 = blocks[packed_offset + 2];\n unpacked[9] = insertBits(unpacked[9], extractBits(val_2, 0u, 6u), 1u, 6u);\n unpacked[10] = extractBits(val_2, 6u, 7u);\n unpacked[11] = extractBits(val_2, 13u, 7u);\n unpacked[12] = extractBits(val_2, 20u, 7u);\n unpacked[13] = extractBits(val_2, 27u, 5u);\n \n let val_3 = blocks[packed_offset + 3];\n unpacked[13] = insertBits(unpacked[13], extractBits(val_3, 0u, 2u), 5u, 2u);\n unpacked[14] = extractBits(val_3, 2u, 7u);\n unpacked[15] = extractBits(val_3, 9u, 7u);\n unpacked[16] = extractBits(val_3, 16u, 7u);\n unpacked[17] = extractBits(val_3, 23u, 7u);\n unpacked[18] = extractBits(val_3, 30u, 2u);\n \n let val_4 = blocks[packed_offset + 4];\n unpacked[18] = insertBits(unpacked[18], extractBits(val_4, 0u, 5u), 2u, 5u);\n unpacked[19] = extractBits(val_4, 5u, 7u);\n unpacked[20] = extractBits(val_4, 12u, 7u);\n unpacked[21] = extractBits(val_4, 19u, 7u);\n unpacked[22] = extractBits(val_4, 26u, 6u);\n \n let val_5 = blocks[packed_offset + 5];\n unpacked[22] = insertBits(unpacked[22], extractBits(val_5, 0u, 1u), 6u, 1u);\n unpacked[23] = extractBits(val_5, 1u, 7u);\n unpacked[24] = extractBits(val_5, 8u, 7u);\n unpacked[25] = extractBits(val_5, 15u, 7u);\n unpacked[26] = extractBits(val_5, 22u, 7u);\n unpacked[27] = extractBits(val_5, 29u, 3u);\n \n let val_6 = blocks[packed_offset + 6];\n unpacked[27] = insertBits(unpacked[27], extractBits(val_6, 0u, 4u), 3u, 4u);\n unpacked[28] = extractBits(val_6, 4u, 7u);\n unpacked[29] = extractBits(val_6, 11u, 7u);\n unpacked[30] = extractBits(val_6, 18u, 7u);\n unpacked[31] = extractBits(val_6, 25u, 7u);\n \n let val_7 = blocks[packed_offset + 7];\n unpacked[32] = extractBits(val_7, 0u, 7u);\n unpacked[33] = extractBits(val_7, 7u, 7u);\n unpacked[34] = extractBits(val_7, 14u, 7u);\n unpacked[35] = extractBits(val_7, 21u, 7u);\n unpacked[36] = extractBits(val_7, 28u, 4u);\n \n let val_8 = blocks[packed_offset + 8];\n unpacked[36] = insertBits(unpacked[36], extractBits(val_8, 0u, 3u), 4u, 3u);\n unpacked[37] = extractBits(val_8, 3u, 7u);\n unpacked[38] = extractBits(val_8, 10u, 7u);\n unpacked[39] = extractBits(val_8, 17u, 7u);\n unpacked[40] = extractBits(val_8, 24u, 7u);\n unpacked[41] = extractBits(val_8, 31u, 1u);\n \n let val_9 = blocks[packed_offset + 9];\n unpacked[41] = insertBits(unpacked[41], extractBits(val_9, 0u, 6u), 1u, 6u);\n unpacked[42] = extractBits(val_9, 6u, 7u);\n unpacked[43] = extractBits(val_9, 13u, 7u);\n unpacked[44] = extractBits(val_9, 20u, 7u);\n unpacked[45] = extractBits(val_9, 27u, 5u);\n \n let val_10 = blocks[packed_offset + 10];\n unpacked[45] = insertBits(unpacked[45], extractBits(val_10, 0u, 2u), 5u, 2u);\n unpacked[46] = extractBits(val_10, 2u, 7u);\n unpacked[47] = extractBits(val_10, 9u, 7u);\n unpacked[48] = extractBits(val_10, 16u, 7u);\n unpacked[49] = extractBits(val_10, 23u, 7u);\n unpacked[50] = extractBits(val_10, 30u, 2u);\n \n let val_11 = blocks[packed_offset + 11];\n unpacked[50] = insertBits(unpacked[50], extractBits(val_11, 0u, 5u), 2u, 5u);\n unpacked[51] = extractBits(val_11, 5u, 7u);\n unpacked[52] = extractBits(val_11, 12u, 7u);\n unpacked[53] = extractBits(val_11, 19u, 7u);\n unpacked[54] = extractBits(val_11, 26u, 6u);\n \n let val_12 = blocks[packed_offset + 12];\n unpacked[54] = insertBits(unpacked[54], extractBits(val_12, 0u, 1u), 6u, 1u);\n unpacked[55] = extractBits(val_12, 1u, 7u);\n unpacked[56] = extractBits(val_12, 8u, 7u);\n unpacked[57] = extractBits(val_12, 15u, 7u);\n unpacked[58] = extractBits(val_12, 22u, 7u);\n unpacked[59] = extractBits(val_12, 29u, 3u);\n \n let val_13 = blocks[packed_offset + 13];\n unpacked[59] = insertBits(unpacked[59], extractBits(val_13, 0u, 4u), 3u, 4u);\n unpacked[60] = extractBits(val_13, 4u, 7u);\n unpacked[61] = extractBits(val_13, 11u, 7u);\n unpacked[62] = extractBits(val_13, 18u, 7u);\n unpacked[63] = extractBits(val_13, 25u, 7u);\n \n let val_14 = blocks[packed_offset + 14];\n unpacked[64] = extractBits(val_14, 0u, 7u);\n unpacked[65] = extractBits(val_14, 7u, 7u);\n unpacked[66] = extractBits(val_14, 14u, 7u);\n unpacked[67] = extractBits(val_14, 21u, 7u);\n unpacked[68] = extractBits(val_14, 28u, 4u);\n \n let val_15 = blocks[packed_offset + 15];\n unpacked[68] = insertBits(unpacked[68], extractBits(val_15, 0u, 3u), 4u, 3u);\n unpacked[69] = extractBits(val_15, 3u, 7u);\n unpacked[70] = extractBits(val_15, 10u, 7u);\n unpacked[71] = extractBits(val_15, 17u, 7u);\n unpacked[72] = extractBits(val_15, 24u, 7u);\n unpacked[73] = extractBits(val_15, 31u, 1u);\n \n let val_16 = blocks[packed_offset + 16];\n unpacked[73] = insertBits(unpacked[73], extractBits(val_16, 0u, 6u), 1u, 6u);\n unpacked[74] = extractBits(val_16, 6u, 7u);\n unpacked[75] = extractBits(val_16, 13u, 7u);\n unpacked[76] = extractBits(val_16, 20u, 7u);\n unpacked[77] = extractBits(val_16, 27u, 5u);\n \n let val_17 = blocks[packed_offset + 17];\n unpacked[77] = insertBits(unpacked[77], extractBits(val_17, 0u, 2u), 5u, 2u);\n unpacked[78] = extractBits(val_17, 2u, 7u);\n unpacked[79] = extractBits(val_17, 9u, 7u);\n unpacked[80] = extractBits(val_17, 16u, 7u);\n unpacked[81] = extractBits(val_17, 23u, 7u);\n unpacked[82] = extractBits(val_17, 30u, 2u);\n \n let val_18 = blocks[packed_offset + 18];\n unpacked[82] = insertBits(unpacked[82], extractBits(val_18, 0u, 5u), 2u, 5u);\n unpacked[83] = extractBits(val_18, 5u, 7u);\n unpacked[84] = extractBits(val_18, 12u, 7u);\n unpacked[85] = extractBits(val_18, 19u, 7u);\n unpacked[86] = extractBits(val_18, 26u, 6u);\n \n let val_19 = blocks[packed_offset + 19];\n unpacked[86] = insertBits(unpacked[86], extractBits(val_19, 0u, 1u), 6u, 1u);\n unpacked[87] = extractBits(val_19, 1u, 7u);\n unpacked[88] = extractBits(val_19, 8u, 7u);\n unpacked[89] = extractBits(val_19, 15u, 7u);\n unpacked[90] = extractBits(val_19, 22u, 7u);\n unpacked[91] = extractBits(val_19, 29u, 3u);\n \n let val_20 = blocks[packed_offset + 20];\n unpacked[91] = insertBits(unpacked[91], extractBits(val_20, 0u, 4u), 3u, 4u);\n unpacked[92] = extractBits(val_20, 4u, 7u);\n unpacked[93] = extractBits(val_20, 11u, 7u);\n unpacked[94] = extractBits(val_20, 18u, 7u);\n unpacked[95] = extractBits(val_20, 25u, 7u);\n \n let val_21 = blocks[packed_offset + 21];\n unpacked[96] = extractBits(val_21, 0u, 7u);\n unpacked[97] = extractBits(val_21, 7u, 7u);\n unpacked[98] = extractBits(val_21, 14u, 7u);\n unpacked[99] = extractBits(val_21, 21u, 7u);\n unpacked[100] = extractBits(val_21, 28u, 4u);\n \n let val_22 = blocks[packed_offset + 22];\n unpacked[100] = insertBits(unpacked[100], extractBits(val_22, 0u, 3u), 4u, 3u);\n unpacked[101] = extractBits(val_22, 3u, 7u);\n unpacked[102] = extractBits(val_22, 10u, 7u);\n unpacked[103] = extractBits(val_22, 17u, 7u);\n unpacked[104] = extractBits(val_22, 24u, 7u);\n unpacked[105] = extractBits(val_22, 31u, 1u);\n \n let val_23 = blocks[packed_offset + 23];\n unpacked[105] = insertBits(unpacked[105], extractBits(val_23, 0u, 6u), 1u, 6u);\n unpacked[106] = extractBits(val_23, 6u, 7u);\n unpacked[107] = extractBits(val_23, 13u, 7u);\n unpacked[108] = extractBits(val_23, 20u, 7u);\n unpacked[109] = extractBits(val_23, 27u, 5u);\n \n let val_24 = blocks[packed_offset + 24];\n unpacked[109] = insertBits(unpacked[109], extractBits(val_24, 0u, 2u), 5u, 2u);\n unpacked[110] = extractBits(val_24, 2u, 7u);\n unpacked[111] = extractBits(val_24, 9u, 7u);\n unpacked[112] = extractBits(val_24, 16u, 7u);\n unpacked[113] = extractBits(val_24, 23u, 7u);\n unpacked[114] = extractBits(val_24, 30u, 2u);\n \n let val_25 = blocks[packed_offset + 25];\n unpacked[114] = insertBits(unpacked[114], extractBits(val_25, 0u, 5u), 2u, 5u);\n unpacked[115] = extractBits(val_25, 5u, 7u);\n unpacked[116] = extractBits(val_25, 12u, 7u);\n unpacked[117] = extractBits(val_25, 19u, 7u);\n unpacked[118] = extractBits(val_25, 26u, 6u);\n \n let val_26 = blocks[packed_offset + 26];\n unpacked[118] = insertBits(unpacked[118], extractBits(val_26, 0u, 1u), 6u, 1u);\n unpacked[119] = extractBits(val_26, 1u, 7u);\n unpacked[120] = extractBits(val_26, 8u, 7u);\n unpacked[121] = extractBits(val_26, 15u, 7u);\n unpacked[122] = extractBits(val_26, 22u, 7u);\n unpacked[123] = extractBits(val_26, 29u, 3u);\n \n let val_27 = blocks[packed_offset + 27];\n unpacked[123] = insertBits(unpacked[123], extractBits(val_27, 0u, 4u), 3u, 4u);\n unpacked[124] = extractBits(val_27, 4u, 7u);\n unpacked[125] = extractBits(val_27, 11u, 7u);\n unpacked[126] = extractBits(val_27, 18u, 7u);\n unpacked[127] = extractBits(val_27, 25u, 7u); \n}\n";var fromFP510Function="\n\nconst exponents: array = array(\n 2.9103830456733704e-11, \n 5.820766091346741e-11, \n 1.1641532182693481e-10, \n 2.3283064365386963e-10,\n 4.656612873077393e-10, \n 9.313225746154785e-10, \n 1.862645149230957e-09, \n 3.725290298461914e-09,\n 7.450580596923828e-09, \n 1.4901161193847656e-08, \n 2.9802322387695312e-08, \n 5.960464477539063e-08,\n 1.1920928955078125e-07, \n 2.384185791015625e-07, \n 4.76837158203125e-07, \n 9.5367431640625e-07,\n 1.9073486328125e-06, \n 3.814697265625e-06, \n 7.62939453125e-06, \n 1.52587890625e-05, \n 3.0517578125e-05,\n 6.103515625e-05, \n 0.0001220703125, \n 0.000244140625, \n 0.00048828125, \n 0.0009765625, \n 0.001953125, \n 0.00390625,\n 0.0078125, \n 0.015625, \n 0.03125, \n 0.0625);\n\nfn from_fp510(x: u32) -> f32 {\n let exponent = f32(exponents[extractBits(x, 10u, 5u)]); \n let fractional = f32(extractBits(x, 0u, 10u)); \n let abs = exponent * fractional;\n return abs * (1.0 - (2.0 * f32(extractBits(x, 15u, 1u))));\n}\n";var preprocessBlocks3BitShaderSource="\n\nstruct argsStruct {\n nbr: u32,\n nbc: u32,\n blocks_offset: u32\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar blocks: array;\n\n".concat(unpackBlock128BitDepth3,"\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= args.nbr || global_id.y >= args.nbc) {\n return;\n }\n \n let blocks_start: u32 = args.blocks_offset + ((global_id.x * args.nbc + global_id.y) * 12u); \n unpack_block_128_bit_depth_3(blocks_start); \n \n let b01: u32 = blocks_start;\n let b2: u32 = blocks_start + 8u;\n \n for (var r = 0u; r < ").concat(rowsPerBlock,"u; r++) {\n let unpacked_idx = r * ").concat(columnsPerBlock,"u;\n let b01_idx = b01 + (r / 2u);\n let b2_idx = b2 + (r / 4u);\n\n blocks[b01_idx] = insertBits(blocks[b01_idx], extractBits(unpacked[unpacked_idx], 0u, 2u), (r * 16u) % 32u, 16u);\n blocks[b2_idx] = insertBits(blocks[b2_idx], extractBits(unpacked[unpacked_idx], 2u, 1u), (r * 8u) % 32u, 8u); \n }\n \n for (var c = 1u; c < ").concat(columnsPerBlock,"u; c++) {\n for (var r = 0u; r < ").concat(rowsPerBlock,"u; r++) {\n let unpacked_idx = r * ").concat(columnsPerBlock,"u + c;\n let b01_idx = b01 + (r / 2u);\n let b2_idx = b2 + (r / 4u);\n \n blocks[b01_idx] = insertBits(blocks[b01_idx], extractBits(unpacked[unpacked_idx], 0u, 2u), ((r * 16u) % 32u) + (2u * c), 2u);\n blocks[b2_idx] = insertBits(blocks[b2_idx], extractBits(unpacked[unpacked_idx], 2u, 1u), ((r * 8u) % 32u) + c, 1u); \n }\n }\n}\n\n").concat(emptyShader);var preprocessBlocks5BitShaderSource="\n\nstruct argsStruct {\n nbr: u32,\n nbc: u32,\n blocks_offset: u32\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar blocks: array;\n\n".concat(unpackBlock128BitDepth5,"\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= args.nbr || global_id.y >= args.nbc) {\n return;\n }\n\n let blocks_start: u32 = args.blocks_offset + ((global_id.x * args.nbc + global_id.y) * 20u);\n unpack_block_128_bit_depth_5(blocks_start); \n \n let b03: u32 = blocks_start;\n let b4: u32 = blocks_start + 16u;\n\n for (var r = 0u; r < ").concat(rowsPerBlock,"u; r++) {\n let unpacked_idx = r * ").concat(columnsPerBlock,"u;\n let b03_idx = b03 + r;\n let b4_idx = b4 + (r / 4u);\n \n blocks[b03_idx] = insertBits(blocks[b03_idx], extractBits(unpacked[unpacked_idx], 0u, 4u), 0u, 32u);\n blocks[b4_idx] = insertBits(blocks[b4_idx], extractBits(unpacked[unpacked_idx], 4u, 1u), (r * 8u) % 32u, 8u);\n }\n \n for (var c = 1u; c < ").concat(columnsPerBlock,"u; c++) {\n for (var r = 0u; r < ").concat(rowsPerBlock,"u; r++) {\n let unpacked_idx = r * ").concat(columnsPerBlock,"u + c;\n let b03_idx = b03 + r;\n let b4_idx = b4 + (r / 4u);\n \n blocks[b03_idx] = insertBits(blocks[b03_idx], extractBits(unpacked[unpacked_idx], 0u, 4u), 4 * c, 4u);\n blocks[b4_idx] = insertBits(blocks[b4_idx], extractBits(unpacked[unpacked_idx], 4u, 1u), ((r * 8u) % 32u) + c, 1u);\n }\n } \n}\n\n").concat(emptyShader);var preprocessBlocks6BitShaderSource="\n\nstruct argsStruct {\n nbr: u32,\n nbc: u32,\n blocks_offset: u32\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar blocks: array;\n\n".concat(unpackBlock128BitDepth6,"\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= args.nbr || global_id.y >= args.nbc) {\n return;\n }\n \n let blocks_start: u32 = args.blocks_offset + ((global_id.x * args.nbc + global_id.y) * 24u);\n unpack_block_128_bit_depth_6(blocks_start);\n \n let b03: u32 = blocks_start;\n let b45: u32 = blocks_start + 16u; \n for (var r = 0u; r < ").concat(rowsPerBlock,"u; r++) {\n let unpacked_idx = r * ").concat(columnsPerBlock,"u;\n let b03_idx = b03 + r;\n let b45_idx = b45 + (r / 2u);\n \n blocks[b03_idx] = insertBits(blocks[b03_idx], extractBits(unpacked[unpacked_idx], 0u, 4u), 0u, 32u);\n blocks[b45_idx] = insertBits(blocks[b45_idx], extractBits(unpacked[unpacked_idx], 4u, 2u), ((r * 16u) % 32u), 16u);\n }\n\n for (var c = 1u; c < ").concat(columnsPerBlock,"u; c++) {\n for (var r = 0u; r < ").concat(rowsPerBlock,"u; r++) {\n let unpacked_idx = r * ").concat(columnsPerBlock,"u + c;\n let b03_idx = b03 + r;\n let b45_idx = b45 + (r / 2u);\n \n blocks[b03_idx] = insertBits(blocks[b03_idx], extractBits(unpacked[unpacked_idx], 0u, 4u), 4 * c, 4u);\n blocks[b45_idx] = insertBits(blocks[b45_idx], extractBits(unpacked[unpacked_idx], 4u, 2u), ((r * 16u) % 32u) + (2 * c), 2u);\n }\n }\n}\n\n").concat(emptyShader);var preprocessBlocks7BitShaderSource="\n\nstruct argsStruct {\n nbr: u32,\n nbc: u32,\n blocks_offset: u32\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar blocks: array;\n\n".concat(unpackBlock128BitDepth7,"\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= args.nbr || global_id.y >= args.nbc) {\n return;\n }\n \n let blocks_start: u32 = args.blocks_offset + ((global_id.x * args.nbc + global_id.y) * 28u);\n unpack_block_128_bit_depth_7(blocks_start);\n \n let b03: u32 = blocks_start;\n let b45: u32 = blocks_start + 16u;\n let b6: u32 = blocks_start + 24u; \n for (var r = 0u; r < ").concat(rowsPerBlock,"u; r++) {\n let unpacked_idx = r * ").concat(columnsPerBlock,"u;\n let b03_idx = b03 + r;\n let b45_idx = b45 + (r / 2u);\n let b6_idx = b6 + (r / 4u);\n \n blocks[b03_idx] = insertBits(blocks[b03_idx], extractBits(unpacked[unpacked_idx], 0u, 4u), 0, 32u);\n blocks[b45_idx] = insertBits(blocks[b45_idx], extractBits(unpacked[unpacked_idx], 4u, 2u), ((r * 16u) % 32u), 16u);\n blocks[b6_idx] = insertBits(blocks[b6_idx], extractBits(unpacked[unpacked_idx], 6u, 1u), ((r * 8u) % 32u), 8u);\n }\n \n for (var c = 1u; c < ").concat(columnsPerBlock,"u; c++) {\n for (var r = 0u; r < ").concat(rowsPerBlock,"u; r++) {\n let unpacked_idx = r * ").concat(columnsPerBlock,"u + c;\n let b03_idx = b03 + r;\n let b45_idx = b45 + (r / 2u);\n let b6_idx = b6 + (r / 4u);\n \n blocks[b03_idx] = insertBits(blocks[b03_idx], extractBits(unpacked[unpacked_idx], 0u, 4u), 4 * c, 4u);\n blocks[b45_idx] = insertBits(blocks[b45_idx], extractBits(unpacked[unpacked_idx], 4u, 2u), ((r * 16u) % 32u) + (2 * c), 2u);\n blocks[b6_idx] = insertBits(blocks[b6_idx], extractBits(unpacked[unpacked_idx], 6u, 1u), ((r * 8u) % 32u) + c, 1u);\n }\n }\n}\n\n").concat(emptyShader);var preprocessShaderSources={3:preprocessBlocks3BitShaderSource,5:preprocessBlocks5BitShaderSource,6:preprocessBlocks6BitShaderSource,7:preprocessBlocks7BitShaderSource};var preprocessShaderNames={3:"pv_picollm_weight_block_mixed_16x8_preprocess_blocks_3bit_shader",5:"pv_picollm_weight_block_mixed_16x8_preprocess_blocks_5bit_shader",6:"pv_picollm_weight_block_mixed_16x8_preprocess_blocks_6bit_shader",7:"pv_picollm_weight_block_mixed_16x8_preprocess_blocks_7bit_shader"};var BM=8;var BN=32;var TM=2;var TN=16;var TC=rowsPerBlock*BM*BN/(TM*TN);var constantSnippet="\nconst BM = ".concat(BM,"u;\nconst BN = ").concat(BN,"u;\n\nconst TM = ").concat(TM,"u;\nconst TN = ").concat(TN,"u;\n\nconst TC = ").concat(TC,"u;\n\nconst ROW_PER_BLOCK = ").concat(rowsPerBlock,"u;\nconst COL_PER_BLOCK = ").concat(columnsPerBlock,"u;\n\nconst VEC_COL_PER_BLOCK = COL_PER_BLOCK / 4u;\n\nconst block_size: u32 = (COL_PER_BLOCK * ROW_PER_BLOCK * bit_depth) / 32u;\n\n");var forwardMultipleInputArgsSnippet="\nstruct argsStruct {\n n: u32,\n m: u32,\n total_nbc: u32,\n k: u32,\n x_offset: u32,\n metas_offset: u32,\n blocks_offset: u32,\n y_offset: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar x: array>;\n\n@group(0) @binding(2)\nvar metas: array;\n\n@group(0) @binding(3)\nvar blocks: array;\n\n@group(0) @binding(4)\nvar y: array;\n";var forwardMultipleSharedPrivateMemSnippet="\nvar shared_x: array, BN * VEC_COL_PER_BLOCK>;\nvar shared_ab: array;\nvar shared_w: array, BM * ROW_PER_BLOCK * VEC_COL_PER_BLOCK>;\n\nvar local_x: array, TN * VEC_COL_PER_BLOCK>;\nvar local_x_sums: array;\nvar local_results: array;\n";var forwardMultipleLocalVarSnippet="\n let tid = local_id.x;\n let bm_idx = workgroup_id.x;\n let bn_idx = workgroup_id.y;\n\n let local_bm_idx = bm_idx * BM;\n let local_bn_idx = bn_idx * BN;\n \n let n_idx = tid % (BN / TN);\n let k_idx = tid / (BN / TN) / (BM * ROW_PER_BLOCK / TM);\n let m_idx = tid / (BN / TN) % (BM * ROW_PER_BLOCK / TM);\n";var forwardMultipleLoadW1Bit="\n let b0 = blocks[src + (row / 4u)];\n\n let b0_offset_base = (row * 8u) % 32u;\n for (var c = 0u; c < VEC_COL_PER_BLOCK; c++) {\n let b0_offset = b0_offset_base + (c * 4u); \n shared_w[dst + c] = vec4(\n f32(extractBits(b0, b0_offset, 1u)), \n f32(extractBits(b0, b0_offset + 1, 1u)),\n f32(extractBits(b0, b0_offset + 2, 1u)),\n f32(extractBits(b0, b0_offset + 3, 1u)));\n }\n";var forwardMultipleLoadW2Bit="\n let b01 = blocks[src + (row / 2u)];\n \n let b01_offset_base = (row * 16u) % 32u;\n for (var c = 0u; c < VEC_COL_PER_BLOCK; c++) { \n let b01_offset = b01_offset_base + (c * 8u);\n shared_w[dst + c] = vec4(\n f32(extractBits(b01, b01_offset, 2u)), \n f32(extractBits(b01, b01_offset + 2, 2u)),\n f32(extractBits(b01, b01_offset + 4, 2u)),\n f32(extractBits(b01, b01_offset + 6, 2u)));\n } \n";var forwardMultipleLoadW3Bit="\n let b01 = blocks[src + (row / 2u)];\n let b2 = blocks[src + 8u + (row / 4u)]; \n\n let b01_offset_base = (row * 16u) % 32u;\n let b2_offset_base = (row * 8u) % 32u;\n for (var c = 0u; c < VEC_COL_PER_BLOCK; c++) {\n let b01_offset = b01_offset_base + (c * 8u);\n let b2_offset = b2_offset_base + (c * 4u);\n\n shared_w[dst + c] = vec4(\n f32(insertBits(extractBits(b01, b01_offset, 2u), extractBits(b2, b2_offset, 1u), 2u, 1u)), \n f32(insertBits(extractBits(b01, b01_offset + 2, 2u), extractBits(b2, b2_offset + 1, 1u), 2u, 1u)),\n f32(insertBits(extractBits(b01, b01_offset + 4, 2u), extractBits(b2, b2_offset + 2, 1u), 2u, 1u)),\n f32(insertBits(extractBits(b01, b01_offset + 6, 2u), extractBits(b2, b2_offset + 3, 1u), 2u, 1u))); \n }\n";var forwardMultipleLoadW4Bit="\n let b03 = blocks[src + row];\n \n for (var c = 0u; c < VEC_COL_PER_BLOCK; c++) {\n let b03_offset = (c * 16u); \n shared_w[dst + c] = vec4(\n f32(extractBits(b03, b03_offset, 4u)), \n f32(extractBits(b03, b03_offset + 4, 4u)),\n f32(extractBits(b03, b03_offset + 8, 4u)),\n f32(extractBits(b03, b03_offset + 12, 4u)));\n }\n";var forwardMultipleLoadW5Bit="\n let b03 = blocks[src + row];\n let b4 = blocks[src + 16u + (row / 4u)];\n \n let b4_offset_base = (row * 8u) % 32u;\n for (var c = 0u; c < VEC_COL_PER_BLOCK; c++) {\n let b03_offset = (c * 16u);\n let b4_offset = b4_offset_base + (c * 4u);\n shared_w[dst + c] = vec4(\n f32(insertBits(extractBits(b03, b03_offset, 4u), extractBits(b4, b4_offset, 1u), 4u, 1u)), \n f32(insertBits(extractBits(b03, b03_offset + 4, 4u), extractBits(b4, b4_offset + 1, 1u), 4u, 1u)),\n f32(insertBits(extractBits(b03, b03_offset + 8, 4u), extractBits(b4, b4_offset + 2, 1u), 4u, 1u)),\n f32(insertBits(extractBits(b03, b03_offset + 12, 4u), extractBits(b4, b4_offset + 3, 1u), 4u, 1u)));\n }\n";var forwardMultipleLoadW6Bit="\n let b03 = blocks[src + row];\n let b45 = blocks[src + 16u + (row / 2u)];\n \n let b45_offset_base = (row * 16u) % 32u;\n for (var c = 0u; c < VEC_COL_PER_BLOCK; c++) { \n let b03_offset = (c * 16u);\n let b45_offset = b45_offset_base + (c * 8u);\n shared_w[dst + c] = vec4(\n f32(insertBits(extractBits(b03, b03_offset, 4u), extractBits(b45, b45_offset, 2u), 4u, 2u)), \n f32(insertBits(extractBits(b03, b03_offset + 4, 4u), extractBits(b45, b45_offset + 2, 2u), 4u, 2u)),\n f32(insertBits(extractBits(b03, b03_offset + 8, 4u), extractBits(b45, b45_offset + 4, 2u), 4u, 2u)),\n f32(insertBits(extractBits(b03, b03_offset + 12, 4u), extractBits(b45, b45_offset + 6, 2u), 4u, 2u)));\n }\n";var forwardMultipleLoadW7Bit="\n let b03 = blocks[src + row];\n let b45 = blocks[src + 16u + (row / 2u)];\n let b6 = blocks[src + 24u + (row / 4u)];\n \n let b45_offset_base = (row * 16u) % 32u;\n let b6_offset_base = (row * 8u) % 32u;\n for (var c = 0u; c < VEC_COL_PER_BLOCK; c++) {\n let b03_offset = (c * 16u);\n let b45_offset = b45_offset_base + (c * 8u);\n let b6_offset = b6_offset_base + (c * 4u);\n \n shared_w[dst + c] = vec4(\n f32(insertBits(insertBits(extractBits(b03, b03_offset, 4u), extractBits(b45, b45_offset, 2u), 4u, 2u), extractBits(b6, b6_offset, 1u), 6u, 1u)), \n f32(insertBits(insertBits(extractBits(b03, b03_offset + 4, 4u), extractBits(b45, b45_offset + 2, 2u), 4u, 2u), extractBits(b6, b6_offset + 1, 1u), 6u, 1u)),\n f32(insertBits(insertBits(extractBits(b03, b03_offset + 8, 4u), extractBits(b45, b45_offset + 4, 2u), 4u, 2u), extractBits(b6, b6_offset + 2, 1u), 6u, 1u)),\n f32(insertBits(insertBits(extractBits(b03, b03_offset + 12, 4u), extractBits(b45, b45_offset + 6, 2u), 4u, 2u), extractBits(b6, b6_offset + 3, 1u), 6u, 1u)));\n }\n";var forwardMultipleLoadW8Bit="\n let b07_offset = src + (row * 2);\n \n for (var c = 0u; c < VEC_COL_PER_BLOCK; c++) {\n let b07 = blocks[b07_offset + c];\n shared_w[dst + c] = vec4(\n f32(extractBits(b07, 0u, 8u)), \n f32(extractBits(b07, 8u, 8u)),\n f32(extractBits(b07, 16u, 8u)),\n f32(extractBits(b07, 24u, 8u)));\n }\n";var forwardLoadWBitDepthSnippets={1:forwardMultipleLoadW1Bit,2:forwardMultipleLoadW2Bit,3:forwardMultipleLoadW3Bit,4:forwardMultipleLoadW4Bit,5:forwardMultipleLoadW5Bit,6:forwardMultipleLoadW6Bit,7:forwardMultipleLoadW7Bit,8:forwardMultipleLoadW8Bit};var forwardMultipleLoadXSnippet="\n let total_work_x = VEC_COL_PER_BLOCK * BN;\n for (var local_idx = 0u; local_idx < divide_pad(total_work_x, TC); local_idx++) {\n let idx = local_idx * TC + tid;\n if (idx < total_work_x) { \n let n_load_idx = local_bn_idx + idx / VEC_COL_PER_BLOCK;\n let inner_idx = idx % VEC_COL_PER_BLOCK;\n \n if (bk_idx < args.k && n_load_idx < args.n) { \n let x_idx = (args.x_offset / 4u) + ((bk_idx * args.n + n_load_idx) * VEC_COL_PER_BLOCK + inner_idx); \n shared_x[idx] = x[x_idx];\n } else {\n shared_x[idx] = vec4(0.0);\n }\n }\n }\n";var forwardMultipleLoadABSnippet="\n let total_work_ab = BM * 2;\n for (var local_idx = 0u; local_idx < divide_pad(total_work_ab, TC); local_idx++) {\n let idx = local_idx * TC + tid;\n if (idx < total_work_ab) {\n let m_load_idx = local_bm_idx + idx / 2; \n let inner_idx = (idx % 2) * 16u;\n \n if (m_load_idx < args.m && bk_idx < args.k) {\n let ab_bits = extractBits(metas[args.metas_offset + (m_load_idx * args.k + bk_idx)], inner_idx, 16u);\n shared_ab[idx] = from_fp510(ab_bits); \n } else {\n shared_ab[idx] = 0.0;\n }\n }\n }\n";var forwardMultipleLoadWSnippet=function forwardMultipleLoadWSnippet(bitDepth){return"\n let total_work_w = BM * ROW_PER_BLOCK;\n for (var local_idx = 0u; local_idx < divide_pad(total_work_w, TC); local_idx++) {\n let idx = local_idx * TC + tid;\n if (idx < total_work_w) {\n let m_load_idx = local_bm_idx + idx / ROW_PER_BLOCK;\n let row = idx % ROW_PER_BLOCK;\n let dst = idx * VEC_COL_PER_BLOCK;\n\n if (m_load_idx < args.m) {\n let src = args.blocks_offset + (m_load_idx * args.k + bk_idx) * block_size;\n ".concat(forwardLoadWBitDepthSnippets[bitDepth],"\n } else { \n for (var c = 0u; c < VEC_COL_PER_BLOCK; c++) {\n shared_w[dst + c] = vec4(0.0);\n }\n }\n }\n }\n")};var forwardMultipleCopyXSnippet="\nfor (var tn_idx = 0u; tn_idx < TN; tn_idx++) { \n var x_sum_vec = vec4(0.0); \n let local_x_idx = tn_idx * VEC_COL_PER_BLOCK;\n let shared_x_idx = (n_idx * TN + tn_idx) * VEC_COL_PER_BLOCK + (k_idx * VEC_COL_PER_BLOCK);\n for (var c = 0u; c < VEC_COL_PER_BLOCK; c++) {\n local_x[local_x_idx + c] = shared_x[shared_x_idx + c];\n x_sum_vec += local_x[local_x_idx + c];\n }\n local_x_sums[tn_idx] = x_sum_vec.x + x_sum_vec.y + x_sum_vec.z + x_sum_vec.w; \n}\n";var forwardMultipleComputeResultsSnippet="\n for (var tm_idx = 0u; tm_idx < TM; tm_idx++) { \n let shared_ab_idx = ((m_idx * TM + tm_idx) / ROW_PER_BLOCK + k_idx) * 2;\n let alpha = shared_ab[shared_ab_idx];\n let beta = shared_ab[shared_ab_idx + 1]; \n let shared_w_idx = ((m_idx * TM + tm_idx) + k_idx) * VEC_COL_PER_BLOCK;\n \n for (var tn_idx = 0u; tn_idx < TN; tn_idx++) { \n let local_x_idx = tn_idx * VEC_COL_PER_BLOCK;\n \n var swx_vec = vec4(0.0); \n for (var c = 0u; c < VEC_COL_PER_BLOCK; c++) { \n swx_vec += shared_w[shared_w_idx + c] * local_x[local_x_idx + c];\n }\n let swx = swx_vec.x + swx_vec.y + swx_vec.z + swx_vec.w;\n \n let kappa = alpha * local_x_sums[tn_idx]; \n let results_idx = tm_idx * TN + tn_idx;\n local_results[results_idx] += kappa + (beta * swx);\n }\n }\n";var forwardMultipleWriteResultsSnippet="\nfor (var tm_idx = 0u; tm_idx < TM; tm_idx++) {\n let row = local_bm_idx * ROW_PER_BLOCK + (m_idx * TM + tm_idx); \n for (var tn_idx = 0u; tn_idx < TN; tn_idx++) { \n let col = local_bn_idx + (n_idx * TN + tn_idx);\n if (row < args.m * ROW_PER_BLOCK && col < args.n) {\n let y_idx = args.y_offset + ((row / ROW_PER_BLOCK) * args.n + col) * ROW_PER_BLOCK + (row % ROW_PER_BLOCK);\n let results_idx = tm_idx * TN + tn_idx;\n \n y[y_idx] += local_results[results_idx];\n }\n }\n}\n";var forwardMultipleShaderSources=function forwardMultipleShaderSources(bitDepth){return"\n\n".concat(forwardMultipleInputArgsSnippet,"\n\n").concat(constantSnippet,"\n\n").concat(forwardMultipleSharedPrivateMemSnippet,"\n\n").concat(fromFP510Function,"\n\n").concat(dividePadFunction,"\n\nconst bit_depth: u32 = ").concat(bitDepth,"u;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n \n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(\n @builtin(local_invocation_id) local_id: vec3,\n @builtin(workgroup_id) workgroup_id: vec3\n) {\n ").concat(forwardMultipleLocalVarSnippet,"\n \n for (var bk_idx = 0u; bk_idx < args.k; bk_idx++) { \n ").concat(forwardMultipleLoadXSnippet,"\n ").concat(forwardMultipleLoadABSnippet," \n ").concat(forwardMultipleLoadWSnippet(bitDepth)," \n workgroupBarrier();\n \n ").concat(forwardMultipleCopyXSnippet,"\n ").concat(forwardMultipleComputeResultsSnippet,"\n workgroupBarrier();\n }\n \n ").concat(forwardMultipleWriteResultsSnippet,"\n}\n\n").concat(emptyShader,"\n")};var forwardShuffleXShaderSource="\nstruct argsStruct {\n n: u32,\n shape1: u32,\n x_offset: u32,\n indices_offset: u32, \n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar x: array;\n\n@group(0) @binding(2)\nvar indices: array;\n\n@group(0) @binding(3)\nvar y: array;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= args.n || global_id.y >= args.shape1) {\n return;\n } \n\n let b = global_id.x;\n let i = global_id.y;\n \n let c = i / 8u;\n let j = i % 8u;\n y[((c * args.n) + b) * 8 + j] = x[args.x_offset + (b * args.shape1) + indices[args.indices_offset + i]];\n}\n\n".concat(emptyShader,"\n");var forwardSingleReduceYShaderSource="\nstruct argsStruct {\n nvr: u32,\n nbc: u32, \n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar x: array>;\n\n@group(0) @binding(2)\nvar y: array>;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) { \n if (global_id.x > args.nvr) {\n return;\n }\n\n let x_start = global_id.x * args.nbc;\n var sum: vec4 = vec4(0.0, 0.0, 0.0, 0.0);\n for (var i = 0u; i < args.nbc; i++) {\n sum += x[x_start + i]; \n }\n y[global_id.x] += sum;\n}\n\n".concat(emptyShader);var forwardShuffleYShaderSource="\nstruct argsStruct {\n n: u32,\n shape0: u32, \n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar x: array;\n\n@group(0) @binding(2)\nvar y: array;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= args.n || global_id.y >= args.shape0) {\n return;\n } \n \n let b = global_id.x;\n let i = global_id.y;\n \n let r = i / 16u;\n let j = i % 16u;\n y[(b * args.shape0) + (r * 16) + j] = x[(((r * args.n) + b) * 16) + j];\n}\n\n".concat(emptyShader);var addBiasShaderSource="\nstruct argsStruct {\n dimension: u32\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar bias: array;\n\n@group(0) @binding(2)\nvar y: array;\n\n".concat(fromFP510Function,"\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) { \n y[(global_id.x * args.dimension) + global_id.y] += bias[global_id.y];\n}\n\n").concat(emptyShader);var forwardSingleBitDepth1ShaderSource="\n\nstruct argsStruct {\n n: u32,\n nbr: u32,\n total_nbc: u32,\n bit_depth_nbc: u32,\n x_offset: u32,\n metas_offset: u32,\n blocks_offset: u32,\n y_offset: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar x: array>;\n\n@group(0) @binding(2)\nvar metas: array;\n\n@group(0) @binding(3)\nvar blocks: array;\n\n@group(0) @binding(4)\nvar y: array>;\n\n".concat(fromFP510Function,"\n\nconst block_size: u32 = 4u;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= (args.nbr * 4) || global_id.y >= args.bit_depth_nbc) {\n return;\n }\n\n let r = global_id.x * 4u;\n let c = global_id.y * ").concat(columnsPerBlock,";\n let br = global_id.x / 4u; \n let bc = global_id.y;\n let br_offset = global_id.x % 4u;\n \n let row_metas_start: u32 = args.metas_offset + (br * args.bit_depth_nbc);\n let row_blocks_start: u32 = args.blocks_offset + (br * args.bit_depth_nbc * block_size); \n \n let alpha = from_fp510(extractBits(metas[row_metas_start + bc], 0, 16u)); \n let beta = from_fp510(extractBits(metas[row_metas_start + bc], 16u, 16u));\n \n let x_start = ((args.x_offset + c) / 4u);\n \n var b0_start = row_blocks_start + br_offset + (bc * block_size);\n var b0_offset = 0u;\n \n var res: array, 2u>;\n var x_sum: f32 = 0.0;\n \n for (var j = 0u; j < ").concat(columnsPerBlock,"; j+=4) {\n \n var b0 = blocks[b0_start];\n \n let w0_0 = f32(extractBits(b0, b0_offset + j, 1u)); \n let w0_1 = f32(extractBits(b0, b0_offset + j + 1, 1u)); \n let w0_2 = f32(extractBits(b0, b0_offset + j + 2, 1u));\n let w0_3 = f32(extractBits(b0, b0_offset + j + 3, 1u));\n \n b0_offset = 8u;\n \n let w1_0 = f32(extractBits(b0, b0_offset + j, 1u)); \n let w1_1 = f32(extractBits(b0, b0_offset + j + 1, 1u)); \n let w1_2 = f32(extractBits(b0, b0_offset + j + 2, 1u));\n let w1_3 = f32(extractBits(b0, b0_offset + j + 3, 1u));\n \n b0_offset = 16u;\n \n let w2_0 = f32(extractBits(b0, b0_offset + j, 1u)); \n let w2_1 = f32(extractBits(b0, b0_offset + j + 1, 1u)); \n let w2_2 = f32(extractBits(b0, b0_offset + j + 2, 1u));\n let w2_3 = f32(extractBits(b0, b0_offset + j + 3, 1u));\n \n b0_offset = 24u;\n \n let w3_0 = f32(extractBits(b0, b0_offset + j, 1u)); \n let w3_1 = f32(extractBits(b0, b0_offset + j + 1, 1u)); \n let w3_2 = f32(extractBits(b0, b0_offset + j + 2, 1u));\n let w3_3 = f32(extractBits(b0, b0_offset + j + 3, 1u));\n \n b0_offset = 0u;\n \n let m = mat4x4(\n w0_0, w1_0, w2_0, w3_0,\n w0_1, w1_1, w2_1, w3_1, \n w0_2, w1_2, w2_2, w3_2,\n w0_3, w1_3, w2_3, w3_3);\n\n let x_idx = (j / 4u);\n let x_vec = x[x_start + x_idx];\n res[x_idx] = m * x_vec;\n \n x_sum += x_vec.x + x_vec.y + x_vec.z + x_vec.w; \n }\n \n let swx = res[0] + res[1];\n let kappa = alpha * x_sum;\n \n let y_start = (args.y_offset + (r * args.total_nbc)) / 4u;\n y[y_start + bc] += (swx * beta) + vec4(kappa);\n}\n\n").concat(emptyShader);var forwardSingleBitDepth2ShaderSource="\n\nstruct argsStruct {\n n: u32,\n nbr: u32,\n total_nbc: u32,\n bit_depth_nbc: u32,\n x_offset: u32,\n metas_offset: u32,\n blocks_offset: u32,\n y_offset: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar x: array>;\n\n@group(0) @binding(2)\nvar metas: array;\n\n@group(0) @binding(3)\nvar blocks: array;\n\n@group(0) @binding(4)\nvar y: array>;\n\n".concat(fromFP510Function,"\n\nconst block_size: u32 = 8u;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= (args.nbr * 4) || global_id.y >= args.bit_depth_nbc) {\n return;\n }\n\n let r = global_id.x * 4u;\n let c = global_id.y * ").concat(columnsPerBlock,";\n let br = global_id.x / 4u; \n let bc = global_id.y;\n let br_offset = global_id.x % 4u;\n \n let row_metas_start: u32 = args.metas_offset + (br * args.bit_depth_nbc);\n let row_blocks_start: u32 = args.blocks_offset + (br * args.bit_depth_nbc * block_size); \n \n let alpha = from_fp510(extractBits(metas[row_metas_start + bc], 0, 16u)); \n let beta = from_fp510(extractBits(metas[row_metas_start + bc], 16u, 16u));\n \n let x_start = ((args.x_offset + c) / 4u);\n \n var b01_start = row_blocks_start + (br_offset * 2u) + (bc * block_size);\n var b01_offset = 0u;\n \n var res: array, 2u>;\n var x_sum: f32 = 0.0;\n \n for (var j = 0u; j < ").concat(columnsPerBlock,"; j+=4) {\n \n var b01 = blocks[b01_start];\n \n let w0_0 = f32(extractBits(b01, b01_offset + (2u * j), 2u)); \n let w0_1 = f32(extractBits(b01, b01_offset + (2u * (j + 1)), 2u)); \n let w0_2 = f32(extractBits(b01, b01_offset + (2u * (j + 2)), 2u));\n let w0_3 = f32(extractBits(b01, b01_offset + (2u * (j + 3)), 2u));\n \n b01_offset = 16u;\n \n let w1_0 = f32(extractBits(b01, b01_offset + (2u * j), 2u)); \n let w1_1 = f32(extractBits(b01, b01_offset + (2u * (j + 1)), 2u)); \n let w1_2 = f32(extractBits(b01, b01_offset + (2u * (j + 2)), 2u));\n let w1_3 = f32(extractBits(b01, b01_offset + (2u * (j + 3)), 2u));\n \n b01_offset = 0u; \n b01 = blocks[b01_start + 1u];\n \n let w2_0 = f32(extractBits(b01, b01_offset + (2u * j), 2u)); \n let w2_1 = f32(extractBits(b01, b01_offset + (2u * (j + 1)), 2u)); \n let w2_2 = f32(extractBits(b01, b01_offset + (2u * (j + 2)), 2u));\n let w2_3 = f32(extractBits(b01, b01_offset + (2u * (j + 3)), 2u));\n \n b01_offset = 16u;\n \n let w3_0 = f32(extractBits(b01, b01_offset + (2u * j), 2u)); \n let w3_1 = f32(extractBits(b01, b01_offset + (2u * (j + 1)), 2u)); \n let w3_2 = f32(extractBits(b01, b01_offset + (2u * (j + 2)), 2u));\n let w3_3 = f32(extractBits(b01, b01_offset + (2u * (j + 3)), 2u));\n \n b01_offset = 0u;\n \n let m = mat4x4(\n w0_0, w1_0, w2_0, w3_0,\n w0_1, w1_1, w2_1, w3_1, \n w0_2, w1_2, w2_2, w3_2,\n w0_3, w1_3, w2_3, w3_3);\n\n let x_idx = (j / 4u);\n let x_vec = x[x_start + x_idx];\n res[x_idx] = m * x_vec;\n \n x_sum += x_vec.x + x_vec.y + x_vec.z + x_vec.w; \n }\n \n let swx = res[0] + res[1];\n let kappa = alpha * x_sum;\n \n let y_start = (args.y_offset + (r * args.total_nbc)) / 4u;\n y[y_start + bc] += (swx * beta) + vec4(kappa);\n}\n\n").concat(emptyShader);var forwardSingleBitDepth3ShaderSource="\n\nstruct argsStruct {\n n: u32,\n nbr: u32,\n total_nbc: u32,\n bit_depth_nbc: u32,\n x_offset: u32,\n metas_offset: u32,\n blocks_offset: u32,\n y_offset: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar x: array>;\n\n@group(0) @binding(2)\nvar metas: array;\n\n@group(0) @binding(3)\nvar blocks: array;\n\n@group(0) @binding(4)\nvar y: array>;\n\n".concat(fromFP510Function,"\n\nconst block_size: u32 = 12u;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id : vec3) {\n if (global_id.x >= (args.nbr * 4) || global_id.y >= args.bit_depth_nbc) {\n return;\n }\n \n let r = global_id.x * 4u;\n let c = global_id.y * ").concat(columnsPerBlock,";\n let br = global_id.x / 4u; \n let bc = global_id.y;\n let br_offset = global_id.x % 4u;\n \n let row_metas_start: u32 = args.metas_offset + (br * args.bit_depth_nbc);\n let row_blocks_start: u32 = args.blocks_offset + (br * args.bit_depth_nbc * block_size); \n \n let alpha = from_fp510(extractBits(metas[row_metas_start + bc], 0, 16u)); \n let beta = from_fp510(extractBits(metas[row_metas_start + bc], 16u, 16u));\n\n let x_start = ((args.x_offset + c) / 4u);\n \n var b01_start = row_blocks_start + (br_offset * 2u) + (bc * block_size);\n var b2_start = row_blocks_start + br_offset + (bc * block_size) + 8u;\n var b01_offset = 0u;\n var b2_offset = 0u;\n\n var res: array, 2u>;\n var x_sum: f32 = 0.0;\n \n for (var j = 0u; j < ").concat(columnsPerBlock,"; j+=4) { \n \n var b01 = blocks[b01_start];\n var b2 = blocks[b2_start];\n \n var b01_bits = extractBits(b01, b01_offset + (2u * j), 2u);\n var b2_bit = extractBits(b2, b2_offset + j, 1u);\n let w0_0 = f32(insertBits(b01_bits, b2_bit, 2u, 1u));\n \n b01_bits = extractBits(b01, b01_offset + (2u * (j + 1)), 2u);\n b2_bit = extractBits(b2, b2_offset + (j + 1), 1u);\n let w0_1 = f32(insertBits(b01_bits, b2_bit, 2u, 1u));\n \n b01_bits = extractBits(b01, b01_offset + (2u * (j + 2)), 2u);\n b2_bit = extractBits(b2, b2_offset + (j + 2), 1u);\n let w0_2 = f32(insertBits(b01_bits, b2_bit, 2u, 1u));\n \n b01_bits = extractBits(b01, b01_offset + (2u * (j + 3)), 2u);\n b2_bit = extractBits(b2, b2_offset + (j + 3), 1u);\n let w0_3 = f32(insertBits(b01_bits, b2_bit, 2u, 1u));\n \n b01_offset = 16u;\n b2_offset = 8u;\n \n b01_bits = extractBits(b01, b01_offset + (2u * j), 2u);\n b2_bit = extractBits(b2, b2_offset + j, 1u); \n let w1_0 = f32(insertBits(b01_bits, b2_bit, 2u, 1u));\n \n b01_bits = extractBits(b01, b01_offset + (2u * (j + 1)), 2u);\n b2_bit = extractBits(b2, b2_offset + (j + 1), 1u);\n let w1_1 = f32(insertBits(b01_bits, b2_bit, 2u, 1u));\n \n b01_bits = extractBits(b01, b01_offset + (2u * (j + 2)), 2u);\n b2_bit = extractBits(b2, b2_offset + (j + 2), 1u);\n let w1_2 = f32(insertBits(b01_bits, b2_bit, 2u, 1u));\n \n b01_bits = extractBits(b01, b01_offset + (2u * (j + 3)), 2u);\n b2_bit = extractBits(b2, b2_offset + (j + 3), 1u);\n let w1_3 = f32(insertBits(b01_bits, b2_bit, 2u, 1u));\n \n b01_offset = 0u;\n b2_offset = 16u; \n b01 = blocks[b01_start + 1u];\n \n b01_bits = extractBits(b01, b01_offset + (2u * j), 2u);\n b2_bit = extractBits(b2, b2_offset + j, 1u); \n let w2_0 = f32(insertBits(b01_bits, b2_bit, 2u, 1u));\n \n b01_bits = extractBits(b01, b01_offset + (2u * (j + 1)), 2u);\n b2_bit = extractBits(b2, b2_offset + (j + 1), 1u);\n let w2_1 = f32(insertBits(b01_bits, b2_bit, 2u, 1u));\n \n b01_bits = extractBits(b01, b01_offset + (2u * (j + 2)), 2u);\n b2_bit = extractBits(b2, b2_offset + (j + 2), 1u);\n let w2_2 = f32(insertBits(b01_bits, b2_bit, 2u, 1u));\n \n b01_bits = extractBits(b01, b01_offset + (2u * (j + 3)), 2u);\n b2_bit = extractBits(b2, b2_offset + (j + 3), 1u);\n let w2_3 = f32(insertBits(b01_bits, b2_bit, 2u, 1u));\n \n b01_offset = 16u;\n b2_offset = 24u; \n \n b01_bits = extractBits(b01, b01_offset + (2u * j), 2u);\n b2_bit = extractBits(b2, b2_offset + j, 1u); \n let w3_0 = f32(insertBits(b01_bits, b2_bit, 2u, 1u));\n \n b01_bits = extractBits(b01, b01_offset + (2u * (j + 1)), 2u);\n b2_bit = extractBits(b2, b2_offset + (j + 1), 1u);\n let w3_1 = f32(insertBits(b01_bits, b2_bit, 2u, 1u));\n \n b01_bits = extractBits(b01, b01_offset + (2u * (j + 2)), 2u);\n b2_bit = extractBits(b2, b2_offset + (j + 2), 1u);\n let w3_2 = f32(insertBits(b01_bits, b2_bit, 2u, 1u));\n \n b01_bits = extractBits(b01, b01_offset + (2u * (j + 3)), 2u);\n b2_bit = extractBits(b2, b2_offset + (j + 3), 1u);\n let w3_3 = f32(insertBits(b01_bits, b2_bit, 2u, 1u));\n \n b01_offset = 0u;\n b2_offset = 0u; \n \n let m = mat4x4(\n w0_0, w1_0, w2_0, w3_0,\n w0_1, w1_1, w2_1, w3_1, \n w0_2, w1_2, w2_2, w3_2,\n w0_3, w1_3, w2_3, w3_3);\n \n let x_idx = (j / 4u);\n let x_vec = x[x_start + x_idx];\n res[x_idx] = m * x_vec;\n \n x_sum += x_vec.x + x_vec.y + x_vec.z + x_vec.w;\n }\n\n let swx = res[0] + res[1];\n let kappa = alpha * x_sum;\n \n let y_start = (args.y_offset + (r * args.total_nbc)) / 4u;\n y[y_start + bc] += (swx * beta) + vec4(kappa);\n}\n\n").concat(emptyShader);var forwardSingleBitDepth4ShaderSource="\n\nstruct argsStruct {\n n: u32,\n nbr: u32,\n total_nbc: u32,\n bit_depth_nbc: u32,\n x_offset: u32,\n metas_offset: u32,\n blocks_offset: u32,\n y_offset: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar x: array>;\n\n@group(0) @binding(2)\nvar metas: array;\n\n@group(0) @binding(3)\nvar blocks: array;\n\n@group(0) @binding(4)\nvar y: array>;\n\n".concat(fromFP510Function,"\n\nconst block_size: u32 = 16u;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= (args.nbr * 4) || global_id.y >= args.bit_depth_nbc) {\n return;\n }\n \n let r = global_id.x * 4u;\n let c = global_id.y * ").concat(columnsPerBlock,";\n let br = global_id.x / 4u; \n let bc = global_id.y;\n let br_offset = global_id.x % 4u;\n \n let row_metas_start: u32 = args.metas_offset + (br * args.bit_depth_nbc);\n let row_blocks_start: u32 = args.blocks_offset + (br * args.bit_depth_nbc * block_size); \n \n let alpha = from_fp510(extractBits(metas[row_metas_start + bc], 0, 16u)); \n let beta = from_fp510(extractBits(metas[row_metas_start + bc], 16u, 16u));\n \n let x_start = ((args.x_offset + c) / 4u);\n \n var b03_start = row_blocks_start + (br_offset * 4u) + (bc * block_size); \n\n var res: array, 2u>;\n var x_sum: f32 = 0.0;\n\n for (var j = 0u; j < ").concat(columnsPerBlock,"; j+=4) {\n \n var b03 = blocks[b03_start]; \n \n let w0_0 = f32(extractBits(b03, 4u * j, 4u)); \n let w0_1 = f32(extractBits(b03, 4u * (j + 1), 4u)); \n let w0_2 = f32(extractBits(b03, 4u * (j + 2), 4u));\n let w0_3 = f32(extractBits(b03, 4u * (j + 3), 4u));\n \n b03 = blocks[b03_start + 1];\n \n let w1_0 = f32(extractBits(b03, 4u * j, 4u)); \n let w1_1 = f32(extractBits(b03, 4u * (j + 1), 4u)); \n let w1_2 = f32(extractBits(b03, 4u * (j + 2), 4u));\n let w1_3 = f32(extractBits(b03, 4u * (j + 3), 4u));\n \n b03 = blocks[b03_start + 2];\n \n let w2_0 = f32(extractBits(b03, 4u * j, 4u)); \n let w2_1 = f32(extractBits(b03, 4u * (j + 1), 4u)); \n let w2_2 = f32(extractBits(b03, 4u * (j + 2), 4u));\n let w2_3 = f32(extractBits(b03, 4u * (j + 3), 4u));\n \n b03 = blocks[b03_start + 3];\n \n let w3_0 = f32(extractBits(b03, 4u * j, 4u)); \n let w3_1 = f32(extractBits(b03, 4u * (j + 1), 4u)); \n let w3_2 = f32(extractBits(b03, 4u * (j + 2), 4u));\n let w3_3 = f32(extractBits(b03, 4u * (j + 3), 4u));\n \n let m = mat4x4(\n w0_0, w1_0, w2_0, w3_0,\n w0_1, w1_1, w2_1, w3_1, \n w0_2, w1_2, w2_2, w3_2,\n w0_3, w1_3, w2_3, w3_3);\n\n let x_idx = (j / 4u);\n let x_vec = x[x_start + x_idx];\n res[x_idx] = m * x_vec;\n \n x_sum += x_vec.x + x_vec.y + x_vec.z + x_vec.w;\n }\n let swx = res[0] + res[1];\n let kappa = alpha * x_sum;\n \n let y_start = (args.y_offset + (r * args.total_nbc)) / 4u;\n y[y_start + bc] += (swx * beta) + vec4(kappa);\n}\n\n").concat(emptyShader);var forwardSingleBitDepth5ShaderSource="\n\nstruct argsStruct {\n n: u32,\n nbr: u32,\n total_nbc: u32,\n bit_depth_nbc: u32,\n x_offset: u32,\n metas_offset: u32,\n blocks_offset: u32,\n y_offset: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar x: array>;\n\n@group(0) @binding(2)\nvar metas: array;\n\n@group(0) @binding(3)\nvar blocks: array;\n\n@group(0) @binding(4)\nvar y: array>;\n\n".concat(fromFP510Function,"\n\nconst block_size: u32 = 20u;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= (args.nbr * 4) || global_id.y >= args.bit_depth_nbc) {\n return;\n }\n \n let r = global_id.x * 4u;\n let c = global_id.y * ").concat(columnsPerBlock,";\n let br = global_id.x / 4u; \n let bc = global_id.y;\n let br_offset = global_id.x % 4u;\n \n let row_metas_start: u32 = args.metas_offset + (br * args.bit_depth_nbc);\n let row_blocks_start: u32 = args.blocks_offset + (br * args.bit_depth_nbc * block_size); \n \n let alpha = from_fp510(extractBits(metas[row_metas_start + bc], 0, 16u)); \n let beta = from_fp510(extractBits(metas[row_metas_start + bc], 16u, 16u));\n \n let x_start = ((args.x_offset + c) / 4u);\n \n var b03_start = row_blocks_start + (br_offset * 4u) + (bc * block_size);\n var b4_start = row_blocks_start + br_offset + (bc * block_size) + 16u;\n \n var b4_offset = 0u;\n \n var res: array, 2u>;\n var x_sum: f32 = 0.0;\n \n for (var j = 0u; j < ").concat(columnsPerBlock,"; j+=4) {\n \n var b03 = blocks[b03_start];\n var b4 = blocks[b4_start];\n \n var b03_bits = extractBits(b03, 4u * j, 4u);\n var b4_bit = extractBits(b4, b4_offset + j, 1u); \n let w0_0 = f32(insertBits(b03_bits, b4_bit, 4u, 1u));\n \n b03_bits = extractBits(b03, 4u * (j + 1), 4u);\n b4_bit = extractBits(b4, b4_offset + (j + 1), 1u);\n let w0_1 = f32(insertBits(b03_bits, b4_bit, 4u, 1u));\n \n b03_bits = extractBits(b03, 4u * (j + 2), 4u);\n b4_bit = extractBits(b4, b4_offset + (j + 2), 1u);\n let w0_2 = f32(insertBits(b03_bits, b4_bit, 4u, 1u));\n \n b03_bits = extractBits(b03, 4u * (j + 3), 4u);\n b4_bit = extractBits(b4, b4_offset + (j + 3), 1u);\n let w0_3 = f32(insertBits(b03_bits, b4_bit, 4u, 1u));\n \n b03 = blocks[b03_start + 1];\n b4_offset = 8u;\n \n b03_bits = extractBits(b03, 4u * j, 4u);\n b4_bit = extractBits(b4, b4_offset + j, 1u); \n let w1_0 = f32(insertBits(b03_bits, b4_bit, 4u, 1u));\n \n b03_bits = extractBits(b03, 4u * (j + 1), 4u);\n b4_bit = extractBits(b4, b4_offset + (j + 1), 1u);\n let w1_1 = f32(insertBits(b03_bits, b4_bit, 4u, 1u));\n \n b03_bits = extractBits(b03, 4u * (j + 2), 4u);\n b4_bit = extractBits(b4, b4_offset + (j + 2), 1u);\n let w1_2 = f32(insertBits(b03_bits, b4_bit, 4u, 1u));\n \n b03_bits = extractBits(b03, 4u * (j + 3), 4u);\n b4_bit = extractBits(b4, b4_offset + (j + 3), 1u);\n let w1_3 = f32(insertBits(b03_bits, b4_bit, 4u, 1u));\n \n b03 = blocks[b03_start + 2];\n b4_offset = 16u;\n \n b03_bits = extractBits(b03, 4u * j, 4u);\n b4_bit = extractBits(b4, b4_offset + j, 1u); \n let w2_0 = f32(insertBits(b03_bits, b4_bit, 4u, 1u));\n \n b03_bits = extractBits(b03, 4u * (j + 1), 4u);\n b4_bit = extractBits(b4, b4_offset + (j + 1), 1u);\n let w2_1 = f32(insertBits(b03_bits, b4_bit, 4u, 1u));\n \n b03_bits = extractBits(b03, 4u * (j + 2), 4u);\n b4_bit = extractBits(b4, b4_offset + (j + 2), 1u);\n let w2_2 = f32(insertBits(b03_bits, b4_bit, 4u, 1u));\n \n b03_bits = extractBits(b03, 4u * (j + 3), 4u);\n b4_bit = extractBits(b4, b4_offset + (j + 3), 1u);\n let w2_3 = f32(insertBits(b03_bits, b4_bit, 4u, 1u));\n \n b03 = blocks[b03_start + 3];\n b4_offset = 24u;\n \n b03_bits = extractBits(b03, 4u * j, 4u);\n b4_bit = extractBits(b4, b4_offset + j, 1u); \n let w3_0 = f32(insertBits(b03_bits, b4_bit, 4u, 1u));\n \n b03_bits = extractBits(b03, 4u * (j + 1), 4u);\n b4_bit = extractBits(b4, b4_offset + (j + 1), 1u);\n let w3_1 = f32(insertBits(b03_bits, b4_bit, 4u, 1u));\n \n b03_bits = extractBits(b03, 4u * (j + 2), 4u);\n b4_bit = extractBits(b4, b4_offset + (j + 2), 1u);\n let w3_2 = f32(insertBits(b03_bits, b4_bit, 4u, 1u));\n \n b03_bits = extractBits(b03, 4u * (j + 3), 4u);\n b4_bit = extractBits(b4, b4_offset + (j + 3), 1u);\n let w3_3 = f32(insertBits(b03_bits, b4_bit, 4u, 1u));\n \n b4_offset = 0u;\n \n let m = mat4x4(\n w0_0, w1_0, w2_0, w3_0,\n w0_1, w1_1, w2_1, w3_1, \n w0_2, w1_2, w2_2, w3_2,\n w0_3, w1_3, w2_3, w3_3);\n\n let x_idx = (j / 4u);\n let x_vec = x[x_start + x_idx];\n res[x_idx] = m * x_vec;\n \n x_sum += x_vec.x + x_vec.y + x_vec.z + x_vec.w;\n }\n let swx = res[0] + res[1];\n let kappa = alpha * x_sum;\n \n let y_start = (args.y_offset + (r * args.total_nbc)) / 4u;\n y[y_start + bc] += (swx * beta) + vec4(kappa);\n}\n\n").concat(emptyShader);var forwardSingleBitDepth6ShaderSource="\n\nstruct argsStruct {\n n: u32,\n nbr: u32,\n total_nbc: u32,\n bit_depth_nbc: u32,\n x_offset: u32,\n metas_offset: u32,\n blocks_offset: u32,\n y_offset: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar x: array>;\n\n@group(0) @binding(2)\nvar metas: array;\n\n@group(0) @binding(3)\nvar blocks: array;\n\n@group(0) @binding(4)\nvar y: array>;\n\n".concat(fromFP510Function,"\n\nconst block_size: u32 = 24u;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= (args.nbr * 4) || global_id.y >= args.bit_depth_nbc) {\n return;\n }\n \n let r = global_id.x * 4u;\n let c = global_id.y * ").concat(columnsPerBlock,";\n let br = global_id.x / 4u; \n let bc = global_id.y;\n let br_offset = global_id.x % 4u;\n \n let row_metas_start: u32 = args.metas_offset + (br * args.bit_depth_nbc);\n let row_blocks_start: u32 = args.blocks_offset + (br * args.bit_depth_nbc * block_size); \n \n let alpha = from_fp510(extractBits(metas[row_metas_start + bc], 0, 16u)); \n let beta = from_fp510(extractBits(metas[row_metas_start + bc], 16u, 16u));\n \n let x_start = ((args.x_offset + c) / 4u);\n \n var b03_start = row_blocks_start + (br_offset * 4u) + (bc * block_size);\n var b45_start = row_blocks_start + (br_offset * 2u) + (bc * block_size) + 16u;\n \n var b45_offset = 0u;\n \n var res: array, 2u>;\n var x_sum: f32 = 0.0;\n \n for (var j = 0u; j < ").concat(columnsPerBlock,"; j+=4) {\n \n var b03 = blocks[b03_start];\n var b45 = blocks[b45_start];\n \n var b03_bits = extractBits(b03, 4u * j, 4u);\n var b45_bits = extractBits(b45, b45_offset + (j * 2), 2u);\n let w0_0 = f32(insertBits(b03_bits, b45_bits, 4u, 2u));\n \n b03_bits = extractBits(b03, 4u * (j + 1), 4u);\n b45_bits = extractBits(b45, b45_offset + (2u * (j + 1)), 2u);\n let w0_1 = f32(insertBits(b03_bits, b45_bits, 4u, 2u));\n \n b03_bits = extractBits(b03, 4u * (j + 2), 4u);\n b45_bits = extractBits(b45, b45_offset + (2u * (j + 2)), 2u);\n let w0_2 = f32(insertBits(b03_bits, b45_bits, 4u, 2u));\n \n b03_bits = extractBits(b03, 4u * (j + 3), 4u);\n b45_bits = extractBits(b45, b45_offset + (2u * (j + 3)), 2u);\n let w0_3 = f32(insertBits(b03_bits, b45_bits, 4u, 2u));\n \n b03 = blocks[b03_start + 1];\n b45_offset = 16u;\n \n b03_bits = extractBits(b03, 4u * j, 4u);\n b45_bits = extractBits(b45, b45_offset + (j * 2), 2u);\n let w1_0 = f32(insertBits(b03_bits, b45_bits, 4u, 2u));\n \n b03_bits = extractBits(b03, 4u * (j + 1), 4u);\n b45_bits = extractBits(b45, b45_offset + (2u * (j + 1)), 2u);\n let w1_1 = f32(insertBits(b03_bits, b45_bits, 4u, 2u));\n \n b03_bits = extractBits(b03, 4u * (j + 2), 4u);\n b45_bits = extractBits(b45, b45_offset + (2u * (j + 2)), 2u);\n let w1_2 = f32(insertBits(b03_bits, b45_bits, 4u, 2u));\n \n b03_bits = extractBits(b03, 4u * (j + 3), 4u);\n b45_bits = extractBits(b45, b45_offset + (2u * (j + 3)), 2u);\n let w1_3 = f32(insertBits(b03_bits, b45_bits, 4u, 2u)); \n \n b03 = blocks[b03_start + 2];\n b45 = blocks[b45_start + 1];\n b45_offset = 0u;\n \n b03_bits = extractBits(b03, 4u * j, 4u);\n b45_bits = extractBits(b45, b45_offset + (j * 2), 2u);\n let w2_0 = f32(insertBits(b03_bits, b45_bits, 4u, 2u));\n \n b03_bits = extractBits(b03, 4u * (j + 1), 4u);\n b45_bits = extractBits(b45, b45_offset + (2u * (j + 1)), 2u);\n let w2_1 = f32(insertBits(b03_bits, b45_bits, 4u, 2u));\n \n b03_bits = extractBits(b03, 4u * (j + 2), 4u);\n b45_bits = extractBits(b45, b45_offset + (2u * (j + 2)), 2u);\n let w2_2 = f32(insertBits(b03_bits, b45_bits, 4u, 2u));\n \n b03_bits = extractBits(b03, 4u * (j + 3), 4u);\n b45_bits = extractBits(b45, b45_offset + (2u * (j + 3)), 2u);\n let w2_3 = f32(insertBits(b03_bits, b45_bits, 4u, 2u));\n \n b03 = blocks[b03_start + 3];\n b45_offset = 16u;\n \n b03_bits = extractBits(b03, 4u * j, 4u);\n b45_bits = extractBits(b45, b45_offset + (j * 2), 2u);\n let w3_0 = f32(insertBits(b03_bits, b45_bits, 4u, 2u));\n \n b03_bits = extractBits(b03, 4u * (j + 1), 4u);\n b45_bits = extractBits(b45, b45_offset + (2u * (j + 1)), 2u);\n let w3_1 = f32(insertBits(b03_bits, b45_bits, 4u, 2u));\n \n b03_bits = extractBits(b03, 4u * (j + 2), 4u);\n b45_bits = extractBits(b45, b45_offset + (2u * (j + 2)), 2u);\n let w3_2 = f32(insertBits(b03_bits, b45_bits, 4u, 2u));\n \n b03_bits = extractBits(b03, 4u * (j + 3), 4u);\n b45_bits = extractBits(b45, b45_offset + (2u * (j + 3)), 2u);\n let w3_3 = f32(insertBits(b03_bits, b45_bits, 4u, 2u));\n \n b45_offset = 0u;\n \n let m = mat4x4(\n w0_0, w1_0, w2_0, w3_0,\n w0_1, w1_1, w2_1, w3_1, \n w0_2, w1_2, w2_2, w3_2,\n w0_3, w1_3, w2_3, w3_3);\n\n let x_idx = (j / 4u);\n let x_vec = x[x_start + x_idx];\n res[x_idx] = m * x_vec;\n \n x_sum += x_vec.x + x_vec.y + x_vec.z + x_vec.w;\n }\n let swx = res[0] + res[1];\n let kappa = alpha * x_sum;\n \n let y_start = (args.y_offset + (r * args.total_nbc)) / 4u;\n y[y_start + bc] += (swx * beta) + vec4(kappa);\n}\n\n").concat(emptyShader);var forwardSingleBitDepth7ShaderSource="\n\nstruct argsStruct {\n n: u32,\n nbr: u32,\n total_nbc: u32,\n bit_depth_nbc: u32,\n x_offset: u32,\n metas_offset: u32,\n blocks_offset: u32,\n y_offset: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar x: array>;\n\n@group(0) @binding(2)\nvar metas: array;\n\n@group(0) @binding(3)\nvar blocks: array;\n\n@group(0) @binding(4)\nvar y: array>;\n\n".concat(fromFP510Function,"\n\nconst block_size: u32 = 28u;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= (args.nbr * 4) || global_id.y >= args.bit_depth_nbc) {\n return;\n }\n \n let r = global_id.x * 4u;\n let c = global_id.y * ").concat(columnsPerBlock,";\n let br = global_id.x / 4u; \n let bc = global_id.y;\n let br_offset = global_id.x % 4u;\n \n let row_metas_start: u32 = args.metas_offset + (br * args.bit_depth_nbc);\n let row_blocks_start: u32 = args.blocks_offset + (br * args.bit_depth_nbc * block_size); \n \n let alpha = from_fp510(extractBits(metas[row_metas_start + bc], 0, 16u)); \n let beta = from_fp510(extractBits(metas[row_metas_start + bc], 16u, 16u));\n \n let x_start = ((args.x_offset + c) / 4u);\n \n var b03_start = row_blocks_start + (br_offset * 4u) + (bc * block_size);\n var b45_start = row_blocks_start + (br_offset * 2u) + (bc * block_size) + 16u;\n var b6_start = row_blocks_start + br_offset + (bc * block_size) + 24u;\n \n var b45_offset = 0u;\n var b6_offset = 0u;\n \n var res: array, 2u>;\n var x_sum: f32 = 0.0;\n \n for (var j = 0u; j < ").concat(columnsPerBlock,"; j+=4) {\n \n var b03 = blocks[b03_start];\n var b45 = blocks[b45_start];\n var b6 = blocks[b6_start];\n \n var b03_bits = extractBits(b03, 4u * j, 4u);\n var b45_bits = extractBits(b45, b45_offset + (j * 2), 2u);\n var b6_bit = extractBits(b6, b6_offset + j, 1u);\n let w0_0 = f32(insertBits(insertBits(b03_bits, b45_bits, 4u, 2u), b6_bit, 6u, 1u));\n \n b03_bits = extractBits(b03, 4u * (j + 1), 4u);\n b45_bits = extractBits(b45, b45_offset + (2u * (j + 1)), 2u);\n b6_bit = extractBits(b6, b6_offset + j + 1, 1u);\n let w0_1 = f32(insertBits(insertBits(b03_bits, b45_bits, 4u, 2u), b6_bit, 6u, 1u));\n \n b03_bits = extractBits(b03, 4u * (j + 2), 4u);\n b45_bits = extractBits(b45, b45_offset + (2u * (j + 2)), 2u);\n b6_bit = extractBits(b6, b6_offset + j + 2, 1u);\n let w0_2 = f32(insertBits(insertBits(b03_bits, b45_bits, 4u, 2u), b6_bit, 6u, 1u)); \n \n b03_bits = extractBits(b03, 4u * (j + 3), 4u);\n b45_bits = extractBits(b45, b45_offset + (2u * (j + 3)), 2u);\n b6_bit = extractBits(b6, b6_offset + j + 3, 1u);\n let w0_3 = f32(insertBits(insertBits(b03_bits, b45_bits, 4u, 2u), b6_bit, 6u, 1u));\n \n b03 = blocks[b03_start + 1];\n b45_offset = 16u;\n b6_offset = 8u;\n \n b03_bits = extractBits(b03, 4u * j, 4u);\n b45_bits = extractBits(b45, b45_offset + (j * 2), 2u);\n b6_bit = extractBits(b6, b6_offset + j, 1u);\n let w1_0 = f32(insertBits(insertBits(b03_bits, b45_bits, 4u, 2u), b6_bit, 6u, 1u));\n \n b03_bits = extractBits(b03, 4u * (j + 1), 4u);\n b45_bits = extractBits(b45, b45_offset + (2u * (j + 1)), 2u);\n b6_bit = extractBits(b6, b6_offset + j + 1, 1u);\n let w1_1 = f32(insertBits(insertBits(b03_bits, b45_bits, 4u, 2u), b6_bit, 6u, 1u));\n \n b03_bits = extractBits(b03, 4u * (j + 2), 4u);\n b45_bits = extractBits(b45, b45_offset + (2u * (j + 2)), 2u);\n b6_bit = extractBits(b6, b6_offset + j + 2, 1u);\n let w1_2 = f32(insertBits(insertBits(b03_bits, b45_bits, 4u, 2u), b6_bit, 6u, 1u)); \n \n b03_bits = extractBits(b03, 4u * (j + 3), 4u);\n b45_bits = extractBits(b45, b45_offset + (2u * (j + 3)), 2u);\n b6_bit = extractBits(b6, b6_offset + j + 3, 1u);\n let w1_3 = f32(insertBits(insertBits(b03_bits, b45_bits, 4u, 2u), b6_bit, 6u, 1u));\n \n b03 = blocks[b03_start + 2];\n b45 = blocks[b45_start + 1];\n b45_offset = 0u;\n b6_offset = 16u;\n\n b03_bits = extractBits(b03, 4u * j, 4u);\n b45_bits = extractBits(b45, b45_offset + (j * 2), 2u);\n b6_bit = extractBits(b6, b6_offset + j, 1u);\n let w2_0 = f32(insertBits(insertBits(b03_bits, b45_bits, 4u, 2u), b6_bit, 6u, 1u));\n \n b03_bits = extractBits(b03, 4u * (j + 1), 4u);\n b45_bits = extractBits(b45, b45_offset + (2u * (j + 1)), 2u);\n b6_bit = extractBits(b6, b6_offset + j + 1, 1u);\n let w2_1 = f32(insertBits(insertBits(b03_bits, b45_bits, 4u, 2u), b6_bit, 6u, 1u));\n \n b03_bits = extractBits(b03, 4u * (j + 2), 4u);\n b45_bits = extractBits(b45, b45_offset + (2u * (j + 2)), 2u);\n b6_bit = extractBits(b6, b6_offset + j + 2, 1u);\n let w2_2 = f32(insertBits(insertBits(b03_bits, b45_bits, 4u, 2u), b6_bit, 6u, 1u)); \n \n b03_bits = extractBits(b03, 4u * (j + 3), 4u);\n b45_bits = extractBits(b45, b45_offset + (2u * (j + 3)), 2u);\n b6_bit = extractBits(b6, b6_offset + j + 3, 1u);\n let w2_3 = f32(insertBits(insertBits(b03_bits, b45_bits, 4u, 2u), b6_bit, 6u, 1u));\n \n b03 = blocks[b03_start + 3];\n b45_offset = 16u;\n b6_offset = 24u;\n \n b03_bits = extractBits(b03, 4u * j, 4u);\n b45_bits = extractBits(b45, b45_offset + (j * 2), 2u);\n b6_bit = extractBits(b6, b6_offset + j, 1u);\n let w3_0 = f32(insertBits(insertBits(b03_bits, b45_bits, 4u, 2u), b6_bit, 6u, 1u));\n \n b03_bits = extractBits(b03, 4u * (j + 1), 4u);\n b45_bits = extractBits(b45, b45_offset + (2u * (j + 1)), 2u);\n b6_bit = extractBits(b6, b6_offset + j + 1, 1u);\n let w3_1 = f32(insertBits(insertBits(b03_bits, b45_bits, 4u, 2u), b6_bit, 6u, 1u));\n \n b03_bits = extractBits(b03, 4u * (j + 2), 4u);\n b45_bits = extractBits(b45, b45_offset + (2u * (j + 2)), 2u);\n b6_bit = extractBits(b6, b6_offset + j + 2, 1u);\n let w3_2 = f32(insertBits(insertBits(b03_bits, b45_bits, 4u, 2u), b6_bit, 6u, 1u)); \n \n b03_bits = extractBits(b03, 4u * (j + 3), 4u);\n b45_bits = extractBits(b45, b45_offset + (2u * (j + 3)), 2u);\n b6_bit = extractBits(b6, b6_offset + j + 3, 1u);\n let w3_3 = f32(insertBits(insertBits(b03_bits, b45_bits, 4u, 2u), b6_bit, 6u, 1u));\n \n b45_offset = 0u;\n b6_offset = 0u;\n \n let m = mat4x4(\n w0_0, w1_0, w2_0, w3_0,\n w0_1, w1_1, w2_1, w3_1, \n w0_2, w1_2, w2_2, w3_2,\n w0_3, w1_3, w2_3, w3_3);\n\n let x_idx = (j / 4u);\n let x_vec = x[x_start + x_idx];\n res[x_idx] = m * x_vec;\n \n x_sum += x_vec.x + x_vec.y + x_vec.z + x_vec.w;\n }\n\n let swx = res[0] + res[1];\n let kappa = alpha * x_sum;\n \n let y_start = (args.y_offset + (r * args.total_nbc)) / 4u;\n y[y_start + bc] += (swx * beta) + vec4(kappa);\n}\n\n").concat(emptyShader);var forwardSingleBitDepth8ShaderSource="\n\nstruct argsStruct {\n n: u32,\n nbr: u32,\n total_nbc: u32,\n bit_depth_nbc: u32,\n x_offset: u32,\n metas_offset: u32,\n blocks_offset: u32,\n y_offset: u32,\n};\n\n@group(0) @binding(0) \nvar args: argsStruct;\n\n@group(0) @binding(1)\nvar x: array>;\n\n@group(0) @binding(2)\nvar metas: array;\n\n@group(0) @binding(3)\nvar blocks: array;\n\n@group(0) @binding(4)\nvar y: array>;\n\n".concat(fromFP510Function,"\n\nconst block_size: u32 = 32u;\n\noverride workgroup_size_x: u32 = 1;\noverride workgroup_size_y: u32 = 1;\noverride workgroup_size_z: u32 = 1;\n\n@compute @workgroup_size(workgroup_size_x, workgroup_size_y, workgroup_size_z)\nfn main(@builtin(global_invocation_id) global_id: vec3) {\n if (global_id.x >= (args.nbr * 4) || global_id.y >= args.bit_depth_nbc) {\n return;\n }\n \n let r = global_id.x * 4u;\n let c = global_id.y * ").concat(columnsPerBlock,";\n let br = global_id.x / 4u; \n let bc = global_id.y;\n let br_offset = global_id.x % 4u;\n \n let row_metas_start: u32 = args.metas_offset + (br * args.bit_depth_nbc);\n let row_blocks_start: u32 = args.blocks_offset + (br * args.bit_depth_nbc * block_size); \n \n let alpha = from_fp510(extractBits(metas[row_metas_start + bc], 0, 16u)); \n let beta = from_fp510(extractBits(metas[row_metas_start + bc], 16u, 16u));\n \n let x_start = ((args.x_offset + c) / 4u);\n \n var b07_start = row_blocks_start + (br_offset * 8u) + (bc * block_size); \n\n var res: array, 2u>;\n var x_sum: f32 = 0.0;\n\n for (var j = 0u; j < 2; j++) {\n \n var b07 = blocks[b07_start + j];\n \n let w0_0 = f32(extractBits(b07, 0u, 8u)); \n let w0_1 = f32(extractBits(b07, 8u, 8u)); \n let w0_2 = f32(extractBits(b07, 16u, 8u));\n let w0_3 = f32(extractBits(b07, 24u, 8u));\n \n b07 = blocks[b07_start + 2 + j];\n \n let w1_0 = f32(extractBits(b07, 0u, 8u)); \n let w1_1 = f32(extractBits(b07, 8u, 8u)); \n let w1_2 = f32(extractBits(b07, 16u, 8u));\n let w1_3 = f32(extractBits(b07, 24u, 8u));\n \n b07 = blocks[b07_start + 4 + j];\n \n let w2_0 = f32(extractBits(b07, 0u, 8u)); \n let w2_1 = f32(extractBits(b07, 8u, 8u)); \n let w2_2 = f32(extractBits(b07, 16u, 8u));\n let w2_3 = f32(extractBits(b07, 24u, 8u));\n \n b07 = blocks[b07_start + 6 + j];\n \n let w3_0 = f32(extractBits(b07, 0u, 8u)); \n let w3_1 = f32(extractBits(b07, 8u, 8u)); \n let w3_2 = f32(extractBits(b07, 16u, 8u));\n let w3_3 = f32(extractBits(b07, 24u, 8u));\n \n let m = mat4x4(\n w0_0, w1_0, w2_0, w3_0,\n w0_1, w1_1, w2_1, w3_1, \n w0_2, w1_2, w2_2, w3_2,\n w0_3, w1_3, w2_3, w3_3);\n\n let x_vec = x[x_start + j];\n res[j] = m * x_vec;\n \n x_sum += x_vec.x + x_vec.y + x_vec.z + x_vec.w;\n }\n let swx = res[0] + res[1];\n let kappa = alpha * x_sum;\n \n let y_start = (args.y_offset + (r * args.total_nbc)) / 4u;\n y[y_start + bc] += (swx * beta) + vec4(kappa);\n}\n\n").concat(emptyShader);var forwardSingleShaderSources={1:forwardSingleBitDepth1ShaderSource,2:forwardSingleBitDepth2ShaderSource,3:forwardSingleBitDepth3ShaderSource,4:forwardSingleBitDepth4ShaderSource,5:forwardSingleBitDepth5ShaderSource,6:forwardSingleBitDepth6ShaderSource,7:forwardSingleBitDepth7ShaderSource,8:forwardSingleBitDepth8ShaderSource};var forwardSingleShaderNames={1:"pv_picollm_weight_block_mixed_16x8_forward_single_bit_depth_1_shader",2:"pv_picollm_weight_block_mixed_16x8_forward_single_bit_depth_2_shader",3:"pv_picollm_weight_block_mixed_16x8_forward_single_bit_depth_3_shader",4:"pv_picollm_weight_block_mixed_16x8_forward_single_bit_depth_4_shader",5:"pv_picollm_weight_block_mixed_16x8_forward_single_bit_depth_5_shader",6:"pv_picollm_weight_block_mixed_16x8_forward_single_bit_depth_6_shader",7:"pv_picollm_weight_block_mixed_16x8_forward_single_bit_depth_7_shader",8:"pv_picollm_weight_block_mixed_16x8_forward_single_bit_depth_8_shader"};var forwardShaderSources={1:forwardMultipleShaderSources(1),2:forwardMultipleShaderSources(2),3:forwardMultipleShaderSources(3),4:forwardMultipleShaderSources(4),5:forwardMultipleShaderSources(5),6:forwardMultipleShaderSources(6),7:forwardMultipleShaderSources(7),8:forwardMultipleShaderSources(8)};var forwardShaderNames={1:"pv_picollm_weight_block_mixed_16x8_forward_multiple_bit_depth_1_shader",2:"pv_picollm_weight_block_mixed_16x8_forward_multiple_bit_depth_2_shader",3:"pv_picollm_weight_block_mixed_16x8_forward_multiple_bit_depth_3_shader",4:"pv_picollm_weight_block_mixed_16x8_forward_multiple_bit_depth_4_shader",5:"pv_picollm_weight_block_mixed_16x8_forward_multiple_bit_depth_5_shader",6:"pv_picollm_weight_block_mixed_16x8_forward_multiple_bit_depth_6_shader",7:"pv_picollm_weight_block_mixed_16x8_forward_multiple_bit_depth_7_shader",8:"pv_picollm_weight_block_mixed_16x8_forward_multiple_bit_depth_8_shader"};var forwardShuffleXShaderName="pv_picollm_weight_block_mixed_16x8_forward_shuffle_x_shader";var forwardShuffleYShaderName="pv_picollm_weight_block_mixed_16x8_forward_shuffle_y_shader";var addBiasShaderName="pv_picollm_weight_block_mixed_16x8_add_bias_shader";var forwardSingleReduceYShaderName="pv_picollm_weight_block_mixed_16x8_forward_single_reduce_y_shader";var _weightBlockMixed16x;var loadPreprocessBlocksShader=function loadPreprocessBlocksShader(device,bitDepth){var bindGroupLayout=device.createBindGroupLayout({label:"weight preprocess blocks ".concat(bitDepth," bind group layout"),entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"weight preprocess blocks ".concat(bitDepth," pipeline layout"),bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"weight preprocess blocks ".concat(bitDepth," shader module"),code:preprocessShaderSources[bitDepth]});var computePipeline=device.createComputePipeline({label:"weight preprocess blocks ".concat(bitDepth," pipeline"),layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint,constants:{workgroup_size_x:preprocessDim,workgroup_size_y:preprocessDim}}});return{computePipeline:computePipeline}};var loadForwardShuffleXShader=function loadForwardShuffleXShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"weight shuffle x bind group layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:3,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"weight shuffle x pipeline layout",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"weight shuffle x shader module",code:forwardShuffleXShaderSource});var computePipeline=device.createComputePipeline({label:"weight shuffle x pipeline",layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint,constants:{workgroup_size_y:PV_PICOLLM_WEBGPU_DEFAULT_WORKGROUP_SIZE}}});return{computePipeline:computePipeline}};var loadForwardSingleReduceYShader=function loadForwardSingleReduceYShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"weight single reduce y bind group layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"weight single reduce y pipeline layout",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"weight single reduce y shader module",code:forwardSingleReduceYShaderSource});var computePipeline=device.createComputePipeline({label:"weight single reduce y pipeline",layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint,constants:{workgroup_size_x:PV_PICOLLM_WEBGPU_DEFAULT_WORKGROUP_SIZE}}});return{computePipeline:computePipeline}};var loadForwardShuffleYShader=function loadForwardShuffleYShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"weight shuffle y bind group layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"weight shuffle y pipeline layout",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"weight shuffle y shader module",code:forwardShuffleYShaderSource});var computePipeline=device.createComputePipeline({label:"weight shuffle y pipeline",layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint}});return{computePipeline:computePipeline}};var loadForwardSingleShader=function loadForwardSingleShader(device,bitDepth){var entries=[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:3,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:4,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}];var bindGroupLayout=device.createBindGroupLayout({label:"weight forward single ".concat(bitDepth," bind group layout"),entries:entries});var pipelineLayout=device.createPipelineLayout({label:"weight forward single ".concat(bitDepth," pipeline layout"),bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"weight forward single ".concat(bitDepth," shader module"),code:forwardSingleShaderSources[bitDepth]});var computePipeline=device.createComputePipeline({label:"weight forward single ".concat(bitDepth," pipeline"),layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint,constants:{workgroup_size_x:weightBlockSize,workgroup_size_y:1}}});return{computePipeline:computePipeline}};var loadForwardShader=function loadForwardShader(device,bitDepth){var entries=[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:3,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:4,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}];var bindGroupLayout=device.createBindGroupLayout({label:"weight forward multi ".concat(bitDepth," bind group layout"),entries:entries});var pipelineLayout=device.createPipelineLayout({label:"weight forward multi ".concat(bitDepth," pipeline layout"),bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"weight forward multi ".concat(bitDepth," shader module"),code:forwardShaderSources[bitDepth]});var computePipeline=device.createComputePipeline({label:"weight forward multi ".concat(bitDepth," pipeline"),layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint,constants:{workgroup_size_x:TC}}});return{computePipeline:computePipeline}};var loadAddBiasShader=function loadAddBiasShader(device){var bindGroupLayout=device.createBindGroupLayout({label:"weight add bias bind group layout",entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]});var pipelineLayout=device.createPipelineLayout({label:"weight add bias pipeline layout",bindGroupLayouts:[bindGroupLayout]});var shaderModule=device.createShaderModule({label:"weight add bias shader module",code:addBiasShaderSource});var computePipeline=device.createComputePipeline({label:"weight add bias pipeline",layout:pipelineLayout,compute:{module:shaderModule,entryPoint:shaderEntryPoint}});return{computePipeline:computePipeline}};var weightBlockMixed16x8Shaders=(_weightBlockMixed16x={},_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_weightBlockMixed16x,preprocessShaderNames[3],function(device){return loadPreprocessBlocksShader(device,3)}),preprocessShaderNames[5],function(device){return loadPreprocessBlocksShader(device,5)}),preprocessShaderNames[6],function(device){return loadPreprocessBlocksShader(device,6)}),preprocessShaderNames[7],function(device){return loadPreprocessBlocksShader(device,7)}),forwardShuffleXShaderName,loadForwardShuffleXShader),forwardShuffleYShaderName,loadForwardShuffleYShader),forwardSingleReduceYShaderName,loadForwardSingleReduceYShader),forwardSingleShaderNames[1],function(device){return loadForwardSingleShader(device,1)}),forwardSingleShaderNames[2],function(device){return loadForwardSingleShader(device,2)}),forwardSingleShaderNames[3],function(device){return loadForwardSingleShader(device,3)}),_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_weightBlockMixed16x,forwardSingleShaderNames[4],function(device){return loadForwardSingleShader(device,4)}),forwardSingleShaderNames[5],function(device){return loadForwardSingleShader(device,5)}),forwardSingleShaderNames[6],function(device){return loadForwardSingleShader(device,6)}),forwardSingleShaderNames[7],function(device){return loadForwardSingleShader(device,7)}),forwardSingleShaderNames[8],function(device){return loadForwardSingleShader(device,8)}),forwardShaderNames[1],function(device){return loadForwardShader(device,1)}),forwardShaderNames[2],function(device){return loadForwardShader(device,2)}),forwardShaderNames[3],function(device){return loadForwardShader(device,3)}),forwardShaderNames[4],function(device){return loadForwardShader(device,4)}),forwardShaderNames[5],function(device){return loadForwardShader(device,5)}),_defineProperty(_defineProperty(_defineProperty(_defineProperty(_weightBlockMixed16x,forwardShaderNames[6],function(device){return loadForwardShader(device,6)}),forwardShaderNames[7],function(device){return loadForwardShader(device,7)}),forwardShaderNames[8],function(device){return loadForwardShader(device,8)}),addBiasShaderName,loadAddBiasShader));function ownKeys$1(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);r&&(o=o.filter(function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable})),t.push.apply(t,o)}return t}function _objectSpread$1(e){for(var r=1;r=r.length?{done:!0}:{done:!1,value:r[_n++]}},e:function e(r){throw r},f:F}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,a=!0,u=!1;return{s:function s(){t=t.call(r)},n:function n(){var r=t.next();return a=r.done,r},e:function e(r){u=!0,o=r},f:function f(){try{a||null==t["return"]||t["return"]()}finally{if(u)throw o}}}}function _unsupportedIterableToArray(r,a){if(r){if("string"==typeof r)return _arrayLikeToArray(r,a);var t={}.toString.call(r).slice(8,-1);return"Object"===t&&r.constructor&&(t=r.constructor.name),"Map"===t||"Set"===t?Array.from(r):"Arguments"===t||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t)?_arrayLikeToArray(r,a):void 0}}function _arrayLikeToArray(r,a){(null==a||a>r.length)&&(a=r.length);for(var e=0,n=Array(a);e1&&_args[1]!==undefined?_args[1]:{};time=_args.length>2&&_args[2]!==undefined?_args[2]:5e3;controller=new AbortController;config=_objectSpread(_objectSpread({},options),{},{signal:controller.signal});timeout=setTimeout(function(){controller.abort()},time);_context.next=7;return fetch(uri,config);case 7:response=_context.sent;clearTimeout(timeout);return _context.abrupt("return",response);case 10:case"end":return _context.stop()}},_callee)}));return _fetchWithTimeout.apply(this,arguments)}function open(_x2,_x3){return _open.apply(this,arguments)}function _open(){_open=_asyncToGenerator(_regeneratorRuntime.mark(function _callee2(path,mode){var error;return _regeneratorRuntime.wrap(function _callee2$(_context2){while(1)switch(_context2.prev=_context2.next){case 0:_context2.prev=0;_context2.next=3;return PvFileIDB.open(path,mode);case 3:return _context2.abrupt("return",_context2.sent);case 6:_context2.prev=6;_context2.t0=_context2["catch"](0);if(_context2.t0.name==="IndexedDBNotSupported"){console.warn("IndexedDB is not supported. Fallback to in-memory storage.")}else if(_context2.t0.name!=="FileNotExists"){console.warn("Unable to access IndexedDB (".concat(_context2.t0.toString(),"). Fallback to in-memory storage."))}if(!(typeof WorkerGlobalScope!=="undefined"&&self instanceof WorkerGlobalScope)){_context2.next=16;break}if(!(_context2.t0.name==="FileNotExists")){_context2.next=12;break}throw _context2.t0;case 12:console.error("In-memory storage cannot be used inside a worker.");error=new Error("Failed to start PvFile: ".concat(_context2.t0.toString()));error.name="PvFileNotSupported";throw error;case 16:return _context2.abrupt("return",PvFileMem.open(path,mode));case 17:case"end":return _context2.stop()}},_callee2,null,[[0,6]])}));return _open.apply(this,arguments)}var moduleOverrides=Object.assign({},Module);var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var readAsync,readBinary;if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(typeof document!="undefined"&&document.currentScript){scriptDirectory=document.currentScript.src}if(_scriptName){scriptDirectory=_scriptName}if(scriptDirectory.startsWith("blob:")){scriptDirectory=""}else{scriptDirectory=scriptDirectory.substr(0,scriptDirectory.replace(/[?#].*/,"").lastIndexOf("/")+1)}{if(ENVIRONMENT_IS_WORKER){readBinary=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=url=>{if(isFileURI(url)){return new Promise((reject,resolve)=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=()=>{if(xhr.status==200||xhr.status==0&&xhr.response){resolve(xhr.response)}reject(xhr.status)};xhr.onerror=reject;xhr.send(null)})}return fetch(url,{credentials:"same-origin"}).then(response=>{if(response.ok){return response.arrayBuffer()}return Promise.reject(new Error(response.status+" : "+response.url))})}}}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.error.bind(console);Object.assign(Module,moduleOverrides);moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var wasmMemory;var ABORT=false;var EXITSTATUS;var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAP64,HEAPU64,HEAPF64;function updateMemoryViews(){var b=wasmMemory.buffer;Module["HEAP8"]=HEAP8=new Int8Array(b);Module["HEAP16"]=HEAP16=new Int16Array(b);Module["HEAPU8"]=HEAPU8=new Uint8Array(b);Module["HEAPU16"]=HEAPU16=new Uint16Array(b);Module["HEAP32"]=HEAP32=new Int32Array(b);Module["HEAPU32"]=HEAPU32=new Uint32Array(b);Module["HEAPF32"]=HEAPF32=new Float32Array(b);Module["HEAPF64"]=HEAPF64=new Float64Array(b);Module["HEAP64"]=HEAP64=new BigInt64Array(b);Module["HEAPU64"]=HEAPU64=new BigUint64Array(b)}var __ATPRERUN__=[];var __ATINIT__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__)}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnInit(cb){__ATINIT__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;Module["monitorRunDependencies"]?.(runDependencies)}function removeRunDependency(id){runDependencies--;Module["monitorRunDependencies"]?.(runDependencies);if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}function abort(what){Module["onAbort"]?.(what);what="Aborted("+what+")";err(what);ABORT=true;EXITSTATUS=1;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);readyPromiseReject(e);throw e}var dataURIPrefix="data:application/octet-stream;base64,";var isDataURI=filename=>filename.startsWith(dataURIPrefix);var isFileURI=filename=>filename.startsWith("file://");function findWasmBinary(){var f="pv_eagle_simd.wasm";if(!isDataURI(f)){return locateFile(f)}return f}var wasmBinaryFile;function getBinarySync(file){if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}function getBinaryPromise(binaryFile){if(!wasmBinary){return readAsync(binaryFile).then(response=>new Uint8Array(response),()=>getBinarySync(binaryFile))}return Promise.resolve().then(()=>getBinarySync(binaryFile))}function instantiateArrayBuffer(binaryFile,imports,receiver){return getBinaryPromise(binaryFile).then(binary=>WebAssembly.instantiate(binary,imports)).then(receiver,reason=>{err(`failed to asynchronously prepare wasm: ${reason}`);abort(reason)})}function instantiateAsync(binary,binaryFile,imports,callback){if(!binary&&typeof WebAssembly.instantiateStreaming=="function"&&!isDataURI(binaryFile)&&!isFileURI(binaryFile)&&typeof fetch=="function"){return fetch(binaryFile,{credentials:"same-origin"}).then(response=>{var result=WebAssembly.instantiateStreaming(response,imports);return result.then(callback,function(reason){err(`wasm streaming compile failed: ${reason}`);err("falling back to ArrayBuffer instantiation");return instantiateArrayBuffer(binaryFile,imports,callback)})})}return instantiateArrayBuffer(binaryFile,imports,callback)}function getWasmImports(){return{a:wasmImports}}function createWasm(){var info=getWasmImports();function receiveInstance(instance,module){wasmExports=instance.exports;wasmExports=Asyncify.instrumentWasmExports(wasmExports);wasmMemory=wasmExports["j"];updateMemoryViews();wasmTable=wasmExports["E"];addOnInit(wasmExports["k"]);removeRunDependency("wasm-instantiate");return wasmExports}addRunDependency("wasm-instantiate");function receiveInstantiationResult(result){receiveInstance(result["instance"])}if(Module["instantiateWasm"]){try{return Module["instantiateWasm"](info,receiveInstance)}catch(e){err(`Module.instantiateWasm callback failed with error: ${e}`);readyPromiseReject(e)}}if(!wasmBinaryFile)wasmBinaryFile=findWasmBinary();instantiateAsync(wasmBinary,wasmBinaryFile,info,receiveInstantiationResult).catch(readyPromiseReject);return{}}function ExitStatus(status){this.name="ExitStatus";this.message=`Program terminated with exit(${status})`;this.status=status}var callRuntimeCallbacks=callbacks=>{while(callbacks.length>0){callbacks.shift()(Module)}};var noExitRuntime=Module["noExitRuntime"]||true;var stackRestore=val=>__emscripten_stack_restore(val);var stackSave=()=>_emscripten_stack_get_current();var getHeapMax=()=>2147483648;var growMemory=size=>{var b=wasmMemory.buffer;var pages=(size-b.byteLength+65535)/65536;try{wasmMemory.grow(pages);updateMemoryViews();return 1}catch(e){}};var _emscripten_resize_heap=requestedSize=>{var oldSize=HEAPU8.length;requestedSize>>>=0;var maxHeapSize=getHeapMax();if(requestedSize>maxHeapSize){return false}var alignUp=(x,multiple)=>x+(multiple-x%multiple)%multiple;for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignUp(Math.max(requestedSize,overGrownHeapSize),65536));var replacement=growMemory(newSize);if(replacement){return true}}return false};function _pv_console_log_wasm(index){console.log(arrayBufferToStringAtIndex(Module.HEAPU8,index))}var _pv_file_close_wasm=async function(fileAddress,statusAddress){statusAddress=unsignedAddress(statusAddress);return Asyncify.handleAsync(async()=>{try{const file=await PvFile.getPtr(fileAddress);await file.close();setInt(statusAddress,0)}catch(e){console.error("pvFileCloseWasm",e);setInt(statusAddress,-1)}})};_pv_file_close_wasm.isAsync=true;var _pv_file_open_wasm=async function(fileAddress,pathAddress,modeAddress,statusAddress){pathAddress=unsignedAddress(pathAddress);modeAddress=unsignedAddress(modeAddress);statusAddress=unsignedAddress(statusAddress);return Asyncify.handleAsync(async()=>{const path=arrayBufferToStringAtIndex(Module.HEAPU8,pathAddress);const mode=arrayBufferToStringAtIndex(Module.HEAPU8,modeAddress);try{const file=await open(path,mode);PvFile.setPtr(fileAddress,file);setInt(statusAddress,0)}catch(e){if(e.name!=="FileNotExists"){console.error("pvFileOpenWasm",e)}setInt(statusAddress,-1)}})};_pv_file_open_wasm.isAsync=true;var _pv_file_read_wasm=async function(fileAddress,contentAddress,size,count,numReadAddress){contentAddress=unsignedAddress(contentAddress);numReadAddress=unsignedAddress(numReadAddress);return Asyncify.handleAsync(async()=>{try{const file=PvFile.getPtr(fileAddress);const content=await file.read(size,count);Module.HEAPU8.set(content,contentAddress);setInt(numReadAddress,content.length/size)}catch(e){console.error("pvFileReadWasm",e);setInt(numReadAddress,-1)}})};_pv_file_read_wasm.isAsync=true;var _pv_file_write_wasm=function(fileAddress,contentAddress,size,count,numWriteAddress){contentAddress=unsignedAddress(contentAddress);numWriteAddress=unsignedAddress(numWriteAddress);return Asyncify.handleAsync(async()=>{try{const file=PvFile.getPtr(fileAddress);const content=new Uint8Array(size*count);content.set(Module.HEAPU8.slice(contentAddress,contentAddress+size*count),0);await file.write(content);setInt(numWriteAddress,content.length/size)}catch(e){console.error("pvFileWriteWasm",e);setInt(numWriteAddress,-1)}})};var _pv_https_request_wasm=async function(httpMethodAddress,serverNameAddress,endpointAddress,headerAddress,bodyAddress,timeoutMs,responseAddressAddress,responseSizeAddress,responseCodeAddress){httpMethodAddress=unsignedAddress(httpMethodAddress);serverNameAddress=unsignedAddress(serverNameAddress);endpointAddress=unsignedAddress(endpointAddress);headerAddress=unsignedAddress(headerAddress);bodyAddress=unsignedAddress(bodyAddress);responseAddressAddress=unsignedAddress(responseAddressAddress);responseSizeAddress=unsignedAddress(responseSizeAddress);responseCodeAddress=unsignedAddress(responseCodeAddress);return Asyncify.handleAsync(async()=>{const httpMethod=arrayBufferToStringAtIndex(Module.HEAPU8,httpMethodAddress);const serverName=arrayBufferToStringAtIndex(Module.HEAPU8,serverNameAddress);const endpoint=arrayBufferToStringAtIndex(Module.HEAPU8,endpointAddress);const header=arrayBufferToStringAtIndex(Module.HEAPU8,headerAddress);const body=arrayBufferToStringAtIndex(Module.HEAPU8,bodyAddress);const headerObject=stringHeaderToObject(header);const options={method:httpMethod};if(body.length>0){options.body=body}if(Object.keys(headerObject).length>0){options.headers=headerObject}let response;let responseText;let statusCode;try{response=await fetchWithTimeout("https://"+serverName+endpoint,options,timeoutMs);statusCode=response.status}catch(error){console.error("pvHttpsRequestWasm",`Failed to fetch: ${error}`);return}try{responseText=await response.text()}catch(error){console.error("pvHttpsRequestWasm",`Failed to get response text: ${error}`);return}const responseAddress=Module._malloc((responseText.length+1)*Int8Array.BYTES_PER_ELEMENT);if(responseAddress===0){console.error("pvMallocError","pvHttpsRequestWasm: cannot allocate memory for response");setInt(responseAddressAddress,0);return}setInt(responseSizeAddress,responseText.length+1);setInt(responseAddressAddress,responseAddress);for(let i=0;i{try{return func()}catch(e){abort(e)}};var handleException=e=>{if(e instanceof ExitStatus||e=="unwind"){return EXITSTATUS}quit_(1,e)};var runtimeKeepaliveCounter=0;var keepRuntimeAlive=()=>noExitRuntime||runtimeKeepaliveCounter>0;var _proc_exit=code=>{EXITSTATUS=code;if(!keepRuntimeAlive()){Module["onExit"]?.(code);ABORT=true}quit_(code,new ExitStatus(code))};var exitJS=(status,implicit)=>{EXITSTATUS=status;_proc_exit(status)};var _exit=exitJS;var maybeExit=()=>{if(!keepRuntimeAlive()){try{_exit(EXITSTATUS)}catch(e){handleException(e)}}};var callUserCallback=func=>{if(ABORT){return}try{func();maybeExit()}catch(e){handleException(e)}};var sigToWasmTypes=sig=>{var typeNames={i:"i32",j:"i64",f:"f32",d:"f64",e:"externref",p:"i32"};var type={parameters:[],results:sig[0]=="v"?[]:[typeNames[sig[0]]]};for(var i=1;i{runtimeKeepaliveCounter+=1};var runtimeKeepalivePop=()=>{runtimeKeepaliveCounter-=1};var Asyncify={instrumentWasmImports(imports){var importPattern=/^(pv_https_request_wasm|pv_file_open_wasm|pv_file_close_wasm|pv_file_read_wasm|pv_file_write_wasm|pv_file_remove_wasm|pv_sleep_wasm|pv_xpu_webgpu_device_init_wasm|pv_xpu_webgpu_device_info_wasm|pv_xpu_webgpu_device_mem_copy_from_xpu_wasm|pv_xpu_webgpu_device_wait_wasm|pv_xpu_webgpu_timer_stop_wasm|invoke_.*|__asyncjs__.*)$/;for(let[x,original]of Object.entries(imports)){if(typeof original=="function"){let isAsyncifyImport=original.isAsync||importPattern.test(x)}}},instrumentWasmExports(exports){var ret={};for(let[x,original]of Object.entries(exports)){if(typeof original=="function"){ret[x]=(...args)=>{Asyncify.exportCallStack.push(x);try{return original(...args)}finally{if(!ABORT){var y=Asyncify.exportCallStack.pop();Asyncify.maybeStopUnwind()}}}}else{ret[x]=original}}return ret},State:{Normal:0,Unwinding:1,Rewinding:2,Disabled:3},state:0,StackSize:4096,currData:null,handleSleepReturnValue:0,exportCallStack:[],callStackNameToId:{},callStackIdToName:{},callStackId:0,asyncPromiseHandlers:null,sleepCallbacks:[],getCallStackId(funcName){var id=Asyncify.callStackNameToId[funcName];if(id===undefined){id=Asyncify.callStackId++;Asyncify.callStackNameToId[funcName]=id;Asyncify.callStackIdToName[id]=funcName}return id},maybeStopUnwind(){if(Asyncify.currData&&Asyncify.state===Asyncify.State.Unwinding&&Asyncify.exportCallStack.length===0){Asyncify.state=Asyncify.State.Normal;runAndAbortIfError(_asyncify_stop_unwind);if(typeof Fibers!="undefined"){Fibers.trampoline()}}},whenDone(){return new Promise((resolve,reject)=>{Asyncify.asyncPromiseHandlers={resolve:resolve,reject:reject}})},allocateData(){var ptr=_malloc(12+Asyncify.StackSize);Asyncify.setDataHeader(ptr,ptr+12,Asyncify.StackSize);Asyncify.setDataRewindFunc(ptr);return ptr},setDataHeader(ptr,stack,stackSize){HEAPU32[ptr>>2]=stack;HEAPU32[ptr+4>>2]=stack+stackSize},setDataRewindFunc(ptr){var bottomOfCallStack=Asyncify.exportCallStack[0];var rewindId=Asyncify.getCallStackId(bottomOfCallStack);HEAP32[ptr+8>>2]=rewindId},getDataRewindFuncName(ptr){var id=HEAP32[ptr+8>>2];var name=Asyncify.callStackIdToName[id];return name},getDataRewindFunc(name){var func=wasmExports[name];return func},doRewind(ptr){var name=Asyncify.getDataRewindFuncName(ptr);var func=Asyncify.getDataRewindFunc(name);return func()},handleSleep(startAsync){if(ABORT)return;if(Asyncify.state===Asyncify.State.Normal){var reachedCallback=false;var reachedAfterCallback=false;startAsync((handleSleepReturnValue=0)=>{if(ABORT)return;Asyncify.handleSleepReturnValue=handleSleepReturnValue;reachedCallback=true;if(!reachedAfterCallback){return}Asyncify.state=Asyncify.State.Rewinding;runAndAbortIfError(()=>_asyncify_start_rewind(Asyncify.currData));if(typeof Browser!="undefined"&&Browser.mainLoop.func){Browser.mainLoop.resume()}var asyncWasmReturnValue,isError=false;try{asyncWasmReturnValue=Asyncify.doRewind(Asyncify.currData)}catch(err){asyncWasmReturnValue=err;isError=true}var handled=false;if(!Asyncify.currData){var asyncPromiseHandlers=Asyncify.asyncPromiseHandlers;if(asyncPromiseHandlers){Asyncify.asyncPromiseHandlers=null;(isError?asyncPromiseHandlers.reject:asyncPromiseHandlers.resolve)(asyncWasmReturnValue);handled=true}}if(isError&&!handled){throw asyncWasmReturnValue}});reachedAfterCallback=true;if(!reachedCallback){Asyncify.state=Asyncify.State.Unwinding;Asyncify.currData=Asyncify.allocateData();if(typeof Browser!="undefined"&&Browser.mainLoop.func){Browser.mainLoop.pause()}runAndAbortIfError(()=>_asyncify_start_unwind(Asyncify.currData))}}else if(Asyncify.state===Asyncify.State.Rewinding){Asyncify.state=Asyncify.State.Normal;runAndAbortIfError(_asyncify_stop_rewind);_free(Asyncify.currData);Asyncify.currData=null;Asyncify.sleepCallbacks.forEach(callUserCallback)}else{abort(`invalid state: ${Asyncify.state}`)}return Asyncify.handleSleepReturnValue},handleAsync(startAsync){return Asyncify.handleSleep(wakeUp=>{startAsync().then(wakeUp)})}};var uleb128Encode=(n,target)=>{if(n<128){target.push(n)}else{target.push(n%128|128,n>>7)}};var generateFuncType=(sig,target)=>{var sigRet=sig.slice(0,1);var sigParam=sig.slice(1);var typeCodes={i:127,p:127,j:126,f:125,d:124,e:111};target.push(96);uleb128Encode(sigParam.length,target);for(var i=0;i{if(typeof WebAssembly.Function=="function"){return new WebAssembly.Function(sigToWasmTypes(sig),func)}var typeSectionBody=[1];generateFuncType(sig,typeSectionBody);var bytes=[0,97,115,109,1,0,0,0,1];uleb128Encode(typeSectionBody.length,bytes);bytes.push(...typeSectionBody);bytes.push(2,7,1,1,101,1,102,0,0,7,5,1,1,102,0,0);var module=new WebAssembly.Module(new Uint8Array(bytes));var instance=new WebAssembly.Instance(module,{e:{f:func}});var wrappedFunc=instance.exports["f"];return wrappedFunc};var wasmTableMirror=[];var wasmTable;var getWasmTableEntry=funcPtr=>{var func=wasmTableMirror[funcPtr];if(!func){if(funcPtr>=wasmTableMirror.length)wasmTableMirror.length=funcPtr+1;wasmTableMirror[funcPtr]=func=wasmTable.get(funcPtr)}return func};var updateTableMap=(offset,count)=>{if(functionsInTableMap){for(var i=offset;i{if(!functionsInTableMap){functionsInTableMap=new WeakMap;updateTableMap(0,wasmTable.length)}return functionsInTableMap.get(func)||0};var freeTableIndexes=[];var getEmptyTableSlot=()=>{if(freeTableIndexes.length){return freeTableIndexes.pop()}try{wasmTable.grow(1)}catch(err){if(!(err instanceof RangeError)){throw err}throw"Unable to grow wasm table. Set ALLOW_TABLE_GROWTH."}return wasmTable.length-1};var setWasmTableEntry=(idx,func)=>{wasmTable.set(idx,func);wasmTableMirror[idx]=wasmTable.get(idx)};var addFunction=(func,sig)=>{var rtn=getFunctionAddress(func);if(rtn){return rtn}var ret=getEmptyTableSlot();try{setWasmTableEntry(ret,func)}catch(err){if(!(err instanceof TypeError)){throw err}var wrapped=convertJsFunctionToWasm(func,sig);setWasmTableEntry(ret,wrapped)}functionsInTableMap.set(func,ret);return ret};var getCFunc=ident=>{var func=Module["_"+ident];return func};var writeArrayToMemory=(array,buffer)=>{HEAP8.set(array,buffer)};var lengthBytesUTF8=str=>{var len=0;for(var i=0;i=55296&&c<=57343){len+=4;++i}else{len+=3}}return len};var stringToUTF8Array=(str,heap,outIdx,maxBytesToWrite)=>{if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}}heap[outIdx]=0;return outIdx-startIdx};var stringToUTF8=(str,outPtr,maxBytesToWrite)=>stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite);var stackAlloc=sz=>__emscripten_stack_alloc(sz);var stringToUTF8OnStack=str=>{var size=lengthBytesUTF8(str)+1;var ret=stackAlloc(size);stringToUTF8(str,ret,size);return ret};var UTF8Decoder=typeof TextDecoder!="undefined"?new TextDecoder:undefined;var UTF8ArrayToString=(heapOrArray,idx,maxBytesToRead)=>{var endIdx=idx+maxBytesToRead;var endPtr=idx;while(heapOrArray[endPtr]&&!(endPtr>=endIdx))++endPtr;if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.subarray(idx,endPtr))}var str="";while(idx>10,56320|ch&1023)}}return str};var UTF8ToString=(ptr,maxBytesToRead)=>ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):"";var ccall=(ident,returnType,argTypes,args,opts)=>{var toC={string:str=>{var ret=0;if(str!==null&&str!==undefined&&str!==0){ret=stringToUTF8OnStack(str)}return ret},array:arr=>{var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string"){return UTF8ToString(ret)}if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i{var numericArgs=!argTypes||argTypes.every(type=>type==="number"||type==="boolean");var numericRet=returnType!=="string";if(numericRet&&numericArgs&&!opts){return getCFunc(ident)}return(...args)=>ccall(ident,returnType,argTypes,args,opts)};Module["cwrap"]=cwrap;xpu_cpu_support();var wasmImports={f:_emscripten_resize_heap,a:_pv_console_log_wasm,d:_pv_file_close_wasm,e:_pv_file_open_wasm,c:_pv_file_read_wasm,b:_pv_file_write_wasm,g:_pv_https_request_wasm,h:_pv_time_wasm,i:_pv_xpu_get_max_workers_wasm};var wasmExports=createWasm();var ___wasm_call_ctors=()=>(___wasm_call_ctors=wasmExports["k"])();var _pv_eagle_init=Module["_pv_eagle_init"]=(a0,a1,a2,a3,a4,a5)=>(_pv_eagle_init=Module["_pv_eagle_init"]=wasmExports["l"])(a0,a1,a2,a3,a4,a5);var _pv_eagle_delete=Module["_pv_eagle_delete"]=a0=>(_pv_eagle_delete=Module["_pv_eagle_delete"]=wasmExports["m"])(a0);var _free=a0=>(_free=wasmExports["n"])(a0);var _malloc=Module["_malloc"]=a0=>(_malloc=Module["_malloc"]=wasmExports["o"])(a0);var _pv_eagle_process=Module["_pv_eagle_process"]=(a0,a1,a2)=>(_pv_eagle_process=Module["_pv_eagle_process"]=wasmExports["p"])(a0,a1,a2);var _pv_sample_rate=Module["_pv_sample_rate"]=()=>(_pv_sample_rate=Module["_pv_sample_rate"]=wasmExports["q"])();var _pv_eagle_frame_length=Module["_pv_eagle_frame_length"]=()=>(_pv_eagle_frame_length=Module["_pv_eagle_frame_length"]=wasmExports["r"])();var _pv_eagle_reset=Module["_pv_eagle_reset"]=a0=>(_pv_eagle_reset=Module["_pv_eagle_reset"]=wasmExports["s"])(a0);var _pv_eagle_version=Module["_pv_eagle_version"]=()=>(_pv_eagle_version=Module["_pv_eagle_version"]=wasmExports["t"])();var _pv_eagle_profiler_init=Module["_pv_eagle_profiler_init"]=(a0,a1,a2,a3)=>(_pv_eagle_profiler_init=Module["_pv_eagle_profiler_init"]=wasmExports["u"])(a0,a1,a2,a3);var _pv_eagle_profiler_delete=Module["_pv_eagle_profiler_delete"]=a0=>(_pv_eagle_profiler_delete=Module["_pv_eagle_profiler_delete"]=wasmExports["v"])(a0);var _pv_eagle_profiler_enroll=Module["_pv_eagle_profiler_enroll"]=(a0,a1,a2,a3,a4)=>(_pv_eagle_profiler_enroll=Module["_pv_eagle_profiler_enroll"]=wasmExports["w"])(a0,a1,a2,a3,a4);var _pv_eagle_profiler_enroll_min_audio_length_samples=Module["_pv_eagle_profiler_enroll_min_audio_length_samples"]=(a0,a1)=>(_pv_eagle_profiler_enroll_min_audio_length_samples=Module["_pv_eagle_profiler_enroll_min_audio_length_samples"]=wasmExports["x"])(a0,a1);var _pv_eagle_profiler_enroll_feedback_to_string=Module["_pv_eagle_profiler_enroll_feedback_to_string"]=a0=>(_pv_eagle_profiler_enroll_feedback_to_string=Module["_pv_eagle_profiler_enroll_feedback_to_string"]=wasmExports["y"])(a0);var _pv_eagle_profiler_export_size=Module["_pv_eagle_profiler_export_size"]=(a0,a1)=>(_pv_eagle_profiler_export_size=Module["_pv_eagle_profiler_export_size"]=wasmExports["z"])(a0,a1);var _pv_eagle_profiler_export=Module["_pv_eagle_profiler_export"]=(a0,a1)=>(_pv_eagle_profiler_export=Module["_pv_eagle_profiler_export"]=wasmExports["A"])(a0,a1);var _pv_eagle_profiler_reset=Module["_pv_eagle_profiler_reset"]=a0=>(_pv_eagle_profiler_reset=Module["_pv_eagle_profiler_reset"]=wasmExports["B"])(a0);var _pv_eagle_list_hardware_devices=Module["_pv_eagle_list_hardware_devices"]=(a0,a1)=>(_pv_eagle_list_hardware_devices=Module["_pv_eagle_list_hardware_devices"]=wasmExports["C"])(a0,a1);var _pv_eagle_free_hardware_devices=Module["_pv_eagle_free_hardware_devices"]=(a0,a1)=>(_pv_eagle_free_hardware_devices=Module["_pv_eagle_free_hardware_devices"]=wasmExports["D"])(a0,a1);var _pv_log_enable=Module["_pv_log_enable"]=()=>(_pv_log_enable=Module["_pv_log_enable"]=wasmExports["F"])();var _pv_log_disable=Module["_pv_log_disable"]=()=>(_pv_log_disable=Module["_pv_log_disable"]=wasmExports["G"])();var _aligned_alloc=Module["_aligned_alloc"]=(a0,a1)=>(_aligned_alloc=Module["_aligned_alloc"]=wasmExports["H"])(a0,a1);var _pv_get_sdk=Module["_pv_get_sdk"]=()=>(_pv_get_sdk=Module["_pv_get_sdk"]=wasmExports["I"])();var _pv_status_to_string=Module["_pv_status_to_string"]=a0=>(_pv_status_to_string=Module["_pv_status_to_string"]=wasmExports["J"])(a0);var _pv_set_sdk=Module["_pv_set_sdk"]=a0=>(_pv_set_sdk=Module["_pv_set_sdk"]=wasmExports["K"])(a0);var _pv_free=Module["_pv_free"]=a0=>(_pv_free=Module["_pv_free"]=wasmExports["L"])(a0);var _pv_get_error_stack=Module["_pv_get_error_stack"]=(a0,a1)=>(_pv_get_error_stack=Module["_pv_get_error_stack"]=wasmExports["M"])(a0,a1);var _pv_free_error_stack=Module["_pv_free_error_stack"]=a0=>(_pv_free_error_stack=Module["_pv_free_error_stack"]=wasmExports["N"])(a0);var __emscripten_memcpy_bulkmem=Module["__emscripten_memcpy_bulkmem"]=(a0,a1,a2)=>(__emscripten_memcpy_bulkmem=Module["__emscripten_memcpy_bulkmem"]=wasmExports["O"])(a0,a1,a2);var __emscripten_memset_bulkmem=Module["__emscripten_memset_bulkmem"]=(a0,a1,a2)=>(__emscripten_memset_bulkmem=Module["__emscripten_memset_bulkmem"]=wasmExports["P"])(a0,a1,a2);var __emscripten_stack_restore=a0=>(__emscripten_stack_restore=wasmExports["Q"])(a0);var __emscripten_stack_alloc=a0=>(__emscripten_stack_alloc=wasmExports["R"])(a0);var _emscripten_stack_get_current=()=>(_emscripten_stack_get_current=wasmExports["S"])();var _asyncify_start_unwind=a0=>(_asyncify_start_unwind=wasmExports["T"])(a0);var _asyncify_stop_unwind=()=>(_asyncify_stop_unwind=wasmExports["U"])();var _asyncify_start_rewind=a0=>(_asyncify_start_rewind=wasmExports["V"])(a0);var _asyncify_stop_rewind=()=>(_asyncify_stop_rewind=wasmExports["W"])();Module["addFunction"]=addFunction;var calledRun;dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function run(){if(runDependencies>0){return}preRun();if(runDependencies>0){return}function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();readyPromiseResolve(Module);Module["onRuntimeInitialized"]?.();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("")},1);doRun()},1)}else{doRun()}}if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}run();moduleRtn=readyPromise; +var Module=moduleArg;var readyPromiseResolve,readyPromiseReject;var readyPromise=new Promise((resolve,reject)=>{readyPromiseResolve=resolve;readyPromiseReject=reject});var ENVIRONMENT_IS_WEB=typeof window=="object";var ENVIRONMENT_IS_WORKER=typeof importScripts=="function";var ENVIRONMENT_IS_NODE=typeof process=="object"&&typeof process.versions=="object"&&typeof process.versions.node=="string";function _typeof$2(o){null;return _typeof$2="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(o){return typeof o}:function(o){return o&&"function"==typeof Symbol&&o.constructor===Symbol&&o!==Symbol.prototype?"symbol":typeof o},_typeof$2(o)}function toPrimitive(t,r){if("object"!=_typeof$2(t)||!t)return t;var e=t[Symbol.toPrimitive];if(void 0!==e){var i=e.call(t,r||"default");if("object"!=_typeof$2(i))return i;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===r?String:Number)(t)}function toPropertyKey(t){var i=toPrimitive(t,"string");return"symbol"==_typeof$2(i)?i:i+""}function _defineProperty(e,r,t){return(r=toPropertyKey(r))in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function asyncGeneratorStep(n,t,e,r,o,a,c){try{var i=n[a](c),u=i.value}catch(n){return void e(n)}i.done?t(u):Promise.resolve(u).then(r,o)}function _asyncToGenerator(n){return function(){var t=this,e=arguments;return new Promise(function(r,o){var a=n.apply(t,e);function _next(n){asyncGeneratorStep(a,r,o,_next,_throw,"next",n)}function _throw(n){asyncGeneratorStep(a,r,o,_next,_throw,"throw",n)}_next(void 0)})}}function getDefaultExportFromCjs(x){return x&&x.__esModule&&Object.prototype.hasOwnProperty.call(x,"default")?x["default"]:x}var regeneratorRuntime$3={exports:{}};var _typeof$1={exports:{}};var _typeof_1=_typeof$1.exports;(function(module){function _typeof(o){null;return module.exports=_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(o){return typeof o}:function(o){return o&&"function"==typeof Symbol&&o.constructor===Symbol&&o!==Symbol.prototype?"symbol":typeof o},module.exports.__esModule=true,module.exports["default"]=module.exports,_typeof(o)}module.exports=_typeof,module.exports.__esModule=true,module.exports["default"]=module.exports})(_typeof$1);var _typeofExports=_typeof$1.exports;var _typeof=getDefaultExportFromCjs(_typeofExports);var regeneratorRuntime$1=regeneratorRuntime$3.exports;(function(module){var _typeof=_typeofExports["default"];function _regeneratorRuntime(){"use strict";module.exports=_regeneratorRuntime=function _regeneratorRuntime(){return e},module.exports.__esModule=true,module.exports["default"]=module.exports;var t,e={},r=Object.prototype,n=r.hasOwnProperty,o=Object.defineProperty||function(t,e,r){t[e]=r.value},i="function"==typeof Symbol?Symbol:{},a=i.iterator||"@@iterator",c=i.asyncIterator||"@@asyncIterator",u=i.toStringTag||"@@toStringTag";function define(t,e,r){return Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}),t[e]}try{define({},"")}catch(t){define=function define(t,e,r){return t[e]=r}}function wrap(t,e,r,n){var i=e&&e.prototype instanceof Generator?e:Generator,a=Object.create(i.prototype),c=new Context(n||[]);return o(a,"_invoke",{value:makeInvokeMethod(t,r,c)}),a}function tryCatch(t,e,r){try{return{type:"normal",arg:t.call(e,r)}}catch(t){return{type:"throw",arg:t}}}e.wrap=wrap;var h="suspendedStart",l="suspendedYield",f="executing",s="completed",y={};function Generator(){}function GeneratorFunction(){}function GeneratorFunctionPrototype(){}var p={};define(p,a,function(){return this});var d=Object.getPrototypeOf,v=d&&d(d(values([])));v&&v!==r&&n.call(v,a)&&(p=v);var g=GeneratorFunctionPrototype.prototype=Generator.prototype=Object.create(p);function defineIteratorMethods(t){["next","throw","return"].forEach(function(e){define(t,e,function(t){return this._invoke(e,t)})})}function AsyncIterator(t,e){function invoke(r,o,i,a){var c=tryCatch(t[r],t,o);if("throw"!==c.type){var u=c.arg,h=u.value;return h&&"object"==_typeof(h)&&n.call(h,"__await")?e.resolve(h.__await).then(function(t){invoke("next",t,i,a)},function(t){invoke("throw",t,i,a)}):e.resolve(h).then(function(t){u.value=t,i(u)},function(t){return invoke("throw",t,i,a)})}a(c.arg)}var r;o(this,"_invoke",{value:function value(t,n){function callInvokeWithMethodAndArg(){return new e(function(e,r){invoke(t,n,e,r)})}return r=r?r.then(callInvokeWithMethodAndArg,callInvokeWithMethodAndArg):callInvokeWithMethodAndArg()}})}function makeInvokeMethod(e,r,n){var o=h;return function(i,a){if(o===f)throw Error("Generator is already running");if(o===s){if("throw"===i)throw a;return{value:t,done:!0}}for(n.method=i,n.arg=a;;){var c=n.delegate;if(c){var u=maybeInvokeDelegate(c,n);if(u){if(u===y)continue;return u}}if("next"===n.method)n.sent=n._sent=n.arg;else if("throw"===n.method){if(o===h)throw o=s,n.arg;n.dispatchException(n.arg)}else"return"===n.method&&n.abrupt("return",n.arg);o=f;var p=tryCatch(e,r,n);if("normal"===p.type){if(o=n.done?s:l,p.arg===y)continue;return{value:p.arg,done:n.done}}"throw"===p.type&&(o=s,n.method="throw",n.arg=p.arg)}}}function maybeInvokeDelegate(e,r){var n=r.method,o=e.iterator[n];if(o===t)return r.delegate=null,"throw"===n&&e.iterator["return"]&&(r.method="return",r.arg=t,maybeInvokeDelegate(e,r),"throw"===r.method)||"return"!==n&&(r.method="throw",r.arg=new TypeError("The iterator does not provide a '"+n+"' method")),y;var i=tryCatch(o,e.iterator,r.arg);if("throw"===i.type)return r.method="throw",r.arg=i.arg,r.delegate=null,y;var a=i.arg;return a?a.done?(r[e.resultName]=a.value,r.next=e.nextLoc,"return"!==r.method&&(r.method="next",r.arg=t),r.delegate=null,y):a:(r.method="throw",r.arg=new TypeError("iterator result is not an object"),r.delegate=null,y)}function pushTryEntry(t){var e={tryLoc:t[0]};1 in t&&(e.catchLoc=t[1]),2 in t&&(e.finallyLoc=t[2],e.afterLoc=t[3]),this.tryEntries.push(e)}function resetTryEntry(t){var e=t.completion||{};e.type="normal",delete e.arg,t.completion=e}function Context(t){this.tryEntries=[{tryLoc:"root"}],t.forEach(pushTryEntry,this),this.reset(!0)}function values(e){if(e||""===e){var r=e[a];if(r)return r.call(e);if("function"==typeof e.next)return e;if(!isNaN(e.length)){var o=-1,i=function next(){for(;++o=0;--o){var i=this.tryEntries[o],a=i.completion;if("root"===i.tryLoc)return handle("end");if(i.tryLoc<=this.prev){var c=n.call(i,"catchLoc"),u=n.call(i,"finallyLoc");if(c&&u){if(this.prev=0;--r){var o=this.tryEntries[r];if(o.tryLoc<=this.prev&&n.call(o,"finallyLoc")&&this.prev=0;--e){var r=this.tryEntries[e];if(r.finallyLoc===t)return this.complete(r.completion,r.afterLoc),resetTryEntry(r),y}},catch:function _catch(t){for(var e=this.tryEntries.length-1;e>=0;--e){var r=this.tryEntries[e];if(r.tryLoc===t){var n=r.completion;if("throw"===n.type){var o=n.arg;resetTryEntry(r)}return o}}throw Error("illegal catch attempt")},delegateYield:function delegateYield(e,r,n){return this.delegate={iterator:values(e),resultName:r,nextLoc:n},"next"===this.method&&(this.arg=t),y}},e}module.exports=_regeneratorRuntime,module.exports.__esModule=true,module.exports["default"]=module.exports})(regeneratorRuntime$3);var regeneratorRuntimeExports=regeneratorRuntime$3.exports;var regeneratorRuntime$2=getDefaultExportFromCjs(regeneratorRuntimeExports);var runtime=regeneratorRuntimeExports();var regenerator=runtime;try{regeneratorRuntime=runtime}catch(accidentalStrictMode){if(typeof globalThis==="object"){globalThis.regeneratorRuntime=runtime}else{Function("r","regeneratorRuntime = r")(runtime)}}var _regeneratorRuntime=getDefaultExportFromCjs(regenerator);const BROWSER_ALIASES_MAP={"Amazon Silk":"amazon_silk","Android Browser":"android",Bada:"bada",BlackBerry:"blackberry",Chrome:"chrome",Chromium:"chromium",Electron:"electron",Epiphany:"epiphany",Firefox:"firefox",Focus:"focus",Generic:"generic","Google Search":"google_search",Googlebot:"googlebot","Internet Explorer":"ie","K-Meleon":"k_meleon",Maxthon:"maxthon","Microsoft Edge":"edge","MZ Browser":"mz","NAVER Whale Browser":"naver",Opera:"opera","Opera Coast":"opera_coast",PhantomJS:"phantomjs",Puffin:"puffin",QupZilla:"qupzilla",QQ:"qq",QQLite:"qqlite",Safari:"safari",Sailfish:"sailfish","Samsung Internet for Android":"samsung_internet",SeaMonkey:"seamonkey",Sleipnir:"sleipnir",Swing:"swing",Tizen:"tizen","UC Browser":"uc",Vivaldi:"vivaldi","WebOS Browser":"webos",WeChat:"wechat","Yandex Browser":"yandex",Roku:"roku"};const BROWSER_MAP={amazon_silk:"Amazon Silk",android:"Android Browser",bada:"Bada",blackberry:"BlackBerry",chrome:"Chrome",chromium:"Chromium",electron:"Electron",epiphany:"Epiphany",firefox:"Firefox",focus:"Focus",generic:"Generic",googlebot:"Googlebot",google_search:"Google Search",ie:"Internet Explorer",k_meleon:"K-Meleon",maxthon:"Maxthon",edge:"Microsoft Edge",mz:"MZ Browser",naver:"NAVER Whale Browser",opera:"Opera",opera_coast:"Opera Coast",phantomjs:"PhantomJS",puffin:"Puffin",qupzilla:"QupZilla",qq:"QQ Browser",qqlite:"QQ Browser Lite",safari:"Safari",sailfish:"Sailfish",samsung_internet:"Samsung Internet for Android",seamonkey:"SeaMonkey",sleipnir:"Sleipnir",swing:"Swing",tizen:"Tizen",uc:"UC Browser",vivaldi:"Vivaldi",webos:"WebOS Browser",wechat:"WeChat",yandex:"Yandex Browser"};const PLATFORMS_MAP={tablet:"tablet",mobile:"mobile",desktop:"desktop",tv:"tv"};const OS_MAP={WindowsPhone:"Windows Phone",Windows:"Windows",MacOS:"macOS",iOS:"iOS",Android:"Android",WebOS:"WebOS",BlackBerry:"BlackBerry",Bada:"Bada",Tizen:"Tizen",Linux:"Linux",ChromeOS:"Chrome OS",PlayStation4:"PlayStation 4",Roku:"Roku"};const ENGINE_MAP={EdgeHTML:"EdgeHTML",Blink:"Blink",Trident:"Trident",Presto:"Presto",Gecko:"Gecko",WebKit:"WebKit"};class Utils{static getFirstMatch(regexp,ua){const match=ua.match(regexp);return match&&match.length>0&&match[1]||""}static getSecondMatch(regexp,ua){const match=ua.match(regexp);return match&&match.length>1&&match[2]||""}static matchAndReturnConst(regexp,ua,_const){if(regexp.test(ua)){return _const}return void 0}static getWindowsVersionName(version){switch(version){case"NT":return"NT";case"XP":return"XP";case"NT 5.0":return"2000";case"NT 5.1":return"XP";case"NT 5.2":return"2003";case"NT 6.0":return"Vista";case"NT 6.1":return"7";case"NT 6.2":return"8";case"NT 6.3":return"8.1";case"NT 10.0":return"10";default:return undefined}}static getMacOSVersionName(version){const v=version.split(".").splice(0,2).map(s=>parseInt(s,10)||0);v.push(0);if(v[0]!==10)return undefined;switch(v[1]){case 5:return"Leopard";case 6:return"Snow Leopard";case 7:return"Lion";case 8:return"Mountain Lion";case 9:return"Mavericks";case 10:return"Yosemite";case 11:return"El Capitan";case 12:return"Sierra";case 13:return"High Sierra";case 14:return"Mojave";case 15:return"Catalina";default:return undefined}}static getAndroidVersionName(version){const v=version.split(".").splice(0,2).map(s=>parseInt(s,10)||0);v.push(0);if(v[0]===1&&v[1]<5)return undefined;if(v[0]===1&&v[1]<6)return"Cupcake";if(v[0]===1&&v[1]>=6)return"Donut";if(v[0]===2&&v[1]<2)return"Eclair";if(v[0]===2&&v[1]===2)return"Froyo";if(v[0]===2&&v[1]>2)return"Gingerbread";if(v[0]===3)return"Honeycomb";if(v[0]===4&&v[1]<1)return"Ice Cream Sandwich";if(v[0]===4&&v[1]<4)return"Jelly Bean";if(v[0]===4&&v[1]>=4)return"KitKat";if(v[0]===5)return"Lollipop";if(v[0]===6)return"Marshmallow";if(v[0]===7)return"Nougat";if(v[0]===8)return"Oreo";if(v[0]===9)return"Pie";return undefined}static getVersionPrecision(version){return version.split(".").length}static compareVersions(versionA,versionB,isLoose=false){const versionAPrecision=Utils.getVersionPrecision(versionA);const versionBPrecision=Utils.getVersionPrecision(versionB);let precision=Math.max(versionAPrecision,versionBPrecision);let lastPrecision=0;const chunks=Utils.map([versionA,versionB],version=>{const delta=precision-Utils.getVersionPrecision(version);const _version=version+new Array(delta+1).join(".0");return Utils.map(_version.split("."),chunk=>new Array(20-chunk.length).join("0")+chunk).reverse()});if(isLoose){lastPrecision=precision-Math.min(versionAPrecision,versionBPrecision)}precision-=1;while(precision>=lastPrecision){if(chunks[0][precision]>chunks[1][precision]){return 1}if(chunks[0][precision]===chunks[1][precision]){if(precision===lastPrecision){return 0}precision-=1}else if(chunks[0][precision]{result[key]=assigner[key]})}}return obj}static getBrowserAlias(browserName){return BROWSER_ALIASES_MAP[browserName]}static getBrowserTypeByAlias(browserAlias){return BROWSER_MAP[browserAlias]||""}}const commonVersionIdentifier=/version\/(\d+(\.?_?\d+)+)/i;const browsersList=[{test:[/googlebot/i],describe(ua){const browser={name:"Googlebot"};const version=Utils.getFirstMatch(/googlebot\/(\d+(\.\d+))/i,ua)||Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/opera/i],describe(ua){const browser={name:"Opera"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua)||Utils.getFirstMatch(/(?:opera)[\s/](\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/opr\/|opios/i],describe(ua){const browser={name:"Opera"};const version=Utils.getFirstMatch(/(?:opr|opios)[\s/](\S+)/i,ua)||Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/SamsungBrowser/i],describe(ua){const browser={name:"Samsung Internet for Android"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua)||Utils.getFirstMatch(/(?:SamsungBrowser)[\s/](\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/Whale/i],describe(ua){const browser={name:"NAVER Whale Browser"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua)||Utils.getFirstMatch(/(?:whale)[\s/](\d+(?:\.\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/MZBrowser/i],describe(ua){const browser={name:"MZ Browser"};const version=Utils.getFirstMatch(/(?:MZBrowser)[\s/](\d+(?:\.\d+)+)/i,ua)||Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/focus/i],describe(ua){const browser={name:"Focus"};const version=Utils.getFirstMatch(/(?:focus)[\s/](\d+(?:\.\d+)+)/i,ua)||Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/swing/i],describe(ua){const browser={name:"Swing"};const version=Utils.getFirstMatch(/(?:swing)[\s/](\d+(?:\.\d+)+)/i,ua)||Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/coast/i],describe(ua){const browser={name:"Opera Coast"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua)||Utils.getFirstMatch(/(?:coast)[\s/](\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/opt\/\d+(?:.?_?\d+)+/i],describe(ua){const browser={name:"Opera Touch"};const version=Utils.getFirstMatch(/(?:opt)[\s/](\d+(\.?_?\d+)+)/i,ua)||Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/yabrowser/i],describe(ua){const browser={name:"Yandex Browser"};const version=Utils.getFirstMatch(/(?:yabrowser)[\s/](\d+(\.?_?\d+)+)/i,ua)||Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/ucbrowser/i],describe(ua){const browser={name:"UC Browser"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua)||Utils.getFirstMatch(/(?:ucbrowser)[\s/](\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/Maxthon|mxios/i],describe(ua){const browser={name:"Maxthon"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua)||Utils.getFirstMatch(/(?:Maxthon|mxios)[\s/](\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/epiphany/i],describe(ua){const browser={name:"Epiphany"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua)||Utils.getFirstMatch(/(?:epiphany)[\s/](\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/puffin/i],describe(ua){const browser={name:"Puffin"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua)||Utils.getFirstMatch(/(?:puffin)[\s/](\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/sleipnir/i],describe(ua){const browser={name:"Sleipnir"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua)||Utils.getFirstMatch(/(?:sleipnir)[\s/](\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/k-meleon/i],describe(ua){const browser={name:"K-Meleon"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua)||Utils.getFirstMatch(/(?:k-meleon)[\s/](\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/micromessenger/i],describe(ua){const browser={name:"WeChat"};const version=Utils.getFirstMatch(/(?:micromessenger)[\s/](\d+(\.?_?\d+)+)/i,ua)||Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/qqbrowser/i],describe(ua){const browser={name:/qqbrowserlite/i.test(ua)?"QQ Browser Lite":"QQ Browser"};const version=Utils.getFirstMatch(/(?:qqbrowserlite|qqbrowser)[/](\d+(\.?_?\d+)+)/i,ua)||Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/msie|trident/i],describe(ua){const browser={name:"Internet Explorer"};const version=Utils.getFirstMatch(/(?:msie |rv:)(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/\sedg\//i],describe(ua){const browser={name:"Microsoft Edge"};const version=Utils.getFirstMatch(/\sedg\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/edg([ea]|ios)/i],describe(ua){const browser={name:"Microsoft Edge"};const version=Utils.getSecondMatch(/edg([ea]|ios)\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/vivaldi/i],describe(ua){const browser={name:"Vivaldi"};const version=Utils.getFirstMatch(/vivaldi\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/seamonkey/i],describe(ua){const browser={name:"SeaMonkey"};const version=Utils.getFirstMatch(/seamonkey\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/sailfish/i],describe(ua){const browser={name:"Sailfish"};const version=Utils.getFirstMatch(/sailfish\s?browser\/(\d+(\.\d+)?)/i,ua);if(version){browser.version=version}return browser}},{test:[/silk/i],describe(ua){const browser={name:"Amazon Silk"};const version=Utils.getFirstMatch(/silk\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/phantom/i],describe(ua){const browser={name:"PhantomJS"};const version=Utils.getFirstMatch(/phantomjs\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/slimerjs/i],describe(ua){const browser={name:"SlimerJS"};const version=Utils.getFirstMatch(/slimerjs\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/blackberry|\bbb\d+/i,/rim\stablet/i],describe(ua){const browser={name:"BlackBerry"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua)||Utils.getFirstMatch(/blackberry[\d]+\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/(web|hpw)[o0]s/i],describe(ua){const browser={name:"WebOS Browser"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua)||Utils.getFirstMatch(/w(?:eb)?[o0]sbrowser\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/bada/i],describe(ua){const browser={name:"Bada"};const version=Utils.getFirstMatch(/dolfin\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/tizen/i],describe(ua){const browser={name:"Tizen"};const version=Utils.getFirstMatch(/(?:tizen\s?)?browser\/(\d+(\.?_?\d+)+)/i,ua)||Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/qupzilla/i],describe(ua){const browser={name:"QupZilla"};const version=Utils.getFirstMatch(/(?:qupzilla)[\s/](\d+(\.?_?\d+)+)/i,ua)||Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/firefox|iceweasel|fxios/i],describe(ua){const browser={name:"Firefox"};const version=Utils.getFirstMatch(/(?:firefox|iceweasel|fxios)[\s/](\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/electron/i],describe(ua){const browser={name:"Electron"};const version=Utils.getFirstMatch(/(?:electron)\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/MiuiBrowser/i],describe(ua){const browser={name:"Miui"};const version=Utils.getFirstMatch(/(?:MiuiBrowser)[\s/](\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/chromium/i],describe(ua){const browser={name:"Chromium"};const version=Utils.getFirstMatch(/(?:chromium)[\s/](\d+(\.?_?\d+)+)/i,ua)||Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/chrome|crios|crmo/i],describe(ua){const browser={name:"Chrome"};const version=Utils.getFirstMatch(/(?:chrome|crios|crmo)\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test:[/GSA/i],describe(ua){const browser={name:"Google Search"};const version=Utils.getFirstMatch(/(?:GSA)\/(\d+(\.?_?\d+)+)/i,ua);if(version){browser.version=version}return browser}},{test(parser){const notLikeAndroid=!parser.test(/like android/i);const butAndroid=parser.test(/android/i);return notLikeAndroid&&butAndroid},describe(ua){const browser={name:"Android Browser"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/playstation 4/i],describe(ua){const browser={name:"PlayStation 4"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/safari|applewebkit/i],describe(ua){const browser={name:"Safari"};const version=Utils.getFirstMatch(commonVersionIdentifier,ua);if(version){browser.version=version}return browser}},{test:[/.*/i],describe(ua){const regexpWithoutDeviceSpec=/^(.*)\/(.*) /;const regexpWithDeviceSpec=/^(.*)\/(.*)[ \t]\((.*)/;const hasDeviceSpec=ua.search("\\(")!==-1;const regexp=hasDeviceSpec?regexpWithDeviceSpec:regexpWithoutDeviceSpec;return{name:Utils.getFirstMatch(regexp,ua),version:Utils.getSecondMatch(regexp,ua)}}}];var osParsersList=[{test:[/Roku\/DVP/],describe(ua){const version=Utils.getFirstMatch(/Roku\/DVP-(\d+\.\d+)/i,ua);return{name:OS_MAP.Roku,version:version}}},{test:[/windows phone/i],describe(ua){const version=Utils.getFirstMatch(/windows phone (?:os)?\s?(\d+(\.\d+)*)/i,ua);return{name:OS_MAP.WindowsPhone,version:version}}},{test:[/windows /i],describe(ua){const version=Utils.getFirstMatch(/Windows ((NT|XP)( \d\d?.\d)?)/i,ua);const versionName=Utils.getWindowsVersionName(version);return{name:OS_MAP.Windows,version:version,versionName:versionName}}},{test:[/Macintosh(.*?) FxiOS(.*?)\//],describe(ua){const result={name:OS_MAP.iOS};const version=Utils.getSecondMatch(/(Version\/)(\d[\d.]+)/,ua);if(version){result.version=version}return result}},{test:[/macintosh/i],describe(ua){const version=Utils.getFirstMatch(/mac os x (\d+(\.?_?\d+)+)/i,ua).replace(/[_\s]/g,".");const versionName=Utils.getMacOSVersionName(version);const os={name:OS_MAP.MacOS,version:version};if(versionName){os.versionName=versionName}return os}},{test:[/(ipod|iphone|ipad)/i],describe(ua){const version=Utils.getFirstMatch(/os (\d+([_\s]\d+)*) like mac os x/i,ua).replace(/[_\s]/g,".");return{name:OS_MAP.iOS,version:version}}},{test(parser){const notLikeAndroid=!parser.test(/like android/i);const butAndroid=parser.test(/android/i);return notLikeAndroid&&butAndroid},describe(ua){const version=Utils.getFirstMatch(/android[\s/-](\d+(\.\d+)*)/i,ua);const versionName=Utils.getAndroidVersionName(version);const os={name:OS_MAP.Android,version:version};if(versionName){os.versionName=versionName}return os}},{test:[/(web|hpw)[o0]s/i],describe(ua){const version=Utils.getFirstMatch(/(?:web|hpw)[o0]s\/(\d+(\.\d+)*)/i,ua);const os={name:OS_MAP.WebOS};if(version&&version.length){os.version=version}return os}},{test:[/blackberry|\bbb\d+/i,/rim\stablet/i],describe(ua){const version=Utils.getFirstMatch(/rim\stablet\sos\s(\d+(\.\d+)*)/i,ua)||Utils.getFirstMatch(/blackberry\d+\/(\d+([_\s]\d+)*)/i,ua)||Utils.getFirstMatch(/\bbb(\d+)/i,ua);return{name:OS_MAP.BlackBerry,version:version}}},{test:[/bada/i],describe(ua){const version=Utils.getFirstMatch(/bada\/(\d+(\.\d+)*)/i,ua);return{name:OS_MAP.Bada,version:version}}},{test:[/tizen/i],describe(ua){const version=Utils.getFirstMatch(/tizen[/\s](\d+(\.\d+)*)/i,ua);return{name:OS_MAP.Tizen,version:version}}},{test:[/linux/i],describe(){return{name:OS_MAP.Linux}}},{test:[/CrOS/],describe(){return{name:OS_MAP.ChromeOS}}},{test:[/PlayStation 4/],describe(ua){const version=Utils.getFirstMatch(/PlayStation 4[/\s](\d+(\.\d+)*)/i,ua);return{name:OS_MAP.PlayStation4,version:version}}}];var platformParsersList=[{test:[/googlebot/i],describe(){return{type:"bot",vendor:"Google"}}},{test:[/huawei/i],describe(ua){const model=Utils.getFirstMatch(/(can-l01)/i,ua)&&"Nova";const platform={type:PLATFORMS_MAP.mobile,vendor:"Huawei"};if(model){platform.model=model}return platform}},{test:[/nexus\s*(?:7|8|9|10).*/i],describe(){return{type:PLATFORMS_MAP.tablet,vendor:"Nexus"}}},{test:[/ipad/i],describe(){return{type:PLATFORMS_MAP.tablet,vendor:"Apple",model:"iPad"}}},{test:[/Macintosh(.*?) FxiOS(.*?)\//],describe(){return{type:PLATFORMS_MAP.tablet,vendor:"Apple",model:"iPad"}}},{test:[/kftt build/i],describe(){return{type:PLATFORMS_MAP.tablet,vendor:"Amazon",model:"Kindle Fire HD 7"}}},{test:[/silk/i],describe(){return{type:PLATFORMS_MAP.tablet,vendor:"Amazon"}}},{test:[/tablet(?! pc)/i],describe(){return{type:PLATFORMS_MAP.tablet}}},{test(parser){const iDevice=parser.test(/ipod|iphone/i);const likeIDevice=parser.test(/like (ipod|iphone)/i);return iDevice&&!likeIDevice},describe(ua){const model=Utils.getFirstMatch(/(ipod|iphone)/i,ua);return{type:PLATFORMS_MAP.mobile,vendor:"Apple",model:model}}},{test:[/nexus\s*[0-6].*/i,/galaxy nexus/i],describe(){return{type:PLATFORMS_MAP.mobile,vendor:"Nexus"}}},{test:[/[^-]mobi/i],describe(){return{type:PLATFORMS_MAP.mobile}}},{test(parser){return parser.getBrowserName(true)==="blackberry"},describe(){return{type:PLATFORMS_MAP.mobile,vendor:"BlackBerry"}}},{test(parser){return parser.getBrowserName(true)==="bada"},describe(){return{type:PLATFORMS_MAP.mobile}}},{test(parser){return parser.getBrowserName()==="windows phone"},describe(){return{type:PLATFORMS_MAP.mobile,vendor:"Microsoft"}}},{test(parser){const osMajorVersion=Number(String(parser.getOSVersion()).split(".")[0]);return parser.getOSName(true)==="android"&&osMajorVersion>=3},describe(){return{type:PLATFORMS_MAP.tablet}}},{test(parser){return parser.getOSName(true)==="android"},describe(){return{type:PLATFORMS_MAP.mobile}}},{test(parser){return parser.getOSName(true)==="macos"},describe(){return{type:PLATFORMS_MAP.desktop,vendor:"Apple"}}},{test(parser){return parser.getOSName(true)==="windows"},describe(){return{type:PLATFORMS_MAP.desktop}}},{test(parser){return parser.getOSName(true)==="linux"},describe(){return{type:PLATFORMS_MAP.desktop}}},{test(parser){return parser.getOSName(true)==="playstation 4"},describe(){return{type:PLATFORMS_MAP.tv}}},{test(parser){return parser.getOSName(true)==="roku"},describe(){return{type:PLATFORMS_MAP.tv}}}];var enginesParsersList=[{test(parser){return parser.getBrowserName(true)==="microsoft edge"},describe(ua){const isBlinkBased=/\sedg\//i.test(ua);if(isBlinkBased){return{name:ENGINE_MAP.Blink}}const version=Utils.getFirstMatch(/edge\/(\d+(\.?_?\d+)+)/i,ua);return{name:ENGINE_MAP.EdgeHTML,version:version}}},{test:[/trident/i],describe(ua){const engine={name:ENGINE_MAP.Trident};const version=Utils.getFirstMatch(/trident\/(\d+(\.?_?\d+)+)/i,ua);if(version){engine.version=version}return engine}},{test(parser){return parser.test(/presto/i)},describe(ua){const engine={name:ENGINE_MAP.Presto};const version=Utils.getFirstMatch(/presto\/(\d+(\.?_?\d+)+)/i,ua);if(version){engine.version=version}return engine}},{test(parser){const isGecko=parser.test(/gecko/i);const likeGecko=parser.test(/like gecko/i);return isGecko&&!likeGecko},describe(ua){const engine={name:ENGINE_MAP.Gecko};const version=Utils.getFirstMatch(/gecko\/(\d+(\.?_?\d+)+)/i,ua);if(version){engine.version=version}return engine}},{test:[/(apple)?webkit\/537\.36/i],describe(){return{name:ENGINE_MAP.Blink}}},{test:[/(apple)?webkit/i],describe(ua){const engine={name:ENGINE_MAP.WebKit};const version=Utils.getFirstMatch(/webkit\/(\d+(\.?_?\d+)+)/i,ua);if(version){engine.version=version}return engine}}];class Parser{constructor(UA,skipParsing=false){if(UA===void 0||UA===null||UA===""){throw new Error("UserAgent parameter can't be empty")}this._ua=UA;this.parsedResult={};if(skipParsing!==true){this.parse()}}getUA(){return this._ua}test(regex){return regex.test(this._ua)}parseBrowser(){this.parsedResult.browser={};const browserDescriptor=Utils.find(browsersList,_browser=>{if(typeof _browser.test==="function"){return _browser.test(this)}if(_browser.test instanceof Array){return _browser.test.some(condition=>this.test(condition))}throw new Error("Browser's test function is not valid")});if(browserDescriptor){this.parsedResult.browser=browserDescriptor.describe(this.getUA())}return this.parsedResult.browser}getBrowser(){if(this.parsedResult.browser){return this.parsedResult.browser}return this.parseBrowser()}getBrowserName(toLowerCase){if(toLowerCase){return String(this.getBrowser().name).toLowerCase()||""}return this.getBrowser().name||""}getBrowserVersion(){return this.getBrowser().version}getOS(){if(this.parsedResult.os){return this.parsedResult.os}return this.parseOS()}parseOS(){this.parsedResult.os={};const os=Utils.find(osParsersList,_os=>{if(typeof _os.test==="function"){return _os.test(this)}if(_os.test instanceof Array){return _os.test.some(condition=>this.test(condition))}throw new Error("Browser's test function is not valid")});if(os){this.parsedResult.os=os.describe(this.getUA())}return this.parsedResult.os}getOSName(toLowerCase){const{name:name}=this.getOS();if(toLowerCase){return String(name).toLowerCase()||""}return name||""}getOSVersion(){return this.getOS().version}getPlatform(){if(this.parsedResult.platform){return this.parsedResult.platform}return this.parsePlatform()}getPlatformType(toLowerCase=false){const{type:type}=this.getPlatform();if(toLowerCase){return String(type).toLowerCase()||""}return type||""}parsePlatform(){this.parsedResult.platform={};const platform=Utils.find(platformParsersList,_platform=>{if(typeof _platform.test==="function"){return _platform.test(this)}if(_platform.test instanceof Array){return _platform.test.some(condition=>this.test(condition))}throw new Error("Browser's test function is not valid")});if(platform){this.parsedResult.platform=platform.describe(this.getUA())}return this.parsedResult.platform}getEngine(){if(this.parsedResult.engine){return this.parsedResult.engine}return this.parseEngine()}getEngineName(toLowerCase){if(toLowerCase){return String(this.getEngine().name).toLowerCase()||""}return this.getEngine().name||""}parseEngine(){this.parsedResult.engine={};const engine=Utils.find(enginesParsersList,_engine=>{if(typeof _engine.test==="function"){return _engine.test(this)}if(_engine.test instanceof Array){return _engine.test.some(condition=>this.test(condition))}throw new Error("Browser's test function is not valid")});if(engine){this.parsedResult.engine=engine.describe(this.getUA())}return this.parsedResult.engine}parse(){this.parseBrowser();this.parseOS();this.parsePlatform();this.parseEngine();return this}getResult(){return Utils.assign({},this.parsedResult)}satisfies(checkTree){const platformsAndOSes={};let platformsAndOSCounter=0;const browsers={};let browsersCounter=0;const allDefinitions=Object.keys(checkTree);allDefinitions.forEach(key=>{const currentDefinition=checkTree[key];if(typeof currentDefinition==="string"){browsers[key]=currentDefinition;browsersCounter+=1}else if(typeof currentDefinition==="object"){platformsAndOSes[key]=currentDefinition;platformsAndOSCounter+=1}});if(platformsAndOSCounter>0){const platformsAndOSNames=Object.keys(platformsAndOSes);const OSMatchingDefinition=Utils.find(platformsAndOSNames,name=>this.isOS(name));if(OSMatchingDefinition){const osResult=this.satisfies(platformsAndOSes[OSMatchingDefinition]);if(osResult!==void 0){return osResult}}const platformMatchingDefinition=Utils.find(platformsAndOSNames,name=>this.isPlatform(name));if(platformMatchingDefinition){const platformResult=this.satisfies(platformsAndOSes[platformMatchingDefinition]);if(platformResult!==void 0){return platformResult}}}if(browsersCounter>0){const browserNames=Object.keys(browsers);const matchingDefinition=Utils.find(browserNames,name=>this.isBrowser(name,true));if(matchingDefinition!==void 0){return this.compareVersion(browsers[matchingDefinition])}}return undefined}isBrowser(browserName,includingAlias=false){const defaultBrowserName=this.getBrowserName().toLowerCase();let browserNameLower=browserName.toLowerCase();const alias=Utils.getBrowserTypeByAlias(browserNameLower);if(includingAlias&&alias){browserNameLower=alias.toLowerCase()}return browserNameLower===defaultBrowserName}compareVersion(version){let expectedResults=[0];let comparableVersion=version;let isLoose=false;const currentBrowserVersion=this.getBrowserVersion();if(typeof currentBrowserVersion!=="string"){return void 0}if(version[0]===">"||version[0]==="<"){comparableVersion=version.substr(1);if(version[1]==="="){isLoose=true;comparableVersion=version.substr(2)}else{expectedResults=[]}if(version[0]===">"){expectedResults.push(1)}else{expectedResults.push(-1)}}else if(version[0]==="="){comparableVersion=version.substr(1)}else if(version[0]==="~"){isLoose=true;comparableVersion=version.substr(1)}return expectedResults.indexOf(Utils.compareVersions(currentBrowserVersion,comparableVersion,isLoose))>-1}isOS(osName){return this.getOSName(true)===String(osName).toLowerCase()}isPlatform(platformType){return this.getPlatformType(true)===String(platformType).toLowerCase()}isEngine(engineName){return this.getEngineName(true)===String(engineName).toLowerCase()}is(anything,includingAlias=false){return this.isBrowser(anything,includingAlias)||this.isOS(anything)||this.isPlatform(anything)}some(anythings=[]){return anythings.some(anything=>this.is(anything))}}class Bowser{static getParser(UA,skipParsing=false){if(typeof UA!=="string"){throw new Error("UserAgent should be a string")}return new Parser(UA,skipParsing)}static parse(UA){return new Parser(UA).getResult()}static get BROWSER_MAP(){return BROWSER_MAP}static get ENGINE_MAP(){return ENGINE_MAP}static get OS_MAP(){return OS_MAP}static get PLATFORMS_MAP(){return PLATFORMS_MAP}}function _classCallCheck(a,n){if(!(a instanceof n))throw new TypeError("Cannot call a class as a function")}function _defineProperties(e,r){for(var t=0;t=this._data.length){return undefined}var res=this._data.slice(this._pos,this._pos+bytes);this._pos+=bytes;return res}},{key:"set",value:function set(pos,data){this._pos=pos;this._data=data}},{key:"clear",value:function clear(){this._pos=0;this._data=new Uint8Array}}])}();var PvFileIDB=function(_PvFile){function PvFileIDB(path,meta,db,mode){var _this;_classCallCheck(this,PvFileIDB);_this=_callSuper$1(this,PvFileIDB);_this._pageSize=512*1024;_this._pagePtr=0;_this._pageOffset=0;_this._path=path;_this._meta=meta;_this._db=db;_this._mode=mode;_this._cache=new PvCache;return _this}_inherits(PvFileIDB,_PvFile);return _createClass(PvFileIDB,[{key:"pageSize",get:function get(){return this._pageSize}},{key:"close",value:function(){var _close=_asyncToGenerator(_regeneratorRuntime.mark(function _callee(){return _regeneratorRuntime.wrap(function _callee$(_context){while(1)switch(_context.prev=_context.next){case 0:this._db.close();case 1:case"end":return _context.stop()}},_callee,this)}));function close(){return _close.apply(this,arguments)}return close}()},{key:"read",value:function(){var _read=_asyncToGenerator(_regeneratorRuntime.mark(function _callee2(size,count){var _this2=this;return _regeneratorRuntime.wrap(function _callee2$(_context2){while(1)switch(_context2.prev=_context2.next){case 0:return _context2.abrupt("return",new Promise(function(resolve,reject){if(!_this2.exists()){reject(new Error("'".concat(_this2._path,"' doesn't exist.")));return}if(_this2._isEOF){var err=new Error("EOF");err.name="EndOfFile";reject(err);return}var copied=0;var maxToCopy=Math.min(size*count,_this2._meta.size);var totalElems=maxToCopy-maxToCopy%size;var buffer=new Uint8Array(totalElems);var res=_this2._cache.get(totalElems);if(res){copied+=res.length;_this2._pageOffset+=res.length;if(_this2._pageOffset===_this2._pageSize){_this2._pagePtr+=1;_this2._pageOffset=0}if(totalElems===copied){resolve(res);return}buffer.set(res)}var keyRange=IDBKeyRange.bound("".concat(_this2._path,"-").concat(PvFileIDB.createPage(_this2._pagePtr)),"".concat(_this2._path,"-").concat(PvFileIDB.createPage(_this2._pagePtr+Math.floor(totalElems/_this2._pageSize)+1)));var store=_this2._store;var req=store.openCursor(keyRange);req.onsuccess=function(){var cursor=req.result;if(!cursor||_this2._isEOF){return}var toCopy=Math.min(totalElems-copied,cursor.value.length-_this2._pageOffset);buffer.set(cursor.value.slice(_this2._pageOffset,_this2._pageOffset+toCopy),copied);copied+=toCopy;_this2._pageOffset+=toCopy;if(_this2._pageOffset===_this2._pageSize){_this2._pagePtr+=1;_this2._pageOffset=0}if(copied1&&_args4[1]!==undefined?_args4[1]:1;return _context4.abrupt("return",new Promise(function(){var _ref=_asyncToGenerator(_regeneratorRuntime.mark(function _callee3(resolve,reject){var _store$transaction3;var store,getCurrentPage,last,newContent,newSize,newMeta,pages,i,keyRange,_store$transaction4;return _regeneratorRuntime.wrap(function _callee3$(_context3){while(1)switch(_context3.prev=_context3.next){case 0:if(!(_this3._mode==="readonly")){_context3.next=3;break}reject(new Error("Instance is readonly mode only."));return _context3.abrupt("return");case 3:if(!(typeof version!=="number"&&version<=0)){_context3.next=6;break}reject(new Error("Version should be a positive number"));return _context3.abrupt("return");case 6:store=_this3._store;getCurrentPage=function getCurrentPage(){return new Promise(function(res){var req=store.get("".concat(_this3._path,"-").concat(PvFileIDB.createPage(_this3._pagePtr)));req.onsuccess=function(){if(req.result!==undefined){res(req.result.slice(0,_this3._pageOffset))}else{res(new Uint8Array(0))}}})};_context3.next=10;return getCurrentPage();case 10:last=_context3.sent;newContent=new Uint8Array(last.length+content.length);newContent.set(last);newContent.set(content,last.length);newSize=_this3._pagePtr*_this3._pageSize+newContent.length;newMeta={size:newSize,numPages:Math.ceil(newSize/_this3._pageSize),version:version,pageSize:_this3._pageSize};store.put(newMeta,_this3._path);pages=Math.ceil(newContent.length/_this3._pageSize);for(i=0;i=this._meta.numPages-1&&this._pageOffset>=this._meta.size%this._pageSize}},{key:"_store",get:function get(){return this._db.transaction(PV_FILE_STORE,this._mode).objectStore(PV_FILE_STORE)}}],[{key:"open",value:function open(path,mode){if(!self.indexedDB){var error=new Error("IndexedDB is not supported");error.name="IndexedDBNotSupported";throw error}return new Promise(function(){var _ref3=_asyncToGenerator(_regeneratorRuntime.mark(function _callee7(resolve,reject){var db,req,_error2;return _regeneratorRuntime.wrap(function _callee7$(_context7){while(1)switch(_context7.prev=_context7.next){case 0:_context7.prev=0;_context7.next=3;return getDB();case 3:db=_context7.sent;req=db.transaction(PV_FILE_STORE,"readwrite").objectStore(PV_FILE_STORE).get(path);req.onerror=function(){reject(req.error)};req.onsuccess=function(){var meta=req.result;var dbMode=mode.includes("r")?"readonly":"readwrite";if(meta===undefined&&dbMode==="readonly"){var _error=new Error("'".concat(path,"' doesn't exist."));_error.name="FileNotExists";reject(_error);return}var fileIDB=new PvFileIDB(path,meta,db,dbMode);if(mode.includes("a")){fileIDB.seek(0,2)}resolve(fileIDB)};_context7.next=12;break;case 9:_context7.prev=9;_context7.t0=_context7["catch"](0);if(_context7.t0.name==="InvalidStateError"){_error2=new Error("IndexedDB is not supported");_error2.name="IndexedDBNotSupported";reject(_error2)}else{reject(_context7.t0)}case 12:case"end":return _context7.stop()}},_callee7,null,[[0,9]])}));return function(_x8,_x9){return _ref3.apply(this,arguments)}}())}},{key:"createPage",value:function createPage(page){return("00000"+page).slice(-6)}}])}(PvFile);function _callSuper(t,o,e){return o=_getPrototypeOf(o),_possibleConstructorReturn(t,_isNativeReflectConstruct()?Reflect.construct(o,e||[],_getPrototypeOf(t).constructor):o.apply(t,e))}function _isNativeReflectConstruct(){try{var t=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch(t){}return(_isNativeReflectConstruct=function _isNativeReflectConstruct(){return!!t})()}var PvFileMem=function(_PvFile){function PvFileMem(path,meta,db,mode){var _this;_classCallCheck(this,PvFileMem);_this=_callSuper(this,PvFileMem);_this._pos=0;_this._path=path;_this._meta=meta;_this._mode=mode;return _this}_inherits(PvFileMem,_PvFile);return _createClass(PvFileMem,[{key:"close",value:function close(){return}},{key:"read",value:function read(size,count){if(!this.exists()){throw new Error("'".concat(this._path,"' doesn't exist."))}if(this._isEOF){var err=new Error("EOF");err.name="EndOfFile";throw err}var toCopy=Math.min(size*count,this._file.length-this._pos);var totalElems=toCopy-toCopy%size;var buffer=new Uint8Array(totalElems);buffer.set(this._file.slice(this._pos,this._pos+totalElems),0);this._pos+=totalElems;return buffer}},{key:"write",value:function write(content){var version=arguments.length>1&&arguments[1]!==undefined?arguments[1]:1;var newFile=new Uint8Array(this._pos+content.length);if(this._file!==undefined){newFile.set(this._file.slice(0,this._pos));newFile.set(content,this._pos)}else{newFile.set(content)}this._file=newFile;this._pos+=content.length}},{key:"seek",value:function seek(offset,whence){if(!this.exists()&&this._mode==="readonly"){throw new Error("'".concat(this._path,"' doesn't exist."))}if(!this.exists()){throw new Error("'".concat(this._path,"' doesn't exist."))}if(offset<0){var err=new Error("EOF");err.name="EndOfFile";throw err}var newOffset;if(whence===0){newOffset=Math.min(offset,this._file.length)}else if(whence===1){newOffset=Math.min(this._pos+offset,this._file.length)}else if(whence===2){newOffset=Math.min(this._file.length+offset,this._file.length)}else{throw new Error("Invalid operation: ".concat(whence,"."))}this._pos=newOffset}},{key:"tell",value:function tell(){if(!this.exists()){return-1}return this._pos}},{key:"remove",value:function(){var _remove=_asyncToGenerator(_regeneratorRuntime.mark(function _callee(){return _regeneratorRuntime.wrap(function _callee$(_context){while(1)switch(_context.prev=_context.next){case 0:if(this.exists()){_context.next=2;break}throw new Error("ENOENT");case 2:PvFileMem._memFiles["delete"](this._path);this._pos=0;case 4:case"end":return _context.stop()}},_callee,this)}));function remove(){return _remove.apply(this,arguments)}return remove}()},{key:"exists",value:function exists(){return this._file!==undefined}},{key:"_isEOF",get:function get(){return this._pos>=this._file.length}},{key:"_file",get:function get(){return PvFileMem._memFiles.get(this._path)},set:function set(content){PvFileMem._memFiles.set(this._path,content)}}],[{key:"open",value:function open(path,mode){var file=PvFileMem._memFiles.get(path);var dbMode=mode.includes("r")?"readonly":"readwrite";if(file===undefined&&dbMode==="readonly"){var error=new Error("'".concat(path,"' doesn't exist."));error.name="FileNotExists";throw error}var fileMem=new PvFileMem(path,undefined,undefined,dbMode);if(mode.includes("a")){fileMem.seek(0,2)}return fileMem}}])}(PvFile);PvFileMem._memFiles=new Map;function ownKeys(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);r&&(o=o.filter(function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable})),t.push.apply(t,o)}return t}function _objectSpread(e){for(var r=1;r=r.length?{done:!0}:{done:!1,value:r[_n++]}},e:function e(r){throw r},f:F}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,a=!0,u=!1;return{s:function s(){t=t.call(r)},n:function n(){var r=t.next();return a=r.done,r},e:function e(r){u=!0,o=r},f:function f(){try{a||null==t["return"]||t["return"]()}finally{if(u)throw o}}}}function _unsupportedIterableToArray(r,a){if(r){if("string"==typeof r)return _arrayLikeToArray(r,a);var t={}.toString.call(r).slice(8,-1);return"Object"===t&&r.constructor&&(t=r.constructor.name),"Map"===t||"Set"===t?Array.from(r):"Arguments"===t||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t)?_arrayLikeToArray(r,a):void 0}}function _arrayLikeToArray(r,a){(null==a||a>r.length)&&(a=r.length);for(var e=0,n=Array(a);e>>0}return address}function arrayBufferToStringAtIndex(arrayBuffer,indexStart){var indexEnd=indexStart;while(arrayBuffer[indexEnd]!==0){indexEnd++}var utf8decoder=new TextDecoder("utf-8");var tempBuffer=new Uint8Array(arrayBuffer.slice(indexStart,indexEnd));return utf8decoder.decode(tempBuffer)}function stringHeaderToObject(stringHeader){var objectHeader={};var _iterator=_createForOfIteratorHelper(stringHeader.split("\r\n")),_step;try{for(_iterator.s();!(_step=_iterator.n()).done;){var property=_step.value;var keyValuePair=property.split(": ");if(keyValuePair[0]!==""){objectHeader[keyValuePair[0]]=keyValuePair[1]}}}catch(err){_iterator.e(err)}finally{_iterator.f()}return objectHeader}function fetchWithTimeout(_x){return _fetchWithTimeout.apply(this,arguments)}function _fetchWithTimeout(){_fetchWithTimeout=_asyncToGenerator(_regeneratorRuntime.mark(function _callee(uri){var options,time,controller,config,timeout,response,_args=arguments;return _regeneratorRuntime.wrap(function _callee$(_context){while(1)switch(_context.prev=_context.next){case 0:options=_args.length>1&&_args[1]!==undefined?_args[1]:{};time=_args.length>2&&_args[2]!==undefined?_args[2]:5e3;controller=new AbortController;config=_objectSpread(_objectSpread({},options),{},{signal:controller.signal});timeout=setTimeout(function(){controller.abort()},time);_context.next=7;return fetch(uri,config);case 7:response=_context.sent;clearTimeout(timeout);return _context.abrupt("return",response);case 10:case"end":return _context.stop()}},_callee)}));return _fetchWithTimeout.apply(this,arguments)}function open(_x2,_x3){return _open.apply(this,arguments)}function _open(){_open=_asyncToGenerator(_regeneratorRuntime.mark(function _callee2(path,mode){var error;return _regeneratorRuntime.wrap(function _callee2$(_context2){while(1)switch(_context2.prev=_context2.next){case 0:_context2.prev=0;_context2.next=3;return PvFileIDB.open(path,mode);case 3:return _context2.abrupt("return",_context2.sent);case 6:_context2.prev=6;_context2.t0=_context2["catch"](0);if(_context2.t0.name==="IndexedDBNotSupported"){console.warn("IndexedDB is not supported. Fallback to in-memory storage.")}else if(_context2.t0.name!=="FileNotExists"){console.warn("Unable to access IndexedDB (".concat(_context2.t0.toString(),"). Fallback to in-memory storage."))}if(!(typeof WorkerGlobalScope!=="undefined"&&self instanceof WorkerGlobalScope)){_context2.next=16;break}if(!(_context2.t0.name==="FileNotExists")){_context2.next=12;break}throw _context2.t0;case 12:console.error("In-memory storage cannot be used inside a worker.");error=new Error("Failed to start PvFile: ".concat(_context2.t0.toString()));error.name="PvFileNotSupported";throw error;case 16:return _context2.abrupt("return",PvFileMem.open(path,mode));case 17:case"end":return _context2.stop()}},_callee2,null,[[0,6]])}));return _open.apply(this,arguments)}var moduleOverrides=Object.assign({},Module);var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var readAsync,readBinary;if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(typeof document!="undefined"&&document.currentScript){scriptDirectory=document.currentScript.src}if(_scriptName){scriptDirectory=_scriptName}if(scriptDirectory.startsWith("blob:")){scriptDirectory=""}else{scriptDirectory=scriptDirectory.substr(0,scriptDirectory.replace(/[?#].*/,"").lastIndexOf("/")+1)}{if(ENVIRONMENT_IS_WORKER){readBinary=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=url=>{if(isFileURI(url)){return new Promise((reject,resolve)=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=()=>{if(xhr.status==200||xhr.status==0&&xhr.response){resolve(xhr.response)}reject(xhr.status)};xhr.onerror=reject;xhr.send(null)})}return fetch(url,{credentials:"same-origin"}).then(response=>{if(response.ok){return response.arrayBuffer()}return Promise.reject(new Error(response.status+" : "+response.url))})}}}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.error.bind(console);Object.assign(Module,moduleOverrides);moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var wasmMemory;var ABORT=false;var EXITSTATUS;var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAP64,HEAPU64,HEAPF64;function updateMemoryViews(){var b=wasmMemory.buffer;Module["HEAP8"]=HEAP8=new Int8Array(b);Module["HEAP16"]=HEAP16=new Int16Array(b);Module["HEAPU8"]=HEAPU8=new Uint8Array(b);Module["HEAPU16"]=HEAPU16=new Uint16Array(b);Module["HEAP32"]=HEAP32=new Int32Array(b);Module["HEAPU32"]=HEAPU32=new Uint32Array(b);Module["HEAPF32"]=HEAPF32=new Float32Array(b);Module["HEAPF64"]=HEAPF64=new Float64Array(b);Module["HEAP64"]=HEAP64=new BigInt64Array(b);Module["HEAPU64"]=HEAPU64=new BigUint64Array(b)}var __ATPRERUN__=[];var __ATINIT__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__)}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnInit(cb){__ATINIT__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;Module["monitorRunDependencies"]?.(runDependencies)}function removeRunDependency(id){runDependencies--;Module["monitorRunDependencies"]?.(runDependencies);if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}function abort(what){Module["onAbort"]?.(what);what="Aborted("+what+")";err(what);ABORT=true;EXITSTATUS=1;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);readyPromiseReject(e);throw e}var dataURIPrefix="data:application/octet-stream;base64,";var isDataURI=filename=>filename.startsWith(dataURIPrefix);var isFileURI=filename=>filename.startsWith("file://");function findWasmBinary(){var f="pv_eagle_simd.wasm";if(!isDataURI(f)){return locateFile(f)}return f}var wasmBinaryFile;function getBinarySync(file){if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}function getBinaryPromise(binaryFile){if(!wasmBinary){return readAsync(binaryFile).then(response=>new Uint8Array(response),()=>getBinarySync(binaryFile))}return Promise.resolve().then(()=>getBinarySync(binaryFile))}function instantiateArrayBuffer(binaryFile,imports,receiver){return getBinaryPromise(binaryFile).then(binary=>WebAssembly.instantiate(binary,imports)).then(receiver,reason=>{err(`failed to asynchronously prepare wasm: ${reason}`);abort(reason)})}function instantiateAsync(binary,binaryFile,imports,callback){if(!binary&&typeof WebAssembly.instantiateStreaming=="function"&&!isDataURI(binaryFile)&&!isFileURI(binaryFile)&&typeof fetch=="function"){return fetch(binaryFile,{credentials:"same-origin"}).then(response=>{var result=WebAssembly.instantiateStreaming(response,imports);return result.then(callback,function(reason){err(`wasm streaming compile failed: ${reason}`);err("falling back to ArrayBuffer instantiation");return instantiateArrayBuffer(binaryFile,imports,callback)})})}return instantiateArrayBuffer(binaryFile,imports,callback)}function getWasmImports(){return{a:wasmImports}}function createWasm(){var info=getWasmImports();function receiveInstance(instance,module){wasmExports=instance.exports;wasmExports=Asyncify.instrumentWasmExports(wasmExports);wasmMemory=wasmExports["i"];updateMemoryViews();wasmTable=wasmExports["C"];addOnInit(wasmExports["j"]);removeRunDependency("wasm-instantiate");return wasmExports}addRunDependency("wasm-instantiate");function receiveInstantiationResult(result){receiveInstance(result["instance"])}if(Module["instantiateWasm"]){try{return Module["instantiateWasm"](info,receiveInstance)}catch(e){err(`Module.instantiateWasm callback failed with error: ${e}`);readyPromiseReject(e)}}if(!wasmBinaryFile)wasmBinaryFile=findWasmBinary();instantiateAsync(wasmBinary,wasmBinaryFile,info,receiveInstantiationResult).catch(readyPromiseReject);return{}}function ExitStatus(status){this.name="ExitStatus";this.message=`Program terminated with exit(${status})`;this.status=status}var callRuntimeCallbacks=callbacks=>{while(callbacks.length>0){callbacks.shift()(Module)}};var noExitRuntime=Module["noExitRuntime"]||true;var stackRestore=val=>__emscripten_stack_restore(val);var stackSave=()=>_emscripten_stack_get_current();var getHeapMax=()=>2147483648;var growMemory=size=>{var b=wasmMemory.buffer;var pages=(size-b.byteLength+65535)/65536;try{wasmMemory.grow(pages);updateMemoryViews();return 1}catch(e){}};var _emscripten_resize_heap=requestedSize=>{var oldSize=HEAPU8.length;requestedSize>>>=0;var maxHeapSize=getHeapMax();if(requestedSize>maxHeapSize){return false}var alignUp=(x,multiple)=>x+(multiple-x%multiple)%multiple;for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignUp(Math.max(requestedSize,overGrownHeapSize),65536));var replacement=growMemory(newSize);if(replacement){return true}}return false};function _pv_console_log_wasm(index){console.log(arrayBufferToStringAtIndex(Module.HEAPU8,index))}var _pv_file_close_wasm=async function(fileAddress,statusAddress){statusAddress=unsignedAddress(statusAddress);return Asyncify.handleAsync(async()=>{try{const file=await PvFile.getPtr(fileAddress);await file.close();setInt(statusAddress,0)}catch(e){console.error("pvFileCloseWasm",e);setInt(statusAddress,-1)}})};_pv_file_close_wasm.isAsync=true;var _pv_file_open_wasm=async function(fileAddress,pathAddress,modeAddress,statusAddress){pathAddress=unsignedAddress(pathAddress);modeAddress=unsignedAddress(modeAddress);statusAddress=unsignedAddress(statusAddress);return Asyncify.handleAsync(async()=>{const path=arrayBufferToStringAtIndex(Module.HEAPU8,pathAddress);const mode=arrayBufferToStringAtIndex(Module.HEAPU8,modeAddress);try{const file=await open(path,mode);PvFile.setPtr(fileAddress,file);setInt(statusAddress,0)}catch(e){if(e.name!=="FileNotExists"){console.error("pvFileOpenWasm",e)}setInt(statusAddress,-1)}})};_pv_file_open_wasm.isAsync=true;var _pv_file_read_wasm=async function(fileAddress,contentAddress,size,count,numReadAddress){contentAddress=unsignedAddress(contentAddress);numReadAddress=unsignedAddress(numReadAddress);return Asyncify.handleAsync(async()=>{try{const file=PvFile.getPtr(fileAddress);const content=await file.read(size,count);Module.HEAPU8.set(content,contentAddress);setInt(numReadAddress,content.length/size)}catch(e){console.error("pvFileReadWasm",e);setInt(numReadAddress,-1)}})};_pv_file_read_wasm.isAsync=true;var _pv_https_request_wasm=async function(httpMethodAddress,serverNameAddress,endpointAddress,headerAddress,bodyAddress,timeoutMs,responseAddressAddress,responseSizeAddress,responseCodeAddress){httpMethodAddress=unsignedAddress(httpMethodAddress);serverNameAddress=unsignedAddress(serverNameAddress);endpointAddress=unsignedAddress(endpointAddress);headerAddress=unsignedAddress(headerAddress);bodyAddress=unsignedAddress(bodyAddress);responseAddressAddress=unsignedAddress(responseAddressAddress);responseSizeAddress=unsignedAddress(responseSizeAddress);responseCodeAddress=unsignedAddress(responseCodeAddress);return Asyncify.handleAsync(async()=>{const httpMethod=arrayBufferToStringAtIndex(Module.HEAPU8,httpMethodAddress);const serverName=arrayBufferToStringAtIndex(Module.HEAPU8,serverNameAddress);const endpoint=arrayBufferToStringAtIndex(Module.HEAPU8,endpointAddress);const header=arrayBufferToStringAtIndex(Module.HEAPU8,headerAddress);const body=arrayBufferToStringAtIndex(Module.HEAPU8,bodyAddress);const headerObject=stringHeaderToObject(header);const options={method:httpMethod};if(body.length>0){options.body=body}if(Object.keys(headerObject).length>0){options.headers=headerObject}let response;let responseText;let statusCode;try{response=await fetchWithTimeout("https://"+serverName+endpoint,options,timeoutMs);statusCode=response.status}catch(error){console.error("pvHttpsRequestWasm",`Failed to fetch: ${error}`);return}try{responseText=await response.text()}catch(error){console.error("pvHttpsRequestWasm",`Failed to get response text: ${error}`);return}const responseAddress=Module._malloc((responseText.length+1)*Int8Array.BYTES_PER_ELEMENT);if(responseAddress===0){console.error("pvMallocError","pvHttpsRequestWasm: cannot allocate memory for response");setInt(responseAddressAddress,0);return}setInt(responseSizeAddress,responseText.length+1);setInt(responseAddressAddress,responseAddress);for(let i=0;i{try{return func()}catch(e){abort(e)}};var handleException=e=>{if(e instanceof ExitStatus||e=="unwind"){return EXITSTATUS}quit_(1,e)};var runtimeKeepaliveCounter=0;var keepRuntimeAlive=()=>noExitRuntime||runtimeKeepaliveCounter>0;var _proc_exit=code=>{EXITSTATUS=code;if(!keepRuntimeAlive()){Module["onExit"]?.(code);ABORT=true}quit_(code,new ExitStatus(code))};var exitJS=(status,implicit)=>{EXITSTATUS=status;_proc_exit(status)};var _exit=exitJS;var maybeExit=()=>{if(!keepRuntimeAlive()){try{_exit(EXITSTATUS)}catch(e){handleException(e)}}};var callUserCallback=func=>{if(ABORT){return}try{func();maybeExit()}catch(e){handleException(e)}};var sigToWasmTypes=sig=>{var typeNames={i:"i32",j:"i64",f:"f32",d:"f64",e:"externref",p:"i32"};var type={parameters:[],results:sig[0]=="v"?[]:[typeNames[sig[0]]]};for(var i=1;i{runtimeKeepaliveCounter+=1};var runtimeKeepalivePop=()=>{runtimeKeepaliveCounter-=1};var Asyncify={instrumentWasmImports(imports){var importPattern=/^(pv_https_request_wasm|pv_file_open_wasm|pv_file_close_wasm|pv_file_read_wasm|pv_file_write_wasm|pv_file_remove_wasm|pv_sleep_wasm|invoke_.*|__asyncjs__.*)$/;for(let[x,original]of Object.entries(imports)){if(typeof original=="function"){let isAsyncifyImport=original.isAsync||importPattern.test(x)}}},instrumentWasmExports(exports){var ret={};for(let[x,original]of Object.entries(exports)){if(typeof original=="function"){ret[x]=(...args)=>{Asyncify.exportCallStack.push(x);try{return original(...args)}finally{if(!ABORT){var y=Asyncify.exportCallStack.pop();Asyncify.maybeStopUnwind()}}}}else{ret[x]=original}}return ret},State:{Normal:0,Unwinding:1,Rewinding:2,Disabled:3},state:0,StackSize:4096,currData:null,handleSleepReturnValue:0,exportCallStack:[],callStackNameToId:{},callStackIdToName:{},callStackId:0,asyncPromiseHandlers:null,sleepCallbacks:[],getCallStackId(funcName){var id=Asyncify.callStackNameToId[funcName];if(id===undefined){id=Asyncify.callStackId++;Asyncify.callStackNameToId[funcName]=id;Asyncify.callStackIdToName[id]=funcName}return id},maybeStopUnwind(){if(Asyncify.currData&&Asyncify.state===Asyncify.State.Unwinding&&Asyncify.exportCallStack.length===0){Asyncify.state=Asyncify.State.Normal;runAndAbortIfError(_asyncify_stop_unwind);if(typeof Fibers!="undefined"){Fibers.trampoline()}}},whenDone(){return new Promise((resolve,reject)=>{Asyncify.asyncPromiseHandlers={resolve:resolve,reject:reject}})},allocateData(){var ptr=_malloc(12+Asyncify.StackSize);Asyncify.setDataHeader(ptr,ptr+12,Asyncify.StackSize);Asyncify.setDataRewindFunc(ptr);return ptr},setDataHeader(ptr,stack,stackSize){HEAPU32[ptr>>2]=stack;HEAPU32[ptr+4>>2]=stack+stackSize},setDataRewindFunc(ptr){var bottomOfCallStack=Asyncify.exportCallStack[0];var rewindId=Asyncify.getCallStackId(bottomOfCallStack);HEAP32[ptr+8>>2]=rewindId},getDataRewindFuncName(ptr){var id=HEAP32[ptr+8>>2];var name=Asyncify.callStackIdToName[id];return name},getDataRewindFunc(name){var func=wasmExports[name];return func},doRewind(ptr){var name=Asyncify.getDataRewindFuncName(ptr);var func=Asyncify.getDataRewindFunc(name);return func()},handleSleep(startAsync){if(ABORT)return;if(Asyncify.state===Asyncify.State.Normal){var reachedCallback=false;var reachedAfterCallback=false;startAsync((handleSleepReturnValue=0)=>{if(ABORT)return;Asyncify.handleSleepReturnValue=handleSleepReturnValue;reachedCallback=true;if(!reachedAfterCallback){return}Asyncify.state=Asyncify.State.Rewinding;runAndAbortIfError(()=>_asyncify_start_rewind(Asyncify.currData));if(typeof Browser!="undefined"&&Browser.mainLoop.func){Browser.mainLoop.resume()}var asyncWasmReturnValue,isError=false;try{asyncWasmReturnValue=Asyncify.doRewind(Asyncify.currData)}catch(err){asyncWasmReturnValue=err;isError=true}var handled=false;if(!Asyncify.currData){var asyncPromiseHandlers=Asyncify.asyncPromiseHandlers;if(asyncPromiseHandlers){Asyncify.asyncPromiseHandlers=null;(isError?asyncPromiseHandlers.reject:asyncPromiseHandlers.resolve)(asyncWasmReturnValue);handled=true}}if(isError&&!handled){throw asyncWasmReturnValue}});reachedAfterCallback=true;if(!reachedCallback){Asyncify.state=Asyncify.State.Unwinding;Asyncify.currData=Asyncify.allocateData();if(typeof Browser!="undefined"&&Browser.mainLoop.func){Browser.mainLoop.pause()}runAndAbortIfError(()=>_asyncify_start_unwind(Asyncify.currData))}}else if(Asyncify.state===Asyncify.State.Rewinding){Asyncify.state=Asyncify.State.Normal;runAndAbortIfError(_asyncify_stop_rewind);_free(Asyncify.currData);Asyncify.currData=null;Asyncify.sleepCallbacks.forEach(callUserCallback)}else{abort(`invalid state: ${Asyncify.state}`)}return Asyncify.handleSleepReturnValue},handleAsync(startAsync){return Asyncify.handleSleep(wakeUp=>{startAsync().then(wakeUp)})}};var uleb128Encode=(n,target)=>{if(n<128){target.push(n)}else{target.push(n%128|128,n>>7)}};var generateFuncType=(sig,target)=>{var sigRet=sig.slice(0,1);var sigParam=sig.slice(1);var typeCodes={i:127,p:127,j:126,f:125,d:124,e:111};target.push(96);uleb128Encode(sigParam.length,target);for(var i=0;i{if(typeof WebAssembly.Function=="function"){return new WebAssembly.Function(sigToWasmTypes(sig),func)}var typeSectionBody=[1];generateFuncType(sig,typeSectionBody);var bytes=[0,97,115,109,1,0,0,0,1];uleb128Encode(typeSectionBody.length,bytes);bytes.push(...typeSectionBody);bytes.push(2,7,1,1,101,1,102,0,0,7,5,1,1,102,0,0);var module=new WebAssembly.Module(new Uint8Array(bytes));var instance=new WebAssembly.Instance(module,{e:{f:func}});var wrappedFunc=instance.exports["f"];return wrappedFunc};var wasmTableMirror=[];var wasmTable;var getWasmTableEntry=funcPtr=>{var func=wasmTableMirror[funcPtr];if(!func){if(funcPtr>=wasmTableMirror.length)wasmTableMirror.length=funcPtr+1;wasmTableMirror[funcPtr]=func=wasmTable.get(funcPtr)}return func};var updateTableMap=(offset,count)=>{if(functionsInTableMap){for(var i=offset;i{if(!functionsInTableMap){functionsInTableMap=new WeakMap;updateTableMap(0,wasmTable.length)}return functionsInTableMap.get(func)||0};var freeTableIndexes=[];var getEmptyTableSlot=()=>{if(freeTableIndexes.length){return freeTableIndexes.pop()}try{wasmTable.grow(1)}catch(err){if(!(err instanceof RangeError)){throw err}throw"Unable to grow wasm table. Set ALLOW_TABLE_GROWTH."}return wasmTable.length-1};var setWasmTableEntry=(idx,func)=>{wasmTable.set(idx,func);wasmTableMirror[idx]=wasmTable.get(idx)};var addFunction=(func,sig)=>{var rtn=getFunctionAddress(func);if(rtn){return rtn}var ret=getEmptyTableSlot();try{setWasmTableEntry(ret,func)}catch(err){if(!(err instanceof TypeError)){throw err}var wrapped=convertJsFunctionToWasm(func,sig);setWasmTableEntry(ret,wrapped)}functionsInTableMap.set(func,ret);return ret};var getCFunc=ident=>{var func=Module["_"+ident];return func};var writeArrayToMemory=(array,buffer)=>{HEAP8.set(array,buffer)};var lengthBytesUTF8=str=>{var len=0;for(var i=0;i=55296&&c<=57343){len+=4;++i}else{len+=3}}return len};var stringToUTF8Array=(str,heap,outIdx,maxBytesToWrite)=>{if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}}heap[outIdx]=0;return outIdx-startIdx};var stringToUTF8=(str,outPtr,maxBytesToWrite)=>stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite);var stackAlloc=sz=>__emscripten_stack_alloc(sz);var stringToUTF8OnStack=str=>{var size=lengthBytesUTF8(str)+1;var ret=stackAlloc(size);stringToUTF8(str,ret,size);return ret};var UTF8Decoder=typeof TextDecoder!="undefined"?new TextDecoder:undefined;var UTF8ArrayToString=(heapOrArray,idx,maxBytesToRead)=>{var endIdx=idx+maxBytesToRead;var endPtr=idx;while(heapOrArray[endPtr]&&!(endPtr>=endIdx))++endPtr;if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.subarray(idx,endPtr))}var str="";while(idx>10,56320|ch&1023)}}return str};var UTF8ToString=(ptr,maxBytesToRead)=>ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):"";var ccall=(ident,returnType,argTypes,args,opts)=>{var toC={string:str=>{var ret=0;if(str!==null&&str!==undefined&&str!==0){ret=stringToUTF8OnStack(str)}return ret},array:arr=>{var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string"){return UTF8ToString(ret)}if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i{var numericArgs=!argTypes||argTypes.every(type=>type==="number"||type==="boolean");var numericRet=returnType!=="string";if(numericRet&&numericArgs&&!opts){return getCFunc(ident)}return(...args)=>ccall(ident,returnType,argTypes,args,opts)};Module["cwrap"]=cwrap;var wasmImports={e:_emscripten_resize_heap,a:_pv_console_log_wasm,c:_pv_file_close_wasm,d:_pv_file_open_wasm,b:_pv_file_read_wasm,f:_pv_https_request_wasm,h:_pv_time_wasm,g:_pv_ypu_get_max_workers_wasm};var wasmExports=createWasm();var ___wasm_call_ctors=()=>(___wasm_call_ctors=wasmExports["j"])();var _pv_eagle_init=Module["_pv_eagle_init"]=(a0,a1,a2,a3,a4)=>(_pv_eagle_init=Module["_pv_eagle_init"]=wasmExports["k"])(a0,a1,a2,a3,a4);var _free=a0=>(_free=wasmExports["l"])(a0);var _pv_eagle_delete=Module["_pv_eagle_delete"]=a0=>(_pv_eagle_delete=Module["_pv_eagle_delete"]=wasmExports["m"])(a0);var _pv_eagle_process_min_audio_length_samples=Module["_pv_eagle_process_min_audio_length_samples"]=(a0,a1)=>(_pv_eagle_process_min_audio_length_samples=Module["_pv_eagle_process_min_audio_length_samples"]=wasmExports["n"])(a0,a1);var _pv_eagle_process=Module["_pv_eagle_process"]=(a0,a1,a2,a3,a4,a5)=>(_pv_eagle_process=Module["_pv_eagle_process"]=wasmExports["o"])(a0,a1,a2,a3,a4,a5);var _pv_sample_rate=Module["_pv_sample_rate"]=()=>(_pv_sample_rate=Module["_pv_sample_rate"]=wasmExports["p"])();var _pv_eagle_scores_delete=Module["_pv_eagle_scores_delete"]=a0=>(_pv_eagle_scores_delete=Module["_pv_eagle_scores_delete"]=wasmExports["q"])(a0);var _pv_eagle_profiler_init=Module["_pv_eagle_profiler_init"]=(a0,a1,a2,a3,a4,a5)=>(_pv_eagle_profiler_init=Module["_pv_eagle_profiler_init"]=wasmExports["r"])(a0,a1,a2,a3,a4,a5);var _pv_eagle_profiler_reset=Module["_pv_eagle_profiler_reset"]=a0=>(_pv_eagle_profiler_reset=Module["_pv_eagle_profiler_reset"]=wasmExports["s"])(a0);var _pv_eagle_profiler_delete=Module["_pv_eagle_profiler_delete"]=a0=>(_pv_eagle_profiler_delete=Module["_pv_eagle_profiler_delete"]=wasmExports["t"])(a0);var _pv_eagle_profiler_enroll=Module["_pv_eagle_profiler_enroll"]=(a0,a1,a2)=>(_pv_eagle_profiler_enroll=Module["_pv_eagle_profiler_enroll"]=wasmExports["u"])(a0,a1,a2);var _pv_eagle_profiler_frame_length=Module["_pv_eagle_profiler_frame_length"]=()=>(_pv_eagle_profiler_frame_length=Module["_pv_eagle_profiler_frame_length"]=wasmExports["v"])();var _pv_eagle_profiler_flush=Module["_pv_eagle_profiler_flush"]=(a0,a1)=>(_pv_eagle_profiler_flush=Module["_pv_eagle_profiler_flush"]=wasmExports["w"])(a0,a1);var _pv_eagle_profiler_export_size=Module["_pv_eagle_profiler_export_size"]=(a0,a1)=>(_pv_eagle_profiler_export_size=Module["_pv_eagle_profiler_export_size"]=wasmExports["x"])(a0,a1);var _pv_eagle_profiler_export=Module["_pv_eagle_profiler_export"]=(a0,a1)=>(_pv_eagle_profiler_export=Module["_pv_eagle_profiler_export"]=wasmExports["y"])(a0,a1);var _pv_eagle_version=Module["_pv_eagle_version"]=()=>(_pv_eagle_version=Module["_pv_eagle_version"]=wasmExports["z"])();var _pv_eagle_list_hardware_devices=Module["_pv_eagle_list_hardware_devices"]=(a0,a1)=>(_pv_eagle_list_hardware_devices=Module["_pv_eagle_list_hardware_devices"]=wasmExports["A"])(a0,a1);var _pv_eagle_free_hardware_devices=Module["_pv_eagle_free_hardware_devices"]=(a0,a1)=>(_pv_eagle_free_hardware_devices=Module["_pv_eagle_free_hardware_devices"]=wasmExports["B"])(a0,a1);var _pv_status_to_string=Module["_pv_status_to_string"]=a0=>(_pv_status_to_string=Module["_pv_status_to_string"]=wasmExports["D"])(a0);var _malloc=Module["_malloc"]=a0=>(_malloc=Module["_malloc"]=wasmExports["E"])(a0);var _pv_log_enable=Module["_pv_log_enable"]=()=>(_pv_log_enable=Module["_pv_log_enable"]=wasmExports["F"])();var _pv_log_disable=Module["_pv_log_disable"]=()=>(_pv_log_disable=Module["_pv_log_disable"]=wasmExports["G"])();var _pv_set_home_dir=Module["_pv_set_home_dir"]=a0=>(_pv_set_home_dir=Module["_pv_set_home_dir"]=wasmExports["H"])(a0);var _aligned_alloc=Module["_aligned_alloc"]=(a0,a1)=>(_aligned_alloc=Module["_aligned_alloc"]=wasmExports["I"])(a0,a1);var _pv_get_sdk=Module["_pv_get_sdk"]=()=>(_pv_get_sdk=Module["_pv_get_sdk"]=wasmExports["J"])();var _pv_set_sdk=Module["_pv_set_sdk"]=a0=>(_pv_set_sdk=Module["_pv_set_sdk"]=wasmExports["K"])(a0);var _pv_free=Module["_pv_free"]=a0=>(_pv_free=Module["_pv_free"]=wasmExports["L"])(a0);var _pv_get_error_stack=Module["_pv_get_error_stack"]=(a0,a1)=>(_pv_get_error_stack=Module["_pv_get_error_stack"]=wasmExports["M"])(a0,a1);var _pv_free_error_stack=Module["_pv_free_error_stack"]=a0=>(_pv_free_error_stack=Module["_pv_free_error_stack"]=wasmExports["N"])(a0);var __emscripten_memcpy_bulkmem=Module["__emscripten_memcpy_bulkmem"]=(a0,a1,a2)=>(__emscripten_memcpy_bulkmem=Module["__emscripten_memcpy_bulkmem"]=wasmExports["O"])(a0,a1,a2);var __emscripten_memset_bulkmem=Module["__emscripten_memset_bulkmem"]=(a0,a1,a2)=>(__emscripten_memset_bulkmem=Module["__emscripten_memset_bulkmem"]=wasmExports["P"])(a0,a1,a2);var __emscripten_stack_restore=a0=>(__emscripten_stack_restore=wasmExports["Q"])(a0);var __emscripten_stack_alloc=a0=>(__emscripten_stack_alloc=wasmExports["R"])(a0);var _emscripten_stack_get_current=()=>(_emscripten_stack_get_current=wasmExports["S"])();var _asyncify_start_unwind=a0=>(_asyncify_start_unwind=wasmExports["T"])(a0);var _asyncify_stop_unwind=()=>(_asyncify_stop_unwind=wasmExports["U"])();var _asyncify_start_rewind=a0=>(_asyncify_start_rewind=wasmExports["V"])(a0);var _asyncify_stop_rewind=()=>(_asyncify_stop_rewind=wasmExports["W"])();Module["addFunction"]=addFunction;var calledRun;dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function run(){if(runDependencies>0){return}preRun();if(runDependencies>0){return}function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();readyPromiseResolve(Module);Module["onRuntimeInitialized"]?.();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("")},1);doRun()},1)}else{doRun()}}if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}run();moduleRtn=readyPromise; return moduleRtn; diff --git a/lib/wasm/pv_eagle_simd.wasm b/lib/wasm/pv_eagle_simd.wasm index 2f99a953..85e60188 100755 Binary files a/lib/wasm/pv_eagle_simd.wasm and b/lib/wasm/pv_eagle_simd.wasm differ diff --git a/lib/windows/amd64/libpv_eagle.dll b/lib/windows/amd64/libpv_eagle.dll index a130fc99..a801ba18 100644 Binary files a/lib/windows/amd64/libpv_eagle.dll and b/lib/windows/amd64/libpv_eagle.dll differ diff --git a/lib/windows/amd64/pv_ypu_impl_cuda_eagle.dll b/lib/windows/amd64/pv_ypu_impl_cuda_eagle.dll index 82fa06ac..c0f6b887 100644 Binary files a/lib/windows/amd64/pv_ypu_impl_cuda_eagle.dll and b/lib/windows/amd64/pv_ypu_impl_cuda_eagle.dll differ diff --git a/lib/windows/arm64/libpv_eagle.dll b/lib/windows/arm64/libpv_eagle.dll index d692d97b..8255d293 100644 Binary files a/lib/windows/arm64/libpv_eagle.dll and b/lib/windows/arm64/libpv_eagle.dll differ