From 948ef471062c8e5f3e24eb625b34726cecb7044e Mon Sep 17 00:00:00 2001 From: upstream-mirror Date: Tue, 15 Sep 2026 17:23:35 +0500 Subject: [PATCH] snapshot of https://github.com/ggml-org/whisper.cpp.git @ da54572229bcf64ba367d96c7ef15770376c4280 (2026-09-15) --- .devops/cublas.Dockerfile | 28 + .devops/main-cuda.Dockerfile | 50 + .devops/main-intel.Dockerfile | 29 + .devops/main-musa.Dockerfile | 40 + .devops/main-rocm.Dockerfile | 81 + .devops/main-vulkan.Dockerfile | 20 + .devops/main.Dockerfile | 20 + .dockerignore | 3 + .github/actions/ccache-clear/action.yml | 22 + .github/workflows/bindings-go.yml | 22 + .github/workflows/bindings-ruby.yml | 32 + .github/workflows/build-android.yml | 80 + .github/workflows/build-clang.yml | 122 + .github/workflows/build-coreml.yml | 65 + .github/workflows/build-cpu.yml | 173 + .github/workflows/build-freebsd.yml | 47 + .github/workflows/build-gcc.yml | 167 + .github/workflows/build-macos.yml | 73 + .github/workflows/build-quantize.yml | 48 + .github/workflows/build-sanitize.yml | 85 + .github/workflows/build-self-hosted.yml | 259 + .github/workflows/build-sycl.yml | 150 + .github/workflows/build-vad.yml | 50 + .github/workflows/build-wasm.yml | 65 + .github/workflows/build-windows.yml | 74 + .github/workflows/close-issue.yml | 28 + .github/workflows/deploy-examples-wasm.yml | 97 + .github/workflows/docker.yml | 73 + .github/workflows/examples.yml | 53 + .github/workflows/make-release.yml | 88 + .github/workflows/release.yml | 941 + .gitignore | 70 + .pi/gg/SYSTEM.md | 30 + AGENTS.md | 102 + AUTHORS | 510 + CMakeLists.txt | 324 + CMakePresets.json | 95 + CONTRIBUTING.md | 176 + LICENSE | 21 + Makefile | 58 + README.md | 970 + README_sycl.md | 249 + bindings/CMakeLists.txt | 19 + bindings/go/.gitignore | 2 + bindings/go/LICENSE | 21 + bindings/go/Makefile | 72 + bindings/go/README.md | 106 + bindings/go/doc.go | 5 + .../go/examples/go-model-download/context.go | 31 + .../go/examples/go-model-download/main.go | 311 + bindings/go/examples/go-whisper/color.go | 22 + bindings/go/examples/go-whisper/flags.go | 147 + bindings/go/examples/go-whisper/main.go | 43 + bindings/go/examples/go-whisper/process.go | 132 + bindings/go/go.mod | 16 + bindings/go/go.sum | 16 + bindings/go/params.go | 244 + bindings/go/pkg/whisper/consts.go | 28 + bindings/go/pkg/whisper/context.go | 385 + bindings/go/pkg/whisper/context_test.go | 172 + bindings/go/pkg/whisper/doc.go | 4 + bindings/go/pkg/whisper/interface.go | 118 + bindings/go/pkg/whisper/model.go | 101 + bindings/go/pkg/whisper/model_test.go | 91 + bindings/go/pkg/whisper/util_test.go | 6 + bindings/go/samples/jfk.wav | Bin 0 -> 352078 bytes bindings/go/whisper.go | 470 + bindings/go/whisper_test.go | 113 + bindings/java/README.md | 87 + bindings/java/build.gradle | 159 + bindings/java/gradle.properties | 6 + .../java/gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 61608 bytes .../gradle/wrapper/gradle-wrapper.properties | 6 + bindings/java/gradlew | 244 + bindings/java/gradlew.bat | 92 + bindings/java/settings.gradle | 1 + .../whispercpp/WhisperConstants.java | 24 + .../ggerganov/whispercpp/WhisperContext.java | 36 + .../ggerganov/whispercpp/WhisperCpp.java | 219 + .../whispercpp/WhisperCppJnaLibrary.java | 390 + .../whispercpp/bean/WhisperSegment.java | 47 + .../callbacks/GgmlAbortCallback.java | 17 + .../WhisperEncoderBeginCallback.java | 24 + .../WhisperLogitsFilterCallback.java | 25 + .../callbacks/WhisperNewSegmentCallback.java | 24 + .../callbacks/WhisperProgressCallback.java | 22 + .../ggerganov/whispercpp/ggml/GgmlTensor.java | 4 + .../ggerganov/whispercpp/ggml/GgmlType.java | 18 + .../ggerganov/whispercpp/model/EModel.java | 10 + .../whispercpp/model/WhisperModel.java | 49 + .../whispercpp/model/WhisperModelLoader.java | 62 + .../whispercpp/model/WhisperState.java | 4 + .../whispercpp/model/WhisperTokenData.java | 50 + .../whispercpp/params/BeamSearchParams.java | 19 + .../ggerganov/whispercpp/params/CBool.java | 30 + .../whispercpp/params/GreedyParams.java | 16 + .../whispercpp/params/WhisperAhead.java | 30 + .../whispercpp/params/WhisperAheads.java | 41 + .../params/WhisperContextParams.java | 81 + .../whispercpp/params/WhisperFilters.java | 10 + .../whispercpp/params/WhisperFullParams.java | 360 + .../whispercpp/params/WhisperHParams.java | 15 + .../params/WhisperSamplingStrategy.java | 10 + .../ggerganov/whispercpp/WhisperCppTest.java | 147 + .../whispercpp/WhisperJnaLibraryTest.java | 17 + bindings/javascript/.gitignore | 3 + bindings/javascript/CMakeLists.txt | 41 + bindings/javascript/README.md | 81 + bindings/javascript/emscripten.cpp | 93 + bindings/javascript/libwhisper.worker.js | 1 + bindings/javascript/package-tmpl.json | 26 + bindings/javascript/whisper.js | 19 + bindings/ruby/.document | 3 + bindings/ruby/.gitignore | 9 + bindings/ruby/.rdoc_options | 2 + bindings/ruby/CHANGELOG.md | 169 + bindings/ruby/README.md | 497 + bindings/ruby/Rakefile | 111 + bindings/ruby/ext/.gitignore | 9 + bindings/ruby/ext/dependencies.rb | 79 + bindings/ruby/ext/dependencies_for_windows.rb | 17 + bindings/ruby/ext/extconf.rb | 35 + bindings/ruby/ext/options.rb | 125 + bindings/ruby/ext/options_for_windows.rb | 51 + bindings/ruby/ext/ruby_whisper.c | 198 + bindings/ruby/ext/ruby_whisper.h | 248 + bindings/ruby/ext/ruby_whisper_context.c | 941 + .../ruby/ext/ruby_whisper_context_params.c | 163 + bindings/ruby/ext/ruby_whisper_error.c | 52 + bindings/ruby/ext/ruby_whisper_log_queue.c | 180 + bindings/ruby/ext/ruby_whisper_log_settable.h | 46 + bindings/ruby/ext/ruby_whisper_model.c | 231 + bindings/ruby/ext/ruby_whisper_parakeet.c | 49 + .../ruby/ext/ruby_whisper_parakeet_context.c | 316 + .../ruby_whisper_parakeet_context_params.c | 117 + .../ruby/ext/ruby_whisper_parakeet_model.c | 84 + .../ruby/ext/ruby_whisper_parakeet_params.c | 548 + .../ruby/ext/ruby_whisper_parakeet_segment.c | 157 + .../ruby/ext/ruby_whisper_parakeet_token.c | 188 + .../ext/ruby_whisper_parakeet_transcribe.cpp | 58 + bindings/ruby/ext/ruby_whisper_params.c | 1548 + bindings/ruby/ext/ruby_whisper_segment.c | 284 + bindings/ruby/ext/ruby_whisper_token.c | 371 + bindings/ruby/ext/ruby_whisper_transcribe.cpp | 104 + bindings/ruby/ext/ruby_whisper_vad_context.c | 154 + .../ext/ruby_whisper_vad_context_detect.cpp | 50 + bindings/ruby/ext/ruby_whisper_vad_params.c | 287 + bindings/ruby/ext/ruby_whisper_vad_segment.c | 138 + bindings/ruby/ext/ruby_whisper_vad_segments.c | 105 + .../ext/sources/CMakeGraphVizOptions.cmake | 8 + bindings/ruby/extsources.rb | 57 + bindings/ruby/lib/whisper/log_settable.rb | 33 + bindings/ruby/lib/whisper/model/uri.rb | 237 + bindings/ruby/lib/whisper/output.rb | 74 + bindings/ruby/sig/whisper.rbs | 1036 + bindings/ruby/test/helper.rb | 26 + bindings/ruby/test/jfk_reader/.gitignore | 5 + bindings/ruby/test/jfk_reader/extconf.rb | 3 + bindings/ruby/test/jfk_reader/jfk_reader.c | 111 + bindings/ruby/test/test_callback.rb | 203 + bindings/ruby/test/test_context_params.rb | 82 + bindings/ruby/test/test_error.rb | 20 + bindings/ruby/test/test_model.rb | 118 + bindings/ruby/test/test_package.rb | 52 + bindings/ruby/test/test_parakeet.rb | 28 + bindings/ruby/test/test_parakeet_callback.rb | 107 + bindings/ruby/test/test_parakeet_context.rb | 123 + .../ruby/test/test_parakeet_context_params.rb | 24 + bindings/ruby/test/test_parakeet_model.rb | 21 + bindings/ruby/test/test_parakeet_params.rb | 78 + bindings/ruby/test/test_parakeet_segment.rb | 42 + bindings/ruby/test/test_parakeet_token.rb | 73 + bindings/ruby/test/test_params.rb | 315 + bindings/ruby/test/test_segment.rb | 145 + bindings/ruby/test/test_token.rb | 81 + bindings/ruby/test/test_vad.rb | 28 + bindings/ruby/test/test_vad_context.rb | 108 + bindings/ruby/test/test_vad_params.rb | 103 + bindings/ruby/test/test_vad_segment.rb | 19 + bindings/ruby/test/test_vad_segments.rb | 16 + bindings/ruby/test/test_whisper.rb | 350 + bindings/ruby/whispercpp.gemspec | 36 + build-xcframework.sh | 574 + ci/README.md | 41 + ci/ruleset-nightly.json | 26 + ci/ruleset-official.json | 39 + ci/run.sh | 390 + cmake/DefaultTargetOptions.cmake | 16 + cmake/FindFFmpeg.cmake | 163 + cmake/arm64-apple-clang.cmake | 16 + cmake/arm64-windows-llvm-cuda.cmake | 24 + cmake/arm64-windows-llvm.cmake | 16 + cmake/build-info.cmake | 60 + cmake/git-vars.cmake | 22 + cmake/parakeet-config.cmake.in | 30 + cmake/parakeet.pc.in | 10 + cmake/riscv64-spacemit-linux-gnu-gcc.cmake | 29 + cmake/whisper-config.cmake.in | 30 + cmake/whisper.pc.in | 10 + cmake/x64-windows-llvm.cmake | 5 + examples/CMakeLists.txt | 127 + examples/addon.node/.gitignore | 3 + examples/addon.node/CMakeLists.txt | 34 + examples/addon.node/README.md | 115 + examples/addon.node/__test__/whisper.spec.js | 133 + examples/addon.node/addon.cpp | 557 + examples/addon.node/index.js | 59 + examples/addon.node/package-lock.json | 4359 + examples/addon.node/package.json | 16 + examples/addon.node/vad-example.js | 132 + examples/bench.wasm/CMakeLists.txt | 49 + examples/bench.wasm/README.md | 47 + examples/bench.wasm/emscripten.cpp | 87 + examples/bench.wasm/index-tmpl.html | 285 + examples/bench/CMakeLists.txt | 8 + examples/bench/README.md | 51 + examples/bench/bench.cpp | 191 + examples/cli/CMakeLists.txt | 8 + examples/cli/README.md | 66 + examples/cli/cli.cpp | 1356 + examples/coi-serviceworker.js | 146 + examples/command.wasm/CMakeLists.txt | 50 + examples/command.wasm/README.md | 47 + examples/command.wasm/emscripten.cpp | 327 + examples/command.wasm/index-tmpl.html | 415 + examples/command/CMakeLists.txt | 10 + examples/command/README.md | 52 + examples/command/command.cpp | 802 + examples/command/commands.txt | 9 + examples/common-ggml.cpp | 246 + examples/common-ggml.h | 18 + examples/common-sdl.cpp | 227 + examples/common-sdl.h | 49 + examples/common-whisper.cpp | 247 + examples/common-whisper.h | 35 + examples/common.cpp | 675 + examples/common.h | 322 + examples/deprecation-warning/CMakeLists.txt | 6 + examples/deprecation-warning/README.md | 17 + .../deprecation-warning.cpp | 38 + examples/ffmpeg-transcode.cpp | 238 + examples/generate-karaoke.sh | 57 + examples/grammar-parser.cpp | 423 + examples/grammar-parser.h | 29 + examples/helpers.js | 191 + examples/json.hpp | 24596 ++++ examples/livestream.sh | 112 + examples/lsp/CMakeLists.txt | 10 + examples/lsp/README.md | 104 + examples/lsp/lsp.cpp | 471 + examples/lsp/whisper.vim | 362 + examples/miniaudio.h | 95844 ++++++++++++++++ examples/parakeet-cli/CMakeLists.txt | 8 + examples/parakeet-cli/README.md | 106 + examples/parakeet-cli/parakeet-cli.cpp | 243 + examples/parakeet-quantize/CMakeLists.txt | 7 + .../parakeet-quantize/parakeet-quantize.cpp | 230 + examples/python/test_whisper_processor.py | 7 + examples/python/whisper_processor.py | 54 + examples/quantize/CMakeLists.txt | 7 + examples/quantize/README.md | 3 + examples/quantize/quantize.cpp | 226 + examples/server.py | 120 + examples/server/CMakeLists.txt | 15 + examples/server/README.md | 124 + examples/server/bench.js | 29 + examples/server/httplib.h | 10497 ++ examples/server/server.cpp | 1310 + examples/stb_vorbis.c | 5584 + examples/stream.wasm/CMakeLists.txt | 49 + examples/stream.wasm/README.md | 45 + examples/stream.wasm/emscripten.cpp | 216 + examples/stream.wasm/index-tmpl.html | 491 + examples/stream/CMakeLists.txt | 10 + examples/stream/README.md | 51 + examples/stream/stream.cpp | 437 + examples/sycl/CMakeLists.txt | 9 + examples/sycl/README.md | 47 + examples/sycl/build.sh | 22 + examples/sycl/ls-sycl-device.cpp | 11 + examples/sycl/run-whisper.sh | 17 + examples/talk-llama/.gitignore | 2 + examples/talk-llama/CMakeLists.txt | 43 + examples/talk-llama/README.md | 61 + examples/talk-llama/eleven-labs.py | 80 + examples/talk-llama/prompts/talk-alpaca.txt | 23 + examples/talk-llama/speak | 40 + examples/talk-llama/speak.bat | 1 + examples/talk-llama/speak.ps1 | 14 + examples/talk-llama/talk-llama.cpp | 813 + examples/test-cmake/.gitignore | 3 + examples/test-cmake/CMakeLists.txt | 17 + examples/test-cmake/README.md | 40 + examples/test-cmake/build-install.sh | 18 + examples/test-cmake/build.sh | 8 + examples/test-cmake/test-cmake.cpp | 9 + examples/twitch.sh | 109 + examples/vad-speech-segments/CMakeLists.txt | 8 + examples/vad-speech-segments/README.md | 52 + examples/vad-speech-segments/speech.cpp | 150 + examples/wchess/CMakeLists.txt | 10 + examples/wchess/README.md | 45 + examples/wchess/libwchess/CMakeLists.txt | 19 + examples/wchess/libwchess/Chessboard.cpp | 803 + examples/wchess/libwchess/Chessboard.h | 33 + examples/wchess/libwchess/WChess.cpp | 193 + examples/wchess/libwchess/WChess.h | 63 + examples/wchess/libwchess/test-chessboard.cpp | 117 + examples/wchess/wchess.cmd/CMakeLists.txt | 8 + examples/wchess/wchess.cmd/wchess.cmd.cpp | 253 + examples/wchess/wchess.wasm/CMakeLists.txt | 50 + .../css/chessboard-1.0.0.css | 54 + .../css/chessboard-1.0.0.min.css | 2 + .../img/chesspieces/wikipedia/bB.png | Bin 0 -> 1405 bytes .../img/chesspieces/wikipedia/bK.png | Bin 0 -> 3009 bytes .../img/chesspieces/wikipedia/bN.png | Bin 0 -> 1875 bytes .../img/chesspieces/wikipedia/bP.png | Bin 0 -> 777 bytes .../img/chesspieces/wikipedia/bQ.png | Bin 0 -> 2648 bytes .../img/chesspieces/wikipedia/bR.png | Bin 0 -> 748 bytes .../img/chesspieces/wikipedia/wB.png | Bin 0 -> 2374 bytes .../img/chesspieces/wikipedia/wK.png | Bin 0 -> 2823 bytes .../img/chesspieces/wikipedia/wN.png | Bin 0 -> 2388 bytes .../img/chesspieces/wikipedia/wP.png | Bin 0 -> 1571 bytes .../img/chesspieces/wikipedia/wQ.png | Bin 0 -> 3812 bytes .../img/chesspieces/wikipedia/wR.png | Bin 0 -> 1097 bytes .../chessboardjs-1.0.0/js/chessboard-1.0.0.js | 1817 + .../js/chessboard-1.0.0.min.js | 2 + .../js/chessboard-1.0.0/CHANGELOG.md | 32 + .../js/chessboard-1.0.0/LICENSE.md | 20 + .../js/chessboard-1.0.0/README.md | 82 + .../js/chessboard-1.0.0/package.json | 29 + examples/wchess/wchess.wasm/index-tmpl.html | 498 + .../wchess/wchess.wasm/jquery-3.7.1.min.js | 2 + examples/wchess/wchess.wasm/wchess.wasm.cpp | 141 + examples/whisper.android.java/.gitignore | 15 + examples/whisper.android.java/README.md | 20 + .../whisper.android.java/README_files/1.jpg | Bin 0 -> 68988 bytes examples/whisper.android.java/app/.gitignore | 1 + .../whisper.android.java/app/build.gradle | 70 + .../app/proguard-rules.pro | 21 + .../android/java/ExampleInstrumentedTest.java | 26 + .../app/src/main/AndroidManifest.xml | 22 + .../app/src/main/assets/logback.xml | 40 + .../whisper/android/java/MainActivity.java | 107 + .../whisper/android/java/app/App.java | 13 + .../android/java/bean/WhisperSegment.java | 47 + .../android/java/services/WhisperService.java | 101 + .../android/java/single/LocalWhisper.java | 66 + .../android/java/task/LoadModelTask.java | 44 + .../android/java/task/TranscriptionTask.java | 44 + .../android/java/utils/AssetUtils.java | 91 + .../android/java/utils/WaveEncoder.java | 105 + .../com/whispercpp/java/whisper/CpuInfo.java | 121 + .../java/whisper/WhisperContext.java | 138 + .../java/whisper/WhisperCpuConfig.java | 12 + .../whispercpp/java/whisper/WhisperLib.java | 75 + .../whispercpp/java/whisper/WhisperUtils.java | 34 + .../app/src/main/jni/whisper/CMakeLists.txt | 73 + .../app/src/main/jni/whisper/jni.c | 261 + .../drawable-v24/ic_launcher_foreground.xml | 30 + .../res/drawable/ic_launcher_background.xml | 170 + .../app/src/main/res/layout/activity_main.xml | 57 + .../res/mipmap-anydpi-v26/ic_launcher.xml | 5 + .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 + .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 3593 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 5339 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 2636 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 3388 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 4926 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 7472 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 7909 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 11873 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 10652 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 16570 bytes .../app/src/main/res/values-night/themes.xml | 16 + .../app/src/main/res/values/colors.xml | 10 + .../app/src/main/res/values/strings.xml | 3 + .../app/src/main/res/values/themes.xml | 16 + .../whisper/android/java/ExampleUnitTest.java | 17 + examples/whisper.android.java/build.gradle | 25 + .../whisper.android.java/gradle.properties | 19 + .../gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 54329 bytes .../gradle/wrapper/gradle-wrapper.properties | 6 + examples/whisper.android.java/gradlew | 172 + examples/whisper.android.java/gradlew.bat | 84 + examples/whisper.android.java/settings.gradle | 2 + examples/whisper.android/.gitignore | 15 + examples/whisper.android/README.md | 14 + examples/whisper.android/app/.gitignore | 1 + examples/whisper.android/app/build.gradle | 76 + .../whisper.android/app/proguard-rules.pro | 21 + .../whispercppdemo/ExampleInstrumentedTest.kt | 24 + .../app/src/main/AndroidManifest.xml | 32 + .../java/com/whispercppdemo/MainActivity.kt | 22 + .../whispercppdemo/media/RiffWaveHelper.kt | 80 + .../com/whispercppdemo/recorder/Recorder.kt | 88 + .../com/whispercppdemo/ui/main/MainScreen.kt | 114 + .../ui/main/MainScreenViewModel.kt | 225 + .../java/com/whispercppdemo/ui/theme/Color.kt | 11 + .../java/com/whispercppdemo/ui/theme/Theme.kt | 69 + .../java/com/whispercppdemo/ui/theme/Type.kt | 34 + .../res/drawable/ic_launcher_background.xml | 170 + .../res/drawable/ic_launcher_foreground.xml | 30 + .../main/res/mipmap-anydpi/ic_launcher.xml | 5 + .../app/src/main/res/values/strings.xml | 3 + .../app/src/main/res/values/themes.xml | 5 + .../app/src/main/res/xml/backup_rules.xml | 13 + .../main/res/xml/data_extraction_rules.xml | 19 + .../com/whispercppdemo/ExampleUnitTest.kt | 17 + examples/whisper.android/build.gradle | 6 + examples/whisper.android/gradle.properties | 23 + .../gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 59203 bytes .../gradle/wrapper/gradle-wrapper.properties | 6 + examples/whisper.android/gradlew | 185 + examples/whisper.android/gradlew.bat | 89 + examples/whisper.android/lib/.gitignore | 1 + examples/whisper.android/lib/build.gradle | 73 + .../lib/src/main/AndroidManifest.xml | 4 + .../java/com/whispercpp/whisper/LibWhisper.kt | 180 + .../whispercpp/whisper/WhisperCpuConfig.kt | 73 + .../lib/src/main/jni/whisper/CMakeLists.txt | 86 + .../lib/src/main/jni/whisper/jni.c | 257 + examples/whisper.android/settings.gradle | 17 + examples/whisper.nvim/README.md | 92 + examples/whisper.nvim/whisper.nvim | 50 + examples/whisper.objc/README.md | 42 + .../whisper.objc.xcodeproj/project.pbxproj | 458 + .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../whisper.objc/whisper.objc/AppDelegate.h | 14 + .../whisper.objc/whisper.objc/AppDelegate.m | 40 + .../AccentColor.colorset/Contents.json | 11 + .../AppIcon.appiconset/Contents.json | 13 + .../Assets.xcassets/Contents.json | 6 + .../Base.lproj/LaunchScreen.storyboard | 25 + .../whisper.objc/Base.lproj/Main.storyboard | 102 + examples/whisper.objc/whisper.objc/Info.plist | 27 + .../whisper.objc/whisper.objc/SceneDelegate.h | 15 + .../whisper.objc/whisper.objc/SceneDelegate.m | 57 + .../whisper.objc/ViewController.h | 45 + .../whisper.objc/ViewController.m | 317 + examples/whisper.objc/whisper.objc/main.m | 18 + examples/whisper.swiftui/.gitignore | 2 + examples/whisper.swiftui/README.md | 55 + .../whisper.cpp.swift/LibWhisper.swift | 157 + .../whisper.swiftui.demo/Models/Model.swift | 17 + .../Models/WhisperState.swift | 203 + .../Resources/models/.gitignore | 0 .../Resources/samples/.gitignore | 0 .../AccentColor.colorset/Contents.json | 11 + .../AppIcon.appiconset/Contents.json | 63 + .../Assets.xcassets/Contents.json | 6 + .../Preview Assets.xcassets/Contents.json | 6 + .../WhisperCppDemo.entitlements | 12 + .../whisper.swiftui.demo/UI/ContentView.swift | 154 + .../UI/DownloadButton.swift | 102 + .../whisper.swiftui.demo/Utils/Recorder.swift | 35 + .../Utils/RiffWaveUtils.swift | 12 + .../WhisperCppDemoApp.swift | 10 + .../whisper.swiftui.xcodeproj/.gitignore | 1 + .../whisper.swiftui.xcodeproj/project.pbxproj | 476 + .../project.xcworkspace/.gitignore | 1 + examples/whisper.wasm/CMakeLists.txt | 50 + examples/whisper.wasm/README.md | 67 + examples/whisper.wasm/emscripten.cpp | 118 + examples/whisper.wasm/index-tmpl.html | 659 + examples/yt-wsp.sh | 227 + ggml/.gitignore | 1 + ggml/CMakeLists.txt | 501 + ggml/cmake/FindNCCL.cmake | 36 + ggml/cmake/GitVars.cmake | 22 + ggml/cmake/common.cmake | 121 + ggml/cmake/ggml-config.cmake.in | 216 + ggml/include/ggml-alloc.h | 86 + ggml/include/ggml-backend.h | 437 + ggml/include/ggml-blas.h | 25 + ggml/include/ggml-cann.h | 123 + ggml/include/ggml-cpp.h | 39 + ggml/include/ggml-cpu.h | 152 + ggml/include/ggml-cuda.h | 47 + ggml/include/ggml-et.h | 28 + ggml/include/ggml-hexagon.h | 19 + ggml/include/ggml-metal.h | 61 + ggml/include/ggml-opencl.h | 26 + ggml/include/ggml-openvino.h | 37 + ggml/include/ggml-opt.h | 256 + ggml/include/ggml-rpc.h | 35 + ggml/include/ggml-sycl.h | 57 + ggml/include/ggml-virtgpu.h | 14 + ggml/include/ggml-vulkan.h | 29 + ggml/include/ggml-webgpu.h | 19 + ggml/include/ggml-zdnn.h | 17 + ggml/include/ggml-zendnn.h | 22 + ggml/include/ggml.h | 3012 + ggml/include/gguf.h | 211 + ggml/src/CMakeLists.txt | 634 + ggml/src/ggml-alloc.c | 1249 + ggml/src/ggml-backend-dl.cpp | 48 + ggml/src/ggml-backend-dl.h | 45 + ggml/src/ggml-backend-impl.h | 291 + ggml/src/ggml-backend-meta.cpp | 2511 + ggml/src/ggml-backend-reg.cpp | 605 + ggml/src/ggml-backend.cpp | 2510 + ggml/src/ggml-blas/CMakeLists.txt | 101 + ggml/src/ggml-blas/ggml-blas.cpp | 530 + ggml/src/ggml-cann/CMakeLists.txt | 89 + ggml/src/ggml-cann/acl_tensor.cpp | 195 + ggml/src/ggml-cann/acl_tensor.h | 349 + ggml/src/ggml-cann/aclnn_ops.cpp | 4479 + ggml/src/ggml-cann/aclnn_ops.h | 1191 + ggml/src/ggml-cann/common.h | 651 + ggml/src/ggml-cann/ggml-cann.cpp | 3070 + ggml/src/ggml-common.h | 1911 + ggml/src/ggml-cpu/CMakeLists.txt | 687 + ggml/src/ggml-cpu/amx/amx.cpp | 249 + ggml/src/ggml-cpu/amx/amx.h | 8 + ggml/src/ggml-cpu/amx/common.h | 115 + ggml/src/ggml-cpu/amx/mmq.cpp | 2511 + ggml/src/ggml-cpu/amx/mmq.h | 10 + ggml/src/ggml-cpu/arch-fallback.h | 349 + ggml/src/ggml-cpu/arch/arm/cpu-feats.cpp | 41 + ggml/src/ggml-cpu/arch/arm/quants.c | 4319 + ggml/src/ggml-cpu/arch/arm/repack.cpp | 5156 + ggml/src/ggml-cpu/arch/loongarch/quants.c | 2309 + ggml/src/ggml-cpu/arch/powerpc/cpu-feats.cpp | 82 + ggml/src/ggml-cpu/arch/powerpc/quants.c | 2304 + ggml/src/ggml-cpu/arch/riscv/cpu-feats.cpp | 38 + ggml/src/ggml-cpu/arch/riscv/quants.c | 6596 ++ ggml/src/ggml-cpu/arch/riscv/repack.cpp | 1703 + ggml/src/ggml-cpu/arch/s390/cpu-feats.cpp | 50 + ggml/src/ggml-cpu/arch/s390/quants.c | 1534 + ggml/src/ggml-cpu/arch/s390/repack.cpp | 225 + ggml/src/ggml-cpu/arch/wasm/quants.c | 1292 + ggml/src/ggml-cpu/arch/x86/cpu-feats.cpp | 327 + ggml/src/ggml-cpu/arch/x86/quants.c | 4108 + ggml/src/ggml-cpu/arch/x86/repack.cpp | 6407 ++ ggml/src/ggml-cpu/binary-ops.cpp | 154 + ggml/src/ggml-cpu/binary-ops.h | 16 + ggml/src/ggml-cpu/cmake/FindSIMD.cmake | 100 + ggml/src/ggml-cpu/cmake/FindSMTIME.cmake | 32 + ggml/src/ggml-cpu/common.h | 95 + ggml/src/ggml-cpu/ggml-cpu-impl.h | 539 + ggml/src/ggml-cpu/ggml-cpu.c | 3936 + ggml/src/ggml-cpu/ggml-cpu.cpp | 712 + ggml/src/ggml-cpu/hbm.cpp | 55 + ggml/src/ggml-cpu/hbm.h | 8 + ggml/src/ggml-cpu/iqp.cpp | 1253 + ggml/src/ggml-cpu/iqp.h | 39 + ggml/src/ggml-cpu/kleidiai/CMakeLists.txt | 14 + ggml/src/ggml-cpu/kleidiai/kernels.cpp | 1101 + ggml/src/ggml-cpu/kleidiai/kernels.h | 101 + ggml/src/ggml-cpu/kleidiai/kleidiai.cpp | 1919 + ggml/src/ggml-cpu/kleidiai/kleidiai.h | 17 + ggml/src/ggml-cpu/llamafile/sgemm.cpp | 4164 + ggml/src/ggml-cpu/llamafile/sgemm.h | 25 + ggml/src/ggml-cpu/ops.cpp | 12164 ++ ggml/src/ggml-cpu/ops.h | 123 + ggml/src/ggml-cpu/quants.c | 1339 + ggml/src/ggml-cpu/quants.h | 106 + ggml/src/ggml-cpu/repack.cpp | 4841 + ggml/src/ggml-cpu/repack.h | 245 + ggml/src/ggml-cpu/simd-gemm.h | 226 + ggml/src/ggml-cpu/simd-mappings.h | 1319 + ggml/src/ggml-cpu/spacemit/ime.cpp | 1742 + ggml/src/ggml-cpu/spacemit/ime.h | 21 + ggml/src/ggml-cpu/spacemit/ime1_kernels.cpp | 1027 + ggml/src/ggml-cpu/spacemit/ime2_kernels.cpp | 5768 + ggml/src/ggml-cpu/spacemit/ime_env.cpp | 320 + ggml/src/ggml-cpu/spacemit/ime_env.h | 55 + ggml/src/ggml-cpu/spacemit/ime_kernels.h | 189 + ggml/src/ggml-cpu/spacemit/repack.cpp | 1795 + ggml/src/ggml-cpu/spacemit/repack.h | 14 + ggml/src/ggml-cpu/spacemit/rvv_kernels.cpp | 3178 + ggml/src/ggml-cpu/spacemit/rvv_kernels.h | 95 + ggml/src/ggml-cpu/spacemit/spine_barrier.h | 34 + ggml/src/ggml-cpu/spacemit/spine_mem_pool.cpp | 760 + ggml/src/ggml-cpu/spacemit/spine_mem_pool.h | 32 + ggml/src/ggml-cpu/spacemit/spine_tcm.h | 409 + ggml/src/ggml-cpu/traits.cpp | 36 + ggml/src/ggml-cpu/traits.h | 38 + ggml/src/ggml-cpu/unary-ops.cpp | 337 + ggml/src/ggml-cpu/unary-ops.h | 35 + ggml/src/ggml-cpu/vec.cpp | 613 + ggml/src/ggml-cpu/vec.h | 1570 + ggml/src/ggml-cuda/CMakeLists.txt | 258 + ggml/src/ggml-cuda/acc.cu | 61 + ggml/src/ggml-cuda/acc.cuh | 5 + ggml/src/ggml-cuda/add-id.cu | 58 + ggml/src/ggml-cuda/add-id.cuh | 3 + ggml/src/ggml-cuda/allreduce.cu | 971 + ggml/src/ggml-cuda/allreduce.cuh | 29 + ggml/src/ggml-cuda/arange.cu | 34 + ggml/src/ggml-cuda/arange.cuh | 5 + ggml/src/ggml-cuda/argmax.cu | 91 + ggml/src/ggml-cuda/argmax.cuh | 3 + ggml/src/ggml-cuda/argsort.cu | 292 + ggml/src/ggml-cuda/argsort.cuh | 20 + ggml/src/ggml-cuda/binbcast.cu | 574 + ggml/src/ggml-cuda/binbcast.cuh | 12 + ggml/src/ggml-cuda/clamp.cu | 45 + ggml/src/ggml-cuda/clamp.cuh | 5 + ggml/src/ggml-cuda/col2im-1d.cu | 81 + ggml/src/ggml-cuda/col2im-1d.cuh | 3 + ggml/src/ggml-cuda/common.cuh | 1717 + ggml/src/ggml-cuda/concat.cu | 242 + ggml/src/ggml-cuda/concat.cuh | 5 + ggml/src/ggml-cuda/conv-transpose-1d.cu | 88 + ggml/src/ggml-cuda/conv-transpose-1d.cuh | 5 + ggml/src/ggml-cuda/conv2d-dw.cu | 161 + ggml/src/ggml-cuda/conv2d-dw.cuh | 5 + ggml/src/ggml-cuda/conv2d-transpose.cu | 115 + ggml/src/ggml-cuda/conv2d-transpose.cuh | 5 + ggml/src/ggml-cuda/conv2d.cu | 167 + ggml/src/ggml-cuda/conv2d.cuh | 5 + ggml/src/ggml-cuda/convert.cu | 705 + ggml/src/ggml-cuda/convert.cuh | 66 + ggml/src/ggml-cuda/count-equal.cu | 64 + ggml/src/ggml-cuda/count-equal.cuh | 5 + ggml/src/ggml-cuda/cp-async.cuh | 57 + ggml/src/ggml-cuda/cpy-utils.cuh | 217 + ggml/src/ggml-cuda/cpy.cu | 617 + ggml/src/ggml-cuda/cpy.cuh | 7 + ggml/src/ggml-cuda/cross-entropy-loss.cu | 177 + ggml/src/ggml-cuda/cross-entropy-loss.cuh | 7 + ggml/src/ggml-cuda/cumsum.cu | 307 + ggml/src/ggml-cuda/cumsum.cuh | 5 + ggml/src/ggml-cuda/dequantize.cuh | 452 + ggml/src/ggml-cuda/diag.cu | 77 + ggml/src/ggml-cuda/diag.cuh | 5 + ggml/src/ggml-cuda/diagmask.cu | 40 + ggml/src/ggml-cuda/diagmask.cuh | 5 + ggml/src/ggml-cuda/dsv4-hc.cu | 294 + ggml/src/ggml-cuda/dsv4-hc.cuh | 6 + ggml/src/ggml-cuda/fattn-common.cuh | 1298 + ggml/src/ggml-cuda/fattn-mma-f16.cuh | 2136 + ggml/src/ggml-cuda/fattn-swizzle.cuh | 126 + ggml/src/ggml-cuda/fattn-tile.cu | 60 + ggml/src/ggml-cuda/fattn-tile.cuh | 1355 + ggml/src/ggml-cuda/fattn-vec.cuh | 609 + ggml/src/ggml-cuda/fattn.cu | 745 + ggml/src/ggml-cuda/fattn.cuh | 7 + ggml/src/ggml-cuda/fill.cu | 37 + ggml/src/ggml-cuda/fill.cuh | 3 + ggml/src/ggml-cuda/fwht.cu | 101 + ggml/src/ggml-cuda/fwht.cuh | 4 + ggml/src/ggml-cuda/gated_delta_net.cu | 327 + ggml/src/ggml-cuda/gated_delta_net.cuh | 14 + ggml/src/ggml-cuda/getrows.cu | 490 + ggml/src/ggml-cuda/getrows.cuh | 15 + ggml/src/ggml-cuda/ggml-cuda.cu | 5786 + ggml/src/ggml-cuda/gla.cu | 93 + ggml/src/ggml-cuda/gla.cuh | 3 + ggml/src/ggml-cuda/im2col.cu | 267 + ggml/src/ggml-cuda/im2col.cuh | 6 + ggml/src/ggml-cuda/lightning-indexer.cu | 588 + ggml/src/ggml-cuda/lightning-indexer.cuh | 4 + ggml/src/ggml-cuda/mean.cu | 77 + ggml/src/ggml-cuda/mean.cuh | 3 + ggml/src/ggml-cuda/mma.cuh | 1456 + ggml/src/ggml-cuda/mmf.cu | 191 + ggml/src/ggml-cuda/mmf.cuh | 927 + ggml/src/ggml-cuda/mmid.cu | 181 + ggml/src/ggml-cuda/mmid.cuh | 5 + ggml/src/ggml-cuda/mmq-config-ampere.cuh | 383 + ggml/src/ggml-cuda/mmq-config-blackwell.cuh | 37 + ggml/src/ggml-cuda/mmq-config-cdna.cuh | 185 + ggml/src/ggml-cuda/mmq-config-gcn.cuh | 281 + ggml/src/ggml-cuda/mmq-config-pascal-dp4a.cuh | 273 + .../src/ggml-cuda/mmq-config-pascal-older.cuh | 273 + ggml/src/ggml-cuda/mmq-config-rdna2.cuh | 273 + ggml/src/ggml-cuda/mmq-config-rdna3-5.cuh | 290 + ggml/src/ggml-cuda/mmq-config-rdna3.cuh | 274 + ggml/src/ggml-cuda/mmq-config-rdna4.cuh | 290 + ggml/src/ggml-cuda/mmq-load-tiles.cuh | 1768 + ggml/src/ggml-cuda/mmq-vec-dot.cuh | 1240 + ggml/src/ggml-cuda/mmq.cu | 393 + ggml/src/ggml-cuda/mmq.cuh | 1605 + ggml/src/ggml-cuda/mmvf.cu | 875 + ggml/src/ggml-cuda/mmvf.cuh | 14 + ggml/src/ggml-cuda/mmvq.cu | 1551 + ggml/src/ggml-cuda/mmvq.cuh | 18 + ggml/src/ggml-cuda/moe-weighted-reduction.cu | 65 + ggml/src/ggml-cuda/moe-weighted-reduction.cuh | 7 + ggml/src/ggml-cuda/norm.cu | 698 + ggml/src/ggml-cuda/norm.cuh | 18 + ggml/src/ggml-cuda/opt-step-adamw.cu | 78 + ggml/src/ggml-cuda/opt-step-adamw.cuh | 5 + ggml/src/ggml-cuda/opt-step-sgd.cu | 49 + ggml/src/ggml-cuda/opt-step-sgd.cuh | 5 + ggml/src/ggml-cuda/out-prod.cu | 125 + ggml/src/ggml-cuda/out-prod.cuh | 3 + ggml/src/ggml-cuda/pad.cu | 106 + ggml/src/ggml-cuda/pad.cuh | 5 + ggml/src/ggml-cuda/pad_reflect_1d.cu | 91 + ggml/src/ggml-cuda/pad_reflect_1d.cuh | 5 + ggml/src/ggml-cuda/pool1d.cu | 85 + ggml/src/ggml-cuda/pool1d.cuh | 5 + ggml/src/ggml-cuda/pool2d.cu | 94 + ggml/src/ggml-cuda/pool2d.cuh | 5 + ggml/src/ggml-cuda/quantize.cu | 697 + ggml/src/ggml-cuda/quantize.cuh | 70 + ggml/src/ggml-cuda/reduce_rows.cuh | 43 + ggml/src/ggml-cuda/roll.cu | 67 + ggml/src/ggml-cuda/roll.cuh | 5 + ggml/src/ggml-cuda/rope.cu | 941 + ggml/src/ggml-cuda/rope.cuh | 11 + ggml/src/ggml-cuda/scale.cu | 37 + ggml/src/ggml-cuda/scale.cuh | 5 + ggml/src/ggml-cuda/set-rows.cu | 398 + ggml/src/ggml-cuda/set-rows.cuh | 7 + ggml/src/ggml-cuda/set.cu | 39 + ggml/src/ggml-cuda/set.cuh | 7 + ggml/src/ggml-cuda/snake.cu | 72 + ggml/src/ggml-cuda/snake.cuh | 8 + ggml/src/ggml-cuda/softcap.cu | 37 + ggml/src/ggml-cuda/softcap.cuh | 5 + ggml/src/ggml-cuda/softmax.cu | 480 + ggml/src/ggml-cuda/softmax.cuh | 7 + ggml/src/ggml-cuda/solve_tri.cu | 273 + ggml/src/ggml-cuda/solve_tri.cuh | 3 + ggml/src/ggml-cuda/ssm-conv.cu | 206 + ggml/src/ggml-cuda/ssm-conv.cuh | 3 + ggml/src/ggml-cuda/ssm-scan.cu | 859 + ggml/src/ggml-cuda/ssm-scan.cuh | 3 + ggml/src/ggml-cuda/sum.cu | 41 + ggml/src/ggml-cuda/sum.cuh | 5 + ggml/src/ggml-cuda/sumrows.cu | 47 + ggml/src/ggml-cuda/sumrows.cuh | 4 + ...ttn-mma-f16-instance-ncols1_1-ncols2_16.cu | 6 + ...ttn-mma-f16-instance-ncols1_1-ncols2_32.cu | 6 + ...attn-mma-f16-instance-ncols1_1-ncols2_8.cu | 12 + ...ttn-mma-f16-instance-ncols1_16-ncols2_1.cu | 10 + ...ttn-mma-f16-instance-ncols1_16-ncols2_2.cu | 11 + ...ttn-mma-f16-instance-ncols1_16-ncols2_4.cu | 12 + ...ttn-mma-f16-instance-ncols1_2-ncols2_16.cu | 6 + ...ttn-mma-f16-instance-ncols1_2-ncols2_32.cu | 6 + ...attn-mma-f16-instance-ncols1_2-ncols2_4.cu | 12 + ...attn-mma-f16-instance-ncols1_2-ncols2_8.cu | 12 + ...ttn-mma-f16-instance-ncols1_32-ncols2_1.cu | 10 + ...ttn-mma-f16-instance-ncols1_32-ncols2_2.cu | 11 + ...ttn-mma-f16-instance-ncols1_4-ncols2_16.cu | 6 + ...attn-mma-f16-instance-ncols1_4-ncols2_2.cu | 11 + ...attn-mma-f16-instance-ncols1_4-ncols2_4.cu | 12 + ...attn-mma-f16-instance-ncols1_4-ncols2_8.cu | 12 + ...ttn-mma-f16-instance-ncols1_64-ncols2_1.cu | 10 + ...attn-mma-f16-instance-ncols1_8-ncols2_1.cu | 10 + ...attn-mma-f16-instance-ncols1_8-ncols2_2.cu | 11 + ...attn-mma-f16-instance-ncols1_8-ncols2_4.cu | 12 + ...attn-mma-f16-instance-ncols1_8-ncols2_8.cu | 12 + .../fattn-tile-instance-dkq112-dv112.cu | 5 + .../fattn-tile-instance-dkq128-dv128.cu | 5 + .../fattn-tile-instance-dkq192-dv128.cu | 5 + .../fattn-tile-instance-dkq256-dv256.cu | 5 + .../fattn-tile-instance-dkq320-dv256.cu | 5 + .../fattn-tile-instance-dkq40-dv40.cu | 5 + .../fattn-tile-instance-dkq512-dv512.cu | 5 + .../fattn-tile-instance-dkq576-dv512.cu | 5 + .../fattn-tile-instance-dkq64-dv64.cu | 5 + .../fattn-tile-instance-dkq72-dv72.cu | 5 + .../fattn-tile-instance-dkq80-dv80.cu | 5 + .../fattn-tile-instance-dkq96-dv96.cu | 5 + .../fattn-vec-instance-bf16-bf16.cu | 7 + .../fattn-vec-instance-bf16-f16.cu | 7 + .../fattn-vec-instance-bf16-q4_0.cu | 7 + .../fattn-vec-instance-bf16-q4_1.cu | 7 + .../fattn-vec-instance-bf16-q5_0.cu | 7 + .../fattn-vec-instance-bf16-q5_1.cu | 7 + .../fattn-vec-instance-bf16-q8_0.cu | 7 + .../fattn-vec-instance-f16-bf16.cu | 7 + .../fattn-vec-instance-f16-f16.cu | 7 + .../fattn-vec-instance-f16-q4_0.cu | 7 + .../fattn-vec-instance-f16-q4_1.cu | 7 + .../fattn-vec-instance-f16-q5_0.cu | 7 + .../fattn-vec-instance-f16-q5_1.cu | 7 + .../fattn-vec-instance-f16-q8_0.cu | 7 + .../fattn-vec-instance-q4_0-bf16.cu | 7 + .../fattn-vec-instance-q4_0-f16.cu | 7 + .../fattn-vec-instance-q4_0-q4_0.cu | 7 + .../fattn-vec-instance-q4_0-q4_1.cu | 7 + .../fattn-vec-instance-q4_0-q5_0.cu | 7 + .../fattn-vec-instance-q4_0-q5_1.cu | 7 + .../fattn-vec-instance-q4_0-q8_0.cu | 7 + .../fattn-vec-instance-q4_1-bf16.cu | 7 + .../fattn-vec-instance-q4_1-f16.cu | 7 + .../fattn-vec-instance-q4_1-q4_0.cu | 7 + .../fattn-vec-instance-q4_1-q4_1.cu | 7 + .../fattn-vec-instance-q4_1-q5_0.cu | 7 + .../fattn-vec-instance-q4_1-q5_1.cu | 7 + .../fattn-vec-instance-q4_1-q8_0.cu | 7 + .../fattn-vec-instance-q5_0-bf16.cu | 7 + .../fattn-vec-instance-q5_0-f16.cu | 7 + .../fattn-vec-instance-q5_0-q4_0.cu | 7 + .../fattn-vec-instance-q5_0-q4_1.cu | 7 + .../fattn-vec-instance-q5_0-q5_0.cu | 7 + .../fattn-vec-instance-q5_0-q5_1.cu | 7 + .../fattn-vec-instance-q5_0-q8_0.cu | 7 + .../fattn-vec-instance-q5_1-bf16.cu | 7 + .../fattn-vec-instance-q5_1-f16.cu | 7 + .../fattn-vec-instance-q5_1-q4_0.cu | 7 + .../fattn-vec-instance-q5_1-q4_1.cu | 7 + .../fattn-vec-instance-q5_1-q5_0.cu | 7 + .../fattn-vec-instance-q5_1-q5_1.cu | 7 + .../fattn-vec-instance-q5_1-q8_0.cu | 7 + .../fattn-vec-instance-q8_0-bf16.cu | 7 + .../fattn-vec-instance-q8_0-f16.cu | 7 + .../fattn-vec-instance-q8_0-q4_0.cu | 7 + .../fattn-vec-instance-q8_0-q4_1.cu | 7 + .../fattn-vec-instance-q8_0-q5_0.cu | 7 + .../fattn-vec-instance-q8_0-q5_1.cu | 7 + .../fattn-vec-instance-q8_0-q8_0.cu | 7 + .../template-instances/generate_cu_files.py | 111 + .../mmf-instance-ncols_1.cu | 5 + .../mmf-instance-ncols_10.cu | 5 + .../mmf-instance-ncols_11.cu | 5 + .../mmf-instance-ncols_12.cu | 5 + .../mmf-instance-ncols_13.cu | 5 + .../mmf-instance-ncols_14.cu | 5 + .../mmf-instance-ncols_15.cu | 5 + .../mmf-instance-ncols_16.cu | 5 + .../mmf-instance-ncols_2.cu | 5 + .../mmf-instance-ncols_3.cu | 5 + .../mmf-instance-ncols_4.cu | 5 + .../mmf-instance-ncols_5.cu | 5 + .../mmf-instance-ncols_6.cu | 5 + .../mmf-instance-ncols_7.cu | 5 + .../mmf-instance-ncols_8.cu | 5 + .../mmf-instance-ncols_9.cu | 5 + .../template-instances/mmq-instance-iq1_s.cu | 5 + .../template-instances/mmq-instance-iq2_s.cu | 5 + .../template-instances/mmq-instance-iq2_xs.cu | 5 + .../mmq-instance-iq2_xxs.cu | 5 + .../template-instances/mmq-instance-iq3_s.cu | 5 + .../mmq-instance-iq3_xxs.cu | 5 + .../template-instances/mmq-instance-iq4_nl.cu | 5 + .../template-instances/mmq-instance-iq4_xs.cu | 5 + .../template-instances/mmq-instance-mxfp4.cu | 5 + .../template-instances/mmq-instance-nvfp4.cu | 5 + .../template-instances/mmq-instance-q1_0.cu | 5 + .../template-instances/mmq-instance-q2_0.cu | 5 + .../template-instances/mmq-instance-q2_k.cu | 5 + .../template-instances/mmq-instance-q3_k.cu | 5 + .../template-instances/mmq-instance-q4_0.cu | 5 + .../template-instances/mmq-instance-q4_1.cu | 5 + .../template-instances/mmq-instance-q4_k.cu | 5 + .../template-instances/mmq-instance-q5_0.cu | 5 + .../template-instances/mmq-instance-q5_1.cu | 5 + .../template-instances/mmq-instance-q5_k.cu | 5 + .../template-instances/mmq-instance-q6_k.cu | 5 + .../template-instances/mmq-instance-q8_0.cu | 5 + ggml/src/ggml-cuda/top-k.cu | 275 + ggml/src/ggml-cuda/top-k.cuh | 3 + ggml/src/ggml-cuda/topk-moe.cu | 442 + ggml/src/ggml-cuda/topk-moe.cuh | 31 + ggml/src/ggml-cuda/tri.cu | 136 + ggml/src/ggml-cuda/tri.cuh | 5 + ggml/src/ggml-cuda/tsembd.cu | 47 + ggml/src/ggml-cuda/tsembd.cuh | 5 + ggml/src/ggml-cuda/unary.cu | 721 + ggml/src/ggml-cuda/unary.cuh | 123 + ggml/src/ggml-cuda/upscale.cu | 293 + ggml/src/ggml-cuda/upscale.cuh | 5 + ggml/src/ggml-cuda/vecdotq.cuh | 1380 + ggml/src/ggml-cuda/vendors/cuda.h | 28 + ggml/src/ggml-cuda/vendors/hip.h | 301 + ggml/src/ggml-cuda/vendors/musa.h | 151 + ggml/src/ggml-cuda/wkv.cu | 253 + ggml/src/ggml-cuda/wkv.cuh | 7 + ggml/src/ggml-et/CMakeLists.txt | 246 + ggml/src/ggml-et/cmake/embed_one_kernel.cmake | 15 + .../cmake/ggml-et-kernels-embed.cpp.in | 6 + .../cmake/ggml-et-kernels-embed.hpp.in | 12 + .../ggml-et-uberkernel-kernel-map.cpp.in | 18 + .../cmake/ggml-et-uberkernel-kernel-map.h.in | 13 + ggml/src/ggml-et/et-kernels/CMakeLists.txt | 137 + .../check_unimplemented_instructions.sh | 36 + ggml/src/ggml-et/et-kernels/src/RunBackend.sh | 23 + ggml/src/ggml-et/et-kernels/src/block_ops.h | 997 + ggml/src/ggml-et/et-kernels/src/clamp_f32.c | 120 + ggml/src/ggml-et/et-kernels/src/concat_f32.c | 175 + ggml/src/ggml-et/et-kernels/src/cont_f16.c | 107 + ggml/src/ggml-et/et-kernels/src/cont_f32.c | 248 + .../ggml-et/et-kernels/src/conv_2d_f32_me.c | 807 + ggml/src/ggml-et/et-kernels/src/cpy_f32_f16.c | 110 + ggml/src/ggml-et/et-kernels/src/crt.S | 15 + ggml/src/ggml-et/et-kernels/src/cumsum_f32.c | 96 + ggml/src/ggml-et/et-kernels/src/diag_f32.c | 90 + ggml/src/ggml-et/et-kernels/src/el_map_f32.c | 377 + ggml/src/ggml-et/et-kernels/src/fill_f32.c | 87 + .../et-kernels/src/flash_attn_ext_f16_me.c | 1000 + .../et-kernels/src/flash_attn_ext_f32.c | 217 + .../et-kernels/src/gated_delta_net_f32.c | 346 + .../src/ggml-et/et-kernels/src/get_rows_f32.c | 612 + ggml/src/ggml-et/et-kernels/src/ggml_tensor.h | 44 + ggml/src/ggml-et/et-kernels/src/glu_f32.c | 606 + .../ggml-et/et-kernels/src/group_norm_f32.c | 171 + ggml/src/ggml-et/et-kernels/src/im2col.c | 130 + ggml/src/ggml-et/et-kernels/src/l2_norm_f32.c | 237 + ggml/src/ggml-et/et-kernels/src/linker.ld | 85 + ggml/src/ggml-et/et-kernels/src/math_fp.h | 299 + ggml/src/ggml-et/et-kernels/src/mean_f32.c | 220 + ggml/src/ggml-et/et-kernels/src/memops.c | 181 + .../src/ggml-et/et-kernels/src/mul_mat_Q4_0.c | 358 + .../src/mul_mat_Q4_0_matrix_engine.c | 368 + .../src/ggml-et/et-kernels/src/mul_mat_Q8_0.c | 413 + ggml/src/ggml-et/et-kernels/src/mul_mat_f16.c | 142 + .../src/mul_mat_f16_matrix_engine.c | 329 + ggml/src/ggml-et/et-kernels/src/mul_mat_f32.c | 137 + .../src/mul_mat_f32_matrix_engine.c | 155 + .../ggml-et/et-kernels/src/mul_mat_id_Q4_0.c | 169 + .../ggml-et/et-kernels/src/mul_mat_id_Q8_0.c | 160 + .../ggml-et/et-kernels/src/mul_mat_id_f32.c | 288 + ggml/src/ggml-et/et-kernels/src/norm_f32.c | 328 + ggml/src/ggml-et/et-kernels/src/pad_f32.c | 165 + ggml/src/ggml-et/et-kernels/src/platform.h | 545 + ggml/src/ggml-et/et-kernels/src/quants.h | 72 + ggml/src/ggml-et/et-kernels/src/repeat_f32.c | 118 + .../src/ggml-et/et-kernels/src/rms_norm_f32.c | 270 + .../ggml-et/et-kernels/src/rms_norm_mul_f32.c | 290 + ggml/src/ggml-et/et-kernels/src/rope_f32.c | 656 + .../ggml-et/et-kernels/src/rwkv_wkv6_f32.c | 184 + .../ggml-et/et-kernels/src/rwkv_wkv7_f32.c | 272 + ggml/src/ggml-et/et-kernels/src/scale_f32.c | 94 + ggml/src/ggml-et/et-kernels/src/set_f32.c | 101 + .../src/ggml-et/et-kernels/src/set_rows_f32.c | 394 + ggml/src/ggml-et/et-kernels/src/softmax_f32.c | 698 + .../ggml-et/et-kernels/src/solve_tri_f32.c | 109 + ggml/src/ggml-et/et-kernels/src/sqr_f32.c | 88 + .../src/ggml-et/et-kernels/src/ssm_conv_f32.c | 129 + .../src/ggml-et/et-kernels/src/ssm_scan_f32.c | 282 + .../src/ggml-et/et-kernels/src/sum_rows_f32.c | 103 + ggml/src/ggml-et/et-kernels/src/tensor.h | 897 + ggml/src/ggml-et/et-kernels/src/tri_f32.c | 244 + ggml/src/ggml-et/et-kernels/src/uberkernel.c | 497 + ggml/src/ggml-et/et-kernels/src/unary_f32.c | 705 + ggml/src/ggml-et/ggml-et-common.h | 86 + ggml/src/ggml-et/ggml-et-cpu-compare.cpp | 502 + ggml/src/ggml-et/ggml-et-cpu-compare.h | 54 + ggml/src/ggml-et/ggml-et-kernels.cpp | 508 + ggml/src/ggml-et/ggml-et-kernels.h | 48 + ggml/src/ggml-et/ggml-et-memops.cpp | 36 + ggml/src/ggml-et/ggml-et-memops.h | 18 + ggml/src/ggml-et/ggml-et-ops.cpp | 2584 + ggml/src/ggml-et/ggml-et-ops.h | 393 + ggml/src/ggml-et/ggml-et-uberkernel-common.h | 17 + ggml/src/ggml-et/ggml-et.cpp | 1880 + ggml/src/ggml-feats.h | 166 + ggml/src/ggml-hexagon/CMakeLists.txt | 113 + ggml/src/ggml-hexagon/ggml-hexagon.cpp | 7079 ++ ggml/src/ggml-hexagon/htp-drv.cpp | 425 + ggml/src/ggml-hexagon/htp-drv.h | 123 + ggml/src/ggml-hexagon/htp-opnode.h | 378 + ggml/src/ggml-hexagon/htp/CMakeLists.txt | 58 + ggml/src/ggml-hexagon/htp/act-ops.c | 602 + ggml/src/ggml-hexagon/htp/allreduce-ops.c | 457 + ggml/src/ggml-hexagon/htp/allreduce-ops.h | 51 + ggml/src/ggml-hexagon/htp/argsort-ops.c | 536 + ggml/src/ggml-hexagon/htp/binary-ops.c | 917 + .../ggml-hexagon/htp/cmake-toolchain.cmake | 155 + ggml/src/ggml-hexagon/htp/concat-ops.c | 328 + ggml/src/ggml-hexagon/htp/cpy-ops.c | 436 + ggml/src/ggml-hexagon/htp/cumsum-ops.c | 284 + ggml/src/ggml-hexagon/htp/diag-ops.c | 247 + ggml/src/ggml-hexagon/htp/dma-queue.c | 104 + ggml/src/ggml-hexagon/htp/dma-queue.h | 408 + ggml/src/ggml-hexagon/htp/fill-ops.c | 146 + ggml/src/ggml-hexagon/htp/flash-attn-ops.c | 2519 + ggml/src/ggml-hexagon/htp/flash-attn-ops.h | 345 + .../ggml-hexagon/htp/gated-delta-net-ops.c | 1189 + ggml/src/ggml-hexagon/htp/get-rows-ops.c | 292 + ggml/src/ggml-hexagon/htp/get-rows-ops.h | 77 + ggml/src/ggml-hexagon/htp/hex-bitmap.h | 24 + ggml/src/ggml-hexagon/htp/hex-common.h | 89 + ggml/src/ggml-hexagon/htp/hex-dma.h | 2 + ggml/src/ggml-hexagon/htp/hex-dump.h | 86 + ggml/src/ggml-hexagon/htp/hex-fastdiv.h | 37 + ggml/src/ggml-hexagon/htp/hex-profile.h | 64 + ggml/src/ggml-hexagon/htp/hex-utils.h | 64 + ggml/src/ggml-hexagon/htp/hmx-fa-kernels.h | 555 + .../ggml-hexagon/htp/hmx-mm-kernels-tiled.h | 1378 + ggml/src/ggml-hexagon/htp/hmx-queue.c | 170 + ggml/src/ggml-hexagon/htp/hmx-queue.h | 160 + ggml/src/ggml-hexagon/htp/hmx-utils.h | 222 + ggml/src/ggml-hexagon/htp/htp-ctx.h | 179 + ggml/src/ggml-hexagon/htp/htp-fence.h | 89 + ggml/src/ggml-hexagon/htp/htp-ops.h | 243 + ggml/src/ggml-hexagon/htp/htp-tensor.c | 351 + ggml/src/ggml-hexagon/htp/htp-tensor.h | 138 + ggml/src/ggml-hexagon/htp/htp-vtcm.h | 19 + ggml/src/ggml-hexagon/htp/htp_iface.idl | 23 + ggml/src/ggml-hexagon/htp/hvx-arith.h | 725 + ggml/src/ggml-hexagon/htp/hvx-base.h | 292 + ggml/src/ggml-hexagon/htp/hvx-copy.h | 262 + ggml/src/ggml-hexagon/htp/hvx-div.h | 291 + ggml/src/ggml-hexagon/htp/hvx-dump.h | 129 + ggml/src/ggml-hexagon/htp/hvx-exp.h | 255 + ggml/src/ggml-hexagon/htp/hvx-fa-kernels.h | 303 + ggml/src/ggml-hexagon/htp/hvx-flash-attn.h | 47 + ggml/src/ggml-hexagon/htp/hvx-floor.h | 100 + ggml/src/ggml-hexagon/htp/hvx-inverse.h | 210 + ggml/src/ggml-hexagon/htp/hvx-log.h | 118 + .../ggml-hexagon/htp/hvx-mm-kernels-flat.h | 1511 + .../ggml-hexagon/htp/hvx-mm-kernels-tiled.h | 1200 + ggml/src/ggml-hexagon/htp/hvx-norm.h | 454 + ggml/src/ggml-hexagon/htp/hvx-pow.h | 42 + ggml/src/ggml-hexagon/htp/hvx-quant.h | 165 + ggml/src/ggml-hexagon/htp/hvx-reduce.h | 336 + ggml/src/ggml-hexagon/htp/hvx-repl.h | 74 + ggml/src/ggml-hexagon/htp/hvx-scale.h | 199 + ggml/src/ggml-hexagon/htp/hvx-sigmoid.h | 181 + ggml/src/ggml-hexagon/htp/hvx-sin-cos.h | 78 + ggml/src/ggml-hexagon/htp/hvx-sqrt.h | 189 + ggml/src/ggml-hexagon/htp/hvx-types.h | 36 + ggml/src/ggml-hexagon/htp/hvx-utils.h | 24 + ggml/src/ggml-hexagon/htp/im2col-ops.c | 339 + ggml/src/ggml-hexagon/htp/main.c | 1304 + ggml/src/ggml-hexagon/htp/matmul-ops.c | 4247 + ggml/src/ggml-hexagon/htp/matmul-ops.h | 778 + ggml/src/ggml-hexagon/htp/pad-ops.c | 558 + ggml/src/ggml-hexagon/htp/repeat-ops.c | 169 + ggml/src/ggml-hexagon/htp/rope-ops.c | 803 + ggml/src/ggml-hexagon/htp/rope-ops.h | 56 + ggml/src/ggml-hexagon/htp/set-rows-ops.c | 260 + ggml/src/ggml-hexagon/htp/set-rows-ops.h | 74 + ggml/src/ggml-hexagon/htp/softmax-ops.c | 430 + ggml/src/ggml-hexagon/htp/solve-tri-ops.c | 299 + ggml/src/ggml-hexagon/htp/ssm-conv.c | 456 + ggml/src/ggml-hexagon/htp/sum-rows-ops.c | 154 + ggml/src/ggml-hexagon/htp/unary-ops.c | 1331 + ggml/src/ggml-hexagon/htp/unary-ops.h | 178 + ggml/src/ggml-hexagon/htp/work-queue.c | 244 + ggml/src/ggml-hexagon/htp/work-queue.h | 38 + ggml/src/ggml-hexagon/libdl.h | 79 + ggml/src/ggml-hexagon/libggml-htp.inf | 36 + ggml/src/ggml-hip/CMakeLists.txt | 144 + ggml/src/ggml-impl.h | 795 + ggml/src/ggml-metal/CMakeLists.txt | 241 + ggml/src/ggml-metal/ggml-metal-common.cpp | 447 + ggml/src/ggml-metal/ggml-metal-common.h | 56 + ggml/src/ggml-metal/ggml-metal-context.h | 42 + ggml/src/ggml-metal/ggml-metal-context.m | 771 + ggml/src/ggml-metal/ggml-metal-device.cpp | 2422 + ggml/src/ggml-metal/ggml-metal-device.h | 360 + ggml/src/ggml-metal/ggml-metal-device.m | 2493 + ggml/src/ggml-metal/ggml-metal-fusion.cpp | 502 + ggml/src/ggml-metal/ggml-metal-fusion.h | 104 + ggml/src/ggml-metal/ggml-metal-impl.h | 1353 + ggml/src/ggml-metal/ggml-metal-ops.cpp | 5550 + ggml/src/ggml-metal/ggml-metal-ops.h | 107 + ggml/src/ggml-metal/ggml-metal-tuning.cpp | 4051 + ggml/src/ggml-metal/ggml-metal-tuning.h | 77 + ggml/src/ggml-metal/ggml-metal.cpp | 1048 + ggml/src/ggml-metal/kernels/argsort.metal | 337 + ggml/src/ggml-metal/kernels/binbcast.metal | 228 + ggml/src/ggml-metal/kernels/common.h | 126 + ggml/src/ggml-metal/kernels/conv.metal | 724 + ggml/src/ggml-metal/kernels/dequantize.h | 735 + ggml/src/ggml-metal/kernels/fa.metal | 2445 + .../ggml-metal/kernels/gated_delta_net.metal | 264 + ggml/src/ggml-metal/kernels/misc.metal | 595 + ggml/src/ggml-metal/kernels/mul_mm.metal | 882 + ggml/src/ggml-metal/kernels/mul_mv.metal | 3395 + ggml/src/ggml-metal/kernels/norm.metal | 308 + ggml/src/ggml-metal/kernels/pool.metal | 148 + ggml/src/ggml-metal/kernels/quantize.h | 262 + ggml/src/ggml-metal/kernels/quantize.metal | 480 + ggml/src/ggml-metal/kernels/reduce.metal | 228 + ggml/src/ggml-metal/kernels/rope.metal | 333 + ggml/src/ggml-metal/kernels/softmax.metal | 223 + ggml/src/ggml-metal/kernels/solve_tri.metal | 75 + ggml/src/ggml-metal/kernels/ssm.metal | 473 + ggml/src/ggml-metal/kernels/tri.metal | 69 + ggml/src/ggml-metal/kernels/unary.metal | 400 + ggml/src/ggml-metal/kernels/upscale.metal | 179 + ggml/src/ggml-metal/kernels/wkv.metal | 179 + ggml/src/ggml-musa/CMakeLists.txt | 114 + ggml/src/ggml-musa/mudnn.cu | 112 + ggml/src/ggml-musa/mudnn.cuh | 12 + ggml/src/ggml-opencl/CMakeLists.txt | 249 + ggml/src/ggml-opencl/cl-program-cache.cpp | 453 + ggml/src/ggml-opencl/cl-program-cache.h | 75 + ggml/src/ggml-opencl/fa_tune.h | 92 + ggml/src/ggml-opencl/ggml-opencl.cpp | 28541 +++++ ggml/src/ggml-opencl/kernels/abs.cl | 113 + ggml/src/ggml-opencl/kernels/add.cl | 190 + ggml/src/ggml-opencl/kernels/add_id.cl | 42 + ggml/src/ggml-opencl/kernels/argsort.cl | 86 + ggml/src/ggml-opencl/kernels/clamp.cl | 20 + ggml/src/ggml-opencl/kernels/concat.cl | 128 + ggml/src/ggml-opencl/kernels/conv2d.cl | 185 + .../src/ggml-opencl/kernels/conv2d_f16_f32.cl | 176 + ggml/src/ggml-opencl/kernels/cpy.cl | 313 + ggml/src/ggml-opencl/kernels/cumsum.cl | 139 + ggml/src/ggml-opencl/kernels/cvt.cl | 2663 + ggml/src/ggml-opencl/kernels/diag.cl | 27 + ggml/src/ggml-opencl/kernels/diag_mask_inf.cl | 58 + ggml/src/ggml-opencl/kernels/div.cl | 138 + ggml/src/ggml-opencl/kernels/embed_kernel.py | 26 + ggml/src/ggml-opencl/kernels/exp.cl | 125 + ggml/src/ggml-opencl/kernels/expm1.cl | 113 + ggml/src/ggml-opencl/kernels/fill.cl | 17 + .../src/ggml-opencl/kernels/flash_attn_f16.cl | 421 + .../src/ggml-opencl/kernels/flash_attn_f32.cl | 422 + .../ggml-opencl/kernels/flash_attn_f32_f16.cl | 2656 + .../kernels/flash_attn_f32_q4_0.cl | 2011 + .../kernels/flash_attn_f32_q8_0.cl | 1840 + .../ggml-opencl/kernels/flash_attn_pre_f16.cl | 156 + .../ggml-opencl/kernels/gated_delta_net.cl | 249 + ggml/src/ggml-opencl/kernels/gelu.cl | 89 + .../ggml-opencl/kernels/gemm_moe_mxfp4_f32.cl | 162 + .../kernels/gemm_moe_mxfp4_f32_ns.cl | 376 + .../kernels/gemm_moe_mxfp4_q8_1_dp4a.cl | 190 + .../kernels/gemm_moe_q4_0_f32_ns.cl | 324 + .../kernels/gemm_moe_q4_0_q8_1_dp4a.cl | 169 + .../kernels/gemm_moe_q4_1_f32_ns.cl | 326 + .../kernels/gemm_moe_q4_k_f32_ns.cl | 348 + .../kernels/gemm_moe_q4_k_q8_1_dp4a.cl | 209 + .../kernels/gemm_moe_q5_0_f32_ns.cl | 328 + .../kernels/gemm_moe_q5_1_f32_ns.cl | 330 + .../kernels/gemm_moe_q5_k_f32_ns.cl | 356 + .../kernels/gemm_moe_q6_k_f32_ns.cl | 335 + .../kernels/gemm_moe_q6_k_q8_1_dp4a.cl | 200 + .../kernels/gemm_moe_q8_0_f32_ns.cl | 221 + .../ggml-opencl/kernels/gemm_moe_q8_1_dp4a.cl | 226 + .../kernels/gemm_noshuffle_iq4_nl_f32.cl | 150 + .../gemm_noshuffle_iq4_nl_q8_1_dp4a.cl | 143 + .../kernels/gemm_noshuffle_q1_0_f32.cl | 94 + .../kernels/gemm_noshuffle_q4_0_f32.cl | 139 + .../kernels/gemm_noshuffle_q4_0_q8_1_dp4a.cl | 127 + .../kernels/gemm_noshuffle_q4_1_f32.cl | 132 + .../kernels/gemm_noshuffle_q4_k_f32.cl | 490 + .../kernels/gemm_noshuffle_q4_k_q8_1_dp4a.cl | 281 + .../kernels/gemm_noshuffle_q5_0_f32.cl | 131 + .../kernels/gemm_noshuffle_q5_0_q8_1_dp4a.cl | 235 + .../kernels/gemm_noshuffle_q5_1_f32.cl | 134 + .../kernels/gemm_noshuffle_q5_k_f32.cl | 176 + .../kernels/gemm_noshuffle_q5_k_q8_1_dp4a.cl | 164 + .../kernels/gemm_noshuffle_q6_k_f32.cl | 245 + .../kernels/gemm_noshuffle_q6_k_f32_tiled.cl | 136 + .../kernels/gemm_noshuffle_q6_k_q8_1_dp4a.cl | 144 + .../kernels/gemm_noshuffle_q8_0_f32.cl | 129 + .../kernels/gemm_noshuffle_q8_0_q8_1_dp4a.cl | 212 + .../kernels/gemm_xmem_f16_f32_os8.cl | 233 + .../ggml-opencl/kernels/gemv_moe_mxfp4_f32.cl | 156 + .../kernels/gemv_moe_mxfp4_f32_ns.cl | 257 + .../kernels/gemv_moe_q4_0_f32_ns.cl | 120 + .../kernels/gemv_moe_q4_1_f32_ns.cl | 123 + .../kernels/gemv_moe_q4_k_f32_ns.cl | 266 + .../kernels/gemv_moe_q5_0_f32_ns.cl | 123 + .../kernels/gemv_moe_q5_1_f32_ns.cl | 125 + .../kernels/gemv_moe_q5_k_f32_ns.cl | 160 + .../kernels/gemv_moe_q6_k_f32_ns.cl | 141 + .../kernels/gemv_noshuffle_iq4_nl_f32.cl | 307 + .../kernels/gemv_noshuffle_q1_0_f32.cl | 125 + .../kernels/gemv_noshuffle_q4_0_f32.cl | 383 + .../gemv_noshuffle_q4_0_f32_32b_trans.cl | 137 + .../kernels/gemv_noshuffle_q4_0_f32_spec.cl | 272 + .../kernels/gemv_noshuffle_q4_1_f32.cl | 384 + .../kernels/gemv_noshuffle_q4_k_f32.cl | 823 + .../gemv_noshuffle_q4_k_f32_32b_trans.cl | 134 + .../kernels/gemv_noshuffle_q4_k_f32_o4.cl | 349 + .../kernels/gemv_noshuffle_q4_k_f32_tiled.cl | 118 + .../kernels/gemv_noshuffle_q5_0_f32.cl | 296 + .../kernels/gemv_noshuffle_q5_1_f32.cl | 299 + .../kernels/gemv_noshuffle_q5_k_f32.cl | 453 + .../kernels/gemv_noshuffle_q6_k_f32.cl | 409 + .../kernels/gemv_noshuffle_q6_k_f32_o4.cl | 372 + .../kernels/gemv_noshuffle_q6_k_f32_tiled.cl | 196 + .../kernels/gemv_noshuffle_q8_0_f32.cl | 280 + ggml/src/ggml-opencl/kernels/get_rows.cl | 193 + ggml/src/ggml-opencl/kernels/glu.cl | 443 + ggml/src/ggml-opencl/kernels/group_norm.cl | 121 + ggml/src/ggml-opencl/kernels/im2col_f16.cl | 57 + ggml/src/ggml-opencl/kernels/im2col_f32.cl | 57 + ggml/src/ggml-opencl/kernels/l2_norm.cl | 71 + ggml/src/ggml-opencl/kernels/mean.cl | 140 + .../src/ggml-opencl/kernels/moe_add_id_glu.cl | 76 + ggml/src/ggml-opencl/kernels/moe_combine.cl | 79 + ggml/src/ggml-opencl/kernels/moe_reorder_b.cl | 30 + .../kernels/moe_reorder_quant_a_q8_1.cl | 64 + .../ggml-opencl/kernels/moe_sort_by_expert.cl | 155 + ggml/src/ggml-opencl/kernels/mul.cl | 152 + .../ggml-opencl/kernels/mul_mat_f16_f32.cl | 130 + .../kernels/mul_mm_f16_f32_kq_kqv.cl | 273 + .../kernels/mul_mm_f16_f32_l4_lm.cl | 146 + .../kernels/mul_mm_f32_f32_l4_lm.cl | 196 + .../kernels/mul_mm_iq4_nl_f32_l4_lm.cl | 171 + .../kernels/mul_mm_q1_0_f32_l4_lm.cl | 156 + .../kernels/mul_mm_q4_0_f32_l4_lm.cl | 163 + .../kernels/mul_mm_q4_1_f32_l4_lm.cl | 165 + .../kernels/mul_mm_q4_k_f32_l4_lm.cl | 189 + .../kernels/mul_mm_q5_0_f32_l4_lm.cl | 173 + .../kernels/mul_mm_q5_1_f32_l4_lm.cl | 175 + .../kernels/mul_mm_q5_k_f32_l4_lm.cl | 202 + .../kernels/mul_mm_q6_k_f32_l4_lm.cl | 158 + .../kernels/mul_mm_q8_0_f32_l4_lm.cl | 154 + .../src/ggml-opencl/kernels/mul_mv_f16_f16.cl | 125 + .../src/ggml-opencl/kernels/mul_mv_f16_f32.cl | 125 + .../kernels/mul_mv_f16_f32_1row.cl | 101 + .../ggml-opencl/kernels/mul_mv_f16_f32_l4.cl | 1237 + .../kernels/mul_mv_f16_f32_mrow.cl | 306 + .../src/ggml-opencl/kernels/mul_mv_f32_f32.cl | 118 + .../kernels/mul_mv_id_mxfp4_f32.cl | 189 + .../kernels/mul_mv_id_mxfp4_f32_flat.cl | 176 + .../kernels/mul_mv_id_q4_0_f32_8x_flat.cl | 283 + .../ggml-opencl/kernels/mul_mv_id_q8_0_f32.cl | 140 + .../kernels/mul_mv_id_q8_0_f32_flat.cl | 222 + .../ggml-opencl/kernels/mul_mv_iq4_nl_f32.cl | 164 + .../kernels/mul_mv_iq4_nl_f32_flat.cl | 202 + .../ggml-opencl/kernels/mul_mv_mxfp4_f32.cl | 144 + .../kernels/mul_mv_mxfp4_f32_flat.cl | 167 + .../ggml-opencl/kernels/mul_mv_q1_0_f32.cl | 141 + .../kernels/mul_mv_q1_0_f32_flat.cl | 190 + .../ggml-opencl/kernels/mul_mv_q4_0_f32.cl | 192 + .../kernels/mul_mv_q4_0_f32_1d_16x_flat.cl | 307 + .../kernels/mul_mv_q4_0_f32_1d_8x_flat.cl | 265 + .../kernels/mul_mv_q4_0_f32_8x_flat.cl | 272 + .../ggml-opencl/kernels/mul_mv_q4_0_f32_v.cl | 254 + .../ggml-opencl/kernels/mul_mv_q4_1_f32.cl | 219 + .../kernels/mul_mv_q4_1_f32_flat.cl | 229 + .../ggml-opencl/kernels/mul_mv_q4_k_f32.cl | 182 + .../kernels/mul_mv_q4_k_f32_flat.cl | 205 + .../ggml-opencl/kernels/mul_mv_q5_0_f32.cl | 241 + .../kernels/mul_mv_q5_0_f32_flat.cl | 243 + .../ggml-opencl/kernels/mul_mv_q5_1_f32.cl | 243 + .../kernels/mul_mv_q5_1_f32_flat.cl | 247 + .../ggml-opencl/kernels/mul_mv_q5_k_f32.cl | 187 + .../kernels/mul_mv_q5_k_f32_flat.cl | 244 + .../ggml-opencl/kernels/mul_mv_q6_k_f32.cl | 194 + .../kernels/mul_mv_q6_k_f32_flat.cl | 272 + .../ggml-opencl/kernels/mul_mv_q8_0_f32.cl | 125 + .../kernels/mul_mv_q8_0_f32_flat.cl | 202 + ggml/src/ggml-opencl/kernels/neg.cl | 125 + ggml/src/ggml-opencl/kernels/norm.cl | 164 + ggml/src/ggml-opencl/kernels/pad.cl | 39 + ggml/src/ggml-opencl/kernels/quant_a_q8_1.cl | 42 + ggml/src/ggml-opencl/kernels/relu.cl | 16 + ggml/src/ggml-opencl/kernels/repeat.cl | 38 + ggml/src/ggml-opencl/kernels/rms_norm.cl | 369 + ggml/src/ggml-opencl/kernels/rope.cl | 759 + ggml/src/ggml-opencl/kernels/scale.cl | 27 + .../kernels/sdpa_xmem_f32_f16_os8.cl | 871 + ggml/src/ggml-opencl/kernels/set_rows.cl | 708 + ggml/src/ggml-opencl/kernels/sigmoid.cl | 29 + ggml/src/ggml-opencl/kernels/silu.cl | 30 + ggml/src/ggml-opencl/kernels/softmax_4_f16.cl | 108 + ggml/src/ggml-opencl/kernels/softmax_4_f32.cl | 108 + ggml/src/ggml-opencl/kernels/softmax_f16.cl | 107 + ggml/src/ggml-opencl/kernels/softmax_f32.cl | 107 + ggml/src/ggml-opencl/kernels/softplus.cl | 116 + ggml/src/ggml-opencl/kernels/solve_tri.cl | 51 + ggml/src/ggml-opencl/kernels/sqr.cl | 53 + ggml/src/ggml-opencl/kernels/sqrt.cl | 53 + ggml/src/ggml-opencl/kernels/ssm_conv.cl | 77 + ggml/src/ggml-opencl/kernels/ssm_scan.cl | 216 + ggml/src/ggml-opencl/kernels/sub.cl | 138 + ggml/src/ggml-opencl/kernels/sum_rows.cl | 140 + ggml/src/ggml-opencl/kernels/tanh.cl | 109 + ggml/src/ggml-opencl/kernels/transpose.cl | 143 + ggml/src/ggml-opencl/kernels/tri.cl | 32 + ggml/src/ggml-opencl/kernels/tsembd.cl | 48 + ggml/src/ggml-opencl/kernels/unary_ext.cl | 85 + ggml/src/ggml-opencl/kernels/upscale.cl | 120 + ggml/src/ggml-opencl/libdl.h | 79 + ggml/src/ggml-openvino/.clang-format | 149 + ggml/src/ggml-openvino/CMakeLists.txt | 22 + ggml/src/ggml-openvino/ggml-decoder.cpp | 2057 + ggml/src/ggml-openvino/ggml-decoder.h | 417 + .../src/ggml-openvino/ggml-openvino-extra.cpp | 493 + ggml/src/ggml-openvino/ggml-openvino-extra.h | 216 + ggml/src/ggml-openvino/ggml-openvino.cpp | 1570 + ggml/src/ggml-openvino/ggml-quants.cpp | 1273 + ggml/src/ggml-openvino/ggml-quants.h | 186 + ggml/src/ggml-openvino/model-cache.cpp | 272 + ggml/src/ggml-openvino/model-cache.h | 56 + ggml/src/ggml-openvino/openvino/decoder.h | 133 + ggml/src/ggml-openvino/openvino/frontend.cpp | 27 + ggml/src/ggml-openvino/openvino/frontend.h | 23 + .../ggml-openvino/openvino/input_model.cpp | 17 + ggml/src/ggml-openvino/openvino/input_model.h | 29 + .../src/ggml-openvino/openvino/node_context.h | 171 + ggml/src/ggml-openvino/openvino/op/add.cpp | 45 + ggml/src/ggml-openvino/openvino/op/add_id.cpp | 76 + .../src/ggml-openvino/openvino/op/argsort.cpp | 47 + ggml/src/ggml-openvino/openvino/op/clamp.cpp | 33 + ggml/src/ggml-openvino/openvino/op/concat.cpp | 48 + ggml/src/ggml-openvino/openvino/op/cont.cpp | 40 + ggml/src/ggml-openvino/openvino/op/cpy.cpp | 295 + ggml/src/ggml-openvino/openvino/op/cumsum.cpp | 29 + ggml/src/ggml-openvino/openvino/op/diag.cpp | 58 + ggml/src/ggml-openvino/openvino/op/div.cpp | 146 + ggml/src/ggml-openvino/openvino/op/fill.cpp | 34 + .../openvino/op/flash_attn_ext.cpp | 241 + .../openvino/op/gated_delta_net.cpp | 327 + .../openvino/op/gated_delta_net.hpp | 65 + .../openvino/op/gather_matmul.hpp | 43 + .../ggml-openvino/openvino/op/get_rows.cpp | 142 + .../ggml-openvino/openvino/op/glu_geglu.cpp | 75 + .../openvino/op/glu_geglu_quick.cpp | 64 + .../ggml-openvino/openvino/op/glu_swiglu.cpp | 110 + ggml/src/ggml-openvino/openvino/op/im2col.cpp | 120 + .../src/ggml-openvino/openvino/op/l2_norm.cpp | 61 + .../ggml-openvino/openvino/op/mul_mat_id.cpp | 283 + ggml/src/ggml-openvino/openvino/op/mulmat.cpp | 100 + ggml/src/ggml-openvino/openvino/op/norm.cpp | 58 + ggml/src/ggml-openvino/openvino/op/pad.cpp | 95 + .../src/ggml-openvino/openvino/op/permute.cpp | 147 + .../src/ggml-openvino/openvino/op/pool_2d.cpp | 53 + ggml/src/ggml-openvino/openvino/op/repeat.cpp | 48 + .../src/ggml-openvino/openvino/op/reshape.cpp | 113 + .../ggml-openvino/openvino/op/rms_norm.cpp | 81 + ggml/src/ggml-openvino/openvino/op/roll.cpp | 36 + ggml/src/ggml-openvino/openvino/op/rope.cpp | 303 + ggml/src/ggml-openvino/openvino/op/scale.cpp | 86 + ggml/src/ggml-openvino/openvino/op/set.cpp | 76 + .../ggml-openvino/openvino/op/set_rows.cpp | 95 + .../src/ggml-openvino/openvino/op/softmax.cpp | 166 + .../ggml-openvino/openvino/op/solve_tri.cpp | 108 + ggml/src/ggml-openvino/openvino/op/sqr.cpp | 35 + .../ggml-openvino/openvino/op/ssm_conv.cpp | 61 + .../ggml-openvino/openvino/op/sum_rows.cpp | 27 + .../ggml-openvino/openvino/op/transpose.cpp | 54 + ggml/src/ggml-openvino/openvino/op/tri.cpp | 82 + .../ggml-openvino/openvino/op/unary_silu.cpp | 27 + .../openvino/op/unary_softplus.cpp | 38 + ggml/src/ggml-openvino/openvino/op/view.cpp | 245 + ggml/src/ggml-openvino/openvino/op_table.cpp | 88 + ggml/src/ggml-openvino/openvino/op_table.h | 67 + .../openvino/pass/fuse_to_conv.cpp | 212 + .../openvino/pass/fuse_to_conv.h | 17 + .../openvino/pass/fuse_to_sdpa.cpp | 60 + .../openvino/pass/fuse_to_sdpa.h | 17 + ...k_decompression_convert_constant_folding.h | 29 + .../pass/mark_dequantization_subgraph.h | 44 + .../openvino/pass/squeeze_matmul.cpp | 58 + .../openvino/pass/squeeze_matmul.h | 17 + .../rt_info/weightless_caching_attributes.hpp | 41 + .../openvino/translate_session.cpp | 432 + .../openvino/translate_session.h | 29 + ggml/src/ggml-openvino/openvino/utils.cpp | 886 + ggml/src/ggml-openvino/openvino/utils.h | 88 + ggml/src/ggml-openvino/utils.cpp | 1496 + ggml/src/ggml-openvino/utils.h | 195 + ggml/src/ggml-opt.cpp | 1094 + ggml/src/ggml-quants.c | 5667 + ggml/src/ggml-quants.h | 115 + ggml/src/ggml-rpc/CMakeLists.txt | 51 + ggml/src/ggml-rpc/ggml-rpc.cpp | 2351 + ggml/src/ggml-rpc/transport-apple.cpp | 481 + ggml/src/ggml-rpc/transport-apple.h | 27 + ggml/src/ggml-rpc/transport.cpp | 739 + ggml/src/ggml-rpc/transport.h | 38 + ggml/src/ggml-sycl/CMakeLists.txt | 224 + ggml/src/ggml-sycl/add-id.cpp | 81 + ggml/src/ggml-sycl/add-id.hpp | 8 + ggml/src/ggml-sycl/backend.hpp | 53 + ggml/src/ggml-sycl/base.hpp | 43 + ggml/src/ggml-sycl/binbcast.cpp | 650 + ggml/src/ggml-sycl/binbcast.hpp | 69 + ggml/src/ggml-sycl/col2im-1d.cpp | 102 + ggml/src/ggml-sycl/col2im-1d.hpp | 8 + ggml/src/ggml-sycl/common.cpp | 162 + ggml/src/ggml-sycl/common.hpp | 1014 + ggml/src/ggml-sycl/concat.cpp | 509 + ggml/src/ggml-sycl/concat.hpp | 20 + ggml/src/ggml-sycl/conv.cpp | 101 + ggml/src/ggml-sycl/conv.hpp | 20 + ggml/src/ggml-sycl/conv2d-dw.cpp | 170 + ggml/src/ggml-sycl/conv2d-dw.hpp | 10 + ggml/src/ggml-sycl/conv2d-transpose.cpp | 125 + ggml/src/ggml-sycl/conv2d-transpose.hpp | 10 + ggml/src/ggml-sycl/conv2d.cpp | 150 + ggml/src/ggml-sycl/conv2d.hpp | 10 + ggml/src/ggml-sycl/conv3d.cpp | 224 + ggml/src/ggml-sycl/conv3d.hpp | 8 + ggml/src/ggml-sycl/convert.cpp | 877 + ggml/src/ggml-sycl/convert.hpp | 64 + ggml/src/ggml-sycl/count-equal.cpp | 79 + ggml/src/ggml-sycl/count-equal.hpp | 9 + ggml/src/ggml-sycl/cpy.cpp | 1433 + ggml/src/ggml-sycl/cpy.hpp | 537 + ggml/src/ggml-sycl/cross_entropy_loss.cpp | 255 + ggml/src/ggml-sycl/cross_entropy_loss.hpp | 7 + ggml/src/ggml-sycl/cumsum.cpp | 148 + ggml/src/ggml-sycl/cumsum.hpp | 5 + ggml/src/ggml-sycl/dequantize.hpp | 1681 + ggml/src/ggml-sycl/diag.cpp | 67 + ggml/src/ggml-sycl/diag.hpp | 5 + ggml/src/ggml-sycl/dmmv.cpp | 2227 + ggml/src/ggml-sycl/dmmv.hpp | 27 + ggml/src/ggml-sycl/dpct/helper.hpp | 3782 + ggml/src/ggml-sycl/dsv4-hc.cpp | 280 + ggml/src/ggml-sycl/dsv4-hc.hpp | 10 + ggml/src/ggml-sycl/element_wise.cpp | 1432 + ggml/src/ggml-sycl/element_wise.hpp | 135 + ggml/src/ggml-sycl/esimd.hpp | 589 + ggml/src/ggml-sycl/fattn-buffers.cpp | 60 + ggml/src/ggml-sycl/fattn-buffers.hpp | 63 + ggml/src/ggml-sycl/fattn-common.hpp | 1185 + ggml/src/ggml-sycl/fattn-mkl.cpp | 689 + ggml/src/ggml-sycl/fattn-onednn.cpp | 450 + ggml/src/ggml-sycl/fattn-onednn.hpp | 18 + ggml/src/ggml-sycl/fattn-tile.cpp | 59 + ggml/src/ggml-sycl/fattn-tile.hpp | 1246 + ggml/src/ggml-sycl/fattn-vec.hpp | 684 + ggml/src/ggml-sycl/fattn.cpp | 452 + ggml/src/ggml-sycl/fattn.hpp | 42 + ggml/src/ggml-sycl/fill.cpp | 55 + ggml/src/ggml-sycl/fill.hpp | 5 + ggml/src/ggml-sycl/fusion.cpp | 212 + ggml/src/ggml-sycl/fusion.hpp | 17 + ggml/src/ggml-sycl/fwht.cpp | 291 + ggml/src/ggml-sycl/fwht.hpp | 12 + ggml/src/ggml-sycl/gated_delta_net.cpp | 366 + ggml/src/ggml-sycl/gated_delta_net.hpp | 19 + ggml/src/ggml-sycl/gemm.hpp | 95 + ggml/src/ggml-sycl/getrows.cpp | 368 + ggml/src/ggml-sycl/getrows.hpp | 20 + ggml/src/ggml-sycl/ggml-sycl.cpp | 7176 ++ ggml/src/ggml-sycl/gla.cpp | 106 + ggml/src/ggml-sycl/gla.hpp | 8 + ggml/src/ggml-sycl/im2col.cpp | 400 + ggml/src/ggml-sycl/im2col.hpp | 23 + ggml/src/ggml-sycl/lightning-indexer.cpp | 197 + ggml/src/ggml-sycl/lightning-indexer.hpp | 8 + ggml/src/ggml-sycl/mem.cpp | 151 + ggml/src/ggml-sycl/mem.hpp | 16 + ggml/src/ggml-sycl/memtrace.cpp | 194 + ggml/src/ggml-sycl/memtrace.hpp | 28 + ggml/src/ggml-sycl/mmq.cpp | 3030 + ggml/src/ggml-sycl/mmq.hpp | 33 + ggml/src/ggml-sycl/mmvq.cpp | 3106 + ggml/src/ggml-sycl/mmvq.hpp | 76 + ggml/src/ggml-sycl/norm.cpp | 1046 + ggml/src/ggml-sycl/norm.hpp | 35 + ggml/src/ggml-sycl/opt-step.cpp | 131 + ggml/src/ggml-sycl/opt-step.hpp | 6 + ggml/src/ggml-sycl/outprod.cpp | 83 + ggml/src/ggml-sycl/outprod.hpp | 10 + ggml/src/ggml-sycl/pad.cpp | 97 + ggml/src/ggml-sycl/pad.hpp | 24 + ggml/src/ggml-sycl/pad_reflect_1d.cpp | 100 + ggml/src/ggml-sycl/pad_reflect_1d.hpp | 10 + ggml/src/ggml-sycl/pool.cpp | 185 + ggml/src/ggml-sycl/pool.hpp | 22 + ggml/src/ggml-sycl/presets.hpp | 79 + ggml/src/ggml-sycl/quantize.hpp | 133 + ggml/src/ggml-sycl/quants.hpp | 204 + ggml/src/ggml-sycl/repeat_back.cpp | 76 + ggml/src/ggml-sycl/repeat_back.hpp | 8 + ggml/src/ggml-sycl/roll.cpp | 122 + ggml/src/ggml-sycl/roll.hpp | 20 + ggml/src/ggml-sycl/rope.cpp | 651 + ggml/src/ggml-sycl/rope.hpp | 26 + ggml/src/ggml-sycl/set.cpp | 73 + ggml/src/ggml-sycl/set.hpp | 5 + ggml/src/ggml-sycl/set_rows.cpp | 577 + ggml/src/ggml-sycl/set_rows.hpp | 8 + ggml/src/ggml-sycl/softmax.cpp | 425 + ggml/src/ggml-sycl/softmax.hpp | 24 + ggml/src/ggml-sycl/solve_tri.cpp | 172 + ggml/src/ggml-sycl/solve_tri.hpp | 8 + ggml/src/ggml-sycl/ssm_conv.cpp | 136 + ggml/src/ggml-sycl/ssm_conv.hpp | 5 + ggml/src/ggml-sycl/ssm_scan.cpp | 170 + ggml/src/ggml-sycl/ssm_scan.hpp | 5 + ggml/src/ggml-sycl/sycl_hw.cpp | 67 + ggml/src/ggml-sycl/sycl_hw.hpp | 38 + .../fattn-tile-instance-dkq112-dv112.cpp | 5 + .../fattn-tile-instance-dkq128-dv128.cpp | 5 + .../fattn-tile-instance-dkq256-dv256.cpp | 5 + .../fattn-tile-instance-dkq40-dv40.cpp | 5 + .../fattn-tile-instance-dkq512-dv512.cpp | 6 + .../fattn-tile-instance-dkq576-dv512.cpp | 5 + .../fattn-tile-instance-dkq64-dv64.cpp | 5 + .../fattn-tile-instance-dkq72-dv72.cpp | 5 + .../fattn-tile-instance-dkq80-dv80.cpp | 5 + .../fattn-tile-instance-dkq96-dv96.cpp | 5 + .../fattn-vec-instance-f16-f16.cpp | 8 + .../fattn-vec-instance-f16-q4_0.cpp | 8 + .../fattn-vec-instance-f16-q4_1.cpp | 8 + .../fattn-vec-instance-f16-q5_0.cpp | 8 + .../fattn-vec-instance-f16-q5_1.cpp | 8 + .../fattn-vec-instance-f16-q8_0.cpp | 8 + .../fattn-vec-instance-q4_0-f16.cpp | 8 + .../fattn-vec-instance-q4_0-q4_0.cpp | 8 + .../fattn-vec-instance-q4_0-q4_1.cpp | 8 + .../fattn-vec-instance-q4_0-q5_0.cpp | 8 + .../fattn-vec-instance-q4_0-q5_1.cpp | 8 + .../fattn-vec-instance-q4_0-q8_0.cpp | 8 + .../fattn-vec-instance-q4_1-f16.cpp | 8 + .../fattn-vec-instance-q4_1-q4_0.cpp | 8 + .../fattn-vec-instance-q4_1-q4_1.cpp | 8 + .../fattn-vec-instance-q4_1-q5_0.cpp | 8 + .../fattn-vec-instance-q4_1-q5_1.cpp | 8 + .../fattn-vec-instance-q4_1-q8_0.cpp | 8 + .../fattn-vec-instance-q5_0-f16.cpp | 8 + .../fattn-vec-instance-q5_0-q4_0.cpp | 8 + .../fattn-vec-instance-q5_0-q4_1.cpp | 8 + .../fattn-vec-instance-q5_0-q5_0.cpp | 8 + .../fattn-vec-instance-q5_0-q5_1.cpp | 8 + .../fattn-vec-instance-q5_0-q8_0.cpp | 8 + .../fattn-vec-instance-q5_1-f16.cpp | 8 + .../fattn-vec-instance-q5_1-q4_0.cpp | 8 + .../fattn-vec-instance-q5_1-q4_1.cpp | 8 + .../fattn-vec-instance-q5_1-q5_0.cpp | 8 + .../fattn-vec-instance-q5_1-q5_1.cpp | 8 + .../fattn-vec-instance-q5_1-q8_0.cpp | 8 + .../fattn-vec-instance-q8_0-f16.cpp | 8 + .../fattn-vec-instance-q8_0-q4_0.cpp | 8 + .../fattn-vec-instance-q8_0-q4_1.cpp | 8 + .../fattn-vec-instance-q8_0-q5_0.cpp | 8 + .../fattn-vec-instance-q8_0-q5_1.cpp | 8 + .../fattn-vec-instance-q8_0-q8_0.cpp | 8 + ggml/src/ggml-sycl/topk-moe.cpp | 620 + ggml/src/ggml-sycl/topk-moe.hpp | 12 + ggml/src/ggml-sycl/topk-radix.cpp | 531 + ggml/src/ggml-sycl/topk-radix.hpp | 24 + ggml/src/ggml-sycl/tsembd.cpp | 73 + ggml/src/ggml-sycl/tsembd.hpp | 20 + ggml/src/ggml-sycl/type.hpp | 112 + ggml/src/ggml-sycl/upscale.cpp | 410 + ggml/src/ggml-sycl/upscale.hpp | 9 + ggml/src/ggml-sycl/vecdotq.hpp | 1747 + ggml/src/ggml-sycl/wkv.cpp | 293 + ggml/src/ggml-sycl/wkv.hpp | 10 + ggml/src/ggml-threading.cpp | 12 + ggml/src/ggml-threading.h | 14 + ggml/src/ggml-version.h.in | 4 + ggml/src/ggml-virtgpu/CMakeLists.txt | 70 + .../ggml-virtgpu/apir_cs_ggml-rpc-front.cpp | 87 + ggml/src/ggml-virtgpu/backend/CMakeLists.txt | 21 + .../backend/apir_cs_ggml-rpc-back.cpp | 115 + .../ggml-virtgpu/backend/backend-convert.h | 13 + .../backend/backend-dispatched-backend.cpp | 102 + .../backend-dispatched-buffer-type.cpp | 105 + .../backend/backend-dispatched-buffer.cpp | 179 + .../backend/backend-dispatched-device.cpp | 149 + .../backend/backend-dispatched.cpp | 51 + .../backend/backend-dispatched.gen.h | 73 + .../ggml-virtgpu/backend/backend-dispatched.h | 27 + .../ggml-virtgpu/backend/backend-virgl-apir.h | 32 + ggml/src/ggml-virtgpu/backend/backend.cpp | 144 + .../backend/shared/api_remoting.h | 95 + .../backend/shared/apir_backend.gen.h | 94 + .../backend/shared/apir_backend.h | 50 + .../src/ggml-virtgpu/backend/shared/apir_cs.h | 378 + .../backend/shared/apir_cs_ggml.h | 232 + .../ggml-virtgpu/backend/shared/apir_cs_rpc.h | 58 + .../ggml-virtgpu/ggml-backend-buffer-type.cpp | 81 + ggml/src/ggml-virtgpu/ggml-backend-buffer.cpp | 123 + ggml/src/ggml-virtgpu/ggml-backend-device.cpp | 160 + ggml/src/ggml-virtgpu/ggml-backend-reg.cpp | 213 + ggml/src/ggml-virtgpu/ggml-backend.cpp | 72 + ggml/src/ggml-virtgpu/ggml-remoting.h | 71 + .../ggml-virtgpu/ggmlremoting_functions.yaml | 166 + ggml/src/ggml-virtgpu/include/apir_hw.h | 9 + ggml/src/ggml-virtgpu/regenerate_remoting.py | 333 + ggml/src/ggml-virtgpu/virtgpu-apir.h | 15 + .../ggml-virtgpu/virtgpu-forward-backend.cpp | 58 + .../virtgpu-forward-buffer-type.cpp | 110 + .../ggml-virtgpu/virtgpu-forward-buffer.cpp | 173 + .../ggml-virtgpu/virtgpu-forward-device.cpp | 194 + ggml/src/ggml-virtgpu/virtgpu-forward-impl.h | 36 + ggml/src/ggml-virtgpu/virtgpu-forward.gen.h | 54 + ggml/src/ggml-virtgpu/virtgpu-shm.cpp | 99 + ggml/src/ggml-virtgpu/virtgpu-shm.h | 23 + ggml/src/ggml-virtgpu/virtgpu-utils.cpp | 179 + ggml/src/ggml-virtgpu/virtgpu-utils.h | 86 + ggml/src/ggml-virtgpu/virtgpu.cpp | 545 + ggml/src/ggml-virtgpu/virtgpu.h | 115 + ggml/src/ggml-vulkan/CMakeLists.txt | 254 + .../ggml-vulkan/cmake/host-toolchain.cmake.in | 15 + ggml/src/ggml-vulkan/ggml-vulkan.cpp | 20964 ++++ .../ggml-vulkan/vulkan-shaders/CMakeLists.txt | 43 + ggml/src/ggml-vulkan/vulkan-shaders/acc.comp | 37 + ggml/src/ggml-vulkan/vulkan-shaders/add.comp | 69 + ggml/src/ggml-vulkan/vulkan-shaders/add1.comp | 28 + .../ggml-vulkan/vulkan-shaders/add_id.comp | 42 + .../ggml-vulkan/vulkan-shaders/arange.comp | 20 + .../ggml-vulkan/vulkan-shaders/argmax.comp | 60 + .../ggml-vulkan/vulkan-shaders/argsort.comp | 92 + .../vulkan-shaders/argsort_large.comp | 117 + .../ggml-vulkan/vulkan-shaders/col2im_1d.comp | 61 + .../ggml-vulkan/vulkan-shaders/concat.comp | 41 + .../vulkan-shaders/contig_copy.comp | 53 + .../ggml-vulkan/vulkan-shaders/conv2d_dw.comp | 105 + .../ggml-vulkan/vulkan-shaders/conv2d_mm.comp | 473 + .../ggml-vulkan/vulkan-shaders/conv3d_mm.comp | 424 + .../vulkan-shaders/conv_transpose_1d.comp | 98 + ggml/src/ggml-vulkan/vulkan-shaders/copy.comp | 25 + .../vulkan-shaders/copy_from_quant.comp | 51 + .../vulkan-shaders/copy_to_quant.comp | 350 + .../vulkan-shaders/copy_transpose.comp | 67 + .../vulkan-shaders/copy_transpose_02.comp | 61 + .../vulkan-shaders/count_equal.comp | 31 + .../vulkan-shaders/count_experts.comp | 135 + .../vulkan-shaders/cross_entropy_loss.comp | 78 + .../cross_entropy_loss_back.comp | 75 + .../ggml-vulkan/vulkan-shaders/cumsum.comp | 83 + .../vulkan-shaders/cumsum_multipass1.comp | 60 + .../vulkan-shaders/cumsum_multipass2.comp | 66 + .../vulkan-shaders/dequant_f32.comp | 20 + .../vulkan-shaders/dequant_funcs.glsl | 756 + .../vulkan-shaders/dequant_funcs_cm2.glsl | 1495 + .../vulkan-shaders/dequant_head.glsl | 13 + .../vulkan-shaders/dequant_iq1_m.comp | 42 + .../vulkan-shaders/dequant_iq1_s.comp | 35 + .../vulkan-shaders/dequant_iq2_s.comp | 44 + .../vulkan-shaders/dequant_iq2_xs.comp | 43 + .../vulkan-shaders/dequant_iq2_xxs.comp | 49 + .../vulkan-shaders/dequant_iq3_s.comp | 40 + .../vulkan-shaders/dequant_iq3_xxs.comp | 51 + .../vulkan-shaders/dequant_iq4_nl.comp | 32 + .../vulkan-shaders/dequant_iq4_xs.comp | 34 + .../vulkan-shaders/dequant_mxfp4.comp | 32 + .../vulkan-shaders/dequant_nvfp4.comp | 32 + .../vulkan-shaders/dequant_q1_0.comp | 29 + .../vulkan-shaders/dequant_q2_0.comp | 29 + .../vulkan-shaders/dequant_q2_k.comp | 34 + .../vulkan-shaders/dequant_q3_k.comp | 42 + .../vulkan-shaders/dequant_q4_0.comp | 30 + .../vulkan-shaders/dequant_q4_1.comp | 32 + .../vulkan-shaders/dequant_q4_k.comp | 68 + .../vulkan-shaders/dequant_q5_0.comp | 34 + .../vulkan-shaders/dequant_q5_1.comp | 35 + .../vulkan-shaders/dequant_q5_k.comp | 70 + .../vulkan-shaders/dequant_q6_k.comp | 33 + .../vulkan-shaders/dequant_q8_0.comp | 42 + .../vulkan-shaders/dequant_tq1_0.comp | 28 + .../vulkan-shaders/dequant_tq2_0.comp | 31 + ggml/src/ggml-vulkan/vulkan-shaders/diag.comp | 28 + .../vulkan-shaders/diag_mask_inf.comp | 34 + ggml/src/ggml-vulkan/vulkan-shaders/div.comp | 27 + .../vulkan-shaders/dot_product_funcs.glsl | 27 + .../vulkan-shaders/dsv4_hc_comb.comp | 90 + .../vulkan-shaders/dsv4_hc_post.comp | 83 + .../vulkan-shaders/dsv4_hc_pre.comp | 59 + .../ggml-vulkan/vulkan-shaders/fa_types.glsl | 45 + .../feature-tests/bfloat16.comp | 7 + .../vulkan-shaders/feature-tests/coopmat.comp | 7 + .../feature-tests/coopmat2.comp | 7 + .../feature-tests/coopmat2_decode_vector.comp | 7 + .../feature-tests/float_e2m1.comp | 7 + .../feature-tests/float_e4m3.comp | 7 + .../feature-tests/integer_dot.comp | 7 + ggml/src/ggml-vulkan/vulkan-shaders/fill.comp | 21 + .../vulkan-shaders/flash_attn.comp | 760 + .../vulkan-shaders/flash_attn_base.glsl | 223 + .../vulkan-shaders/flash_attn_cm1.comp | 647 + .../vulkan-shaders/flash_attn_cm2.comp | 489 + .../vulkan-shaders/flash_attn_dequant.glsl | 146 + .../vulkan-shaders/flash_attn_mask_opt.comp | 162 + .../vulkan-shaders/flash_attn_mmq_funcs.glsl | 203 + .../flash_attn_split_k_reduce.comp | 121 + ggml/src/ggml-vulkan/vulkan-shaders/fwht.comp | 115 + .../vulkan-shaders/gated_delta_net.comp | 189 + .../src/ggml-vulkan/vulkan-shaders/geglu.comp | 13 + .../ggml-vulkan/vulkan-shaders/geglu_erf.comp | 27 + .../vulkan-shaders/geglu_quick.comp | 11 + .../vulkan-shaders/generic_binary_head.glsl | 65 + .../vulkan-shaders/generic_head.glsl | 11 + .../vulkan-shaders/generic_unary_head.glsl | 75 + .../ggml-vulkan/vulkan-shaders/get_rows.comp | 42 + .../vulkan-shaders/get_rows_back.comp | 25 + .../vulkan-shaders/get_rows_quant.comp | 51 + .../vulkan-shaders/ggml_type_ids.glsl | 34 + ggml/src/ggml-vulkan/vulkan-shaders/gla.comp | 82 + .../ggml-vulkan/vulkan-shaders/glu_head.glsl | 43 + .../ggml-vulkan/vulkan-shaders/glu_main.glsl | 35 + .../vulkan-shaders/group_norm.comp | 66 + .../ggml-vulkan/vulkan-shaders/im2col.comp | 138 + .../ggml-vulkan/vulkan-shaders/im2col_3d.comp | 124 + .../vulkan-shaders/iq_shmem_init.glsl | 2 + .../ggml-vulkan/vulkan-shaders/l2_norm.comp | 41 + .../vulkan-shaders/lightning_indexer.comp | 151 + ggml/src/ggml-vulkan/vulkan-shaders/log.comp | 17 + ggml/src/ggml-vulkan/vulkan-shaders/mul.comp | 27 + .../mul_mat_split_k_reduce.comp | 48 + .../vulkan-shaders/mul_mat_vec.comp | 264 + .../vulkan-shaders/mul_mat_vec_base.glsl | 230 + .../vulkan-shaders/mul_mat_vec_iface.glsl | 35 + .../vulkan-shaders/mul_mat_vec_iq1_m.comp | 132 + .../vulkan-shaders/mul_mat_vec_iq1_s.comp | 95 + .../vulkan-shaders/mul_mat_vec_iq2_s.comp | 90 + .../vulkan-shaders/mul_mat_vec_iq2_xs.comp | 105 + .../vulkan-shaders/mul_mat_vec_iq2_xxs.comp | 87 + .../vulkan-shaders/mul_mat_vec_iq3_s.comp | 93 + .../vulkan-shaders/mul_mat_vec_iq3_xxs.comp | 88 + .../vulkan-shaders/mul_mat_vec_iq4_xs.comp | 97 + .../vulkan-shaders/mul_mat_vec_nc.comp | 124 + .../vulkan-shaders/mul_mat_vec_p021.comp | 156 + .../vulkan-shaders/mul_mat_vec_q2_k.comp | 128 + .../vulkan-shaders/mul_mat_vec_q3_k.comp | 132 + .../vulkan-shaders/mul_mat_vec_q4_k.comp | 134 + .../vulkan-shaders/mul_mat_vec_q5_k.comp | 165 + .../vulkan-shaders/mul_mat_vec_q6_k.comp | 130 + .../vulkan-shaders/mul_mat_vec_tq1_0.comp | 85 + .../vulkan-shaders/mul_mat_vec_tq2_0.comp | 102 + .../vulkan-shaders/mul_mat_vecq.comp | 141 + .../vulkan-shaders/mul_mat_vecq_funcs.glsl | 564 + .../ggml-vulkan/vulkan-shaders/mul_mm.comp | 544 + .../vulkan-shaders/mul_mm_cm2.comp | 779 + .../vulkan-shaders/mul_mm_funcs.glsl | 717 + .../vulkan-shaders/mul_mm_id_funcs.glsl | 89 + .../ggml-vulkan/vulkan-shaders/mul_mmq.comp | 317 + .../vulkan-shaders/mul_mmq_funcs.glsl | 488 + .../vulkan-shaders/mul_mmq_shmem_types.glsl | 99 + .../ggml-vulkan/vulkan-shaders/multi_add.comp | 194 + ggml/src/ggml-vulkan/vulkan-shaders/norm.comp | 44 + .../vulkan-shaders/opt_step_adamw.comp | 42 + .../vulkan-shaders/opt_step_sgd.comp | 22 + .../ggml-vulkan/vulkan-shaders/out_prod.comp | 59 + ggml/src/ggml-vulkan/vulkan-shaders/pad.comp | 64 + .../vulkan-shaders/pad_reflect_1d.comp | 43 + .../ggml-vulkan/vulkan-shaders/pool1d.comp | 65 + .../ggml-vulkan/vulkan-shaders/pool2d.comp | 74 + .../vulkan-shaders/quantize_q8_1.comp | 127 + .../src/ggml-vulkan/vulkan-shaders/reglu.comp | 9 + .../ggml-vulkan/vulkan-shaders/repeat.comp | 26 + .../vulkan-shaders/repeat_back.comp | 37 + .../ggml-vulkan/vulkan-shaders/rms_norm.comp | 178 + .../vulkan-shaders/rms_norm_back.comp | 55 + .../vulkan-shaders/rms_norm_partials.comp | 87 + ggml/src/ggml-vulkan/vulkan-shaders/roll.comp | 46 + .../vulkan-shaders/rope_funcs.glsl | 218 + .../ggml-vulkan/vulkan-shaders/rope_head.glsl | 19 + .../vulkan-shaders/rope_multi.comp | 17 + .../ggml-vulkan/vulkan-shaders/rope_neox.comp | 17 + .../ggml-vulkan/vulkan-shaders/rope_norm.comp | 17 + .../vulkan-shaders/rope_params.glsl | 35 + .../vulkan-shaders/rope_vision.comp | 17 + .../src/ggml-vulkan/vulkan-shaders/scale.comp | 24 + .../ggml-vulkan/vulkan-shaders/silu_back.comp | 26 + .../src/ggml-vulkan/vulkan-shaders/snake.comp | 49 + .../ggml-vulkan/vulkan-shaders/soft_max.comp | 195 + .../vulkan-shaders/soft_max_back.comp | 54 + .../vulkan-shaders/soft_max_large1.comp | 62 + .../vulkan-shaders/soft_max_large2.comp | 79 + .../vulkan-shaders/soft_max_large3.comp | 65 + .../vulkan-shaders/soft_max_large_common.glsl | 53 + .../ggml-vulkan/vulkan-shaders/solve_tri.comp | 81 + .../ggml-vulkan/vulkan-shaders/ssm_conv.comp | 60 + .../ggml-vulkan/vulkan-shaders/ssm_scan.comp | 134 + ggml/src/ggml-vulkan/vulkan-shaders/sub.comp | 29 + .../ggml-vulkan/vulkan-shaders/sum_rows.comp | 47 + .../ggml-vulkan/vulkan-shaders/sum_rows.glsl | 19 + .../ggml-vulkan/vulkan-shaders/swiglu.comp | 9 + .../vulkan-shaders/swiglu_clamp.comp | 12 + .../vulkan-shaders/swiglu_oai.comp | 14 + .../vulkan-shaders/timestep_embedding.comp | 42 + .../vulkan-shaders/topk_argsort.comp | 118 + .../ggml-vulkan/vulkan-shaders/topk_moe.comp | 221 + .../vulkan-shaders/topk_nary_search.comp | 246 + .../vulkan-shaders/topk_radix_select.comp | 144 + ggml/src/ggml-vulkan/vulkan-shaders/tri.comp | 42 + .../src/ggml-vulkan/vulkan-shaders/types.glsl | 2005 + .../src/ggml-vulkan/vulkan-shaders/unary.comp | 205 + .../ggml-vulkan/vulkan-shaders/upscale.comp | 178 + .../src/ggml-vulkan/vulkan-shaders/utils.glsl | 37 + .../vulkan-shaders/vulkan-shaders-gen.cpp | 1425 + ggml/src/ggml-vulkan/vulkan-shaders/wkv6.comp | 87 + ggml/src/ggml-vulkan/vulkan-shaders/wkv7.comp | 91 + ggml/src/ggml-webgpu/CMakeLists.txt | 89 + .../ggml-webgpu/ggml-webgpu-shader-lib.hpp | 3457 + ggml/src/ggml-webgpu/ggml-webgpu.cpp | 4809 + ggml/src/ggml-webgpu/pre_wgsl.hpp | 808 + ggml/src/ggml-webgpu/wgsl-shaders/add_id.wgsl | 64 + ggml/src/ggml-webgpu/wgsl-shaders/argmax.wgsl | 72 + .../src/ggml-webgpu/wgsl-shaders/argsort.wgsl | 102 + .../wgsl-shaders/argsort_merge.wgsl | 134 + ggml/src/ggml-webgpu/wgsl-shaders/binary.wgsl | 142 + .../wgsl-shaders/common_decls.tmpl | 967 + ggml/src/ggml-webgpu/wgsl-shaders/concat.wgsl | 92 + ggml/src/ggml-webgpu/wgsl-shaders/conv2d.wgsl | 127 + .../ggml-webgpu/wgsl-shaders/conv2d_dw.wgsl | 100 + ggml/src/ggml-webgpu/wgsl-shaders/cpy.wgsl | 84 + ggml/src/ggml-webgpu/wgsl-shaders/cumsum.wgsl | 66 + .../ggml-webgpu/wgsl-shaders/embed_wgsl.py | 89 + .../ggml-webgpu/wgsl-shaders/flash_attn.wgsl | 408 + .../wgsl-shaders/flash_attn_decls.tmpl | 134 + .../wgsl-shaders/flash_attn_staging.tmpl | 136 + .../wgsl-shaders/flash_attn_tile.wgsl | 240 + .../wgsl-shaders/flash_attn_vec_blk.wgsl | 101 + .../wgsl-shaders/flash_attn_vec_reduce.wgsl | 84 + .../wgsl-shaders/flash_attn_vec_split.wgsl | 503 + .../wgsl-shaders/gated_delta_net.wgsl | 149 + .../ggml-webgpu/wgsl-shaders/get_rows.wgsl | 794 + ggml/src/ggml-webgpu/wgsl-shaders/glu.wgsl | 178 + ggml/src/ggml-webgpu/wgsl-shaders/im2col.wgsl | 77 + ggml/src/ggml-webgpu/wgsl-shaders/memset.wgsl | 40 + .../wgsl-shaders/mul_mat_decls.tmpl | 1052 + .../ggml-webgpu/wgsl-shaders/mul_mat_id.wgsl | 195 + .../wgsl-shaders/mul_mat_id_gather.wgsl | 52 + .../wgsl-shaders/mul_mat_id_vec.wgsl | 154 + .../wgsl-shaders/mul_mat_reg_tile.wgsl | 159 + .../wgsl-shaders/mul_mat_subgroup_matrix.wgsl | 210 + .../ggml-webgpu/wgsl-shaders/mul_mat_vec.wgsl | 167 + .../wgsl-shaders/mul_mat_vec_acc.tmpl | 1560 + .../wgsl-shaders/mul_mat_vec_q_acc.tmpl | 297 + ggml/src/ggml-webgpu/wgsl-shaders/pad.wgsl | 86 + .../wgsl-shaders/quant_inner_loops.tmpl | 21 + .../ggml-webgpu/wgsl-shaders/quantize_q8.wgsl | 178 + ggml/src/ggml-webgpu/wgsl-shaders/repeat.wgsl | 70 + .../wgsl-shaders/rms_norm_mul.wgsl | 151 + ggml/src/ggml-webgpu/wgsl-shaders/rope.wgsl | 228 + .../ggml-webgpu/wgsl-shaders/row_norm.wgsl | 152 + ggml/src/ggml-webgpu/wgsl-shaders/scale.wgsl | 65 + ggml/src/ggml-webgpu/wgsl-shaders/set.wgsl | 109 + .../ggml-webgpu/wgsl-shaders/set_rows.wgsl | 108 + .../wgsl-shaders/set_rows_quant.wgsl | 224 + .../ggml-webgpu/wgsl-shaders/soft_max.wgsl | 210 + .../ggml-webgpu/wgsl-shaders/solve_tri.wgsl | 120 + .../ggml-webgpu/wgsl-shaders/ssm_conv.wgsl | 65 + .../ggml-webgpu/wgsl-shaders/ssm_scan.wgsl | 247 + .../ggml-webgpu/wgsl-shaders/sum_rows.wgsl | 55 + ggml/src/ggml-webgpu/wgsl-shaders/unary.wgsl | 213 + .../src/ggml-webgpu/wgsl-shaders/upscale.wgsl | 240 + ggml/src/ggml-zdnn/.gitignore | 1 + ggml/src/ggml-zdnn/CMakeLists.txt | 36 + ggml/src/ggml-zdnn/common.hpp | 59 + ggml/src/ggml-zdnn/ggml-zdnn.cpp | 638 + ggml/src/ggml-zdnn/mmf.cpp | 80 + ggml/src/ggml-zdnn/mmf.hpp | 12 + ggml/src/ggml-zdnn/utils.cpp | 79 + ggml/src/ggml-zdnn/utils.hpp | 19 + ggml/src/ggml-zendnn/CMakeLists.txt | 91 + ggml/src/ggml-zendnn/ggml-zendnn.cpp | 838 + ggml/src/ggml.c | 8139 ++ ggml/src/ggml.cpp | 26 + ggml/src/gguf.cpp | 1707 + grammars/assistant.gbnf | 57 + grammars/chess.gbnf | 29 + grammars/colors.gbnf | 16 + include/parakeet.h | 343 + include/whisper.h | 772 + media/matmul.png | Bin 0 -> 265705 bytes models/.gitignore | 1 + models/README.md | 111 + models/convert-h5-to-coreml.py | 117 + models/convert-h5-to-ggml.py | 218 + models/convert-parakeet-to-ggml.py | 337 + models/convert-pt-to-ggml.py | 342 + models/convert-silero-vad-to-ggml.py | 196 + models/convert-whisper-to-coreml.py | 333 + models/convert-whisper-to-openvino.py | 59 + models/download-coreml-model.sh | 102 + models/download-ggml-model.cmd | 114 + models/download-ggml-model.sh | 155 + models/download-vad-model.cmd | 99 + models/download-vad-model.sh | 105 + models/download-vitisai-model.cmd | 32 + models/download-vitisai-model.ps1 | 218 + models/download-vitisai-model.sh | 226 + models/generate-coreml-interface.sh | 31 + models/generate-coreml-model.sh | 38 + models/generate-parakeet-test-model.py | 190 + models/ggml_to_pt.py | 109 + models/requirements-coreml.txt | 4 + models/requirements-openvino.txt | 3 + models/requirements-parakeet.txt | 3 + samples/jfk.mp3 | Bin 0 -> 76447 bytes scripts/apple/validate-apps.sh | 5 + scripts/apple/validate-ios.sh | 817 + scripts/apple/validate-macos.sh | 778 + scripts/apple/validate-tvos.sh | 810 + scripts/apple/validate-visionos.sh | 808 + scripts/bench-all-gg.txt | 411 + scripts/bench-all.sh | 118 + scripts/bench-wts.sh | 70 + scripts/bench.py | 225 + scripts/build-info.sh | 30 + scripts/convert-all.sh | 8 + scripts/deploy-wasm.sh | 31 + scripts/gen-authors.sh | 9 + scripts/get-flags.mk | 38 + scripts/make-release-checks.sh | 125 + scripts/make-release-desc.sh | 87 + scripts/quantize-all.sh | 37 + scripts/quantize-parakeet.sh | 15 + scripts/release.sh | 204 + scripts/sha-all.sh | 7 + scripts/sync-ggml-am.sh | 160 + scripts/sync-ggml.last | 1 + scripts/sync-ggml.sh | 21 + scripts/sync-llama.sh | 20 + scripts/upload-parakeet.py | 157 + src/CMakeLists.txt | 258 + src/coreml/whisper-compat.h | 10 + src/coreml/whisper-compat.m | 35 + src/coreml/whisper-decoder-impl.h | 158 + src/coreml/whisper-decoder-impl.m | 227 + src/coreml/whisper-encoder-impl.h | 154 + src/coreml/whisper-encoder-impl.m | 223 + src/coreml/whisper-encoder.h | 26 + src/coreml/whisper-encoder.mm | 73 + src/openvino/whisper-openvino-encoder.cpp | 108 + src/openvino/whisper-openvino-encoder.h | 31 + src/parakeet-arch.h | 239 + src/parakeet.cpp | 3886 + src/vitisai/whisper-vitisai-encoder.cpp | 571 + src/vitisai/whisper-vitisai-encoder.h | 36 + src/vitisai/whisper-vitisai-helpers.cpp | 472 + src/vitisai/whisper-vitisai-helpers.h | 117 + src/whisper-arch.h | 197 + src/whisper.cpp | 9312 ++ tests/.gitignore | 3 + tests/CMakeLists.txt | 196 + tests/earnings21/.gitignore | 6 + tests/earnings21/Makefile | 16 + tests/earnings21/README.md | 87 + tests/earnings21/eval.mk | 58 + tests/earnings21/eval.py | 68 + tests/earnings21/normalizers/LICENSE | 25 + tests/earnings21/normalizers/__init__.py | 2 + tests/earnings21/normalizers/basic.py | 80 + tests/earnings21/normalizers/english.json | 1741 + tests/earnings21/normalizers/english.py | 550 + tests/en-0-ref.txt | 1 + tests/en-1-ref.txt | 1 + tests/en-2-ref.txt | 1 + tests/es-0-ref.txt | 1 + tests/librispeech-parakeet/.gitignore | 6 + tests/librispeech-parakeet/Makefile | 15 + tests/librispeech-parakeet/README.md | 57 + tests/librispeech-parakeet/eval.mk | 39 + tests/librispeech-parakeet/eval.py | 47 + .../librispeech-parakeet/normalizers/LICENSE | 25 + .../normalizers/__init__.py | 2 + .../librispeech-parakeet/normalizers/basic.py | 80 + .../normalizers/english.json | 1741 + .../normalizers/english.py | 550 + tests/librispeech/.gitignore | 6 + tests/librispeech/Makefile | 15 + tests/librispeech/README.md | 60 + tests/librispeech/eval.mk | 39 + tests/librispeech/eval.py | 47 + tests/librispeech/normalizers/LICENSE | 25 + tests/librispeech/normalizers/__init__.py | 2 + tests/librispeech/normalizers/basic.py | 80 + tests/librispeech/normalizers/english.json | 1741 + tests/librispeech/normalizers/english.py | 550 + tests/parakeet-expected-diffusion-output.txt | 1 + tests/parakeet-expected-gb1-output.txt | 1 + tests/parakeet-expected-jfk-output.txt | 1 + tests/parakeet-verification.h | 110 + tests/run-tests.sh | 164 + tests/test-c.c | 3 + tests/test-common-utf8.cpp | 34 + tests/test-parakeet-full.cpp | 101 + tests/test-parakeet.cpp | 126 + tests/test-vad-full.cpp | 87 + tests/test-vad.cpp | 85 + tests/test-whisper-buffer-loader.cpp | 24 + tests/test-whisper-zero-samples.cpp | 32 + tests/test-whisper.js | 58 + 1955 files changed, 719115 insertions(+) create mode 100644 .devops/cublas.Dockerfile create mode 100644 .devops/main-cuda.Dockerfile create mode 100644 .devops/main-intel.Dockerfile create mode 100644 .devops/main-musa.Dockerfile create mode 100644 .devops/main-rocm.Dockerfile create mode 100644 .devops/main-vulkan.Dockerfile create mode 100644 .devops/main.Dockerfile create mode 100644 .dockerignore create mode 100644 .github/actions/ccache-clear/action.yml create mode 100644 .github/workflows/bindings-go.yml create mode 100644 .github/workflows/bindings-ruby.yml create mode 100644 .github/workflows/build-android.yml create mode 100644 .github/workflows/build-clang.yml create mode 100644 .github/workflows/build-coreml.yml create mode 100644 .github/workflows/build-cpu.yml create mode 100644 .github/workflows/build-freebsd.yml create mode 100644 .github/workflows/build-gcc.yml create mode 100644 .github/workflows/build-macos.yml create mode 100644 .github/workflows/build-quantize.yml create mode 100644 .github/workflows/build-sanitize.yml create mode 100644 .github/workflows/build-self-hosted.yml create mode 100644 .github/workflows/build-sycl.yml create mode 100644 .github/workflows/build-vad.yml create mode 100644 .github/workflows/build-wasm.yml create mode 100644 .github/workflows/build-windows.yml create mode 100644 .github/workflows/close-issue.yml create mode 100644 .github/workflows/deploy-examples-wasm.yml create mode 100644 .github/workflows/docker.yml create mode 100644 .github/workflows/examples.yml create mode 100644 .github/workflows/make-release.yml create mode 100644 .github/workflows/release.yml create mode 100644 .gitignore create mode 100644 .pi/gg/SYSTEM.md create mode 100644 AGENTS.md create mode 100644 AUTHORS create mode 100644 CMakeLists.txt create mode 100644 CMakePresets.json create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 README.md create mode 100644 README_sycl.md create mode 100644 bindings/CMakeLists.txt create mode 100644 bindings/go/.gitignore create mode 100644 bindings/go/LICENSE create mode 100644 bindings/go/Makefile create mode 100644 bindings/go/README.md create mode 100644 bindings/go/doc.go create mode 100644 bindings/go/examples/go-model-download/context.go create mode 100644 bindings/go/examples/go-model-download/main.go create mode 100644 bindings/go/examples/go-whisper/color.go create mode 100644 bindings/go/examples/go-whisper/flags.go create mode 100644 bindings/go/examples/go-whisper/main.go create mode 100644 bindings/go/examples/go-whisper/process.go create mode 100644 bindings/go/go.mod create mode 100644 bindings/go/go.sum create mode 100644 bindings/go/params.go create mode 100644 bindings/go/pkg/whisper/consts.go create mode 100644 bindings/go/pkg/whisper/context.go create mode 100644 bindings/go/pkg/whisper/context_test.go create mode 100644 bindings/go/pkg/whisper/doc.go create mode 100644 bindings/go/pkg/whisper/interface.go create mode 100644 bindings/go/pkg/whisper/model.go create mode 100644 bindings/go/pkg/whisper/model_test.go create mode 100644 bindings/go/pkg/whisper/util_test.go create mode 100644 bindings/go/samples/jfk.wav create mode 100644 bindings/go/whisper.go create mode 100644 bindings/go/whisper_test.go create mode 100644 bindings/java/README.md create mode 100644 bindings/java/build.gradle create mode 100644 bindings/java/gradle.properties create mode 100644 bindings/java/gradle/wrapper/gradle-wrapper.jar create mode 100644 bindings/java/gradle/wrapper/gradle-wrapper.properties create mode 100755 bindings/java/gradlew create mode 100644 bindings/java/gradlew.bat create mode 100644 bindings/java/settings.gradle create mode 100644 bindings/java/src/main/java/io/github/ggerganov/whispercpp/WhisperConstants.java create mode 100644 bindings/java/src/main/java/io/github/ggerganov/whispercpp/WhisperContext.java create mode 100644 bindings/java/src/main/java/io/github/ggerganov/whispercpp/WhisperCpp.java create mode 100644 bindings/java/src/main/java/io/github/ggerganov/whispercpp/WhisperCppJnaLibrary.java create mode 100644 bindings/java/src/main/java/io/github/ggerganov/whispercpp/bean/WhisperSegment.java create mode 100644 bindings/java/src/main/java/io/github/ggerganov/whispercpp/callbacks/GgmlAbortCallback.java create mode 100644 bindings/java/src/main/java/io/github/ggerganov/whispercpp/callbacks/WhisperEncoderBeginCallback.java create mode 100644 bindings/java/src/main/java/io/github/ggerganov/whispercpp/callbacks/WhisperLogitsFilterCallback.java create mode 100644 bindings/java/src/main/java/io/github/ggerganov/whispercpp/callbacks/WhisperNewSegmentCallback.java create mode 100644 bindings/java/src/main/java/io/github/ggerganov/whispercpp/callbacks/WhisperProgressCallback.java create mode 100644 bindings/java/src/main/java/io/github/ggerganov/whispercpp/ggml/GgmlTensor.java create mode 100644 bindings/java/src/main/java/io/github/ggerganov/whispercpp/ggml/GgmlType.java create mode 100644 bindings/java/src/main/java/io/github/ggerganov/whispercpp/model/EModel.java create mode 100644 bindings/java/src/main/java/io/github/ggerganov/whispercpp/model/WhisperModel.java create mode 100644 bindings/java/src/main/java/io/github/ggerganov/whispercpp/model/WhisperModelLoader.java create mode 100644 bindings/java/src/main/java/io/github/ggerganov/whispercpp/model/WhisperState.java create mode 100644 bindings/java/src/main/java/io/github/ggerganov/whispercpp/model/WhisperTokenData.java create mode 100644 bindings/java/src/main/java/io/github/ggerganov/whispercpp/params/BeamSearchParams.java create mode 100644 bindings/java/src/main/java/io/github/ggerganov/whispercpp/params/CBool.java create mode 100644 bindings/java/src/main/java/io/github/ggerganov/whispercpp/params/GreedyParams.java create mode 100644 bindings/java/src/main/java/io/github/ggerganov/whispercpp/params/WhisperAhead.java create mode 100644 bindings/java/src/main/java/io/github/ggerganov/whispercpp/params/WhisperAheads.java create mode 100644 bindings/java/src/main/java/io/github/ggerganov/whispercpp/params/WhisperContextParams.java create mode 100644 bindings/java/src/main/java/io/github/ggerganov/whispercpp/params/WhisperFilters.java create mode 100644 bindings/java/src/main/java/io/github/ggerganov/whispercpp/params/WhisperFullParams.java create mode 100644 bindings/java/src/main/java/io/github/ggerganov/whispercpp/params/WhisperHParams.java create mode 100644 bindings/java/src/main/java/io/github/ggerganov/whispercpp/params/WhisperSamplingStrategy.java create mode 100644 bindings/java/src/test/java/io/github/ggerganov/whispercpp/WhisperCppTest.java create mode 100644 bindings/java/src/test/java/io/github/ggerganov/whispercpp/WhisperJnaLibraryTest.java create mode 100644 bindings/javascript/.gitignore create mode 100644 bindings/javascript/CMakeLists.txt create mode 100644 bindings/javascript/README.md create mode 100644 bindings/javascript/emscripten.cpp create mode 100644 bindings/javascript/libwhisper.worker.js create mode 100644 bindings/javascript/package-tmpl.json create mode 100644 bindings/javascript/whisper.js create mode 100644 bindings/ruby/.document create mode 100644 bindings/ruby/.gitignore create mode 100644 bindings/ruby/.rdoc_options create mode 100644 bindings/ruby/CHANGELOG.md create mode 100644 bindings/ruby/README.md create mode 100644 bindings/ruby/Rakefile create mode 100644 bindings/ruby/ext/.gitignore create mode 100644 bindings/ruby/ext/dependencies.rb create mode 100644 bindings/ruby/ext/dependencies_for_windows.rb create mode 100644 bindings/ruby/ext/extconf.rb create mode 100644 bindings/ruby/ext/options.rb create mode 100644 bindings/ruby/ext/options_for_windows.rb create mode 100644 bindings/ruby/ext/ruby_whisper.c create mode 100644 bindings/ruby/ext/ruby_whisper.h create mode 100644 bindings/ruby/ext/ruby_whisper_context.c create mode 100644 bindings/ruby/ext/ruby_whisper_context_params.c create mode 100644 bindings/ruby/ext/ruby_whisper_error.c create mode 100644 bindings/ruby/ext/ruby_whisper_log_queue.c create mode 100644 bindings/ruby/ext/ruby_whisper_log_settable.h create mode 100644 bindings/ruby/ext/ruby_whisper_model.c create mode 100644 bindings/ruby/ext/ruby_whisper_parakeet.c create mode 100644 bindings/ruby/ext/ruby_whisper_parakeet_context.c create mode 100644 bindings/ruby/ext/ruby_whisper_parakeet_context_params.c create mode 100644 bindings/ruby/ext/ruby_whisper_parakeet_model.c create mode 100644 bindings/ruby/ext/ruby_whisper_parakeet_params.c create mode 100644 bindings/ruby/ext/ruby_whisper_parakeet_segment.c create mode 100644 bindings/ruby/ext/ruby_whisper_parakeet_token.c create mode 100644 bindings/ruby/ext/ruby_whisper_parakeet_transcribe.cpp create mode 100644 bindings/ruby/ext/ruby_whisper_params.c create mode 100644 bindings/ruby/ext/ruby_whisper_segment.c create mode 100644 bindings/ruby/ext/ruby_whisper_token.c create mode 100644 bindings/ruby/ext/ruby_whisper_transcribe.cpp create mode 100644 bindings/ruby/ext/ruby_whisper_vad_context.c create mode 100644 bindings/ruby/ext/ruby_whisper_vad_context_detect.cpp create mode 100644 bindings/ruby/ext/ruby_whisper_vad_params.c create mode 100644 bindings/ruby/ext/ruby_whisper_vad_segment.c create mode 100644 bindings/ruby/ext/ruby_whisper_vad_segments.c create mode 100644 bindings/ruby/ext/sources/CMakeGraphVizOptions.cmake create mode 100644 bindings/ruby/extsources.rb create mode 100644 bindings/ruby/lib/whisper/log_settable.rb create mode 100644 bindings/ruby/lib/whisper/model/uri.rb create mode 100644 bindings/ruby/lib/whisper/output.rb create mode 100644 bindings/ruby/sig/whisper.rbs create mode 100644 bindings/ruby/test/helper.rb create mode 100644 bindings/ruby/test/jfk_reader/.gitignore create mode 100644 bindings/ruby/test/jfk_reader/extconf.rb create mode 100644 bindings/ruby/test/jfk_reader/jfk_reader.c create mode 100644 bindings/ruby/test/test_callback.rb create mode 100644 bindings/ruby/test/test_context_params.rb create mode 100644 bindings/ruby/test/test_error.rb create mode 100644 bindings/ruby/test/test_model.rb create mode 100644 bindings/ruby/test/test_package.rb create mode 100644 bindings/ruby/test/test_parakeet.rb create mode 100644 bindings/ruby/test/test_parakeet_callback.rb create mode 100644 bindings/ruby/test/test_parakeet_context.rb create mode 100644 bindings/ruby/test/test_parakeet_context_params.rb create mode 100644 bindings/ruby/test/test_parakeet_model.rb create mode 100644 bindings/ruby/test/test_parakeet_params.rb create mode 100644 bindings/ruby/test/test_parakeet_segment.rb create mode 100644 bindings/ruby/test/test_parakeet_token.rb create mode 100644 bindings/ruby/test/test_params.rb create mode 100644 bindings/ruby/test/test_segment.rb create mode 100644 bindings/ruby/test/test_token.rb create mode 100644 bindings/ruby/test/test_vad.rb create mode 100644 bindings/ruby/test/test_vad_context.rb create mode 100644 bindings/ruby/test/test_vad_params.rb create mode 100644 bindings/ruby/test/test_vad_segment.rb create mode 100644 bindings/ruby/test/test_vad_segments.rb create mode 100644 bindings/ruby/test/test_whisper.rb create mode 100644 bindings/ruby/whispercpp.gemspec create mode 100755 build-xcframework.sh create mode 100644 ci/README.md create mode 100644 ci/ruleset-nightly.json create mode 100644 ci/ruleset-official.json create mode 100644 ci/run.sh create mode 100644 cmake/DefaultTargetOptions.cmake create mode 100644 cmake/FindFFmpeg.cmake create mode 100644 cmake/arm64-apple-clang.cmake create mode 100644 cmake/arm64-windows-llvm-cuda.cmake create mode 100644 cmake/arm64-windows-llvm.cmake create mode 100644 cmake/build-info.cmake create mode 100644 cmake/git-vars.cmake create mode 100644 cmake/parakeet-config.cmake.in create mode 100644 cmake/parakeet.pc.in create mode 100644 cmake/riscv64-spacemit-linux-gnu-gcc.cmake create mode 100644 cmake/whisper-config.cmake.in create mode 100644 cmake/whisper.pc.in create mode 100644 cmake/x64-windows-llvm.cmake create mode 100644 examples/CMakeLists.txt create mode 100644 examples/addon.node/.gitignore create mode 100644 examples/addon.node/CMakeLists.txt create mode 100644 examples/addon.node/README.md create mode 100644 examples/addon.node/__test__/whisper.spec.js create mode 100644 examples/addon.node/addon.cpp create mode 100644 examples/addon.node/index.js create mode 100644 examples/addon.node/package-lock.json create mode 100644 examples/addon.node/package.json create mode 100644 examples/addon.node/vad-example.js create mode 100644 examples/bench.wasm/CMakeLists.txt create mode 100644 examples/bench.wasm/README.md create mode 100644 examples/bench.wasm/emscripten.cpp create mode 100644 examples/bench.wasm/index-tmpl.html create mode 100644 examples/bench/CMakeLists.txt create mode 100644 examples/bench/README.md create mode 100644 examples/bench/bench.cpp create mode 100644 examples/cli/CMakeLists.txt create mode 100644 examples/cli/README.md create mode 100644 examples/cli/cli.cpp create mode 100644 examples/coi-serviceworker.js create mode 100644 examples/command.wasm/CMakeLists.txt create mode 100644 examples/command.wasm/README.md create mode 100644 examples/command.wasm/emscripten.cpp create mode 100644 examples/command.wasm/index-tmpl.html create mode 100644 examples/command/CMakeLists.txt create mode 100644 examples/command/README.md create mode 100644 examples/command/command.cpp create mode 100644 examples/command/commands.txt create mode 100644 examples/common-ggml.cpp create mode 100644 examples/common-ggml.h create mode 100644 examples/common-sdl.cpp create mode 100644 examples/common-sdl.h create mode 100644 examples/common-whisper.cpp create mode 100644 examples/common-whisper.h create mode 100644 examples/common.cpp create mode 100644 examples/common.h create mode 100644 examples/deprecation-warning/CMakeLists.txt create mode 100644 examples/deprecation-warning/README.md create mode 100644 examples/deprecation-warning/deprecation-warning.cpp create mode 100644 examples/ffmpeg-transcode.cpp create mode 100755 examples/generate-karaoke.sh create mode 100644 examples/grammar-parser.cpp create mode 100644 examples/grammar-parser.h create mode 100644 examples/helpers.js create mode 100644 examples/json.hpp create mode 100755 examples/livestream.sh create mode 100644 examples/lsp/CMakeLists.txt create mode 100644 examples/lsp/README.md create mode 100644 examples/lsp/lsp.cpp create mode 100644 examples/lsp/whisper.vim create mode 100644 examples/miniaudio.h create mode 100644 examples/parakeet-cli/CMakeLists.txt create mode 100644 examples/parakeet-cli/README.md create mode 100644 examples/parakeet-cli/parakeet-cli.cpp create mode 100644 examples/parakeet-quantize/CMakeLists.txt create mode 100644 examples/parakeet-quantize/parakeet-quantize.cpp create mode 100644 examples/python/test_whisper_processor.py create mode 100644 examples/python/whisper_processor.py create mode 100644 examples/quantize/CMakeLists.txt create mode 100644 examples/quantize/README.md create mode 100644 examples/quantize/quantize.cpp create mode 100644 examples/server.py create mode 100644 examples/server/CMakeLists.txt create mode 100644 examples/server/README.md create mode 100644 examples/server/bench.js create mode 100644 examples/server/httplib.h create mode 100644 examples/server/server.cpp create mode 100644 examples/stb_vorbis.c create mode 100644 examples/stream.wasm/CMakeLists.txt create mode 100644 examples/stream.wasm/README.md create mode 100644 examples/stream.wasm/emscripten.cpp create mode 100644 examples/stream.wasm/index-tmpl.html create mode 100644 examples/stream/CMakeLists.txt create mode 100644 examples/stream/README.md create mode 100644 examples/stream/stream.cpp create mode 100644 examples/sycl/CMakeLists.txt create mode 100644 examples/sycl/README.md create mode 100644 examples/sycl/build.sh create mode 100644 examples/sycl/ls-sycl-device.cpp create mode 100644 examples/sycl/run-whisper.sh create mode 100644 examples/talk-llama/.gitignore create mode 100644 examples/talk-llama/CMakeLists.txt create mode 100644 examples/talk-llama/README.md create mode 100644 examples/talk-llama/eleven-labs.py create mode 100644 examples/talk-llama/prompts/talk-alpaca.txt create mode 100755 examples/talk-llama/speak create mode 100644 examples/talk-llama/speak.bat create mode 100644 examples/talk-llama/speak.ps1 create mode 100644 examples/talk-llama/talk-llama.cpp create mode 100644 examples/test-cmake/.gitignore create mode 100644 examples/test-cmake/CMakeLists.txt create mode 100644 examples/test-cmake/README.md create mode 100755 examples/test-cmake/build-install.sh create mode 100755 examples/test-cmake/build.sh create mode 100644 examples/test-cmake/test-cmake.cpp create mode 100755 examples/twitch.sh create mode 100644 examples/vad-speech-segments/CMakeLists.txt create mode 100644 examples/vad-speech-segments/README.md create mode 100644 examples/vad-speech-segments/speech.cpp create mode 100644 examples/wchess/CMakeLists.txt create mode 100644 examples/wchess/README.md create mode 100644 examples/wchess/libwchess/CMakeLists.txt create mode 100644 examples/wchess/libwchess/Chessboard.cpp create mode 100644 examples/wchess/libwchess/Chessboard.h create mode 100644 examples/wchess/libwchess/WChess.cpp create mode 100644 examples/wchess/libwchess/WChess.h create mode 100644 examples/wchess/libwchess/test-chessboard.cpp create mode 100644 examples/wchess/wchess.cmd/CMakeLists.txt create mode 100644 examples/wchess/wchess.cmd/wchess.cmd.cpp create mode 100644 examples/wchess/wchess.wasm/CMakeLists.txt create mode 100644 examples/wchess/wchess.wasm/chessboardjs-1.0.0/css/chessboard-1.0.0.css create mode 100644 examples/wchess/wchess.wasm/chessboardjs-1.0.0/css/chessboard-1.0.0.min.css create mode 100644 examples/wchess/wchess.wasm/chessboardjs-1.0.0/img/chesspieces/wikipedia/bB.png create mode 100644 examples/wchess/wchess.wasm/chessboardjs-1.0.0/img/chesspieces/wikipedia/bK.png create mode 100644 examples/wchess/wchess.wasm/chessboardjs-1.0.0/img/chesspieces/wikipedia/bN.png create mode 100644 examples/wchess/wchess.wasm/chessboardjs-1.0.0/img/chesspieces/wikipedia/bP.png create mode 100644 examples/wchess/wchess.wasm/chessboardjs-1.0.0/img/chesspieces/wikipedia/bQ.png create mode 100644 examples/wchess/wchess.wasm/chessboardjs-1.0.0/img/chesspieces/wikipedia/bR.png create mode 100644 examples/wchess/wchess.wasm/chessboardjs-1.0.0/img/chesspieces/wikipedia/wB.png create mode 100644 examples/wchess/wchess.wasm/chessboardjs-1.0.0/img/chesspieces/wikipedia/wK.png create mode 100644 examples/wchess/wchess.wasm/chessboardjs-1.0.0/img/chesspieces/wikipedia/wN.png create mode 100644 examples/wchess/wchess.wasm/chessboardjs-1.0.0/img/chesspieces/wikipedia/wP.png create mode 100644 examples/wchess/wchess.wasm/chessboardjs-1.0.0/img/chesspieces/wikipedia/wQ.png create mode 100644 examples/wchess/wchess.wasm/chessboardjs-1.0.0/img/chesspieces/wikipedia/wR.png create mode 100644 examples/wchess/wchess.wasm/chessboardjs-1.0.0/js/chessboard-1.0.0.js create mode 100644 examples/wchess/wchess.wasm/chessboardjs-1.0.0/js/chessboard-1.0.0.min.js create mode 100644 examples/wchess/wchess.wasm/chessboardjs-1.0.0/js/chessboard-1.0.0/CHANGELOG.md create mode 100644 examples/wchess/wchess.wasm/chessboardjs-1.0.0/js/chessboard-1.0.0/LICENSE.md create mode 100644 examples/wchess/wchess.wasm/chessboardjs-1.0.0/js/chessboard-1.0.0/README.md create mode 100644 examples/wchess/wchess.wasm/chessboardjs-1.0.0/js/chessboard-1.0.0/package.json create mode 100644 examples/wchess/wchess.wasm/index-tmpl.html create mode 100644 examples/wchess/wchess.wasm/jquery-3.7.1.min.js create mode 100644 examples/wchess/wchess.wasm/wchess.wasm.cpp create mode 100644 examples/whisper.android.java/.gitignore create mode 100644 examples/whisper.android.java/README.md create mode 100644 examples/whisper.android.java/README_files/1.jpg create mode 100644 examples/whisper.android.java/app/.gitignore create mode 100644 examples/whisper.android.java/app/build.gradle create mode 100644 examples/whisper.android.java/app/proguard-rules.pro create mode 100644 examples/whisper.android.java/app/src/androidTest/java/com/litongjava/whisper/android/java/ExampleInstrumentedTest.java create mode 100644 examples/whisper.android.java/app/src/main/AndroidManifest.xml create mode 100644 examples/whisper.android.java/app/src/main/assets/logback.xml create mode 100644 examples/whisper.android.java/app/src/main/java/com/litongjava/whisper/android/java/MainActivity.java create mode 100644 examples/whisper.android.java/app/src/main/java/com/litongjava/whisper/android/java/app/App.java create mode 100644 examples/whisper.android.java/app/src/main/java/com/litongjava/whisper/android/java/bean/WhisperSegment.java create mode 100644 examples/whisper.android.java/app/src/main/java/com/litongjava/whisper/android/java/services/WhisperService.java create mode 100644 examples/whisper.android.java/app/src/main/java/com/litongjava/whisper/android/java/single/LocalWhisper.java create mode 100644 examples/whisper.android.java/app/src/main/java/com/litongjava/whisper/android/java/task/LoadModelTask.java create mode 100644 examples/whisper.android.java/app/src/main/java/com/litongjava/whisper/android/java/task/TranscriptionTask.java create mode 100644 examples/whisper.android.java/app/src/main/java/com/litongjava/whisper/android/java/utils/AssetUtils.java create mode 100644 examples/whisper.android.java/app/src/main/java/com/litongjava/whisper/android/java/utils/WaveEncoder.java create mode 100644 examples/whisper.android.java/app/src/main/java/com/whispercpp/java/whisper/CpuInfo.java create mode 100644 examples/whisper.android.java/app/src/main/java/com/whispercpp/java/whisper/WhisperContext.java create mode 100644 examples/whisper.android.java/app/src/main/java/com/whispercpp/java/whisper/WhisperCpuConfig.java create mode 100644 examples/whisper.android.java/app/src/main/java/com/whispercpp/java/whisper/WhisperLib.java create mode 100644 examples/whisper.android.java/app/src/main/java/com/whispercpp/java/whisper/WhisperUtils.java create mode 100644 examples/whisper.android.java/app/src/main/jni/whisper/CMakeLists.txt create mode 100644 examples/whisper.android.java/app/src/main/jni/whisper/jni.c create mode 100644 examples/whisper.android.java/app/src/main/res/drawable-v24/ic_launcher_foreground.xml create mode 100644 examples/whisper.android.java/app/src/main/res/drawable/ic_launcher_background.xml create mode 100644 examples/whisper.android.java/app/src/main/res/layout/activity_main.xml create mode 100644 examples/whisper.android.java/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 examples/whisper.android.java/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml create mode 100644 examples/whisper.android.java/app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 examples/whisper.android.java/app/src/main/res/mipmap-hdpi/ic_launcher_round.png create mode 100644 examples/whisper.android.java/app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 examples/whisper.android.java/app/src/main/res/mipmap-mdpi/ic_launcher_round.png create mode 100644 examples/whisper.android.java/app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 examples/whisper.android.java/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png create mode 100644 examples/whisper.android.java/app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 examples/whisper.android.java/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 examples/whisper.android.java/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 examples/whisper.android.java/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 examples/whisper.android.java/app/src/main/res/values-night/themes.xml create mode 100644 examples/whisper.android.java/app/src/main/res/values/colors.xml create mode 100644 examples/whisper.android.java/app/src/main/res/values/strings.xml create mode 100644 examples/whisper.android.java/app/src/main/res/values/themes.xml create mode 100644 examples/whisper.android.java/app/src/test/java/com/litongjava/whisper/android/java/ExampleUnitTest.java create mode 100644 examples/whisper.android.java/build.gradle create mode 100644 examples/whisper.android.java/gradle.properties create mode 100644 examples/whisper.android.java/gradle/wrapper/gradle-wrapper.jar create mode 100644 examples/whisper.android.java/gradle/wrapper/gradle-wrapper.properties create mode 100755 examples/whisper.android.java/gradlew create mode 100644 examples/whisper.android.java/gradlew.bat create mode 100644 examples/whisper.android.java/settings.gradle create mode 100644 examples/whisper.android/.gitignore create mode 100644 examples/whisper.android/README.md create mode 100644 examples/whisper.android/app/.gitignore create mode 100644 examples/whisper.android/app/build.gradle create mode 100644 examples/whisper.android/app/proguard-rules.pro create mode 100644 examples/whisper.android/app/src/androidTest/java/com/whispercppdemo/ExampleInstrumentedTest.kt create mode 100644 examples/whisper.android/app/src/main/AndroidManifest.xml create mode 100644 examples/whisper.android/app/src/main/java/com/whispercppdemo/MainActivity.kt create mode 100644 examples/whisper.android/app/src/main/java/com/whispercppdemo/media/RiffWaveHelper.kt create mode 100644 examples/whisper.android/app/src/main/java/com/whispercppdemo/recorder/Recorder.kt create mode 100644 examples/whisper.android/app/src/main/java/com/whispercppdemo/ui/main/MainScreen.kt create mode 100644 examples/whisper.android/app/src/main/java/com/whispercppdemo/ui/main/MainScreenViewModel.kt create mode 100644 examples/whisper.android/app/src/main/java/com/whispercppdemo/ui/theme/Color.kt create mode 100644 examples/whisper.android/app/src/main/java/com/whispercppdemo/ui/theme/Theme.kt create mode 100644 examples/whisper.android/app/src/main/java/com/whispercppdemo/ui/theme/Type.kt create mode 100644 examples/whisper.android/app/src/main/res/drawable/ic_launcher_background.xml create mode 100644 examples/whisper.android/app/src/main/res/drawable/ic_launcher_foreground.xml create mode 100644 examples/whisper.android/app/src/main/res/mipmap-anydpi/ic_launcher.xml create mode 100644 examples/whisper.android/app/src/main/res/values/strings.xml create mode 100644 examples/whisper.android/app/src/main/res/values/themes.xml create mode 100644 examples/whisper.android/app/src/main/res/xml/backup_rules.xml create mode 100644 examples/whisper.android/app/src/main/res/xml/data_extraction_rules.xml create mode 100644 examples/whisper.android/app/src/test/java/com/whispercppdemo/ExampleUnitTest.kt create mode 100644 examples/whisper.android/build.gradle create mode 100644 examples/whisper.android/gradle.properties create mode 100644 examples/whisper.android/gradle/wrapper/gradle-wrapper.jar create mode 100644 examples/whisper.android/gradle/wrapper/gradle-wrapper.properties create mode 100755 examples/whisper.android/gradlew create mode 100644 examples/whisper.android/gradlew.bat create mode 100644 examples/whisper.android/lib/.gitignore create mode 100644 examples/whisper.android/lib/build.gradle create mode 100644 examples/whisper.android/lib/src/main/AndroidManifest.xml create mode 100644 examples/whisper.android/lib/src/main/java/com/whispercpp/whisper/LibWhisper.kt create mode 100644 examples/whisper.android/lib/src/main/java/com/whispercpp/whisper/WhisperCpuConfig.kt create mode 100644 examples/whisper.android/lib/src/main/jni/whisper/CMakeLists.txt create mode 100644 examples/whisper.android/lib/src/main/jni/whisper/jni.c create mode 100644 examples/whisper.android/settings.gradle create mode 100644 examples/whisper.nvim/README.md create mode 100755 examples/whisper.nvim/whisper.nvim create mode 100644 examples/whisper.objc/README.md create mode 100644 examples/whisper.objc/whisper.objc.xcodeproj/project.pbxproj create mode 100644 examples/whisper.objc/whisper.objc.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 examples/whisper.objc/whisper.objc.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 examples/whisper.objc/whisper.objc/AppDelegate.h create mode 100644 examples/whisper.objc/whisper.objc/AppDelegate.m create mode 100644 examples/whisper.objc/whisper.objc/Assets.xcassets/AccentColor.colorset/Contents.json create mode 100644 examples/whisper.objc/whisper.objc/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 examples/whisper.objc/whisper.objc/Assets.xcassets/Contents.json create mode 100644 examples/whisper.objc/whisper.objc/Base.lproj/LaunchScreen.storyboard create mode 100644 examples/whisper.objc/whisper.objc/Base.lproj/Main.storyboard create mode 100644 examples/whisper.objc/whisper.objc/Info.plist create mode 100644 examples/whisper.objc/whisper.objc/SceneDelegate.h create mode 100644 examples/whisper.objc/whisper.objc/SceneDelegate.m create mode 100644 examples/whisper.objc/whisper.objc/ViewController.h create mode 100644 examples/whisper.objc/whisper.objc/ViewController.m create mode 100644 examples/whisper.objc/whisper.objc/main.m create mode 100644 examples/whisper.swiftui/.gitignore create mode 100644 examples/whisper.swiftui/README.md create mode 100644 examples/whisper.swiftui/whisper.cpp.swift/LibWhisper.swift create mode 100644 examples/whisper.swiftui/whisper.swiftui.demo/Models/Model.swift create mode 100644 examples/whisper.swiftui/whisper.swiftui.demo/Models/WhisperState.swift create mode 100644 examples/whisper.swiftui/whisper.swiftui.demo/Resources/models/.gitignore create mode 100644 examples/whisper.swiftui/whisper.swiftui.demo/Resources/samples/.gitignore create mode 100644 examples/whisper.swiftui/whisper.swiftui.demo/Supporting files/Assets.xcassets/AccentColor.colorset/Contents.json create mode 100644 examples/whisper.swiftui/whisper.swiftui.demo/Supporting files/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 examples/whisper.swiftui/whisper.swiftui.demo/Supporting files/Assets.xcassets/Contents.json create mode 100644 examples/whisper.swiftui/whisper.swiftui.demo/Supporting files/Preview Content/Preview Assets.xcassets/Contents.json create mode 100644 examples/whisper.swiftui/whisper.swiftui.demo/Supporting files/WhisperCppDemo.entitlements create mode 100644 examples/whisper.swiftui/whisper.swiftui.demo/UI/ContentView.swift create mode 100644 examples/whisper.swiftui/whisper.swiftui.demo/UI/DownloadButton.swift create mode 100644 examples/whisper.swiftui/whisper.swiftui.demo/Utils/Recorder.swift create mode 100644 examples/whisper.swiftui/whisper.swiftui.demo/Utils/RiffWaveUtils.swift create mode 100644 examples/whisper.swiftui/whisper.swiftui.demo/WhisperCppDemoApp.swift create mode 100644 examples/whisper.swiftui/whisper.swiftui.xcodeproj/.gitignore create mode 100644 examples/whisper.swiftui/whisper.swiftui.xcodeproj/project.pbxproj create mode 100644 examples/whisper.swiftui/whisper.swiftui.xcodeproj/project.xcworkspace/.gitignore create mode 100644 examples/whisper.wasm/CMakeLists.txt create mode 100644 examples/whisper.wasm/README.md create mode 100644 examples/whisper.wasm/emscripten.cpp create mode 100644 examples/whisper.wasm/index-tmpl.html create mode 100755 examples/yt-wsp.sh create mode 100644 ggml/.gitignore create mode 100644 ggml/CMakeLists.txt create mode 100644 ggml/cmake/FindNCCL.cmake create mode 100644 ggml/cmake/GitVars.cmake create mode 100644 ggml/cmake/common.cmake create mode 100644 ggml/cmake/ggml-config.cmake.in create mode 100644 ggml/include/ggml-alloc.h create mode 100644 ggml/include/ggml-backend.h create mode 100644 ggml/include/ggml-blas.h create mode 100644 ggml/include/ggml-cann.h create mode 100644 ggml/include/ggml-cpp.h create mode 100644 ggml/include/ggml-cpu.h create mode 100644 ggml/include/ggml-cuda.h create mode 100644 ggml/include/ggml-et.h create mode 100644 ggml/include/ggml-hexagon.h create mode 100644 ggml/include/ggml-metal.h create mode 100644 ggml/include/ggml-opencl.h create mode 100644 ggml/include/ggml-openvino.h create mode 100644 ggml/include/ggml-opt.h create mode 100644 ggml/include/ggml-rpc.h create mode 100644 ggml/include/ggml-sycl.h create mode 100644 ggml/include/ggml-virtgpu.h create mode 100644 ggml/include/ggml-vulkan.h create mode 100644 ggml/include/ggml-webgpu.h create mode 100644 ggml/include/ggml-zdnn.h create mode 100644 ggml/include/ggml-zendnn.h create mode 100644 ggml/include/ggml.h create mode 100644 ggml/include/gguf.h create mode 100644 ggml/src/CMakeLists.txt create mode 100644 ggml/src/ggml-alloc.c create mode 100644 ggml/src/ggml-backend-dl.cpp create mode 100644 ggml/src/ggml-backend-dl.h create mode 100644 ggml/src/ggml-backend-impl.h create mode 100644 ggml/src/ggml-backend-meta.cpp create mode 100644 ggml/src/ggml-backend-reg.cpp create mode 100644 ggml/src/ggml-backend.cpp create mode 100644 ggml/src/ggml-blas/CMakeLists.txt create mode 100644 ggml/src/ggml-blas/ggml-blas.cpp create mode 100755 ggml/src/ggml-cann/CMakeLists.txt create mode 100644 ggml/src/ggml-cann/acl_tensor.cpp create mode 100644 ggml/src/ggml-cann/acl_tensor.h create mode 100644 ggml/src/ggml-cann/aclnn_ops.cpp create mode 100644 ggml/src/ggml-cann/aclnn_ops.h create mode 100644 ggml/src/ggml-cann/common.h create mode 100644 ggml/src/ggml-cann/ggml-cann.cpp create mode 100644 ggml/src/ggml-common.h create mode 100644 ggml/src/ggml-cpu/CMakeLists.txt create mode 100644 ggml/src/ggml-cpu/amx/amx.cpp create mode 100644 ggml/src/ggml-cpu/amx/amx.h create mode 100644 ggml/src/ggml-cpu/amx/common.h create mode 100644 ggml/src/ggml-cpu/amx/mmq.cpp create mode 100644 ggml/src/ggml-cpu/amx/mmq.h create mode 100644 ggml/src/ggml-cpu/arch-fallback.h create mode 100644 ggml/src/ggml-cpu/arch/arm/cpu-feats.cpp create mode 100644 ggml/src/ggml-cpu/arch/arm/quants.c create mode 100644 ggml/src/ggml-cpu/arch/arm/repack.cpp create mode 100644 ggml/src/ggml-cpu/arch/loongarch/quants.c create mode 100644 ggml/src/ggml-cpu/arch/powerpc/cpu-feats.cpp create mode 100644 ggml/src/ggml-cpu/arch/powerpc/quants.c create mode 100644 ggml/src/ggml-cpu/arch/riscv/cpu-feats.cpp create mode 100644 ggml/src/ggml-cpu/arch/riscv/quants.c create mode 100644 ggml/src/ggml-cpu/arch/riscv/repack.cpp create mode 100644 ggml/src/ggml-cpu/arch/s390/cpu-feats.cpp create mode 100644 ggml/src/ggml-cpu/arch/s390/quants.c create mode 100644 ggml/src/ggml-cpu/arch/s390/repack.cpp create mode 100644 ggml/src/ggml-cpu/arch/wasm/quants.c create mode 100644 ggml/src/ggml-cpu/arch/x86/cpu-feats.cpp create mode 100644 ggml/src/ggml-cpu/arch/x86/quants.c create mode 100644 ggml/src/ggml-cpu/arch/x86/repack.cpp create mode 100644 ggml/src/ggml-cpu/binary-ops.cpp create mode 100644 ggml/src/ggml-cpu/binary-ops.h create mode 100644 ggml/src/ggml-cpu/cmake/FindSIMD.cmake create mode 100644 ggml/src/ggml-cpu/cmake/FindSMTIME.cmake create mode 100644 ggml/src/ggml-cpu/common.h create mode 100644 ggml/src/ggml-cpu/ggml-cpu-impl.h create mode 100644 ggml/src/ggml-cpu/ggml-cpu.c create mode 100644 ggml/src/ggml-cpu/ggml-cpu.cpp create mode 100644 ggml/src/ggml-cpu/hbm.cpp create mode 100644 ggml/src/ggml-cpu/hbm.h create mode 100644 ggml/src/ggml-cpu/iqp.cpp create mode 100644 ggml/src/ggml-cpu/iqp.h create mode 100644 ggml/src/ggml-cpu/kleidiai/CMakeLists.txt create mode 100644 ggml/src/ggml-cpu/kleidiai/kernels.cpp create mode 100644 ggml/src/ggml-cpu/kleidiai/kernels.h create mode 100644 ggml/src/ggml-cpu/kleidiai/kleidiai.cpp create mode 100644 ggml/src/ggml-cpu/kleidiai/kleidiai.h create mode 100644 ggml/src/ggml-cpu/llamafile/sgemm.cpp create mode 100644 ggml/src/ggml-cpu/llamafile/sgemm.h create mode 100644 ggml/src/ggml-cpu/ops.cpp create mode 100644 ggml/src/ggml-cpu/ops.h create mode 100644 ggml/src/ggml-cpu/quants.c create mode 100644 ggml/src/ggml-cpu/quants.h create mode 100644 ggml/src/ggml-cpu/repack.cpp create mode 100644 ggml/src/ggml-cpu/repack.h create mode 100644 ggml/src/ggml-cpu/simd-gemm.h create mode 100644 ggml/src/ggml-cpu/simd-mappings.h create mode 100644 ggml/src/ggml-cpu/spacemit/ime.cpp create mode 100644 ggml/src/ggml-cpu/spacemit/ime.h create mode 100644 ggml/src/ggml-cpu/spacemit/ime1_kernels.cpp create mode 100644 ggml/src/ggml-cpu/spacemit/ime2_kernels.cpp create mode 100644 ggml/src/ggml-cpu/spacemit/ime_env.cpp create mode 100644 ggml/src/ggml-cpu/spacemit/ime_env.h create mode 100644 ggml/src/ggml-cpu/spacemit/ime_kernels.h create mode 100644 ggml/src/ggml-cpu/spacemit/repack.cpp create mode 100644 ggml/src/ggml-cpu/spacemit/repack.h create mode 100644 ggml/src/ggml-cpu/spacemit/rvv_kernels.cpp create mode 100644 ggml/src/ggml-cpu/spacemit/rvv_kernels.h create mode 100644 ggml/src/ggml-cpu/spacemit/spine_barrier.h create mode 100644 ggml/src/ggml-cpu/spacemit/spine_mem_pool.cpp create mode 100644 ggml/src/ggml-cpu/spacemit/spine_mem_pool.h create mode 100644 ggml/src/ggml-cpu/spacemit/spine_tcm.h create mode 100644 ggml/src/ggml-cpu/traits.cpp create mode 100644 ggml/src/ggml-cpu/traits.h create mode 100644 ggml/src/ggml-cpu/unary-ops.cpp create mode 100644 ggml/src/ggml-cpu/unary-ops.h create mode 100644 ggml/src/ggml-cpu/vec.cpp create mode 100644 ggml/src/ggml-cpu/vec.h create mode 100644 ggml/src/ggml-cuda/CMakeLists.txt create mode 100644 ggml/src/ggml-cuda/acc.cu create mode 100644 ggml/src/ggml-cuda/acc.cuh create mode 100644 ggml/src/ggml-cuda/add-id.cu create mode 100644 ggml/src/ggml-cuda/add-id.cuh create mode 100644 ggml/src/ggml-cuda/allreduce.cu create mode 100644 ggml/src/ggml-cuda/allreduce.cuh create mode 100644 ggml/src/ggml-cuda/arange.cu create mode 100644 ggml/src/ggml-cuda/arange.cuh create mode 100644 ggml/src/ggml-cuda/argmax.cu create mode 100644 ggml/src/ggml-cuda/argmax.cuh create mode 100644 ggml/src/ggml-cuda/argsort.cu create mode 100644 ggml/src/ggml-cuda/argsort.cuh create mode 100644 ggml/src/ggml-cuda/binbcast.cu create mode 100644 ggml/src/ggml-cuda/binbcast.cuh create mode 100644 ggml/src/ggml-cuda/clamp.cu create mode 100644 ggml/src/ggml-cuda/clamp.cuh create mode 100644 ggml/src/ggml-cuda/col2im-1d.cu create mode 100644 ggml/src/ggml-cuda/col2im-1d.cuh create mode 100644 ggml/src/ggml-cuda/common.cuh create mode 100644 ggml/src/ggml-cuda/concat.cu create mode 100644 ggml/src/ggml-cuda/concat.cuh create mode 100644 ggml/src/ggml-cuda/conv-transpose-1d.cu create mode 100644 ggml/src/ggml-cuda/conv-transpose-1d.cuh create mode 100644 ggml/src/ggml-cuda/conv2d-dw.cu create mode 100644 ggml/src/ggml-cuda/conv2d-dw.cuh create mode 100644 ggml/src/ggml-cuda/conv2d-transpose.cu create mode 100644 ggml/src/ggml-cuda/conv2d-transpose.cuh create mode 100644 ggml/src/ggml-cuda/conv2d.cu create mode 100644 ggml/src/ggml-cuda/conv2d.cuh create mode 100644 ggml/src/ggml-cuda/convert.cu create mode 100644 ggml/src/ggml-cuda/convert.cuh create mode 100644 ggml/src/ggml-cuda/count-equal.cu create mode 100644 ggml/src/ggml-cuda/count-equal.cuh create mode 100644 ggml/src/ggml-cuda/cp-async.cuh create mode 100644 ggml/src/ggml-cuda/cpy-utils.cuh create mode 100644 ggml/src/ggml-cuda/cpy.cu create mode 100644 ggml/src/ggml-cuda/cpy.cuh create mode 100644 ggml/src/ggml-cuda/cross-entropy-loss.cu create mode 100644 ggml/src/ggml-cuda/cross-entropy-loss.cuh create mode 100644 ggml/src/ggml-cuda/cumsum.cu create mode 100644 ggml/src/ggml-cuda/cumsum.cuh create mode 100644 ggml/src/ggml-cuda/dequantize.cuh create mode 100644 ggml/src/ggml-cuda/diag.cu create mode 100644 ggml/src/ggml-cuda/diag.cuh create mode 100644 ggml/src/ggml-cuda/diagmask.cu create mode 100644 ggml/src/ggml-cuda/diagmask.cuh create mode 100644 ggml/src/ggml-cuda/dsv4-hc.cu create mode 100644 ggml/src/ggml-cuda/dsv4-hc.cuh create mode 100644 ggml/src/ggml-cuda/fattn-common.cuh create mode 100644 ggml/src/ggml-cuda/fattn-mma-f16.cuh create mode 100644 ggml/src/ggml-cuda/fattn-swizzle.cuh create mode 100644 ggml/src/ggml-cuda/fattn-tile.cu create mode 100644 ggml/src/ggml-cuda/fattn-tile.cuh create mode 100644 ggml/src/ggml-cuda/fattn-vec.cuh create mode 100644 ggml/src/ggml-cuda/fattn.cu create mode 100644 ggml/src/ggml-cuda/fattn.cuh create mode 100644 ggml/src/ggml-cuda/fill.cu create mode 100644 ggml/src/ggml-cuda/fill.cuh create mode 100644 ggml/src/ggml-cuda/fwht.cu create mode 100644 ggml/src/ggml-cuda/fwht.cuh create mode 100644 ggml/src/ggml-cuda/gated_delta_net.cu create mode 100644 ggml/src/ggml-cuda/gated_delta_net.cuh create mode 100644 ggml/src/ggml-cuda/getrows.cu create mode 100644 ggml/src/ggml-cuda/getrows.cuh create mode 100644 ggml/src/ggml-cuda/ggml-cuda.cu create mode 100644 ggml/src/ggml-cuda/gla.cu create mode 100644 ggml/src/ggml-cuda/gla.cuh create mode 100644 ggml/src/ggml-cuda/im2col.cu create mode 100644 ggml/src/ggml-cuda/im2col.cuh create mode 100644 ggml/src/ggml-cuda/lightning-indexer.cu create mode 100644 ggml/src/ggml-cuda/lightning-indexer.cuh create mode 100644 ggml/src/ggml-cuda/mean.cu create mode 100644 ggml/src/ggml-cuda/mean.cuh create mode 100644 ggml/src/ggml-cuda/mma.cuh create mode 100644 ggml/src/ggml-cuda/mmf.cu create mode 100644 ggml/src/ggml-cuda/mmf.cuh create mode 100644 ggml/src/ggml-cuda/mmid.cu create mode 100644 ggml/src/ggml-cuda/mmid.cuh create mode 100644 ggml/src/ggml-cuda/mmq-config-ampere.cuh create mode 100644 ggml/src/ggml-cuda/mmq-config-blackwell.cuh create mode 100644 ggml/src/ggml-cuda/mmq-config-cdna.cuh create mode 100644 ggml/src/ggml-cuda/mmq-config-gcn.cuh create mode 100644 ggml/src/ggml-cuda/mmq-config-pascal-dp4a.cuh create mode 100644 ggml/src/ggml-cuda/mmq-config-pascal-older.cuh create mode 100644 ggml/src/ggml-cuda/mmq-config-rdna2.cuh create mode 100644 ggml/src/ggml-cuda/mmq-config-rdna3-5.cuh create mode 100644 ggml/src/ggml-cuda/mmq-config-rdna3.cuh create mode 100644 ggml/src/ggml-cuda/mmq-config-rdna4.cuh create mode 100644 ggml/src/ggml-cuda/mmq-load-tiles.cuh create mode 100644 ggml/src/ggml-cuda/mmq-vec-dot.cuh create mode 100644 ggml/src/ggml-cuda/mmq.cu create mode 100644 ggml/src/ggml-cuda/mmq.cuh create mode 100644 ggml/src/ggml-cuda/mmvf.cu create mode 100644 ggml/src/ggml-cuda/mmvf.cuh create mode 100644 ggml/src/ggml-cuda/mmvq.cu create mode 100644 ggml/src/ggml-cuda/mmvq.cuh create mode 100644 ggml/src/ggml-cuda/moe-weighted-reduction.cu create mode 100644 ggml/src/ggml-cuda/moe-weighted-reduction.cuh create mode 100644 ggml/src/ggml-cuda/norm.cu create mode 100644 ggml/src/ggml-cuda/norm.cuh create mode 100644 ggml/src/ggml-cuda/opt-step-adamw.cu create mode 100644 ggml/src/ggml-cuda/opt-step-adamw.cuh create mode 100644 ggml/src/ggml-cuda/opt-step-sgd.cu create mode 100644 ggml/src/ggml-cuda/opt-step-sgd.cuh create mode 100644 ggml/src/ggml-cuda/out-prod.cu create mode 100644 ggml/src/ggml-cuda/out-prod.cuh create mode 100644 ggml/src/ggml-cuda/pad.cu create mode 100644 ggml/src/ggml-cuda/pad.cuh create mode 100644 ggml/src/ggml-cuda/pad_reflect_1d.cu create mode 100644 ggml/src/ggml-cuda/pad_reflect_1d.cuh create mode 100644 ggml/src/ggml-cuda/pool1d.cu create mode 100644 ggml/src/ggml-cuda/pool1d.cuh create mode 100644 ggml/src/ggml-cuda/pool2d.cu create mode 100644 ggml/src/ggml-cuda/pool2d.cuh create mode 100644 ggml/src/ggml-cuda/quantize.cu create mode 100644 ggml/src/ggml-cuda/quantize.cuh create mode 100644 ggml/src/ggml-cuda/reduce_rows.cuh create mode 100644 ggml/src/ggml-cuda/roll.cu create mode 100644 ggml/src/ggml-cuda/roll.cuh create mode 100644 ggml/src/ggml-cuda/rope.cu create mode 100644 ggml/src/ggml-cuda/rope.cuh create mode 100644 ggml/src/ggml-cuda/scale.cu create mode 100644 ggml/src/ggml-cuda/scale.cuh create mode 100644 ggml/src/ggml-cuda/set-rows.cu create mode 100644 ggml/src/ggml-cuda/set-rows.cuh create mode 100644 ggml/src/ggml-cuda/set.cu create mode 100644 ggml/src/ggml-cuda/set.cuh create mode 100644 ggml/src/ggml-cuda/snake.cu create mode 100644 ggml/src/ggml-cuda/snake.cuh create mode 100644 ggml/src/ggml-cuda/softcap.cu create mode 100644 ggml/src/ggml-cuda/softcap.cuh create mode 100644 ggml/src/ggml-cuda/softmax.cu create mode 100644 ggml/src/ggml-cuda/softmax.cuh create mode 100644 ggml/src/ggml-cuda/solve_tri.cu create mode 100644 ggml/src/ggml-cuda/solve_tri.cuh create mode 100644 ggml/src/ggml-cuda/ssm-conv.cu create mode 100644 ggml/src/ggml-cuda/ssm-conv.cuh create mode 100644 ggml/src/ggml-cuda/ssm-scan.cu create mode 100644 ggml/src/ggml-cuda/ssm-scan.cuh create mode 100644 ggml/src/ggml-cuda/sum.cu create mode 100644 ggml/src/ggml-cuda/sum.cuh create mode 100644 ggml/src/ggml-cuda/sumrows.cu create mode 100644 ggml/src/ggml-cuda/sumrows.cuh create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_1-ncols2_16.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_1-ncols2_32.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_1-ncols2_8.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_16-ncols2_1.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_16-ncols2_2.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_16-ncols2_4.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_2-ncols2_16.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_2-ncols2_32.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_2-ncols2_4.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_2-ncols2_8.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_32-ncols2_1.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_32-ncols2_2.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_4-ncols2_16.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_4-ncols2_2.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_4-ncols2_4.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_4-ncols2_8.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_64-ncols2_1.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_8-ncols2_1.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_8-ncols2_2.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_8-ncols2_4.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_8-ncols2_8.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-tile-instance-dkq112-dv112.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-tile-instance-dkq128-dv128.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-tile-instance-dkq192-dv128.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-tile-instance-dkq256-dv256.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-tile-instance-dkq320-dv256.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-tile-instance-dkq40-dv40.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-tile-instance-dkq512-dv512.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-tile-instance-dkq576-dv512.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-tile-instance-dkq64-dv64.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-tile-instance-dkq72-dv72.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-tile-instance-dkq80-dv80.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-tile-instance-dkq96-dv96.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-bf16-bf16.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-bf16-f16.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-bf16-q4_0.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-bf16-q4_1.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-bf16-q5_0.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-bf16-q5_1.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-bf16-q8_0.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-f16-bf16.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-f16-f16.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-f16-q4_0.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-f16-q4_1.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-f16-q5_0.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-f16-q5_1.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-f16-q8_0.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q4_0-bf16.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q4_0-f16.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q4_0-q4_0.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q4_0-q4_1.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q4_0-q5_0.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q4_0-q5_1.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q4_0-q8_0.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q4_1-bf16.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q4_1-f16.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q4_1-q4_0.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q4_1-q4_1.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q4_1-q5_0.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q4_1-q5_1.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q4_1-q8_0.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q5_0-bf16.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q5_0-f16.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q5_0-q4_0.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q5_0-q4_1.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q5_0-q5_0.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q5_0-q5_1.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q5_0-q8_0.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q5_1-bf16.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q5_1-f16.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q5_1-q4_0.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q5_1-q4_1.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q5_1-q5_0.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q5_1-q5_1.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q5_1-q8_0.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q8_0-bf16.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q8_0-f16.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q8_0-q4_0.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q8_0-q4_1.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q8_0-q5_0.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q8_0-q5_1.cu create mode 100644 ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q8_0-q8_0.cu create mode 100755 ggml/src/ggml-cuda/template-instances/generate_cu_files.py create mode 100644 ggml/src/ggml-cuda/template-instances/mmf-instance-ncols_1.cu create mode 100644 ggml/src/ggml-cuda/template-instances/mmf-instance-ncols_10.cu create mode 100644 ggml/src/ggml-cuda/template-instances/mmf-instance-ncols_11.cu create mode 100644 ggml/src/ggml-cuda/template-instances/mmf-instance-ncols_12.cu create mode 100644 ggml/src/ggml-cuda/template-instances/mmf-instance-ncols_13.cu create mode 100644 ggml/src/ggml-cuda/template-instances/mmf-instance-ncols_14.cu create mode 100644 ggml/src/ggml-cuda/template-instances/mmf-instance-ncols_15.cu create mode 100644 ggml/src/ggml-cuda/template-instances/mmf-instance-ncols_16.cu create mode 100644 ggml/src/ggml-cuda/template-instances/mmf-instance-ncols_2.cu create mode 100644 ggml/src/ggml-cuda/template-instances/mmf-instance-ncols_3.cu create mode 100644 ggml/src/ggml-cuda/template-instances/mmf-instance-ncols_4.cu create mode 100644 ggml/src/ggml-cuda/template-instances/mmf-instance-ncols_5.cu create mode 100644 ggml/src/ggml-cuda/template-instances/mmf-instance-ncols_6.cu create mode 100644 ggml/src/ggml-cuda/template-instances/mmf-instance-ncols_7.cu create mode 100644 ggml/src/ggml-cuda/template-instances/mmf-instance-ncols_8.cu create mode 100644 ggml/src/ggml-cuda/template-instances/mmf-instance-ncols_9.cu create mode 100644 ggml/src/ggml-cuda/template-instances/mmq-instance-iq1_s.cu create mode 100644 ggml/src/ggml-cuda/template-instances/mmq-instance-iq2_s.cu create mode 100644 ggml/src/ggml-cuda/template-instances/mmq-instance-iq2_xs.cu create mode 100644 ggml/src/ggml-cuda/template-instances/mmq-instance-iq2_xxs.cu create mode 100644 ggml/src/ggml-cuda/template-instances/mmq-instance-iq3_s.cu create mode 100644 ggml/src/ggml-cuda/template-instances/mmq-instance-iq3_xxs.cu create mode 100644 ggml/src/ggml-cuda/template-instances/mmq-instance-iq4_nl.cu create mode 100644 ggml/src/ggml-cuda/template-instances/mmq-instance-iq4_xs.cu create mode 100644 ggml/src/ggml-cuda/template-instances/mmq-instance-mxfp4.cu create mode 100644 ggml/src/ggml-cuda/template-instances/mmq-instance-nvfp4.cu create mode 100644 ggml/src/ggml-cuda/template-instances/mmq-instance-q1_0.cu create mode 100644 ggml/src/ggml-cuda/template-instances/mmq-instance-q2_0.cu create mode 100644 ggml/src/ggml-cuda/template-instances/mmq-instance-q2_k.cu create mode 100644 ggml/src/ggml-cuda/template-instances/mmq-instance-q3_k.cu create mode 100644 ggml/src/ggml-cuda/template-instances/mmq-instance-q4_0.cu create mode 100644 ggml/src/ggml-cuda/template-instances/mmq-instance-q4_1.cu create mode 100644 ggml/src/ggml-cuda/template-instances/mmq-instance-q4_k.cu create mode 100644 ggml/src/ggml-cuda/template-instances/mmq-instance-q5_0.cu create mode 100644 ggml/src/ggml-cuda/template-instances/mmq-instance-q5_1.cu create mode 100644 ggml/src/ggml-cuda/template-instances/mmq-instance-q5_k.cu create mode 100644 ggml/src/ggml-cuda/template-instances/mmq-instance-q6_k.cu create mode 100644 ggml/src/ggml-cuda/template-instances/mmq-instance-q8_0.cu create mode 100644 ggml/src/ggml-cuda/top-k.cu create mode 100644 ggml/src/ggml-cuda/top-k.cuh create mode 100644 ggml/src/ggml-cuda/topk-moe.cu create mode 100644 ggml/src/ggml-cuda/topk-moe.cuh create mode 100644 ggml/src/ggml-cuda/tri.cu create mode 100644 ggml/src/ggml-cuda/tri.cuh create mode 100644 ggml/src/ggml-cuda/tsembd.cu create mode 100644 ggml/src/ggml-cuda/tsembd.cuh create mode 100644 ggml/src/ggml-cuda/unary.cu create mode 100644 ggml/src/ggml-cuda/unary.cuh create mode 100644 ggml/src/ggml-cuda/upscale.cu create mode 100644 ggml/src/ggml-cuda/upscale.cuh create mode 100644 ggml/src/ggml-cuda/vecdotq.cuh create mode 100644 ggml/src/ggml-cuda/vendors/cuda.h create mode 100644 ggml/src/ggml-cuda/vendors/hip.h create mode 100644 ggml/src/ggml-cuda/vendors/musa.h create mode 100644 ggml/src/ggml-cuda/wkv.cu create mode 100644 ggml/src/ggml-cuda/wkv.cuh create mode 100644 ggml/src/ggml-et/CMakeLists.txt create mode 100644 ggml/src/ggml-et/cmake/embed_one_kernel.cmake create mode 100644 ggml/src/ggml-et/cmake/ggml-et-kernels-embed.cpp.in create mode 100644 ggml/src/ggml-et/cmake/ggml-et-kernels-embed.hpp.in create mode 100644 ggml/src/ggml-et/cmake/ggml-et-uberkernel-kernel-map.cpp.in create mode 100644 ggml/src/ggml-et/cmake/ggml-et-uberkernel-kernel-map.h.in create mode 100644 ggml/src/ggml-et/et-kernels/CMakeLists.txt create mode 100755 ggml/src/ggml-et/et-kernels/scripts/check_unimplemented_instructions.sh create mode 100644 ggml/src/ggml-et/et-kernels/src/RunBackend.sh create mode 100644 ggml/src/ggml-et/et-kernels/src/block_ops.h create mode 100644 ggml/src/ggml-et/et-kernels/src/clamp_f32.c create mode 100644 ggml/src/ggml-et/et-kernels/src/concat_f32.c create mode 100644 ggml/src/ggml-et/et-kernels/src/cont_f16.c create mode 100644 ggml/src/ggml-et/et-kernels/src/cont_f32.c create mode 100644 ggml/src/ggml-et/et-kernels/src/conv_2d_f32_me.c create mode 100644 ggml/src/ggml-et/et-kernels/src/cpy_f32_f16.c create mode 100644 ggml/src/ggml-et/et-kernels/src/crt.S create mode 100644 ggml/src/ggml-et/et-kernels/src/cumsum_f32.c create mode 100644 ggml/src/ggml-et/et-kernels/src/diag_f32.c create mode 100644 ggml/src/ggml-et/et-kernels/src/el_map_f32.c create mode 100644 ggml/src/ggml-et/et-kernels/src/fill_f32.c create mode 100644 ggml/src/ggml-et/et-kernels/src/flash_attn_ext_f16_me.c create mode 100644 ggml/src/ggml-et/et-kernels/src/flash_attn_ext_f32.c create mode 100644 ggml/src/ggml-et/et-kernels/src/gated_delta_net_f32.c create mode 100644 ggml/src/ggml-et/et-kernels/src/get_rows_f32.c create mode 100644 ggml/src/ggml-et/et-kernels/src/ggml_tensor.h create mode 100644 ggml/src/ggml-et/et-kernels/src/glu_f32.c create mode 100644 ggml/src/ggml-et/et-kernels/src/group_norm_f32.c create mode 100644 ggml/src/ggml-et/et-kernels/src/im2col.c create mode 100644 ggml/src/ggml-et/et-kernels/src/l2_norm_f32.c create mode 100644 ggml/src/ggml-et/et-kernels/src/linker.ld create mode 100644 ggml/src/ggml-et/et-kernels/src/math_fp.h create mode 100644 ggml/src/ggml-et/et-kernels/src/mean_f32.c create mode 100644 ggml/src/ggml-et/et-kernels/src/memops.c create mode 100644 ggml/src/ggml-et/et-kernels/src/mul_mat_Q4_0.c create mode 100644 ggml/src/ggml-et/et-kernels/src/mul_mat_Q4_0_matrix_engine.c create mode 100644 ggml/src/ggml-et/et-kernels/src/mul_mat_Q8_0.c create mode 100644 ggml/src/ggml-et/et-kernels/src/mul_mat_f16.c create mode 100644 ggml/src/ggml-et/et-kernels/src/mul_mat_f16_matrix_engine.c create mode 100644 ggml/src/ggml-et/et-kernels/src/mul_mat_f32.c create mode 100644 ggml/src/ggml-et/et-kernels/src/mul_mat_f32_matrix_engine.c create mode 100644 ggml/src/ggml-et/et-kernels/src/mul_mat_id_Q4_0.c create mode 100644 ggml/src/ggml-et/et-kernels/src/mul_mat_id_Q8_0.c create mode 100644 ggml/src/ggml-et/et-kernels/src/mul_mat_id_f32.c create mode 100644 ggml/src/ggml-et/et-kernels/src/norm_f32.c create mode 100644 ggml/src/ggml-et/et-kernels/src/pad_f32.c create mode 100644 ggml/src/ggml-et/et-kernels/src/platform.h create mode 100644 ggml/src/ggml-et/et-kernels/src/quants.h create mode 100644 ggml/src/ggml-et/et-kernels/src/repeat_f32.c create mode 100644 ggml/src/ggml-et/et-kernels/src/rms_norm_f32.c create mode 100644 ggml/src/ggml-et/et-kernels/src/rms_norm_mul_f32.c create mode 100644 ggml/src/ggml-et/et-kernels/src/rope_f32.c create mode 100644 ggml/src/ggml-et/et-kernels/src/rwkv_wkv6_f32.c create mode 100644 ggml/src/ggml-et/et-kernels/src/rwkv_wkv7_f32.c create mode 100644 ggml/src/ggml-et/et-kernels/src/scale_f32.c create mode 100644 ggml/src/ggml-et/et-kernels/src/set_f32.c create mode 100644 ggml/src/ggml-et/et-kernels/src/set_rows_f32.c create mode 100644 ggml/src/ggml-et/et-kernels/src/softmax_f32.c create mode 100644 ggml/src/ggml-et/et-kernels/src/solve_tri_f32.c create mode 100644 ggml/src/ggml-et/et-kernels/src/sqr_f32.c create mode 100644 ggml/src/ggml-et/et-kernels/src/ssm_conv_f32.c create mode 100644 ggml/src/ggml-et/et-kernels/src/ssm_scan_f32.c create mode 100644 ggml/src/ggml-et/et-kernels/src/sum_rows_f32.c create mode 100644 ggml/src/ggml-et/et-kernels/src/tensor.h create mode 100644 ggml/src/ggml-et/et-kernels/src/tri_f32.c create mode 100644 ggml/src/ggml-et/et-kernels/src/uberkernel.c create mode 100644 ggml/src/ggml-et/et-kernels/src/unary_f32.c create mode 100644 ggml/src/ggml-et/ggml-et-common.h create mode 100644 ggml/src/ggml-et/ggml-et-cpu-compare.cpp create mode 100644 ggml/src/ggml-et/ggml-et-cpu-compare.h create mode 100644 ggml/src/ggml-et/ggml-et-kernels.cpp create mode 100644 ggml/src/ggml-et/ggml-et-kernels.h create mode 100644 ggml/src/ggml-et/ggml-et-memops.cpp create mode 100644 ggml/src/ggml-et/ggml-et-memops.h create mode 100644 ggml/src/ggml-et/ggml-et-ops.cpp create mode 100644 ggml/src/ggml-et/ggml-et-ops.h create mode 100644 ggml/src/ggml-et/ggml-et-uberkernel-common.h create mode 100644 ggml/src/ggml-et/ggml-et.cpp create mode 100644 ggml/src/ggml-feats.h create mode 100644 ggml/src/ggml-hexagon/CMakeLists.txt create mode 100644 ggml/src/ggml-hexagon/ggml-hexagon.cpp create mode 100644 ggml/src/ggml-hexagon/htp-drv.cpp create mode 100644 ggml/src/ggml-hexagon/htp-drv.h create mode 100644 ggml/src/ggml-hexagon/htp-opnode.h create mode 100644 ggml/src/ggml-hexagon/htp/CMakeLists.txt create mode 100644 ggml/src/ggml-hexagon/htp/act-ops.c create mode 100644 ggml/src/ggml-hexagon/htp/allreduce-ops.c create mode 100644 ggml/src/ggml-hexagon/htp/allreduce-ops.h create mode 100644 ggml/src/ggml-hexagon/htp/argsort-ops.c create mode 100644 ggml/src/ggml-hexagon/htp/binary-ops.c create mode 100644 ggml/src/ggml-hexagon/htp/cmake-toolchain.cmake create mode 100644 ggml/src/ggml-hexagon/htp/concat-ops.c create mode 100644 ggml/src/ggml-hexagon/htp/cpy-ops.c create mode 100644 ggml/src/ggml-hexagon/htp/cumsum-ops.c create mode 100644 ggml/src/ggml-hexagon/htp/diag-ops.c create mode 100644 ggml/src/ggml-hexagon/htp/dma-queue.c create mode 100644 ggml/src/ggml-hexagon/htp/dma-queue.h create mode 100644 ggml/src/ggml-hexagon/htp/fill-ops.c create mode 100644 ggml/src/ggml-hexagon/htp/flash-attn-ops.c create mode 100644 ggml/src/ggml-hexagon/htp/flash-attn-ops.h create mode 100644 ggml/src/ggml-hexagon/htp/gated-delta-net-ops.c create mode 100644 ggml/src/ggml-hexagon/htp/get-rows-ops.c create mode 100644 ggml/src/ggml-hexagon/htp/get-rows-ops.h create mode 100644 ggml/src/ggml-hexagon/htp/hex-bitmap.h create mode 100644 ggml/src/ggml-hexagon/htp/hex-common.h create mode 100644 ggml/src/ggml-hexagon/htp/hex-dma.h create mode 100644 ggml/src/ggml-hexagon/htp/hex-dump.h create mode 100644 ggml/src/ggml-hexagon/htp/hex-fastdiv.h create mode 100644 ggml/src/ggml-hexagon/htp/hex-profile.h create mode 100644 ggml/src/ggml-hexagon/htp/hex-utils.h create mode 100644 ggml/src/ggml-hexagon/htp/hmx-fa-kernels.h create mode 100644 ggml/src/ggml-hexagon/htp/hmx-mm-kernels-tiled.h create mode 100644 ggml/src/ggml-hexagon/htp/hmx-queue.c create mode 100644 ggml/src/ggml-hexagon/htp/hmx-queue.h create mode 100644 ggml/src/ggml-hexagon/htp/hmx-utils.h create mode 100644 ggml/src/ggml-hexagon/htp/htp-ctx.h create mode 100644 ggml/src/ggml-hexagon/htp/htp-fence.h create mode 100644 ggml/src/ggml-hexagon/htp/htp-ops.h create mode 100644 ggml/src/ggml-hexagon/htp/htp-tensor.c create mode 100644 ggml/src/ggml-hexagon/htp/htp-tensor.h create mode 100644 ggml/src/ggml-hexagon/htp/htp-vtcm.h create mode 100644 ggml/src/ggml-hexagon/htp/htp_iface.idl create mode 100644 ggml/src/ggml-hexagon/htp/hvx-arith.h create mode 100644 ggml/src/ggml-hexagon/htp/hvx-base.h create mode 100644 ggml/src/ggml-hexagon/htp/hvx-copy.h create mode 100644 ggml/src/ggml-hexagon/htp/hvx-div.h create mode 100644 ggml/src/ggml-hexagon/htp/hvx-dump.h create mode 100644 ggml/src/ggml-hexagon/htp/hvx-exp.h create mode 100644 ggml/src/ggml-hexagon/htp/hvx-fa-kernels.h create mode 100644 ggml/src/ggml-hexagon/htp/hvx-flash-attn.h create mode 100644 ggml/src/ggml-hexagon/htp/hvx-floor.h create mode 100644 ggml/src/ggml-hexagon/htp/hvx-inverse.h create mode 100644 ggml/src/ggml-hexagon/htp/hvx-log.h create mode 100644 ggml/src/ggml-hexagon/htp/hvx-mm-kernels-flat.h create mode 100644 ggml/src/ggml-hexagon/htp/hvx-mm-kernels-tiled.h create mode 100644 ggml/src/ggml-hexagon/htp/hvx-norm.h create mode 100644 ggml/src/ggml-hexagon/htp/hvx-pow.h create mode 100644 ggml/src/ggml-hexagon/htp/hvx-quant.h create mode 100644 ggml/src/ggml-hexagon/htp/hvx-reduce.h create mode 100644 ggml/src/ggml-hexagon/htp/hvx-repl.h create mode 100644 ggml/src/ggml-hexagon/htp/hvx-scale.h create mode 100644 ggml/src/ggml-hexagon/htp/hvx-sigmoid.h create mode 100644 ggml/src/ggml-hexagon/htp/hvx-sin-cos.h create mode 100644 ggml/src/ggml-hexagon/htp/hvx-sqrt.h create mode 100644 ggml/src/ggml-hexagon/htp/hvx-types.h create mode 100644 ggml/src/ggml-hexagon/htp/hvx-utils.h create mode 100644 ggml/src/ggml-hexagon/htp/im2col-ops.c create mode 100644 ggml/src/ggml-hexagon/htp/main.c create mode 100644 ggml/src/ggml-hexagon/htp/matmul-ops.c create mode 100644 ggml/src/ggml-hexagon/htp/matmul-ops.h create mode 100644 ggml/src/ggml-hexagon/htp/pad-ops.c create mode 100644 ggml/src/ggml-hexagon/htp/repeat-ops.c create mode 100644 ggml/src/ggml-hexagon/htp/rope-ops.c create mode 100644 ggml/src/ggml-hexagon/htp/rope-ops.h create mode 100644 ggml/src/ggml-hexagon/htp/set-rows-ops.c create mode 100644 ggml/src/ggml-hexagon/htp/set-rows-ops.h create mode 100644 ggml/src/ggml-hexagon/htp/softmax-ops.c create mode 100644 ggml/src/ggml-hexagon/htp/solve-tri-ops.c create mode 100644 ggml/src/ggml-hexagon/htp/ssm-conv.c create mode 100644 ggml/src/ggml-hexagon/htp/sum-rows-ops.c create mode 100644 ggml/src/ggml-hexagon/htp/unary-ops.c create mode 100644 ggml/src/ggml-hexagon/htp/unary-ops.h create mode 100644 ggml/src/ggml-hexagon/htp/work-queue.c create mode 100644 ggml/src/ggml-hexagon/htp/work-queue.h create mode 100644 ggml/src/ggml-hexagon/libdl.h create mode 100644 ggml/src/ggml-hexagon/libggml-htp.inf create mode 100644 ggml/src/ggml-hip/CMakeLists.txt create mode 100644 ggml/src/ggml-impl.h create mode 100644 ggml/src/ggml-metal/CMakeLists.txt create mode 100644 ggml/src/ggml-metal/ggml-metal-common.cpp create mode 100644 ggml/src/ggml-metal/ggml-metal-common.h create mode 100644 ggml/src/ggml-metal/ggml-metal-context.h create mode 100644 ggml/src/ggml-metal/ggml-metal-context.m create mode 100644 ggml/src/ggml-metal/ggml-metal-device.cpp create mode 100644 ggml/src/ggml-metal/ggml-metal-device.h create mode 100644 ggml/src/ggml-metal/ggml-metal-device.m create mode 100644 ggml/src/ggml-metal/ggml-metal-fusion.cpp create mode 100644 ggml/src/ggml-metal/ggml-metal-fusion.h create mode 100644 ggml/src/ggml-metal/ggml-metal-impl.h create mode 100644 ggml/src/ggml-metal/ggml-metal-ops.cpp create mode 100644 ggml/src/ggml-metal/ggml-metal-ops.h create mode 100644 ggml/src/ggml-metal/ggml-metal-tuning.cpp create mode 100644 ggml/src/ggml-metal/ggml-metal-tuning.h create mode 100644 ggml/src/ggml-metal/ggml-metal.cpp create mode 100644 ggml/src/ggml-metal/kernels/argsort.metal create mode 100644 ggml/src/ggml-metal/kernels/binbcast.metal create mode 100644 ggml/src/ggml-metal/kernels/common.h create mode 100644 ggml/src/ggml-metal/kernels/conv.metal create mode 100644 ggml/src/ggml-metal/kernels/dequantize.h create mode 100644 ggml/src/ggml-metal/kernels/fa.metal create mode 100644 ggml/src/ggml-metal/kernels/gated_delta_net.metal create mode 100644 ggml/src/ggml-metal/kernels/misc.metal create mode 100644 ggml/src/ggml-metal/kernels/mul_mm.metal create mode 100644 ggml/src/ggml-metal/kernels/mul_mv.metal create mode 100644 ggml/src/ggml-metal/kernels/norm.metal create mode 100644 ggml/src/ggml-metal/kernels/pool.metal create mode 100644 ggml/src/ggml-metal/kernels/quantize.h create mode 100644 ggml/src/ggml-metal/kernels/quantize.metal create mode 100644 ggml/src/ggml-metal/kernels/reduce.metal create mode 100644 ggml/src/ggml-metal/kernels/rope.metal create mode 100644 ggml/src/ggml-metal/kernels/softmax.metal create mode 100644 ggml/src/ggml-metal/kernels/solve_tri.metal create mode 100644 ggml/src/ggml-metal/kernels/ssm.metal create mode 100644 ggml/src/ggml-metal/kernels/tri.metal create mode 100644 ggml/src/ggml-metal/kernels/unary.metal create mode 100644 ggml/src/ggml-metal/kernels/upscale.metal create mode 100644 ggml/src/ggml-metal/kernels/wkv.metal create mode 100644 ggml/src/ggml-musa/CMakeLists.txt create mode 100644 ggml/src/ggml-musa/mudnn.cu create mode 100644 ggml/src/ggml-musa/mudnn.cuh create mode 100644 ggml/src/ggml-opencl/CMakeLists.txt create mode 100644 ggml/src/ggml-opencl/cl-program-cache.cpp create mode 100644 ggml/src/ggml-opencl/cl-program-cache.h create mode 100644 ggml/src/ggml-opencl/fa_tune.h create mode 100644 ggml/src/ggml-opencl/ggml-opencl.cpp create mode 100644 ggml/src/ggml-opencl/kernels/abs.cl create mode 100644 ggml/src/ggml-opencl/kernels/add.cl create mode 100644 ggml/src/ggml-opencl/kernels/add_id.cl create mode 100644 ggml/src/ggml-opencl/kernels/argsort.cl create mode 100644 ggml/src/ggml-opencl/kernels/clamp.cl create mode 100644 ggml/src/ggml-opencl/kernels/concat.cl create mode 100644 ggml/src/ggml-opencl/kernels/conv2d.cl create mode 100644 ggml/src/ggml-opencl/kernels/conv2d_f16_f32.cl create mode 100644 ggml/src/ggml-opencl/kernels/cpy.cl create mode 100644 ggml/src/ggml-opencl/kernels/cumsum.cl create mode 100644 ggml/src/ggml-opencl/kernels/cvt.cl create mode 100644 ggml/src/ggml-opencl/kernels/diag.cl create mode 100644 ggml/src/ggml-opencl/kernels/diag_mask_inf.cl create mode 100644 ggml/src/ggml-opencl/kernels/div.cl create mode 100644 ggml/src/ggml-opencl/kernels/embed_kernel.py create mode 100644 ggml/src/ggml-opencl/kernels/exp.cl create mode 100644 ggml/src/ggml-opencl/kernels/expm1.cl create mode 100644 ggml/src/ggml-opencl/kernels/fill.cl create mode 100644 ggml/src/ggml-opencl/kernels/flash_attn_f16.cl create mode 100644 ggml/src/ggml-opencl/kernels/flash_attn_f32.cl create mode 100644 ggml/src/ggml-opencl/kernels/flash_attn_f32_f16.cl create mode 100644 ggml/src/ggml-opencl/kernels/flash_attn_f32_q4_0.cl create mode 100644 ggml/src/ggml-opencl/kernels/flash_attn_f32_q8_0.cl create mode 100644 ggml/src/ggml-opencl/kernels/flash_attn_pre_f16.cl create mode 100644 ggml/src/ggml-opencl/kernels/gated_delta_net.cl create mode 100644 ggml/src/ggml-opencl/kernels/gelu.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemm_moe_mxfp4_f32.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemm_moe_mxfp4_f32_ns.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemm_moe_mxfp4_q8_1_dp4a.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemm_moe_q4_0_f32_ns.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemm_moe_q4_0_q8_1_dp4a.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemm_moe_q4_1_f32_ns.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemm_moe_q4_k_f32_ns.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemm_moe_q4_k_q8_1_dp4a.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemm_moe_q5_0_f32_ns.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemm_moe_q5_1_f32_ns.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemm_moe_q5_k_f32_ns.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemm_moe_q6_k_f32_ns.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemm_moe_q6_k_q8_1_dp4a.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemm_moe_q8_0_f32_ns.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemm_moe_q8_1_dp4a.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemm_noshuffle_iq4_nl_f32.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemm_noshuffle_iq4_nl_q8_1_dp4a.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemm_noshuffle_q1_0_f32.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemm_noshuffle_q4_0_f32.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemm_noshuffle_q4_0_q8_1_dp4a.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemm_noshuffle_q4_1_f32.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemm_noshuffle_q4_k_f32.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemm_noshuffle_q4_k_q8_1_dp4a.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemm_noshuffle_q5_0_f32.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemm_noshuffle_q5_0_q8_1_dp4a.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemm_noshuffle_q5_1_f32.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemm_noshuffle_q5_k_f32.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemm_noshuffle_q5_k_q8_1_dp4a.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemm_noshuffle_q6_k_f32.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemm_noshuffle_q6_k_f32_tiled.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemm_noshuffle_q6_k_q8_1_dp4a.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemm_noshuffle_q8_0_f32.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemm_noshuffle_q8_0_q8_1_dp4a.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemm_xmem_f16_f32_os8.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemv_moe_mxfp4_f32.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemv_moe_mxfp4_f32_ns.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemv_moe_q4_0_f32_ns.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemv_moe_q4_1_f32_ns.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemv_moe_q4_k_f32_ns.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemv_moe_q5_0_f32_ns.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemv_moe_q5_1_f32_ns.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemv_moe_q5_k_f32_ns.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemv_moe_q6_k_f32_ns.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemv_noshuffle_iq4_nl_f32.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemv_noshuffle_q1_0_f32.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemv_noshuffle_q4_0_f32.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemv_noshuffle_q4_0_f32_32b_trans.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemv_noshuffle_q4_0_f32_spec.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemv_noshuffle_q4_1_f32.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemv_noshuffle_q4_k_f32.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemv_noshuffle_q4_k_f32_32b_trans.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemv_noshuffle_q4_k_f32_o4.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemv_noshuffle_q4_k_f32_tiled.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemv_noshuffle_q5_0_f32.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemv_noshuffle_q5_1_f32.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemv_noshuffle_q5_k_f32.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemv_noshuffle_q6_k_f32.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemv_noshuffle_q6_k_f32_o4.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemv_noshuffle_q6_k_f32_tiled.cl create mode 100644 ggml/src/ggml-opencl/kernels/gemv_noshuffle_q8_0_f32.cl create mode 100644 ggml/src/ggml-opencl/kernels/get_rows.cl create mode 100644 ggml/src/ggml-opencl/kernels/glu.cl create mode 100644 ggml/src/ggml-opencl/kernels/group_norm.cl create mode 100644 ggml/src/ggml-opencl/kernels/im2col_f16.cl create mode 100644 ggml/src/ggml-opencl/kernels/im2col_f32.cl create mode 100644 ggml/src/ggml-opencl/kernels/l2_norm.cl create mode 100644 ggml/src/ggml-opencl/kernels/mean.cl create mode 100644 ggml/src/ggml-opencl/kernels/moe_add_id_glu.cl create mode 100644 ggml/src/ggml-opencl/kernels/moe_combine.cl create mode 100644 ggml/src/ggml-opencl/kernels/moe_reorder_b.cl create mode 100644 ggml/src/ggml-opencl/kernels/moe_reorder_quant_a_q8_1.cl create mode 100644 ggml/src/ggml-opencl/kernels/moe_sort_by_expert.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mat_f16_f32.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mm_f16_f32_kq_kqv.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mm_f16_f32_l4_lm.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mm_f32_f32_l4_lm.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mm_iq4_nl_f32_l4_lm.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mm_q1_0_f32_l4_lm.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mm_q4_0_f32_l4_lm.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mm_q4_1_f32_l4_lm.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mm_q4_k_f32_l4_lm.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mm_q5_0_f32_l4_lm.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mm_q5_1_f32_l4_lm.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mm_q5_k_f32_l4_lm.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mm_q6_k_f32_l4_lm.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mm_q8_0_f32_l4_lm.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mv_f16_f16.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mv_f16_f32.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mv_f16_f32_1row.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mv_f16_f32_l4.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mv_f16_f32_mrow.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mv_f32_f32.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mv_id_mxfp4_f32.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mv_id_mxfp4_f32_flat.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mv_id_q4_0_f32_8x_flat.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mv_id_q8_0_f32.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mv_id_q8_0_f32_flat.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mv_iq4_nl_f32.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mv_iq4_nl_f32_flat.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mv_mxfp4_f32.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mv_mxfp4_f32_flat.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mv_q1_0_f32.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mv_q1_0_f32_flat.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mv_q4_0_f32.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mv_q4_0_f32_1d_16x_flat.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mv_q4_0_f32_1d_8x_flat.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mv_q4_0_f32_8x_flat.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mv_q4_0_f32_v.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mv_q4_1_f32.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mv_q4_1_f32_flat.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mv_q4_k_f32.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mv_q4_k_f32_flat.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mv_q5_0_f32.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mv_q5_0_f32_flat.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mv_q5_1_f32.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mv_q5_1_f32_flat.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mv_q5_k_f32.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mv_q5_k_f32_flat.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mv_q6_k_f32.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mv_q6_k_f32_flat.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mv_q8_0_f32.cl create mode 100644 ggml/src/ggml-opencl/kernels/mul_mv_q8_0_f32_flat.cl create mode 100644 ggml/src/ggml-opencl/kernels/neg.cl create mode 100644 ggml/src/ggml-opencl/kernels/norm.cl create mode 100644 ggml/src/ggml-opencl/kernels/pad.cl create mode 100644 ggml/src/ggml-opencl/kernels/quant_a_q8_1.cl create mode 100644 ggml/src/ggml-opencl/kernels/relu.cl create mode 100644 ggml/src/ggml-opencl/kernels/repeat.cl create mode 100644 ggml/src/ggml-opencl/kernels/rms_norm.cl create mode 100644 ggml/src/ggml-opencl/kernels/rope.cl create mode 100644 ggml/src/ggml-opencl/kernels/scale.cl create mode 100644 ggml/src/ggml-opencl/kernels/sdpa_xmem_f32_f16_os8.cl create mode 100644 ggml/src/ggml-opencl/kernels/set_rows.cl create mode 100644 ggml/src/ggml-opencl/kernels/sigmoid.cl create mode 100644 ggml/src/ggml-opencl/kernels/silu.cl create mode 100644 ggml/src/ggml-opencl/kernels/softmax_4_f16.cl create mode 100644 ggml/src/ggml-opencl/kernels/softmax_4_f32.cl create mode 100644 ggml/src/ggml-opencl/kernels/softmax_f16.cl create mode 100644 ggml/src/ggml-opencl/kernels/softmax_f32.cl create mode 100644 ggml/src/ggml-opencl/kernels/softplus.cl create mode 100644 ggml/src/ggml-opencl/kernels/solve_tri.cl create mode 100644 ggml/src/ggml-opencl/kernels/sqr.cl create mode 100644 ggml/src/ggml-opencl/kernels/sqrt.cl create mode 100644 ggml/src/ggml-opencl/kernels/ssm_conv.cl create mode 100644 ggml/src/ggml-opencl/kernels/ssm_scan.cl create mode 100644 ggml/src/ggml-opencl/kernels/sub.cl create mode 100644 ggml/src/ggml-opencl/kernels/sum_rows.cl create mode 100644 ggml/src/ggml-opencl/kernels/tanh.cl create mode 100644 ggml/src/ggml-opencl/kernels/transpose.cl create mode 100644 ggml/src/ggml-opencl/kernels/tri.cl create mode 100644 ggml/src/ggml-opencl/kernels/tsembd.cl create mode 100644 ggml/src/ggml-opencl/kernels/unary_ext.cl create mode 100644 ggml/src/ggml-opencl/kernels/upscale.cl create mode 100644 ggml/src/ggml-opencl/libdl.h create mode 100644 ggml/src/ggml-openvino/.clang-format create mode 100644 ggml/src/ggml-openvino/CMakeLists.txt create mode 100644 ggml/src/ggml-openvino/ggml-decoder.cpp create mode 100644 ggml/src/ggml-openvino/ggml-decoder.h create mode 100644 ggml/src/ggml-openvino/ggml-openvino-extra.cpp create mode 100644 ggml/src/ggml-openvino/ggml-openvino-extra.h create mode 100644 ggml/src/ggml-openvino/ggml-openvino.cpp create mode 100644 ggml/src/ggml-openvino/ggml-quants.cpp create mode 100644 ggml/src/ggml-openvino/ggml-quants.h create mode 100644 ggml/src/ggml-openvino/model-cache.cpp create mode 100644 ggml/src/ggml-openvino/model-cache.h create mode 100644 ggml/src/ggml-openvino/openvino/decoder.h create mode 100644 ggml/src/ggml-openvino/openvino/frontend.cpp create mode 100644 ggml/src/ggml-openvino/openvino/frontend.h create mode 100644 ggml/src/ggml-openvino/openvino/input_model.cpp create mode 100644 ggml/src/ggml-openvino/openvino/input_model.h create mode 100644 ggml/src/ggml-openvino/openvino/node_context.h create mode 100644 ggml/src/ggml-openvino/openvino/op/add.cpp create mode 100644 ggml/src/ggml-openvino/openvino/op/add_id.cpp create mode 100644 ggml/src/ggml-openvino/openvino/op/argsort.cpp create mode 100644 ggml/src/ggml-openvino/openvino/op/clamp.cpp create mode 100644 ggml/src/ggml-openvino/openvino/op/concat.cpp create mode 100644 ggml/src/ggml-openvino/openvino/op/cont.cpp create mode 100644 ggml/src/ggml-openvino/openvino/op/cpy.cpp create mode 100644 ggml/src/ggml-openvino/openvino/op/cumsum.cpp create mode 100644 ggml/src/ggml-openvino/openvino/op/diag.cpp create mode 100644 ggml/src/ggml-openvino/openvino/op/div.cpp create mode 100644 ggml/src/ggml-openvino/openvino/op/fill.cpp create mode 100644 ggml/src/ggml-openvino/openvino/op/flash_attn_ext.cpp create mode 100644 ggml/src/ggml-openvino/openvino/op/gated_delta_net.cpp create mode 100644 ggml/src/ggml-openvino/openvino/op/gated_delta_net.hpp create mode 100644 ggml/src/ggml-openvino/openvino/op/gather_matmul.hpp create mode 100644 ggml/src/ggml-openvino/openvino/op/get_rows.cpp create mode 100644 ggml/src/ggml-openvino/openvino/op/glu_geglu.cpp create mode 100644 ggml/src/ggml-openvino/openvino/op/glu_geglu_quick.cpp create mode 100644 ggml/src/ggml-openvino/openvino/op/glu_swiglu.cpp create mode 100644 ggml/src/ggml-openvino/openvino/op/im2col.cpp create mode 100644 ggml/src/ggml-openvino/openvino/op/l2_norm.cpp create mode 100644 ggml/src/ggml-openvino/openvino/op/mul_mat_id.cpp create mode 100644 ggml/src/ggml-openvino/openvino/op/mulmat.cpp create mode 100644 ggml/src/ggml-openvino/openvino/op/norm.cpp create mode 100644 ggml/src/ggml-openvino/openvino/op/pad.cpp create mode 100644 ggml/src/ggml-openvino/openvino/op/permute.cpp create mode 100644 ggml/src/ggml-openvino/openvino/op/pool_2d.cpp create mode 100644 ggml/src/ggml-openvino/openvino/op/repeat.cpp create mode 100644 ggml/src/ggml-openvino/openvino/op/reshape.cpp create mode 100644 ggml/src/ggml-openvino/openvino/op/rms_norm.cpp create mode 100644 ggml/src/ggml-openvino/openvino/op/roll.cpp create mode 100644 ggml/src/ggml-openvino/openvino/op/rope.cpp create mode 100644 ggml/src/ggml-openvino/openvino/op/scale.cpp create mode 100644 ggml/src/ggml-openvino/openvino/op/set.cpp create mode 100644 ggml/src/ggml-openvino/openvino/op/set_rows.cpp create mode 100644 ggml/src/ggml-openvino/openvino/op/softmax.cpp create mode 100644 ggml/src/ggml-openvino/openvino/op/solve_tri.cpp create mode 100644 ggml/src/ggml-openvino/openvino/op/sqr.cpp create mode 100644 ggml/src/ggml-openvino/openvino/op/ssm_conv.cpp create mode 100644 ggml/src/ggml-openvino/openvino/op/sum_rows.cpp create mode 100644 ggml/src/ggml-openvino/openvino/op/transpose.cpp create mode 100644 ggml/src/ggml-openvino/openvino/op/tri.cpp create mode 100644 ggml/src/ggml-openvino/openvino/op/unary_silu.cpp create mode 100644 ggml/src/ggml-openvino/openvino/op/unary_softplus.cpp create mode 100644 ggml/src/ggml-openvino/openvino/op/view.cpp create mode 100644 ggml/src/ggml-openvino/openvino/op_table.cpp create mode 100644 ggml/src/ggml-openvino/openvino/op_table.h create mode 100644 ggml/src/ggml-openvino/openvino/pass/fuse_to_conv.cpp create mode 100644 ggml/src/ggml-openvino/openvino/pass/fuse_to_conv.h create mode 100644 ggml/src/ggml-openvino/openvino/pass/fuse_to_sdpa.cpp create mode 100644 ggml/src/ggml-openvino/openvino/pass/fuse_to_sdpa.h create mode 100644 ggml/src/ggml-openvino/openvino/pass/mark_decompression_convert_constant_folding.h create mode 100644 ggml/src/ggml-openvino/openvino/pass/mark_dequantization_subgraph.h create mode 100644 ggml/src/ggml-openvino/openvino/pass/squeeze_matmul.cpp create mode 100644 ggml/src/ggml-openvino/openvino/pass/squeeze_matmul.h create mode 100644 ggml/src/ggml-openvino/openvino/rt_info/weightless_caching_attributes.hpp create mode 100644 ggml/src/ggml-openvino/openvino/translate_session.cpp create mode 100644 ggml/src/ggml-openvino/openvino/translate_session.h create mode 100644 ggml/src/ggml-openvino/openvino/utils.cpp create mode 100644 ggml/src/ggml-openvino/openvino/utils.h create mode 100644 ggml/src/ggml-openvino/utils.cpp create mode 100644 ggml/src/ggml-openvino/utils.h create mode 100644 ggml/src/ggml-opt.cpp create mode 100644 ggml/src/ggml-quants.c create mode 100644 ggml/src/ggml-quants.h create mode 100644 ggml/src/ggml-rpc/CMakeLists.txt create mode 100644 ggml/src/ggml-rpc/ggml-rpc.cpp create mode 100644 ggml/src/ggml-rpc/transport-apple.cpp create mode 100644 ggml/src/ggml-rpc/transport-apple.h create mode 100644 ggml/src/ggml-rpc/transport.cpp create mode 100644 ggml/src/ggml-rpc/transport.h create mode 100644 ggml/src/ggml-sycl/CMakeLists.txt create mode 100644 ggml/src/ggml-sycl/add-id.cpp create mode 100644 ggml/src/ggml-sycl/add-id.hpp create mode 100644 ggml/src/ggml-sycl/backend.hpp create mode 100644 ggml/src/ggml-sycl/base.hpp create mode 100644 ggml/src/ggml-sycl/binbcast.cpp create mode 100644 ggml/src/ggml-sycl/binbcast.hpp create mode 100644 ggml/src/ggml-sycl/col2im-1d.cpp create mode 100644 ggml/src/ggml-sycl/col2im-1d.hpp create mode 100644 ggml/src/ggml-sycl/common.cpp create mode 100644 ggml/src/ggml-sycl/common.hpp create mode 100644 ggml/src/ggml-sycl/concat.cpp create mode 100644 ggml/src/ggml-sycl/concat.hpp create mode 100644 ggml/src/ggml-sycl/conv.cpp create mode 100644 ggml/src/ggml-sycl/conv.hpp create mode 100644 ggml/src/ggml-sycl/conv2d-dw.cpp create mode 100644 ggml/src/ggml-sycl/conv2d-dw.hpp create mode 100644 ggml/src/ggml-sycl/conv2d-transpose.cpp create mode 100644 ggml/src/ggml-sycl/conv2d-transpose.hpp create mode 100644 ggml/src/ggml-sycl/conv2d.cpp create mode 100644 ggml/src/ggml-sycl/conv2d.hpp create mode 100644 ggml/src/ggml-sycl/conv3d.cpp create mode 100644 ggml/src/ggml-sycl/conv3d.hpp create mode 100644 ggml/src/ggml-sycl/convert.cpp create mode 100644 ggml/src/ggml-sycl/convert.hpp create mode 100644 ggml/src/ggml-sycl/count-equal.cpp create mode 100644 ggml/src/ggml-sycl/count-equal.hpp create mode 100644 ggml/src/ggml-sycl/cpy.cpp create mode 100644 ggml/src/ggml-sycl/cpy.hpp create mode 100644 ggml/src/ggml-sycl/cross_entropy_loss.cpp create mode 100644 ggml/src/ggml-sycl/cross_entropy_loss.hpp create mode 100644 ggml/src/ggml-sycl/cumsum.cpp create mode 100644 ggml/src/ggml-sycl/cumsum.hpp create mode 100644 ggml/src/ggml-sycl/dequantize.hpp create mode 100644 ggml/src/ggml-sycl/diag.cpp create mode 100644 ggml/src/ggml-sycl/diag.hpp create mode 100644 ggml/src/ggml-sycl/dmmv.cpp create mode 100644 ggml/src/ggml-sycl/dmmv.hpp create mode 100644 ggml/src/ggml-sycl/dpct/helper.hpp create mode 100644 ggml/src/ggml-sycl/dsv4-hc.cpp create mode 100644 ggml/src/ggml-sycl/dsv4-hc.hpp create mode 100644 ggml/src/ggml-sycl/element_wise.cpp create mode 100644 ggml/src/ggml-sycl/element_wise.hpp create mode 100644 ggml/src/ggml-sycl/esimd.hpp create mode 100644 ggml/src/ggml-sycl/fattn-buffers.cpp create mode 100644 ggml/src/ggml-sycl/fattn-buffers.hpp create mode 100644 ggml/src/ggml-sycl/fattn-common.hpp create mode 100644 ggml/src/ggml-sycl/fattn-mkl.cpp create mode 100644 ggml/src/ggml-sycl/fattn-onednn.cpp create mode 100644 ggml/src/ggml-sycl/fattn-onednn.hpp create mode 100644 ggml/src/ggml-sycl/fattn-tile.cpp create mode 100644 ggml/src/ggml-sycl/fattn-tile.hpp create mode 100644 ggml/src/ggml-sycl/fattn-vec.hpp create mode 100644 ggml/src/ggml-sycl/fattn.cpp create mode 100644 ggml/src/ggml-sycl/fattn.hpp create mode 100644 ggml/src/ggml-sycl/fill.cpp create mode 100644 ggml/src/ggml-sycl/fill.hpp create mode 100644 ggml/src/ggml-sycl/fusion.cpp create mode 100644 ggml/src/ggml-sycl/fusion.hpp create mode 100644 ggml/src/ggml-sycl/fwht.cpp create mode 100644 ggml/src/ggml-sycl/fwht.hpp create mode 100644 ggml/src/ggml-sycl/gated_delta_net.cpp create mode 100644 ggml/src/ggml-sycl/gated_delta_net.hpp create mode 100644 ggml/src/ggml-sycl/gemm.hpp create mode 100644 ggml/src/ggml-sycl/getrows.cpp create mode 100644 ggml/src/ggml-sycl/getrows.hpp create mode 100644 ggml/src/ggml-sycl/ggml-sycl.cpp create mode 100644 ggml/src/ggml-sycl/gla.cpp create mode 100644 ggml/src/ggml-sycl/gla.hpp create mode 100644 ggml/src/ggml-sycl/im2col.cpp create mode 100644 ggml/src/ggml-sycl/im2col.hpp create mode 100644 ggml/src/ggml-sycl/lightning-indexer.cpp create mode 100644 ggml/src/ggml-sycl/lightning-indexer.hpp create mode 100644 ggml/src/ggml-sycl/mem.cpp create mode 100644 ggml/src/ggml-sycl/mem.hpp create mode 100644 ggml/src/ggml-sycl/memtrace.cpp create mode 100644 ggml/src/ggml-sycl/memtrace.hpp create mode 100644 ggml/src/ggml-sycl/mmq.cpp create mode 100644 ggml/src/ggml-sycl/mmq.hpp create mode 100644 ggml/src/ggml-sycl/mmvq.cpp create mode 100644 ggml/src/ggml-sycl/mmvq.hpp create mode 100644 ggml/src/ggml-sycl/norm.cpp create mode 100644 ggml/src/ggml-sycl/norm.hpp create mode 100644 ggml/src/ggml-sycl/opt-step.cpp create mode 100644 ggml/src/ggml-sycl/opt-step.hpp create mode 100644 ggml/src/ggml-sycl/outprod.cpp create mode 100644 ggml/src/ggml-sycl/outprod.hpp create mode 100644 ggml/src/ggml-sycl/pad.cpp create mode 100644 ggml/src/ggml-sycl/pad.hpp create mode 100644 ggml/src/ggml-sycl/pad_reflect_1d.cpp create mode 100644 ggml/src/ggml-sycl/pad_reflect_1d.hpp create mode 100644 ggml/src/ggml-sycl/pool.cpp create mode 100644 ggml/src/ggml-sycl/pool.hpp create mode 100644 ggml/src/ggml-sycl/presets.hpp create mode 100644 ggml/src/ggml-sycl/quantize.hpp create mode 100644 ggml/src/ggml-sycl/quants.hpp create mode 100644 ggml/src/ggml-sycl/repeat_back.cpp create mode 100644 ggml/src/ggml-sycl/repeat_back.hpp create mode 100644 ggml/src/ggml-sycl/roll.cpp create mode 100644 ggml/src/ggml-sycl/roll.hpp create mode 100644 ggml/src/ggml-sycl/rope.cpp create mode 100644 ggml/src/ggml-sycl/rope.hpp create mode 100644 ggml/src/ggml-sycl/set.cpp create mode 100644 ggml/src/ggml-sycl/set.hpp create mode 100644 ggml/src/ggml-sycl/set_rows.cpp create mode 100644 ggml/src/ggml-sycl/set_rows.hpp create mode 100644 ggml/src/ggml-sycl/softmax.cpp create mode 100644 ggml/src/ggml-sycl/softmax.hpp create mode 100644 ggml/src/ggml-sycl/solve_tri.cpp create mode 100644 ggml/src/ggml-sycl/solve_tri.hpp create mode 100644 ggml/src/ggml-sycl/ssm_conv.cpp create mode 100644 ggml/src/ggml-sycl/ssm_conv.hpp create mode 100644 ggml/src/ggml-sycl/ssm_scan.cpp create mode 100644 ggml/src/ggml-sycl/ssm_scan.hpp create mode 100644 ggml/src/ggml-sycl/sycl_hw.cpp create mode 100644 ggml/src/ggml-sycl/sycl_hw.hpp create mode 100644 ggml/src/ggml-sycl/template-instances/fattn-tile-instance-dkq112-dv112.cpp create mode 100644 ggml/src/ggml-sycl/template-instances/fattn-tile-instance-dkq128-dv128.cpp create mode 100644 ggml/src/ggml-sycl/template-instances/fattn-tile-instance-dkq256-dv256.cpp create mode 100644 ggml/src/ggml-sycl/template-instances/fattn-tile-instance-dkq40-dv40.cpp create mode 100644 ggml/src/ggml-sycl/template-instances/fattn-tile-instance-dkq512-dv512.cpp create mode 100644 ggml/src/ggml-sycl/template-instances/fattn-tile-instance-dkq576-dv512.cpp create mode 100644 ggml/src/ggml-sycl/template-instances/fattn-tile-instance-dkq64-dv64.cpp create mode 100644 ggml/src/ggml-sycl/template-instances/fattn-tile-instance-dkq72-dv72.cpp create mode 100644 ggml/src/ggml-sycl/template-instances/fattn-tile-instance-dkq80-dv80.cpp create mode 100644 ggml/src/ggml-sycl/template-instances/fattn-tile-instance-dkq96-dv96.cpp create mode 100644 ggml/src/ggml-sycl/template-instances/fattn-vec-instance-f16-f16.cpp create mode 100644 ggml/src/ggml-sycl/template-instances/fattn-vec-instance-f16-q4_0.cpp create mode 100644 ggml/src/ggml-sycl/template-instances/fattn-vec-instance-f16-q4_1.cpp create mode 100644 ggml/src/ggml-sycl/template-instances/fattn-vec-instance-f16-q5_0.cpp create mode 100644 ggml/src/ggml-sycl/template-instances/fattn-vec-instance-f16-q5_1.cpp create mode 100644 ggml/src/ggml-sycl/template-instances/fattn-vec-instance-f16-q8_0.cpp create mode 100644 ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q4_0-f16.cpp create mode 100644 ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q4_0-q4_0.cpp create mode 100644 ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q4_0-q4_1.cpp create mode 100644 ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q4_0-q5_0.cpp create mode 100644 ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q4_0-q5_1.cpp create mode 100644 ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q4_0-q8_0.cpp create mode 100644 ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q4_1-f16.cpp create mode 100644 ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q4_1-q4_0.cpp create mode 100644 ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q4_1-q4_1.cpp create mode 100644 ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q4_1-q5_0.cpp create mode 100644 ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q4_1-q5_1.cpp create mode 100644 ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q4_1-q8_0.cpp create mode 100644 ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q5_0-f16.cpp create mode 100644 ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q5_0-q4_0.cpp create mode 100644 ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q5_0-q4_1.cpp create mode 100644 ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q5_0-q5_0.cpp create mode 100644 ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q5_0-q5_1.cpp create mode 100644 ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q5_0-q8_0.cpp create mode 100644 ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q5_1-f16.cpp create mode 100644 ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q5_1-q4_0.cpp create mode 100644 ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q5_1-q4_1.cpp create mode 100644 ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q5_1-q5_0.cpp create mode 100644 ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q5_1-q5_1.cpp create mode 100644 ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q5_1-q8_0.cpp create mode 100644 ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q8_0-f16.cpp create mode 100644 ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q8_0-q4_0.cpp create mode 100644 ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q8_0-q4_1.cpp create mode 100644 ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q8_0-q5_0.cpp create mode 100644 ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q8_0-q5_1.cpp create mode 100644 ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q8_0-q8_0.cpp create mode 100644 ggml/src/ggml-sycl/topk-moe.cpp create mode 100644 ggml/src/ggml-sycl/topk-moe.hpp create mode 100644 ggml/src/ggml-sycl/topk-radix.cpp create mode 100644 ggml/src/ggml-sycl/topk-radix.hpp create mode 100644 ggml/src/ggml-sycl/tsembd.cpp create mode 100644 ggml/src/ggml-sycl/tsembd.hpp create mode 100644 ggml/src/ggml-sycl/type.hpp create mode 100644 ggml/src/ggml-sycl/upscale.cpp create mode 100644 ggml/src/ggml-sycl/upscale.hpp create mode 100644 ggml/src/ggml-sycl/vecdotq.hpp create mode 100644 ggml/src/ggml-sycl/wkv.cpp create mode 100644 ggml/src/ggml-sycl/wkv.hpp create mode 100644 ggml/src/ggml-threading.cpp create mode 100644 ggml/src/ggml-threading.h create mode 100644 ggml/src/ggml-version.h.in create mode 100644 ggml/src/ggml-virtgpu/CMakeLists.txt create mode 100644 ggml/src/ggml-virtgpu/apir_cs_ggml-rpc-front.cpp create mode 100644 ggml/src/ggml-virtgpu/backend/CMakeLists.txt create mode 100644 ggml/src/ggml-virtgpu/backend/apir_cs_ggml-rpc-back.cpp create mode 100644 ggml/src/ggml-virtgpu/backend/backend-convert.h create mode 100644 ggml/src/ggml-virtgpu/backend/backend-dispatched-backend.cpp create mode 100644 ggml/src/ggml-virtgpu/backend/backend-dispatched-buffer-type.cpp create mode 100644 ggml/src/ggml-virtgpu/backend/backend-dispatched-buffer.cpp create mode 100644 ggml/src/ggml-virtgpu/backend/backend-dispatched-device.cpp create mode 100644 ggml/src/ggml-virtgpu/backend/backend-dispatched.cpp create mode 100644 ggml/src/ggml-virtgpu/backend/backend-dispatched.gen.h create mode 100644 ggml/src/ggml-virtgpu/backend/backend-dispatched.h create mode 100644 ggml/src/ggml-virtgpu/backend/backend-virgl-apir.h create mode 100644 ggml/src/ggml-virtgpu/backend/backend.cpp create mode 100644 ggml/src/ggml-virtgpu/backend/shared/api_remoting.h create mode 100644 ggml/src/ggml-virtgpu/backend/shared/apir_backend.gen.h create mode 100644 ggml/src/ggml-virtgpu/backend/shared/apir_backend.h create mode 100644 ggml/src/ggml-virtgpu/backend/shared/apir_cs.h create mode 100644 ggml/src/ggml-virtgpu/backend/shared/apir_cs_ggml.h create mode 100644 ggml/src/ggml-virtgpu/backend/shared/apir_cs_rpc.h create mode 100644 ggml/src/ggml-virtgpu/ggml-backend-buffer-type.cpp create mode 100644 ggml/src/ggml-virtgpu/ggml-backend-buffer.cpp create mode 100644 ggml/src/ggml-virtgpu/ggml-backend-device.cpp create mode 100644 ggml/src/ggml-virtgpu/ggml-backend-reg.cpp create mode 100644 ggml/src/ggml-virtgpu/ggml-backend.cpp create mode 100644 ggml/src/ggml-virtgpu/ggml-remoting.h create mode 100644 ggml/src/ggml-virtgpu/ggmlremoting_functions.yaml create mode 100644 ggml/src/ggml-virtgpu/include/apir_hw.h create mode 100755 ggml/src/ggml-virtgpu/regenerate_remoting.py create mode 100644 ggml/src/ggml-virtgpu/virtgpu-apir.h create mode 100644 ggml/src/ggml-virtgpu/virtgpu-forward-backend.cpp create mode 100644 ggml/src/ggml-virtgpu/virtgpu-forward-buffer-type.cpp create mode 100644 ggml/src/ggml-virtgpu/virtgpu-forward-buffer.cpp create mode 100644 ggml/src/ggml-virtgpu/virtgpu-forward-device.cpp create mode 100644 ggml/src/ggml-virtgpu/virtgpu-forward-impl.h create mode 100644 ggml/src/ggml-virtgpu/virtgpu-forward.gen.h create mode 100644 ggml/src/ggml-virtgpu/virtgpu-shm.cpp create mode 100644 ggml/src/ggml-virtgpu/virtgpu-shm.h create mode 100644 ggml/src/ggml-virtgpu/virtgpu-utils.cpp create mode 100644 ggml/src/ggml-virtgpu/virtgpu-utils.h create mode 100644 ggml/src/ggml-virtgpu/virtgpu.cpp create mode 100644 ggml/src/ggml-virtgpu/virtgpu.h create mode 100644 ggml/src/ggml-vulkan/CMakeLists.txt create mode 100644 ggml/src/ggml-vulkan/cmake/host-toolchain.cmake.in create mode 100644 ggml/src/ggml-vulkan/ggml-vulkan.cpp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/CMakeLists.txt create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/acc.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/add.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/add1.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/add_id.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/arange.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/argmax.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/argsort.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/argsort_large.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/col2im_1d.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/concat.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/contig_copy.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/conv2d_dw.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/conv2d_mm.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/conv3d_mm.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/conv_transpose_1d.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/copy.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/copy_from_quant.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/copy_to_quant.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/copy_transpose.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/copy_transpose_02.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/count_equal.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/count_experts.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/cross_entropy_loss.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/cross_entropy_loss_back.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/cumsum.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/cumsum_multipass1.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/cumsum_multipass2.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/dequant_f32.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/dequant_funcs.glsl create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/dequant_funcs_cm2.glsl create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/dequant_head.glsl create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/dequant_iq1_m.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/dequant_iq1_s.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/dequant_iq2_s.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/dequant_iq2_xs.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/dequant_iq2_xxs.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/dequant_iq3_s.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/dequant_iq3_xxs.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/dequant_iq4_nl.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/dequant_iq4_xs.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/dequant_mxfp4.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/dequant_nvfp4.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/dequant_q1_0.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/dequant_q2_0.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/dequant_q2_k.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/dequant_q3_k.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/dequant_q4_0.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/dequant_q4_1.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/dequant_q4_k.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/dequant_q5_0.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/dequant_q5_1.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/dequant_q5_k.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/dequant_q6_k.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/dequant_q8_0.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/dequant_tq1_0.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/dequant_tq2_0.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/diag.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/diag_mask_inf.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/div.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/dot_product_funcs.glsl create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/dsv4_hc_comb.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/dsv4_hc_post.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/dsv4_hc_pre.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/fa_types.glsl create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/feature-tests/bfloat16.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/feature-tests/coopmat.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/feature-tests/coopmat2.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/feature-tests/coopmat2_decode_vector.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/feature-tests/float_e2m1.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/feature-tests/float_e4m3.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/feature-tests/integer_dot.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/fill.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/flash_attn.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/flash_attn_base.glsl create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/flash_attn_cm1.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/flash_attn_cm2.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/flash_attn_dequant.glsl create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/flash_attn_mask_opt.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/flash_attn_mmq_funcs.glsl create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/flash_attn_split_k_reduce.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/fwht.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/gated_delta_net.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/geglu.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/geglu_erf.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/geglu_quick.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/generic_binary_head.glsl create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/generic_head.glsl create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/generic_unary_head.glsl create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/get_rows.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/get_rows_back.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/get_rows_quant.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/ggml_type_ids.glsl create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/gla.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/glu_head.glsl create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/glu_main.glsl create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/group_norm.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/im2col.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/im2col_3d.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/iq_shmem_init.glsl create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/l2_norm.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/lightning_indexer.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/log.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/mul.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_split_k_reduce.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_base.glsl create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_iface.glsl create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_iq1_m.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_iq1_s.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_iq2_s.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_iq2_xs.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_iq2_xxs.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_iq3_s.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_iq3_xxs.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_iq4_xs.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_nc.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_p021.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_q2_k.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_q3_k.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_q4_k.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_q5_k.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_q6_k.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_tq1_0.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_tq2_0.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vecq.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vecq_funcs.glsl create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/mul_mm.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/mul_mm_cm2.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/mul_mm_funcs.glsl create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/mul_mm_id_funcs.glsl create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/mul_mmq.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/mul_mmq_funcs.glsl create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/mul_mmq_shmem_types.glsl create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/multi_add.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/norm.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/opt_step_adamw.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/opt_step_sgd.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/out_prod.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/pad.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/pad_reflect_1d.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/pool1d.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/pool2d.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/quantize_q8_1.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/reglu.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/repeat.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/repeat_back.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/rms_norm.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/rms_norm_back.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/rms_norm_partials.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/roll.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/rope_funcs.glsl create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/rope_head.glsl create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/rope_multi.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/rope_neox.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/rope_norm.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/rope_params.glsl create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/rope_vision.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/scale.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/silu_back.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/snake.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/soft_max.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/soft_max_back.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/soft_max_large1.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/soft_max_large2.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/soft_max_large3.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/soft_max_large_common.glsl create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/solve_tri.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/ssm_conv.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/ssm_scan.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/sub.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/sum_rows.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/sum_rows.glsl create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/swiglu.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/swiglu_clamp.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/swiglu_oai.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/timestep_embedding.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/topk_argsort.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/topk_moe.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/topk_nary_search.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/topk_radix_select.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/tri.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/types.glsl create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/unary.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/upscale.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/utils.glsl create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/vulkan-shaders-gen.cpp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/wkv6.comp create mode 100644 ggml/src/ggml-vulkan/vulkan-shaders/wkv7.comp create mode 100644 ggml/src/ggml-webgpu/CMakeLists.txt create mode 100644 ggml/src/ggml-webgpu/ggml-webgpu-shader-lib.hpp create mode 100644 ggml/src/ggml-webgpu/ggml-webgpu.cpp create mode 100644 ggml/src/ggml-webgpu/pre_wgsl.hpp create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/add_id.wgsl create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/argmax.wgsl create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/argsort.wgsl create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/argsort_merge.wgsl create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/binary.wgsl create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/common_decls.tmpl create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/concat.wgsl create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/conv2d.wgsl create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/conv2d_dw.wgsl create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/cpy.wgsl create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/cumsum.wgsl create mode 100755 ggml/src/ggml-webgpu/wgsl-shaders/embed_wgsl.py create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/flash_attn.wgsl create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/flash_attn_decls.tmpl create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/flash_attn_staging.tmpl create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/flash_attn_tile.wgsl create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/flash_attn_vec_blk.wgsl create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/flash_attn_vec_reduce.wgsl create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/flash_attn_vec_split.wgsl create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/gated_delta_net.wgsl create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/get_rows.wgsl create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/glu.wgsl create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/im2col.wgsl create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/memset.wgsl create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/mul_mat_decls.tmpl create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/mul_mat_id.wgsl create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/mul_mat_id_gather.wgsl create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/mul_mat_id_vec.wgsl create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/mul_mat_reg_tile.wgsl create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/mul_mat_subgroup_matrix.wgsl create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/mul_mat_vec.wgsl create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/mul_mat_vec_acc.tmpl create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/mul_mat_vec_q_acc.tmpl create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/pad.wgsl create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/quant_inner_loops.tmpl create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/quantize_q8.wgsl create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/repeat.wgsl create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/rms_norm_mul.wgsl create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/rope.wgsl create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/row_norm.wgsl create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/scale.wgsl create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/set.wgsl create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/set_rows.wgsl create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/set_rows_quant.wgsl create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/soft_max.wgsl create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/solve_tri.wgsl create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/ssm_conv.wgsl create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/ssm_scan.wgsl create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/sum_rows.wgsl create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/unary.wgsl create mode 100644 ggml/src/ggml-webgpu/wgsl-shaders/upscale.wgsl create mode 100644 ggml/src/ggml-zdnn/.gitignore create mode 100644 ggml/src/ggml-zdnn/CMakeLists.txt create mode 100644 ggml/src/ggml-zdnn/common.hpp create mode 100644 ggml/src/ggml-zdnn/ggml-zdnn.cpp create mode 100644 ggml/src/ggml-zdnn/mmf.cpp create mode 100644 ggml/src/ggml-zdnn/mmf.hpp create mode 100644 ggml/src/ggml-zdnn/utils.cpp create mode 100644 ggml/src/ggml-zdnn/utils.hpp create mode 100644 ggml/src/ggml-zendnn/CMakeLists.txt create mode 100644 ggml/src/ggml-zendnn/ggml-zendnn.cpp create mode 100644 ggml/src/ggml.c create mode 100644 ggml/src/ggml.cpp create mode 100644 ggml/src/gguf.cpp create mode 100644 grammars/assistant.gbnf create mode 100644 grammars/chess.gbnf create mode 100644 grammars/colors.gbnf create mode 100644 include/parakeet.h create mode 100644 include/whisper.h create mode 100644 media/matmul.png create mode 100644 models/.gitignore create mode 100644 models/README.md create mode 100644 models/convert-h5-to-coreml.py create mode 100644 models/convert-h5-to-ggml.py create mode 100755 models/convert-parakeet-to-ggml.py create mode 100644 models/convert-pt-to-ggml.py create mode 100644 models/convert-silero-vad-to-ggml.py create mode 100644 models/convert-whisper-to-coreml.py create mode 100644 models/convert-whisper-to-openvino.py create mode 100755 models/download-coreml-model.sh create mode 100644 models/download-ggml-model.cmd create mode 100755 models/download-ggml-model.sh create mode 100644 models/download-vad-model.cmd create mode 100755 models/download-vad-model.sh create mode 100644 models/download-vitisai-model.cmd create mode 100644 models/download-vitisai-model.ps1 create mode 100755 models/download-vitisai-model.sh create mode 100755 models/generate-coreml-interface.sh create mode 100755 models/generate-coreml-model.sh create mode 100755 models/generate-parakeet-test-model.py create mode 100644 models/ggml_to_pt.py create mode 100644 models/requirements-coreml.txt create mode 100644 models/requirements-openvino.txt create mode 100644 models/requirements-parakeet.txt create mode 100644 samples/jfk.mp3 create mode 100755 scripts/apple/validate-apps.sh create mode 100755 scripts/apple/validate-ios.sh create mode 100755 scripts/apple/validate-macos.sh create mode 100755 scripts/apple/validate-tvos.sh create mode 100755 scripts/apple/validate-visionos.sh create mode 100644 scripts/bench-all-gg.txt create mode 100755 scripts/bench-all.sh create mode 100755 scripts/bench-wts.sh create mode 100644 scripts/bench.py create mode 100755 scripts/build-info.sh create mode 100755 scripts/convert-all.sh create mode 100755 scripts/deploy-wasm.sh create mode 100755 scripts/gen-authors.sh create mode 100644 scripts/get-flags.mk create mode 100755 scripts/make-release-checks.sh create mode 100755 scripts/make-release-desc.sh create mode 100755 scripts/quantize-all.sh create mode 100755 scripts/quantize-parakeet.sh create mode 100755 scripts/release.sh create mode 100755 scripts/sha-all.sh create mode 100755 scripts/sync-ggml-am.sh create mode 100644 scripts/sync-ggml.last create mode 100755 scripts/sync-ggml.sh create mode 100755 scripts/sync-llama.sh create mode 100644 scripts/upload-parakeet.py create mode 100644 src/CMakeLists.txt create mode 100644 src/coreml/whisper-compat.h create mode 100644 src/coreml/whisper-compat.m create mode 100644 src/coreml/whisper-decoder-impl.h create mode 100644 src/coreml/whisper-decoder-impl.m create mode 100644 src/coreml/whisper-encoder-impl.h create mode 100644 src/coreml/whisper-encoder-impl.m create mode 100644 src/coreml/whisper-encoder.h create mode 100644 src/coreml/whisper-encoder.mm create mode 100644 src/openvino/whisper-openvino-encoder.cpp create mode 100644 src/openvino/whisper-openvino-encoder.h create mode 100644 src/parakeet-arch.h create mode 100644 src/parakeet.cpp create mode 100644 src/vitisai/whisper-vitisai-encoder.cpp create mode 100644 src/vitisai/whisper-vitisai-encoder.h create mode 100644 src/vitisai/whisper-vitisai-helpers.cpp create mode 100644 src/vitisai/whisper-vitisai-helpers.h create mode 100644 src/whisper-arch.h create mode 100644 src/whisper.cpp create mode 100644 tests/.gitignore create mode 100644 tests/CMakeLists.txt create mode 100644 tests/earnings21/.gitignore create mode 100644 tests/earnings21/Makefile create mode 100644 tests/earnings21/README.md create mode 100644 tests/earnings21/eval.mk create mode 100644 tests/earnings21/eval.py create mode 100644 tests/earnings21/normalizers/LICENSE create mode 100644 tests/earnings21/normalizers/__init__.py create mode 100644 tests/earnings21/normalizers/basic.py create mode 100644 tests/earnings21/normalizers/english.json create mode 100644 tests/earnings21/normalizers/english.py create mode 100644 tests/en-0-ref.txt create mode 100644 tests/en-1-ref.txt create mode 100644 tests/en-2-ref.txt create mode 100644 tests/es-0-ref.txt create mode 100644 tests/librispeech-parakeet/.gitignore create mode 100644 tests/librispeech-parakeet/Makefile create mode 100644 tests/librispeech-parakeet/README.md create mode 100644 tests/librispeech-parakeet/eval.mk create mode 100644 tests/librispeech-parakeet/eval.py create mode 100644 tests/librispeech-parakeet/normalizers/LICENSE create mode 100644 tests/librispeech-parakeet/normalizers/__init__.py create mode 100644 tests/librispeech-parakeet/normalizers/basic.py create mode 100644 tests/librispeech-parakeet/normalizers/english.json create mode 100644 tests/librispeech-parakeet/normalizers/english.py create mode 100644 tests/librispeech/.gitignore create mode 100644 tests/librispeech/Makefile create mode 100644 tests/librispeech/README.md create mode 100644 tests/librispeech/eval.mk create mode 100644 tests/librispeech/eval.py create mode 100644 tests/librispeech/normalizers/LICENSE create mode 100644 tests/librispeech/normalizers/__init__.py create mode 100644 tests/librispeech/normalizers/basic.py create mode 100644 tests/librispeech/normalizers/english.json create mode 100644 tests/librispeech/normalizers/english.py create mode 100644 tests/parakeet-expected-diffusion-output.txt create mode 100644 tests/parakeet-expected-gb1-output.txt create mode 100644 tests/parakeet-expected-jfk-output.txt create mode 100644 tests/parakeet-verification.h create mode 100755 tests/run-tests.sh create mode 100644 tests/test-c.c create mode 100644 tests/test-common-utf8.cpp create mode 100644 tests/test-parakeet-full.cpp create mode 100644 tests/test-parakeet.cpp create mode 100644 tests/test-vad-full.cpp create mode 100644 tests/test-vad.cpp create mode 100644 tests/test-whisper-buffer-loader.cpp create mode 100644 tests/test-whisper-zero-samples.cpp create mode 100644 tests/test-whisper.js diff --git a/.devops/cublas.Dockerfile b/.devops/cublas.Dockerfile new file mode 100644 index 0000000..1fae256 --- /dev/null +++ b/.devops/cublas.Dockerfile @@ -0,0 +1,28 @@ +ARG UBUNTU_VERSION=22.04 + +# This needs to generally match the container host's environment. +ARG CUDA_VERSION=11.7.1 + +# Target the CUDA build image +ARG BASE_CUDA_DEV_CONTAINER=nvidia/cuda:${CUDA_VERSION}-devel-ubuntu${UBUNTU_VERSION} + +FROM ${BASE_CUDA_DEV_CONTAINER} as build + +# Unless otherwise specified, we make a fat build. +ARG CUDA_DOCKER_ARCH=all + +RUN apt-get update && \ + apt-get install -y build-essential git cmake libsdl2-dev wget git + +WORKDIR /app + +COPY . . + +# Set nvcc architecture +ENV CUDA_DOCKER_ARCH=${CUDA_DOCKER_ARCH} +# Enable cuBLAS +ENV GGML_CUDA=1 + +RUN make base.en + +ENTRYPOINT ["/app/main"] diff --git a/.devops/main-cuda.Dockerfile b/.devops/main-cuda.Dockerfile new file mode 100644 index 0000000..0d065df --- /dev/null +++ b/.devops/main-cuda.Dockerfile @@ -0,0 +1,50 @@ +ARG UBUNTU_VERSION=22.04 +# This needs to generally match the container host's environment. +ARG CUDA_VERSION=13.0.0 +# Target the CUDA build image +ARG BASE_CUDA_DEV_CONTAINER=nvidia/cuda:${CUDA_VERSION}-devel-ubuntu${UBUNTU_VERSION} +# Target the CUDA runtime image +ARG BASE_CUDA_RUN_CONTAINER=nvidia/cuda:${CUDA_VERSION}-runtime-ubuntu${UBUNTU_VERSION} + +FROM ${BASE_CUDA_DEV_CONTAINER} AS build +WORKDIR /app + +# Unless otherwise specified, we make a fat build. +ARG CUDA_DOCKER_ARCH=all +# Set nvcc architecture +ENV CUDA_DOCKER_ARCH=${CUDA_DOCKER_ARCH} + +RUN apt-get update && \ + apt-get install -y build-essential libsdl2-dev wget cmake git \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/* + +# The build stage has no real GPU/driver, so the linker needs the +# forward-compat libcuda stub to resolve CUDA driver-API symbols. +# Ref: https://stackoverflow.com/a/53464012 +ENV CUDA_MAIN_VERSION=13.0 +ENV LD_LIBRARY_PATH /usr/local/cuda-${CUDA_MAIN_VERSION}/compat:$LD_LIBRARY_PATH + +COPY .. . +# Enable cuBLAS +RUN --mount=type=secret,id=HF_TOKEN,required=false,env=HF_TOKEN make base.en CMAKE_ARGS="-DGGML_CUDA=1 -DCMAKE_CUDA_ARCHITECTURES='75;80;86;90'" + +RUN find /app/build -name "*.o" -delete && \ + find /app/build -name "*.a" -delete && \ + rm -rf /app/build/CMakeFiles && \ + rm -rf /app/build/cmake_install.cmake && \ + rm -rf /app/build/_deps + +FROM ${BASE_CUDA_RUN_CONTAINER} AS runtime +WORKDIR /app + +RUN apt-get update && \ + apt-get install -y curl ffmpeg wget cmake git \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/* + +COPY --from=build /app /app +RUN du -sh /app/* +RUN find /app -type f -size +100M +ENV PATH=/app/build/bin:$PATH +ENTRYPOINT [ "bash", "-c" ] diff --git a/.devops/main-intel.Dockerfile b/.devops/main-intel.Dockerfile new file mode 100644 index 0000000..a0c04ad --- /dev/null +++ b/.devops/main-intel.Dockerfile @@ -0,0 +1,29 @@ +ARG ONEAPI_VERSION=2025.3.3-0-devel-ubuntu24.04 + +FROM intel/deep-learning-essentials:$ONEAPI_VERSION AS build +WORKDIR /app + +RUN apt-get update && \ + apt-get install -y build-essential libsdl2-dev wget cmake git \ + && rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/* + +COPY .. . +# Enable SYCL +ARG GGML_SYCL_F16=OFF +RUN --mount=type=secret,id=HF_TOKEN,required=false,env=HF_TOKEN \ + if [ "${GGML_SYCL_F16}" = "ON" ]; then \ + echo "GGML_SYCL_F16 is set" \ + && export OPT_SYCL_F16="-DGGML_SYCL_F16=ON"; \ + fi && \ + make base.en CMAKE_ARGS="-DGGML_SYCL=1 -DCMAKE_C_COMPILER=icx -DCMAKE_CXX_COMPILER=icpx ${OPT_SYCL_F16}" + +FROM intel/deep-learning-essentials:$ONEAPI_VERSION AS runtime +WORKDIR /app + +RUN apt-get update && \ + apt-get install -y curl ffmpeg libsdl2-dev wget cmake git \ + && rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/* + +COPY --from=build /app /app +ENV PATH=/app/build/bin:$PATH +ENTRYPOINT [ "bash", "-c" ] diff --git a/.devops/main-musa.Dockerfile b/.devops/main-musa.Dockerfile new file mode 100644 index 0000000..c683678 --- /dev/null +++ b/.devops/main-musa.Dockerfile @@ -0,0 +1,40 @@ +ARG UBUNTU_VERSION=22.04 +# This needs to generally match the container host's environment. +ARG MUSA_VERSION=rc4.2.0 +# Target the MUSA build image +ARG BASE_MUSA_DEV_CONTAINER=mthreads/musa:${MUSA_VERSION}-devel-ubuntu${UBUNTU_VERSION}-amd64 +# Target the MUSA runtime image +ARG BASE_MUSA_RUN_CONTAINER=mthreads/musa:${MUSA_VERSION}-runtime-ubuntu${UBUNTU_VERSION}-amd64 + +FROM ${BASE_MUSA_DEV_CONTAINER} AS build +WORKDIR /app + +RUN apt-get update && \ + apt-get install -y build-essential libsdl2-dev wget cmake git && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/* /tmp/* /var/tmp/* + +COPY .. . +# Enable muBLAS +RUN --mount=type=secret,id=HF_TOKEN,required=false,env=HF_TOKEN make base.en CMAKE_ARGS="-DGGML_MUSA=1" + +RUN find /app/build -name "*.o" -delete && \ + find /app/build -name "*.a" -delete && \ + rm -rf /app/build/CMakeFiles && \ + rm -rf /app/build/cmake_install.cmake && \ + rm -rf /app/build/_deps + +FROM ${BASE_MUSA_RUN_CONTAINER} AS runtime +WORKDIR /app + +RUN apt-get update && \ + apt-get install -y curl ffmpeg wget cmake git && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/* /tmp/* /var/tmp/* + +COPY --from=build /app/build/bin /app/build/bin +COPY --from=build /app/samples /app/samples +COPY --from=build /app/models /app/models + +ENV PATH=/app/build/bin:$PATH +ENTRYPOINT [ "bash", "-c" ] diff --git a/.devops/main-rocm.Dockerfile b/.devops/main-rocm.Dockerfile new file mode 100644 index 0000000..efe29e1 --- /dev/null +++ b/.devops/main-rocm.Dockerfile @@ -0,0 +1,81 @@ +# build stage +FROM registry.fedoraproject.org/fedora:44 AS build + +WORKDIR /app + +# ROCm 7.14 repository (TheRock release stream) +RUN <<'EOF' +tee /etc/yum.repos.d/rocm.repo </dev/null) + if [ -z "$CACHES" ]; then + echo "No caches found with key prefix: ${{ inputs.key }}" + exit 0 + fi + while read -r id key; do + echo "Deleting cache: $id ($key)" + gh cache delete "$id" + done <<< "$CACHES" diff --git a/.github/workflows/bindings-go.yml b/.github/workflows/bindings-go.yml new file mode 100644 index 0000000..91f869e --- /dev/null +++ b/.github/workflows/bindings-go.yml @@ -0,0 +1,22 @@ +name: Bindings Tests (Go) +on: + push: + paths: + - bindings/go/** + - include/whisper.h + pull_request: + paths: + - bindings/go/** + - include/whisper.h + +jobs: + ubuntu-22: + runs-on: ubuntu-22.04 + steps: + - uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6 + with: + go-version: '^1.23' + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + - run: | + cd bindings/go + make test diff --git a/.github/workflows/bindings-ruby.yml b/.github/workflows/bindings-ruby.yml new file mode 100644 index 0000000..8cdb7a8 --- /dev/null +++ b/.github/workflows/bindings-ruby.yml @@ -0,0 +1,32 @@ +name: Bindings Tests (Ruby) + +on: + push: + branches: + - master + paths: + - bindings/ruby/** + - include/whisper.h + - examples/common-whisper.h + - ggml/include/ggml.h + + pull_request: + types: [opened, synchronize, reopened] + paths: + - bindings/ruby/** + - include/whisper.h + - examples/common-whisper.h + - ggml/include/ggml.h + +jobs: + ubuntu-22: + runs-on: ubuntu-22.04 + defaults: + run: + working-directory: bindings/ruby + steps: + - uses: ruby/setup-ruby@afeafc3d1ab54a631816aba4c914a0081c12ff2f # v1.310.0 + with: + ruby-version: '3.3' + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + - run: rake test diff --git a/.github/workflows/build-android.yml b/.github/workflows/build-android.yml new file mode 100644 index 0000000..571c358 --- /dev/null +++ b/.github/workflows/build-android.yml @@ -0,0 +1,80 @@ +name: CI (android) + +on: + workflow_dispatch: # allows manual triggering + push: + branches: + - master + paths: ['.github/workflows/build-android.yml', + '**/CMakeLists.txt', + '**/*.h', + '**/*.hpp', + '**/*.c', + '**/*.cpp', + '**/*.java'] + + pull_request: + types: [opened, synchronize, reopened] + paths-ignore: + - 'bindings/ruby/**' # handled by bindings-ruby.yml + - 'bindings/go/**' # handled by bindings-go.yml + - 'examples/addon.node/**' # handled by examples.yml + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref && github.ref || github.run_id }} + cancel-in-progress: true + +jobs: + android: + runs-on: ubuntu-22.04 + + steps: + - name: Clone + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + with: + path: whisper + + - name: Install Java + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 + with: + distribution: zulu + java-version: 21 + + - name: Setup Android SDK + uses: android-actions/setup-android@40fd30fb8d7440372e1316f5d1809ec01dcd3699 # v4.0.1 + + - name: Build + run: | + cd whisper/examples/whisper.android + ./gradlew assembleRelease --no-daemon + + - name: Build with external ggml + run: | + export PATH_TO_GGML=$PWD/ggml + cd whisper/examples/whisper.android + ./gradlew assembleRelease --no-daemon + + android_java: + runs-on: ubuntu-22.04 + + steps: + - name: Clone + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + + - name: set up JDK 11 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 + with: + java-version: '11' + distribution: 'temurin' + cache: gradle + + - name: Setup Android SDK + uses: android-actions/setup-android@40fd30fb8d7440372e1316f5d1809ec01dcd3699 # v4.0.1 + with: + cmdline-tools-version: 9.0 + + - name: Build + run: | + cd examples/whisper.android.java + chmod +x ./gradlew + ./gradlew assembleRelease diff --git a/.github/workflows/build-clang.yml b/.github/workflows/build-clang.yml new file mode 100644 index 0000000..396b097 --- /dev/null +++ b/.github/workflows/build-clang.yml @@ -0,0 +1,122 @@ +name: CI (clang) + +on: + workflow_dispatch: # allows manual triggering + push: + branches: + - master + paths: ['.github/workflows/build-clang.yml', + '**/CMakeLists.txt', + '**/Makefile', + '**/*.mk', + '**/*.cmake', + '**/*.in', + '**/*.h', + '**/*.hpp', + '**/*.c', + '**/*.cpp', + '**/*.cu', + '**/*.cuh', + '**/*.cl'] + + pull_request: + types: [opened, synchronize, reopened] + paths-ignore: + - 'bindings/ruby/**' # handled by bindings-ruby.yml + - 'bindings/go/**' # handled by bindings-go.yml + - 'examples/addon.node/**' # handled by examples.yml + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref && github.ref || github.run_id }} + cancel-in-progress: true + +env: + ubuntu_image: "ubuntu:22.04" + +jobs: + ubuntu-22-clang: + runs-on: ubuntu-22.04 + + strategy: + fail-fast: false + matrix: + build: [Debug, Release] + #arch: [linux/amd64, linux/arm64, linux/arm/v7, linux/ppc64le] + # TODO: arm/v7 disabled due to clang bug + # https://github.com/ggerganov/whisper.cpp/actions/runs/9657764109/job/26637633042?pr=2256#step:4:1990 + arch: [linux/amd64, linux/ppc64le] + + steps: + - name: Clone + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + + - name: Set CCACHE_DIR + run: echo "CCACHE_DIR=${{ runner.temp }}/ccache" >> $GITHUB_ENV + + - name: ccache + uses: ggml-org/ccache-action@v1.2.21 + with: + key: clang-${{ matrix.arch }}-${{ matrix.build }} + evict-old-files: 1d + save: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} + + - name: Set up QEMU + uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4 + + - name: Build ${{ matrix.arch }} + run: | + docker run --platform ${{ matrix.arch }} --rm \ + -v ${{ github.workspace }}:/workspace \ + -v ${CCACHE_DIR}:${CCACHE_DIR} \ + -e CCACHE_DIR=${CCACHE_DIR} \ + -w /workspace ${{ env.ubuntu_image }} /bin/sh -c ' + set -e + export DEBIAN_FRONTEND=noninteractive + sed -i "s|archive.ubuntu.com|mirrors.kernel.org|g" /etc/apt/sources.list + sed -i "s|security.ubuntu.com|mirrors.kernel.org|g" /etc/apt/sources.list + + apt update + apt install -y clang build-essential cmake libsdl2-dev git ccache + cmake . -DWHISPER_SDL2=ON -DCMAKE_BUILD_TYPE=${{ matrix.build }} \ + -DCMAKE_CXX_COMPILER=clang++ \ + -DCMAKE_C_COMPILER=clang \ + -DCMAKE_C_COMPILER_LAUNCHER=ccache \ + -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ + -DGGML_NATIVE=OFF + make + ctest -L gh --output-on-failure' + + ubuntu-22-clang-arm64: + runs-on: ubuntu-22.04-arm + + strategy: + fail-fast: false + matrix: + build: [Debug, Release] + + steps: + - name: Clone + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + + - name: ccache + uses: ggml-org/ccache-action@v1.2.21 + with: + key: clang-arm64-${{ matrix.build }} + evict-old-files: 1d + save: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y clang build-essential cmake libsdl2-dev git + + - name: Build and Test + run: | + cmake . -DWHISPER_SDL2=ON \ + -DCMAKE_BUILD_TYPE=${{ matrix.build }} \ + -DCMAKE_CXX_COMPILER=clang++ \ + -DCMAKE_C_COMPILER=clang \ + -DGGML_NATIVE=OFF \ + -DGGML_CPU_ARM_ARCH=armv8-a + make + ctest -L gh --output-on-failure diff --git a/.github/workflows/build-coreml.yml b/.github/workflows/build-coreml.yml new file mode 100644 index 0000000..8dedd78 --- /dev/null +++ b/.github/workflows/build-coreml.yml @@ -0,0 +1,65 @@ +name: CI (coreml) + +on: + workflow_dispatch: # allows manual triggering + push: + branches: + - master + tags: + - 'v*' + paths: ['.github/workflows/build-coreml.yml', + '**/CMakeLists.txt', + '**/*.h', + '**/*.hpp', + '**/*.c', + '**/*.cpp', + '**/*.swift', + '**/*.m', + '**/*.mm', + '**/*.metal'] + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref && github.ref || github.run_id }} + cancel-in-progress: true + +env: + BRANCH_NAME: ${{ github.head_ref || github.ref_name }} + +jobs: + coreml-base-en: + runs-on: macos-latest + + steps: + - name: Checkout with full history + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + with: + fetch-depth: 0 + + - name: Set environment variables + id: set_vars + run: | + BUILD_NUMBER=$(git rev-list --count HEAD) + SHORT_HASH=$(git rev-parse --short=7 HEAD) + if [[ "${{ github.ref_type }}" == "tag" ]]; then + TAG_NAME="${{ github.ref_name }}" + elif [[ "${{ env.BRANCH_NAME }}" == "master" ]]; then + TAG_NAME="b${BUILD_NUMBER}" + else + SAFE_NAME=$(echo "${{ env.BRANCH_NAME }}" | tr '/' '-') + TAG_NAME="${SAFE_NAME}-b${BUILD_NUMBER}-${SHORT_HASH}" + fi + echo "MODEL_NAME=base.en" >> $GITHUB_ENV + echo "GEN_MODEL_NAME=whisper-${TAG_NAME}-ggml-base.en-encoder.mlmodelc" >> $GITHUB_ENV + + - name: Download model + env: + HF_TOKEN: ${{ secrets.HF_TOKEN }} + run: | + ./models/download-ggml-model.sh ${{ env.MODEL_NAME }} + + - name: Generate CoreML model + run: | + python3.11 -m venv venv + source venv/bin/activate + pip install ane_transformers openai-whisper coremltools + ./models/generate-coreml-model.sh ${{ env.MODEL_NAME }} diff --git a/.github/workflows/build-cpu.yml b/.github/workflows/build-cpu.yml new file mode 100644 index 0000000..e2b7488 --- /dev/null +++ b/.github/workflows/build-cpu.yml @@ -0,0 +1,173 @@ +name: CI (cpu) + +on: + workflow_dispatch: # allows manual triggering + push: + branches: + - master + paths: ['.github/workflows/build-cpu.yml', + '**/CMakeLists.txt', + '**/Makefile', + '**/*.mk', + '**/*.cmake', + '**/*.in', + '**/*.h', + '**/*.hpp', + '**/*.c', + '**/*.cpp', + '**/*.cu', + '**/*.cuh', + '**/*.cl'] + + pull_request: + types: [opened, synchronize, reopened] + paths-ignore: + - 'bindings/ruby/**' # handled by bindings-ruby.yml + - 'bindings/go/**' # handled by bindings-go.yml + - 'examples/addon.node/**' # handled by examples.yml + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref && github.ref || github.run_id }} + cancel-in-progress: true + +# TODO: simplify the following jobs using a matrix +jobs: + ggml-ci-x64-cpu-low-perf: + runs-on: ubuntu-22.04 + + steps: + - name: Clone + id: checkout + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + + - name: ccache + uses: ggml-org/ccache-action@v1.2.21 + with: + key: ggml-ci-x64-cpu-low-perf + evict-old-files: 1d + save: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} + + - name: Dependencies + id: depends + run: | + sudo apt-get update + sudo apt-get install build-essential libcurl4-openssl-dev + + - name: Test + id: ggml-ci + env: + HF_TOKEN: ${{ secrets.HF_TOKEN }} + run: | + LLAMA_ARG_THREADS=$(nproc) GG_BUILD_LOW_PERF=1 bash ./ci/run.sh ./tmp/results ./tmp/mnt + + ggml-ci-arm64-cpu-low-perf: + runs-on: ubuntu-22.04-arm + + steps: + - name: Clone + id: checkout + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + + - name: ccache + uses: ggml-org/ccache-action@v1.2.21 + with: + key: ggml-ci-arm64-cpu-low-perf + evict-old-files: 1d + save: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} + + - name: Dependencies + id: depends + run: | + sudo apt-get update + sudo apt-get install build-essential libcurl4-openssl-dev + + - name: Test + id: ggml-ci + env: + HF_TOKEN: ${{ secrets.HF_TOKEN }} + run: | + LLAMA_ARG_THREADS=$(nproc) GG_BUILD_LOW_PERF=1 bash ./ci/run.sh ./tmp/results ./tmp/mnt + + ggml-ci-x64-cpu-high-perf: + runs-on: ubuntu-22.04 + + steps: + - name: Clone + id: checkout + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + + - name: ccache + uses: ggml-org/ccache-action@v1.2.21 + with: + key: ggml-ci-x64-cpu-high-perf + evict-old-files: 1d + save: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} + + - name: Dependencies + id: depends + run: | + sudo apt-get update + sudo apt-get install build-essential libcurl4-openssl-dev + + - name: Test + id: ggml-ci + env: + HF_TOKEN: ${{ secrets.HF_TOKEN }} + run: | + LLAMA_ARG_THREADS=$(nproc) bash ./ci/run.sh ./tmp/results ./tmp/mnt + + ggml-ci-arm64-cpu-high-perf: + runs-on: ubuntu-22.04-arm + + steps: + - name: Clone + id: checkout + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + + - name: ccache + uses: ggml-org/ccache-action@v1.2.21 + with: + key: ggml-ci-arm64-cpu-high-perf + evict-old-files: 1d + save: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} + + - name: Dependencies + id: depends + run: | + sudo apt-get update + sudo apt-get install build-essential libcurl4-openssl-dev + + - name: Test + id: ggml-ci + env: + HF_TOKEN: ${{ secrets.HF_TOKEN }} + run: | + LLAMA_ARG_THREADS=$(nproc) GG_BUILD_NO_SVE=1 GG_BUILD_NO_BF16=1 GG_BUILD_EXTRA_TESTS_0=1 bash ./ci/run.sh ./tmp/results ./tmp/mnt + + ggml-ci-arm64-cpu-high-perf-sve: + runs-on: ubuntu-22.04-arm + + steps: + - name: Clone + id: checkout + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + + - name: ccache + uses: ggml-org/ccache-action@v1.2.21 + with: + key: ggml-ci-arm64-cpu-high-perf-sve + evict-old-files: 1d + save: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} + + - name: Dependencies + id: depends + run: | + sudo apt-get update + sudo apt-get install build-essential libcurl4-openssl-dev + + - name: Test + id: ggml-ci + env: + HF_TOKEN: ${{ secrets.HF_TOKEN }} + run: | + LLAMA_ARG_THREADS=$(nproc) GG_BUILD_NO_BF16=1 GG_BUILD_EXTRA_TESTS_0=1 bash ./ci/run.sh ./tmp/results ./tmp/mnt diff --git a/.github/workflows/build-freebsd.yml b/.github/workflows/build-freebsd.yml new file mode 100644 index 0000000..64e78ad --- /dev/null +++ b/.github/workflows/build-freebsd.yml @@ -0,0 +1,47 @@ +name: CI (freebsd) + +on: + workflow_dispatch: # allows manual triggering + push: + branches: + - master + paths: ['.github/workflows/build-freebsd.yml', + '**/CMakeLists.txt', + '**/Makefile', + '**/*.mk', + '**/*.cmake', + '**/*.in', + '**/*.h', + '**/*.hpp', + '**/*.c', + '**/*.cpp'] + + pull_request: + types: [opened, synchronize, reopened] + paths-ignore: + - 'bindings/ruby/**' # handled by bindings-ruby.yml + - 'bindings/go/**' # handled by bindings-go.yml + - 'examples/addon.node/**' # handled by examples.yml + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref && github.ref || github.run_id }} + cancel-in-progress: true + +jobs: + freeBSD-latest: + runs-on: macos-13 + + steps: + - name: Clone + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + + - name: Build + uses: cross-platform-actions/action@fe0167d8082ac584754ef3ffb567fded22642c7d # v0.27.0 + with: + operating_system: freebsd + version: '14.2' + run: | + sudo pkg update + sudo pkg install -y gmake sdl2 cmake git + cmake -B build + cmake --build build --config Release diff --git a/.github/workflows/build-gcc.yml b/.github/workflows/build-gcc.yml new file mode 100644 index 0000000..53c1b2d --- /dev/null +++ b/.github/workflows/build-gcc.yml @@ -0,0 +1,167 @@ +name: CI (gcc) + +on: + workflow_dispatch: # allows manual triggering + push: + branches: + - master + paths: ['.github/workflows/build-gcc.yml', + '**/CMakeLists.txt', + '**/Makefile', + '**/*.mk', + '**/*.cmake', + '**/*.in', + '**/*.h', + '**/*.hpp', + '**/*.c', + '**/*.cpp', + '**/*.cu', + '**/*.cuh', + '**/*.cl'] + + pull_request: + types: [opened, synchronize, reopened] + paths-ignore: + - 'bindings/ruby/**' # handled by bindings-ruby.yml + - 'bindings/go/**' # handled by bindings-go.yml + - 'examples/addon.node/**' # handled by examples.yml + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref && github.ref || github.run_id }} + cancel-in-progress: true + +env: + ubuntu_image: "ubuntu:22.04" + +jobs: + ubuntu-22-gcc: + runs-on: ubuntu-22.04 + + strategy: + fail-fast: false + matrix: + build: [Debug, Release] + arch: [linux/amd64, linux/ppc64le] + + steps: + - name: Clone + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + + - name: Set CCACHE_DIR + run: echo "CCACHE_DIR=${{ runner.temp }}/ccache" >> $GITHUB_ENV + + - name: ccache + uses: ggml-org/ccache-action@v1.2.21 + with: + key: gcc-${{ matrix.arch }}-${{ matrix.build }} + evict-old-files: 1d + save: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} + + - name: Set up QEMU + uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4 + + - name: Build ${{ matrix.arch }} + run: | + docker run --platform ${{ matrix.arch }} --rm \ + -v ${{ github.workspace }}:/workspace \ + -v ${CCACHE_DIR}:${CCACHE_DIR} \ + -e CCACHE_DIR=${CCACHE_DIR} \ + -w /workspace ${{ env.ubuntu_image }} /bin/sh -c ' + set -e + export DEBIAN_FRONTEND=noninteractive + sed -i "s|archive.ubuntu.com|mirrors.kernel.org|g" /etc/apt/sources.list + sed -i "s|security.ubuntu.com|mirrors.kernel.org|g" /etc/apt/sources.list + + apt update + apt install -y build-essential cmake libsdl2-dev git ccache + cmake . -DWHISPER_SDL2=ON -DCMAKE_BUILD_TYPE=${{ matrix.build }} \ + -DGGML_NATIVE=OFF \ + -DCMAKE_C_COMPILER_LAUNCHER=ccache \ + -DCMAKE_CXX_COMPILER_LAUNCHER=ccache + make + ctest -L gh --output-on-failure' + + ubuntu-22-gcc-arm64: + runs-on: ubuntu-22.04-arm + + strategy: + fail-fast: false + matrix: + build: [Debug, Release] + + steps: + - name: Clone + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + + - name: ccache + uses: ggml-org/ccache-action@v1.2.21 + with: + key: gcc-arm64-${{ matrix.build }} + evict-old-files: 1d + save: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y build-essential cmake libsdl2-dev git + + - name: Configure CMake + run: | + cmake . \ + -DWHISPER_SDL2=ON \ + -DCMAKE_BUILD_TYPE=${{ matrix.build }} \ + -DGGML_NATIVE=OFF \ + -DGGML_CPU_ARM_ARCH=armv8-a + + - name: Build and Test + run: | + make + ctest -L gh --output-on-failure + + ubuntu-22-gcc-arm-v7: + runs-on: ubuntu-22.04 + + strategy: + fail-fast: false + matrix: + build: [Debug, Release] + arch: [linux/arm/v7] + + steps: + - name: Clone + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + + - name: Set CCACHE_DIR + run: echo "CCACHE_DIR=${{ runner.temp }}/ccache" >> $GITHUB_ENV + + - name: ccache + uses: ggml-org/ccache-action@v1.2.21 + with: + key: gcc-${{ matrix.arch }}-${{ matrix.build }} + evict-old-files: 1d + save: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} + + - name: Set up QEMU + uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4 + + - name: Build ${{ matrix.arch }} + run: | + docker run --platform ${{ matrix.arch }} --rm \ + -v ${{ github.workspace }}:/workspace \ + -v ${CCACHE_DIR}:${CCACHE_DIR} \ + -e CCACHE_DIR=${CCACHE_DIR} \ + -w /workspace ${{ env.ubuntu_image }} /bin/sh -c ' + set -e + export DEBIAN_FRONTEND=noninteractive + sed -i "s|archive.ubuntu.com|mirrors.kernel.org|g" /etc/apt/sources.list + sed -i "s|security.ubuntu.com|mirrors.kernel.org|g" /etc/apt/sources.list + + apt update + apt install -y build-essential cmake libsdl2-dev git ccache + cmake . -DWHISPER_SDL2=ON -DCMAKE_BUILD_TYPE=${{ matrix.build }} \ + -DGGML_NATIVE=OFF \ + -DGGML_CPU_ARM_ARCH=armv7-a+fp \ + -DCMAKE_C_COMPILER_LAUNCHER=ccache \ + -DCMAKE_CXX_COMPILER_LAUNCHER=ccache + make + ctest -L gh --output-on-failure' diff --git a/.github/workflows/build-macos.yml b/.github/workflows/build-macos.yml new file mode 100644 index 0000000..7db74d4 --- /dev/null +++ b/.github/workflows/build-macos.yml @@ -0,0 +1,73 @@ +name: CI (macOS) + +on: + workflow_dispatch: # allows manual triggering + push: + branches: + - master + paths: ['.github/workflows/build-macos.yml', + '**/CMakeLists.txt', + '**/Makefile', + '**/*.mk', + '**/*.cmake', + '**/*.in', + '**/*.h', + '**/*.hpp', + '**/*.c', + '**/*.cpp', + '**/*.cu', + '**/*.cuh', + '**/*.swift', + '**/*.m', + '**/*.mm', + '**/*.metal'] + + pull_request: + types: [opened, synchronize, reopened] + paths-ignore: + - 'bindings/ruby/**' # handled by bindings-ruby.yml + - 'bindings/go/**' # handled by bindings-go.yml + - 'examples/addon.node/**' # handled by examples.yml + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref && github.ref || github.run_id }} + cancel-in-progress: true + +jobs: + macOS-latest: + runs-on: macOS-latest + + strategy: + matrix: + destination: ['generic/platform=macOS', 'generic/platform=iOS', 'generic/platform=tvOS'] + + steps: + - name: Clone + id: checkout + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + + - name: ccache + uses: ggml-org/ccache-action@v1.2.21 + with: + key: macos-${{ matrix.destination }} + evict-old-files: 1d + save: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} + + - name: Dependencies + run: | + brew update + cmake --version + brew install sdl2 + + - name: Build + run: | + sysctl -a + cmake -B build -G Xcode \ + -DGGML_NATIVE=OFF \ + -DGGML_METAL_USE_BF16=ON \ + -DGGML_METAL_EMBED_LIBRARY=ON \ + -DWHISPER_BUILD_EXAMPLES=OFF \ + -DWHISPER_BUILD_TESTS=OFF \ + -DWHISPER_BUILD_SERVER=OFF \ + -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" + cmake --build build --config Release -j $(sysctl -n hw.logicalcpu) diff --git a/.github/workflows/build-quantize.yml b/.github/workflows/build-quantize.yml new file mode 100644 index 0000000..11a352e --- /dev/null +++ b/.github/workflows/build-quantize.yml @@ -0,0 +1,48 @@ +name: CI (quantize) + +on: + workflow_dispatch: # allows manual triggering + push: + branches: + - master + paths: ['.github/workflows/build-quantize.yml', + '**/CMakeLists.txt', + '**/*.h', + '**/*.hpp', + '**/*.c', + '**/*.cpp'] + + pull_request: + types: [opened, synchronize, reopened] + paths-ignore: + - 'bindings/ruby/**' # handled by bindings-ruby.yml + - 'bindings/go/**' # handled by bindings-go.yml + - 'examples/addon.node/**' # handled by examples.yml + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref && github.ref || github.run_id }} + cancel-in-progress: true + +jobs: + quantize: + runs-on: ubuntu-22.04 + + steps: + - name: Clone + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + + - name: ccache + uses: ggml-org/ccache-action@v1.2.21 + with: + key: quantize-ubuntu-22 + evict-old-files: 1d + save: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} + + - name: Test quantize + env: + HF_TOKEN: ${{ secrets.HF_TOKEN }} + run: | + ./models/download-ggml-model.sh tiny.en + cmake -B build -DGGML_NATIVE=OFF -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache + cmake --build build --config Release + ./build/bin/whisper-quantize models/ggml-tiny.en.bin models/ggml-tiny.en-q4_0.bin q4_0 diff --git a/.github/workflows/build-sanitize.yml b/.github/workflows/build-sanitize.yml new file mode 100644 index 0000000..465faea --- /dev/null +++ b/.github/workflows/build-sanitize.yml @@ -0,0 +1,85 @@ +name: CI (sanitize) + +on: + workflow_dispatch: # allows manual triggering + push: + branches: + - master + paths: ['.github/workflows/build-sanitize.yml', + '**/CMakeLists.txt', + '**/Makefile', + '**/*.mk', + '**/*.cmake', + '**/*.h', + '**/*.hpp', + '**/*.c', + '**/*.cpp'] + + pull_request: + types: [opened, synchronize, reopened] + paths-ignore: + - 'bindings/ruby/**' + - 'bindings/go/**' + - 'examples/addon.node/**' + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref && github.ref || github.run_id }} + cancel-in-progress: true + +jobs: + ubuntu-22-gcc-sanitized: + runs-on: ubuntu-22.04 + + continue-on-error: true + + strategy: + fail-fast: false + matrix: + sanitizer: [ADDRESS, THREAD, UNDEFINED] + + steps: + - name: Clone + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + + - name: ccache + uses: ggml-org/ccache-action@v1.2.21 + with: + key: sanitize-${{ matrix.sanitizer }} + evict-old-files: 1d + save: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y build-essential cmake git + + - name: Build (undefined) + if: ${{ matrix.sanitizer == 'UNDEFINED' }} + run: | + cmake . -DCMAKE_BUILD_TYPE=Debug \ + -DWHISPER_SANITIZE_${{ matrix.sanitizer }}=ON \ + -DGGML_NATIVE=OFF \ + -DGGML_OPENMP=OFF + make + + - name: Build + if: ${{ matrix.sanitizer == 'ADDRESS' }} + run: | + cmake . -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DWHISPER_SANITIZE_${{ matrix.sanitizer }}=ON \ + -DGGML_NATIVE=OFF + make + + - name: Build (no OpenMP) + if: ${{ matrix.sanitizer == 'THREAD' }} + run: | + cmake . -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DWHISPER_SANITIZE_${{ matrix.sanitizer }}=ON \ + -DGGML_NATIVE=OFF \ + -DGGML_OPENMP=OFF + make + + - name: Test + if: ${{ matrix.sanitizer != 'UNDEFINED' }} + run: | + ctest -L gh --output-on-failure diff --git a/.github/workflows/build-self-hosted.yml b/.github/workflows/build-self-hosted.yml new file mode 100644 index 0000000..8daa9d4 --- /dev/null +++ b/.github/workflows/build-self-hosted.yml @@ -0,0 +1,259 @@ +name: CI (self-hosted) + +on: + workflow_dispatch: # allows manual triggering + push: + branches: + - master + paths: [ + '.github/workflows/build.yml', + '**/CMakeLists.txt', + '**/.cmake', + '**/*.h', + '**/*.hpp', + '**/*.c', + '**/*.cpp', + '**/*.cu', + '**/*.cuh', + '**/*.swift', + '**/*.m', + '**/*.mm', + '**/*.metal', + '**/*.comp' + ] + + pull_request: + types: [opened, synchronize, reopened] + paths: [ + '.github/workflows/build-self-hosted.yml', + '**/CMakeLists.txt', + '**/.cmake', + '**/*.h', + '**/*.hpp', + '**/*.c', + '**/*.cpp', + '**/*.cu', + '**/*.cuh', + '**/*.swift', + '**/*.m', + '**/*.mm', + '**/*.metal', + '**/*.comp' + ] + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref && github.ref || github.run_id }} + cancel-in-progress: true + +jobs: + gpu-cuda: + runs-on: [self-hosted, Linux, NVIDIA] + + steps: + - name: Clone + id: checkout + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + + - name: Test + id: ggml-ci + run: | + nvidia-smi + GG_BUILD_CUDA=1 bash ./ci/run.sh ~/results/whisper.cpp ~/mnt/whisper.cpp + + gpu-vulkan-nvidia-cm: + runs-on: [self-hosted, Linux, NVIDIA] + + steps: + - name: Clone + id: checkout + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + + - name: Test + id: ggml-ci + run: | + vulkaninfo --summary + GG_BUILD_VULKAN=1 GGML_VK_DISABLE_COOPMAT2=1 bash ./ci/run.sh ~/results/whisper.cpp ~/mnt/whisper.cpp + + gpu-vulkan-nvidia-cm2: + runs-on: [self-hosted, Linux, NVIDIA, COOPMAT2] + + steps: + - name: Clone + id: checkout + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + + - name: Test + id: ggml-ci + run: | + vulkaninfo --summary + GG_BUILD_VULKAN=1 bash ./ci/run.sh ~/results/whisper.cpp ~/mnt/whisper.cpp + + gpu-metal: + runs-on: [self-hosted, macOS, ARM64] + + steps: + - name: Clone + id: checkout + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + + - name: Test + id: ggml-ci + run: | + GG_BUILD_METAL=1 bash ./ci/run.sh ~/results/whisper.cpp ~/mnt/whisper.cpp + + gpu-vulkan: + runs-on: [self-hosted, macOS, ARM64] + + steps: + - name: Clone + id: checkout + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + + - name: Test + id: ggml-ci + run: | + vulkaninfo --summary + GG_BUILD_VULKAN=1 bash ./ci/run.sh ~/results/whisper.cpp ~/mnt/whisper.cpp + + npu-amd-windows: + runs-on: [self-hosted, Windows, X64, strix-halo, devlab-dispatch] + timeout-minutes: 60 + continue-on-error: true # advisory while the runner pool is new; revisit later + + env: + FLEXML_URL: https://github.com/lemonade-sdk/whisper.cpp-rocm/releases/download/deps/flexmlrt-1.7.0-win.zip + MODEL: base + + steps: + - name: Clone + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + + - uses: microsoft/setup-msbuild@v2 + + - name: Install CMake if not available + shell: powershell + run: | + $installed = Get-Command cmake -ErrorAction SilentlyContinue + if (-not $installed) { + $ver = "3.28.1" + $url = "https://github.com/Kitware/CMake/releases/download/v$ver/cmake-$ver-windows-x86_64.msi" + Invoke-WebRequest -Uri $url -OutFile cmake.msi + Start-Process msiexec.exe -ArgumentList "/i cmake.msi /quiet /norestart" -Wait + $p = "C:\Program Files\CMake\bin" + $env:PATH = "$p;$env:PATH" + echo $p >> $env:GITHUB_PATH + cmake --version + if ($LASTEXITCODE -ne 0) { Write-Error "CMake install failed"; exit 1 } + } else { cmake --version } + + - name: Download FlexML runtime + shell: powershell + run: | + Invoke-WebRequest -Uri "${{ env.FLEXML_URL }}" -OutFile flexmlrt.zip + if (-Not (Test-Path "flexmlrt.zip")) { Write-Error "flexmlrt.zip not downloaded"; exit 1 } + if ((Get-Item "flexmlrt.zip").Length -eq 0) { Write-Error "flexmlrt.zip is empty"; exit 1 } + tar xf flexmlrt.zip + if ($LASTEXITCODE -ne 0) { Write-Error "Extraction failed"; exit 1 } + if (-not (Test-Path "flexmlrt")) { Write-Error "No flexmlrt directory after extraction"; exit 1 } + + - name: Setup FlexML, configure and build + shell: cmd + run: | + cd flexmlrt + call setup.bat + if errorlevel 1 ( echo ERROR: FlexML setup.bat failed & exit /b 1 ) + cd .. + cmake -B build -A x64 -DCMAKE_BUILD_TYPE=Release -DWHISPER_VITISAI=ON + if errorlevel 1 ( echo ERROR: CMake configure failed & exit /b 1 ) + cmake --build build --config Release -j + if errorlevel 1 ( echo ERROR: Build failed & exit /b 1 ) + + - name: Copy FlexML DLLs to build output + shell: powershell + run: | + foreach ($d in "flexmlrt/bin", "flexmlrt/lib") { + if (Test-Path "$d/*.dll") { Copy-Item "$d/*.dll" "build/bin/Release/" -Force } + } + if (-not (Test-Path "build/bin/Release/flexmlrt.dll")) { + Write-Error "flexmlrt.dll not staged next to binaries"; exit 1 + } + + - name: Download ggml model + shell: cmd + run: | + call models\download-ggml-model.cmd %MODEL% models + if not exist models\ggml-%MODEL%.bin ( echo ERROR: model download failed & exit /b 1 ) + + - name: Download NPU encoder cache + shell: cmd + run: | + .\models\download-vitisai-model.cmd %MODEL% + if not exist models\ggml-%MODEL%-encoder-vitisai.rai ( echo ERROR: VitisAI encoder cache download failed & exit /b 1 ) + + - name: Run NPU smoke test + shell: cmd + run: | + build\bin\Release\whisper-cli.exe -m models\ggml-%MODEL%.bin -f samples\jfk.wav > vitisai.log 2>&1 + type vitisai.log + findstr /I /C:"vitisai" vitisai.log || ( echo ERROR: no VitisAI activity - encoder likely fell back to CPU & exit /b 1 ) + findstr /I /C:"ask not what your country" vitisai.log || ( echo ERROR: incorrect transcription & exit /b 1 ) + + - name: Upload smoke test log + if: always() + uses: actions/upload-artifact@v4 + with: + name: vitisai-smoke-log-windows + path: vitisai.log + + npu-amd-linux: + runs-on: [self-hosted, Linux, X64, strix-halo, devlab-dispatch] + timeout-minutes: 60 + continue-on-error: true # advisory while the runner pool is new; revisit later + + env: + FLEXML_LINUX_URL: https://github.com/lemonade-sdk/whisper.cpp-rocm/releases/download/deps/flexmlrt-1.8.0-linux.tar.gz + MODEL: base + + steps: + - name: Clone + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + + - name: Verify NPU device + run: | + lsmod | grep -q amdxdna || { echo "ERROR: amdxdna driver not loaded"; exit 1; } + ls /dev/accel/accel* || { echo "ERROR: no NPU accel device node"; exit 1; } + + - name: Download FlexML runtime (Linux) + run: | + curl -L --fail -o flexmlrt.tar.gz "$FLEXML_LINUX_URL" + tar xf flexmlrt.tar.gz + source flexmlrt/setup.sh + echo "FlexmlRT_DIR=$PWD/flexmlrt/share/cmake/FlexmlRT" >> $GITHUB_ENV + echo "LD_LIBRARY_PATH=$PWD/flexmlrt/lib:$LD_LIBRARY_PATH" >> $GITHUB_ENV + + - name: Configure and build + run: | + cmake -B build -DCMAKE_BUILD_TYPE=Release -DWHISPER_VITISAI=ON + cmake --build build --config Release -j $(nproc) + + - name: Download ggml model + run: | + ./models/download-ggml-model.sh $MODEL + + - name: Download NPU encoder cache + run: | + sh ./models/download-vitisai-model.sh $MODEL + [ -f "models/ggml-$MODEL-encoder-vitisai.rai" ] || { echo "ERROR: VitisAI encoder cache download failed"; exit 1; } + + - name: Run NPU smoke test + run: | + ./build/bin/whisper-cli -m "models/ggml-$MODEL.bin" -f samples/jfk.wav 2>&1 | tee vitisai.log + grep -qi "vitisai" vitisai.log || { echo "ERROR: no VitisAI activity - CPU fallback?"; exit 1; } + grep -qi "ask not what your country" vitisai.log || { echo "ERROR: incorrect transcription"; exit 1; } + + - name: Upload smoke test log + if: always() + uses: actions/upload-artifact@v4 + with: + name: vitisai-smoke-log-linux + path: vitisai.log diff --git a/.github/workflows/build-sycl.yml b/.github/workflows/build-sycl.yml new file mode 100644 index 0000000..be7d032 --- /dev/null +++ b/.github/workflows/build-sycl.yml @@ -0,0 +1,150 @@ +name: CI (sycl) + +on: + workflow_dispatch: # allows manual triggering + push: + branches: + - master + paths: ['.github/workflows/build-sycl.yml', + '**/CMakeLists.txt', + '**/Makefile', + '**/*.mk', + '**/*.cmake', + '**/*.in', + '**/*.h', + '**/*.hpp', + '**/*.c', + '**/*.cpp', + '**/*.cu', + '**/*.cuh', + '**/*.cl'] + + pull_request: + types: [opened, synchronize, reopened] + paths-ignore: + - 'bindings/ruby/**' # handled by bindings-ruby.yml + - 'bindings/go/**' # handled by bindings-go.yml + - 'examples/addon.node/**' # handled by examples.yml + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref && github.ref || github.run_id }} + cancel-in-progress: true + +jobs: + ubuntu-22-cmake-sycl: + runs-on: ubuntu-22.04 + + strategy: + fail-fast: false + matrix: + dwhisper_sycl: [ON] + dcmake_c_compiler: [icx] + dcmake_cxx_compiler: [icpx] + arch: [linux/amd64, linux/arm64, linux/arm/v7, linux/ppc64le] + + continue-on-error: true + + steps: + - name: Clone + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + + - name: add oneAPI to apt + shell: bash + run: | + cd /tmp + wget https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB + sudo apt-key add GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB + rm GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB + sudo add-apt-repository "deb https://apt.repos.intel.com/oneapi all main" + + - name: install oneAPI dpcpp compiler + shell: bash + run: | + sudo apt update + sudo apt install intel-oneapi-compiler-dpcpp-cpp + + - name: install oneAPI MKL library + shell: bash + run: | + sudo apt install intel-oneapi-mkl-devel + + - name: ccache + uses: ggml-org/ccache-action@v1.2.21 + with: + key: sycl-${{ matrix.arch }} + evict-old-files: 1d + save: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} + + - name: Build + id: cmake_build + env: + CCACHE_SLOPPINESS: time_macros + CCACHE_NODIRECT: 1 + run: | + source /opt/intel/oneapi/setvars.sh + export CCACHE_COMPILERCHECK="string:$(icpx --version 2>&1 | head -1)" + mkdir build + cd build + cmake -DGGML_SYCL=ON -DGGML_NATIVE=OFF -DCMAKE_C_COMPILER=icx -DCMAKE_CXX_COMPILER=icpx \ + -DCMAKE_C_COMPILER_LAUNCHER=ccache \ + -DCMAKE_CXX_COMPILER_LAUNCHER=ccache .. + cmake --build . --config Release -j $(nproc) + + ubuntu-22-cmake-sycl-fp16: + runs-on: ubuntu-22.04 + + strategy: + fail-fast: false + matrix: + dwhisper_sycl: [ON] + dcmake_c_compiler: [icx] + dcmake_cxx_compiler: [icpx] + arch: [linux/amd64, linux/arm64, linux/arm/v7, linux/ppc64le] + + continue-on-error: true + + steps: + - name: Clone + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + + - name: add oneAPI to apt + shell: bash + run: | + cd /tmp + wget https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB + sudo apt-key add GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB + rm GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB + sudo add-apt-repository "deb https://apt.repos.intel.com/oneapi all main" + + - name: install oneAPI dpcpp compiler + shell: bash + run: | + sudo apt update + sudo apt install intel-oneapi-compiler-dpcpp-cpp + + - name: install oneAPI MKL library + shell: bash + run: | + sudo apt install intel-oneapi-mkl-devel + + - name: ccache + uses: ggml-org/ccache-action@v1.2.21 + with: + key: sycl-fp16-${{ matrix.arch }} + evict-old-files: 1d + save: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} + + - name: Build + id: cmake_build + env: + CCACHE_SLOPPINESS: time_macros + CCACHE_NODIRECT: 1 + run: | + source /opt/intel/oneapi/setvars.sh + export CCACHE_COMPILERCHECK="string:$(icpx --version 2>&1 | head -1)" + mkdir build + cd build + cmake -DGGML_SYCL_F16=ON -DGGML_NATIVE=OFF -DCMAKE_C_COMPILER=icx -DCMAKE_CXX_COMPILER=icpx \ + -DCMAKE_C_COMPILER_LAUNCHER=ccache \ + -DCMAKE_CXX_COMPILER_LAUNCHER=ccache .. + cmake --build . --config Release -j $(nproc) diff --git a/.github/workflows/build-vad.yml b/.github/workflows/build-vad.yml new file mode 100644 index 0000000..d34a96e --- /dev/null +++ b/.github/workflows/build-vad.yml @@ -0,0 +1,50 @@ +name: CI (vad) + +on: + workflow_dispatch: # allows manual triggering + push: + branches: + - master + paths: ['.github/workflows/build-vad.yml', + '**/CMakeLists.txt', + '**/*.h', + '**/*.hpp', + '**/*.c', + '**/*.cpp'] + + pull_request: + types: [opened, synchronize, reopened] + paths-ignore: + - 'bindings/ruby/**' # handled by bindings-ruby.yml + - 'bindings/go/**' # handled by bindings-go.yml + - 'examples/addon.node/**' # handled by examples.yml + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref && github.ref || github.run_id }} + cancel-in-progress: true + +jobs: + vad: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + + - name: ccache + uses: ggml-org/ccache-action@v1.2.21 + with: + key: vad-ubuntu-latest + evict-old-files: 1d + save: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} + + - name: Build + shell: bash + run: | + cmake -B build -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DGGML_NATIVE=OFF + cmake --build build --config Release + + - name: Test + shell: bash + run: | + ctest -R ^test-vad$ --test-dir build --output-on-failure -VV diff --git a/.github/workflows/build-wasm.yml b/.github/workflows/build-wasm.yml new file mode 100644 index 0000000..c17a44a --- /dev/null +++ b/.github/workflows/build-wasm.yml @@ -0,0 +1,65 @@ +name: CI (wasm) + +on: + workflow_dispatch: # allows manual triggering + push: + branches: + - master + paths: ['.github/workflows/build-wasm.yml', + '**/CMakeLists.txt', + '**/Makefile', + '**/*.mk', + '**/*.cmake', + '**/*.in', + '**/*.h', + '**/*.hpp', + '**/*.c', + '**/*.cpp'] + + pull_request: + types: [opened, synchronize, reopened] + paths-ignore: + - 'bindings/ruby/**' # handled by bindings-ruby.yml + - 'bindings/go/**' # handled by bindings-go.yml + - 'examples/addon.node/**' # handled by examples.yml + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref && github.ref || github.run_id }} + cancel-in-progress: true + +jobs: + emscripten: + runs-on: ubuntu-22.04 + + strategy: + matrix: + build: [Release] + + steps: + - name: Clone + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + + - name: Setup emsdk + uses: emscripten-core/setup-emsdk@6ab9eb1bda2574c4ddb79809fc9247783eaf9021 # v14 + + - name: Verify + run: emcc -v + + - name: ccache + uses: ggml-org/ccache-action@v1.2.21 + with: + key: wasm-ubuntu-22 + evict-old-files: 1d + save: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} + + - name: Build + env: + CCACHE_SLOPPINESS: time_macros,include_file_mtime,include_file_ctime + CCACHE_COMPILERCHECK: content + run: | + emcmake cmake -B build -DCMAKE_BUILD_TYPE=${{ matrix.build }} \ + -DCMAKE_C_COMPILER_LAUNCHER=ccache \ + -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ + "-DCMAKE_C_FLAGS=-ffile-prefix-map=$EMSDK=/emsdk" \ + "-DCMAKE_CXX_FLAGS=-ffile-prefix-map=$EMSDK=/emsdk" + cmake --build build -j $(nproc) diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml new file mode 100644 index 0000000..76b7a73 --- /dev/null +++ b/.github/workflows/build-windows.yml @@ -0,0 +1,74 @@ +name: CI (windows) + +on: + workflow_dispatch: # allows manual triggering + push: + branches: + - master + paths: ['.github/workflows/build-windows.yml', + '**/CMakeLists.txt', + '**/Makefile', + '**/*.mk', + '**/*.cmake', + '**/*.in', + '**/*.h', + '**/*.hpp', + '**/*.c', + '**/*.cpp', + '**/*.cu', + '**/*.cuh', + '**/*.cl'] + + pull_request: + types: [opened, synchronize, reopened] + paths-ignore: + - 'bindings/ruby/**' # handled by bindings-ruby.yml + - 'bindings/go/**' # handled by bindings-go.yml + - 'examples/addon.node/**' # handled by examples.yml + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref && github.ref || github.run_id }} + cancel-in-progress: true + +jobs: + windows-msys2: + runs-on: windows-latest + + strategy: + fail-fast: false + matrix: + include: + - { sys: UCRT64, env: ucrt-x86_64, compiler: gcc, build: Release } + - { sys: CLANG64, env: clang-x86_64, compiler: clang, build: Release } + + steps: + - name: Clone + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + + - name: Setup ${{ matrix.sys }} + uses: msys2/setup-msys2@cafece8e6baf9247cf9b1bf95097b0b983cc558d # v2 + with: + update: true + msystem: ${{matrix.sys}} + install: >- + mingw-w64-${{matrix.env}}-${{matrix.compiler}} + mingw-w64-${{matrix.env}}-cmake + mingw-w64-${{matrix.env}}-SDL2 + mingw-w64-${{matrix.env}}-openblas + + - name: Build using CMake + shell: msys2 {0} + run: | + cmake -B build -DWHISPER_SDL2=ON + cmake --build build --config ${{ matrix.build }} -j $(nproc) + + - name: Clean after building using CMake + shell: msys2 {0} + run: | + rm -rf build + + - name: Build using CMake w/ OpenBLAS + shell: msys2 {0} + run: | + cmake -B build -DGGML_BLAS=ON -DGGML_BLAS_VENDOR=OpenBLAS + cmake --build build --config ${{ matrix.build }} -j $(nproc) diff --git a/.github/workflows/close-issue.yml b/.github/workflows/close-issue.yml new file mode 100644 index 0000000..449feac --- /dev/null +++ b/.github/workflows/close-issue.yml @@ -0,0 +1,28 @@ +name: Mark inactive issues stale +on: + schedule: + - cron: "42 0 * * *" + +# Fine-grant permission +# https://docs.github.com/en/actions/security-for-github-actions/security-guides/automatic-token-authentication#modifying-the-permissions-for-the-github_token +permissions: + issues: write + +jobs: + mark-issues: + runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write + steps: + - uses: actions/stale@v10 + with: + exempt-issue-labels: "refactor,help wanted,good first issue,research,bug,roadmap" + days-before-issue-stale: 30 + days-before-issue-close: -1 + stale-issue-label: "stale" + stale-issue-message: "This issue was marked as stale because it has been inactive for 30 days." + days-before-pr-stale: -1 + days-before-pr-close: -1 + operations-per-run: 10000 + repo-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/deploy-examples-wasm.yml b/.github/workflows/deploy-examples-wasm.yml new file mode 100644 index 0000000..55df147 --- /dev/null +++ b/.github/workflows/deploy-examples-wasm.yml @@ -0,0 +1,97 @@ +name: Examples WASM +on: + push: + branches: ["master"] + + workflow_dispatch: + +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: "pages" + cancel-in-progress: false + +jobs: + deploy-wasm-github-pages: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + + - name: Setup Pages + uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5 + + - name: Setup emsdk + uses: emscripten-core/setup-emsdk@6ab9eb1bda2574c4ddb79809fc9247783eaf9021 # v14 + + - name: Build WASM Examples + # Enable for real build later in whisper.cpp + run: | + mkdir -p build-em && cd build-em + emcmake cmake .. -DCMAKE_BUILD_TYPE=Release + make -j + + - name: Create staging directory + run: mkdir -p staging + + - name: Create .nojekyll file in staging directory + run: touch staging/.nojekyll + + - name: Copy application files + run: | + build_dir=build-em/bin + + ls ${build_dir} + + # command.wasm + target_dir=staging/command.wasm + mkdir -p ${target_dir} + cp ${build_dir}/command.wasm/{index.html,command.js,helpers.js} ${target_dir} + cp ${build_dir}/libcommand.js ${target_dir} + + # bench.wasm + target_dir=staging/bench.wasm + mkdir -p ${target_dir} + cp ${build_dir}/bench.wasm/{index.html,bench.js,helpers.js} ${target_dir} + cp ${build_dir}/libbench.js ${target_dir} + + # stream.wasm + target_dir=staging/stream.wasm + mkdir -p ${target_dir} + cp ${build_dir}/stream.wasm/{index.html,stream.js,helpers.js} ${target_dir} + cp ${build_dir}/libstream.js ${target_dir} + + # wchess.wasm + target_dir=staging/wchess.wasm + mkdir -p ${target_dir} + cp -r ${build_dir}/wchess.wasm/{index.html,css,img,js} ${target_dir} + cp ${build_dir}/wchess.wasm.js ${target_dir} + + # whisper.wasm (this will be the main example page) + target_dir=staging + mkdir -p ${target_dir} + cp ${build_dir}/whisper.wasm/{index.html,main.js,helpers.js} ${target_dir} + cp ${build_dir}/libmain.js ${target_dir} + + # Copy Cross-Origin Isolation service worker + cp -v examples/coi-serviceworker.js staging/ + + - name: List files in staging directory (for debugging) + run: | + echo "Files in staging directory:" + find staging -type f | sort + + - name: Upload artifact + uses: actions/upload-pages-artifact@7b1f4a764d45c48632c6b24a0339c27f5614fb0b # v4 + with: + path: ./staging + + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4 diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 0000000..2d95e1a --- /dev/null +++ b/.github/workflows/docker.yml @@ -0,0 +1,73 @@ +name: Publish Docker image + +on: + workflow_dispatch: # allows manual triggering + schedule: + # Rebuild daily rather than on every push because it is expensive + - cron: '12 4 * * *' + +jobs: + push_to_registry: + name: Push Docker image to Docker Hub + + runs-on: ${{ matrix.config.runs_on }} + env: + COMMIT_SHA: ${{ github.sha }} + strategy: + fail-fast: false + matrix: + config: + - { tag: "main", dockerfile: ".devops/main.Dockerfile", platform: "linux/amd64", runs_on: "ubuntu-24.04" } + - { tag: "main-arm64", dockerfile: ".devops/main.Dockerfile", platform: "linux/arm64", runs_on: "ubuntu-24.04-arm" } + - { tag: "main-musa", dockerfile: ".devops/main-musa.Dockerfile", platform: "linux/amd64", runs_on: "ubuntu-24.04" } + - { tag: "main-intel", dockerfile: ".devops/main-intel.Dockerfile", platform: "linux/amd64", runs_on: "ubuntu-24.04" } + - { tag: "main-cuda", dockerfile: ".devops/main-cuda.Dockerfile", platform: "linux/amd64", runs_on: "ubuntu-24.04" } + - { tag: "main-vulkan", dockerfile: ".devops/main-vulkan.Dockerfile", platform: "linux/amd64", runs_on: "ubuntu-24.04" } + - { tag: "main-vulkan-arm64", dockerfile: ".devops/main-vulkan.Dockerfile", platform: "linux/arm64", runs_on: "ubuntu-24.04-arm" } + + steps: + - name: Check out the repo + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4 + + - name: Log in to Docker Hub + uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Free up disk space + run: | + sudo apt-get remove -y '^dotnet-.*' '^llvm-.*' '^mysql-.*' '^postgresql-.*' + sudo apt-get autoremove -y + sudo apt-get autoclean + + sudo rm -rf /usr/share/dotnet + sudo rm -rf /usr/local/lib/android + sudo rm -rf /opt/ghc + sudo rm -rf /opt/hostedtoolcache/CodeQL + + docker system prune -af + + df -h + + - name: Generate tags + id: tags + run: | + TAGS="ghcr.io/${{ github.repository }}:${{ matrix.config.tag }}" + TAGS="$TAGS,ghcr.io/${{ github.repository }}:${{ matrix.config.tag }}-${{ env.COMMIT_SHA }}" + echo "tags=$TAGS" >> $GITHUB_OUTPUT + + - name: Build and push Docker image (tagged) + uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7 + with: + context: . + push: true + platforms: ${{ matrix.config.platform }} + tags: ${{ steps.tags.outputs.tags }} + file: ${{ matrix.config.dockerfile }} + secrets: | + HF_TOKEN=${{ secrets.HF_TOKEN }} diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml new file mode 100644 index 0000000..0f8f0a0 --- /dev/null +++ b/.github/workflows/examples.yml @@ -0,0 +1,53 @@ +name: Examples Tests +on: + push: + branches: + - master + paths: + - examples/addon.node/** + - include/whisper.h + pull_request: + paths: + - examples/addon.node/** + - include/whisper.h + +jobs: + addon_node-ubuntu-22: + runs-on: ubuntu-22.04 + strategy: + matrix: + node-version: [ 20.x, 22.x ] + steps: + - name: Clone + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + + - name: Dependencies + run: | + sudo apt-get update + sudo apt-get install build-essential git + sudo apt-get install cmake + sudo apt-get install libsdl2-dev + + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6 + with: + node-version: ${{ matrix.node-version }} + cache: 'npm' + cache-dependency-path: examples/addon.node/package-lock.json + + - name: Install package.json dependencies + working-directory: ./examples/addon.node + run: npm install + + - name: Compile addon.node + run: npx cmake-js compile -T addon.node -B Release + + - name: Download test model + env: + HF_TOKEN: ${{ secrets.HF_TOKEN }} + run: | + bash ./models/download-ggml-model.sh base.en + - name: Test + run: | + cd examples/addon.node + npm run test diff --git a/.github/workflows/make-release.yml b/.github/workflows/make-release.yml new file mode 100644 index 0000000..451c3a5 --- /dev/null +++ b/.github/workflows/make-release.yml @@ -0,0 +1,88 @@ +name: Make Release + +on: + workflow_dispatch: + inputs: + commit: + description: 'Commit SHA to release (empty = branch HEAD)' + required: false + default: '' + type: string + dry_run: + description: 'Dry run - validate without creating the tag' + required: true + type: boolean + default: true + +env: + GH_TOKEN: ${{ github.token }} + +permissions: + contents: write + +jobs: + make-release: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + with: + ref: ${{ inputs.commit != '' && inputs.commit || github.ref_name }} + fetch-depth: 0 + ssh-key: ${{ secrets.DEPLOY_KEY_RELEASE }} + + - name: Run release checks + id: checks + run: bash scripts/make-release-checks.sh ${{ github.event.inputs.dry_run == 'true' && '--dry-run' || '' }} + env: + GITHUB_REPOSITORY: ${{ github.repository }} + RELEASE_BRANCH: ${{ github.ref_name }} + + - name: Create release tag + if: ${{ github.event.inputs.dry_run == 'false' }} + run: | + VERSION="${{ steps.checks.outputs.version }}" + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git tag -a "${VERSION}" -m "Release ${VERSION}" + git push origin "${VERSION}" + echo "Created and pushed tag ${VERSION}" + + - name: Generate release description + id: desc + run: bash scripts/make-release-desc.sh "${{ steps.checks.outputs.version }}" + env: + GITHUB_REPOSITORY: ${{ github.repository }} + + - name: Create release + if: ${{ github.event.inputs.dry_run == 'false' }} + uses: ggml-org/action-create-release@v1 + env: + GITHUB_TOKEN: ${{ github.token }} + with: + tag_name: ${{ steps.checks.outputs.version }} + prerelease: false + # TODO: enrich the body of the release with more information + body: | + ## Overview + + New version has been released. + + ${{ steps.desc.outputs.nightly }} + **More info:** [dist : releases and versioning of ggml-org projects](https://github.com/ggml-org/ggml/discussions/1579) + + ## ${{ steps.desc.outputs.changelog_title }} + + ${{ steps.desc.outputs.changelog }} + + - name: Dry run summary + if: ${{ github.event.inputs.dry_run == 'true' }} + run: | + if [[ "${{ steps.checks.outputs.checks_passed }}" == "true" ]]; then + echo "Dry run complete - all checks passed." + echo "Would have created tag: ${{ steps.checks.outputs.version }}" + else + echo "::error::Dry run found release check failures. A release tag would not be created." + exit 1 + fi diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..e72f2c7 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,941 @@ +name: Release + +# Builds dev releases (b* tags) when manually dispatched with create_release: true. +# Run this as a verification build before making a release (see make-release.yml). +# Pushing a v* tag does not trigger this workflow; releases are made via make-release.yml. + +on: + workflow_dispatch: + inputs: + create_release: + description: 'Create new developer release' + required: true + type: boolean + pre_release_tag: + description: 'Pre-release tag name' + required: false + type: string + +env: + BRANCH_NAME: ${{ github.head_ref || github.ref_name }} + VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite" + WHISPER_BUILD_IS_DEV: OFF + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref && github.ref || github.run_id }} + cancel-in-progress: true + +permissions: + contents: write # for creating release + id-token: write + attestations: write + +jobs: + determine-tag: + runs-on: ubuntu-latest + outputs: + tag_name: ${{ steps.tag.outputs.name }} + should_release: ${{ steps.tag.outputs.should_release }} + + steps: + - name: Checkout with full history + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + with: + fetch-depth: 0 + + - name: Determine tag name + id: tag + shell: bash + run: | + BUILD_NUMBER=$(git rev-list --count HEAD) + SHORT_HASH=$(git rev-parse --short=7 HEAD) + CUSTOM_TAG="${{ github.event.inputs.pre_release_tag }}" + SHOULD_RELEASE="false" + + echo "Raw values:" + echo "BUILD_NUMBER: $BUILD_NUMBER" + echo "SHORT_HASH: $SHORT_HASH" + echo "BRANCH_NAME: ${{ env.BRANCH_NAME }}" + echo "CUSTOM_TAG: $CUSTOM_TAG" + + if [[ -n "$CUSTOM_TAG" ]]; then + echo "Using custom tag" + TAG_NAME="${CUSTOM_TAG}" + SHOULD_RELEASE="true" + elif [[ "${{ env.BRANCH_NAME }}" == "master" ]]; then + echo "Using master branch format" + TAG_NAME="b${BUILD_NUMBER}" + SHOULD_RELEASE="false" + else + echo "Using non-master branch format" + SAFE_NAME=$(echo "${{ env.BRANCH_NAME }}" | tr '/' '-') + TAG_NAME="${SAFE_NAME}-b${BUILD_NUMBER}-${SHORT_HASH}" + SHOULD_RELEASE="false" + fi + + if [[ "${{ github.event.inputs.create_release }}" == "true" ]]; then + echo "Manual release requested" + SHOULD_RELEASE="true" + fi + + echo "Final tag name: $TAG_NAME" + echo "Should release: $SHOULD_RELEASE" + echo "name=$TAG_NAME" >> $GITHUB_OUTPUT + echo "should_release=$SHOULD_RELEASE" >> $GITHUB_OUTPUT + + ubuntu-cpu: + runs-on: ${{ matrix.os }} + needs: determine-tag + if: ${{ needs.determine-tag.outputs.should_release == 'true' }} + + strategy: + matrix: + include: + - build: x64 + os: ubuntu-22.04 + - build: arm64 + os: ubuntu-22.04-arm + + steps: + - name: Clone + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + + - name: ccache + uses: ggml-org/ccache-action@v1.2.21 + with: + key: release-${{ matrix.os }}-cpu + evict-old-files: 1d + + - name: Dependencies + run: | + sudo apt-get update + sudo apt-get install -y build-essential cmake + + - name: Build + run: | + cmake -B build \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_RPATH='$ORIGIN' \ + -DCMAKE_BUILD_WITH_INSTALL_RPATH=ON \ + -DGGML_BACKEND_DL=ON \ + -DGGML_NATIVE=OFF \ + -DWHISPER_BUILD_IS_DEV=${{ env.WHISPER_BUILD_IS_DEV }} \ + ${{ matrix.build == 'x64' && '-DGGML_CPU_ALL_VARIANTS=ON' || '-DGGML_CPU_ARM_ARCH=armv8-a' }} + cmake --build build --config Release -j $(nproc) + + - name: Pack artifacts + run: | + cp LICENSE ./build/bin/ + tar -czvf whisper-bin-ubuntu-${{ matrix.build }}.tar.gz \ + --transform "s,^\.,whisper-bin-ubuntu-${{ matrix.build }}," \ + -C ./build/bin . + + - name: Upload artifacts + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + path: whisper-bin-ubuntu-${{ matrix.build }}.tar.gz + name: whisper-bin-ubuntu-${{ matrix.build }}.tar.gz + + windows: + runs-on: windows-latest + needs: determine-tag + + strategy: + matrix: + build: [Release] + arch: [Win32, x64] + sdl2: [ON] + include: + - arch: Win32 + s2arc: x86 + jnaPath: win32-x86 + - arch: x64 + s2arc: x64 + jnaPath: win32-x86-64 + - sdl2: ON + s2ver: 2.28.5 + + steps: + - name: Clone + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + + - name: Add msbuild to PATH + uses: microsoft/setup-msbuild@6fb02220983dee41ce7ae257b6f4d8f9bf5ed4ce # v2 + + - name: Fetch SDL2 and set SDL2_DIR + if: matrix.sdl2 == 'ON' + run: | + C:/msys64/usr/bin/wget.exe -qO sdl2.zip https://github.com/libsdl-org/SDL/releases/download/release-${{ matrix.s2ver }}/SDL2-devel-${{ matrix.s2ver }}-VC.zip + 7z x sdl2.zip + echo "SDL2_DIR=$env:GITHUB_WORKSPACE/SDL2-${{ matrix.s2ver }}/cmake" >> $env:GITHUB_ENV + + - name: Configure + run: > + cmake -S . -B ./build -A ${{ matrix.arch }} + -DCMAKE_BUILD_TYPE=${{ matrix.build }} + -DBUILD_SHARED_LIBS=ON + -DWHISPER_SDL2=${{ matrix.sdl2 }} + -DGGML_NATIVE=OFF + -DWHISPER_BUILD_IS_DEV=${{ env.WHISPER_BUILD_IS_DEV }} + ${{ matrix.arch == 'x64' && '-DGGML_BACKEND_DL=ON -DGGML_CPU_ALL_VARIANTS=ON' || '-DGGML_BMI2=OFF' }} + + - name: Build + run: | + cd ./build + msbuild ALL_BUILD.vcxproj -t:build -p:configuration=${{ matrix.build }} -p:platform=${{ matrix.arch }} + + - name: Copy SDL2.dll + if: matrix.sdl2 == 'ON' + run: copy "$env:SDL2_DIR/../lib/${{ matrix.s2arc }}/SDL2.dll" build/bin/${{ matrix.build }} + + - name: Upload SDL2.dll + if: matrix.sdl2 == 'ON' + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: ${{ matrix.s2arc }}_SDL2.dll + path: build/bin/${{ matrix.build }}/SDL2.dll + + - name: Upload whisper dll + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: whisper_${{ matrix.arch }}.dll + path: build/bin/${{ matrix.build }}/whisper.dll + + - name: Upload ggml dll + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: ggml_${{ matrix.arch }}.dll + path: build/bin/${{ matrix.build }}/ggml.dll + overwrite: true + + - name: Upload ggml base dll + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: ggml_base_${{ matrix.arch }}.dll + path: build/bin/${{ matrix.build }}/ggml-base.dll + + - name: Upload ggml cpu dll + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: ggml_cpu_${{ matrix.arch }}.dll + path: build/bin/${{ matrix.build }}/ggml-cpu.dll + + - name: Pack bin artifacts + shell: pwsh + run: | + Compress-Archive -Path "build/bin/${{ matrix.build }}" -DestinationPath "whisper-bin-${{ matrix.arch }}.zip" + + - name: Upload binaries + if: ${{ matrix.sdl2 == 'ON' && needs.determine-tag.outputs.should_release == 'true' }} + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: whisper-bin-${{ matrix.arch }}.zip + path: whisper-bin-${{ matrix.arch }}.zip + + windows-blas: + runs-on: windows-latest + needs: determine-tag + + strategy: + matrix: + build: [Release] + arch: [Win32, x64] + blas: [ON] + sdl2: [ON] + blasver: [0.3.29] + include: + - arch: Win32 + s2arc: x86 + blasfile: x86 + - arch: x64 + s2arc: x64 + blasfile: x64_64 + - sdl2: ON + s2ver: 2.28.5 + + steps: + - name: Clone + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + + - name: Export GitHub Actions cache environment variables + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + with: + script: | + core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || ''); + core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || ''); + + - name: Add msbuild to PATH + uses: microsoft/setup-msbuild@6fb02220983dee41ce7ae257b6f4d8f9bf5ed4ce # v2 + + - name: Install OpenBLAS and pkgconfiglite + if: matrix.blas == 'ON' + run: | + Invoke-WebRequest "https://github.com/OpenMathLib/OpenBLAS/releases/download/v${{matrix.blasver}}/OpenBLAS-${{matrix.blasver}}_${{matrix.blasfile}}.zip" -OutFile "OpenBLAS-${{matrix.blasver}}.zip" + Expand-Archive "OpenBLAS-${{matrix.blasver}}.zip" -DestinationPath "OpenBLAS-${{matrix.blasver}}" + choco install pkgconfiglite + + - name: Fetch SDL2 and set SDL2_DIR + if: matrix.sdl2 == 'ON' + run: | + C:/msys64/usr/bin/wget.exe -qO sdl2.zip https://github.com/libsdl-org/SDL/releases/download/release-${{ matrix.s2ver }}/SDL2-devel-${{ matrix.s2ver }}-VC.zip + 7z x sdl2.zip + echo "SDL2_DIR=$env:GITHUB_WORKSPACE/SDL2-${{ matrix.s2ver }}/cmake" >> $env:GITHUB_ENV + + - name: Configure + run: > + cmake -S . -B ./build -A ${{ matrix.arch }} + -DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake" + -DCMAKE_BUILD_TYPE=${{ matrix.build }} + -DGGML_BLAS=${{ matrix.blas }} + -DGGML_BLAS_VENDOR=OpenBLAS + -DBLAS_LIBRARIES="$env:GITHUB_WORKSPACE/OpenBLAS-${{matrix.blasver}}/lib/libopenblas.lib" + -DBLAS_INCLUDE_DIRS="$env:GITHUB_WORKSPACE/OpenBLAS-${{matrix.blasver}}/include" + -DWHISPER_SDL2=${{ matrix.sdl2 }} + -DGGML_NATIVE=OFF + -DWHISPER_BUILD_IS_DEV=${{ env.WHISPER_BUILD_IS_DEV }} + ${{ matrix.arch == 'x64' && '-DGGML_BACKEND_DL=ON -DGGML_CPU_ALL_VARIANTS=ON' || '-DGGML_BMI2=OFF' }} + + - name: Build + run: | + cd ./build + msbuild ALL_BUILD.vcxproj -t:build -p:configuration=${{ matrix.build }} -p:platform=${{ matrix.arch }} + + - name: Copy openblas.dll + if: matrix.blas == 'ON' + run: copy "$env:GITHUB_WORKSPACE/OpenBLAS-${{matrix.blasver}}/bin/libopenblas.dll" build/bin/${{ matrix.build }} + + - name: Copy SDL2.dll + if: matrix.sdl2 == 'ON' + run: copy "$env:SDL2_DIR/../lib/${{ matrix.s2arc }}/SDL2.dll" build/bin/${{ matrix.build }} + + - name: Pack bin artifacts + shell: pwsh + run: | + Compress-Archive -Path "build/bin/${{ matrix.build }}" -DestinationPath "whisper-blas-bin-${{ matrix.arch }}.zip" + + - name: Upload binaries + if: ${{ matrix.blas == 'ON' && matrix.sdl2 == 'ON' && needs.determine-tag.outputs.should_release == 'true' }} + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: whisper-blas-bin-${{ matrix.arch }}.zip + path: whisper-blas-bin-${{ matrix.arch }}.zip + + windows-cuda: + runs-on: windows-2022 + needs: determine-tag + strategy: + fail-fast: false + matrix: + build: [Release] + arch: [x64] + cublas: [ON] + sdl2: [ON] + cuda-toolkit: [12.4.0, 11.8.0] + include: + - arch: x64 + sdl2: ON + sdl2_ver: 2.28.5 + steps: + - name: Clone repository + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + + - name: Install Ninja + id: install_ninja + run: | + choco install ninja + + - name: Install ccache + uses: ggml-org/ccache-action@v1.2.21 + with: + key: ${{ github.job }}-${{ matrix.cuda-toolkit }}-${{ matrix.build }} + evict-old-files: 5d + + - name: Install Cuda Toolkit 11.8.0 + if: ${{ matrix.cuda-toolkit == '11.8.0' }} + run: | + $CUDA_VERSION = ${{ matrix.cuda-toolkit }} + $CUDA_TOOLKIT_DIR = "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v$CUDA_VERSION" + $CUDA_DOWNLOAD = "https://developer.download.nvidia.com/compute/cuda/redist" + + # Components versions + $CUDART_VER = "11.8.89" + $NVCC_VER = "11.8.89" + $NVRTC_VER = "11.8.89" + $CUBLAS_VER = "11.8.1.74" + $NVTX_VER = "11.8.86" + $VS_VER = "11.8.86" + $NVPROF_VER = "11.8.87" + $CCCL_VER = "11.8.89" + + # Create the directory where the CUDA Toolkit will be installed + mkdir -p $CUDA_TOOLKIT_DIR + + # Install unzip to extract the downloaded files + choco install unzip -y + + # Download all the required components + curl -O "$CUDA_DOWNLOAD/cuda_cudart/windows-x86_64/cuda_cudart-windows-x86_64-${CUDART_VER}-archive.zip" + curl -O "$CUDA_DOWNLOAD/cuda_nvcc/windows-x86_64/cuda_nvcc-windows-x86_64-${NVCC_VER}-archive.zip" + curl -O "$CUDA_DOWNLOAD/cuda_nvrtc/windows-x86_64/cuda_nvrtc-windows-x86_64-${NVRTC_VER}-archive.zip" + curl -O "$CUDA_DOWNLOAD/libcublas/windows-x86_64/libcublas-windows-x86_64-${CUBLAS_VER}-archive.zip" + curl -O "$CUDA_DOWNLOAD/cuda_nvtx/windows-x86_64/cuda_nvtx-windows-x86_64-${NVTX_VER}-archive.zip" + curl -O "$CUDA_DOWNLOAD/visual_studio_integration/windows-x86_64/visual_studio_integration-windows-x86_64-${VS_VER}-archive.zip" + curl -O "$CUDA_DOWNLOAD/cuda_nvprof/windows-x86_64/cuda_nvprof-windows-x86_64-${NVPROF_VER}-archive.zip" + curl -O "$CUDA_DOWNLOAD/cuda_cccl/windows-x86_64/cuda_cccl-windows-x86_64-${CCCL_VER}-archive.zip" + + # Extract all the downloaded files to the CUDA Toolkit directory + unzip '*.zip' -d $CUDA_TOOLKIT_DIR + + # Copy all the extracted files to the main CUDA Toolkit directory + xcopy "$CUDA_TOOLKIT_DIR\cuda_cudart-windows-x86_64-${CUDART_VER}-archive\*" "$CUDA_TOOLKIT_DIR" /E /I /H /Y + xcopy "$CUDA_TOOLKIT_DIR\cuda_nvcc-windows-x86_64-${NVCC_VER}-archive\*" "$CUDA_TOOLKIT_DIR" /E /I /H /Y + xcopy "$CUDA_TOOLKIT_DIR\cuda_nvrtc-windows-x86_64-${NVRTC_VER}-archive\*" "$CUDA_TOOLKIT_DIR" /E /I /H /Y + xcopy "$CUDA_TOOLKIT_DIR\libcublas-windows-x86_64-${CUBLAS_VER}-archive\*" "$CUDA_TOOLKIT_DIR" /E /I /H /Y + xcopy "$CUDA_TOOLKIT_DIR\cuda_nvtx-windows-x86_64-${NVTX_VER}-archive\*" "$CUDA_TOOLKIT_DIR" /E /I /H /Y + xcopy "$CUDA_TOOLKIT_DIR\cuda_nvprof-windows-x86_64-${NVPROF_VER}-archive\*" "$CUDA_TOOLKIT_DIR" /E /I /H /Y + xcopy "$CUDA_TOOLKIT_DIR\cuda_cccl-windows-x86_64-${CCCL_VER}-archive\*" "$CUDA_TOOLKIT_DIR" /E /I /H /Y + xcopy "$CUDA_TOOLKIT_DIR\visual_studio_integration-windows-x86_64-${VS_VER}-archive\*" "$CUDA_TOOLKIT_DIR" /E /I /H /Y + + # Visual Studio integration + xcopy "$CUDA_TOOLKIT_DIR\visual_studio_integration-windows-x86_64-${VS_VER}-archive\visual_studio_integration\MSBuildExtensions\*" "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Microsoft\VC\v170\BuildCustomizations" /E /I /H /Y + + # Set environment variables + echo "$CUDA_TOOLKIT_DIR\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + echo "$CUDA_TOOLKIT_DIR\libnvvp" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + echo "CUDA_PATH=$CUDA_TOOLKIT_DIR" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 + echo "CUDA_PATH_V11_8=$CUDA_TOOLKIT_DIR" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 + + - name: Install Cuda Toolkit 12.4.0 + if: ${{ matrix.cuda-toolkit == '12.4.0' }} + run: | + $CUDA_VERSION = ${{ matrix.cuda-toolkit }} + $CUDA_TOOLKIT_DIR = "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v$CUDA_VERSION" + $CUDA_DOWNLOAD = "https://developer.download.nvidia.com/compute/cuda/redist" + + # Components versions + $CUDART_VER = "12.4.127" + $NVCC_VER = "12.4.131" + $NVRTC_VER = "12.4.127" + $CUBLAS_VER = "12.4.5.8" + $NVTX_VER = "12.4.127" + $PROFILER_VER = "12.4.127" + $VS_VER = "12.4.127" + $NVPROF_VER = "12.4.128" + $CCCL_VER = "12.4.127" + + # Create the directory where the CUDA Toolkit will be installed + mkdir -p $CUDA_TOOLKIT_DIR + + # Install unzip to extract the downloaded files + choco install unzip -y + + # Download all the required components + curl -O "$CUDA_DOWNLOAD/cuda_cudart/windows-x86_64/cuda_cudart-windows-x86_64-${CUDART_VER}-archive.zip" + curl -O "$CUDA_DOWNLOAD/cuda_nvcc/windows-x86_64/cuda_nvcc-windows-x86_64-${NVCC_VER}-archive.zip" + curl -O "$CUDA_DOWNLOAD/cuda_nvrtc/windows-x86_64/cuda_nvrtc-windows-x86_64-${NVRTC_VER}-archive.zip" + curl -O "$CUDA_DOWNLOAD/libcublas/windows-x86_64/libcublas-windows-x86_64-${CUBLAS_VER}-archive.zip" + curl -O "$CUDA_DOWNLOAD/cuda_nvtx/windows-x86_64/cuda_nvtx-windows-x86_64-${NVTX_VER}-archive.zip" + curl -O "$CUDA_DOWNLOAD/cuda_profiler_api/windows-x86_64/cuda_profiler_api-windows-x86_64-${PROFILER_VER}-archive.zip" + curl -O "$CUDA_DOWNLOAD/visual_studio_integration/windows-x86_64/visual_studio_integration-windows-x86_64-${VS_VER}-archive.zip" + curl -O "$CUDA_DOWNLOAD/cuda_nvprof/windows-x86_64/cuda_nvprof-windows-x86_64-${NVPROF_VER}-archive.zip" + curl -O "$CUDA_DOWNLOAD/cuda_cccl/windows-x86_64/cuda_cccl-windows-x86_64-${CCCL_VER}-archive.zip" + + # Extract all the downloaded files to the CUDA Toolkit directory + unzip -q '*.zip' -d $CUDA_TOOLKIT_DIR + + # Copy all the extracted files to the main CUDA Toolkit directory + xcopy "$CUDA_TOOLKIT_DIR\cuda_cudart-windows-x86_64-${CUDART_VER}-archive\*" "$CUDA_TOOLKIT_DIR" /E /I /H /Y + xcopy "$CUDA_TOOLKIT_DIR\cuda_nvcc-windows-x86_64-${NVCC_VER}-archive\*" "$CUDA_TOOLKIT_DIR" /E /I /H /Y + xcopy "$CUDA_TOOLKIT_DIR\cuda_nvrtc-windows-x86_64-${NVRTC_VER}-archive\*" "$CUDA_TOOLKIT_DIR" /E /I /H /Y + xcopy "$CUDA_TOOLKIT_DIR\libcublas-windows-x86_64-${CUBLAS_VER}-archive\*" "$CUDA_TOOLKIT_DIR" /E /I /H /Y + xcopy "$CUDA_TOOLKIT_DIR\cuda_nvtx-windows-x86_64-${NVTX_VER}-archive\*" "$CUDA_TOOLKIT_DIR" /E /I /H /Y + xcopy "$CUDA_TOOLKIT_DIR\cuda_nvprof-windows-x86_64-${NVPROF_VER}-archive\*" "$CUDA_TOOLKIT_DIR" /E /I /H /Y + xcopy "$CUDA_TOOLKIT_DIR\cuda_cccl-windows-x86_64-${CCCL_VER}-archive\*" "$CUDA_TOOLKIT_DIR" /E /I /H /Y + xcopy "$CUDA_TOOLKIT_DIR\cuda_profiler_api-windows-x86_64-${PROFILER_VER}-archive\*" "$CUDA_TOOLKIT_DIR" /E /I /H /Y + xcopy "$CUDA_TOOLKIT_DIR\visual_studio_integration-windows-x86_64-${VS_VER}-archive\*" "$CUDA_TOOLKIT_DIR" /E /I /H /Y + + # Visual Studio integration + xcopy "$CUDA_TOOLKIT_DIR\visual_studio_integration-windows-x86_64-${VS_VER}-archive\visual_studio_integration\MSBuildExtensions\*" "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Microsoft\VC\v170\BuildCustomizations" /E /I /H /Y + + # Set environment variables + echo "$CUDA_TOOLKIT_DIR\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + echo "$CUDA_TOOLKIT_DIR\libnvvp" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + echo "CUDA_PATH=$CUDA_TOOLKIT_DIR" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 + echo "CUDA_PATH_V12_2=$CUDA_TOOLKIT_DIR" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 + + - name: Add msbuild to PATH + uses: microsoft/setup-msbuild@6fb02220983dee41ce7ae257b6f4d8f9bf5ed4ce # v2 + + - name: Install 7-Zip + run: choco install 7zip -y + + - name: Fetch SDL2 and set SDL2_DIR + if: matrix.sdl2 == 'ON' + run: | + Invoke-WebRequest -Uri https://github.com/libsdl-org/SDL/releases/download/release-${{ matrix.sdl2_ver }}/SDL2-devel-${{ matrix.sdl2_ver }}-VC.zip -OutFile sdl2.zip + 7z x sdl2.zip + echo "SDL2_DIR=${{ github.workspace }}\SDL2-${{ matrix.sdl2_ver }}\cmake" | Out-File -FilePath $env:GITHUB_ENV -Append + echo "${{ github.workspace }}\SDL2-${{ matrix.sdl2_ver }}\cmake" > SDL2_PATH.txt + + - name: Install cmake + run: choco install cmake + + - name: Build Project + shell: cmd + run: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" + cmake --version + where cmake + if "${{ matrix.cuda-toolkit }}" == "11.8.0" ( + set CUDA_FLAGS=-allow-unsupported-compiler -D_ALLOW_COMPILER_AND_STL_VERSION_MISMATCH -D_DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR + ) else ( + set CUDA_FLAGS= + ) + cmake -S . -B build -G "Ninja Multi-Config" ^ + -DCMAKE_BUILD_TYPE=${{ matrix.build }} ^ + -DGGML_CUDA=${{ matrix.cublas }} ^ + -DWHISPER_SDL2=${{ matrix.sdl2 }} ^ + -DSDL2_DIR="%SDL2_DIR%" ^ + -DCMAKE_POLICY_VERSION_MINIMUM=3.5 ^ + -DCMAKE_CUDA_FLAGS="%CUDA_FLAGS%" ^ + -DGGML_BACKEND_DL=ON ^ + -DGGML_NATIVE=OFF ^ + -DWHISPER_BUILD_IS_DEV=${{ env.WHISPER_BUILD_IS_DEV }} ^ + -DGGML_CPU_ALL_VARIANTS=ON + set /A NINJA_JOBS=%NUMBER_OF_PROCESSORS%-1 + cmake --build build --config ${{ matrix.build }} -j %NUMBER_OF_PROCESSORS% + + - name: Check ccache status after build + run: | + ccache --show-stats + + - name: Copy CUDA DLLs + run: | + Get-ChildItem "$env:CUDA_PATH\bin\" -Filter "*.dll" | + Copy-Item -Destination "build/bin/${{ matrix.build }}" + + - name: Copy SDL2.dll + if: matrix.sdl2 == 'ON' + run: copy "$env:SDL2_DIR/../lib/${{ matrix.arch }}/SDL2.dll" build/bin/${{ matrix.build }} + + - name: Pack bin artifacts + shell: pwsh + run: | + Compress-Archive -Path "build/bin/${{ matrix.build }}" -DestinationPath "whisper-bin-win-cuda-${{ matrix.cuda-toolkit }}-${{ matrix.arch }}.zip" + + - name: Upload binaries + if: ${{ needs.determine-tag.outputs.should_release == 'true' }} + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: whisper-bin-win-cuda-${{ matrix.cuda-toolkit }}-${{ matrix.arch }}.zip + path: whisper-bin-win-cuda-${{ matrix.cuda-toolkit }}-${{ matrix.arch }}.zip + + windows-arm64-cpu: + runs-on: windows-2022 + needs: determine-tag + + strategy: + matrix: + build: [Release] + + steps: + - name: Clone + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + + - name: Install Ninja + run: | + choco install ninja + + - name: ccache + uses: ggml-org/ccache-action@v1.2.21 + with: + key: release-windows-arm64-cpu + evict-old-files: 1d + + - name: Configure and Build + shell: cmd + run: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" amd64_arm64 + cmake -S . -B build -G "Ninja Multi-Config" ^ + -D CMAKE_TOOLCHAIN_FILE=cmake/arm64-windows-llvm.cmake ^ + -DBUILD_SHARED_LIBS=ON ^ + -DGGML_NATIVE=OFF ^ + -DGGML_BACKEND_DL=ON ^ + -DWHISPER_SDL2=OFF ^ + -DWHISPER_BUILD_IS_DEV=${{ env.WHISPER_BUILD_IS_DEV }} + cmake --build build --config ${{ matrix.build }} + + - name: Copy OpenMP runtime DLL + shell: pwsh + run: | + $vswhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" + $vsInstallPath = & $vswhere -latest -products '*' -requires Microsoft.VisualStudio.Component.VC.Tools.ARM64 -property installationPath + if (-not $vsInstallPath) { + Write-Error "Could not find a Visual Studio install with the ARM64 MSVC toolset" + exit 1 + } + $redistVersion = Get-ChildItem "$vsInstallPath\VC\Redist\MSVC" -Directory | + Where-Object { $_.Name -match '^\d+\.\d+\.\d+$' } | + Sort-Object Name -Descending | Select-Object -First 1 + $ompDll = "$vsInstallPath\VC\Redist\MSVC\$($redistVersion.Name)\debug_nonredist\arm64\Microsoft.VC143.OpenMP.LLVM\libomp140.aarch64.dll" + if (-not (Test-Path $ompDll)) { + Write-Error "libomp140.aarch64.dll not found at $ompDll" + exit 1 + } + Copy-Item $ompDll "build\bin\${{ matrix.build }}\" -Force + + - name: Pack bin artifacts + shell: pwsh + run: | + Compress-Archive -Path "build/bin/${{ matrix.build }}" -DestinationPath "whisper-bin-win-cpu-arm64.zip" + + - name: Upload binaries + if: ${{ needs.determine-tag.outputs.should_release == 'true' }} + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: whisper-bin-win-cpu-arm64.zip + path: whisper-bin-win-cpu-arm64.zip + + windows-arm64-opencl-adreno: + runs-on: windows-2022 + needs: determine-tag + + strategy: + matrix: + build: [Release] + + steps: + - name: Clone + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + + - name: Install Ninja + run: | + choco install ninja + + - name: Install OpenCL Headers and Libs + run: | + git clone https://github.com/KhronosGroup/OpenCL-Headers + cd OpenCL-Headers + cmake -B build ` + -DBUILD_TESTING=OFF ` + -DOPENCL_HEADERS_BUILD_TESTING=OFF ` + -DOPENCL_HEADERS_BUILD_CXX_TESTS=OFF ` + -DCMAKE_INSTALL_PREFIX="$env:RUNNER_TEMP/opencl-arm64-release" + cmake --build build --target install + cd .. + git clone https://github.com/KhronosGroup/OpenCL-ICD-Loader + cd OpenCL-ICD-Loader + cmake -B build-arm64-release ` + -A arm64 ` + -DCMAKE_PREFIX_PATH="$env:RUNNER_TEMP/opencl-arm64-release" ` + -DCMAKE_INSTALL_PREFIX="$env:RUNNER_TEMP/opencl-arm64-release" + cmake --build build-arm64-release --target install --config release + + - name: ccache + uses: ggml-org/ccache-action@v1.2.21 + with: + key: release-windows-arm64-opencl-adreno + evict-old-files: 1d + + - name: Configure and Build + shell: cmd + run: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" amd64_arm64 + cmake -S . -B build -G "Ninja Multi-Config" ^ + -D CMAKE_TOOLCHAIN_FILE=cmake/arm64-windows-llvm.cmake ^ + -DCMAKE_PREFIX_PATH="%RUNNER_TEMP%/opencl-arm64-release" ^ + -DBUILD_SHARED_LIBS=ON ^ + -DGGML_NATIVE=OFF ^ + -DGGML_BACKEND_DL=ON ^ + -DGGML_OPENCL=ON ^ + -DGGML_OPENCL_USE_ADRENO_KERNELS=ON ^ + -DWHISPER_SDL2=OFF ^ + -DWHISPER_BUILD_IS_DEV=${{ env.WHISPER_BUILD_IS_DEV }} + cmake --build build --config ${{ matrix.build }} + + - name: Copy OpenMP runtime DLL + shell: pwsh + run: | + $vswhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" + $vsInstallPath = & $vswhere -latest -products '*' -requires Microsoft.VisualStudio.Component.VC.Tools.ARM64 -property installationPath + if (-not $vsInstallPath) { + Write-Error "Could not find a Visual Studio install with the ARM64 MSVC toolset" + exit 1 + } + $redistVersion = Get-ChildItem "$vsInstallPath\VC\Redist\MSVC" -Directory | + Where-Object { $_.Name -match '^\d+\.\d+\.\d+$' } | + Sort-Object Name -Descending | Select-Object -First 1 + $ompDll = "$vsInstallPath\VC\Redist\MSVC\$($redistVersion.Name)\debug_nonredist\arm64\Microsoft.VC143.OpenMP.LLVM\libomp140.aarch64.dll" + if (-not (Test-Path $ompDll)) { + Write-Error "libomp140.aarch64.dll not found at $ompDll" + exit 1 + } + Copy-Item $ompDll "build\bin\${{ matrix.build }}\" -Force + + - name: Pack bin artifacts + shell: pwsh + run: | + Compress-Archive -Path "build/bin/${{ matrix.build }}" -DestinationPath "whisper-bin-win-opencl-adreno-arm64.zip" + + - name: Upload binaries + if: ${{ needs.determine-tag.outputs.should_release == 'true' }} + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: whisper-bin-win-opencl-adreno-arm64.zip + path: whisper-bin-win-opencl-adreno-arm64.zip + + windows-arm64-cuda: + runs-on: windows-2022 + needs: determine-tag + + strategy: + matrix: + build: [Release] + cuda-toolkit: ['13.4'] + + steps: + - name: Clone repository + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + + - name: Install Ninja + run: | + choco install ninja + + - name: Install ccache + uses: ggml-org/ccache-action@v1.2.21 + with: + key: ${{ github.job }}-${{ matrix.cuda-toolkit }}-${{ matrix.build }} + evict-old-files: 5d + + # nvcc cross-compiles for ARM64 from this x64 runner using the ARM64-targeting + # host cl.exe; the CUDA runtime/cublas libs still need their own ARM64 archives + # since the standard x64 CUDA packages don't ship ARM64 binaries. + - name: Install Cuda Toolkit 13.4 (ARM64 target) + run: | + $CUDA_TOOLKIT_DIR = "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v13.4" + $CUDA_DOWNLOAD = "https://developer.download.nvidia.com/compute/cuda/redist" + + # Components versions + $CCCL_VER = "13.3.4.2.1" + $CRT_VER = "13.4.59" + $NVCC_VER = "13.4.59" + $NVVM_VER = "13.4.59" + $CUDART_VER = "13.4.49" + $CUBLAS_VER = "13.7.0.27" + + mkdir -p $CUDA_TOOLKIT_DIR + choco install unzip -y + + curl -O "$CUDA_DOWNLOAD/cccl/windows-x86_64/cccl-windows-x86_64-${CCCL_VER}-archive.zip" + curl -O "$CUDA_DOWNLOAD/cuda_crt/windows-x86_64/cuda_crt-windows-x86_64-${CRT_VER}-archive.zip" + curl -O "$CUDA_DOWNLOAD/cuda_nvcc/windows-x86_64/cuda_nvcc-windows-x86_64-${NVCC_VER}-archive.zip" + curl -O "$CUDA_DOWNLOAD/libnvvm/windows-x86_64/libnvvm-windows-x86_64-${NVVM_VER}-archive.zip" + curl -O "$CUDA_DOWNLOAD/cuda_cudart/windows-arm64/cuda_cudart-windows-arm64-${CUDART_VER}-archive.zip" + curl -O "$CUDA_DOWNLOAD/libcublas/windows-arm64/libcublas-windows-arm64-${CUBLAS_VER}-archive.zip" + + unzip '*.zip' -d $CUDA_TOOLKIT_DIR + + xcopy "$CUDA_TOOLKIT_DIR\cccl-windows-x86_64-${CCCL_VER}-archive\*" "$CUDA_TOOLKIT_DIR" /E /I /H /Y + xcopy "$CUDA_TOOLKIT_DIR\cuda_crt-windows-x86_64-${CRT_VER}-archive\*" "$CUDA_TOOLKIT_DIR" /E /I /H /Y + xcopy "$CUDA_TOOLKIT_DIR\cuda_nvcc-windows-x86_64-${NVCC_VER}-archive\*" "$CUDA_TOOLKIT_DIR" /E /I /H /Y + xcopy "$CUDA_TOOLKIT_DIR\libnvvm-windows-x86_64-${NVVM_VER}-archive\*" "$CUDA_TOOLKIT_DIR" /E /I /H /Y + xcopy "$CUDA_TOOLKIT_DIR\cuda_cudart-windows-arm64-${CUDART_VER}-archive\*" "$CUDA_TOOLKIT_DIR" /E /I /H /Y + xcopy "$CUDA_TOOLKIT_DIR\libcublas-windows-arm64-${CUBLAS_VER}-archive\*" "$CUDA_TOOLKIT_DIR" /E /I /H /Y + + echo "$CUDA_TOOLKIT_DIR\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + echo "CUDA_PATH=$CUDA_TOOLKIT_DIR" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 + + - name: Configure and Build + shell: cmd + run: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" amd64_arm64 + cmake -S . -B build -G "Ninja Multi-Config" ^ + -D CMAKE_TOOLCHAIN_FILE=cmake/arm64-windows-llvm-cuda.cmake ^ + -DCMAKE_BUILD_TYPE=${{ matrix.build }} ^ + -DGGML_CUDA=ON ^ + -DCMAKE_POLICY_VERSION_MINIMUM=3.5 ^ + -DGGML_BACKEND_DL=ON ^ + -DGGML_NATIVE=OFF ^ + -DWHISPER_SDL2=OFF ^ + -DWHISPER_BUILD_IS_DEV=${{ env.WHISPER_BUILD_IS_DEV }} + cmake --build build --config ${{ matrix.build }} + + - name: Copy CUDA runtime DLLs + run: | + Get-ChildItem "$env:CUDA_PATH\bin\arm64" -Filter "cudart64_*.dll" | Copy-Item -Destination "build/bin/${{ matrix.build }}" + Get-ChildItem "$env:CUDA_PATH\bin\arm64" -Filter "cublas64_*.dll" | Copy-Item -Destination "build/bin/${{ matrix.build }}" + Get-ChildItem "$env:CUDA_PATH\bin\arm64" -Filter "cublasLt64_*.dll" | Copy-Item -Destination "build/bin/${{ matrix.build }}" + + - name: Copy OpenMP runtime DLL + shell: pwsh + run: | + $vswhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" + $vsInstallPath = & $vswhere -latest -products '*' -requires Microsoft.VisualStudio.Component.VC.Tools.ARM64 -property installationPath + if (-not $vsInstallPath) { + Write-Error "Could not find a Visual Studio install with the ARM64 MSVC toolset" + exit 1 + } + $redistVersion = Get-ChildItem "$vsInstallPath\VC\Redist\MSVC" -Directory | + Where-Object { $_.Name -match '^\d+\.\d+\.\d+$' } | + Sort-Object Name -Descending | Select-Object -First 1 + $ompDll = "$vsInstallPath\VC\Redist\MSVC\$($redistVersion.Name)\debug_nonredist\arm64\Microsoft.VC143.OpenMP.LLVM\libomp140.aarch64.dll" + if (-not (Test-Path $ompDll)) { + Write-Error "libomp140.aarch64.dll not found at $ompDll" + exit 1 + } + Copy-Item $ompDll "build\bin\${{ matrix.build }}\" -Force + + - name: Pack bin artifacts + shell: pwsh + run: | + Compress-Archive -Path "build/bin/${{ matrix.build }}" -DestinationPath "whisper-bin-win-cuda-${{ matrix.cuda-toolkit }}-arm64.zip" + + - name: Upload binaries + if: ${{ needs.determine-tag.outputs.should_release == 'true' }} + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + name: whisper-bin-win-cuda-${{ matrix.cuda-toolkit }}-arm64.zip + path: whisper-bin-win-cuda-${{ matrix.cuda-toolkit }}-arm64.zip + + ios-xcode-build: + runs-on: macos-latest + needs: determine-tag + + strategy: + matrix: + build: [Release] + + steps: + - name: Checkout code + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + + - name: Configure + run: | + cp models/for-tests-ggml-base.en.bin models/ggml-base.en.bin + mkdir models/ggml-base.en-encoder.mlmodelc + + - name: Build + id: cmake_build + run: | + sysctl -a + mkdir build + cd build + cmake -G Xcode .. \ + -DGGML_METAL_USE_BF16=ON \ + -DGGML_METAL_EMBED_LIBRARY=ON \ + -DWHISPER_BUILD_IS_DEV=${{ env.WHISPER_BUILD_IS_DEV }} \ + -DWHISPER_BUILD_EXAMPLES=OFF \ + -DWHISPER_BUILD_TESTS=OFF \ + -DWHISPER_BUILD_SERVER=OFF \ + -DCMAKE_SYSTEM_NAME=iOS \ + -DCMAKE_OSX_DEPLOYMENT_TARGET=14.0 \ + -DCMAKE_XCODE_ATTRIBUTE_DEVELOPMENT_TEAM=ggml + cmake --build . --config Release -j $(sysctl -n hw.logicalcpu) -- CODE_SIGNING_ALLOWED=NO + + - name: xcodebuild for swift package + id: xcodebuild + run: | + ./build-xcframework.sh + + - name: Build objc example + run: xcodebuild -project examples/whisper.objc/whisper.objc.xcodeproj -scheme whisper.objc -configuration ${{ matrix.build }} -sdk iphoneos CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO FRAMEWORK_FOLDER_PATH=./build-ios build + + - name: Build swiftui example + run: xcodebuild -project examples/whisper.swiftui/whisper.swiftui.xcodeproj -scheme WhisperCppDemo -configuration ${{ matrix.build }} -sdk iphoneos CODE_SIGNING_REQUIRED=NO CODE_SIGN_IDENTITY= -destination 'generic/platform=iOS' FRAMEWORK_FOLDER_PATH=./build-ios build + + - name: Pack artifacts + id: pack_artifacts + run: | + zip --symlinks -r whisper-${{ needs.determine-tag.outputs.tag_name }}-xcframework.zip build-apple/whisper.xcframework + + - name: Upload artifacts + if: ${{ needs.determine-tag.outputs.should_release == 'true' }} + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 + with: + path: whisper-${{ needs.determine-tag.outputs.tag_name }}-xcframework.zip + name: whisper-${{ needs.determine-tag.outputs.tag_name }}-xcframework.zip + + release: + if: ${{ github.event.inputs.create_release == 'true' || github.event.inputs.pre_release_tag != '' }} + + runs-on: ubuntu-latest + + needs: + - determine-tag + - ubuntu-cpu + - ios-xcode-build + - windows + - windows-blas + - windows-cuda + - windows-arm64-cpu + - windows-arm64-opencl-adreno + - windows-arm64-cuda + + steps: + - name: Clone + id: checkout + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + with: + fetch-depth: 0 + ssh-key: ${{ secrets.DEPLOY_KEY_RELEASE }} + + # Downloads all the artifacts from the previous jobs + - name: Download artifacts + id: download-artifact + uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7 + with: + path: ./artifact + merge-multiple: true + + - name: Move artifacts + id: move_artifacts + run: | + mkdir -p ./release + mv -v ./artifact/*.zip ./release 2>/dev/null || true + mv -v ./artifact/*.tar.gz ./release 2>/dev/null || true + + - name: Attest release artifacts + uses: actions/attest@1e69f48acb82d1966a394da916b4c1698aa569d6 # v4 + with: + subject-path: 'release/*' + + - name: Create and push git tag + run: | + TAG="${{ needs.determine-tag.outputs.tag_name }}" + if git rev-parse -q --verify "refs/tags/${TAG}" >/dev/null 2>&1; then + echo "Tag ${TAG} already exists, skipping creation" + else + git tag "${TAG}" + git push origin "${TAG}" + fi + + - name: Create release + id: create_release + uses: ggml-org/action-create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ needs.determine-tag.outputs.tag_name }} + prerelease: true + + - name: Upload release + id: upload_release + uses: actions/github-script@ffc2c79a5b2490bd33e0a41c1de74b877714d736 # v3 + with: + github-token: ${{secrets.GITHUB_TOKEN}} + script: | + const path = require('path'); + const fs = require('fs'); + const release_id = '${{ steps.create_release.outputs.id }}'; + for (let file of await fs.readdirSync('./release')) { + if (path.extname(file) === '.zip' || file.endsWith('.tar.gz')) { + console.log('uploadReleaseAsset', file); + await github.repos.uploadReleaseAsset({ + owner: context.repo.owner, + repo: context.repo.repo, + release_id: release_id, + name: file, + data: await fs.readFileSync(`./release/${file}`) + }); + } + } diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7a98228 --- /dev/null +++ b/.gitignore @@ -0,0 +1,70 @@ +*.o +*.a +*.d +.cache/ +.coreml/ +.test/ +.venv/ +.vs/ +.vscode/ +.DS_Store +.vimspector.json +/CMakeSettings.json +/CMakeUserPresets.json +/talk-llama.dSYM/ + +build/ +build-*/ +build_*/ +tmp/ + +# SPM +.build/ +.swiftpm +*.metallib + +ggml-metal-embed.metal +ggml-metal-embed.metal.tmp + +/main +/stream +/command +/talk +/talk-llama +/bench +/quantize +/server +/lsp + +arm_neon.h +sync.sh +libwhisper.a +libwhisper.so +compile_commands.json + +examples/arm_neon.h +examples/whisper.objc/whisper.objc.xcodeproj/xcshareddata +examples/whisper.objc/whisper.objc.xcodeproj/xcuserdata/ +examples/whisper.objc/whisper.objc.xcodeproj/project.xcworkspace/xcuserdata + +extra/bench-gg.txt + +models/*.mlmodel +models/*.mlmodelc +models/*.mlpackage +models/*-encoder-openvino.xml +models/*-encoder-openvino-cache/ +bindings/java/.gradle/ +bindings/java/.idea/ +.idea/ + +benchmark_results.csv +cmake-build-debug/ +.cxx/ +.gradle/ +local.properties +.log +.exe + +# AGENTS +.pi/SYSTEM.md diff --git a/.pi/gg/SYSTEM.md b/.pi/gg/SYSTEM.md new file mode 100644 index 0000000..4788308 --- /dev/null +++ b/.pi/gg/SYSTEM.md @@ -0,0 +1,30 @@ +You are a coding agent. Here are some very important rules that you must follow: + +General: +- Be very precise and concise when writing code, comments, explanations, etc. +- If an inline comment exceeds 2 lines, replace it with: `// note: TODO LATER` +- PR and commit titles format: ` : `. Lookup recents for examples +- Don't try to build or run the code unless you are explicitly asked to do so +- Use the `gh` CLI tool when querying PRs, issues, or other GitHub resources + +Coding: +- When in doubt, always refer to the CONTRIBUTING.md file of the project +- In `test-backend-ops.cpp`, do not mention specific backends (e.g. Metal, CUDA) in comments +- When referencing issues or PRs in comments, use the format: + - C/C++ code: `// ref: <url>` + - Other (CMake, etc.): `# ref: <url>` + +Pull requests (PRs): +- New branch names are prefixed with "gg/" +- Before opening a pull request, ask the user to confirm the description +- Don't explicitly wrap lines in the PR description (each paragraph and bullet is a single line) +- When creating a pull request, look for the repository's PR template and follow it +- For the AI usage disclosure section, write "YES. pi:llama.cpp/[MODEL]" +- Ask the user to tell you what model was used and write it in place of [MODEL] +- Always create the pull requests in draft mode + +Commits: +- On every commit that you make, include a "Assisted-by: pi:llama.cpp/[MODEL]" tag +- Do not explicitly set the git author in commits - rely on the default git config +- Always use `--no-gpg-sign` when committing +- Never `git push` without explicit confirmation from the user diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..f34f324 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,102 @@ +# Instructions for whisper.cpp + +> [!IMPORTANT] +> This project does **not** accept pull requests that are fully or predominantly AI-generated. AI tools may be utilized solely in an assistive capacity. +> +> Read more: [CONTRIBUTING.md](CONTRIBUTING.md) + +AI assistance is permissible only when the majority of the code is authored by a human contributor, with AI employed exclusively for corrections or to expand on verbose modifications that the contributor has already conceptualized (see examples below). + +--- + +## Guidelines for Contributors Using AI + +whisper.cpp is built by humans, for humans. Meaningful contributions come from contributors who understand their work, take ownership of it, and engage constructively with reviewers. + +Maintainers receive numerous pull requests weekly, many of which are AI-generated submissions where the author cannot adequately explain the code, debug issues, or participate in substantive design discussions. Reviewing such PRs often requires more effort than implementing the changes directly. + +**A pull request represents a long-term commitment.** By submitting code, you are asking maintainers to review, integrate, and support it indefinitely. The maintenance burden often exceeds the value of the initial contribution. + +Most maintainers already have access to AI tools. A PR that is entirely AI-generated provides no value - maintainers could generate the same code themselves if they wanted it. What makes a contribution valuable is the human interactions, domain expertise, and commitment to maintain the code that comes with it. + +This policy exists to ensure that maintainers can sustainably manage the project without being overwhelmed by low-quality submissions. + +--- + +## Guidelines for Contributors + +Contributors are expected to: + +1. **Demonstrate full understanding of their code.** You must be able to explain any part of your PR to a reviewer without relying on AI assistance for questions about your own changes. + +2. **Take responsibility for maintenance.** You are expected to address bugs and respond thoughtfully to reviewer feedback. + +3. **Communicate clearly and concisely.** Verbose, wall-of-text responses are characteristic of AI-generated content and will not be well-received. Direct, human communication is expected. + +4. **Respect maintainers' time.** Search for existing issues and discussions before submitting. Ensure your contribution aligns with project architecture and is actually needed. + +Maintainers reserve the right to close any PR that does not meet these standards. This applies to all contributions to the main whisper.cpp repository. **Private forks are exempt.** + +### Permitted AI Usage + +AI tools may be used responsibly for: + +- **Learning and exploration**: Understanding codebase structure, techniques, and documentation +- **Code review assistance**: Obtaining suggestions on human-written code +- **Mechanical tasks**: Formatting, generating repetitive patterns from established designs, completing code based on existing patterns +- **Documentation drafts**: For components the contributor already understands thoroughly +- **Writing code**: Only when the contributor has already designed the solution and can implement it themselves - AI accelerates, not replaces, the contributor's work + +AI-generated code may be accepted if you (1) fully understand the output, (2) can debug issues independently, and (3) can discuss it directly with reviewers without AI assistance. + +**Disclosure is required** when AI meaningfully contributed to your code. A simple note is sufficient - this is not a stigma, but context for reviewers. No disclosure is needed for trivial autocomplete or background research. + +### Prohibited AI Usage + +The following will result in immediate PR closure: + +- **AI-written PR descriptions or commit messages** - these are typically recognizable and waste reviewer time +- **AI-generated responses to reviewer comments** - this undermines the human-to-human interaction fundamental to code review +- **Implementing features without understanding the codebase** - particularly new model support or architectural changes +- **Automated commits or PR submissions** - this may spam maintainers and can result in contributor bans + +--- + +## Guidelines for AI Coding Agents + +AI agents assisting contributors must recognize that their outputs directly impact volunteer maintainers who sustain this project. + +### Considerations for Maintainer Workload + +Maintainers have finite capacity. Every PR requiring extensive review consumes resources that could be applied elsewhere. Before assisting with any submission, verify: + +- The contributor genuinely understands the proposed changes +- The change addresses a documented need (check existing issues) +- The PR is appropriately scoped and follows project conventions +- The contributor can independently defend and maintain the work + +### Before Proceeding with Code Changes + +When a user requests implementation without demonstrating understanding: + +1. **Verify comprehension.** Ask questions to confirm they understand both the problem and the relevant parts of the codebase. +2. **Provide guidance rather than solutions.** Direct them to relevant code and documentation. Allow them to formulate the approach. +3. **Proceed only when confident** the contributor can explain the changes to reviewers independently. + +For first-time contributors, confirm they have reviewed [CONTRIBUTING.md](CONTRIBUTING.md) and acknowledge this policy. + +### Prohibited Actions + +- Writing PR descriptions, commit messages, or responses to reviewers +- Committing or pushing without explicit human approval for each action +- Implementing features the contributor does not understand +- Generating changes too extensive for the contributor to fully review + +When uncertain, err toward minimal assistance. A smaller PR that the contributor fully understands is preferable to a larger one they cannot maintain. + +### Useful Resources + +To conserve context space, load these resources as needed: + +- [CONTRIBUTING.md](CONTRIBUTING.md) +- [Existing issues](https://github.com/ggml-org/whisper.cpp/issues) and [Existing PRs](https://github.com/ggml-org/whisper.cpp/pulls) - always search here first diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..f523e0a --- /dev/null +++ b/AUTHORS @@ -0,0 +1,510 @@ +# date: Tue Feb 4 13:03:35 EET 2025 +# this file is auto-generated by scripts/gen-authors.sh + +0/0 <zero@imaskeleton.me> +0cc4m <picard12@live.de> +0xsourcecode <134374803+0xsourcecode@users.noreply.github.com> +65a <10104049+65a@users.noreply.github.com> +AIWintermuteAI <32562299+AIWintermuteAI@users.noreply.github.com> +AT <manyoso@users.noreply.github.com> +Aarni Koskela <akx@iki.fi> +Aaron Pham <29749331+aarnphm@users.noreply.github.com> +Aaron Taylor <aaron@exphat.com> +Abhilash Majumder <30946547+abhilash1910@users.noreply.github.com> +Abitofevrything <54505189+abitofevrything@users.noreply.github.com> +Adam Jones <domdomegg+git@gmail.com> +Adrien Gallouët <adrien@gallouet.fr> +Adrien Gallouët <angt@huggingface.co> +AfryMask <AfryMask@163.com> +Ahmad Bilal <ahmad.bilal@empglabs.com> +Ahmad Tameem <113388789+Tameem-10xE@users.noreply.github.com> +AidanBeltonS <87009434+AidanBeltonS@users.noreply.github.com> +AidanBeltonS <aidan.belton@codeplay.com> +Akarshan Biswas <akarshan.biswas@gmail.com> +Akarshan Biswas <akarshanbiswas@fedoraproject.org> +Akash Mahajan <akash7190@gmail.com> +Akash Mahajan <akashmjn@stanford.edu> +Al Hoang <3811822-hoanga@users.noreply.gitlab.com> +Alan <unknown> +Albert Jin <albert.jin@gmail.com> +Alberto Cabrera Pérez <alberto.cabrera@codeplay.com> +Alberto Cabrera Pérez <alberto.cabrera@intel.com> +Aleksander Andrzejewski <18704749+aleksanderandrzejewski@users.noreply.github.com> +Alex Azarov <alex@azarov.by> +Alex Bacart <13940752+alex-bacart@users.noreply.github.com> +Alex Evgrashin <aevgrashin@yandex.ru> +Alex O'Connell <35843486+acon96@users.noreply.github.com> +Alexandr Graschenkov <alexandr.graschenkov91@gmail.com> +Alexandru Mariuti <alex@mariuti.com> +Alexey Kharlamov <alexey@kharlamov.biz> +Alfredo Montesinos <alfredo.montesinos@g.austincc.edu> +Ali Alameh <ali.alameh@isae.edu.lb> +Alter <0x7c48@gmail.com> +Ananta Bastola <anantarajbastola@gmail.com> +Andreas Kieslinger <47689530+aendk@users.noreply.github.com> +Andreas Lubbe <git@lubbe.org> +Andreu Huguet <andreuhuguet@gmail.com> +Andrew Huynh <a5thuynh@gmail.com> +Andrew Minh Nguyen <40281306+amqdn@users.noreply.github.com> +Andrew S <andrews54757@gmail.com> +Andy Maloney <asmaloney@gmail.com> +Anton Kostin <masguit42@users.noreply.github.com> +Artyom Mezin <psycho.fading@gmail.com> +Asad Memon <asad.lionpk@gmail.com> +Ashraful Islam <ashraful.meche@gmail.com> +AsukaMinato <asukaminato@nyan.eu.org> +AustinMroz <austinmroz@utexas.edu> +Avik Sengupta <avik@sengupta.net> +Bader-eddine Ouaich <49657842+baderouaich@users.noreply.github.com> +Baffin Lee <baffinlee@gmail.com> +Ben Ashbaugh <ben.ashbaugh@intel.com> +Ben Nortier <bjnortier@gmail.com> +Benjamin Heiniger <benjamin.heiniger@bluewin.ch> +Bernhard M. Wiedemann <githubbmwprimary@lsmod.de> +Binozo <70137898+Binozo@users.noreply.github.com> +Bo-Yi Wu <appleboy.tw@gmail.com> +Boris Bliznioukov <blib@mail.com> +Borislav Stanimirov <b.stanimirov@abv.bg> +Brad Murray <59848399+bradmurray-dt@users.noreply.github.com> +Brian Murray <brian@bmurray.ca> +CRD716 <crd716@gmail.com> +Canis Lupus <Canis-UK@users.noreply.github.com> +Carlos Zoido <mrgalleta@gmail.com> +Carolinabanana <140120812+Carolinabanana@users.noreply.github.com> +CarterLi999 <664681047@qq.com> +ChangSeok Oh <shivamidow@users.noreply.github.com> +Changyeon Kim <cyzero.kim@samsung.com> +Chaoqun <27287694+OpenWaygate@users.noreply.github.com> +Charles Xu <63788048+chaxu01@users.noreply.github.com> +Charles Xu <charles.xu@arm.com> +Chen Xi <xi2.chen@intel.com> +Chen Xi <xixichen08@foxmail.com> +Chenguang Li <87689256+noemotiovon@users.noreply.github.com> +Chia-Hsiang Cheng <88014292+garychia@users.noreply.github.com> +Chidi Williams <williamschidi1@gmail.com> +Chris Elrod <elrodc@gmail.com> +Christian <12550267+iceychris@users.noreply.github.com> +Christian Kastner <ckk@kvr.at> +Clifford Heath <clifford.heath@gmail.com> +Clint Herron <hanclinto@gmail.com> +Colin <github@whoisc.cc> +Conrad Kramer <conrad@conradkramer.com> +Corey Earwood <iamcgn+github@gmail.com> +CrispStrobe <154636388+CrispStrobe@users.noreply.github.com> +DAN™ <dranger003@gmail.com> +DGdev91 <DGdev91@users.noreply.github.com> +Damian Czaja <trojan295@protonmail.com> +Dan Johansson <164997844+eddnjjn@users.noreply.github.com> +Dan Johansson <dan.johansson@arm.com> +Daniel Bevenius <daniel.bevenius@gmail.com> +Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com> +Daniel Ziegenberg <daniel@ziegenberg.at> +Daniele <57776841+daniandtheweb@users.noreply.github.com> +Dave <dave-fl@users.noreply.github.com> +Dave Airlie <airlied@gmail.com> +Dave Airlie <airlied@redhat.com> +Daven Sanassy <daven@vochlea.co.uk> +David <dnhkng@gmail.com> +David Thorpe <djt@mutablelogic.com> +DavidKorczynski <david@adalogics.com> +Davidson Francis <davidsondfgl@gmail.com> +Dener Stassun <denerstassun@gmail.com> +Dibakar Gope <dibakar.gope@arm.com> +Didzis Gosko <didzis@users.noreply.github.com> +Diego Devesa <slarengh@gmail.com> +Digipom <admin@digipom.com> +Dimo <dimo@ieee.org> +Djip007 <3705339+Djip007@users.noreply.github.com> +Djip007 <djip.perois@free.fr> +Dody Suria Wijaya <dodysw@gmail.com> +Dou Xinpeng <15529241576@163.com> +Dou Xinpeng <81913537+Dou-Git@users.noreply.github.com> +Dr. Tom Murphy VII Ph.D <499244+tom7@users.noreply.github.com> +Duncan McConnell <ddmcconnell4@gmail.com> +Egor Egorov <me@egorfine.com> +Elkana Bardugo <ttv200@gmail.com> +Emmanuel Schmidbauer <eschmidbauer@gmail.com> +Engininja2 <139037756+Engininja2@users.noreply.github.com> +Eric Curtin <ericcurtin17@gmail.com> +Eric Swanson <eswanson@alloscomp.com> +Eric Tendian <erictendian@gmail.com> +Eric Zhang <34133756+EZForever@users.noreply.github.com> +Erik Scholz <Green-Sky@users.noreply.github.com> +Evan Jones <evan.q.jones@gmail.com> +Evan Martin <evan.martin@gmail.com> +Eve <139727413+netrunnereve@users.noreply.github.com> +Evgeny Kuznetsov <evgeny@kuznetsov.md> +F1L1P <78918286+F1L1Pv2@users.noreply.github.com> +Faisal Zaghloul <quic_fzaghlou@quicinc.com> +Fangjun Kuang <csukuangfj@gmail.com> +Felix <stenbackfelix@gmail.com> +Finn Voorhees <finnvoorhees@gmail.com> +FirstTimeEZ <179362031+FirstTimeEZ@users.noreply.github.com> +FlippFuzz <41221030+FlippFuzz@users.noreply.github.com> +Frankie Robertson <frankier@users.noreply.github.com> +Gang Chen <goncha@gmail.com> +Gavin Cai <gavin1818@hotmail.com> +George Hindle <george@georgehindle.com> +Georgi Gerganov <ggerganov@gmail.com> +Gilad S <7817232+giladgd@users.noreply.github.com> +Gilad S <giladgd@users.noreply.github.com> +Gilad S. <7817232+giladgd@users.noreply.github.com> +GitAritron <103900385+GitAritron@users.noreply.github.com> +GiviMAD <GiviMAD@users.noreply.github.com> +Gleicon Moraes <gleicon@gmail.com> +Gregor Jasny <gjasny@googlemail.com> +Guillaume Wenzek <gwenzek@users.noreply.github.com> +HY. Kelvin Lee <34256578+hykelvinlee42@users.noreply.github.com> +Halalaluyafail3 <55773281+Halalaluyafail3@users.noreply.github.com> +Hang <bebound@gmail.com> +Haus1 <haus.xda@gmail.com> +Herman Semenov <GermanAizek@yandex.ru> +HimariO <dsfhe49854@gmail.com> +Hong Bo PENG <penghb@cn.ibm.com> +Hrishikesh Barman <geekodour@users.noreply.github.com> +Hugo <hugo@whynothugo.nl> +Ian Bicking <ian@ianbicking.org> +Ian Bull <irbull@eclipsesource.com> +Ihar Hrachyshka <ihrachys@redhat.com> +Ikko Ashimine <eltociear@gmail.com> +Ikko Eltociear Ashimine <eltociear@gmail.com> +InconsolableCellist <23345188+InconsolableCellist@users.noreply.github.com> +Ismatulla Mansurov <47342870+sapoepsilon@users.noreply.github.com> +Ivan <nekotekina@gmail.com> +Ivan Filipov <159561759+vanaka11@users.noreply.github.com> +Ivan Gorin <ivangorin21@gmail.com> +Ivo von Putzer Reibegg <ivo.putzer@gmail.com> +JJ <103335846+computerscienceiscool@users.noreply.github.com> +Jack Mousseau <jmousseau@users.noreply.github.com> +JacobLinCool <jacoblincool@gmail.com> +Jakub Ráček <blizzcz@gmail.com> +Jared Van Bortel <jared@nomic.ai> +Jay Binks <jaybinks@gmail.com> +Jayant <jayantyadav202@gmail.com> +Jeff Bolz <jbolz@nvidia.com> +Jeroen Mostert <jeroen.mostert@cm.com> +Jhen-Jie Hong <developer@jhen.me> +Jhen-Jie Hong <iainst0409@gmail.com> +JidongZhang-THU <1119708529@qq.com> +Jo Liss <joliss42@gmail.com> +Joe Todd <joe.todd@codeplay.com> +Johan <jr.raffin@gmail.com> +Johannes Gäßler <johannesg@5d6.de> +John Balis <phobossystems@gmail.com> +JohnnyB <jboero@users.noreply.github.com> +Jonathan Soo <jcsoo@agora.com> +Jonno <1160532+razodactyl@users.noreply.github.com> +Joonas Pihlajamaa <joonas.pihlajamaa@iki.fi> +Jose <34888496+Jerry-Master@users.noreply.github.com> +Josh Bleecher Snyder <josharian@gmail.com> +Josscii <jossciiweiyi@gmail.com> +Judd <foldl@users.noreply.github.com> +Jumper775 <78500318+jumpers775@users.noreply.github.com> +Jun Hee Yoo <contact.jhyoo@gmail.com> +Junil Kim <logyourself@gmail.com> +Justina Cho <justcho5@gmail.com> +Justine Tunney <jtunney@gmail.com> +Justine Tunney <jtunney@mozilla.com> +KITAITI Makoto <KitaitiMakoto@gmail.com> +KP Kaiser <kirk@zothcorp.com> +Kamilake <exjang0@gmail.com> +Karol Kontny <82021046+kkontny@users.noreply.github.com> +Karthick <j.karthic2004@gmail.com> +Kartik Saranathan <278928+Kartiku@users.noreply.github.com> +Kasumi <90275229+kasumi-1@users.noreply.github.com> +Kawrakow <48489457+ikawrakow@users.noreply.github.com> +Kendrick Taylor <kendrick@circuitsix.com> +Kevin Brothaler <admin@digipom.com> +Kevin Gibbons <bakkot@gmail.com> +Konosuke Sakai <konosuke@konosuke.work> +Konstantin Zhuravlyov <konstantin.zhuravlyov@amd.com> +Kreijstal <rainb@tfwno.gf> +Kylin <56434533+KyL0N@users.noreply.github.com> +LBlue <153975653+lbluep@users.noreply.github.com> +Larry Battle <larry.battle.tech@gmail.com> +Laytan Laats <laytanlaats@hotmail.com> +Leo Moll <leo.moll@yeasoft.com> +Lexevolution <31176843+Lexevolution@users.noreply.github.com> +LittleLoli <26589867+WhichWho@users.noreply.github.com> +Lucas Zanek <57494138+LucasZNK@users.noreply.github.com> +Luis Herrera <herrera-luis@users.noreply.github.com> +Lukas Rist <glaslos@gmail.com> +M. A. Ali <73258591+MightyStud@users.noreply.github.com> +M. Eren Akbiyik <erenakbiyik@gmail.com> +Ma Mingfei <mingfei.ma@intel.com> +Maciek <maciek.mab122@gmail.com> +Mahesh Madhav <67384846+heshpdx@users.noreply.github.com> +Marcin Mielniczuk <marmistrz.dev@zoho.eu> +Mark Karpelès <MagicalTux@users.noreply.github.com> +Mark Zhuang <zhuangqiubin@gmail.com> +Markus Tavenrath <mtavenrath@users.noreply.github.com> +Martin Delille <martin@delille.org> +Martin Warnaar <martinwarnaar@gmail.com> +Masaya, Kato <62578291+msy-kato@users.noreply.github.com> +Matheus de Sousa <23645013+keyehzy@users.noreply.github.com> +Mathieu Baudier <mbaudier@argeo.org> +Mathijs de Bruin <mathijs@mathijsfietst.nl> +Matija Pevec <mightymatth@users.noreply.github.com> +Matt Stephenson <mstephenson6@users.noreply.github.com> +Max Krasnyansky <max.krasnyansky@gmail.com> +Max Krasnyansky <quic_maxk@quicinc.com> +Maximiliano Levi <8160966+maxilevi@users.noreply.github.com> +Meng, Hengyu <hengyu.meng@intel.com> +Mengqing Cao <cmq0113@163.com> +Michael Podvitskiy <podvitskiymichael@gmail.com> +Michael Rienstra <mrienstra@gmail.com> +Mikhail Grigorev <sleuthhound@gmail.com> +Mohammadreza Hendiani <hendiani.mohammadreza@gmail.com> +Mohit Agarwal <mohit@sdf.org> +Molly Sophia <mollysophia379@gmail.com> +Murilo Santana <mvrilo@gmail.com> +NETZkultur GmbH <mulholland@netzkultur.de> +Natsu <chino@hotococoa.moe> +Neil Chudleigh <nchudleigh@users.noreply.github.com> +Neo Zhang <14088817+arthw@users.noreply.github.com> +Neo Zhang Jianyu <jianyu.zhang@intel.com> +Neuman Vong <neuman.vong@gmail.com> +Nicholai Tukanov <nicholaitukanov@gmail.com> +Nicholas Albion <nalbion@yahoo.com> +Nico Bosshard <nico@bosshome.ch> +Nicolò Scipione <nicolo.scipione@codeplay.com> +Niels Mayer <Niels.Mayer@gmail.com> +Nikita Sarychev <42014488+sARY77@users.noreply.github.com> +Nikolaj Olsson <nikse.dk@gmail.com> +Okabintaro <103938900+Okabintaro@users.noreply.github.com> +Oleg Sidorov <me@whitebox.io> +Oleg Sidorov <oleg@sidorov.nl> +Olivier Chafik <ochafik@users.noreply.github.com> +Ondrej Kokes <ondrej.kokes@gmail.com> +Ouadie EL FAROUKI <ouadie.elfarouki@codeplay.com> +PAB <pierreantoine.bannier@gmail.com> +Paul Tsochantaris <ptsochantaris@icloud.com> +Pedro Probst <pprobst@insiberia.net> +Peng <hzp1024@qq.com> +Peter <peter277@users.noreply.github.com> +Philipp Zabel <philipp.zabel@gmail.com> +Philippe Normand <phil@base-art.net> +Philippe Normand <philn@igalia.com> +Plamen Minev <pacominev@gmail.com> +Prashant Vithule <119530321+Vithulep@users.noreply.github.com> +Przemysław Pawełczyk <przemoc@gmail.com> +Qianhe Chen <54462604+chenqianhe@users.noreply.github.com> +R0CKSTAR <xiaodong.ye@mthreads.com> +R0CKSTAR <yeahdongcn@gmail.com> +Radoslav Gerganov <rgerganov@gmail.com> +Radosław Gryta <radek.gryta@gmail.com> +Rahul Vadhyar <107788610+RahulVadhyar@users.noreply.github.com> +Raiya Araki <83504221+rai62@users.noreply.github.com> +Reinforce-II <fate@eastal.com> +Reinis Muiznieks <muiznieks.reinis@gmail.com> +RelatedTitle <r3latedtitle@gmail.com> +Rémy Oudompheng <oudomphe@phare.normalesup.org> +RhinoDevel <RhinoDevel@users.noreply.github.com> +Rich Jones <miserlou@gmail.com> +Robert Ormandi <52251610+ormandi@users.noreply.github.com> +Robin <robin.xw@hotmail.com> +Roddur Dasgupta <roddurd@gmail.com> +Roland Rabien <figbug@gmail.com> +Romain Biessy <romain.biessy@codeplay.com> +Ronsor <ronsor@ronsor.pw> +Rotem Dan <rotemdan@gmail.com> +Ryan Hitchman <hitchmanr@gmail.com> +Ryan Metcalfe <107415876+RyanMetcalfeInt8@users.noreply.github.com> +RyanChang <ftes90015@gmail.com> +SRHMorris <69468379+SRHMorris@users.noreply.github.com> +SXX <sxx1136965276@gmail.com> +Sacha Arbonel <sacha.arbonel@hotmail.fr> +Salman Faroz <stsfaroz@gmail.com> +Salvatore Mesoraca <s.mesoraca16@gmail.com> +Sam <49637763+Onlyartist9@users.noreply.github.com> +Sam Pullara <spullara@gmail.com> +Samuel Durante <44513615+samueldurantes@users.noreply.github.com> +Sanchit Gandhi <93869735+sanchit-gandhi@users.noreply.github.com> +Sandro Hanea <40202887+sandrohanea@users.noreply.github.com> +Sergio López <slp@redhat.com> +Sergio López <slp@sinrega.org> +Shanshan Shen <467638484@qq.com> +Shijie <821898965@qq.com> +Shupei Fan <dymarkfan@outlook.com> +Siddharth Ramakrishnan <srr2141@columbia.edu> +Sigbjørn Skjæret <sigbjorn.skjaeret@scala.com> +Simon Moisselin <simon.moisstoll@gmail.com> +Sindre Sorhus <sindresorhus@gmail.com> +Slava Primenko <primenko.s@gmail.com> +Srihari-mcw <96763064+Srihari-mcw@users.noreply.github.com> +Stavros Panakakis <53979866+Stavrospanakakis@users.noreply.github.com> +Stefan Sydow <s.sydow@heinlein-video.de> +Stefan Sydow <stefan@sydow.email> +Syahmi Azhar <prsyahmi@gmail.com> +Syed Jafri <syedjafri97@gmail.com> +Sơn Phan Trung <phantrungson17@gmail.com> +Taisei Mima <bhbstar.me@gmail.com> +Takeshi Inoue <inoue.takeshi@gmail.com> +Tamotsu Takahashi <ttakah+github@gmail.com> +Taras Glek <taras@thegp.com> +Tauseef Mohiuddin <35351464+tauseefmohammed2@users.noreply.github.com> +Thamster <Thamster@users.noreply.github.com> +Thijs Raymakers <thijs@raymakers.nl> +Thomas Fitzsimmons <fitzsim@fitzsim.org> +Tiago Fassoni <tiagofassoni@users.noreply.github.com> +Tienshiao Ma <tienshiao@tienshiao.org> +Tim Miller <drasticactions@users.noreply.github.com> +Timothy Cronin <40186632+4imothy@users.noreply.github.com> +Tobrun <tobrun.van.nuland@gmail.com> +Todd <taf2@users.noreply.github.com> +Toliver <teejae@gmail.com> +Tong Li <31761981+litongjava@users.noreply.github.com> +Tony Wasserka <4840017+neobrain@users.noreply.github.com> +Topping1 <78745143+Topping1@users.noreply.github.com> +Travis Cline <travis.cline@gmail.com> +UEXTM.com <84163508+uextm@users.noreply.github.com> +UsernamesLame <156965854+UsernamesLame@users.noreply.github.com> +Vadim Peretokin <vperetokin@hey.com> +Valentin Gosu <1454649+valenting@users.noreply.github.com> +Vin Misra <vinith@alum.mit.edu> +Vulcan <93451215+trholding@users.noreply.github.com> +WhiteOlivierus <36532695+WhiteOlivierus@users.noreply.github.com> +William Tambellini <william.tambellini@gmail.com> +William Tambellini <wtambellini@sdl.com> +Wilson Silva <wilson.dsigns@gmail.com> +Xiang (Kevin) Li <kevinli020508@gmail.com> +Xiao-Yong Jin <jinxiaoyong@gmail.com> +XiaotaoChen <chenxiaotao1234@gmail.com> +Xingchen Song(宋星辰) <xingchensong1996@163.com> +Xinpeng Dou <81913537+Dou-Git@users.noreply.github.com> +Xuan Son Nguyen <thichthat@gmail.com> +Yajing Tang <phillis@google.com> +Yang Shen <aplshenyang@gmail.com> +Yunès <jean.baptiste.yunes@free.fr> +Yuri Khrustalev <ykhrustalev@users.noreply.github.com> +Yusuf Redžić <48274562+redzic@users.noreply.github.com> +ZaBlazzingZephyrus <119159668+blazingzephyr@users.noreply.github.com> +Zhenwei Jin <109658203+kylo5aby@users.noreply.github.com> +Zhiyuan Li <lizhiyuan@uniartisan.com> +Zhiyuan Li <uniartisan2017@gmail.com> +Zigfrid Zvezdin <ziggerZZ@gmail.com> +Zollner <24618122+Zolliner@users.noreply.github.com> +a3sh <38979186+A3shTnT@users.noreply.github.com> +ag2s20150909 <19373730+ag2s20150909@users.noreply.github.com> +agray3 <agray3@users.noreply.github.com> +ai-at-home <149282006+ai-at-home@users.noreply.github.com> +aldorof <aldorof@users.noreply.github.com> +alonfaraj <alonfaraj@gmail.com> +amd-dwang <dong.wang@amd.com> +amritahs-ibm <amritahs@linux.vnet.ibm.com> +andypayne <apayne@gmail.com> +ardfork <134447697+ardfork@users.noreply.github.com> +arizhih <40765267+arizhih@users.noreply.github.com> +automaticcat <daogiatuank54@gmail.com> +bandoti <141645996+bandoti@users.noreply.github.com> +be-next <jerome.ramette@gmail.com> +bert hubert <bert@hubertnet.nl> +billyct <billy_allen@126.com> +bmwl <brian.marshall@tolko.com> +bobqianic <129547291+bobqianic@users.noreply.github.com> +bocytko <bocytko+github@gmail.com> +boolemancer <48014766+boolemancer@users.noreply.github.com> +boolemancer <boolemancer@gmail.com> +bradmit <151883577+bradmit@users.noreply.github.com> +brunofaustino <b.fa.amorim@gmail.com> +bssrdf <merlintiger@hotmail.com> +byte-6174 <88070277+byte-6174@users.noreply.github.com> +cdosoftei <ciprian.dosoftei@gmail.com> +clach04 <Chris.Clark@actian.com> +compilade <113953597+compilade@users.noreply.github.com> +compilade <git@compilade.net> +conradg <conradjgodfrey@gmail.com> +crummyh <elijah@crums.us> +ddpasa <112642920+ddpasa@users.noreply.github.com> +denersc <denerstassun@gmail.com> +dscripka <dscripka@users.noreply.github.com> +duthils <duthils@duthils.net> +ecneladis <ecneladis@users.noreply.github.com> +faker <nspyia2002@gmail.com> +fitzsim <fitzsim@fitzsim.org> +fj-y-saito <85871716+fj-y-saito@users.noreply.github.com> +fraxy-v <65565042+fraxy-v@users.noreply.github.com> +genevera (she/her) <genevera@users.noreply.github.com> +geniusnut <geniusnut@gmail.com> +gilbertgong <gilbert.gong@gmail.com> +gn64 <yukikaze.jp@gmail.com> +goldwaving <77494627+goldwaving@users.noreply.github.com> +greeshmay <greeshmay@gmail.com> +haopeng <657407891@qq.com> +hipudding <huafengchun@gmail.com> +hsinhoyeh <yhh92u@gmail.com> +hydai <z54981220@gmail.com> +iamthad <thadeus.j.fleming@gmail.com> +issixx <46835150+issixx@users.noreply.github.com> +james wolf <contractorwolf@hotmail.com> +jdomke <28772296+jdomke@users.noreply.github.com> +jettoblack <jettoblack@gmail.com> +jiez <373447296@qq.com> +joecryptotoo <80373433+joecryptotoo@users.noreply.github.com> +jorismertz <35079666+jorismertz@users.noreply.github.com> +junchao-loongson <68935141+junchao-loongson@users.noreply.github.com> +junkfood <69683722+JunkFood02@users.noreply.github.com> +jwijffels <jwijffels@bnosac.be> +k.h.lai <adrian.k.h.lai@outlook.com> +kamranjon <kamranjon@gmail.com> +katsu560 <katsu560oo-@docomo.ne.jp> +kennethge <57784063+kenneth-ge@users.noreply.github.com> +keyehzy <msamuel@aluno.puc-rio.br> +kunnis <kunnis@users.noreply.github.com> +l3utterfly <gc.pthzfoldr@gmail.com> +leejet <leejet714@gmail.com> +leo-pony <nengjunma@outlook.com> +lhez <quic_lih@quicinc.com> +litong <31761981+litongjava@users.noreply.github.com> +liuwei-git <14815172+liuwei-git@users.noreply.github.com> +lnyan <lkwq007@gmail.com> +luoyu-intel <yu.luo@intel.com> +m.bell <m.bell@techsmith.com> +mahorozte <41834471+mahorozte@users.noreply.github.com> +mashizora <30516315+mashizora@users.noreply.github.com> +matt23654 <matthew.webber@protonmail.com> +matteo <matteogeniaccio@yahoo.it> +mgrachten <maarten@grachten.eu> +mkiol <mkiol@users.noreply.github.com> +mky_coder <47767389+mkycoder@users.noreply.github.com> +novag <7754358+novag@users.noreply.github.com> +pajowu <pajowu@pajowu.de> +pengxin99 <pengxin.yuan@intel.com> +petterreinholdtsen <pere-github@hungry.com> +polarmoon <90010972+polarmoon@users.noreply.github.com> +rlapray <lapray.romain@gmail.com> +sandrohanea <40202887+sandrohanea@users.noreply.github.com> +semiformal-net <84111142+semiformal-net@users.noreply.github.com> +shibukazu <61775791+shibukazu@users.noreply.github.com> +shikokuchuo <53399081+shikokuchuo@users.noreply.github.com> +slaren <slarengh@gmail.com> +slashlib <slashlib@users.noreply.github.com> +snadampal <87143774+snadampal@users.noreply.github.com> +someone13574 <81528246+someone13574@users.noreply.github.com> +st-gr <38470677+st-gr@users.noreply.github.com> +stduhpf <stephduh@live.fr> +stormofice <58337328+stormofice@users.noreply.github.com> +texmex76 <40733439+texmex76@users.noreply.github.com> +thefinaldegree <thefinaldegree@gmail.com> +thewh1teagle <61390950+thewh1teagle@users.noreply.github.com> +toboil-features <160222185+toboil-features@users.noreply.github.com> +trixirt <trix@redhat.com> +ulatekh <ulatekh@yahoo.com> +undef <undefdev@gmail.com> +uvos <devnull@uvos.xyz> +uvos <philipp@uvos.xyz> +valVk <valVk@users.noreply.github.com> +venkr <venkateshrameshkumar+1@gmail.com> +vicalloy <zbirder@gmail.com> +wangshuai09 <391746016@qq.com> +woachk <24752637+woachk@users.noreply.github.com> +xctan <axunlei@gmail.com> +xdrudis <xavierdrudis@yahoo.es> +yuri@FreeBSD <yuri@FreeBSD> +zhangjixiong <code.zjx@gmail.com> +zhentaoyu <zhentao.yu@intel.com> +zhouwg <6889919+zhouwg@users.noreply.github.com> +zhouwg <zhouwg2000@gmail.com> +谢乃闻 <sienaiwun@users.noreply.github.com> +布客飞龙 <562826179@qq.com> +Артём Земляк <azemlyak@smart-consulting.ru> diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..4c049f3 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,324 @@ +cmake_minimum_required(VERSION 3.5) # for add_link_options and implicit target directories. +project("whisper.cpp" C CXX) +include(CheckIncludeFileCXX) + +### whisper.cpp version +set(WHISPER_VERSION_MAJOR 1) +set(WHISPER_VERSION_MINOR 9) +set(WHISPER_VERSION_PATCH 4) +set(WHISPER_VERSION_BASE "${WHISPER_VERSION_MAJOR}.${WHISPER_VERSION_MINOR}.${WHISPER_VERSION_PATCH}") + +# whether this is a development/nightly build +# set this to OFF when making a release from a release tag (vX.Y.Z) +# ref: https://github.com/ggml-org/ggml/discussions/1579 +option(WHISPER_BUILD_IS_DEV "whisper: dev build" ON) + +if (WHISPER_BUILD_IS_DEV) + set(WHISPER_VERSION "${WHISPER_VERSION_BASE}-dev") +else() + # TODO: check that the current commit is tagged correctly according to the version specified above + set(WHISPER_VERSION "${WHISPER_VERSION_BASE}") +endif() + +message(STATUS "whisper.cpp version: ${WHISPER_VERSION}") + +#set(CMAKE_WARN_DEPRECATED YES) +set(CMAKE_WARN_UNUSED_CLI YES) + +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +if (NOT XCODE AND NOT MSVC AND NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo") +endif() + +# Add path to modules +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/") + +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) + +if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) + set(WHISPER_STANDALONE ON) + + include(git-vars) + + # configure project version + configure_file(${CMAKE_SOURCE_DIR}/bindings/javascript/package-tmpl.json ${CMAKE_SOURCE_DIR}/bindings/javascript/package.json @ONLY) +else() + set(WHISPER_STANDALONE OFF) +endif() + +if (EMSCRIPTEN) + set(BUILD_SHARED_LIBS_DEFAULT OFF) + + set(CMAKE_CXX_STANDARD 17) + set(CMAKE_CXX_STANDARD_REQUIRED ON) + + option(WHISPER_WASM_SINGLE_FILE "whisper: embed WASM inside the generated whisper.js" ON) + + # TODO: without these, we get the following error: + # wasm-ld: error: --shared-memory is disallowed by whisper.cpp.o because it was not compiled with 'atomics' or 'bulk-memory' features. + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") + + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s TOTAL_STACK=5242880") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -s TOTAL_STACK=5242880") + + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated") +else() + if (MINGW) + set(BUILD_SHARED_LIBS_DEFAULT OFF) + else() + set(BUILD_SHARED_LIBS_DEFAULT ON) + endif() +endif() + +option(BUILD_SHARED_LIBS "build shared libraries" ${BUILD_SHARED_LIBS_DEFAULT}) + +# +# option list +# + +# debug +option(WHISPER_ALL_WARNINGS "whisper: enable all compiler warnings" ON) +option(WHISPER_ALL_WARNINGS_3RD_PARTY "whisper: enable all compiler warnings in 3rd party libs" OFF) + +# build +option(WHISPER_FATAL_WARNINGS "whisper: enable -Werror flag" OFF) +option(WHISPER_USE_SYSTEM_GGML "whisper: use system-installed GGML library" OFF) +option(WHISPER_USE_SYSTEM_LLAMA "whisper: use system-installed llama.cpp library" OFF) + +if (WHISPER_USE_SYSTEM_LLAMA AND NOT WHISPER_USE_SYSTEM_GGML) + message(STATUS "WHISPER_USE_SYSTEM_LLAMA=ON: setting WHISPER_USE_SYSTEM_GGML=ON") + set(WHISPER_USE_SYSTEM_GGML ON CACHE BOOL "" FORCE) +endif() + +# sanitizers +option(WHISPER_SANITIZE_THREAD "whisper: enable thread sanitizer" OFF) +option(WHISPER_SANITIZE_ADDRESS "whisper: enable address sanitizer" OFF) +option(WHISPER_SANITIZE_UNDEFINED "whisper: enable undefined sanitizer" OFF) + +# extra artifacts +option(WHISPER_BUILD_TESTS "whisper: build tests" ${WHISPER_STANDALONE}) +option(WHISPER_BUILD_EXAMPLES "whisper: build examples" ${WHISPER_STANDALONE}) +option(WHISPER_BUILD_SERVER "whisper: build server example" ${WHISPER_STANDALONE}) + +# 3rd party libs +option(WHISPER_CURL "whisper: use libcurl to download model from an URL" OFF) +option(WHISPER_SDL2 "whisper: support for libSDL2" OFF) + +if (CMAKE_SYSTEM_NAME MATCHES "Linux") + option(WHISPER_COMMON_FFMPEG "whisper: examples link with ffmpeg libs in order to decode more audio formats" OFF) +endif() + +option(WHISPER_COREML "whisper: enable Core ML framework" OFF) +option(WHISPER_COREML_ALLOW_FALLBACK "whisper: allow non-CoreML fallback" OFF) +option(WHISPER_OPENVINO "whisper: support for OpenVINO" OFF) +option(WHISPER_VITISAI "whisper: support for AMD Vitis AI" OFF) + +# Required for relocatable CMake package +include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/build-info.cmake) + +# override ggml options +set(GGML_SANITIZE_THREAD ${WHISPER_SANITIZE_THREAD}) +set(GGML_SANITIZE_ADDRESS ${WHISPER_SANITIZE_ADDRESS}) +set(GGML_SANITIZE_UNDEFINED ${WHISPER_SANITIZE_UNDEFINED}) +set(GGML_ALL_WARNINGS ${WHISPER_ALL_WARNINGS}) +set(GGML_FATAL_WARNINGS ${WHISPER_FATAL_WARNINGS}) + +# transition helpers +function (whisper_option_depr TYPE OLD NEW) + if (${OLD}) + message(${TYPE} "${OLD} is deprecated and will be removed in the future.\nUse ${NEW} instead\n") + set(${NEW} ON) + endif() +endfunction() + +whisper_option_depr(FATAL_ERROR WHISPER_CUBLAS GGML_CUDA) +whisper_option_depr(WARNING WHISPER_CUDA GGML_CUDA) +whisper_option_depr(WARNING WHISPER_KOMPUTE GGML_KOMPUTE) +whisper_option_depr(WARNING WHISPER_METAL GGML_METAL) +whisper_option_depr(WARNING WHISPER_METAL_EMBED_LIBRARY GGML_METAL_EMBED_LIBRARY) +whisper_option_depr(WARNING WHISPER_NATIVE GGML_NATIVE) +whisper_option_depr(WARNING WHISPER_OPENMP GGML_OPENMP) +whisper_option_depr(WARNING WHISPER_RPC GGML_RPC) +whisper_option_depr(WARNING WHISPER_SYCL GGML_SYCL) +whisper_option_depr(WARNING WHISPER_SYCL_F16 GGML_SYCL_F16) +whisper_option_depr(WARNING WHISPER_CCACHE GGML_CCACHE) +whisper_option_depr(WARNING WHISPER_FFMPEG WHISPER_COMMON_FFMPEG) + +if (GGML_CUDA AND NOT MSVC) + #GGML_CUDA enabled, add the necessary compile options -Wno-deprecated-gpu-targets + add_compile_options(-Wno-deprecated-gpu-targets) +endif() + +# +# build the library +# + +if (NOT TARGET ggml) + if (WHISPER_USE_SYSTEM_GGML) + find_package(ggml REQUIRED) + if (NOT ggml_FOUND) + message(FATAL_ERROR "System-installed GGML library not found.") + endif() + add_library(ggml ALIAS ggml::ggml) + else() + add_subdirectory(ggml) + if(WIN32) + # The following adds a _DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR macro and is a workaround for + # the Windows C++ standard library which does not support constexpr mutexes. + # From the release notes://github.com/microsoft/STL/wiki/Changelog + # Disable constexpr mutex constructor on Windows + # Fixed mutex's constructor to be constexpr. #3824 #4000 #4339 + # Note: Programs that aren't following the documented restrictions on binary compatibility may encounter + # null dereferences in mutex machinery. You must follow this rule: + # When you mix binaries built by different supported versions of the toolset, the Redistributable version + # must be at least as new as the latest toolset used by any app component. + # You can define _DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR as an escape hatch. + # + # Specifically to whisper.cpp this would cause a crash when using the Java bindings. + # resulting in a Invalid memory access error. + target_compile_definitions(ggml-base PRIVATE _DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR) + endif() + endif() + # ... otherwise assume ggml is added by a parent CMakeLists.txt +endif() +add_subdirectory(src) + +# +# install +# + +include(GNUInstallDirs) +include(CMakePackageConfigHelpers) + +if (NOT DEFINED WHISPER_BUILD_NUMBER) + set(WHISPER_BUILD_NUMBER ${BUILD_NUMBER}) +endif() +if (NOT DEFINED WHISPER_BUILD_COMMIT) + set(WHISPER_BUILD_COMMIT ${BUILD_COMMIT}) +endif() + +set(WHISPER_INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_INCLUDEDIR} CACHE PATH "Location of header files") +set(WHISPER_LIB_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR} CACHE PATH "Location of library files") +set(WHISPER_BIN_INSTALL_DIR ${CMAKE_INSTALL_BINDIR} CACHE PATH "Location of binary files") + +get_directory_property(WHISPER_TRANSIENT_DEFINES COMPILE_DEFINITIONS) + +set_target_properties(whisper PROPERTIES PUBLIC_HEADER ${CMAKE_CURRENT_SOURCE_DIR}/include/whisper.h) + +install(TARGETS whisper LIBRARY PUBLIC_HEADER) + +target_compile_definitions(whisper PRIVATE + WHISPER_VERSION="${WHISPER_VERSION}" +) + +set_target_properties(parakeet PROPERTIES PUBLIC_HEADER ${CMAKE_CURRENT_SOURCE_DIR}/include/parakeet.h) +install(TARGETS parakeet LIBRARY PUBLIC_HEADER) + +target_compile_definitions(parakeet PRIVATE + PARAKEET_VERSION="${WHISPER_VERSION}" +) + +configure_package_config_file( + ${CMAKE_CURRENT_SOURCE_DIR}/cmake/whisper-config.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/whisper-config.cmake + INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/whisper + PATH_VARS + WHISPER_INCLUDE_INSTALL_DIR + WHISPER_LIB_INSTALL_DIR + WHISPER_BIN_INSTALL_DIR ) + +write_basic_package_version_file( + ${CMAKE_CURRENT_BINARY_DIR}/whisper-config-version.cmake + VERSION ${WHISPER_VERSION} + COMPATIBILITY SameMajorVersion) + +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/whisper-config.cmake + ${CMAKE_CURRENT_BINARY_DIR}/whisper-config-version.cmake + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/whisper) + +configure_file(cmake/whisper.pc.in + "${CMAKE_CURRENT_BINARY_DIR}/whisper.pc" + @ONLY) + +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/whisper.pc" + DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) + +set(PARAKEET_INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_INCLUDEDIR} CACHE PATH "Location of header files") +set(PARAKEET_LIB_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR} CACHE PATH "Location of library files") +set(PARAKEET_BIN_INSTALL_DIR ${CMAKE_INSTALL_BINDIR} CACHE PATH "Location of binary files") + +configure_package_config_file( + ${CMAKE_CURRENT_SOURCE_DIR}/cmake/parakeet-config.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/parakeet-config.cmake + INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/parakeet + PATH_VARS + PARAKEET_INCLUDE_INSTALL_DIR + PARAKEET_LIB_INSTALL_DIR + PARAKEET_BIN_INSTALL_DIR) + +write_basic_package_version_file( + ${CMAKE_CURRENT_BINARY_DIR}/parakeet-config-version.cmake + VERSION ${WHISPER_VERSION} + COMPATIBILITY SameMajorVersion) + +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/parakeet-config.cmake + ${CMAKE_CURRENT_BINARY_DIR}/parakeet-config-version.cmake + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/parakeet) + +configure_file(cmake/parakeet.pc.in + "${CMAKE_CURRENT_BINARY_DIR}/parakeet.pc" + @ONLY) + +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/parakeet.pc" + DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) + +# +# programs, examples and tests +# + +if (WHISPER_BUILD_TESTS AND NOT CMAKE_JS_VERSION) + include(CTest) + add_subdirectory(tests) +endif () + +if (WHISPER_BUILD_EXAMPLES) + add_subdirectory(examples) +endif() + +if (MSVC) + set(MSVC_WARNING_FLAGS + /wd4101 # Unreferenced local variable + /wd4005 # Macro redefinition + /wd4065 # switch statement contains 'default' but no 'case' labels + /wd4267 # Conversion from 'size_t' to a smaller type, possible loss of data + /wd4244 # Conversion from one type to another type, possible loss of ata + /wd4805 # Unsafe mix of type + /wd4305 # Truncation from 'type1' to 'type2' (often double to float) + /wd4996 # Function or variable may be unsafe/deprecated + ) + function(disable_msvc_warnings target_name) + if(TARGET ${target_name}) + target_compile_options(${target_name} PRIVATE ${MSVC_WARNING_FLAGS}) + endif() + endfunction() + + if (WHISPER_BUILD_EXAMPLES) + disable_msvc_warnings(whisper) + disable_msvc_warnings(common) + disable_msvc_warnings(common-sdl) + disable_msvc_warnings(lsp) + disable_msvc_warnings(wchess-core) + disable_msvc_warnings(whisper-command) + disable_msvc_warnings(whisper-cli) + disable_msvc_warnings(whisper-server) + disable_msvc_warnings(whisper-stream) + disable_msvc_warnings(whisper-talk-llama) + disable_msvc_warnings(whisper-bench) + disable_msvc_warnings(quantize) + disable_msvc_warnings(vad-speech-segments) + endif() +endif() diff --git a/CMakePresets.json b/CMakePresets.json new file mode 100644 index 0000000..b5afeb3 --- /dev/null +++ b/CMakePresets.json @@ -0,0 +1,95 @@ +{ + "version": 4, + "configurePresets": [ + { + "name": "base", + "hidden": true, + "generator": "Ninja", + "binaryDir": "${sourceDir}/build-${presetName}", + "cacheVariables": { + "CMAKE_EXPORT_COMPILE_COMMANDS": "ON", + "CMAKE_INSTALL_RPATH": "$ORIGIN;$ORIGIN/.." + } + }, + { + "name": "sycl-base", + "hidden": true, + "generator": "Ninja", + "binaryDir": "${sourceDir}/build-${presetName}", + "cacheVariables": { + "CMAKE_EXPORT_COMPILE_COMMANDS": "ON", + "CMAKE_CXX_COMPILER": "icx", + "CMAKE_C_COMPILER": "cl", + "GGML_SYCL": "ON", + "CMAKE_INSTALL_RPATH": "$ORIGIN;$ORIGIN/.." + } + }, + { "name": "debug", "hidden": true, "cacheVariables": { "CMAKE_BUILD_TYPE": "Debug" } }, + { "name": "release", "hidden": true, "cacheVariables": { "CMAKE_BUILD_TYPE": "Release" } }, + { "name": "reldbg", "hidden": true, "cacheVariables": { "CMAKE_BUILD_TYPE": "RelWithDebInfo" } }, + { "name": "static", "hidden": true, "cacheVariables": { "GGML_STATIC": "ON" } }, + { "name": "sycl_f16", "hidden": true, "cacheVariables": { "GGML_SYCL_F16": "ON" } }, + { "name": "vulkan", "hidden": true, "cacheVariables": { "GGML_VULKAN": "ON" } }, + + { + "name": "x64-windows-llvm", "hidden": true, + "cacheVariables": { + "CMAKE_TOOLCHAIN_FILE": "${sourceDir}/cmake/x64-windows-llvm.cmake" + } + }, + + { + "name": "arm64-windows-llvm", "hidden": true, + "architecture": { "value": "arm64", "strategy": "external" }, + "toolset": { "value": "host=x64", "strategy": "external" }, + "cacheVariables": { + "CMAKE_TOOLCHAIN_FILE": "${sourceDir}/cmake/arm64-windows-llvm.cmake" + } + }, + + { + "name": "arm64-apple-clang", "hidden": true, + "architecture": { "value": "arm64", "strategy": "external" }, + "toolset": { "value": "host=x64", "strategy": "external" }, + "cacheVariables": { + "CMAKE_TOOLCHAIN_FILE": "${sourceDir}/cmake/arm64-apple-clang.cmake" + } + }, + { + "name": "x64-linux-gcc", "hidden": true, + "cacheVariables": { + "CMAKE_C_COMPILER": "gcc", + "CMAKE_CXX_COMPILER": "g++" + } + }, + { "name": "x64-linux-gcc-debug", "inherits": [ "base", "x64-linux-gcc", "debug" ] }, + { "name": "x64-linux-gcc-release", "inherits": [ "base", "x64-linux-gcc", "release" ] }, + { "name": "x64-linux-gcc-reldbg", "inherits": [ "base", "x64-linux-gcc", "reldbg" ] }, + { "name": "x64-linux-gcc+static-release", "inherits": [ "base", "x64-linux-gcc", "release", "static" ] }, + + { "name": "arm64-windows-llvm-debug", "inherits": [ "base", "arm64-windows-llvm", "debug" ] }, + { "name": "arm64-windows-llvm-release", "inherits": [ "base", "arm64-windows-llvm", "reldbg" ] }, + { "name": "arm64-windows-llvm+static-release", "inherits": [ "base", "arm64-windows-llvm", "reldbg", "static" ] }, + + { "name": "arm64-apple-clang-debug", "inherits": [ "base", "arm64-apple-clang", "debug" ] }, + { "name": "arm64-apple-clang-release", "inherits": [ "base", "arm64-apple-clang", "reldbg" ] }, + { "name": "arm64-apple-clang+static-release", "inherits": [ "base", "arm64-apple-clang", "reldbg", "static" ] }, + + { "name": "x64-windows-llvm-debug", "inherits": [ "base", "x64-windows-llvm", "debug" ] }, + { "name": "x64-windows-llvm-release", "inherits": [ "base", "x64-windows-llvm", "release" ] }, + { "name": "x64-windows-llvm-reldbg", "inherits": [ "base", "x64-windows-llvm", "reldbg" ] }, + { "name": "x64-windows-llvm+static-release", "inherits": [ "base", "x64-windows-llvm", "reldbg", "static" ] }, + + { "name": "x64-windows-msvc-debug", "inherits": [ "base", "debug" ] }, + { "name": "x64-windows-msvc-release", "inherits": [ "base", "reldbg" ] }, + { "name": "x64-windows-msvc+static-release", "inherits": [ "base", "reldbg", "static" ] }, + + { "name": "x64-windows-sycl-debug", "inherits": [ "sycl-base", "debug" ] }, + { "name": "x64-windows-sycl-debug-f16", "inherits": [ "sycl-base", "debug", "sycl_f16" ] }, + { "name": "x64-windows-sycl-release", "inherits": [ "sycl-base", "release" ] }, + { "name": "x64-windows-sycl-release-f16", "inherits": [ "sycl-base", "release", "sycl_f16" ] }, + + { "name": "x64-windows-vulkan-debug", "inherits": [ "base", "vulkan", "debug" ] }, + { "name": "x64-windows-vulkan-release", "inherits": [ "base", "vulkan", "release" ] } + ] +} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..c301604 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,176 @@ +# Contributors + +The project differentiates between 3 levels of contributors: + +- Contributors: people who have contributed before (no special privileges) +- Collaborators (Triage): people with significant contributions, who may be responsible for some parts of the code, and are expected to maintain and review contributions for the code they own +- Maintainers: responsible for reviewing and merging PRs, after approval from the code owners + +# AI Usage Policy + +> [!IMPORTANT] +> This project does **not** accept pull requests that are fully or predominantly AI-generated. AI tools may be utilized solely in an assistive capacity. +> +> Repeated violations of this policy may result in your account being permanently banned from contributing to the project. +> +> Detailed information regarding permissible and restricted uses of AI can be found in the [AGENTS.md](AGENTS.md) file. + +Code that is initially generated by AI and subsequently edited will still be considered AI-generated. AI assistance is permissible only when the majority of the code is authored by a human contributor, with AI employed exclusively for corrections or to expand on verbose modifications that the contributor has already conceptualized (e.g., generating repeated lines with minor variations). + +If AI is used to generate any portion of the code, contributors must adhere to the following requirements: + +1. Explicitly disclose the manner in which AI was employed. +2. Perform a comprehensive manual review prior to submitting the pull request. +3. Be prepared to explain every line of code they submitted when asked about it by a maintainer. +4. It is strictly prohibited to use AI to write your posts for you (bug reports, feature requests, pull request descriptions, Github discussions, responding to humans, ...). + +For more info, please refer to the [AGENTS.md](AGENTS.md) file. + +# Pull requests (for contributors & collaborators) + +Before submitting your PR: +- Search for existing PRs to prevent duplicating efforts +- whisper.cpp uses the ggml tensor library for model evaluation. If you are unfamiliar with ggml, consider taking a look at the [examples in the ggml repository](https://github.com/ggml-org/ggml/tree/master/examples/). [simple](https://github.com/ggml-org/ggml/tree/master/examples/simple) shows the bare minimum for using ggml. [gpt-2](https://github.com/ggml-org/ggml/tree/master/examples/gpt-2) has minimal implementations for language model inference using GPT-2. [mnist](https://github.com/ggml-org/ggml/tree/master/examples/mnist) demonstrates how to train and evaluate a simple image classifier +- Test your changes: + - Execute [the full CI locally on your machine](ci/README.md) before publishing +- Create separate PRs for each feature or fix: + - Avoid combining unrelated changes in a single PR + - For intricate features, consider opening a feature request first to discuss and align expectations +- If you are a new contributor + - Limit your open PRs to 1 + - Do not submit trivial fixes (e.g. typos, formatting changes) + +After submitting your PR: +- Expect requests for modifications to ensure the code meets whisper.cpp's standards for quality and long-term maintainability +- Maintainers will rely on your insights and approval when making a final decision to approve and merge a PR +- If your PR becomes stale, rebase it on top of latest `master` to get maintainers attention + +# Pull requests (for maintainers) + +- Squash-merge PRs +- Use the following format for the squashed commit title: `<module> : <commit title> (#<issue_number>)`. For example: `utils : fix typo in utils.py (#1234)` +- Optionally pick a `<module>` from here: https://github.com/ggml-org/llama.cpp/wiki/Modules +- Let other maintainers merge their own PRs +- When merging a PR, make sure you have a good understanding of the changes +- Be mindful of maintenance: most of the work going into a feature happens after the PR is merged. If the PR author is not committed to contribute long-term, someone else needs to take responsibility (you) + +Maintainers reserve the right to decline review or close pull requests for any reason, without any questions, particularly under any of the following conditions: +- The proposed change is already mentioned in the roadmap or an existing issue, and it has been assigned to someone. +- The pull request duplicates an existing one. +- The contributor fails to adhere to this contributing guide or the AI policy. + +# Coding guidelines + +- Avoid adding third-party dependencies, extra files, extra headers, etc. +- Always consider cross-compatibility with other operating systems and architectures +- Avoid fancy-looking modern STL constructs, use basic `for` loops, avoid templates, keep it simple +- Vertical alignment makes things more readable and easier to batch edit +- Clean-up any trailing whitespaces, use 4 spaces for indentation, brackets on the same line, `void * ptr`, `int & a` +- Use sized integer types such as `int32_t` in the public API, e.g. `size_t` may also be appropriate for allocation sizes or byte offsets +- Declare structs with `struct foo {}` instead of `typedef struct foo {} foo` + - In C++ code omit optional `struct` and `enum` keyword whenever they are not necessary + ```cpp + // OK + llama_context * ctx; + const llama_rope_type rope_type; + + // not OK + struct llama_context * ctx; + const enum llama_rope_type rope_type; + ``` + + _(NOTE: this guideline is yet to be applied to the `whisper.cpp` codebase. New code should follow this guideline.)_ + +- Try to follow the existing patterns in the code (indentation, spaces, etc.). In case of doubt use `clang-format` (from clang-tools v15+) to format the added code +- For anything not covered in the current guidelines, refer to the [C++ Core Guidelines](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines) +- Tensors store data in row-major order. We refer to dimension 0 as columns, 1 as rows, 2 as matrices +- Matrix multiplication is unconventional: [`C = ggml_mul_mat(ctx, A, B)`](https://github.com/ggml-org/llama.cpp/blob/880e352277fc017df4d5794f0c21c44e1eae2b84/ggml.h#L1058-L1064) means $C^T = A B^T \Leftrightarrow C = B A^T.$ + +![matmul](media/matmul.png) + +# Naming guidelines + +- Use `snake_case` for function, variable and type names +- Naming usually optimizes for longest common prefix (see https://github.com/ggml-org/ggml/pull/302#discussion_r1243240963) + + ```cpp + // not OK + int small_number; + int big_number; + + // OK + int number_small; + int number_big; + ``` + +- Enum values are always in upper case and prefixed with the enum name + + ```cpp + enum llama_vocab_type { + LLAMA_VOCAB_TYPE_NONE = 0, + LLAMA_VOCAB_TYPE_SPM = 1, + LLAMA_VOCAB_TYPE_BPE = 2, + LLAMA_VOCAB_TYPE_WPM = 3, + LLAMA_VOCAB_TYPE_UGM = 4, + LLAMA_VOCAB_TYPE_RWKV = 5, + }; + ``` + +- The general naming pattern is `<class>_<method>`, with `<method>` being `<action>_<noun>` + + ```cpp + llama_model_init(); // class: "llama_model", method: "init" + llama_sampler_chain_remove(); // class: "llama_sampler_chain", method: "remove" + llama_sampler_get_seed(); // class: "llama_sampler", method: "get_seed" + llama_set_embeddings(); // class: "llama_context", method: "set_embeddings" + llama_n_threads(); // class: "llama_context", method: "n_threads" + llama_adapter_lora_free(); // class: "llama_adapter_lora", method: "free" + ``` + + - The `get` `<action>` can be omitted + - The `<noun>` can be omitted if not necessary + - The `_context` suffix of the `<class>` is optional. Use it to disambiguate symbols when needed + - Use `init`/`free` for constructor/destructor `<action>` + +- Use the `_t` suffix when a type is supposed to be opaque to the user - it's not relevant to them if it is a struct or anything else + + ```cpp + typedef struct llama_context * llama_context_t; + + enum llama_pooling_type llama_pooling_type(const llama_context_t ctx); + ``` + + _(NOTE: this guideline is yet to be applied to the `whisper.cpp` codebase. New code should follow this guideline)_ + +- C/C++ filenames are all lowercase with dashes. Headers use the `.h` extension. Source files use the `.c` or `.cpp` extension +- Python filenames are all lowercase with underscores + +- _(TODO: abbreviations usage)_ + +# Preprocessor directives + +- _(TODO: add guidelines with examples and apply them to the codebase)_ + + ```cpp + #ifdef FOO + #endif // FOO + ``` + +# Code maintenance + +- New code should follow the guidelines (coding, naming, etc.) outlined in this document. Exceptions are allowed in isolated, backend-specific parts of the code that do not interface directly with the `ggml` interfaces. + _(NOTE: for legacy reasons, existing code is not required to follow this guideline)_ + +- For changes in server, please make sure to refer to the [server development documentation](./tools/server/README-dev.md) + +# Documentation + +- Documentation is a community effort +- When you need to look into the source code to figure out how to use an API consider adding a short summary to the header file for future reference +- When you notice incorrect or outdated documentation, please update it + +# Resources + +The Github issues, PRs and discussions contain a lot of information that can be useful to get familiar with the codebase. For convenience, some of the more important information is referenced from Github projects: + +https://github.com/ggml-org/whisper.cpp/projects diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..e7dca55 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023-2026 The ggml authors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..7c4fbe3 --- /dev/null +++ b/Makefile @@ -0,0 +1,58 @@ +# +# Audio samples +# + +.PHONY: build +build: + cmake -B build $(CMAKE_ARGS) + cmake --build build --config Release --parallel $(shell nproc) + +# download a few audio samples into folder "./samples": +.PHONY: samples +samples: + @echo "Downloading samples..." + @mkdir -p samples + @wget --quiet --show-progress -O samples/gb0.ogg https://upload.wikimedia.org/wikipedia/commons/2/22/George_W._Bush%27s_weekly_radio_address_%28November_1%2C_2008%29.oga + @wget --quiet --show-progress -O samples/gb1.ogg https://upload.wikimedia.org/wikipedia/commons/1/1f/George_W_Bush_Columbia_FINAL.ogg + @wget --quiet --show-progress -O samples/hp0.ogg https://upload.wikimedia.org/wikipedia/en/d/d4/En.henryfphillips.ogg + @wget --quiet --show-progress -O samples/mm1.wav https://cdn.openai.com/whisper/draft-20220913a/micro-machines.wav + @wget --quiet --show-progress -O samples/a13.mp3 https://upload.wikimedia.org/wikipedia/commons/transcoded/6/6f/Apollo13-wehaveaproblem.ogg/Apollo13-wehaveaproblem.ogg.mp3 + @wget --quiet --show-progress -O samples/diffusion2023-07-03.flac https://archive.org/download/diffusion2023-07-03/diffusion2023-07-03.flac + +# +# Models +# + +# if not already downloaded, the following targets download the specified model and +# runs it on all samples in the folder "./samples": + +.PHONY: tiny.en +.PHONY: tiny +.PHONY: base.en +.PHONY: base +.PHONY: small.en +.PHONY: small +.PHONY: medium.en +.PHONY: medium +.PHONY: large-v1 +.PHONY: large-v2 +.PHONY: large-v3 +.PHONY: large-v3-turbo + +tiny.en tiny base.en base small.en small medium.en medium large-v1 large-v2 large-v3 large-v3-turbo: + bash ./models/download-ggml-model.sh $@ + cmake -B build $(CMAKE_ARGS) + cmake --build build --config Release --parallel $(shell nproc) + @echo "" + @echo "===============================================" + @echo "Running $@ on all samples in ./samples ..." + @echo "===============================================" + @echo "" + @for f in samples/*.{flac,mp3,ogg,wav}; do \ + echo "----------------------------------------------" ; \ + echo "[+] Running $@ on $$f ... (run 'ffplay $$f' to listen)" ; \ + echo "----------------------------------------------" ; \ + echo "" ; \ + ./build/bin/whisper-cli -m models/ggml-$@.bin -f $$f ; \ + echo "" ; \ + done diff --git a/README.md b/README.md new file mode 100644 index 0000000..6bf407d --- /dev/null +++ b/README.md @@ -0,0 +1,970 @@ +# whisper.cpp + +<div align="center"> + +![whisper.cpp](https://user-images.githubusercontent.com/1991296/235238348-05d0f6a4-da44-4900-a1de-d0707e75b763.jpeg) + +[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT) +[![Release](https://img.shields.io/github/v/release/ggml-org/whisper.cpp?filter=v*)](https://github.com/ggml-org/whisper.cpp/releases) +[![Actions Status](https://github.com/ggml-org/whisper.cpp/workflows/CI/badge.svg)](https://github.com/ggml-org/whisper.cpp/actions) +[![Conan Center](https://shields.io/conan/v/whisper-cpp)](https://conan.io/center/whisper-cpp) +[![npm](https://img.shields.io/npm/v/whisper.cpp.svg)](https://www.npmjs.com/package/whisper.cpp/) + +</div> + +High-performance inference of [OpenAI's Whisper](https://github.com/openai/whisper) automatic speech recognition (ASR) model: + +- Plain C/C++ implementation without dependencies +- Apple Silicon first-class citizen - optimized via ARM NEON, Accelerate framework, Metal and [Core ML](#core-ml-support) +- AVX intrinsics support for x86 architectures +- [VSX intrinsics support for POWER architectures](#power-vsx-intrinsics) +- Mixed F16 / F32 precision +- [Integer quantization support](#quantization) +- Zero memory allocations at runtime +- [Vulkan support](#vulkan-gpu-support) +- Support for CPU-only inference +- [Efficient GPU support for NVIDIA](#nvidia-gpu-support) +- [AMD ROCm GPU support](#amd-rocm-gpu-support) +- [AMD Ryzen AI NPU Support](#amd-ryzen-ai-npu-support) +- [OpenVINO Support](#openvino-support) +- [Ascend NPU Support](#ascend-npu-support) +- [Moore Threads GPU Support](#moore-threads-gpu-support) +- [C-style API](https://github.com/ggml-org/whisper.cpp/blob/master/include/whisper.h) +- [Voice Activity Detection (VAD)](#voice-activity-detection-vad) + +Supported platforms: + +- [x] Mac OS (Intel and Arm) +- [x] [iOS](examples/whisper.objc) +- [x] [Android](examples/whisper.android) +- [x] [Java](bindings/java/README.md) +- [x] Linux / [FreeBSD](https://github.com/ggml-org/whisper.cpp/issues/56#issuecomment-1350920264) +- [x] [WebAssembly](examples/whisper.wasm) +- [x] Windows ([MSVC](https://github.com/ggml-org/whisper.cpp/blob/master/.github/workflows/build.yml#L117-L144) and [MinGW](https://github.com/ggml-org/whisper.cpp/issues/168)) +- [x] [Raspberry Pi](https://github.com/ggml-org/whisper.cpp/discussions/166) +- [x] [Docker](https://github.com/ggml-org/whisper.cpp/pkgs/container/whisper.cpp) + +The entire high-level implementation of the model is contained in [whisper.h](include/whisper.h) and [whisper.cpp](src/whisper.cpp). +The rest of the code is part of the [`ggml`](https://github.com/ggml-org/ggml) machine learning library. + +Having such a lightweight implementation of the model allows to easily integrate it in different platforms and applications. +As an example, here is a video of running the model on an iPhone 13 device - fully offline, on-device: [whisper.objc](examples/whisper.objc) + +https://user-images.githubusercontent.com/1991296/197385372-962a6dea-bca1-4d50-bf96-1d8c27b98c81.mp4 + +You can also easily make your own offline voice assistant application: [command](examples/command) + +https://user-images.githubusercontent.com/1991296/204038393-2f846eae-c255-4099-a76d-5735c25c49da.mp4 + +On Apple Silicon, the inference runs fully on the GPU via Metal: + +https://github.com/ggml-org/whisper.cpp/assets/1991296/c82e8f86-60dc-49f2-b048-d2fdbd6b5225 + +## Quick start + +First clone the repository: + +```bash +git clone https://github.com/ggml-org/whisper.cpp.git +``` + +Navigate into the directory: + +``` +cd whisper.cpp +``` + +Then, download one of the Whisper [models](models/README.md) converted in [`ggml` format](#ggml-format). For example: + +```bash +sh ./models/download-ggml-model.sh base.en +``` + +Now build the [whisper-cli](examples/cli) example and transcribe an audio file like this: + +```bash +# build the project +cmake -B build +cmake --build build -j --config Release + +# transcribe an audio file +./build/bin/whisper-cli -f samples/jfk.wav +``` + +--- + +For a quick demo, simply run `make base.en`. + +The command downloads the `base.en` model converted to custom `ggml` format and runs the inference on all `.wav` samples in the folder `samples`. + +For detailed usage instructions, run: `./build/bin/whisper-cli -h` + +Note that the [whisper-cli](examples/cli) example currently runs only with 16-bit WAV files, so make sure to convert your input before running the tool. +For example, you can use `ffmpeg` like this: + +```bash +ffmpeg -i input.mp3 -ar 16000 -ac 1 -c:a pcm_s16le output.wav +``` + +## More audio samples + +If you want some extra audio samples to play with, simply run: + +``` +make -j samples +``` + +This will download a few more audio files from Wikipedia and convert them to 16-bit WAV format via `ffmpeg`. + +You can download and run the other models as follows: + +``` +make -j tiny.en +make -j tiny +make -j base.en +make -j base +make -j small.en +make -j small +make -j medium.en +make -j medium +make -j large-v1 +make -j large-v2 +make -j large-v3 +make -j large-v3-turbo +``` + +## Memory usage + +| Model | Disk | Mem | +| ------ | ------- | ------- | +| tiny | 75 MiB | ~273 MB | +| base | 142 MiB | ~388 MB | +| small | 466 MiB | ~852 MB | +| medium | 1.5 GiB | ~2.1 GB | +| large | 2.9 GiB | ~3.9 GB | + +## POWER VSX Intrinsics + +`whisper.cpp` supports POWER architectures and includes code which +significantly speeds operation on Linux running on POWER9/10, making it +capable of faster-than-realtime transcription on underclocked Raptor +Talos II. Ensure you have a BLAS package installed, and replace the +standard cmake setup with: + +```bash +# build with GGML_BLAS defined +cmake -B build -DGGML_BLAS=1 +cmake --build build -j --config Release +./build/bin/whisper-cli [ .. etc .. ] +``` + +## Quantization + +`whisper.cpp` supports integer quantization of the Whisper `ggml` models. +Quantized models require less memory and disk space and depending on the hardware can be processed more efficiently. + +Here are the steps for creating and using a quantized model: + +```bash +# quantize a model with Q5_0 method +cmake -B build +cmake --build build -j --config Release +./build/bin/quantize models/ggml-base.en.bin models/ggml-base.en-q5_0.bin q5_0 + +# run the examples as usual, specifying the quantized model file +./build/bin/whisper-cli -m models/ggml-base.en-q5_0.bin ./samples/gb0.wav +``` + +## Core ML support + +On Apple Silicon devices, the Encoder inference can be executed on the Apple Neural Engine (ANE) via Core ML. This can result in significant +speed-up - more than x3 faster compared with CPU-only execution. Here are the instructions for generating a Core ML model and using it with `whisper.cpp`: + +- Install Python dependencies needed for the creation of the Core ML model: + + ```bash + pip install ane_transformers + pip install openai-whisper + pip install coremltools + ``` + + - To ensure `coremltools` operates correctly, please confirm that [Xcode](https://developer.apple.com/xcode/) is installed and execute `xcode-select --install` to install the command-line tools. + - Python 3.11 is recommended. + - MacOS Sonoma (version 14) or newer is recommended, as older versions of MacOS might experience issues with transcription hallucination. + - [OPTIONAL] It is recommended to utilize a Python version management system, such as [Miniconda](https://docs.conda.io/en/latest/miniconda.html) for this step: + - To create an environment, use: `conda create -n py311-whisper python=3.11 -y` + - To activate the environment, use: `conda activate py311-whisper` + +- Generate a Core ML model. For example, to generate a `base.en` model, use: + + ```bash + ./models/generate-coreml-model.sh base.en + ``` + + This will generate the folder `models/ggml-base.en-encoder.mlmodelc` + +- Build `whisper.cpp` with Core ML support: + + ```bash + # using CMake + cmake -B build -DWHISPER_COREML=1 + cmake --build build -j --config Release + ``` + +- Run the examples as usual. For example: + + ```text + $ ./build/bin/whisper-cli -m models/ggml-base.en.bin -f samples/jfk.wav + + ... + + whisper_init_state: loading Core ML model from 'models/ggml-base.en-encoder.mlmodelc' + whisper_init_state: first run on a device may take a while ... + whisper_init_state: Core ML model loaded + + system_info: n_threads = 4 / 10 | AVX = 0 | AVX2 = 0 | AVX512 = 0 | FMA = 0 | NEON = 1 | ARM_FMA = 1 | F16C = 0 | FP16_VA = 1 | WASM_SIMD = 0 | BLAS = 1 | SSE3 = 0 | VSX = 0 | COREML = 1 | + + ... + ``` + + The first run on a device is slow, since the ANE service compiles the Core ML model to some device-specific format. + Next runs are faster. + +For more information about the Core ML implementation please refer to PR [#566](https://github.com/ggml-org/whisper.cpp/pull/566). + +## OpenVINO support + +On platforms that support [OpenVINO](https://github.com/openvinotoolkit/openvino), the Encoder inference can be executed +on OpenVINO-supported devices including x86 CPUs and Intel GPUs (integrated & discrete). + +This can result in significant speedup in encoder performance. Here are the instructions for generating the OpenVINO model and using it with `whisper.cpp`: + +- First, setup python virtual env. and install python dependencies. Python 3.10 is recommended. + + Windows: + + ```powershell + cd models + python -m venv openvino_conv_env + openvino_conv_env\Scripts\activate + python -m pip install --upgrade pip + pip install -r requirements-openvino.txt + ``` + + Linux and macOS: + + ```bash + cd models + python3 -m venv openvino_conv_env + source openvino_conv_env/bin/activate + python -m pip install --upgrade pip + pip install -r requirements-openvino.txt + ``` + +- Generate an OpenVINO encoder model. For example, to generate a `base.en` model, use: + + ``` + python convert-whisper-to-openvino.py --model base.en + ``` + + This will produce ggml-base.en-encoder-openvino.xml/.bin IR model files. It's recommended to relocate these to the same folder as `ggml` models, as that + is the default location that the OpenVINO extension will search at runtime. + +- Build `whisper.cpp` with OpenVINO support: + + Download OpenVINO package from [release page](https://github.com/openvinotoolkit/openvino/releases). The recommended version to use is [2026.3.0](https://github.com/openvinotoolkit/openvino/releases/tag/2026.3.0). Ready to use Binaries of the required libraries can be found in the [OpenVino Archives](https://storage.openvinotoolkit.org/repositories/openvino/packages/2026.3/) + + After downloading & extracting package onto your development system, set up required environment by sourcing setupvars script. For example: + + Linux: + + ```bash + source /path/to/openvino_toolkit_ubuntu/setupvars.sh + ``` + + Windows (cmd): + + ```powershell + C:\Path\To\openvino_toolkit_windows\setupvars.bat + ``` + + And then build the project using cmake: + + ```bash + cmake -B build -DWHISPER_OPENVINO=1 + cmake --build build -j --config Release + ``` + +- Run the examples as usual. For example: + + ```text + $ ./build/bin/whisper-cli -m models/ggml-base.en.bin -f samples/jfk.wav + + ... + + whisper_ctx_init_openvino_encoder: loading OpenVINO model from 'models/ggml-base.en-encoder-openvino.xml' + whisper_ctx_init_openvino_encoder: first run on a device may take a while ... + whisper_openvino_init: path_model = models/ggml-base.en-encoder-openvino.xml, device = GPU, cache_dir = models/ggml-base.en-encoder-openvino-cache + whisper_ctx_init_openvino_encoder: OpenVINO model loaded + + system_info: n_threads = 4 / 8 | AVX = 1 | AVX2 = 1 | AVX512 = 0 | FMA = 1 | NEON = 0 | ARM_FMA = 0 | F16C = 1 | FP16_VA = 0 | WASM_SIMD = 0 | BLAS = 0 | SSE3 = 1 | VSX = 0 | COREML = 0 | OPENVINO = 1 | + + ... + ``` + + The first time run on an OpenVINO device is slow, since the OpenVINO framework will compile the IR (Intermediate Representation) model to a device-specific 'blob'. This device-specific blob will get + cached for the next run. + +For more information about the OpenVINO implementation please refer to PR [#1037](https://github.com/ggml-org/whisper.cpp/pull/1037). + +## AMD Ryzen™ AI NPU support + +On AMD Ryzen™ AI 300 and 400 Series processors with a dedicated NPU, whisper.cpp can fully offload the Whisper encoder to the NPU via VitisAI, delivering significant speedup over CPU-only inference. + +### Prerequisites + +Supported Platforms + +- **Windows 11** +- **Linux** (Ubuntu 24.04 LTS, Python 3.12) + +Install the XRT runtime and FlexML runtime for your platform: + +- **XRT**: provides the NPU kernel driver and `xrt-smi` diagnostic tool — on Windows this is bundled with the NPU driver; on Linux install it separately following the [NPU driver installation guide](https://ryzenai.docs.amd.com/en/latest/linux.html#install-npu-drivers) +- **FlexML runtime** (`flexmlrt`): VitisAI inference engine used by whisper.cpp — download from the [FlexML runtime releases](https://github.com/lemonade-sdk/whisper.cpp-rocm/releases/tag/deps) + +After installing, source the setup scripts in every shell you use to build or run whisper.cpp: + +```bash +# Linux +source /opt/xilinx/xrt/setup.sh +source /path/to/flexmlrt/setup.sh +``` + +```cmd +:: Windows +cd /path/to/flexmlrt && call setup.bat +``` + +You can verify the NPU is visible with: + +```bash +xrt-smi examine +``` + +### Download models + +Download the ggml model and the matching prebuilt VitisAI encoder cache: + +```bash +# Linux / macOS +sh ./models/download-ggml-model.sh base +sh ./models/download-vitisai-model.sh base +``` + +```cmd +:: Windows +.\models\download-ggml-model.cmd base +.\models\download-vitisai-model.cmd base +``` + +Use the same model name with both scripts. To see all available VitisAI encoder caches: + +```bash +sh ./models/download-vitisai-model.sh --list +``` + +```cmd +.\models\download-vitisai-model.cmd --list +``` + +The VitisAI script queries the [AMD Ryzen AI Whisper NPU collection on Hugging Face](https://huggingface.co/collections/amd/ryzen-ai-whisper-npu-optimized-onnx-models) and downloads the `.rai` encoder cache as `models/ggml-<model>-encoder-vitisai.rai`. + +> Depending on the `.rai` cache, VitisAI may offload the encoder only, or the encoder plus cross-projection layers. whisper.cpp detects this at runtime and logs the selected offload mode during model initialization. + +### Build + +```bash +cmake -B build -DWHISPER_VITISAI=1 +cmake --build build -j --config Release +``` + +### Run + +```bash +./build/bin/whisper-cli -m models/ggml-base.bin -f samples/jfk.wav +``` + +For more information see the [Ryzen AI documentation](https://ryzenai.docs.amd.com/en/latest/). + + +## NVIDIA GPU support + +With NVIDIA cards the processing of the models is done efficiently on the GPU via cuBLAS and custom CUDA kernels. +First, make sure you have installed `cuda`: https://developer.nvidia.com/cuda-downloads + +Now build `whisper.cpp` with CUDA support: + +``` +cmake -B build -DGGML_CUDA=1 +cmake --build build -j --config Release +``` + +or for newer NVIDIA GPU's (RTX 5000 series): +``` +cmake -B build -DGGML_CUDA=1 -DCMAKE_CUDA_ARCHITECTURES="86" +cmake --build build -j --config Release +``` + +## Vulkan GPU support +Cross-vendor solution which allows you to accelerate workload on your GPU. +First, make sure your graphics card driver provides support for Vulkan API. + +Now build `whisper.cpp` with Vulkan support: +``` +cmake -B build -DGGML_VULKAN=1 +cmake --build build -j --config Release +``` + +## AMD ROCm GPU support + +With AMD GPUs the processing can be accelerated via HIP/ROCm. +First, make sure you have installed [ROCm](https://rocm.docs.amd.com/en/latest/). + +Now build `whisper.cpp` with HIP support: + +``` +cmake -B build -DGGML_HIP=1 -DAMDGPU_TARGETS="gfx1201" +cmake --build build -j --config Release +``` + +Replace `gfx1201` with your GPU architecture. You can find it with: + +``` +rocminfo | grep "gfx" +``` + +Common architectures: `gfx1100` (RX 7900 XTX), `gfx1101` (RX 7800 XT), `gfx1201` (RX 9070 XT). +For multiple GPUs with different architectures: `-DAMDGPU_TARGETS="gfx1100;gfx1201"`. + +## BLAS CPU support via OpenBLAS + +Encoder processing can be accelerated on the CPU via OpenBLAS. +First, make sure you have installed `openblas`: https://www.openblas.net/ + +Now build `whisper.cpp` with OpenBLAS support: + +``` +cmake -B build -DGGML_BLAS=1 +cmake --build build -j --config Release +``` + +## Ascend NPU support + +Ascend NPU provides inference acceleration via [`CANN`](https://www.hiascend.com/en/software/cann) and AI cores. + +First, check if your Ascend NPU device is supported: + +**Verified devices** +| Ascend NPU | Status | +|:-----------------------------:|:-------:| +| Atlas 300T A2 | Support | +| Atlas 300I Duo | Support | + +Then, make sure you have installed [`CANN toolkit`](https://www.hiascend.com/en/software/cann/community) . The latest version of CANN is recommended. + +Now build `whisper.cpp` with CANN support: + +``` +cmake -B build -DGGML_CANN=1 +cmake --build build -j --config Release +``` + +Run the inference examples as usual, for example: + +``` +./build/bin/whisper-cli -f samples/jfk.wav -m models/ggml-base.en.bin -t 8 +``` + +*Notes:* + +- If you have trouble with Ascend NPU device, please create a issue with **[CANN]** prefix/tag. +- If you run successfully with your Ascend NPU device, please help update the table `Verified devices`. + +## Moore Threads GPU support + +With Moore Threads cards the processing of the models is done efficiently on the GPU via muBLAS and custom MUSA kernels. +First, make sure you have installed `MUSA SDK rc4.2.0`: https://developer.mthreads.com/sdk/download/musa?equipment=&os=&driverVersion=&version=4.2.0 + +Now build `whisper.cpp` with MUSA support: + +``` +cmake -B build -DGGML_MUSA=1 +cmake --build build -j --config Release +``` + +or specify the architecture for your Moore Threads GPU. For example, if you have a MTT S80 GPU, you can specify the architecture as follows: + +``` +cmake -B build -DGGML_MUSA=1 -DMUSA_ARCHITECTURES="21" +cmake --build build -j --config Release +``` + +## FFmpeg support (examples only) + +By default, the examples in this repo use the [miniaudio](https://github.com/mackron/miniaudio) library to decode audio files. +Some of the examples also can use FFmpeg for decoding and broader format support. To enable that, build with `WHISPER_COMMON_FFMPEG`. + +First, you need to install required libraries: + +```bash +# Debian/Ubuntu +sudo apt install libavcodec-dev libavformat-dev libavutil-dev + +# RHEL/Fedora +sudo dnf install libavcodec-free-devel libavformat-free-devel libavutil-free-devel +``` + +Then you can build the project as follows: + +```bash +cmake -B build -D WHISPER_COMMON_FFMPEG=yes +cmake --build build +``` + +Run the following example to confirm it's working: + +```bash +# Convert an audio file to Opus format +ffmpeg -i samples/jfk.wav jfk.opus + +# Transcribe the audio file +./build/bin/whisper-cli --model models/ggml-base.en.bin --file jfk.opus +``` + +## Docker + +### Prerequisites + +- Docker must be installed and running on your system. +- Create a folder to store big models & intermediate files (ex. /whisper/models) + +### Images + +We have multiple Docker images available for this project: + +1. `ghcr.io/ggml-org/whisper.cpp:main`: This image includes the main executable file as well as `curl` and `ffmpeg`. (platforms: `linux/amd64`, `linux/arm64`) +2. `ghcr.io/ggml-org/whisper.cpp:main-cuda`: Same as `main` but compiled with CUDA support. (platforms: `linux/amd64`) +3. `ghcr.io/ggml-org/whisper.cpp:main-musa`: Same as `main` but compiled with MUSA support. (platforms: `linux/amd64`) +4. `ghcr.io/ggml-org/whisper.cpp:main-vulkan`: Same as `main` but compiled with Vulkan support. (platforms: `linux/amd64`) + +### Usage + +```shell +# download model and persist it in a local folder +docker run -it --rm \ + -v path/to/models:/models \ + whisper.cpp:main "./models/download-ggml-model.sh base /models" + +# transcribe an audio file +docker run -it --rm \ + -v path/to/models:/models \ + -v path/to/audios:/audios \ + whisper.cpp:main "whisper-cli -m /models/ggml-base.bin -f /audios/jfk.wav" + +# transcribe an audio file in samples folder +docker run -it --rm \ + -v path/to/models:/models \ + whisper.cpp:main "whisper-cli -m /models/ggml-base.bin -f ./samples/jfk.wav" + +# run the web server +docker run -it --rm -p "8080:8080" \ + -v path/to/models:/models \ + whisper.cpp:main "whisper-server --host 127.0.0.1 -m /models/ggml-base.bin" + +# run the bench too on the small.en model using 4 threads +docker run -it --rm \ + -v path/to/models:/models \ + whisper.cpp:main "whisper-bench -m /models/ggml-small.en.bin -t 4" +``` + +## Installing with Conan + +You can install pre-built binaries for whisper.cpp or build it from source using [Conan](https://conan.io/). Use the following command: + +``` +conan install --requires="whisper-cpp/[*]" --build=missing +``` + +For detailed instructions on how to use Conan, please refer to the [Conan documentation](https://docs.conan.io/2/). + +## Limitations + +- Inference only + +## Real-time audio input example + +This is a naive example of performing real-time inference on audio from your microphone. +The [stream](examples/stream) tool samples the audio every half a second and runs the transcription continuously. +More info is available in [issue #10](https://github.com/ggml-org/whisper.cpp/issues/10). +You will need to have [sdl2](https://wiki.libsdl.org/SDL2/Installation) installed for it to work properly. + +```bash +cmake -B build -DWHISPER_SDL2=ON +cmake --build build -j --config Release +./build/bin/whisper-stream -m ./models/ggml-base.en.bin -t 8 --step 500 --length 5000 +``` + +https://user-images.githubusercontent.com/1991296/194935793-76afede7-cfa8-48d8-a80f-28ba83be7d09.mp4 + +## Confidence color-coding + +Adding the `--print-colors` argument will print the transcribed text using an experimental color coding strategy +to highlight words with high or low confidence: + +```bash +./build/bin/whisper-cli -m models/ggml-base.en.bin -f samples/gb0.wav --print-colors +``` + +<img width="965" alt="image" src="https://user-images.githubusercontent.com/1991296/197356445-311c8643-9397-4e5e-b46e-0b4b4daa2530.png"> + +## Controlling the length of the generated text segments (experimental) + +For example, to limit the line length to a maximum of 16 characters, simply add `-ml 16`: + +```text +$ ./build/bin/whisper-cli -m ./models/ggml-base.en.bin -f ./samples/jfk.wav -ml 16 + +whisper_model_load: loading model from './models/ggml-base.en.bin' +... +system_info: n_threads = 4 / 10 | AVX2 = 0 | AVX512 = 0 | NEON = 1 | FP16_VA = 1 | WASM_SIMD = 0 | BLAS = 1 | + +main: processing './samples/jfk.wav' (176000 samples, 11.0 sec), 4 threads, 1 processors, lang = en, task = transcribe, timestamps = 1 ... + +[00:00:00.000 --> 00:00:00.850] And so my +[00:00:00.850 --> 00:00:01.590] fellow +[00:00:01.590 --> 00:00:04.140] Americans, ask +[00:00:04.140 --> 00:00:05.660] not what your +[00:00:05.660 --> 00:00:06.840] country can do +[00:00:06.840 --> 00:00:08.430] for you, ask +[00:00:08.430 --> 00:00:09.440] what you can do +[00:00:09.440 --> 00:00:10.020] for your +[00:00:10.020 --> 00:00:11.000] country. +``` + +## Word-level timestamp (experimental) + +The `--max-len` argument can be used to obtain word-level timestamps. Simply use `-ml 1`: + +```text +$ ./build/bin/whisper-cli -m ./models/ggml-base.en.bin -f ./samples/jfk.wav -ml 1 + +whisper_model_load: loading model from './models/ggml-base.en.bin' +... +system_info: n_threads = 4 / 10 | AVX2 = 0 | AVX512 = 0 | NEON = 1 | FP16_VA = 1 | WASM_SIMD = 0 | BLAS = 1 | + +main: processing './samples/jfk.wav' (176000 samples, 11.0 sec), 4 threads, 1 processors, lang = en, task = transcribe, timestamps = 1 ... + +[00:00:00.000 --> 00:00:00.320] +[00:00:00.320 --> 00:00:00.370] And +[00:00:00.370 --> 00:00:00.690] so +[00:00:00.690 --> 00:00:00.850] my +[00:00:00.850 --> 00:00:01.590] fellow +[00:00:01.590 --> 00:00:02.850] Americans +[00:00:02.850 --> 00:00:03.300] , +[00:00:03.300 --> 00:00:04.140] ask +[00:00:04.140 --> 00:00:04.990] not +[00:00:04.990 --> 00:00:05.410] what +[00:00:05.410 --> 00:00:05.660] your +[00:00:05.660 --> 00:00:06.260] country +[00:00:06.260 --> 00:00:06.600] can +[00:00:06.600 --> 00:00:06.840] do +[00:00:06.840 --> 00:00:07.010] for +[00:00:07.010 --> 00:00:08.170] you +[00:00:08.170 --> 00:00:08.190] , +[00:00:08.190 --> 00:00:08.430] ask +[00:00:08.430 --> 00:00:08.910] what +[00:00:08.910 --> 00:00:09.040] you +[00:00:09.040 --> 00:00:09.320] can +[00:00:09.320 --> 00:00:09.440] do +[00:00:09.440 --> 00:00:09.760] for +[00:00:09.760 --> 00:00:10.020] your +[00:00:10.020 --> 00:00:10.510] country +[00:00:10.510 --> 00:00:11.000] . +``` + +## Speaker segmentation via tinydiarize (experimental) + +More information about this approach is available here: https://github.com/ggml-org/whisper.cpp/pull/1058 + +Sample usage: + +```py +# download a tinydiarize compatible model +./models/download-ggml-model.sh small.en-tdrz + +# run as usual, adding the "-tdrz" command-line argument +./build/bin/whisper-cli -f ./samples/a13.wav -m ./models/ggml-small.en-tdrz.bin -tdrz +... +main: processing './samples/a13.wav' (480000 samples, 30.0 sec), 4 threads, 1 processors, lang = en, task = transcribe, tdrz = 1, timestamps = 1 ... +... +[00:00:00.000 --> 00:00:03.800] Okay Houston, we've had a problem here. [SPEAKER_TURN] +[00:00:03.800 --> 00:00:06.200] This is Houston. Say again please. [SPEAKER_TURN] +[00:00:06.200 --> 00:00:08.260] Uh Houston we've had a problem. +[00:00:08.260 --> 00:00:11.320] We've had a main beam up on a volt. [SPEAKER_TURN] +[00:00:11.320 --> 00:00:13.820] Roger main beam interval. [SPEAKER_TURN] +[00:00:13.820 --> 00:00:15.100] Uh uh [SPEAKER_TURN] +[00:00:15.100 --> 00:00:18.020] So okay stand, by thirteen we're looking at it. [SPEAKER_TURN] +[00:00:18.020 --> 00:00:25.740] Okay uh right now uh Houston the uh voltage is uh is looking good um. +[00:00:27.620 --> 00:00:29.940] And we had a a pretty large bank or so. +``` + +## Karaoke-style movie generation (experimental) + +The [whisper-cli](examples/cli) example provides support for output of karaoke-style movies, where the +currently pronounced word is highlighted. Use the `-owts` argument and run the generated bash script. +This requires to have `ffmpeg` installed. + +Here are a few _"typical"_ examples: + +```bash +./build/bin/whisper-cli -m ./models/ggml-base.en.bin -f ./samples/jfk.wav -owts +source ./samples/jfk.wav.wts +ffplay ./samples/jfk.wav.mp4 +``` + +https://user-images.githubusercontent.com/1991296/199337465-dbee4b5e-9aeb-48a3-b1c6-323ac4db5b2c.mp4 + +--- + +```bash +./build/bin/whisper-cli -m ./models/ggml-base.en.bin -f ./samples/mm0.wav -owts +source ./samples/mm0.wav.wts +ffplay ./samples/mm0.wav.mp4 +``` + +https://user-images.githubusercontent.com/1991296/199337504-cc8fd233-0cb7-4920-95f9-4227de3570aa.mp4 + +--- + +```bash +./build/bin/whisper-cli -m ./models/ggml-base.en.bin -f ./samples/gb0.wav -owts +source ./samples/gb0.wav.wts +ffplay ./samples/gb0.wav.mp4 +``` + +https://user-images.githubusercontent.com/1991296/199337538-b7b0c7a3-2753-4a88-a0cd-f28a317987ba.mp4 + +--- + +## Video comparison of different models + +Use the [scripts/bench-wts.sh](https://github.com/ggml-org/whisper.cpp/blob/master/scripts/bench-wts.sh) script to generate a video in the following format: + +```bash +./scripts/bench-wts.sh samples/jfk.wav +ffplay ./samples/jfk.wav.all.mp4 +``` + +https://user-images.githubusercontent.com/1991296/223206245-2d36d903-cf8e-4f09-8c3b-eb9f9c39d6fc.mp4 + +--- + +## Benchmarks + +In order to have an objective comparison of the performance of the inference across different system configurations, +use the [whisper-bench](examples/bench) tool. The tool simply runs the Encoder part of the model and prints how much time it +took to execute it. The results are summarized in the following Github issue: + +[Benchmark results](https://github.com/ggml-org/whisper.cpp/issues/89) + +Additionally a script to run whisper.cpp with different models and audio files is provided [bench.py](scripts/bench.py). + +You can run it with the following command, by default it will run against any standard model in the models folder. + +```bash +python3 scripts/bench.py -f samples/jfk.wav -t 2,4,8 -p 1,2 +``` + +It is written in python with the intention of being easy to modify and extend for your benchmarking use case. + +It outputs a csv file with the results of the benchmarking. + +## `ggml` format + +The original models are converted to a custom binary format. This allows to pack everything needed into a single file: + +- model parameters +- mel filters +- vocabulary +- weights + +You can download the converted models using the [models/download-ggml-model.sh](models/download-ggml-model.sh) script +or manually from here: + +- https://huggingface.co/ggerganov/whisper.cpp + +For more details, see the conversion script [models/convert-pt-to-ggml.py](models/convert-pt-to-ggml.py) or [models/README.md](models/README.md). + +## [Bindings](https://github.com/ggml-org/whisper.cpp/discussions/categories/bindings) + +- [x] Rust: [tazz4843/whisper-rs](https://github.com/tazz4843/whisper-rs) | [#310](https://github.com/ggml-org/whisper.cpp/discussions/310) +- [x] JavaScript: [bindings/javascript](bindings/javascript) | [#309](https://github.com/ggml-org/whisper.cpp/discussions/309) + - React Native (iOS / Android): [whisper.rn](https://github.com/mybigday/whisper.rn) +- [x] Go: [bindings/go](bindings/go) | [#312](https://github.com/ggml-org/whisper.cpp/discussions/312) +- [x] Java: + - [GiviMAD/whisper-jni](https://github.com/GiviMAD/whisper-jni) +- [x] Ruby: [bindings/ruby](bindings/ruby) | [#507](https://github.com/ggml-org/whisper.cpp/discussions/507) +- [x] Objective-C / Swift: [ggml-org/whisper.spm](https://github.com/ggml-org/whisper.spm) | [#313](https://github.com/ggml-org/whisper.cpp/discussions/313) + - [exPHAT/SwiftWhisper](https://github.com/exPHAT/SwiftWhisper) +- [x] .NET: | [#422](https://github.com/ggml-org/whisper.cpp/discussions/422) + - [sandrohanea/whisper.net](https://github.com/sandrohanea/whisper.net) + - [NickDarvey/whisper](https://github.com/NickDarvey/whisper) +- [x] Python: | [#9](https://github.com/ggml-org/whisper.cpp/issues/9) + - [stlukey/whispercpp.py](https://github.com/stlukey/whispercpp.py) (Cython) + - [AIWintermuteAI/whispercpp](https://github.com/AIWintermuteAI/whispercpp) (Updated fork of aarnphm/whispercpp) + - [aarnphm/whispercpp](https://github.com/aarnphm/whispercpp) (Pybind11) + - [abdeladim-s/pywhispercpp](https://github.com/abdeladim-s/pywhispercpp) (Pybind11) +- [x] R: [bnosac/audio.whisper](https://github.com/bnosac/audio.whisper) +- [x] Unity: [macoron/whisper.unity](https://github.com/Macoron/whisper.unity) + +## XCFramework +The XCFramework is a precompiled version of the library for iOS, visionOS, tvOS, +and macOS. It can be used in Swift projects without the need to compile the +library from source. For example, the v1.7.5 version of the XCFramework can be +used as follows: + +```swift +// swift-tools-version: 5.10 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "Whisper", + targets: [ + .executableTarget( + name: "Whisper", + dependencies: [ + "WhisperFramework" + ]), + .binaryTarget( + name: "WhisperFramework", + url: "https://github.com/ggml-org/whisper.cpp/releases/download/v1.7.5/whisper-v1.7.5-xcframework.zip", + checksum: "c7faeb328620d6012e130f3d705c51a6ea6c995605f2df50f6e1ad68c59c6c4a" + ) + ] +) +``` + +## Voice Activity Detection (VAD) +Support for Voice Activity Detection (VAD) can be enabled using the `--vad` +argument to `whisper-cli`. In addition to this option a VAD model is also +required. + +The way this works is that first the audio samples are passed through +the VAD model which will detect speech segments. Using this information, +only the speech segments that are detected are extracted from the original audio +input and passed to whisper for processing. This reduces the amount of audio +data that needs to be processed by whisper and can significantly speed up the +transcription process. + +The following VAD models are currently supported: + +### Silero-VAD +[Silero-vad](https://github.com/snakers4/silero-vad) is a lightweight VAD model +written in Python that is fast and accurate. + +Models can be downloaded by running the following command on Linux or MacOS: +```console +$ ./models/download-vad-model.sh silero-v6.2.0 +Downloading ggml model silero-v6.2.0 from 'https://huggingface.co/ggml-org/whisper-vad' ... +ggml-silero-v6.2.0.bin 100%[==============================================>] 864.35K --.-KB/s in 0.04s +Done! Model 'silero-v6.2.0' saved in '/path/models/ggml-silero-v6.2.0.bin' +You can now use it like this: + + $ ./build/bin/whisper-cli -vm /path/models/ggml-silero-v6.2.0.bin --vad -f samples/jfk.wav -m models/ggml-base.en.bin + +``` +And the following command on Windows: +```console +> .\models\download-vad-model.cmd silero-v6.2.0 +Downloading vad model silero-v6.2.0... +Done! Model silero-v6.2.0 saved in C:\Users\danie\work\ai\whisper.cpp\ggml-silero-v6.2.0.bin +You can now use it like this: + +C:\path\build\bin\Release\whisper-cli.exe -vm C:\path\ggml-silero-v6.2.0.bin --vad -m models/ggml-base.en.bin -f samples\jfk.wav + +``` + +To see a list of all available models, run the above commands without any +arguments. + +This model can be also be converted manually to ggml using the following command: +```console +$ python3 -m venv venv && source venv/bin/activate +$ (venv) pip install silero-vad +$ (venv) $ python models/convert-silero-vad-to-ggml.py --output models/silero.bin +Saving GGML Silero-VAD model to models/silero-v6.2.0-ggml.bin +``` +And it can then be used with whisper as follows: +```console +$ ./build/bin/whisper-cli \ + --file ./samples/jfk.wav \ + --model ./models/ggml-base.en.bin \ + --vad \ + --vad-model ./models/silero-v6.2.0-ggml.bin +``` + +### VAD Options + +* --vad-threshold: Threshold probability for speech detection. A probability +for a speech segment/frame above this threshold will be considered as speech. + +* --vad-min-speech-duration-ms: Minimum speech duration in milliseconds. Speech +segments shorter than this value will be discarded to filter out brief noise or +false positives. + +* --vad-min-silence-duration-ms: Minimum silence duration in milliseconds. Silence +periods must be at least this long to end a speech segment. Shorter silence +periods will be ignored and included as part of the speech. + +* --vad-max-speech-duration-s: Maximum speech duration in seconds. Speech segments +longer than this will be automatically split into multiple segments at silence +points exceeding 98ms to prevent excessively long segments. + +* --vad-speech-pad-ms: Speech padding in milliseconds. Adds this amount of padding +before and after each detected speech segment to avoid cutting off speech edges. + +* --vad-samples-overlap: Amount of audio to extend from each speech segment into +the next one, in seconds (e.g., 0.10 = 100ms overlap). This ensures speech isn't +cut off abruptly between segments when they're concatenated together. + +## Examples + +There are various examples of using the library for different projects in the [examples](examples) folder. +Some of the examples are even ported to run in the browser using WebAssembly. Check them out! + +| Example | Web | Description | +| --------------------------------------------------- | ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | +| [whisper-cli](examples/cli) | [whisper.wasm](examples/whisper.wasm) | Tool for translating and transcribing audio using Whisper | +| [whisper-bench](examples/bench) | [bench.wasm](examples/bench.wasm) | Benchmark the performance of Whisper on your machine | +| [whisper-stream](examples/stream) | [stream.wasm](examples/stream.wasm) | Real-time transcription of raw microphone capture | +| [whisper-command](examples/command) | [command.wasm](examples/command.wasm) | Basic voice assistant example for receiving voice commands from the mic | +| [whisper-server](examples/server) | | HTTP transcription server with OAI-like API | +| [whisper-talk-llama](examples/talk-llama) | | Talk with a LLaMA bot | +| [whisper.objc](examples/whisper.objc) | | iOS mobile application using whisper.cpp | +| [whisper.swiftui](examples/whisper.swiftui) | | SwiftUI iOS / macOS application using whisper.cpp | +| [whisper.android](examples/whisper.android) | | Android mobile application using whisper.cpp | +| [whisper.nvim](examples/whisper.nvim) | | Speech-to-text plugin for Neovim | +| [generate-karaoke.sh](examples/generate-karaoke.sh) | | Helper script to easily [generate a karaoke video](https://youtu.be/uj7hVta4blM) of raw audio capture | +| [livestream.sh](examples/livestream.sh) | | [Livestream audio transcription](https://github.com/ggml-org/whisper.cpp/issues/185) | +| [yt-wsp.sh](examples/yt-wsp.sh) | | Download + transcribe and/or translate any VOD [(original)](https://gist.github.com/DaniruKun/96f763ec1a037cc92fe1a059b643b818) | +| [wchess](examples/wchess) | [wchess.wasm](examples/wchess) | Voice-controlled chess | + +## [Discussions](https://github.com/ggml-org/whisper.cpp/discussions) + +If you have any kind of feedback about this project feel free to use the Discussions section and open a new topic. +You can use the [Show and tell](https://github.com/ggml-org/whisper.cpp/discussions/categories/show-and-tell) category +to share your own projects that use `whisper.cpp`. If you have a question, make sure to check the +[Frequently asked questions (#126)](https://github.com/ggml-org/whisper.cpp/discussions/126) discussion. diff --git a/README_sycl.md b/README_sycl.md new file mode 100644 index 0000000..2d31d28 --- /dev/null +++ b/README_sycl.md @@ -0,0 +1,249 @@ +# whisper.cpp for SYCL + +[Background](#background) + +[OS](#os) + +[Intel GPU](#intel-gpu) + +[Linux](#linux) + +[Environment Variable](#environment-variable) + +[Known Issue](#known-issue) + +[Todo](#todo) + +## Background + +SYCL is a higher-level programming model to improve programming productivity on various hardware accelerators—such as CPUs, GPUs, and FPGAs. It is a single-source embedded domain-specific language based on pure C++17. + +oneAPI is a specification that is open and standards-based, supporting multiple architecture types including but not limited to GPU, CPU, and FPGA. The spec has both direct programming and API-based programming paradigms. + +Intel uses the SYCL as direct programming language to support CPU, GPUs and FPGAs. + +To avoid re-inventing the wheel, this code refers other code paths in llama.cpp (like OpenBLAS, cuBLAS, CLBlast). We use a open-source tool [SYCLomatic](https://github.com/oneapi-src/SYCLomatic) (Commercial release [Intel® DPC++ Compatibility Tool](https://www.intel.com/content/www/us/en/developer/tools/oneapi/dpc-compatibility-tool.html)) migrate to SYCL. + +The whisper.cpp for SYCL is used to support Intel GPUs. + +For Intel CPU, recommend to use whisper.cpp for X86 (Intel MKL build). + +## OS + +|OS|Status|Verified| +|-|-|-| +|Linux|Support|Ubuntu 22.04| +|Windows|Ongoing| | + + +## Intel GPU + +|Intel GPU| Status | Verified Model| +|-|-|-| +|Intel Data Center Max Series| Support| Max 1550| +|Intel Data Center Flex Series| Support| Flex 170| +|Intel Arc Series| Support| Arc 770| +|Intel built-in Arc GPU| Support| built-in Arc GPU in Meteor Lake| +|Intel iGPU| Support| iGPU in i5-1250P, i7-1165G7| + + +## Linux + +### Setup Environment + +1. Install Intel GPU driver. + +a. Please install Intel GPU driver by official guide: [Install GPU Drivers](https://dgpu-docs.intel.com/driver/installation.html). + +Note: for iGPU, please install the client GPU driver. + +b. Add user to group: video, render. + +``` +sudo usermod -aG render username +sudo usermod -aG video username +``` + +Note: re-login to enable it. + +c. Check + +``` +sudo apt install clinfo +sudo clinfo -l +``` + +Output (example): + +``` +Platform #0: Intel(R) OpenCL Graphics + `-- Device #0: Intel(R) Arc(TM) A770 Graphics + + +Platform #0: Intel(R) OpenCL HD Graphics + `-- Device #0: Intel(R) Iris(R) Xe Graphics [0x9a49] +``` + +2. Install Intel® oneAPI Base toolkit. + + +a. Please follow the procedure in [Get the Intel® oneAPI Base Toolkit ](https://www.intel.com/content/www/us/en/developer/tools/oneapi/base-toolkit.html). + +Recommend to install to default folder: **/opt/intel/oneapi**. + +Following guide use the default folder as example. If you use other folder, please modify the following guide info with your folder. + +b. Check + +``` +source /opt/intel/oneapi/setvars.sh + +sycl-ls +``` + +There should be one or more level-zero devices. Like **[ext_oneapi_level_zero:gpu:0]**. + +Output (example): +``` +[opencl:acc:0] Intel(R) FPGA Emulation Platform for OpenCL(TM), Intel(R) FPGA Emulation Device OpenCL 1.2 [2023.16.10.0.17_160000] +[opencl:cpu:1] Intel(R) OpenCL, 13th Gen Intel(R) Core(TM) i7-13700K OpenCL 3.0 (Build 0) [2023.16.10.0.17_160000] +[opencl:gpu:2] Intel(R) OpenCL Graphics, Intel(R) Arc(TM) A770 Graphics OpenCL 3.0 NEO [23.30.26918.50] +[ext_oneapi_level_zero:gpu:0] Intel(R) Level-Zero, Intel(R) Arc(TM) A770 Graphics 1.3 [1.3.26918] + +``` + +2. Build locally: + +``` +mkdir -p build +cd build +source /opt/intel/oneapi/setvars.sh + +#for FP16 +#cmake .. -DWHISPER_SYCL=ON -DCMAKE_C_COMPILER=icx -DCMAKE_CXX_COMPILER=icpx -DWHISPER_SYCL_F16=ON + +#for FP32 +cmake .. -DWHISPER_SYCL=ON -DCMAKE_C_COMPILER=icx -DCMAKE_CXX_COMPILER=icpx + +#build example/main only +#cmake --build . --config Release --target main + +#build all binary +cmake --build . --config Release -v + +``` + +or + +``` +./examples/sycl/build.sh +``` + +Note: + +- By default, it will build for all binary files. It will take more time. To reduce the time, we recommend to build for **example/main** only. + +### Run + +1. Put model file to folder **models** + +2. Enable oneAPI running environment + +``` +source /opt/intel/oneapi/setvars.sh +``` + +3. List device ID + +Run without parameter: + +``` +./build/bin/ls-sycl-device + +or + +./build/bin/main +``` + +Check the ID in startup log, like: + +``` +found 4 SYCL devices: + Device 0: Intel(R) Arc(TM) A770 Graphics, compute capability 1.3, + max compute_units 512, max work group size 1024, max sub group size 32, global mem size 16225243136 + Device 1: Intel(R) FPGA Emulation Device, compute capability 1.2, + max compute_units 24, max work group size 67108864, max sub group size 64, global mem size 67065057280 + Device 2: 13th Gen Intel(R) Core(TM) i7-13700K, compute capability 3.0, + max compute_units 24, max work group size 8192, max sub group size 64, global mem size 67065057280 + Device 3: Intel(R) Arc(TM) A770 Graphics, compute capability 3.0, + max compute_units 512, max work group size 1024, max sub group size 32, global mem size 16225243136 + +``` + +|Attribute|Note| +|-|-| +|compute capability 1.3|Level-zero running time, recommended | +|compute capability 3.0|OpenCL running time, slower than level-zero in most cases| + +4. Set device ID and execute whisper.cpp + +Set device ID = 0 by **GGML_SYCL_DEVICE=0** + +``` +GGML_SYCL_DEVICE=0 ./build/bin/main -m models/ggml-base.en.bin -f samples/jfk.wav +``` +or run by script: + +``` +./examples/sycl/run_whisper.sh +``` + + + +5. Check the device ID in output + +Like: +``` +Using device **0** (Intel(R) Arc(TM) A770 Graphics) as main device +``` + + +## Environment Variable + +#### Build + +|Name|Value|Function| +|-|-|-| +|WHISPER_SYCL|ON (mandatory)|Enable build with SYCL code path. <br>For FP32/FP16, WHISPER_SYCL=ON is mandatory.| +|WHISPER_SYCL_F16|ON (optional)|Enable FP16 build with SYCL code path.For FP32, do not set it.| +|CMAKE_C_COMPILER|icx|Use icx compiler for SYCL code path| +|CMAKE_CXX_COMPILER|icpx|use icpx for SYCL code path| + +#### Running + + +|Name|Value|Function| +|-|-|-| +|GGML_SYCL_DEVICE|0 (default) or 1|Set the device id used. Check the device ids by default running output| +|GGML_SYCL_DEBUG|0 (default) or 1|Enable log function by macro: GGML_SYCL_DEBUG| + +## Known Issue + +- Error: `error while loading shared libraries: libsycl.so.7: cannot open shared object file: No such file or directory`. + + Miss to enable oneAPI running environment. + + Install oneAPI base toolkit and enable it by: `source /opt/intel/oneapi/setvars.sh`. + + +- Hang during startup + + llama.cpp use mmap as default way to read model file and copy to GPU. In some system, memcpy will be abnormal and block. + + Solution: add **--no-mmap**. + +## Todo + +- Support to build in Windows. + +- Support multiple cards. diff --git a/bindings/CMakeLists.txt b/bindings/CMakeLists.txt new file mode 100644 index 0000000..af79c51 --- /dev/null +++ b/bindings/CMakeLists.txt @@ -0,0 +1,19 @@ +if (EMSCRIPTEN) + add_subdirectory(javascript) + + add_custom_command( + OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/javascript/publish.log + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/javascript/whisper.js + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/javascript/libwhisper.worker.js + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/javascript/package.json + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/javascript + COMMAND npm publish + COMMAND touch publish.log + COMMENT "Publishing npm module v${PROJECT_VERSION}" + VERBATIM + ) + + add_custom_target(publish-npm + DEPENDS javascript/publish.log + ) +endif() diff --git a/bindings/go/.gitignore b/bindings/go/.gitignore new file mode 100644 index 0000000..036df1d --- /dev/null +++ b/bindings/go/.gitignore @@ -0,0 +1,2 @@ +build +models diff --git a/bindings/go/LICENSE b/bindings/go/LICENSE new file mode 100644 index 0000000..a8f0d7b --- /dev/null +++ b/bindings/go/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 David Thorpe + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/bindings/go/Makefile b/bindings/go/Makefile new file mode 100644 index 0000000..e4436a6 --- /dev/null +++ b/bindings/go/Makefile @@ -0,0 +1,72 @@ +ifndef UNAME_S +UNAME_S := $(shell uname -s) +endif + +ifndef UNAME_P +UNAME_P := $(shell uname -p) +endif + +ifndef UNAME_M +UNAME_M := $(shell uname -m) +endif + +GGML_METAL_PATH_RESOURCES := $(abspath ../..) +BUILD_DIR := build_go +MODELS_DIR := models +EXAMPLES_DIR := $(wildcard examples/*) +INCLUDE_PATH := $(abspath ../../include):$(abspath ../../ggml/include) +LIBRARY_PATH := $(abspath ../../${BUILD_DIR}/src):$(abspath ../../${BUILD_DIR}/ggml/src) + +ifeq ($(GGML_CUDA),1) + LIBRARY_PATH := $(LIBRARY_PATH):$(CUDA_PATH)/targets/$(UNAME_M)-linux/lib/ + BUILD_FLAGS := -ldflags "-extldflags '-lcudart -lcuda -lcublas'" +endif + +ifeq ($(UNAME_S),Darwin) + LIBRARY_PATH := $(LIBRARY_PATH):$(abspath ../../${BUILD_DIR}/ggml/src/ggml-blas):$(abspath ../../${BUILD_DIR}/ggml/src/ggml-metal) + EXT_LDFLAGS := -framework Foundation -framework Metal -framework MetalKit -lggml-metal -lggml-blas +endif + +all: clean whisper examples + +whisper: mkdir + cmake -S ../.. -B ../../${BUILD_DIR} \ + -DCMAKE_BUILD_TYPE=Release \ + -DBUILD_SHARED_LIBS=OFF + cmake --build ../../${BUILD_DIR} --target whisper + +test: model-small whisper modtidy +ifeq ($(UNAME_S),Darwin) + @C_INCLUDE_PATH=${INCLUDE_PATH} LIBRARY_PATH=${LIBRARY_PATH} GGML_METAL_PATH_RESOURCES=${GGML_METAL_PATH_RESOURCES} go test -ldflags "-extldflags '$(EXT_LDFLAGS)'" -v . + @C_INCLUDE_PATH=${INCLUDE_PATH} LIBRARY_PATH=${LIBRARY_PATH} GGML_METAL_PATH_RESOURCES=${GGML_METAL_PATH_RESOURCES} go test -ldflags "-extldflags '$(EXT_LDFLAGS)'" -v ./pkg/whisper/... +else + @C_INCLUDE_PATH=${INCLUDE_PATH} LIBRARY_PATH=${LIBRARY_PATH} go test -v . + @C_INCLUDE_PATH=${INCLUDE_PATH} LIBRARY_PATH=${LIBRARY_PATH} go test -v ./pkg/whisper/... +endif + +examples: $(EXAMPLES_DIR) + +model-small: mkdir examples/go-model-download + @${BUILD_DIR}/go-model-download -out models ggml-small.en.bin + +$(EXAMPLES_DIR): mkdir whisper modtidy + @echo Build example $(notdir $@) +ifeq ($(UNAME_S),Darwin) + @C_INCLUDE_PATH=${INCLUDE_PATH} LIBRARY_PATH=${LIBRARY_PATH} GGML_METAL_PATH_RESOURCES=${GGML_METAL_PATH_RESOURCES} go build ${BUILD_FLAGS} -ldflags "-extldflags '$(EXT_LDFLAGS)'" -o ${BUILD_DIR}/$(notdir $@) ./$@ +else + @C_INCLUDE_PATH=${INCLUDE_PATH} LIBRARY_PATH=${LIBRARY_PATH} go build ${BUILD_FLAGS} -o ${BUILD_DIR}/$(notdir $@) ./$@ +endif + +mkdir: + @echo Mkdir ${BUILD_DIR} + @install -d ${BUILD_DIR} + @echo Mkdir ${MODELS_DIR} + @install -d ${MODELS_DIR} + +modtidy: + @go mod tidy + +clean: + @echo Clean + @rm -fr $(BUILD_DIR) + @go clean diff --git a/bindings/go/README.md b/bindings/go/README.md new file mode 100644 index 0000000..9d83209 --- /dev/null +++ b/bindings/go/README.md @@ -0,0 +1,106 @@ +# Go bindings for Whisper + +This package provides Go bindings for whisper.cpp. They have been tested on: + + * Darwin (OS X) 12.6 on x64_64 + * Debian Linux on arm64 + * Fedora Linux on x86_64 + +The "low level" bindings are in the `bindings/go` directory and there is a more +Go-style package in the `bindings/go/pkg/whisper` directory. The most simple usage +is as follows: + +```go +import ( + "github.com/ggerganov/whisper.cpp/bindings/go/pkg/whisper" +) + +func main() { + var modelpath string // Path to the model + var samples []float32 // Samples to process + + // Load the model + model, err := whisper.New(modelpath) + if err != nil { + panic(err) + } + defer model.Close() + + // Process samples + context, err := model.NewContext() + if err != nil { + panic(err) + } + if err := context.Process(samples, nil, nil, nil); err != nil { + return err + } + + // Print out the results + for { + segment, err := context.NextSegment() + if err != nil { + break + } + fmt.Printf("[%6s->%6s] %s\n", segment.Start, segment.End, segment.Text) + } +} +``` + +## Building & Testing + +In order to build, you need to have the Go compiler installed. You can get it from [here](https://golang.org/dl/). Run the tests with: + +```bash +git clone https://github.com/ggml-org/whisper.cpp.git +cd whisper.cpp/bindings/go +make test +``` + +This will compile a static `libwhisper.a` in a `build` folder, download a model file, then run the tests. To build the examples: + +```bash +make examples +``` + +To build using cuda support add `GGML_CUDA=1`: + +```bash +GGML_CUDA=1 make examples +``` + +The examples are placed in the `build` directory. Once built, you can download all the models with the following command: + +```bash +./build/go-model-download -out models +``` + +And you can then test a model against samples with the following command: + +```bash +./build/go-whisper -model models/ggml-tiny.en.bin samples/jfk.wav +``` + +## Using the bindings + +To use the bindings in your own software, + + 1. Import `github.com/ggerganov/whisper.cpp/bindings/go/pkg/whisper` (or `github.com/ggerganov/whisper.cpp/bindings/go` into your package; + 2. Compile `libwhisper.a` (you can use `make whisper` in the `bindings/go` directory); + 3. Link your go binary against whisper by setting the environment variables `C_INCLUDE_PATH` and `LIBRARY_PATH` + to point to the `whisper.h` file directory and `libwhisper.a` file directory respectively. + +Look at the `Makefile` in the `bindings/go` directory for an example. + +The API Documentation: + + * https://pkg.go.dev/github.com/ggerganov/whisper.cpp/bindings/go + * https://pkg.go.dev/github.com/ggerganov/whisper.cpp/bindings/go/pkg/whisper + +Getting help: + + * Follow the discussion for the go bindings [here](https://github.com/ggml-org/whisper.cpp/discussions/312) + +## License + +The license for the Go bindings is the same as the license for the rest of the whisper.cpp project, which is the MIT License. See the `LICENSE` file for more details. + diff --git a/bindings/go/doc.go b/bindings/go/doc.go new file mode 100644 index 0000000..a5dae93 --- /dev/null +++ b/bindings/go/doc.go @@ -0,0 +1,5 @@ +/* +github.com/ggml-org/whisper.cpp/bindings/go +provides a speech-to-text service bindings for the Go programming language. +*/ +package whisper diff --git a/bindings/go/examples/go-model-download/context.go b/bindings/go/examples/go-model-download/context.go new file mode 100644 index 0000000..7d5f0dd --- /dev/null +++ b/bindings/go/examples/go-model-download/context.go @@ -0,0 +1,31 @@ +package main + +import ( + "context" + "os" + "os/signal" +) + +// ContextForSignal returns a context object which is cancelled when a signal +// is received. It returns nil if no signal parameter is provided +func ContextForSignal(signals ...os.Signal) context.Context { + if len(signals) == 0 { + return nil + } + + ch := make(chan os.Signal, 1) // Buffered channel with space for 1 signal + ctx, cancel := context.WithCancel(context.Background()) + + // Send message on channel when signal received + signal.Notify(ch, signals...) + + // When any signal is received, call cancel + go func() { + <-ch + cancel() + }() + + // Return success + return ctx +} + diff --git a/bindings/go/examples/go-model-download/main.go b/bindings/go/examples/go-model-download/main.go new file mode 100644 index 0000000..e72262e --- /dev/null +++ b/bindings/go/examples/go-model-download/main.go @@ -0,0 +1,311 @@ +package main + +import ( + "context" + "flag" + "fmt" + "io" + "net/http" + "net/url" + "os" + "path/filepath" + "strings" + "syscall" + "time" +) + +/////////////////////////////////////////////////////////////////////////////// +// CONSTANTS + +const ( + srcUrl = "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/" // The location of the models + srcExt = ".bin" // Filename extension + bufSize = 1024 * 64 // Size of the buffer used for downloading the model +) + +var ( + // The models which will be downloaded, if no model is specified as an argument + modelNames = []string{ + "tiny", "tiny-q5_1", "tiny-q8_0", + "tiny.en", "tiny.en-q5_1", "tiny.en-q8_0", + "base", "base-q5_1", "base-q8_0", + "base.en", "base.en-q5_1", "base.en-q8_0", + "small", "small-q5_1", "small-q8_0", + "small.en", "small.en-q5_1", "small.en-q8_0", + "medium", "medium-q5_0", "medium-q8_0", + "medium.en", "medium.en-q5_0", "medium.en-q8_0", + "large-v1", + "large-v2", "large-v2-q5_0", "large-v2-q8_0", + "large-v3", "large-v3-q5_0", + "large-v3-turbo", "large-v3-turbo-q5_0", "large-v3-turbo-q8_0", + } +) + +var ( + // The output folder. When not set, use current working directory. + flagOut = flag.String("out", "", "Output folder") + + // HTTP timeout parameter - will timeout if takes longer than this to download a model + flagTimeout = flag.Duration("timeout", 30*time.Minute, "HTTP timeout") + + // Quiet parameter - will not print progress if set + flagQuiet = flag.Bool("quiet", false, "Quiet mode") +) + +/////////////////////////////////////////////////////////////////////////////// +// MAIN + +func main() { + flag.Usage = func() { + name := filepath.Base(flag.CommandLine.Name()) + fmt.Fprintf(flag.CommandLine.Output(), ` + Usage: %s [options] [<model>...] + + Options: + -out string Specify the output folder where models will be saved. + Default: Current working directory. + -timeout duration Set the maximum duration for downloading a model. + Example: 10m, 1h (default: 30m0s). + -quiet Suppress all output except errors. + + Examples: + 1. Download a specific model: + %s -out ./models tiny-q8_0 + + 2. Download all models: + %s -out ./models + + `, name, name, name) + + flag.PrintDefaults() + } + flag.Parse() + + // Get output path + out, err := GetOut() + if err != nil { + fmt.Fprintln(os.Stderr, "Error:", err) + os.Exit(-1) + } + + // Create context which quits on SIGINT or SIGQUIT + ctx := ContextForSignal(os.Interrupt, syscall.SIGQUIT) + + // Progress filehandle + progress := os.Stdout + if *flagQuiet { + progress, err = os.Open(os.DevNull) + if err != nil { + fmt.Fprintln(os.Stderr, "Error:", err) + os.Exit(-1) + } + defer progress.Close() + } + + // Download models - exit on error or interrupt + for _, model := range GetModels() { + url, err := URLForModel(model) + if err != nil { + fmt.Fprintln(os.Stderr, "Error:", err) + continue + } else if path, err := Download(ctx, progress, url, out); err == nil || err == io.EOF { + continue + } else if err == context.Canceled { + os.Remove(path) + fmt.Fprintln(progress, "\nInterrupted") + break + } else if err == context.DeadlineExceeded { + os.Remove(path) + fmt.Fprintln(progress, "Timeout downloading model") + continue + } else { + os.Remove(path) + fmt.Fprintln(os.Stderr, "Error:", err) + break + } + } +} + +/////////////////////////////////////////////////////////////////////////////// +// PUBLIC METHODS + +// GetOut returns the path to the output directory +func GetOut() (string, error) { + if *flagOut == "" { + return os.Getwd() + } + if info, err := os.Stat(*flagOut); err != nil { + return "", err + } else if !info.IsDir() { + return "", fmt.Errorf("not a directory: %s", info.Name()) + } else { + return *flagOut, nil + } +} + +// GetModels returns the list of models to download +func GetModels() []string { + if flag.NArg() == 0 { + fmt.Println("No model specified.") + fmt.Println("Preparing to download all models...") + + // Calculate total download size + fmt.Println("Calculating total download size...") + totalSize, err := CalculateTotalDownloadSize(modelNames) + if err != nil { + fmt.Println("Error calculating download sizes:", err) + os.Exit(1) + } + + fmt.Println("View available models: https://huggingface.co/ggerganov/whisper.cpp/tree/main") + fmt.Printf("Total download size: %.2f GB\n", float64(totalSize)/(1024*1024*1024)) + fmt.Println("Would you like to download all models? (y/N)") + + // Prompt for user input + var response string + fmt.Scanln(&response) + if response != "y" && response != "Y" { + fmt.Println("Aborting. Specify a model to download.") + os.Exit(0) + } + + return modelNames // Return all models if confirmed + } + return flag.Args() // Return specific models if arguments are provided +} + +func CalculateTotalDownloadSize(models []string) (int64, error) { + var totalSize int64 + client := http.Client{} + + for _, model := range models { + modelURL, err := URLForModel(model) + if err != nil { + return 0, err + } + + // Issue a HEAD request to get the file size + req, err := http.NewRequest("HEAD", modelURL, nil) + if err != nil { + return 0, err + } + + resp, err := client.Do(req) + if err != nil { + return 0, err + } + resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + fmt.Printf("Warning: Unable to fetch size for %s (HTTP %d)\n", model, resp.StatusCode) + continue + } + + size := resp.ContentLength + totalSize += size + } + return totalSize, nil +} + +// URLForModel returns the URL for the given model on huggingface.co +func URLForModel(model string) (string, error) { + // Ensure "ggml-" prefix is added only once + if !strings.HasPrefix(model, "ggml-") { + model = "ggml-" + model + } + + // Ensure ".bin" extension is added only once + if filepath.Ext(model) != srcExt { + model += srcExt + } + + // Parse the base URL + url, err := url.Parse(srcUrl) + if err != nil { + return "", err + } + + // Ensure no trailing slash in the base URL + url.Path = fmt.Sprintf("%s/%s", strings.TrimSuffix(url.Path, "/"), model) + return url.String(), nil +} + +// Download downloads the model from the given URL to the given output directory +func Download(ctx context.Context, p io.Writer, model, out string) (string, error) { + // Create HTTP client + client := http.Client{ + Timeout: *flagTimeout, + } + + // Initiate the download + req, err := http.NewRequest("GET", model, nil) + if err != nil { + return "", err + } + resp, err := client.Do(req) + if err != nil { + return "", err + } + defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { + return "", fmt.Errorf("%s: %s", model, resp.Status) + } + + // If output file exists and is the same size as the model, skip + path := filepath.Join(out, filepath.Base(model)) + if info, err := os.Stat(path); err == nil && info.Size() == resp.ContentLength { + fmt.Fprintln(p, "Skipping", model, "as it already exists") + return "", nil + } + + // Create file + w, err := os.Create(path) + if err != nil { + return "", err + } + defer w.Close() + + // Report + fmt.Fprintln(p, "Downloading", model, "to", out) + + // Progressively download the model + data := make([]byte, bufSize) + count, pct := int64(0), int64(0) + ticker := time.NewTicker(5 * time.Second) + for { + select { + case <-ctx.Done(): + // Cancelled, return error + return path, ctx.Err() + case <-ticker.C: + pct = DownloadReport(p, pct, count, resp.ContentLength) + default: + // Read body + n, err := resp.Body.Read(data) + if n > 0 { + if m, err := w.Write(data[:n]); err != nil { + return path, err + } else { + count += int64(m) + } + } + + if err != nil { + if err == io.EOF { + DownloadReport(p, pct, count, resp.ContentLength) + return path, nil + } + return path, err + } + } + } +} + +// Report periodically reports the download progress when percentage changes +func DownloadReport(w io.Writer, pct, count, total int64) int64 { + pct_ := count * 100 / total + if pct_ > pct { + fmt.Fprintf(w, " ...%d MB written (%d%%)\n", count/1e6, pct_) + } + return pct_ +} diff --git a/bindings/go/examples/go-whisper/color.go b/bindings/go/examples/go-whisper/color.go new file mode 100644 index 0000000..fa5ac2f --- /dev/null +++ b/bindings/go/examples/go-whisper/color.go @@ -0,0 +1,22 @@ +package main + +import "fmt" + +/////////////////////////////////////////////////////////////////////////////// +// CONSTANTS + +const ( + Reset = "\033[0m" + RGBPrefix = "\033[38;5;" // followed by RGB values in decimal format separated by colons + RGBSuffix = "m" +) + +/////////////////////////////////////////////////////////////////////////////// +// PUBLIC METHODS + +// Colorize text with RGB values, from 0 to 23 +func Colorize(text string, v int) string { + // https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit + // Grayscale colors are in the range 232-255 + return RGBPrefix + fmt.Sprint(v%24+232) + RGBSuffix + text + Reset +} diff --git a/bindings/go/examples/go-whisper/flags.go b/bindings/go/examples/go-whisper/flags.go new file mode 100644 index 0000000..766c92f --- /dev/null +++ b/bindings/go/examples/go-whisper/flags.go @@ -0,0 +1,147 @@ +package main + +import ( + "flag" + "fmt" + "strings" + "time" + + // Packages + whisper "github.com/ggerganov/whisper.cpp/bindings/go/pkg/whisper" +) + +/////////////////////////////////////////////////////////////////////////////// +// TYPES + +type Flags struct { + *flag.FlagSet +} + +/////////////////////////////////////////////////////////////////////////////// +// LIFECYCLE + +func NewFlags(name string, args []string) (*Flags, error) { + flags := &Flags{ + FlagSet: flag.NewFlagSet(name, flag.ContinueOnError), + } + + // Register the command line arguments + registerFlags(flags) + + // Parse command line + if err := flags.Parse(args); err != nil { + return nil, err + } + + // Return success + return flags, nil +} + +/////////////////////////////////////////////////////////////////////////////// +// PUBLIC METHODS + +func (flags *Flags) GetModel() string { + return flags.Lookup("model").Value.String() +} + +func (flags *Flags) GetLanguage() string { + return flags.Lookup("language").Value.String() +} + +func (flags *Flags) IsTranslate() bool { + return flags.Lookup("translate").Value.(flag.Getter).Get().(bool) +} + +func (flags *Flags) GetOffset() time.Duration { + return flags.Lookup("offset").Value.(flag.Getter).Get().(time.Duration) +} + +func (flags *Flags) GetDuration() time.Duration { + return flags.Lookup("duration").Value.(flag.Getter).Get().(time.Duration) +} + +func (flags *Flags) GetThreads() uint { + return flags.Lookup("threads").Value.(flag.Getter).Get().(uint) +} + +func (flags *Flags) GetOut() string { + return strings.ToLower(flags.Lookup("out").Value.String()) +} + +func (flags *Flags) IsTokens() bool { + return flags.Lookup("tokens").Value.String() == "true" +} + +func (flags *Flags) IsColorize() bool { + return flags.Lookup("colorize").Value.String() == "true" +} + +func (flags *Flags) GetMaxLen() uint { + return flags.Lookup("max-len").Value.(flag.Getter).Get().(uint) +} + +func (flags *Flags) GetMaxTokens() uint { + return flags.Lookup("max-tokens").Value.(flag.Getter).Get().(uint) +} + +func (flags *Flags) GetWordThreshold() float32 { + return float32(flags.Lookup("word-thold").Value.(flag.Getter).Get().(float64)) +} + +func (flags *Flags) SetParams(context whisper.Context) error { + if lang := flags.GetLanguage(); lang != "" && lang != "auto" { + fmt.Fprintf(flags.Output(), "Setting language to %q\n", lang) + if err := context.SetLanguage(lang); err != nil { + return err + } + } + if flags.IsTranslate() && context.IsMultilingual() { + fmt.Fprintf(flags.Output(), "Setting translate to true\n") + context.SetTranslate(true) + } + if offset := flags.GetOffset(); offset != 0 { + fmt.Fprintf(flags.Output(), "Setting offset to %v\n", offset) + context.SetOffset(offset) + } + if duration := flags.GetDuration(); duration != 0 { + fmt.Fprintf(flags.Output(), "Setting duration to %v\n", duration) + context.SetDuration(duration) + } + if threads := flags.GetThreads(); threads != 0 { + fmt.Fprintf(flags.Output(), "Setting threads to %d\n", threads) + context.SetThreads(threads) + } + if max_len := flags.GetMaxLen(); max_len != 0 { + fmt.Fprintf(flags.Output(), "Setting max_segment_length to %d\n", max_len) + context.SetMaxSegmentLength(max_len) + } + if max_tokens := flags.GetMaxTokens(); max_tokens != 0 { + fmt.Fprintf(flags.Output(), "Setting max_tokens to %d\n", max_tokens) + context.SetMaxTokensPerSegment(max_tokens) + } + if word_threshold := flags.GetWordThreshold(); word_threshold != 0 { + fmt.Fprintf(flags.Output(), "Setting word_threshold to %f\n", word_threshold) + context.SetTokenThreshold(word_threshold) + } + + // Return success + return nil +} + +/////////////////////////////////////////////////////////////////////////////// +// PRIVATE METHODS + +func registerFlags(flag *Flags) { + flag.String("model", "", "Path to the model file") + flag.String("language", "", "Spoken language") + flag.Bool("translate", false, "Translate from source language to english") + flag.Duration("offset", 0, "Time offset") + flag.Duration("duration", 0, "Duration of audio to process") + flag.Uint("threads", 0, "Number of threads to use") + flag.Uint("max-len", 0, "Maximum segment length in characters") + flag.Uint("max-tokens", 0, "Maximum tokens per segment") + flag.Float64("word-thold", 0, "Maximum segment score") + flag.Bool("tokens", false, "Display tokens") + flag.Bool("colorize", false, "Colorize tokens") + flag.String("out", "", "Output format (srt, none or leave as empty string)") +} diff --git a/bindings/go/examples/go-whisper/main.go b/bindings/go/examples/go-whisper/main.go new file mode 100644 index 0000000..1bff7f5 --- /dev/null +++ b/bindings/go/examples/go-whisper/main.go @@ -0,0 +1,43 @@ +package main + +import ( + "flag" + "fmt" + "os" + "path/filepath" + + // Packages + whisper "github.com/ggerganov/whisper.cpp/bindings/go/pkg/whisper" +) + +func main() { + flags, err := NewFlags(filepath.Base(os.Args[0]), os.Args[1:]) + if err == flag.ErrHelp { + os.Exit(0) + } else if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } else if flags.GetModel() == "" { + fmt.Fprintln(os.Stderr, "Use -model flag to specify which model file to use") + os.Exit(1) + } else if flags.NArg() == 0 { + fmt.Fprintln(os.Stderr, "No input files specified") + os.Exit(1) + } + + // Load model + model, err := whisper.New(flags.GetModel()) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + defer model.Close() + + // Process files + for _, filename := range flags.Args() { + if err := Process(model, filename, flags); err != nil { + fmt.Fprintln(os.Stderr, err) + continue + } + } +} diff --git a/bindings/go/examples/go-whisper/process.go b/bindings/go/examples/go-whisper/process.go new file mode 100644 index 0000000..833947e --- /dev/null +++ b/bindings/go/examples/go-whisper/process.go @@ -0,0 +1,132 @@ +package main + +import ( + "fmt" + "io" + "os" + "time" + + // Package imports + whisper "github.com/ggerganov/whisper.cpp/bindings/go/pkg/whisper" + wav "github.com/go-audio/wav" +) + +func Process(model whisper.Model, path string, flags *Flags) error { + var data []float32 + + // Create processing context + context, err := model.NewContext() + if err != nil { + return err + } + + // Set the parameters + if err := flags.SetParams(context); err != nil { + return err + } + + fmt.Printf("\n%s\n", context.SystemInfo()) + + // Open the file + fmt.Fprintf(flags.Output(), "Loading %q\n", path) + fh, err := os.Open(path) + if err != nil { + return err + } + defer fh.Close() + + // Decode the WAV file - load the full buffer + dec := wav.NewDecoder(fh) + if buf, err := dec.FullPCMBuffer(); err != nil { + return err + } else if dec.SampleRate != whisper.SampleRate { + return fmt.Errorf("unsupported sample rate: %d", dec.SampleRate) + } else if dec.NumChans != 1 { + return fmt.Errorf("unsupported number of channels: %d", dec.NumChans) + } else { + data = buf.AsFloat32Buffer().Data + } + + // Segment callback when -tokens is specified + var cb whisper.SegmentCallback + if flags.IsTokens() { + cb = func(segment whisper.Segment) { + fmt.Fprintf(flags.Output(), "%02d [%6s->%6s] ", segment.Num, segment.Start.Truncate(time.Millisecond), segment.End.Truncate(time.Millisecond)) + for _, token := range segment.Tokens { + if flags.IsColorize() && context.IsText(token) { + fmt.Fprint(flags.Output(), Colorize(token.Text, int(token.P*24.0)), " ") + } else { + fmt.Fprint(flags.Output(), token.Text, " ") + } + } + fmt.Fprintln(flags.Output(), "") + fmt.Fprintln(flags.Output(), "") + } + } + + // Process the data + fmt.Fprintf(flags.Output(), " ...processing %q\n", path) + context.ResetTimings() + if err := context.Process(data, nil, cb, nil); err != nil { + return err + } + + context.PrintTimings() + + // Print out the results + switch { + case flags.GetOut() == "srt": + return OutputSRT(os.Stdout, context) + case flags.GetOut() == "none": + return nil + default: + return Output(os.Stdout, context, flags.IsColorize()) + } +} + +// Output text as SRT file +func OutputSRT(w io.Writer, context whisper.Context) error { + n := 1 + for { + segment, err := context.NextSegment() + if err == io.EOF { + return nil + } else if err != nil { + return err + } + fmt.Fprintln(w, n) + fmt.Fprintln(w, srtTimestamp(segment.Start), " --> ", srtTimestamp(segment.End)) + fmt.Fprintln(w, segment.Text) + fmt.Fprintln(w, "") + n++ + } +} + +// Output text to terminal +func Output(w io.Writer, context whisper.Context, colorize bool) error { + for { + segment, err := context.NextSegment() + if err == io.EOF { + return nil + } else if err != nil { + return err + } + fmt.Fprintf(w, "[%6s->%6s]", segment.Start.Truncate(time.Millisecond), segment.End.Truncate(time.Millisecond)) + if colorize { + for _, token := range segment.Tokens { + if !context.IsText(token) { + continue + } + fmt.Fprint(w, " ", Colorize(token.Text, int(token.P*24.0))) + } + fmt.Fprint(w, "\n") + } else { + fmt.Fprintln(w, " ", segment.Text) + } + } +} + +// Return srtTimestamp +func srtTimestamp(t time.Duration) string { + return fmt.Sprintf("%02d:%02d:%02d,%03d", t/time.Hour, (t%time.Hour)/time.Minute, (t%time.Minute)/time.Second, (t%time.Second)/time.Millisecond) +} diff --git a/bindings/go/go.mod b/bindings/go/go.mod new file mode 100644 index 0000000..7c92c7b --- /dev/null +++ b/bindings/go/go.mod @@ -0,0 +1,16 @@ +module github.com/ggerganov/whisper.cpp/bindings/go + +go 1.23 + +require ( + github.com/go-audio/wav v1.1.0 + github.com/stretchr/testify v1.9.0 +) + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/go-audio/audio v1.0.0 // indirect + github.com/go-audio/riff v1.0.0 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/bindings/go/go.sum b/bindings/go/go.sum new file mode 100644 index 0000000..1f99aeb --- /dev/null +++ b/bindings/go/go.sum @@ -0,0 +1,16 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-audio/audio v1.0.0 h1:zS9vebldgbQqktK4H0lUqWrG8P0NxCJVqcj7ZpNnwd4= +github.com/go-audio/audio v1.0.0/go.mod h1:6uAu0+H2lHkwdGsAY+j2wHPNPpPoeg5AaEFh9FlA+Zs= +github.com/go-audio/riff v1.0.0 h1:d8iCGbDvox9BfLagY94fBynxSPHO80LmZCaOsmKxokA= +github.com/go-audio/riff v1.0.0/go.mod h1:l3cQwc85y79NQFCRB7TiPoNiaijp6q8Z0Uv38rVG498= +github.com/go-audio/wav v1.1.0 h1:jQgLtbqBzY7G+BM8fXF7AHUk1uHUviWS4X39d5rsL2g= +github.com/go-audio/wav v1.1.0/go.mod h1:mpe9qfwbScEbkd8uybLuIpTgHyrISw/OTuvjUW2iGtE= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/bindings/go/params.go b/bindings/go/params.go new file mode 100644 index 0000000..7d6a30d --- /dev/null +++ b/bindings/go/params.go @@ -0,0 +1,244 @@ +package whisper + +import ( + "fmt" +) + +/////////////////////////////////////////////////////////////////////////////// +// CGO + +/* +#include <whisper.h> +*/ +import "C" + +/////////////////////////////////////////////////////////////////////////////// +// PUBLIC METHODS + +func (p *Params) SetTranslate(v bool) { + p.translate = toBool(v) +} + +func (p *Params) SetSplitOnWord(v bool) { + p.split_on_word = toBool(v) +} + +func (p *Params) SetNoContext(v bool) { + p.no_context = toBool(v) +} + +func (p *Params) SetSingleSegment(v bool) { + p.single_segment = toBool(v) +} + +func (p *Params) SetPrintSpecial(v bool) { + p.print_special = toBool(v) +} + +func (p *Params) SetPrintProgress(v bool) { + p.print_progress = toBool(v) +} + +func (p *Params) SetPrintRealtime(v bool) { + p.print_realtime = toBool(v) +} + +func (p *Params) SetPrintTimestamps(v bool) { + p.print_timestamps = toBool(v) +} + +// Voice Activity Detection (VAD) +func (p *Params) SetVAD(v bool) { + p.vad = toBool(v) +} + +func (p *Params) SetVADModelPath(path string) { + p.vad_model_path = C.CString(path) +} + +func (p *Params) SetVADThreshold(t float32) { + p.vad_params.threshold = C.float(t) +} + +func (p *Params) SetVADMinSpeechMs(ms int) { + p.vad_params.min_speech_duration_ms = C.int(ms) +} + +func (p *Params) SetVADMinSilenceMs(ms int) { + p.vad_params.min_silence_duration_ms = C.int(ms) +} + +func (p *Params) SetVADMaxSpeechSec(s float32) { + p.vad_params.max_speech_duration_s = C.float(s) +} + +func (p *Params) SetVADSpeechPadMs(ms int) { + p.vad_params.speech_pad_ms = C.int(ms) +} + +func (p *Params) SetVADSamplesOverlap(sec float32) { + p.vad_params.samples_overlap = C.float(sec) +} + +// Set language id +func (p *Params) SetLanguage(lang int) error { + if lang == -1 { + p.language = nil + return nil + } + str := C.whisper_lang_str(C.int(lang)) + if str == nil { + return ErrInvalidLanguage + } else { + p.language = str + } + return nil +} + +// Get language id +func (p *Params) Language() int { + if p.language == nil { + return -1 + } + return int(C.whisper_lang_id(p.language)) +} + +// Threads available +func (p *Params) Threads() int { + return int(p.n_threads) +} + +// Set number of threads to use +func (p *Params) SetThreads(threads int) { + p.n_threads = C.int(threads) +} + +// Set start offset in ms +func (p *Params) SetOffset(offset_ms int) { + p.offset_ms = C.int(offset_ms) +} + +// Set audio duration to process in ms +func (p *Params) SetDuration(duration_ms int) { + p.duration_ms = C.int(duration_ms) +} + +// Set timestamp token probability threshold (~0.01) +func (p *Params) SetTokenThreshold(t float32) { + p.thold_pt = C.float(t) +} + +// Set timestamp token sum probability threshold (~0.01) +func (p *Params) SetTokenSumThreshold(t float32) { + p.thold_ptsum = C.float(t) +} + +// Set max segment length in characters +func (p *Params) SetMaxSegmentLength(n int) { + p.max_len = C.int(n) +} + +func (p *Params) SetTokenTimestamps(b bool) { + p.token_timestamps = toBool(b) +} + +// Set max tokens per segment (0 = no limit) +func (p *Params) SetMaxTokensPerSegment(n int) { + p.max_tokens = C.int(n) +} + +// Set audio encoder context +func (p *Params) SetAudioCtx(n int) { + p.audio_ctx = C.int(n) +} + +func (p *Params) SetMaxContext(n int) { + p.n_max_text_ctx = C.int(n) +} + +func (p *Params) SetBeamSize(n int) { + p.beam_search.beam_size = C.int(n) +} + +func (p *Params) SetEntropyThold(t float32) { + p.entropy_thold = C.float(t) +} + +func (p *Params) SetTemperature(t float32) { + p.temperature = C.float(t) +} + +// Sets the fallback temperature incrementation +// Pass -1.0 to disable this feature +func (p *Params) SetTemperatureFallback(t float32) { + p.temperature_inc = C.float(t) +} + +// Set initial prompt +func (p *Params) SetInitialPrompt(prompt string) { + p.initial_prompt = C.CString(prompt) +} + +func (p *Params) SetCarryInitialPrompt(v bool) { + p.carry_initial_prompt = toBool(v) +} + +/////////////////////////////////////////////////////////////////////////////// +// PRIVATE METHODS + +func toBool(v bool) C.bool { + if v { + return C.bool(true) + } + return C.bool(false) +} + +/////////////////////////////////////////////////////////////////////////////// +// STRINGIFY + +func (p *Params) String() string { + str := "<whisper.params" + str += fmt.Sprintf(" strategy=%v", p.strategy) + str += fmt.Sprintf(" n_threads=%d", p.n_threads) + if p.language != nil { + str += fmt.Sprintf(" language=%s", C.GoString(p.language)) + } + str += fmt.Sprintf(" n_max_text_ctx=%d", p.n_max_text_ctx) + str += fmt.Sprintf(" offset_ms=%d", p.offset_ms) + str += fmt.Sprintf(" duration_ms=%d", p.duration_ms) + str += fmt.Sprintf(" audio_ctx=%d", p.audio_ctx) + str += fmt.Sprintf(" initial_prompt=%s", C.GoString(p.initial_prompt)) + str += fmt.Sprintf(" entropy_thold=%f", p.entropy_thold) + str += fmt.Sprintf(" temperature=%f", p.temperature) + str += fmt.Sprintf(" temperature_inc=%f", p.temperature_inc) + str += fmt.Sprintf(" beam_size=%d", p.beam_search.beam_size) + if p.translate { + str += " translate" + } + if p.no_context { + str += " no_context" + } + if p.single_segment { + str += " single_segment" + } + if p.print_special { + str += " print_special" + } + if p.print_progress { + str += " print_progress" + } + if p.print_realtime { + str += " print_realtime" + } + if p.print_timestamps { + str += " print_timestamps" + } + if p.token_timestamps { + str += " token_timestamps" + } + if p.carry_initial_prompt { + str += " carry_initial_prompt" + } + + return str + ">" +} diff --git a/bindings/go/pkg/whisper/consts.go b/bindings/go/pkg/whisper/consts.go new file mode 100644 index 0000000..5c22dc1 --- /dev/null +++ b/bindings/go/pkg/whisper/consts.go @@ -0,0 +1,28 @@ +package whisper + +import ( + "errors" + + // Bindings + whisper "github.com/ggerganov/whisper.cpp/bindings/go" +) + +/////////////////////////////////////////////////////////////////////////////// +// ERRORS + +var ( + ErrUnableToLoadModel = errors.New("unable to load model") + ErrInternalAppError = errors.New("internal application error") + ErrProcessingFailed = errors.New("processing failed") + ErrUnsupportedLanguage = errors.New("unsupported language") + ErrModelNotMultilingual = errors.New("model is not multilingual") +) + +/////////////////////////////////////////////////////////////////////////////// +// CONSTANTS + +// SampleRate is the sample rate of the audio data. +const SampleRate = whisper.SampleRate + +// SampleBits is the number of bytes per sample. +const SampleBits = whisper.SampleBits diff --git a/bindings/go/pkg/whisper/context.go b/bindings/go/pkg/whisper/context.go new file mode 100644 index 0000000..d356d72 --- /dev/null +++ b/bindings/go/pkg/whisper/context.go @@ -0,0 +1,385 @@ +package whisper + +import ( + "fmt" + "io" + "runtime" + "strings" + "time" + + // Bindings + whisper "github.com/ggerganov/whisper.cpp/bindings/go" +) + +/////////////////////////////////////////////////////////////////////////////// +// TYPES + +type context struct { + n int + model *model + params whisper.Params +} + +// Make sure context adheres to the interface +var _ Context = (*context)(nil) + +/////////////////////////////////////////////////////////////////////////////// +// LIFECYCLE + +func newContext(model *model, params whisper.Params) (Context, error) { + context := new(context) + context.model = model + context.params = params + + // Return success + return context, nil +} + +/////////////////////////////////////////////////////////////////////////////// +// PUBLIC METHODS + +// Set the language to use for speech recognition. +func (context *context) SetLanguage(lang string) error { + if context.model.ctx == nil { + return ErrInternalAppError + } + if !context.model.IsMultilingual() { + return ErrModelNotMultilingual + } + + if lang == "auto" { + context.params.SetLanguage(-1) + } else if id := context.model.ctx.Whisper_lang_id(lang); id < 0 { + return ErrUnsupportedLanguage + } else if err := context.params.SetLanguage(id); err != nil { + return err + } + // Return success + return nil +} + +func (context *context) IsMultilingual() bool { + return context.model.IsMultilingual() +} + +// Get language +func (context *context) Language() string { + id := context.params.Language() + if id == -1 { + return "auto" + } + return whisper.Whisper_lang_str(context.params.Language()) +} + +func (context *context) DetectedLanguage() string { + return whisper.Whisper_lang_str(context.model.ctx.Whisper_full_lang_id()) +} + +// Set translate flag +func (context *context) SetTranslate(v bool) { + context.params.SetTranslate(v) +} + +// Voice Activity Detection (VAD) +func (context *context) SetVAD(v bool) { + context.params.SetVAD(v) +} + +func (context *context) SetVADModelPath(path string) { + context.params.SetVADModelPath(path) +} + +func (context *context) SetVADThreshold(t float32) { + context.params.SetVADThreshold(t) +} + +func (context *context) SetVADMinSpeechMs(ms int) { + context.params.SetVADMinSpeechMs(ms) +} + +func (context *context) SetVADMinSilenceMs(ms int) { + context.params.SetVADMinSilenceMs(ms) +} + +func (context *context) SetVADMaxSpeechSec(s float32) { + context.params.SetVADMaxSpeechSec(s) +} + +func (context *context) SetVADSpeechPadMs(ms int) { + context.params.SetVADSpeechPadMs(ms) +} + +func (context *context) SetVADSamplesOverlap(sec float32) { + context.params.SetVADSamplesOverlap(sec) +} + +func (context *context) SetSplitOnWord(v bool) { + context.params.SetSplitOnWord(v) +} + +// Set number of threads to use +func (context *context) SetThreads(v uint) { + context.params.SetThreads(int(v)) +} + +// Set time offset +func (context *context) SetOffset(v time.Duration) { + context.params.SetOffset(int(v.Milliseconds())) +} + +// Set duration of audio to process +func (context *context) SetDuration(v time.Duration) { + context.params.SetDuration(int(v.Milliseconds())) +} + +// Set timestamp token probability threshold (~0.01) +func (context *context) SetTokenThreshold(t float32) { + context.params.SetTokenThreshold(t) +} + +// Set timestamp token sum probability threshold (~0.01) +func (context *context) SetTokenSumThreshold(t float32) { + context.params.SetTokenSumThreshold(t) +} + +// Set max segment length in characters +func (context *context) SetMaxSegmentLength(n uint) { + context.params.SetMaxSegmentLength(int(n)) +} + +// Set token timestamps flag +func (context *context) SetTokenTimestamps(b bool) { + context.params.SetTokenTimestamps(b) +} + +// Set max tokens per segment (0 = no limit) +func (context *context) SetMaxTokensPerSegment(n uint) { + context.params.SetMaxTokensPerSegment(int(n)) +} + +// Set audio encoder context +func (context *context) SetAudioCtx(n uint) { + context.params.SetAudioCtx(int(n)) +} + +// Set maximum number of text context tokens to store +func (context *context) SetMaxContext(n int) { + context.params.SetMaxContext(n) +} + +// Set Beam Size +func (context *context) SetBeamSize(n int) { + context.params.SetBeamSize(n) +} + +// Set Entropy threshold +func (context *context) SetEntropyThold(t float32) { + context.params.SetEntropyThold(t) +} + +// Set Temperature +func (context *context) SetTemperature(t float32) { + context.params.SetTemperature(t) +} + +// Set the fallback temperature incrementation +// Pass -1.0 to disable this feature +func (context *context) SetTemperatureFallback(t float32) { + context.params.SetTemperatureFallback(t) +} + +// Set initial prompt +func (context *context) SetInitialPrompt(prompt string) { + context.params.SetInitialPrompt(prompt) +} + +// ResetTimings resets the mode timings. Should be called before processing +func (context *context) ResetTimings() { + context.model.ctx.Whisper_reset_timings() +} + +// PrintTimings prints the model timings to stdout. +func (context *context) PrintTimings() { + context.model.ctx.Whisper_print_timings() +} + +// SystemInfo returns the system information +func (context *context) SystemInfo() string { + return fmt.Sprintf("system_info: n_threads = %d / %d | %s\n", + context.params.Threads(), + runtime.NumCPU(), + whisper.Whisper_print_system_info(), + ) +} + +// Use mel data at offset_ms to try and auto-detect the spoken language +// Make sure to call whisper_pcm_to_mel() or whisper_set_mel() first. +// Returns the probabilities of all languages. +func (context *context) WhisperLangAutoDetect(offset_ms int, n_threads int) ([]float32, error) { + langProbs, err := context.model.ctx.Whisper_lang_auto_detect(offset_ms, n_threads) + if err != nil { + return nil, err + } + return langProbs, nil +} + +// Process new sample data and return any errors +func (context *context) Process( + data []float32, + callEncoderBegin EncoderBeginCallback, + callNewSegment SegmentCallback, + callProgress ProgressCallback, +) error { + if context.model.ctx == nil { + return ErrInternalAppError + } + // If the callback is defined then we force on single_segment mode + if callNewSegment != nil { + context.params.SetSingleSegment(true) + } + + // We don't do parallel processing at the moment + processors := 0 + if processors > 1 { + if err := context.model.ctx.Whisper_full_parallel(context.params, data, processors, callEncoderBegin, + func(new int) { + if callNewSegment != nil { + num_segments := context.model.ctx.Whisper_full_n_segments() + s0 := num_segments - new + for i := s0; i < num_segments; i++ { + callNewSegment(toSegment(context.model.ctx, i)) + } + } + }); err != nil { + return err + } + } else if err := context.model.ctx.Whisper_full(context.params, data, callEncoderBegin, + func(new int) { + if callNewSegment != nil { + num_segments := context.model.ctx.Whisper_full_n_segments() + s0 := num_segments - new + for i := s0; i < num_segments; i++ { + callNewSegment(toSegment(context.model.ctx, i)) + } + } + }, func(progress int) { + if callProgress != nil { + callProgress(progress) + } + }); err != nil { + return err + } + + // Reset n so that more Segments can be available within NextSegment call + context.n = 0 + + // Return success + return nil +} + +// Return the next segment of tokens +func (context *context) NextSegment() (Segment, error) { + if context.model.ctx == nil { + return Segment{}, ErrInternalAppError + } + if context.n >= context.model.ctx.Whisper_full_n_segments() { + return Segment{}, io.EOF + } + + // Populate result + result := toSegment(context.model.ctx, context.n) + + // Increment the cursor + context.n++ + + // Return success + return result, nil +} + +// Test for text tokens +func (context *context) IsText(t Token) bool { + switch { + case context.IsBEG(t): + return false + case context.IsSOT(t): + return false + case whisper.Token(t.Id) >= context.model.ctx.Whisper_token_eot(): + return false + case context.IsPREV(t): + return false + case context.IsSOLM(t): + return false + case context.IsNOT(t): + return false + default: + return true + } +} + +// Test for "begin" token +func (context *context) IsBEG(t Token) bool { + return whisper.Token(t.Id) == context.model.ctx.Whisper_token_beg() +} + +// Test for "start of transcription" token +func (context *context) IsSOT(t Token) bool { + return whisper.Token(t.Id) == context.model.ctx.Whisper_token_sot() +} + +// Test for "end of transcription" token +func (context *context) IsEOT(t Token) bool { + return whisper.Token(t.Id) == context.model.ctx.Whisper_token_eot() +} + +// Test for "start of prev" token +func (context *context) IsPREV(t Token) bool { + return whisper.Token(t.Id) == context.model.ctx.Whisper_token_prev() +} + +// Test for "start of lm" token +func (context *context) IsSOLM(t Token) bool { + return whisper.Token(t.Id) == context.model.ctx.Whisper_token_solm() +} + +// Test for "No timestamps" token +func (context *context) IsNOT(t Token) bool { + return whisper.Token(t.Id) == context.model.ctx.Whisper_token_not() +} + +// Test for token associated with a specific language +func (context *context) IsLANG(t Token, lang string) bool { + if id := context.model.ctx.Whisper_lang_id(lang); id >= 0 { + return whisper.Token(t.Id) == context.model.ctx.Whisper_token_lang(id) + } else { + return false + } +} + +/////////////////////////////////////////////////////////////////////////////// +// PRIVATE METHODS + +func toSegment(ctx *whisper.Context, n int) Segment { + return Segment{ + Num: n, + Text: strings.TrimSpace(ctx.Whisper_full_get_segment_text(n)), + Start: time.Duration(ctx.Whisper_full_get_segment_t0(n)) * time.Millisecond * 10, + End: time.Duration(ctx.Whisper_full_get_segment_t1(n)) * time.Millisecond * 10, + Tokens: toTokens(ctx, n), + } +} + +func toTokens(ctx *whisper.Context, n int) []Token { + result := make([]Token, ctx.Whisper_full_n_tokens(n)) + for i := 0; i < len(result); i++ { + data := ctx.Whisper_full_get_token_data(n, i) + + result[i] = Token{ + Id: int(ctx.Whisper_full_get_token_id(n, i)), + Text: ctx.Whisper_full_get_token_text(n, i), + P: ctx.Whisper_full_get_token_p(n, i), + Start: time.Duration(data.T0()) * time.Millisecond * 10, + End: time.Duration(data.T1()) * time.Millisecond * 10, + } + } + return result +} diff --git a/bindings/go/pkg/whisper/context_test.go b/bindings/go/pkg/whisper/context_test.go new file mode 100644 index 0000000..79f6a59 --- /dev/null +++ b/bindings/go/pkg/whisper/context_test.go @@ -0,0 +1,172 @@ +package whisper_test + +import ( + "os" + "strings" + "testing" + + "github.com/ggerganov/whisper.cpp/bindings/go/pkg/whisper" + "github.com/go-audio/wav" + assert "github.com/stretchr/testify/assert" +) + +func TestSetLanguage(t *testing.T) { + assert := assert.New(t) + + model, err := whisper.New(ModelPath) + assert.NoError(err) + assert.NotNil(model) + defer model.Close() + + context, err := model.NewContext() + assert.NoError(err) + + // This returns an error since + // the model 'models/ggml-small.en.bin' + // that is loaded is not multilingual + err = context.SetLanguage("en") + assert.Error(err) +} + +func TestContextModelIsMultilingual(t *testing.T) { + assert := assert.New(t) + + model, err := whisper.New(ModelPath) + assert.NoError(err) + assert.NotNil(model) + defer model.Close() + + context, err := model.NewContext() + assert.NoError(err) + + isMultilingual := context.IsMultilingual() + + // This returns false since + // the model 'models/ggml-small.en.bin' + // that is loaded is not multilingual + assert.False(isMultilingual) +} + +func TestLanguage(t *testing.T) { + assert := assert.New(t) + + model, err := whisper.New(ModelPath) + assert.NoError(err) + assert.NotNil(model) + defer model.Close() + + context, err := model.NewContext() + assert.NoError(err) + + // This always returns en since + // the model 'models/ggml-small.en.bin' + // that is loaded is not multilingual + expectedLanguage := "en" + actualLanguage := context.Language() + assert.Equal(expectedLanguage, actualLanguage) +} + +func TestProcess(t *testing.T) { + assert := assert.New(t) + + fh, err := os.Open(SamplePath) + assert.NoError(err) + defer fh.Close() + + // Decode the WAV file - load the full buffer + dec := wav.NewDecoder(fh) + buf, err := dec.FullPCMBuffer() + assert.NoError(err) + assert.Equal(uint16(1), dec.NumChans) + + data := buf.AsFloat32Buffer().Data + + model, err := whisper.New(ModelPath) + assert.NoError(err) + assert.NotNil(model) + defer model.Close() + + context, err := model.NewContext() + assert.NoError(err) + + err = context.Process(data, nil, nil, nil) + assert.NoError(err) +} + +func TestProcessMaxTokensPerSegment(t *testing.T) { + assert := assert.New(t) + + if _, err := os.Stat(ModelPath); os.IsNotExist(err) { + t.Skip("Skipping test, model not found:", ModelPath) + } + + fh, err := os.Open(SamplePath) + assert.NoError(err) + defer fh.Close() + + // Decode the WAV file - load the full buffer + dec := wav.NewDecoder(fh) + buf, err := dec.FullPCMBuffer() + assert.NoError(err) + assert.Equal(uint16(1), dec.NumChans) + + data := buf.AsFloat32Buffer().Data + + model, err := whisper.New(ModelPath) + assert.NoError(err) + assert.NotNil(model) + defer model.Close() + + context, err := model.NewContext() + assert.NoError(err) + + context.SetMaxTokensPerSegment(5) + + err = context.Process(data, nil, nil, nil) + assert.NoError(err) + + var text strings.Builder + nSegments := 0 + for { + segment, err := context.NextSegment() + if err != nil { + break + } + nSegments++ + text.WriteString(segment.Text) + } + + assert.Greater(nSegments, 1) + assert.Contains(text.String(), "country") +} + +func TestDetectedLanguage(t *testing.T) { + assert := assert.New(t) + + fh, err := os.Open(SamplePath) + assert.NoError(err) + defer fh.Close() + + // Decode the WAV file - load the full buffer + dec := wav.NewDecoder(fh) + buf, err := dec.FullPCMBuffer() + assert.NoError(err) + assert.Equal(uint16(1), dec.NumChans) + + data := buf.AsFloat32Buffer().Data + + model, err := whisper.New(ModelPath) + assert.NoError(err) + assert.NotNil(model) + defer model.Close() + + context, err := model.NewContext() + assert.NoError(err) + + err = context.Process(data, nil, nil, nil) + assert.NoError(err) + + expectedLanguage := "en" + actualLanguage := context.DetectedLanguage() + assert.Equal(expectedLanguage, actualLanguage) +} diff --git a/bindings/go/pkg/whisper/doc.go b/bindings/go/pkg/whisper/doc.go new file mode 100644 index 0000000..fd4f1b9 --- /dev/null +++ b/bindings/go/pkg/whisper/doc.go @@ -0,0 +1,4 @@ +/* +This is the higher-level speech-to-text whisper.cpp API for go +*/ +package whisper diff --git a/bindings/go/pkg/whisper/interface.go b/bindings/go/pkg/whisper/interface.go new file mode 100644 index 0000000..2b275dd --- /dev/null +++ b/bindings/go/pkg/whisper/interface.go @@ -0,0 +1,118 @@ +package whisper + +import ( + "io" + "time" +) + +/////////////////////////////////////////////////////////////////////////////// +// TYPES + +// SegmentCallback is the callback function for processing segments in real +// time. It is called during the Process function +type SegmentCallback func(Segment) + +// ProgressCallback is the callback function for reporting progress during +// processing. It is called during the Process function +type ProgressCallback func(int) + +// EncoderBeginCallback is the callback function for checking if we want to +// continue processing. It is called during the Process function +type EncoderBeginCallback func() bool + +// Model is the interface to a whisper model. Create a new model with the +// function whisper.New(string) +type Model interface { + io.Closer + + // Return a new speech-to-text context. + NewContext() (Context, error) + + // Return true if the model is multilingual. + IsMultilingual() bool + + // Return all languages supported. + Languages() []string +} + +// Context is the speech recognition context. +type Context interface { + SetLanguage(string) error // Set the language to use for speech recognition, use "auto" for auto detect language. + SetTranslate(bool) // Set translate flag + IsMultilingual() bool // Return true if the model is multilingual. + Language() string // Get language + DetectedLanguage() string // Get detected language + + SetOffset(time.Duration) // Set offset + SetDuration(time.Duration) // Set duration + SetThreads(uint) // Set number of threads to use + SetSplitOnWord(bool) // Set split on word flag + SetTokenThreshold(float32) // Set timestamp token probability threshold + SetTokenSumThreshold(float32) // Set timestamp token sum probability threshold + SetMaxSegmentLength(uint) // Set max segment length in characters + SetTokenTimestamps(bool) // Set token timestamps flag + SetMaxTokensPerSegment(uint) // Set max tokens per segment (0 = no limit) + SetAudioCtx(uint) // Set audio encoder context + SetMaxContext(n int) // Set maximum number of text context tokens to store + SetBeamSize(n int) // Set Beam Size + SetEntropyThold(t float32) // Set Entropy threshold + SetInitialPrompt(prompt string) // Set initial prompt + SetTemperature(t float32) // Set temperature + SetTemperatureFallback(t float32) // Set temperature incrementation + + SetVAD(v bool) + SetVADModelPath(path string) + SetVADThreshold(t float32) + SetVADMinSpeechMs(ms int) + SetVADMinSilenceMs(ms int) + SetVADMaxSpeechSec(s float32) + SetVADSpeechPadMs(ms int) + SetVADSamplesOverlap(sec float32) + + // Process mono audio data and return any errors. + // If defined, newly generated segments are passed to the + // callback function during processing. + Process([]float32, EncoderBeginCallback, SegmentCallback, ProgressCallback) error + + // After process is called, return segments until the end of the stream + // is reached, when io.EOF is returned. + NextSegment() (Segment, error) + + IsBEG(Token) bool // Test for "begin" token + IsSOT(Token) bool // Test for "start of transcription" token + IsEOT(Token) bool // Test for "end of transcription" token + IsPREV(Token) bool // Test for "start of prev" token + IsSOLM(Token) bool // Test for "start of lm" token + IsNOT(Token) bool // Test for "No timestamps" token + IsLANG(Token, string) bool // Test for token associated with a specific language + IsText(Token) bool // Test for text token + + // Timings + PrintTimings() + ResetTimings() + + SystemInfo() string +} + +// Segment is the text result of a speech recognition. +type Segment struct { + // Segment Number + Num int + + // Time beginning and end timestamps for the segment. + Start, End time.Duration + + // The text of the segment. + Text string + + // The tokens of the segment. + Tokens []Token +} + +// Token is a text or special token +type Token struct { + Id int + Text string + P float32 + Start, End time.Duration +} diff --git a/bindings/go/pkg/whisper/model.go b/bindings/go/pkg/whisper/model.go new file mode 100644 index 0000000..68a1502 --- /dev/null +++ b/bindings/go/pkg/whisper/model.go @@ -0,0 +1,101 @@ +package whisper + +import ( + "fmt" + "os" + "runtime" + + // Bindings + whisper "github.com/ggerganov/whisper.cpp/bindings/go" +) + +/////////////////////////////////////////////////////////////////////////////// +// TYPES + +type model struct { + path string + ctx *whisper.Context +} + +// Make sure model adheres to the interface +var _ Model = (*model)(nil) + +/////////////////////////////////////////////////////////////////////////////// +// LIFECYCLE + +func New(path string) (Model, error) { + model := new(model) + if _, err := os.Stat(path); err != nil { + return nil, err + } else if ctx := whisper.Whisper_init(path); ctx == nil { + return nil, ErrUnableToLoadModel + } else { + model.ctx = ctx + model.path = path + } + + // Return success + return model, nil +} + +func (model *model) Close() error { + if model.ctx != nil { + model.ctx.Whisper_free() + } + + // Release resources + model.ctx = nil + + // Return success + return nil +} + +/////////////////////////////////////////////////////////////////////////////// +// STRINGIFY + +func (model *model) String() string { + str := "<whisper.model" + if model.ctx != nil { + str += fmt.Sprintf(" model=%q", model.path) + } + return str + ">" +} + +/////////////////////////////////////////////////////////////////////////////// +// PUBLIC METHODS + +// Return true if model is multilingual (language and translation options are supported) +func (model *model) IsMultilingual() bool { + return model.ctx.Whisper_is_multilingual() != 0 +} + +// Return all recognized languages. Initially it is set to auto-detect +func (model *model) Languages() []string { + result := make([]string, 0, whisper.Whisper_lang_max_id()) + for i := 0; i < whisper.Whisper_lang_max_id(); i++ { + str := whisper.Whisper_lang_str(i) + if model.ctx.Whisper_lang_id(str) >= 0 { + result = append(result, str) + } + } + return result +} + +func (model *model) NewContext() (Context, error) { + if model.ctx == nil { + return nil, ErrInternalAppError + } + + // Create new context + params := model.ctx.Whisper_full_default_params(whisper.SAMPLING_GREEDY) + params.SetTranslate(false) + params.SetPrintSpecial(false) + params.SetPrintProgress(false) + params.SetPrintRealtime(false) + params.SetPrintTimestamps(false) + params.SetThreads(runtime.NumCPU()) + params.SetNoContext(true) + + // Return new context + return newContext(model, params) +} diff --git a/bindings/go/pkg/whisper/model_test.go b/bindings/go/pkg/whisper/model_test.go new file mode 100644 index 0000000..8797f0d --- /dev/null +++ b/bindings/go/pkg/whisper/model_test.go @@ -0,0 +1,91 @@ +package whisper_test + +import ( + "testing" + + "github.com/ggerganov/whisper.cpp/bindings/go/pkg/whisper" + assert "github.com/stretchr/testify/assert" +) + +func TestNew(t *testing.T) { + assert := assert.New(t) + t.Run("valid model path", func(t *testing.T) { + model, err := whisper.New(ModelPath) + assert.NoError(err) + assert.NotNil(model) + defer model.Close() + + }) + + t.Run("invalid model path", func(t *testing.T) { + invalidModelPath := "invalid-model-path.bin" + model, err := whisper.New(invalidModelPath) + assert.Error(err) + assert.Nil(model) + }) +} + +func TestClose(t *testing.T) { + assert := assert.New(t) + + model, err := whisper.New(ModelPath) + assert.NoError(err) + assert.NotNil(model) + + err = model.Close() + assert.NoError(err) +} + +func TestNewContext(t *testing.T) { + assert := assert.New(t) + + model, err := whisper.New(ModelPath) + assert.NoError(err) + assert.NotNil(model) + defer model.Close() + + context, err := model.NewContext() + assert.NoError(err) + assert.NotNil(context) +} + +func TestIsMultilingual(t *testing.T) { + assert := assert.New(t) + + model, err := whisper.New(ModelPath) + assert.NoError(err) + assert.NotNil(model) + defer model.Close() + + isMultilingual := model.IsMultilingual() + + // This returns false since + // the model 'models/ggml-small.en.bin' + // that is loaded is not multilingual + assert.False(isMultilingual) +} + +func TestLanguages(t *testing.T) { + assert := assert.New(t) + + model, err := whisper.New(ModelPath) + assert.NoError(err) + assert.NotNil(model) + defer model.Close() + + expectedLanguages := []string{ + "en", "zh", "de", "es", "ru", "ko", "fr", "ja", "pt", "tr", "pl", + "ca", "nl", "ar", "sv", "it", "id", "hi", "fi", "vi", "he", "uk", + "el", "ms", "cs", "ro", "da", "hu", "ta", "no", "th", "ur", "hr", + "bg", "lt", "la", "mi", "ml", "cy", "sk", "te", "fa", "lv", "bn", + "sr", "az", "sl", "kn", "et", "mk", "br", "eu", "is", "hy", "ne", + "mn", "bs", "kk", "sq", "sw", "gl", "mr", "pa", "si", "km", "sn", + "yo", "so", "af", "oc", "ka", "be", "tg", "sd", "gu", "am", "yi", + "lo", "uz", "fo", "ht", "ps", "tk", "nn", "mt", "sa", "lb", "my", + "bo", "tl", "mg", "as", "tt", "haw", "ln", "ha", "ba", "jw", "su", + } + + actualLanguages := model.Languages() + + assert.Equal(expectedLanguages, actualLanguages) +} diff --git a/bindings/go/pkg/whisper/util_test.go b/bindings/go/pkg/whisper/util_test.go new file mode 100644 index 0000000..8ea2d5b --- /dev/null +++ b/bindings/go/pkg/whisper/util_test.go @@ -0,0 +1,6 @@ +package whisper_test + +const ( + ModelPath = "../../models/ggml-small.en.bin" + SamplePath = "../../samples/jfk.wav" +) diff --git a/bindings/go/samples/jfk.wav b/bindings/go/samples/jfk.wav new file mode 100644 index 0000000000000000000000000000000000000000..3184d372cd2f8b804d3a540c70ec50d927b335d2 GIT binary patch literal 352078 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�^Q!L_W@a=e*Zxws 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�<VGy@d-){RZyMRwQQTnP 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 literal 0 HcmV?d00001 diff --git a/bindings/go/whisper.go b/bindings/go/whisper.go new file mode 100644 index 0000000..3ef7341 --- /dev/null +++ b/bindings/go/whisper.go @@ -0,0 +1,470 @@ +package whisper + +import ( + "errors" + "unsafe" +) + +/////////////////////////////////////////////////////////////////////////////// +// CGO + +/* +#cgo LDFLAGS: -lwhisper -lggml -lggml-base -lggml-cpu -lm -lstdc++ +#cgo linux LDFLAGS: -fopenmp +#cgo darwin LDFLAGS: -lggml-metal -lggml-blas +#cgo darwin LDFLAGS: -framework Accelerate -framework Metal -framework Foundation -framework CoreGraphics +#include <whisper.h> +#include <stdlib.h> + +extern void callNewSegment(void* user_data, int new); +extern void callProgress(void* user_data, int progress); +extern bool callEncoderBegin(void* user_data); + +// Text segment callback +// Called on every newly generated text segment +// Use the whisper_full_...() functions to obtain the text segments +static void whisper_new_segment_cb(struct whisper_context* ctx, struct whisper_state* state, int n_new, void* user_data) { + if(user_data != NULL && ctx != NULL) { + callNewSegment(user_data, n_new); + } +} + +// Progress callback +// Called on every newly generated text segment +// Use the whisper_full_...() functions to obtain the text segments +static void whisper_progress_cb(struct whisper_context* ctx, struct whisper_state* state, int progress, void* user_data) { + if(user_data != NULL && ctx != NULL) { + callProgress(user_data, progress); + } +} + +// Encoder begin callback +// If not NULL, called before the encoder starts +// If it returns false, the computation is aborted +static bool whisper_encoder_begin_cb(struct whisper_context* ctx, struct whisper_state* state, void* user_data) { + if(user_data != NULL && ctx != NULL) { + return callEncoderBegin(user_data); + } + return false; +} + +// Get default parameters and set callbacks +static struct whisper_full_params whisper_full_default_params_cb(struct whisper_context* ctx, enum whisper_sampling_strategy strategy) { + struct whisper_full_params params = whisper_full_default_params(strategy); + params.new_segment_callback = whisper_new_segment_cb; + params.new_segment_callback_user_data = (void*)(ctx); + params.encoder_begin_callback = whisper_encoder_begin_cb; + params.encoder_begin_callback_user_data = (void*)(ctx); + params.progress_callback = whisper_progress_cb; + params.progress_callback_user_data = (void*)(ctx); + return params; +} +*/ +import "C" + +/////////////////////////////////////////////////////////////////////////////// +// TYPES + +type ( + Context C.struct_whisper_context + Token C.whisper_token + TokenData C.struct_whisper_token_data + SamplingStrategy C.enum_whisper_sampling_strategy + Params C.struct_whisper_full_params +) + +/////////////////////////////////////////////////////////////////////////////// +// GLOBALS + +const ( + SAMPLING_GREEDY SamplingStrategy = C.WHISPER_SAMPLING_GREEDY + SAMPLING_BEAM_SEARCH SamplingStrategy = C.WHISPER_SAMPLING_BEAM_SEARCH +) + +const ( + SampleRate = C.WHISPER_SAMPLE_RATE // Expected sample rate, samples per second + SampleBits = uint16(unsafe.Sizeof(C.float(0))) * 8 // Sample size in bits + NumFFT = C.WHISPER_N_FFT + HopLength = C.WHISPER_HOP_LENGTH + ChunkSize = C.WHISPER_CHUNK_SIZE +) + +var ( + ErrTokenizerFailed = errors.New("whisper_tokenize failed") + ErrAutoDetectFailed = errors.New("whisper_lang_auto_detect failed") + ErrConversionFailed = errors.New("whisper_convert failed") + ErrInvalidLanguage = errors.New("invalid language") +) + +/////////////////////////////////////////////////////////////////////////////// +// PUBLIC METHODS + +// Allocates all memory needed for the model and loads the model from the given file. +// Returns NULL on failure. +func Whisper_init(path string) *Context { + cPath := C.CString(path) + defer C.free(unsafe.Pointer(cPath)) + if ctx := C.whisper_init_from_file_with_params(cPath, C.whisper_context_default_params()); ctx != nil { + return (*Context)(ctx) + } else { + return nil + } +} + +// Frees all memory allocated by the model. +func (ctx *Context) Whisper_free() { + C.whisper_free((*C.struct_whisper_context)(ctx)) +} + +// Convert RAW PCM audio to log mel spectrogram. +// The resulting spectrogram is stored inside the provided whisper context. +func (ctx *Context) Whisper_pcm_to_mel(data []float32, threads int) error { + if C.whisper_pcm_to_mel((*C.struct_whisper_context)(ctx), (*C.float)(&data[0]), C.int(len(data)), C.int(threads)) == 0 { + return nil + } else { + return ErrConversionFailed + } +} + +// This can be used to set a custom log mel spectrogram inside the provided whisper context. +// Use this instead of whisper_pcm_to_mel() if you want to provide your own log mel spectrogram. +// n_mel must be 80 +func (ctx *Context) Whisper_set_mel(data []float32, n_mel int) error { + if C.whisper_set_mel((*C.struct_whisper_context)(ctx), (*C.float)(&data[0]), C.int(len(data)), C.int(n_mel)) == 0 { + return nil + } else { + return ErrConversionFailed + } +} + +// Run the Whisper encoder on the log mel spectrogram stored inside the provided whisper context. +// Make sure to call whisper_pcm_to_mel() or whisper_set_mel() first. +// offset can be used to specify the offset of the first frame in the spectrogram. +func (ctx *Context) Whisper_encode(offset, threads int) error { + if C.whisper_encode((*C.struct_whisper_context)(ctx), C.int(offset), C.int(threads)) == 0 { + return nil + } else { + return ErrConversionFailed + } +} + +// Run the Whisper decoder to obtain the logits and probabilities for the next token. +// Make sure to call whisper_encode() first. +// tokens + n_tokens is the provided context for the decoder. +// n_past is the number of tokens to use from previous decoder calls. +func (ctx *Context) Whisper_decode(tokens []Token, past, threads int) error { + if C.whisper_decode((*C.struct_whisper_context)(ctx), (*C.whisper_token)(&tokens[0]), C.int(len(tokens)), C.int(past), C.int(threads)) == 0 { + return nil + } else { + return ErrConversionFailed + } +} + +// Convert the provided text into tokens. The tokens pointer must be large enough to hold the resulting tokens. +// Returns the number of tokens on success +func (ctx *Context) Whisper_tokenize(text string, tokens []Token) (int, error) { + cText := C.CString(text) + defer C.free(unsafe.Pointer(cText)) + if n := C.whisper_tokenize((*C.struct_whisper_context)(ctx), cText, (*C.whisper_token)(&tokens[0]), C.int(len(tokens))); n >= 0 { + return int(n), nil + } else { + return 0, ErrTokenizerFailed + } +} + +// Return the id of the specified language, returns -1 if not found +// Examples: +// +// "de" -> 2 +// "german" -> 2 +func (ctx *Context) Whisper_lang_id(lang string) int { + return int(C.whisper_lang_id(C.CString(lang))) +} + +// Largest language id (i.e. number of available languages - 1) +func Whisper_lang_max_id() int { + return int(C.whisper_lang_max_id()) +} + +// Return the short string of the specified language id (e.g. 2 -> "de"), +// returns empty string if not found +func Whisper_lang_str(id int) string { + return C.GoString(C.whisper_lang_str(C.int(id))) +} + +// Use mel data at offset_ms to try and auto-detect the spoken language +// Make sure to call whisper_pcm_to_mel() or whisper_set_mel() first. +// Returns the probabilities of all languages. +// ref: https://github.com/openai/whisper/blob/main/whisper/decoding.py#L18-L69 +func (ctx *Context) Whisper_lang_auto_detect(offset_ms, n_threads int) ([]float32, error) { + probs := make([]float32, Whisper_lang_max_id()+1) + if n := int(C.whisper_lang_auto_detect((*C.struct_whisper_context)(ctx), C.int(offset_ms), C.int(n_threads), (*C.float)(&probs[0]))); n < 0 { + return nil, ErrAutoDetectFailed + } else { + return probs, nil + } +} + +func (ctx *Context) Whisper_n_len() int { + return int(C.whisper_n_len((*C.struct_whisper_context)(ctx))) +} + +func (ctx *Context) Whisper_n_vocab() int { + return int(C.whisper_n_vocab((*C.struct_whisper_context)(ctx))) +} + +func (ctx *Context) Whisper_n_text_ctx() int { + return int(C.whisper_n_text_ctx((*C.struct_whisper_context)(ctx))) +} + +func (ctx *Context) Whisper_n_audio_ctx() int { + return int(C.whisper_n_audio_ctx((*C.struct_whisper_context)(ctx))) +} + +func (ctx *Context) Whisper_is_multilingual() int { + return int(C.whisper_is_multilingual((*C.struct_whisper_context)(ctx))) +} + +// The probabilities for the next token +//func (ctx *Whisper_context) Whisper_get_probs() []float32 { +// return (*[1 << 30]float32)(unsafe.Pointer(C.whisper_get_probs((*C.struct_whisper_context)(ctx))))[:ctx.Whisper_n_vocab()] +//} + +// Token Id -> String. Uses the vocabulary in the provided context +func (ctx *Context) Whisper_token_to_str(token Token) string { + return C.GoString(C.whisper_token_to_str((*C.struct_whisper_context)(ctx), C.whisper_token(token))) +} + +// Special tokens +func (ctx *Context) Whisper_token_eot() Token { + return Token(C.whisper_token_eot((*C.struct_whisper_context)(ctx))) +} + +// Special tokens +func (ctx *Context) Whisper_token_sot() Token { + return Token(C.whisper_token_sot((*C.struct_whisper_context)(ctx))) +} + +// Special tokens +func (ctx *Context) Whisper_token_prev() Token { + return Token(C.whisper_token_prev((*C.struct_whisper_context)(ctx))) +} + +// Special tokens +func (ctx *Context) Whisper_token_solm() Token { + return Token(C.whisper_token_solm((*C.struct_whisper_context)(ctx))) +} + +// Special tokens +func (ctx *Context) Whisper_token_not() Token { + return Token(C.whisper_token_not((*C.struct_whisper_context)(ctx))) +} + +// Special tokens +func (ctx *Context) Whisper_token_beg() Token { + return Token(C.whisper_token_beg((*C.struct_whisper_context)(ctx))) +} + +// Special tokens +func (ctx *Context) Whisper_token_lang(lang_id int) Token { + return Token(C.whisper_token_lang((*C.struct_whisper_context)(ctx), C.int(lang_id))) +} + +// Task tokens +func (ctx *Context) Whisper_token_translate() Token { + return Token(C.whisper_token_translate((*C.struct_whisper_context)(ctx))) +} + +// Task tokens +func (ctx *Context) Whisper_token_transcribe() Token { + return Token(C.whisper_token_transcribe((*C.struct_whisper_context)(ctx))) +} + +// Performance information +func (ctx *Context) Whisper_print_timings() { + C.whisper_print_timings((*C.struct_whisper_context)(ctx)) +} + +// Performance information +func (ctx *Context) Whisper_reset_timings() { + C.whisper_reset_timings((*C.struct_whisper_context)(ctx)) +} + +// Print system information +func Whisper_print_system_info() string { + return C.GoString(C.whisper_print_system_info()) +} + +// Return default parameters for a strategy +func (ctx *Context) Whisper_full_default_params(strategy SamplingStrategy) Params { + // Get default parameters + return Params(C.whisper_full_default_params_cb((*C.struct_whisper_context)(ctx), C.enum_whisper_sampling_strategy(strategy))) +} + +// Run the entire model: PCM -> log mel spectrogram -> encoder -> decoder -> text +// Uses the specified decoding strategy to obtain the text. +func (ctx *Context) Whisper_full( + params Params, + samples []float32, + encoderBeginCallback func() bool, + newSegmentCallback func(int), + progressCallback func(int), +) error { + registerEncoderBeginCallback(ctx, encoderBeginCallback) + registerNewSegmentCallback(ctx, newSegmentCallback) + registerProgressCallback(ctx, progressCallback) + defer registerEncoderBeginCallback(ctx, nil) + defer registerNewSegmentCallback(ctx, nil) + defer registerProgressCallback(ctx, nil) + if C.whisper_full((*C.struct_whisper_context)(ctx), (C.struct_whisper_full_params)(params), (*C.float)(&samples[0]), C.int(len(samples))) == 0 { + return nil + } else { + return ErrConversionFailed + } +} + +// Split the input audio in chunks and process each chunk separately using whisper_full() +// It seems this approach can offer some speedup in some cases. +// However, the transcription accuracy can be worse at the beginning and end of each chunk. +func (ctx *Context) Whisper_full_parallel(params Params, samples []float32, processors int, encoderBeginCallback func() bool, newSegmentCallback func(int)) error { + registerEncoderBeginCallback(ctx, encoderBeginCallback) + registerNewSegmentCallback(ctx, newSegmentCallback) + defer registerEncoderBeginCallback(ctx, nil) + defer registerNewSegmentCallback(ctx, nil) + + if C.whisper_full_parallel((*C.struct_whisper_context)(ctx), (C.struct_whisper_full_params)(params), (*C.float)(&samples[0]), C.int(len(samples)), C.int(processors)) == 0 { + return nil + } else { + return ErrConversionFailed + } +} + +// Return the id of the autodetected language, returns -1 if not found +// Added to whisper.cpp in +// https://github.com/ggerganov/whisper.cpp/commit/a1c1583cc7cd8b75222857afc936f0638c5683d6 +// +// Examples: +// +// "de" -> 2 +// "german" -> 2 +func (ctx *Context) Whisper_full_lang_id() int { + return int(C.whisper_full_lang_id((*C.struct_whisper_context)(ctx))) +} + +// Number of generated text segments. +// A segment can be a few words, a sentence, or even a paragraph. +func (ctx *Context) Whisper_full_n_segments() int { + return int(C.whisper_full_n_segments((*C.struct_whisper_context)(ctx))) +} + +// Get the start and end time of the specified segment. +func (ctx *Context) Whisper_full_get_segment_t0(segment int) int64 { + return int64(C.whisper_full_get_segment_t0((*C.struct_whisper_context)(ctx), C.int(segment))) +} + +// Get the start and end time of the specified segment. +func (ctx *Context) Whisper_full_get_segment_t1(segment int) int64 { + return int64(C.whisper_full_get_segment_t1((*C.struct_whisper_context)(ctx), C.int(segment))) +} + +// Get the text of the specified segment. +func (ctx *Context) Whisper_full_get_segment_text(segment int) string { + return C.GoString(C.whisper_full_get_segment_text((*C.struct_whisper_context)(ctx), C.int(segment))) +} + +// Get number of tokens in the specified segment. +func (ctx *Context) Whisper_full_n_tokens(segment int) int { + return int(C.whisper_full_n_tokens((*C.struct_whisper_context)(ctx), C.int(segment))) +} + +// Get the token text of the specified token index in the specified segment. +func (ctx *Context) Whisper_full_get_token_text(segment int, token int) string { + return C.GoString(C.whisper_full_get_token_text((*C.struct_whisper_context)(ctx), C.int(segment), C.int(token))) +} + +// Get the token of the specified token index in the specified segment. +func (ctx *Context) Whisper_full_get_token_id(segment int, token int) Token { + return Token(C.whisper_full_get_token_id((*C.struct_whisper_context)(ctx), C.int(segment), C.int(token))) +} + +// Get token data for the specified token in the specified segment. +// This contains probabilities, timestamps, etc. +func (ctx *Context) Whisper_full_get_token_data(segment int, token int) TokenData { + return TokenData(C.whisper_full_get_token_data((*C.struct_whisper_context)(ctx), C.int(segment), C.int(token))) +} + +// Get the probability of the specified token in the specified segment. +func (ctx *Context) Whisper_full_get_token_p(segment int, token int) float32 { + return float32(C.whisper_full_get_token_p((*C.struct_whisper_context)(ctx), C.int(segment), C.int(token))) +} + +/////////////////////////////////////////////////////////////////////////////// +// CALLBACKS + +var ( + cbNewSegment = make(map[unsafe.Pointer]func(int)) + cbProgress = make(map[unsafe.Pointer]func(int)) + cbEncoderBegin = make(map[unsafe.Pointer]func() bool) +) + +func registerNewSegmentCallback(ctx *Context, fn func(int)) { + if fn == nil { + delete(cbNewSegment, unsafe.Pointer(ctx)) + } else { + cbNewSegment[unsafe.Pointer(ctx)] = fn + } +} + +func registerProgressCallback(ctx *Context, fn func(int)) { + if fn == nil { + delete(cbProgress, unsafe.Pointer(ctx)) + } else { + cbProgress[unsafe.Pointer(ctx)] = fn + } +} + +func registerEncoderBeginCallback(ctx *Context, fn func() bool) { + if fn == nil { + delete(cbEncoderBegin, unsafe.Pointer(ctx)) + } else { + cbEncoderBegin[unsafe.Pointer(ctx)] = fn + } +} + +//export callNewSegment +func callNewSegment(user_data unsafe.Pointer, new C.int) { + if fn, ok := cbNewSegment[user_data]; ok { + fn(int(new)) + } +} + +//export callProgress +func callProgress(user_data unsafe.Pointer, progress C.int) { + if fn, ok := cbProgress[user_data]; ok { + fn(int(progress)) + } +} + +//export callEncoderBegin +func callEncoderBegin(user_data unsafe.Pointer) C.bool { + if fn, ok := cbEncoderBegin[user_data]; ok { + if fn() { + return C.bool(true) + } else { + return C.bool(false) + } + } + return true +} + +func (t TokenData) T0() int64 { + return int64(t.t0) +} + +func (t TokenData) T1() int64 { + return int64(t.t1) +} + +func (t TokenData) Id() Token { + return Token(t.id) +} diff --git a/bindings/go/whisper_test.go b/bindings/go/whisper_test.go new file mode 100644 index 0000000..40648ff --- /dev/null +++ b/bindings/go/whisper_test.go @@ -0,0 +1,113 @@ +package whisper_test + +import ( + "os" + "runtime" + "testing" + "time" + + // Packages + whisper "github.com/ggerganov/whisper.cpp/bindings/go" + wav "github.com/go-audio/wav" + assert "github.com/stretchr/testify/assert" +) + +const ( + ModelPath = "models/ggml-small.en.bin" + SamplePath = "samples/jfk.wav" +) + +func Test_Whisper_000(t *testing.T) { + assert := assert.New(t) + if _, err := os.Stat(ModelPath); os.IsNotExist(err) { + t.Skip("Skipping test, model not found:", ModelPath) + } + ctx := whisper.Whisper_init(ModelPath) + assert.NotNil(ctx) + ctx.Whisper_free() +} + +func Test_Whisper_001(t *testing.T) { + assert := assert.New(t) + if _, err := os.Stat(ModelPath); os.IsNotExist(err) { + t.Skip("Skipping test, model not found:", ModelPath) + } + if _, err := os.Stat(SamplePath); os.IsNotExist(err) { + t.Skip("Skipping test, sample not found:", SamplePath) + } + + // Open samples + fh, err := os.Open(SamplePath) + assert.NoError(err) + defer fh.Close() + + // Read samples + d := wav.NewDecoder(fh) + buf, err := d.FullPCMBuffer() + assert.NoError(err) + + // Run whisper + ctx := whisper.Whisper_init(ModelPath) + assert.NotNil(ctx) + defer ctx.Whisper_free() + params := ctx.Whisper_full_default_params(whisper.SAMPLING_GREEDY) + data := buf.AsFloat32Buffer().Data + err = ctx.Whisper_full(params, data, nil, nil, nil) + assert.NoError(err) + + // Print out tokens + num_segments := ctx.Whisper_full_n_segments() + assert.GreaterOrEqual(num_segments, 1) + for i := 0; i < num_segments; i++ { + str := ctx.Whisper_full_get_segment_text(i) + assert.NotEmpty(str) + t0 := time.Duration(ctx.Whisper_full_get_segment_t0(i)) * time.Millisecond + t1 := time.Duration(ctx.Whisper_full_get_segment_t1(i)) * time.Millisecond + t.Logf("[%6s->%-6s] %q", t0, t1, str) + } +} + +func Test_Whisper_002(t *testing.T) { + assert := assert.New(t) + for i := 0; i < whisper.Whisper_lang_max_id(); i++ { + str := whisper.Whisper_lang_str(i) + assert.NotEmpty(str) + t.Log(str) + } +} + +func Test_Whisper_003(t *testing.T) { + threads := runtime.NumCPU() + assert := assert.New(t) + if _, err := os.Stat(ModelPath); os.IsNotExist(err) { + t.Skip("Skipping test, model not found:", ModelPath) + } + if _, err := os.Stat(SamplePath); os.IsNotExist(err) { + t.Skip("Skipping test, sample not found:", SamplePath) + } + + // Open samples + fh, err := os.Open(SamplePath) + assert.NoError(err) + defer fh.Close() + + // Read samples + d := wav.NewDecoder(fh) + buf, err := d.FullPCMBuffer() + assert.NoError(err) + + // Make the model + ctx := whisper.Whisper_init(ModelPath) + assert.NotNil(ctx) + defer ctx.Whisper_free() + + // Get MEL + assert.NoError(ctx.Whisper_pcm_to_mel(buf.AsFloat32Buffer().Data, threads)) + + // Get Languages + languages, err := ctx.Whisper_lang_auto_detect(0, threads) + assert.NoError(err) + for i, p := range languages { + t.Logf("%s: %f", whisper.Whisper_lang_str(i), p) + } +} diff --git a/bindings/java/README.md b/bindings/java/README.md new file mode 100644 index 0000000..9042699 --- /dev/null +++ b/bindings/java/README.md @@ -0,0 +1,87 @@ +# Java JNI bindings for Whisper + +This package provides Java JNI bindings for whisper.cpp. They have been tested on: + + * <strike>Darwin (OS X) 12.6 on x64_64</strike> + * Ubuntu on x86_64 + * Windows on x86_64 + +The "low level" bindings are in `WhisperCppJnaLibrary`. The most simple usage is as follows: + +JNA will attempt to load the `whispercpp` shared library from: + +- jna.library.path +- jna.platform.library +- ~/Library/Frameworks +- /Library/Frameworks +- /System/Library/Frameworks +- classpath + +```java +import io.github.ggerganov.whispercpp.WhisperCpp; + +public class Example { + + public static void main(String[] args) { + + WhisperCpp whisper = new WhisperCpp(); + try { + // By default, models are loaded from ~/.cache/whisper/ and are usually named "ggml-${name}.bin" + // or you can provide the absolute path to the model file. + whisper.initContext("../ggml-base.en.bin"); + WhisperFullParams.ByValue whisperParams = whisper.getFullDefaultParams(WhisperSamplingStrategy.WHISPER_SAMPLING_BEAM_SEARCH); + + // custom configuration if required + //whisperParams.n_threads = 8; + whisperParams.temperature = 0.0f; + whisperParams.temperature_inc = 0.2f; + //whisperParams.language = "en"; + + float[] samples = readAudio(); // divide each value by 32767.0f + List<WhisperSegment> whisperSegmentList = whisper.fullTranscribeWithTime(whisperParams, samples); + + for (WhisperSegment whisperSegment : whisperSegmentList) { + + long start = whisperSegment.getStart(); + long end = whisperSegment.getEnd(); + + String text = whisperSegment.getSentence(); + + System.out.println("start: "+start); + System.out.println("end: "+end); + System.out.println("text: "+text); + + } + + } catch (IOException e) { + e.printStackTrace(); + } finally { + whisper.close(); + } + + } +} +``` + +## Building & Testing + +In order to build, you need to have the JDK 8 or higher installed. Run the tests with: + +```bash +git clone https://github.com/ggml-org/whisper.cpp.git +cd whisper.cpp/bindings/java + +./gradlew build +``` + +You need to have the `whisper` library in your [JNA library path](https://java-native-access.github.io/jna/4.2.1/com/sun/jna/NativeLibrary.html). On Windows the dll is included in the jar and you can update it: + +```bash +copy /y ..\..\build\bin\Release\whisper.dll build\generated\resources\main\win32-x86-64\whisper.dll +``` + + +## License + +The license for the Java bindings is the same as the license for the rest of the whisper.cpp project, which is the MIT License. See the `LICENSE` file for more details. + diff --git a/bindings/java/build.gradle b/bindings/java/build.gradle new file mode 100644 index 0000000..30184ee --- /dev/null +++ b/bindings/java/build.gradle @@ -0,0 +1,159 @@ +plugins { + id 'java' + id 'java-library' + id 'maven-publish' + id 'signing' +} + +archivesBaseName = 'whispercpp' +group = 'io.github.ggerganov' +version = '1.4.0' + + +sourceCompatibility = 1.8 +targetCompatibility = 1.8 + +sourceSets { + main { + resources { + srcDirs = ['src/main/resources', 'build/generated/resources/main'] + } + } + test { + runtimeClasspath += files('build/generated/resources/main') + } +} + +tasks.register('copyLibwhisperDynlib', Copy) { + from '../../build/src' + include 'libwhisper.dylib' + into 'build/generated/resources/main' +} + +tasks.register('copyLibwhisperSo', Copy) { + from '../../build/src' + include 'libwhisper.so' + into 'build/generated/resources/main' +} + +tasks.register('copyWhisperDLL', Copy) { + from '../../build/bin/Release' + include 'whisper.dll' + into 'build/generated/resources/main' +} + +tasks.register('copyGGML_BASE_DLL', Copy) { + from '../../build/bin/Release' + include 'ggml-base.dll' + into 'build/generated/resources/main' +} + +tasks.register('copyGGML_DLL', Copy) { + from '../../build/bin/Release' + include 'ggml.dll' + into 'build/generated/resources/main' +} + +tasks.register('copyGGML_CPU_DLL', Copy) { + from '../../build/bin/Release' + include 'ggml-cpu.dll' + into 'build/generated/resources/main' +} + +tasks.register('copyLibs') { + dependsOn copyLibwhisperDynlib, copyLibwhisperSo, copyWhisperDLL, copyGGML_BASE_DLL, copyGGML_DLL, copyGGML_CPU_DLL +} + +test { + systemProperty 'jna.library.path', project.file('build/generated/resources/main').absolutePath +} + +java { + withSourcesJar() + withJavadocJar() +} + +sourcesJar() { + dependsOn copyLibs +} + +jar { + dependsOn copyLibs + exclude '**/whisper_java.exp', '**/whisper_java.lib' +} + +javadoc { + options.addStringOption('Xdoclint:none', '-quiet') +} + +tasks.withType(Test) { + useJUnitPlatform() +} + +test.dependsOn copyLibs +processResources.dependsOn copyLibs + +dependencies { + implementation "net.java.dev.jna:jna:5.13.0" + testImplementation "org.junit.jupiter:junit-jupiter:5.9.2" + testImplementation "org.assertj:assertj-core:3.24.2" +} + +repositories { + mavenCentral() +} + +publishing { + publications { + mavenJava(MavenPublication) { + artifactId = 'whispercpp' + from components.java + pom { + name = 'whispercpp' + description = "Java JNA bindings for OpenAI's Whisper model, implemented in C/C++" + url = 'https://github.com/ggerganov/whisper.cpp' + licenses { + license { + name = 'MIT licence' + url = 'https://raw.githubusercontent.com/ggerganov/whisper.cpp/master/LICENSE' + } + } + developers { + developer { + id = 'ggerganov' + name = 'Georgi Gerganov' + email = 'ggerganov@gmail.com' + } + developer { + id = 'nalbion' + name = 'Nicholas Albion' + email = 'nalbion@yahoo.com' + } + } + scm { + connection = 'scm:git:git://github.com/ggerganov/whisper.cpp.git' + url = 'https://github.com/ggerganov/whisper.cpp' + } + } + } + } + + repositories { + maven { + def releasesRepoUrl = 'https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/' + def snapshotsRepoUrl = 'https://s01.oss.sonatype.org/content/repositories/snapshots/' + url = version.endsWith('-SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl + credentials { + username = System.getenv("MAVEN_USERNAME") + password = System.getenv("MAVEN_PASSWORD") + } + } + } +} + +signing { + def signingKey = System.getenv("PGP_SECRET") + def signingPassword = System.getenv("PGP_PASSPHRASE") + useInMemoryPgpKeys(signingKey, signingPassword) + sign publishing.publications.mavenJava +} diff --git a/bindings/java/gradle.properties b/bindings/java/gradle.properties new file mode 100644 index 0000000..3ea68c2 --- /dev/null +++ b/bindings/java/gradle.properties @@ -0,0 +1,6 @@ +org.gradle.jvmargs=-Xms256m -Xmx1024m +system.include.dir=/usr/include +#system.local.include.dir=../../include +system.local.include.dir=./build/generated/sources/headers/java/main +jni.include.dir=/usr/lib/jvm/java-8-openjdk-amd64/include/ +jni.lib.dir=/usr/lib/jvm/java-8-openjdk-amd64/lib/ diff --git a/bindings/java/gradle/wrapper/gradle-wrapper.jar b/bindings/java/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..ccebba7710deaf9f98673a68957ea02138b60d0a GIT binary patch literal 61608 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 Njln_&>W!lQ`ah3D4r%}Z literal 0 HcmV?d00001 diff --git a/bindings/java/gradle/wrapper/gradle-wrapper.properties b/bindings/java/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..0c85a1f --- /dev/null +++ b/bindings/java/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.1-bin.zip +networkTimeout=10000 +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/bindings/java/gradlew b/bindings/java/gradlew new file mode 100755 index 0000000..79a61d4 --- /dev/null +++ b/bindings/java/gradlew @@ -0,0 +1,244 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# 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. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/bindings/java/gradlew.bat b/bindings/java/gradlew.bat new file mode 100644 index 0000000..6689b85 --- /dev/null +++ b/bindings/java/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/bindings/java/settings.gradle b/bindings/java/settings.gradle new file mode 100644 index 0000000..dbc6f38 --- /dev/null +++ b/bindings/java/settings.gradle @@ -0,0 +1 @@ +rootProject.name = "whispercpp" diff --git a/bindings/java/src/main/java/io/github/ggerganov/whispercpp/WhisperConstants.java b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/WhisperConstants.java new file mode 100644 index 0000000..0c828f1 --- /dev/null +++ b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/WhisperConstants.java @@ -0,0 +1,24 @@ +package io.github.ggerganov.whispercpp; + +/** + * Presets for alignment heads in DTW token timestamps + */ +public class WhisperConstants { + // Alignment heads presets + public static final int WHISPER_AHEADS_NONE = 0; + public static final int WHISPER_AHEADS_TINY_EN = 1; + public static final int WHISPER_AHEADS_TINY = 2; + public static final int WHISPER_AHEADS_BASE_EN = 3; + public static final int WHISPER_AHEADS_BASE = 4; + public static final int WHISPER_AHEADS_SMALL_EN = 5; + public static final int WHISPER_AHEADS_SMALL = 6; + public static final int WHISPER_AHEADS_MEDIUM_EN = 7; + public static final int WHISPER_AHEADS_MEDIUM = 8; + public static final int WHISPER_AHEADS_LARGE_V1 = 9; + public static final int WHISPER_AHEADS_LARGE_V2 = 10; + public static final int WHISPER_AHEADS_LARGE_V3 = 11; + public static final int WHISPER_AHEADS_LARGE_V3_TURBO = 12; + public static final int WHISPER_AHEADS_CUSTOM = 13; + public static final int WHISPER_AHEADS_N_TOP_MOST = 14; + public static final int WHISPER_AHEADS_COUNT = 15; +} diff --git a/bindings/java/src/main/java/io/github/ggerganov/whispercpp/WhisperContext.java b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/WhisperContext.java new file mode 100644 index 0000000..7ac124e --- /dev/null +++ b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/WhisperContext.java @@ -0,0 +1,36 @@ +package io.github.ggerganov.whispercpp; + +import com.sun.jna.NativeLong; +import com.sun.jna.Structure; +import com.sun.jna.ptr.PointerByReference; +import com.sun.jna.Pointer; +import io.github.ggerganov.whispercpp.ggml.GgmlType; +import io.github.ggerganov.whispercpp.WhisperModel; +import io.github.ggerganov.whispercpp.params.WhisperContextParams; + +import java.util.List; + +public class WhisperContext extends Structure { + public NativeLong t_load_us; + public NativeLong t_start_us; + + /** weight type (FP32 / FP16 / QX) */ + public GgmlType wtype = GgmlType.GGML_TYPE_F16; + /** intermediate type (FP32 or FP16) */ + public GgmlType itype = GgmlType.GGML_TYPE_F16; + + public WhisperContextParams.ByValue params; + + public Pointer model; + public Pointer vocab; + public Pointer state; + + /** populated by whisper_init_from_file_with_params() */ + public Pointer path_model; + + @Override + protected List<String> getFieldOrder() { + return List.of("t_load_us", "t_start_us", "wtype", "itype", + "params", "model", "vocab", "state", "path_model"); + } +} diff --git a/bindings/java/src/main/java/io/github/ggerganov/whispercpp/WhisperCpp.java b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/WhisperCpp.java new file mode 100644 index 0000000..cc53148 --- /dev/null +++ b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/WhisperCpp.java @@ -0,0 +1,219 @@ +package io.github.ggerganov.whispercpp; + +import com.sun.jna.Native; +import com.sun.jna.Pointer; +import io.github.ggerganov.whispercpp.bean.WhisperSegment; +import io.github.ggerganov.whispercpp.params.WhisperContextParams; +import io.github.ggerganov.whispercpp.params.WhisperFullParams; +import io.github.ggerganov.whispercpp.params.WhisperSamplingStrategy; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * Before calling most methods, you must call `initContext(modelPath)` to initialise the `ctx` Pointer. + */ +public class WhisperCpp implements AutoCloseable { + private WhisperCppJnaLibrary lib = WhisperCppJnaLibrary.instance; + private Pointer ctx = null; + private Pointer paramsPointer = null; + private Pointer greedyParamsPointer = null; + private Pointer beamParamsPointer = null; + + public File modelDir() { + String modelDirPath = System.getenv("XDG_CACHE_HOME"); + if (modelDirPath == null) { + modelDirPath = System.getProperty("user.home") + "/.cache"; + } + + return new File(modelDirPath, "whisper"); + } + + /** + * @param modelPath - absolute path, or just the name (eg: "base", "base-en" or "base.en") + */ + public void initContext(String modelPath) throws FileNotFoundException { + initContextImpl(modelPath, getContextDefaultParams()); + } + + /** + * @param modelPath - absolute path, or just the name (eg: "base", "base-en" or "base.en") + * @param params - params to use when initialising the context + */ + public void initContext(String modelPath, WhisperContextParams.ByValue params) throws FileNotFoundException { + initContextImpl(modelPath, params); + } + + private void initContextImpl(String modelPath, WhisperContextParams.ByValue params) throws FileNotFoundException { + if (ctx != null) { + lib.whisper_free(ctx); + } + + if (!modelPath.contains("/") && !modelPath.contains("\\")) { + if (!modelPath.endsWith(".bin")) { + modelPath = "ggml-" + modelPath.replace("-", ".") + ".bin"; + } + + modelPath = new File(modelDir(), modelPath).getAbsolutePath(); + } + + ctx = lib.whisper_init_from_file_with_params(modelPath, params); + + if (ctx == null) { + throw new FileNotFoundException(modelPath); + } + } + + /** + * Provides default params which can be used with `whisper_init_from_file_with_params()` etc. + * Returns a ByValue instance to ensure proper parameter passing to native code. + */ + public WhisperContextParams.ByValue getContextDefaultParams() { + WhisperContextParams.ByValue valueParams = new WhisperContextParams.ByValue( + lib.whisper_context_default_params_by_ref()); + valueParams.read(); + return valueParams; + } + + /** + * Provides default params which can be used with `whisper_full()` etc. + * Because this function allocates memory for the params, the caller must call either: + * - call `whisper_free_params()` + * - `Native.free(Pointer.nativeValue(pointer));` + * + * @param strategy - GREEDY + */ + public WhisperFullParams.ByValue getFullDefaultParams(WhisperSamplingStrategy strategy) { + Pointer pointer; + + // whisper_full_default_params_by_ref allocates memory which we need to delete, so only create max 1 pointer for each strategy. + if (strategy == WhisperSamplingStrategy.WHISPER_SAMPLING_GREEDY) { + if (greedyParamsPointer == null) { + greedyParamsPointer = lib.whisper_full_default_params_by_ref(strategy.ordinal()); + } + pointer = greedyParamsPointer; + } else { + if (beamParamsPointer == null) { + beamParamsPointer = lib.whisper_full_default_params_by_ref(strategy.ordinal()); + } + pointer = beamParamsPointer; + } + + WhisperFullParams.ByValue params = new WhisperFullParams.ByValue(pointer); + params.read(); + return params; + } + + @Override + public void close() { + freeContext(); + freeParams(); + System.out.println("Whisper closed"); + } + + private void freeContext() { + if (ctx != null) { + lib.whisper_free(ctx); + } + } + + private void freeParams() { + if (paramsPointer != null) { + Native.free(Pointer.nativeValue(paramsPointer)); + paramsPointer = null; + } + if (greedyParamsPointer != null) { + Native.free(Pointer.nativeValue(greedyParamsPointer)); + greedyParamsPointer = null; + } + if (beamParamsPointer != null) { + Native.free(Pointer.nativeValue(beamParamsPointer)); + beamParamsPointer = null; + } + } + + /** + * Run the entire model: PCM -> log mel spectrogram -> encoder -> decoder -> text. + * Not thread safe for same context + * Uses the specified decoding strategy to obtain the text. + */ + public String fullTranscribe(WhisperFullParams.ByValue whisperParams, float[] audioData) throws IOException { + if (ctx == null) { + throw new IllegalStateException("Model not initialised"); + } + + /* + WhisperFullParams.ByValue valueParams = new WhisperFullParams.ByValue( + lib.whisper_full_default_params_by_ref(WhisperSamplingStrategy.WHISPER_SAMPLING_BEAM_SEARCH.ordinal())); + valueParams.read(); + */ + + if (lib.whisper_full(ctx, whisperParams, audioData, audioData.length) != 0) { + throw new IOException("Failed to process audio"); + } + + int nSegments = lib.whisper_full_n_segments(ctx); + + StringBuilder str = new StringBuilder(); + + for (int i = 0; i < nSegments; i++) { + String text = lib.whisper_full_get_segment_text(ctx, i); + System.out.println("Segment:" + text); + str.append(text); + } + + return str.toString().trim(); + } + + /** + * Full transcribe with time list. + * + * @param whisperParams the whisper params + * @param audioData the audio data + * @return the list + * @throws IOException the io exception + */ + public List<WhisperSegment> fullTranscribeWithTime(WhisperFullParams.ByValue whisperParams, float[] audioData) throws IOException { + if (ctx == null) { + throw new IllegalStateException("Model not initialised"); + } + + if (lib.whisper_full(ctx, whisperParams, audioData, audioData.length) != 0) { + throw new IOException("Failed to process audio"); + } + + int nSegments = lib.whisper_full_n_segments(ctx); + List<WhisperSegment> segments= new ArrayList<>(nSegments); + + for (int i = 0; i < nSegments; i++) { + long t0 = lib.whisper_full_get_segment_t0(ctx, i); + String text = lib.whisper_full_get_segment_text(ctx, i); + long t1 = lib.whisper_full_get_segment_t1(ctx, i); + segments.add(new WhisperSegment(t0,t1,text)); + } + + return segments; + } + +// public int getTextSegmentCount(Pointer ctx) { +// return lib.whisper_full_n_segments(ctx); +// } +// public String getTextSegment(Pointer ctx, int index) { +// return lib.whisper_full_get_segment_text(ctx, index); +// } + + public String getSystemInfo() { + return lib.whisper_print_system_info(); + } + + public int benchMemcpy(int nthread) { + return lib.whisper_bench_memcpy(nthread); + } + + public int benchGgmlMulMat(int nthread) { + return lib.whisper_bench_ggml_mul_mat(nthread); + } +} diff --git a/bindings/java/src/main/java/io/github/ggerganov/whispercpp/WhisperCppJnaLibrary.java b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/WhisperCppJnaLibrary.java new file mode 100644 index 0000000..690f1bd --- /dev/null +++ b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/WhisperCppJnaLibrary.java @@ -0,0 +1,390 @@ +package io.github.ggerganov.whispercpp; + +import com.sun.jna.Library; +import com.sun.jna.Native; +import com.sun.jna.Pointer; +import io.github.ggerganov.whispercpp.model.WhisperModelLoader; +import io.github.ggerganov.whispercpp.model.WhisperTokenData; +import io.github.ggerganov.whispercpp.params.WhisperContextParams; +import io.github.ggerganov.whispercpp.params.WhisperFullParams; + +public interface WhisperCppJnaLibrary extends Library { + + WhisperCppJnaLibrary instance = Native.load("whisper", WhisperCppJnaLibrary.class); + + String whisper_print_system_info(); + + /** + * DEPRECATED. Allocate (almost) all memory needed for the model by loading from a file. + * + * @param path_model Path to the model file + * @return Whisper context on success, null on failure + */ + Pointer whisper_init_from_file(String path_model); + + /** + * Provides default params which can be used with `whisper_init_from_file_with_params()` etc. + * Because this function allocates memory for the params, the caller must call either: + * - call `whisper_free_context_params()` + * - `Native.free(Pointer.nativeValue(pointer));` + */ + Pointer whisper_context_default_params_by_ref(); + + void whisper_free_context_params(Pointer params); + + /** + * Allocate (almost) all memory needed for the model by loading from a file. + * + * @param path_model Path to the model file + * @param params Pointer to whisper_context_params + * @return Whisper context on success, null on failure + */ + Pointer whisper_init_from_file_with_params(String path_model, WhisperContextParams.ByValue params); + + /** + * Allocate (almost) all memory needed for the model by loading from a buffer. + * + * @param buffer Model buffer + * @param buffer_size Size of the model buffer + * @return Whisper context on success, null on failure + */ + Pointer whisper_init_from_buffer(Pointer buffer, int buffer_size); + + /** + * Allocate (almost) all memory needed for the model using a model loader. + * + * @param loader Model loader + * @return Whisper context on success, null on failure + */ + Pointer whisper_init(WhisperModelLoader loader); + + /** + * Allocate (almost) all memory needed for the model by loading from a file without allocating the state. + * + * @param path_model Path to the model file + * @return Whisper context on success, null on failure + */ + Pointer whisper_init_from_file_no_state(String path_model); + + /** + * Allocate (almost) all memory needed for the model by loading from a buffer without allocating the state. + * + * @param buffer Model buffer + * @param buffer_size Size of the model buffer + * @return Whisper context on success, null on failure + */ + Pointer whisper_init_from_buffer_no_state(Pointer buffer, int buffer_size); + +// Pointer whisper_init_from_buffer_no_state(Pointer buffer, long buffer_size); + + /** + * Allocate (almost) all memory needed for the model using a model loader without allocating the state. + * + * @param loader Model loader + * @return Whisper context on success, null on failure + */ + Pointer whisper_init_no_state(WhisperModelLoader loader); + + /** + * Allocate memory for the Whisper state. + * + * @param ctx Whisper context + * @return Whisper state on success, null on failure + */ + Pointer whisper_init_state(Pointer ctx); + + /** + * Free all allocated memory associated with the Whisper context. + * + * @param ctx Whisper context + */ + void whisper_free(Pointer ctx); + + /** + * Free all allocated memory associated with the Whisper state. + * + * @param state Whisper state + */ + void whisper_free_state(Pointer state); + + + /** + * Convert RAW PCM audio to log mel spectrogram. + * The resulting spectrogram is stored inside the default state of the provided whisper context. + * + * @param ctx - Pointer to a WhisperContext + * @return 0 on success + */ + int whisper_pcm_to_mel(Pointer ctx, final float[] samples, int n_samples, int n_threads); + + /** + * @param ctx Pointer to a WhisperContext + * @param state Pointer to WhisperState + * @param n_samples + * @param n_threads + * @return 0 on success + */ + int whisper_pcm_to_mel_with_state(Pointer ctx, Pointer state, final float[] samples, int n_samples, int n_threads); + + /** + * This can be used to set a custom log mel spectrogram inside the default state of the provided whisper context. + * Use this instead of whisper_pcm_to_mel() if you want to provide your own log mel spectrogram. + * n_mel must be 80 + * @return 0 on success + */ + int whisper_set_mel(Pointer ctx, final float[] data, int n_len, int n_mel); + int whisper_set_mel_with_state(Pointer ctx, Pointer state, final float[] data, int n_len, int n_mel); + + /** + * Run the Whisper encoder on the log mel spectrogram stored inside the default state in the provided whisper context. + * Make sure to call whisper_pcm_to_mel() or whisper_set_mel() first. + * Offset can be used to specify the offset of the first frame in the spectrogram. + * @return 0 on success + */ + int whisper_encode(Pointer ctx, int offset, int n_threads); + + int whisper_encode_with_state(Pointer ctx, Pointer state, int offset, int n_threads); + + /** + * Run the Whisper decoder to obtain the logits and probabilities for the next token. + * Make sure to call whisper_encode() first. + * tokens + n_tokens is the provided context for the decoder. + * n_past is the number of tokens to use from previous decoder calls. + * Returns 0 on success + * TODO: add support for multiple decoders + */ + int whisper_decode(Pointer ctx, Pointer tokens, int n_tokens, int n_past, int n_threads); + + /** + * @param ctx + * @param state + * @param tokens Pointer to int tokens + * @param n_tokens + * @param n_past + * @param n_threads + * @return + */ + int whisper_decode_with_state(Pointer ctx, Pointer state, Pointer tokens, int n_tokens, int n_past, int n_threads); + + /** + * Convert the provided text into tokens. + * The tokens pointer must be large enough to hold the resulting tokens. + * Returns the number of tokens on success, no more than n_max_tokens + * Returns -1 on failure + * TODO: not sure if correct + */ + int whisper_tokenize(Pointer ctx, String text, Pointer tokens, int n_max_tokens); + + /** Largest language id (i.e. number of available languages - 1) */ + int whisper_lang_max_id(); + + /** + * @return the id of the specified language, returns -1 if not found. + * Examples: + * "de" -> 2 + * "german" -> 2 + */ + int whisper_lang_id(String lang); + + /** @return the short string of the specified language id (e.g. 2 -> "de"), returns nullptr if not found */ + String whisper_lang_str(int id); + + /** + * Use mel data at offset_ms to try and auto-detect the spoken language. + * Make sure to call whisper_pcm_to_mel() or whisper_set_mel() first + * Returns the top language id or negative on failure + * If not null, fills the lang_probs array with the probabilities of all languages + * The array must be whisper_lang_max_id() + 1 in size + * + * ref: https://github.com/openai/whisper/blob/main/whisper/decoding.py#L18-L69 + */ + int whisper_lang_auto_detect(Pointer ctx, int offset_ms, int n_threads, float[] lang_probs); + + int whisper_lang_auto_detect_with_state(Pointer ctx, Pointer state, int offset_ms, int n_threads, float[] lang_probs); + + int whisper_n_len (Pointer ctx); // mel length + int whisper_n_len_from_state(Pointer state); // mel length + int whisper_n_vocab (Pointer ctx); + int whisper_n_text_ctx (Pointer ctx); + int whisper_n_audio_ctx (Pointer ctx); + int whisper_is_multilingual (Pointer ctx); + + int whisper_model_n_vocab (Pointer ctx); + int whisper_model_n_audio_ctx (Pointer ctx); + int whisper_model_n_audio_state(Pointer ctx); + int whisper_model_n_audio_head (Pointer ctx); + int whisper_model_n_audio_layer(Pointer ctx); + int whisper_model_n_text_ctx (Pointer ctx); + int whisper_model_n_text_state (Pointer ctx); + int whisper_model_n_text_head (Pointer ctx); + int whisper_model_n_text_layer (Pointer ctx); + int whisper_model_n_mels (Pointer ctx); + int whisper_model_ftype (Pointer ctx); + int whisper_model_type (Pointer ctx); + + /** + * Token logits obtained from the last call to whisper_decode(). + * The logits for the last token are stored in the last row + * Rows: n_tokens + * Cols: n_vocab + */ + float[] whisper_get_logits (Pointer ctx); + float[] whisper_get_logits_from_state(Pointer state); + + // Token Id -> String. Uses the vocabulary in the provided context + String whisper_token_to_str(Pointer ctx, int token); + String whisper_model_type_readable(Pointer ctx); + + // Special tokens + int whisper_token_eot (Pointer ctx); + int whisper_token_sot (Pointer ctx); + int whisper_token_prev(Pointer ctx); + int whisper_token_solm(Pointer ctx); + int whisper_token_not (Pointer ctx); + int whisper_token_beg (Pointer ctx); + int whisper_token_lang(Pointer ctx, int lang_id); + + // Task tokens + int whisper_token_translate (Pointer ctx); + int whisper_token_transcribe(Pointer ctx); + + // Performance information from the default state. + void whisper_print_timings(Pointer ctx); + void whisper_reset_timings(Pointer ctx); + + // Note: Even if `whisper_full_params is stripped back to just 4 ints, JNA throws "Invalid memory access" + // when `whisper_full_default_params()` tries to return a struct. + // WhisperFullParams whisper_full_default_params(int strategy); + + /** + * Provides default params which can be used with `whisper_full()` etc. + * Because this function allocates memory for the params, the caller must call either: + * - call `whisper_free_params()` + * - `Native.free(Pointer.nativeValue(pointer));` + * + * @param strategy - WhisperSamplingStrategy.value + */ + Pointer whisper_full_default_params_by_ref(int strategy); + + void whisper_free_params(Pointer params); + + /** + * Run the entire model: PCM -> log mel spectrogram -> encoder -> decoder -> text + * Not thread safe for same context + * Uses the specified decoding strategy to obtain the text. + */ + int whisper_full(Pointer ctx, WhisperFullParams.ByValue params, final float[] samples, int n_samples); + + public int whisper_full_with_state(Pointer ctx, Pointer state, WhisperFullParams.ByValue params, float[] samples, int n_samples); + //int whisper_full_with_state(Pointer ctx, Pointer state, WhisperFullParams params, final float[] samples, int n_samples); + + // Split the input audio in chunks and process each chunk separately using whisper_full_with_state() + // Result is stored in the default state of the context + // Not thread safe if executed in parallel on the same context. + // It seems this approach can offer some speedup in some cases. + // However, the transcription accuracy can be worse at the beginning and end of each chunk. + int whisper_full_parallel(Pointer ctx, WhisperFullParams.ByValue params, final float[] samples, int n_samples, int n_processors); + + /** + * Number of generated text segments. + * A segment can be a few words, a sentence, or even a paragraph. + * @param ctx Pointer to WhisperContext + */ + int whisper_full_n_segments (Pointer ctx); + + /** + * @param state Pointer to WhisperState + */ + int whisper_full_n_segments_from_state(Pointer state); + + /** + * Language id associated with the context's default state. + * @param ctx Pointer to WhisperContext + */ + int whisper_full_lang_id(Pointer ctx); + + /** Language id associated with the provided state */ + int whisper_full_lang_id_from_state(Pointer state); + + + /** Get the start time of the specified segment. */ + long whisper_full_get_segment_t0(Pointer ctx, int i_segment); + + /** Get the start time of the specified segment from the state. */ + long whisper_full_get_segment_t0_from_state(Pointer state, int i_segment); + + /** Get the end time of the specified segment. */ + long whisper_full_get_segment_t1(Pointer ctx, int i_segment); + + /** Get the end time of the specified segment from the state. */ + long whisper_full_get_segment_t1_from_state(Pointer state, int i_segment); + + /** Get the text of the specified segment. */ + String whisper_full_get_segment_text(Pointer ctx, int i_segment); + + /** Get the text of the specified segment from the state. */ + String whisper_full_get_segment_text_from_state(Pointer state, int i_segment); + + /** Get the number of tokens in the specified segment. */ + int whisper_full_n_tokens(Pointer ctx, int i_segment); + + /** Get the number of tokens in the specified segment from the state. */ + int whisper_full_n_tokens_from_state(Pointer state, int i_segment); + + /** Get the token text of the specified token in the specified segment. */ + String whisper_full_get_token_text(Pointer ctx, int i_segment, int i_token); + + + /** Get the token text of the specified token in the specified segment from the state. */ + String whisper_full_get_token_text_from_state(Pointer ctx, Pointer state, int i_segment, int i_token); + + /** Get the token ID of the specified token in the specified segment. */ + int whisper_full_get_token_id(Pointer ctx, int i_segment, int i_token); + + /** Get the token ID of the specified token in the specified segment from the state. */ + int whisper_full_get_token_id_from_state(Pointer state, int i_segment, int i_token); + + /** Get token data for the specified token in the specified segment. */ + WhisperTokenData whisper_full_get_token_data(Pointer ctx, int i_segment, int i_token); + + /** Get token data for the specified token in the specified segment from the state. */ + WhisperTokenData whisper_full_get_token_data_from_state(Pointer state, int i_segment, int i_token); + + /** Get the probability of the specified token in the specified segment. */ + float whisper_full_get_token_p(Pointer ctx, int i_segment, int i_token); + + /** Get the probability of the specified token in the specified segment from the state. */ + float whisper_full_get_token_p_from_state(Pointer state, int i_segment, int i_token); + + /** + * Benchmark function for memcpy. + * + * @param nThreads Number of threads to use for the benchmark. + * @return The result of the benchmark. + */ + int whisper_bench_memcpy(int nThreads); + + /** + * Benchmark function for memcpy as a string. + * + * @param nThreads Number of threads to use for the benchmark. + * @return The result of the benchmark as a string. + */ + String whisper_bench_memcpy_str(int nThreads); + + /** + * Benchmark function for ggml_mul_mat. + * + * @param nThreads Number of threads to use for the benchmark. + * @return The result of the benchmark. + */ + int whisper_bench_ggml_mul_mat(int nThreads); + + /** + * Benchmark function for ggml_mul_mat as a string. + * + * @param nThreads Number of threads to use for the benchmark. + * @return The result of the benchmark as a string. + */ + String whisper_bench_ggml_mul_mat_str(int nThreads); +} diff --git a/bindings/java/src/main/java/io/github/ggerganov/whispercpp/bean/WhisperSegment.java b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/bean/WhisperSegment.java new file mode 100644 index 0000000..da970b5 --- /dev/null +++ b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/bean/WhisperSegment.java @@ -0,0 +1,47 @@ +package io.github.ggerganov.whispercpp.bean; + +/** + * Created by litonglinux@qq.com on 10/21/2023_7:48 AM + */ +public class WhisperSegment { + private long start, end; + private String sentence; + + public WhisperSegment() { + } + + public WhisperSegment(long start, long end, String sentence) { + this.start = start; + this.end = end; + this.sentence = sentence; + } + + public long getStart() { + return start; + } + + public long getEnd() { + return end; + } + + public String getSentence() { + return sentence; + } + + public void setStart(long start) { + this.start = start; + } + + public void setEnd(long end) { + this.end = end; + } + + public void setSentence(String sentence) { + this.sentence = sentence; + } + + @Override + public String toString() { + return "[" + start + " --> " + end + "]:" + sentence; + } +} diff --git a/bindings/java/src/main/java/io/github/ggerganov/whispercpp/callbacks/GgmlAbortCallback.java b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/callbacks/GgmlAbortCallback.java new file mode 100644 index 0000000..244e419 --- /dev/null +++ b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/callbacks/GgmlAbortCallback.java @@ -0,0 +1,17 @@ +package io.github.ggerganov.whispercpp.callbacks; + +import com.sun.jna.Callback; + +/** + * Callback for aborting GGML computation + * Maps to the C typedef: bool (*ggml_abort_callback)(void * data) + */ +public interface GgmlAbortCallback extends Callback { + /** + * Return true to abort the computation, false to continue + * + * @param data User data passed to the callback + * @return true to abort, false to continue + */ + boolean invoke(com.sun.jna.Pointer data); +} diff --git a/bindings/java/src/main/java/io/github/ggerganov/whispercpp/callbacks/WhisperEncoderBeginCallback.java b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/callbacks/WhisperEncoderBeginCallback.java new file mode 100644 index 0000000..3d228cb --- /dev/null +++ b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/callbacks/WhisperEncoderBeginCallback.java @@ -0,0 +1,24 @@ +package io.github.ggerganov.whispercpp.callbacks; + +import com.sun.jna.Callback; +import com.sun.jna.Pointer; +import io.github.ggerganov.whispercpp.WhisperContext; +import io.github.ggerganov.whispercpp.model.WhisperState; + +/** + * Callback before the encoder starts. + * If not null, called before the encoder starts. + * If it returns false, the computation is aborted. + */ +public interface WhisperEncoderBeginCallback extends Callback { + + /** + * Callback method before the encoder starts. + * + * @param ctx The whisper context. + * @param state The whisper state. + * @param user_data User data. + * @return True if the computation should proceed, false otherwise. + */ + boolean callback(Pointer ctx, Pointer state, Pointer user_data); +} diff --git a/bindings/java/src/main/java/io/github/ggerganov/whispercpp/callbacks/WhisperLogitsFilterCallback.java b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/callbacks/WhisperLogitsFilterCallback.java new file mode 100644 index 0000000..9777c76 --- /dev/null +++ b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/callbacks/WhisperLogitsFilterCallback.java @@ -0,0 +1,25 @@ +package io.github.ggerganov.whispercpp.callbacks; + +import com.sun.jna.Callback; +import com.sun.jna.Pointer; +import io.github.ggerganov.whispercpp.model.WhisperTokenData; + +/** + * Callback to filter logits. + * Can be used to modify the logits before sampling. + * If not null, called after applying temperature to logits. + */ +public interface WhisperLogitsFilterCallback extends Callback { + + /** + * Callback method to filter logits. + * + * @param ctx The whisper context. + * @param state The whisper state. + * @param tokens The array of whisper_token_data. + * @param n_tokens The number of tokens. + * @param logits The array of logits. + * @param user_data User data. + */ + void callback(Pointer ctx, Pointer state, WhisperTokenData[] tokens, int n_tokens, float[] logits, Pointer user_data); +} diff --git a/bindings/java/src/main/java/io/github/ggerganov/whispercpp/callbacks/WhisperNewSegmentCallback.java b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/callbacks/WhisperNewSegmentCallback.java new file mode 100644 index 0000000..27b1c61 --- /dev/null +++ b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/callbacks/WhisperNewSegmentCallback.java @@ -0,0 +1,24 @@ +package io.github.ggerganov.whispercpp.callbacks; + +import com.sun.jna.Callback; +import com.sun.jna.Pointer; +import io.github.ggerganov.whispercpp.WhisperContext; +import io.github.ggerganov.whispercpp.model.WhisperState; + +/** + * Callback for the text segment. + * Called on every newly generated text segment. + * Use the whisper_full_...() functions to obtain the text segments. + */ +public interface WhisperNewSegmentCallback extends Callback { + + /** + * Callback method for the text segment. + * + * @param ctx The whisper context. + * @param state The whisper state. + * @param n_new The number of newly generated text segments. + * @param user_data User data. + */ + void callback(Pointer ctx, Pointer state, int n_new, Pointer user_data); +} diff --git a/bindings/java/src/main/java/io/github/ggerganov/whispercpp/callbacks/WhisperProgressCallback.java b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/callbacks/WhisperProgressCallback.java new file mode 100644 index 0000000..c64f0ab --- /dev/null +++ b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/callbacks/WhisperProgressCallback.java @@ -0,0 +1,22 @@ +package io.github.ggerganov.whispercpp.callbacks; + +import com.sun.jna.Callback; +import com.sun.jna.Pointer; +import io.github.ggerganov.whispercpp.WhisperContext; +import io.github.ggerganov.whispercpp.model.WhisperState; + +/** + * Callback for progress updates. + */ +public interface WhisperProgressCallback extends Callback { + + /** + * Callback method for progress updates. + * + * @param ctx The whisper context. + * @param state The whisper state. + * @param progress The progress value. + * @param user_data User data. + */ + void callback(Pointer ctx, Pointer state, int progress, Pointer user_data); +} diff --git a/bindings/java/src/main/java/io/github/ggerganov/whispercpp/ggml/GgmlTensor.java b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/ggml/GgmlTensor.java new file mode 100644 index 0000000..2569957 --- /dev/null +++ b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/ggml/GgmlTensor.java @@ -0,0 +1,4 @@ +package io.github.ggerganov.whispercpp.ggml; + +public class GgmlTensor { +} diff --git a/bindings/java/src/main/java/io/github/ggerganov/whispercpp/ggml/GgmlType.java b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/ggml/GgmlType.java new file mode 100644 index 0000000..363120e --- /dev/null +++ b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/ggml/GgmlType.java @@ -0,0 +1,18 @@ +package io.github.ggerganov.whispercpp.ggml; + +public enum GgmlType { + GGML_TYPE_F32, + GGML_TYPE_F16, + GGML_TYPE_Q4_0, + GGML_TYPE_Q4_1, + REMOVED_GGML_TYPE_Q4_2, // support has been removed + REMOVED_GGML_TYPE_Q4_3, // support has been removed + GGML_TYPE_Q5_0, + GGML_TYPE_Q5_1, + GGML_TYPE_Q8_0, + GGML_TYPE_Q8_1, + GGML_TYPE_I8, + GGML_TYPE_I16, + GGML_TYPE_I32, + GGML_TYPE_COUNT, +} diff --git a/bindings/java/src/main/java/io/github/ggerganov/whispercpp/model/EModel.java b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/model/EModel.java new file mode 100644 index 0000000..b2475b3 --- /dev/null +++ b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/model/EModel.java @@ -0,0 +1,10 @@ +package io.github.ggerganov.whispercpp.model; + +public enum EModel { + MODEL_UNKNOWN, + MODEL_TINY, + MODEL_BASE, + MODEL_SMALL, + MODEL_MEDIUM, + MODEL_LARGE, +} diff --git a/bindings/java/src/main/java/io/github/ggerganov/whispercpp/model/WhisperModel.java b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/model/WhisperModel.java new file mode 100644 index 0000000..497ef42 --- /dev/null +++ b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/model/WhisperModel.java @@ -0,0 +1,49 @@ +package io.github.ggerganov.whispercpp; + +import io.github.ggerganov.whispercpp.ggml.GgmlTensor; +import io.github.ggerganov.whispercpp.model.EModel; + +public class WhisperModel { +// EModel type = EModel.MODEL_UNKNOWN; +// +// WhisperHParams hparams; +// WhisperFilters filters; +// +// // encoder.positional_embedding +// GgmlTensor e_pe; +// +// // encoder.conv1 +// GgmlTensor e_conv_1_w; +// GgmlTensor e_conv_1_b; +// +// // encoder.conv2 +// GgmlTensor e_conv_2_w; +// GgmlTensor e_conv_2_b; +// +// // encoder.ln_post +// GgmlTensor e_ln_w; +// GgmlTensor e_ln_b; +// +// // decoder.positional_embedding +// GgmlTensor d_pe; +// +// // decoder.token_embedding +// GgmlTensor d_te; +// +// // decoder.ln +// GgmlTensor d_ln_w; +// GgmlTensor d_ln_b; +// +// std::vector<whisper_layer_encoder> layers_encoder; +// std::vector<whisper_layer_decoder> layers_decoder; +// +// // context +// struct ggml_context * ctx; +// +// // the model memory buffer is read-only and can be shared between processors +// std::vector<uint8_t> * buf; +// +// // tensors +// int n_loaded; +// Map<String, GgmlTensor> tensors; +} diff --git a/bindings/java/src/main/java/io/github/ggerganov/whispercpp/model/WhisperModelLoader.java b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/model/WhisperModelLoader.java new file mode 100644 index 0000000..82615d9 --- /dev/null +++ b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/model/WhisperModelLoader.java @@ -0,0 +1,62 @@ +package io.github.ggerganov.whispercpp.model; + +import com.sun.jna.Callback; +import com.sun.jna.Pointer; +import com.sun.jna.Structure; + + +public class WhisperModelLoader extends Structure { + public Pointer context; + public ReadFunction read; + public EOFFunction eof; + public CloseFunction close; + + public static class ReadFunction implements Callback { + public Pointer invoke(Pointer ctx, Pointer output, int readSize) { + // TODO + return ctx; + } + } + + public static class EOFFunction implements Callback { + public boolean invoke(Pointer ctx) { + // TODO + return false; + } + } + + public static class CloseFunction implements Callback { + public void invoke(Pointer ctx) { + // TODO + } + } + +// public WhisperModelLoader(Pointer p) { +// super(p); +// read = new ReadFunction(); +// eof = new EOFFunction(); +// close = new CloseFunction(); +// read.setCallback(this); +// eof.setCallback(this); +// close.setCallback(this); +// read.write(); +// eof.write(); +// close.write(); +// } + + public WhisperModelLoader() { + super(); + } + + public interface ReadCallback extends Callback { + Pointer invoke(Pointer ctx, Pointer output, int readSize); + } + + public interface EOFCallback extends Callback { + boolean invoke(Pointer ctx); + } + + public interface CloseCallback extends Callback { + void invoke(Pointer ctx); + } +} diff --git a/bindings/java/src/main/java/io/github/ggerganov/whispercpp/model/WhisperState.java b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/model/WhisperState.java new file mode 100644 index 0000000..af93772 --- /dev/null +++ b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/model/WhisperState.java @@ -0,0 +1,4 @@ +package io.github.ggerganov.whispercpp.model; + +public class WhisperState { +} diff --git a/bindings/java/src/main/java/io/github/ggerganov/whispercpp/model/WhisperTokenData.java b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/model/WhisperTokenData.java new file mode 100644 index 0000000..bfa83f9 --- /dev/null +++ b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/model/WhisperTokenData.java @@ -0,0 +1,50 @@ +package io.github.ggerganov.whispercpp.model; + +import com.sun.jna.Structure; + +import java.util.Arrays; +import java.util.List; + +/** + * Structure representing token data. + */ +public class WhisperTokenData extends Structure { + + /** Token ID. */ + public int id; + + /** Forced timestamp token ID. */ + public int tid; + + /** Probability of the token. */ + public float p; + + /** Log probability of the token. */ + public float plog; + + /** Probability of the timestamp token. */ + public float pt; + + /** Sum of probabilities of all timestamp tokens. */ + public float ptsum; + + /** + * Start time of the token (token-level timestamp data). + * Do not use if you haven't computed token-level timestamps. + */ + public long t0; + + /** + * End time of the token (token-level timestamp data). + * Do not use if you haven't computed token-level timestamps. + */ + public long t1; + + /** Voice length of the token. */ + public float vlen; + + @Override + protected List<String> getFieldOrder() { + return Arrays.asList("id", "tid", "p", "plog", "pt", "ptsum", "t0", "t1", "vlen"); + } +} diff --git a/bindings/java/src/main/java/io/github/ggerganov/whispercpp/params/BeamSearchParams.java b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/params/BeamSearchParams.java new file mode 100644 index 0000000..fd621dd --- /dev/null +++ b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/params/BeamSearchParams.java @@ -0,0 +1,19 @@ +package io.github.ggerganov.whispercpp.params; + +import com.sun.jna.Structure; + +import java.util.Arrays; +import java.util.List; + +public class BeamSearchParams extends Structure { + /** ref: <a href="https://github.com/openai/whisper/blob/f82bc59f5ea234d4b97fb2860842ed38519f7e65/whisper/transcribe.py#L265">...</a> */ + public int beam_size; + + /** ref: <a href="https://arxiv.org/pdf/2204.05424.pdf">...</a> */ + public float patience; + + @Override + protected List<String> getFieldOrder() { + return Arrays.asList("beam_size", "patience"); + } +} diff --git a/bindings/java/src/main/java/io/github/ggerganov/whispercpp/params/CBool.java b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/params/CBool.java new file mode 100644 index 0000000..1f6814b --- /dev/null +++ b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/params/CBool.java @@ -0,0 +1,30 @@ +package io.github.ggerganov.whispercpp.params; + +import com.sun.jna.IntegerType; + +import java.util.function.BooleanSupplier; + +public class CBool extends IntegerType implements BooleanSupplier { + public static final int SIZE = 1; + public static final CBool FALSE = new CBool(0); + public static final CBool TRUE = new CBool(1); + + + public CBool() { + this(0); + } + + public CBool(long value) { + super(SIZE, value, true); + } + + @Override + public boolean getAsBoolean() { + return intValue() == 1; + } + + @Override + public String toString() { + return intValue() == 1 ? "true" : "false"; + } +} diff --git a/bindings/java/src/main/java/io/github/ggerganov/whispercpp/params/GreedyParams.java b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/params/GreedyParams.java new file mode 100644 index 0000000..e3b0138 --- /dev/null +++ b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/params/GreedyParams.java @@ -0,0 +1,16 @@ +package io.github.ggerganov.whispercpp.params; + +import com.sun.jna.Structure; + +import java.util.Collections; +import java.util.List; + +public class GreedyParams extends Structure { + /** <a href="https://github.com/openai/whisper/blob/f82bc59f5ea234d4b97fb2860842ed38519f7e65/whisper/transcribe.py#L264">...</a> */ + public int best_of; + + @Override + protected List<String> getFieldOrder() { + return Collections.singletonList("best_of"); + } +} diff --git a/bindings/java/src/main/java/io/github/ggerganov/whispercpp/params/WhisperAhead.java b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/params/WhisperAhead.java new file mode 100644 index 0000000..39691dc --- /dev/null +++ b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/params/WhisperAhead.java @@ -0,0 +1,30 @@ +package io.github.ggerganov.whispercpp.params; +import com.sun.jna.*; +import java.util.Arrays; +import java.util.List; + +public class WhisperAhead extends Structure { + + public int n_text_layer; + + public int n_head; + + public WhisperAhead() { + super(); + } + + public WhisperAhead(int textLayer, int head) { + super(); + this.n_text_layer = textLayer; + this.n_head = head; + } + + @Override + protected List<String> getFieldOrder() { + return Arrays.asList("n_text_layer", "n_head"); + } + + public static class ByReference extends WhisperAhead implements Structure.ByReference {} + + public static class ByValue extends WhisperAhead implements Structure.ByValue {} +} diff --git a/bindings/java/src/main/java/io/github/ggerganov/whispercpp/params/WhisperAheads.java b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/params/WhisperAheads.java new file mode 100644 index 0000000..bca5eb0 --- /dev/null +++ b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/params/WhisperAheads.java @@ -0,0 +1,41 @@ +package io.github.ggerganov.whispercpp.params; +import com.sun.jna.*; +import java.util.Arrays; +import java.util.List; + +public class WhisperAheads extends Structure { + public NativeLong n_heads; + + public Pointer heads; + + public WhisperAheads() { + super(); + } + + /** + * Create alignment heads from an array of WhisperAhead objects + */ + public void setHeads(WhisperAhead[] aheadsArray) { + this.n_heads = new NativeLong(aheadsArray.length); + + int structSize = aheadsArray[0].size(); + Memory mem = new Memory(structSize * aheadsArray.length); + + for (int i = 0; i < aheadsArray.length; i++) { + aheadsArray[i].write(); + byte[] buffer = aheadsArray[i].getPointer().getByteArray(0, structSize); + mem.write(i * structSize, buffer, 0, buffer.length); + } + + this.heads = mem; + } + + @Override + protected List<String> getFieldOrder() { + return Arrays.asList("n_heads", "heads"); + } + + public static class ByReference extends WhisperAheads implements Structure.ByReference {} + + public static class ByValue extends WhisperAheads implements Structure.ByValue {} +} diff --git a/bindings/java/src/main/java/io/github/ggerganov/whispercpp/params/WhisperContextParams.java b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/params/WhisperContextParams.java new file mode 100644 index 0000000..66ec5d7 --- /dev/null +++ b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/params/WhisperContextParams.java @@ -0,0 +1,81 @@ +package io.github.ggerganov.whispercpp.params; +import com.sun.jna.*; +import java.util.Arrays; +import java.util.List; + +/** + * Parameters for the whisper_init_from_file_with_params() function. + * If you change the order or add new parameters, make sure to update the default values in whisper.cpp: + * whisper_context_default_params() + */ +public class WhisperContextParams extends Structure { + public WhisperContextParams(Pointer p) { + super(p); + } + + public WhisperContextParams() { + super(); + } + + /** Use GPU for inference (default = true) */ + public CBool use_gpu; + + /** Use flash attention (default = true) */ + public CBool flash_attn; + + /** CUDA device to use (default = 0) */ + public int gpu_device; + + /** [EXPERIMENTAL] Enable token-level timestamps with DTW (default = false) */ + public CBool dtw_token_timestamps; + + /** [EXPERIMENTAL] Alignment heads preset for DTW */ + public int dtw_aheads_preset; + + /** Number of top layers to use for DTW when using WHISPER_AHEADS_N_TOP_MOST preset */ + public int dtw_n_top; + + public WhisperAheads.ByValue dtw_aheads; + + /** DTW memory size (internal use) */ + public NativeLong dtw_mem_size; + + /** Use GPU for inference */ + public void useGpu(boolean enable) { + use_gpu = enable ? CBool.TRUE : CBool.FALSE; + } + + /** Use flash attention */ + public void useFlashAttn(boolean enable) { + flash_attn = enable ? CBool.TRUE : CBool.FALSE; + } + + /** Enable DTW token-level timestamps */ + public void enableDtwTokenTimestamps(boolean enable) { + dtw_token_timestamps = enable ? CBool.TRUE : CBool.FALSE; + } + + /** Set DTW alignment heads preset */ + public void setDtwAheadsPreset(int preset) { + dtw_aheads_preset = preset; + } + + @Override + protected List<String> getFieldOrder() { + return Arrays.asList( + "use_gpu", + "flash_attn", + "gpu_device", + "dtw_token_timestamps", + "dtw_aheads_preset", + "dtw_n_top", + "dtw_aheads", + "dtw_mem_size" + ); + } + + public static class ByValue extends WhisperContextParams implements Structure.ByValue { + public ByValue() { super(); } + public ByValue(Pointer p) { super(p); } + } +} diff --git a/bindings/java/src/main/java/io/github/ggerganov/whispercpp/params/WhisperFilters.java b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/params/WhisperFilters.java new file mode 100644 index 0000000..b035243 --- /dev/null +++ b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/params/WhisperFilters.java @@ -0,0 +1,10 @@ +package io.github.ggerganov.whispercpp.params; + +import java.util.List; + +public class WhisperFilters { + int n_mel; + int n_fft; + + List<Float> data; +} diff --git a/bindings/java/src/main/java/io/github/ggerganov/whispercpp/params/WhisperFullParams.java b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/params/WhisperFullParams.java new file mode 100644 index 0000000..76ce80f --- /dev/null +++ b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/params/WhisperFullParams.java @@ -0,0 +1,360 @@ +package io.github.ggerganov.whispercpp.params; + +import com.sun.jna.*; +import io.github.ggerganov.whispercpp.callbacks.WhisperEncoderBeginCallback; +import io.github.ggerganov.whispercpp.callbacks.WhisperLogitsFilterCallback; +import io.github.ggerganov.whispercpp.callbacks.WhisperNewSegmentCallback; +import io.github.ggerganov.whispercpp.callbacks.WhisperProgressCallback; +import io.github.ggerganov.whispercpp.callbacks.GgmlAbortCallback; + +import java.util.Arrays; +import java.util.List; + +/** + * Parameters for the whisper_full() function. + * If you change the order or add new parameters, make sure to update the default values in whisper.cpp: + * whisper_full_default_params() + */ +public class WhisperFullParams extends Structure { + + public WhisperFullParams() { + super(); + } + + public WhisperFullParams(Pointer p) { + super(p); + } + + /** Sampling strategy for whisper_full() function. */ + public int strategy; + + /** Number of threads. (default = 4) */ + public int n_threads; + + /** Maximum tokens to use from past text as a prompt for the decoder. (default = 16384) */ + public int n_max_text_ctx; + + /** Start offset in milliseconds. (default = 0) */ + public int offset_ms; + + /** Audio duration to process in milliseconds. (default = 0) */ + public int duration_ms; + + /** Translate flag. (default = false) */ + public CBool translate; + + /** The compliment of translateMode() */ + public void transcribeMode() { + translate = CBool.FALSE; + } + + /** The compliment of transcribeMode() */ + public void translateMode() { + translate = CBool.TRUE; + } + + /** Flag to indicate whether to use past transcription (if any) as an initial prompt for the decoder. (default = true) */ + public CBool no_context; + + /** Flag to indicate whether to use past transcription (if any) as an initial prompt for the decoder. (default = true) */ + public void enableContext(boolean enable) { + no_context = enable ? CBool.FALSE : CBool.TRUE; + } + + /** Generate timestamps or not? */ + public CBool no_timestamps; + + /** Flag to force single segment output (useful for streaming). (default = false) */ + public CBool single_segment; + + /** Flag to force single segment output (useful for streaming). (default = false) */ + public void singleSegment(boolean single) { + single_segment = single ? CBool.TRUE : CBool.FALSE; + } + + /** Flag to print special tokens (e.g., <SOT>, <EOT>, <BEG>, etc.). (default = false) */ + public CBool print_special; + + /** Flag to print special tokens (e.g., <SOT>, <EOT>, <BEG>, etc.). (default = false) */ + public void printSpecial(boolean enable) { + print_special = enable ? CBool.TRUE : CBool.FALSE; + } + + /** Flag to print progress information. (default = true) */ + public CBool print_progress; + + /** Flag to print progress information. (default = true) */ + public void printProgress(boolean enable) { + print_progress = enable ? CBool.TRUE : CBool.FALSE; + } + + /** Flag to print results from within whisper.cpp (avoid it, use callback instead). (default = true) */ + public CBool print_realtime; + + /** Flag to print results from within whisper.cpp (avoid it, use callback instead). (default = true) */ + public void printRealtime(boolean enable) { + print_realtime = enable ? CBool.TRUE : CBool.FALSE; + } + + /** Flag to print timestamps for each text segment when printing realtime. (default = true) */ + public CBool print_timestamps; + + /** Flag to print timestamps for each text segment when printing realtime. (default = true) */ + public void printTimestamps(boolean enable) { + print_timestamps = enable ? CBool.TRUE : CBool.FALSE; + } + + /** [EXPERIMENTAL] Flag to enable token-level timestamps. (default = false) */ + public CBool token_timestamps; + + /** [EXPERIMENTAL] Flag to enable token-level timestamps. (default = false) */ + public void tokenTimestamps(boolean enable) { + token_timestamps = enable ? CBool.TRUE : CBool.FALSE; + } + + /** [EXPERIMENTAL] Timestamp token probability threshold (~0.01). (default = 0.01) */ + public float thold_pt; + + /** [EXPERIMENTAL] Timestamp token sum probability threshold (~0.01). */ + public float thold_ptsum; + + /** Maximum segment length in characters. (default = 0) */ + public int max_len; + + /** Flag to split on word rather than on token (when used with max_len). (default = false) */ + public CBool split_on_word; + + /** Flag to split on word rather than on token (when used with max_len). (default = false) */ + public void splitOnWord(boolean enable) { + split_on_word = enable ? CBool.TRUE : CBool.FALSE; + } + + /** Maximum tokens per segment (0, default = no limit) */ + public int max_tokens; + + /** [EXPERIMENTAL] Enable debug mode for extra info */ + public CBool debug_mode; + + /** Enable debug mode */ + public void enableDebugMode(boolean enable) { + debug_mode = enable ? CBool.TRUE : CBool.FALSE; + } + + /** Overwrite the audio context size (0 = use default). */ + public int audio_ctx; + + /** Enable tinydiarize (default = false) */ + public CBool tdrz_enable; + + /** Enable tinydiarize (default = false) */ + public void tdrzEnable(boolean enable) { + tdrz_enable = enable ? CBool.TRUE : CBool.FALSE; + } + + /** Regular expression matching tokens to suppress. */ + public String suppress_regex; + + /** Tokens to provide to the whisper decoder as an initial prompt. + * These are prepended to any existing text context from a previous call. */ + public String initial_prompt; + /** Always prepend initial_prompt for every decode chunk. */ + public CBool carry_initial_prompt; + + /** Prompt tokens. (int*) */ + public Pointer prompt_tokens; + + public void setPromptTokens(int[] tokens) { + Memory mem = new Memory(tokens.length * 4L); + mem.write(0, tokens, 0, tokens.length); + prompt_tokens = mem; + } + + /** Number of prompt tokens. */ + public int prompt_n_tokens; + + /** Language for auto-detection. + * For auto-detection, set to `null`, `""`, or "auto". */ + public String language; + + /** Flag to indicate whether to detect language automatically. */ + public CBool detect_language; + + /** Flag to indicate whether to detect language automatically. */ + public void detectLanguage(boolean enable) { + detect_language = enable ? CBool.TRUE : CBool.FALSE; + } + + // Common decoding parameters. + + /** Flag to suppress blank tokens. */ + public CBool suppress_blank; + + public void suppressBlanks(boolean enable) { + suppress_blank = enable ? CBool.TRUE : CBool.FALSE; + } + + /** Flag to suppress non-speech tokens. */ + public CBool suppress_nst; + + /** Flag to suppress non-speech tokens. */ + public void suppressNonSpeechTokens(boolean enable) { + suppress_nst = enable ? CBool.TRUE : CBool.FALSE; + } + + /** Initial decoding temperature. */ + public float temperature; + + /** Maximum initial timestamp. */ + public float max_initial_ts; + + /** Length penalty. */ + public float length_penalty; + + // Fallback parameters. + + /** Temperature increment. */ + public float temperature_inc; + + /** Entropy threshold (similar to OpenAI's "compression_ratio_threshold"). */ + public float entropy_thold; + + /** Log probability threshold. */ + public float logprob_thold; + + /** No speech threshold. */ + public float no_speech_thold; + + /** Greedy decoding parameters. */ + public GreedyParams greedy; + + /** + * Beam search decoding parameters. + */ + public BeamSearchParams beam_search; + + public void setBestOf(int bestOf) { + if (greedy == null) { + greedy = new GreedyParams(); + } + greedy.best_of = bestOf; + } + + public void setBeamSize(int beamSize) { + if (beam_search == null) { + beam_search = new BeamSearchParams(); + } + beam_search.beam_size = beamSize; + } + + public void setBeamSizeAndPatience(int beamSize, float patience) { + if (beam_search == null) { + beam_search = new BeamSearchParams(); + } + beam_search.beam_size = beamSize; + beam_search.patience = patience; + } + + /** + * Callback for every newly generated text segment. + * WhisperNewSegmentCallback + */ + public Pointer new_segment_callback; + + /** + * User data for the new_segment_callback. + */ + public Pointer new_segment_callback_user_data; + + /** + * Callback on each progress update. + * WhisperProgressCallback + */ + public Pointer progress_callback; + + /** + * User data for the progress_callback. + */ + public Pointer progress_callback_user_data; + + /** + * Callback each time before the encoder starts. + * WhisperEncoderBeginCallback + */ + public Pointer encoder_begin_callback; + + /** + * User data for the encoder_begin_callback. + */ + public Pointer encoder_begin_callback_user_data; + + /** Callback used to abort GGML computation */ + public Pointer abort_callback; + + /** User data for the abort_callback */ + public Pointer abort_callback_user_data; + + public void setAbortCallback(GgmlAbortCallback callback) { + abort_callback = CallbackReference.getFunctionPointer(callback); + } + + /** + * Callback by each decoder to filter obtained logits. + * WhisperLogitsFilterCallback + */ + public Pointer logits_filter_callback; + + /** + * User data for the logits_filter_callback. + */ + public Pointer logits_filter_callback_user_data; + + + public void setNewSegmentCallback(WhisperNewSegmentCallback callback) { + new_segment_callback = CallbackReference.getFunctionPointer(callback); + } + + public void setProgressCallback(WhisperProgressCallback callback) { + progress_callback = CallbackReference.getFunctionPointer(callback); + } + + public void setEncoderBeginCallbackeginCallbackCallback(WhisperEncoderBeginCallback callback) { + encoder_begin_callback = CallbackReference.getFunctionPointer(callback); + } + + public void setLogitsFilterCallback(WhisperLogitsFilterCallback callback) { + logits_filter_callback = CallbackReference.getFunctionPointer(callback); + } + + /** Grammar stuff */ + public Pointer grammar_rules; + public long n_grammar_rules; + public long i_start_rule; + public float grammar_penalty; + + @Override + protected List<String> getFieldOrder() { + return Arrays.asList("strategy", "n_threads", "n_max_text_ctx", + "offset_ms", "duration_ms", "translate", "no_context", + "no_timestamps", "single_segment", "print_special", + "print_progress", "print_realtime", "print_timestamps", + "token_timestamps", "thold_pt", "thold_ptsum", "max_len", + "split_on_word", "max_tokens", "debug_mode", "audio_ctx", + "tdrz_enable", "suppress_regex", "initial_prompt", "carry_initial_prompt", + "prompt_tokens", "prompt_n_tokens", "language", "detect_language", + "suppress_blank", "suppress_nst", "temperature", + "max_initial_ts", "length_penalty", "temperature_inc", + "entropy_thold", "logprob_thold", "no_speech_thold", "greedy", + "beam_search", "new_segment_callback", "new_segment_callback_user_data", + "progress_callback", "progress_callback_user_data", + "encoder_begin_callback", "encoder_begin_callback_user_data", + "abort_callback", "abort_callback_user_data", + "logits_filter_callback", "logits_filter_callback_user_data", + "grammar_rules", "n_grammar_rules", "i_start_rule", "grammar_penalty"); + } + + public static class ByValue extends WhisperFullParams implements Structure.ByValue { + public ByValue() { super(); } + public ByValue(Pointer p) { super(p); } + } + +} diff --git a/bindings/java/src/main/java/io/github/ggerganov/whispercpp/params/WhisperHParams.java b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/params/WhisperHParams.java new file mode 100644 index 0000000..99feae0 --- /dev/null +++ b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/params/WhisperHParams.java @@ -0,0 +1,15 @@ +package io.github.ggerganov.whispercpp.params; + +public class WhisperHParams { + int n_vocab = 51864; + int n_audio_ctx = 1500; + int n_audio_state = 384; + int n_audio_head = 6; + int n_audio_layer = 4; + int n_text_ctx = 448; + int n_text_state = 384; + int n_text_head = 6; + int n_text_layer = 4; + int n_mels = 80; + int ftype = 1; +} diff --git a/bindings/java/src/main/java/io/github/ggerganov/whispercpp/params/WhisperSamplingStrategy.java b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/params/WhisperSamplingStrategy.java new file mode 100644 index 0000000..a32c793 --- /dev/null +++ b/bindings/java/src/main/java/io/github/ggerganov/whispercpp/params/WhisperSamplingStrategy.java @@ -0,0 +1,10 @@ +package io.github.ggerganov.whispercpp.params; + +/** Available sampling strategies */ +public enum WhisperSamplingStrategy { + /** similar to OpenAI's GreedyDecoder */ + WHISPER_SAMPLING_GREEDY, + + /** similar to OpenAI's BeamSearchDecoder */ + WHISPER_SAMPLING_BEAM_SEARCH +} diff --git a/bindings/java/src/test/java/io/github/ggerganov/whispercpp/WhisperCppTest.java b/bindings/java/src/test/java/io/github/ggerganov/whispercpp/WhisperCppTest.java new file mode 100644 index 0000000..e5b22cf --- /dev/null +++ b/bindings/java/src/test/java/io/github/ggerganov/whispercpp/WhisperCppTest.java @@ -0,0 +1,147 @@ +package io.github.ggerganov.whispercpp; + +import static org.junit.jupiter.api.Assertions.*; + +import io.github.ggerganov.whispercpp.bean.WhisperSegment; +import io.github.ggerganov.whispercpp.params.CBool; +import io.github.ggerganov.whispercpp.params.WhisperContextParams; +import io.github.ggerganov.whispercpp.params.WhisperFullParams; +import io.github.ggerganov.whispercpp.params.WhisperSamplingStrategy; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import java.io.File; +import java.io.FileNotFoundException; +import java.util.List; + +class WhisperCppTest { + private static WhisperCpp whisper = new WhisperCpp(); + private static boolean modelInitialised = false; + + @BeforeAll + static void init() throws FileNotFoundException { + // By default, models are loaded from ~/.cache/whisper/ and are usually named "ggml-${name}.bin" + // or you can provide the absolute path to the model file. + //String modelName = "../../models/ggml-tiny.bin"; + String modelName = "../../models/ggml-tiny.en.bin"; + try { + WhisperContextParams.ByValue contextParams = whisper.getContextDefaultParams(); + contextParams.useFlashAttn(false); // Disable flash attention + whisper.initContext(modelName, contextParams); + //whisper.getFullDefaultParams(WhisperSamplingStrategy.WHISPER_SAMPLING_GREEDY); + //whisper.getJavaDefaultParams(WhisperSamplingStrategy.WHISPER_SAMPLING_BEAM_SEARCH); + modelInitialised = true; + } catch (FileNotFoundException ex) { + System.out.println("Model " + modelName + " not found"); + } + } + + @Test + void testGetDefaultFullParams_BeamSearch() { + // When + WhisperFullParams params = whisper.getFullDefaultParams(WhisperSamplingStrategy.WHISPER_SAMPLING_BEAM_SEARCH); + + // Then + assertEquals(WhisperSamplingStrategy.WHISPER_SAMPLING_BEAM_SEARCH.ordinal(), params.strategy); + assertNotEquals(0, params.n_threads); + assertEquals(16384, params.n_max_text_ctx); + assertFalse(params.translate); + assertEquals(0.01f, params.thold_pt); + assertEquals(5, params.beam_search.beam_size); + assertEquals(-1.0f, params.beam_search.patience); + } + + @Test + void testGetDefaultFullParams_Greedy() { + // When + WhisperFullParams params = whisper.getFullDefaultParams(WhisperSamplingStrategy.WHISPER_SAMPLING_GREEDY); + + // Then + assertEquals(WhisperSamplingStrategy.WHISPER_SAMPLING_GREEDY.ordinal(), params.strategy); + assertNotEquals(0, params.n_threads); + assertEquals(16384, params.n_max_text_ctx); + assertEquals(5, params.greedy.best_of); + } + + @Test + void testFullTranscribe() throws Exception { + if (!modelInitialised) { + System.out.println("Model not initialised, skipping test"); + return; + } + + // Given + File file = new File(System.getProperty("user.dir"), "../../samples/jfk.wav"); + AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(file); + + byte[] b = new byte[audioInputStream.available()]; + float[] floats = new float[b.length / 2]; + + //WhisperFullParams params = whisper.getFullDefaultParams(WhisperSamplingStrategy.WHISPER_SAMPLING_GREEDY); + WhisperFullParams.ByValue params = whisper.getFullDefaultParams(WhisperSamplingStrategy.WHISPER_SAMPLING_BEAM_SEARCH); + params.setProgressCallback((ctx, state, progress, user_data) -> System.out.println("progress: " + progress)); + params.print_progress = CBool.FALSE; + //params.initial_prompt = "and so my fellow Americans um, like"; + + + try { + audioInputStream.read(b); + + for (int i = 0, j = 0; i < b.length; i += 2, j++) { + int intSample = (int) (b[i + 1]) << 8 | (int) (b[i]) & 0xFF; + floats[j] = intSample / 32767.0f; + } + + // When + String result = whisper.fullTranscribe(params, floats); + + // Then + System.err.println(result); + assertEquals("And so my fellow Americans ask not what your country can do for you " + + "ask what you can do for your country.", + result.replace(",", "")); + } finally { + audioInputStream.close(); + } + } + + @Test + void testFullTranscribeWithTime() throws Exception { + if (!modelInitialised) { + System.out.println("Model not initialised, skipping test"); + return; + } + + // Given + File file = new File(System.getProperty("user.dir"), "../../samples/jfk.wav"); + AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(file); + + byte[] b = new byte[audioInputStream.available()]; + float[] floats = new float[b.length / 2]; + + //WhisperFullParams params = whisper.getFullDefaultParams(WhisperSamplingStrategy.WHISPER_SAMPLING_GREEDY); + WhisperFullParams.ByValue params = whisper.getFullDefaultParams(WhisperSamplingStrategy.WHISPER_SAMPLING_BEAM_SEARCH); + params.setProgressCallback((ctx, state, progress, user_data) -> System.out.println("progress: " + progress)); + params.print_progress = CBool.FALSE; + //params.initial_prompt = "and so my fellow Americans um, like"; + + try { + audioInputStream.read(b); + + for (int i = 0, j = 0; i < b.length; i += 2, j++) { + int intSample = (int) (b[i + 1]) << 8 | (int) (b[i]) & 0xFF; + floats[j] = intSample / 32767.0f; + } + + List<WhisperSegment> segments = whisper.fullTranscribeWithTime(params, floats); + assertTrue(segments.size() > 0, "The size of segments should be greater than 0"); + for (WhisperSegment segment : segments) { + System.out.println(segment); + } + } finally { + audioInputStream.close(); + } + } + +} diff --git a/bindings/java/src/test/java/io/github/ggerganov/whispercpp/WhisperJnaLibraryTest.java b/bindings/java/src/test/java/io/github/ggerganov/whispercpp/WhisperJnaLibraryTest.java new file mode 100644 index 0000000..07a340c --- /dev/null +++ b/bindings/java/src/test/java/io/github/ggerganov/whispercpp/WhisperJnaLibraryTest.java @@ -0,0 +1,17 @@ +package io.github.ggerganov.whispercpp; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.Test; + +class WhisperJnaLibraryTest { + + @Test + void testWhisperPrint_system_info() { + String systemInfo = WhisperCppJnaLibrary.instance.whisper_print_system_info(); + // eg: "AVX = 1 | AVX2 = 1 | AVX512 = 0 | FMA = 1 | NEON = 0 | ARM_FMA = 0 | F16C = 1 | FP16_VA = 0 + // | WASM_SIMD = 0 | BLAS = 0 | SSE3 = 1 | VSX = 0 | COREML = 0 | " + System.out.println("System info: " + systemInfo); + assertTrue(systemInfo.length() > 10); + } +} diff --git a/bindings/javascript/.gitignore b/bindings/javascript/.gitignore new file mode 100644 index 0000000..218a2e5 --- /dev/null +++ b/bindings/javascript/.gitignore @@ -0,0 +1,3 @@ +publish.log +# generated by CMake configure from package-tmpl.json +package.json diff --git a/bindings/javascript/CMakeLists.txt b/bindings/javascript/CMakeLists.txt new file mode 100644 index 0000000..6b5af79 --- /dev/null +++ b/bindings/javascript/CMakeLists.txt @@ -0,0 +1,41 @@ +set(TARGET libwhisper) + +add_executable(${TARGET} + emscripten.cpp + ) + +target_link_libraries(${TARGET} PRIVATE + whisper + ) + +unset(EXTRA_FLAGS) + +if (WHISPER_WASM_SINGLE_FILE) + set(EXTRA_FLAGS "-s SINGLE_FILE=1") + message(STATUS "Embedding WASM inside whisper.js") + + add_custom_command( + TARGET ${TARGET} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_BINARY_DIR}/bin/libwhisper.js + ${CMAKE_CURRENT_SOURCE_DIR}/whisper.js + ) + + add_custom_command( + TARGET ${TARGET} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_BINARY_DIR}/bin/libwhisper.worker.js + ${CMAKE_CURRENT_SOURCE_DIR}/libwhisper.worker.js + ) +endif() + +set_target_properties(${TARGET} PROPERTIES LINK_FLAGS " \ + --bind \ + -s MODULARIZE=1 \ + -s EXPORT_NAME=\"'whisper_factory'\" \ + -s FORCE_FILESYSTEM=1 \ + -s USE_PTHREADS=1 \ + -s PTHREAD_POOL_SIZE=8 \ + -s ALLOW_MEMORY_GROWTH=1 \ + ${EXTRA_FLAGS} \ + ") diff --git a/bindings/javascript/README.md b/bindings/javascript/README.md new file mode 100644 index 0000000..5e726e1 --- /dev/null +++ b/bindings/javascript/README.md @@ -0,0 +1,81 @@ +# whisper.cpp + +Node.js package for Whisper speech recognition + +Package: https://www.npmjs.com/package/whisper.cpp + +## Details + +The performance is comparable to when running `whisper.cpp` in the browser via WASM. + +The API is currently very rudimentary: [bindings/javascript/emscripten.cpp](/bindings/javascript/emscripten.cpp) + +For sample usage check [tests/test-whisper.js](/tests/test-whisper.js) + +## Package building + test + +```bash +# load emscripten +source /path/to/emsdk/emsdk_env.sh + +# clone repo +git clone https://github.com/ggerganov/whisper.cpp +cd whisper.cpp + +# grab base.en model +./models/download-ggml-model.sh base.en + +# prepare PCM sample for testing +ffmpeg -i samples/jfk.wav -f f32le -acodec pcm_f32le samples/jfk.pcmf32 + +# build +mkdir build-em && cd build-em +emcmake cmake .. && make -j + +# run test +node ../tests/test-whisper.js + +# For Node.js versions prior to v16.4.0, experimental features need to be enabled: +node --experimental-wasm-threads --experimental-wasm-simd ../tests/test-whisper.js + +# publish npm package +make publish-npm +``` + +## Sample run + +```text +$ node --experimental-wasm-threads --experimental-wasm-simd ../tests/test-whisper.js + +whisper_model_load: loading model from 'whisper.bin' +whisper_model_load: n_vocab = 51864 +whisper_model_load: n_audio_ctx = 1500 +whisper_model_load: n_audio_state = 512 +whisper_model_load: n_audio_head = 8 +whisper_model_load: n_audio_layer = 6 +whisper_model_load: n_text_ctx = 448 +whisper_model_load: n_text_state = 512 +whisper_model_load: n_text_head = 8 +whisper_model_load: n_text_layer = 6 +whisper_model_load: n_mels = 80 +whisper_model_load: f16 = 1 +whisper_model_load: type = 2 +whisper_model_load: adding 1607 extra tokens +whisper_model_load: mem_required = 506.00 MB +whisper_model_load: ggml ctx size = 140.60 MB +whisper_model_load: memory size = 22.83 MB +whisper_model_load: model size = 140.54 MB + +system_info: n_threads = 8 / 10 | AVX = 0 | AVX2 = 0 | AVX512 = 0 | NEON = 0 | F16C = 0 | FP16_VA = 0 | WASM_SIMD = 1 | BLAS = 0 | + +operator(): processing 176000 samples, 11.0 sec, 8 threads, 1 processors, lang = en, task = transcribe ... + +[00:00:00.000 --> 00:00:11.000] And so my fellow Americans, ask not what your country can do for you, ask what you can do for your country. + +whisper_print_timings: load time = 162.37 ms +whisper_print_timings: mel time = 183.70 ms +whisper_print_timings: sample time = 4.27 ms +whisper_print_timings: encode time = 8582.63 ms / 1430.44 ms per layer +whisper_print_timings: decode time = 436.16 ms / 72.69 ms per layer +whisper_print_timings: total time = 9370.90 ms +``` diff --git a/bindings/javascript/emscripten.cpp b/bindings/javascript/emscripten.cpp new file mode 100644 index 0000000..b442c1f --- /dev/null +++ b/bindings/javascript/emscripten.cpp @@ -0,0 +1,93 @@ +// +// This is the Javascript API of whisper.cpp +// +// Very crude at the moment. +// Feel free to contribute and make this better! +// +// See the tests/test-whisper.js for sample usage +// + +#include "whisper.h" + +#include <emscripten.h> +#include <emscripten/bind.h> + +#include <thread> +#include <vector> + +struct whisper_context * g_context; + +EMSCRIPTEN_BINDINGS(whisper) { + emscripten::function("init", emscripten::optional_override([](const std::string & path_model) { + if (g_context == nullptr) { + g_context = whisper_init_from_file_with_params(path_model.c_str(), whisper_context_default_params()); + if (g_context != nullptr) { + return true; + } else { + return false; + } + } + + return false; + })); + + emscripten::function("free", emscripten::optional_override([]() { + if (g_context) { + whisper_free(g_context); + g_context = nullptr; + } + })); + + emscripten::function("full_default", emscripten::optional_override([](const emscripten::val & audio, const std::string & lang, bool translate) { + if (g_context == nullptr) { + return -1; + } + + struct whisper_full_params params = whisper_full_default_params(whisper_sampling_strategy::WHISPER_SAMPLING_GREEDY); + + params.print_realtime = true; + params.print_progress = false; + params.print_timestamps = true; + params.print_special = false; + params.translate = translate; + params.language = whisper_is_multilingual(g_context) ? lang.c_str() : "en"; + params.n_threads = std::min(8, (int) std::thread::hardware_concurrency()); + params.offset_ms = 0; + + std::vector<float> pcmf32; + const int n = audio["length"].as<int>(); + + emscripten::val heap = emscripten::val::module_property("HEAPU8"); + emscripten::val memory = heap["buffer"]; + + pcmf32.resize(n); + + emscripten::val memoryView = audio["constructor"].new_(memory, reinterpret_cast<uintptr_t>(pcmf32.data()), n); + memoryView.call<void>("set", audio); + + // print system information + { + printf("\n"); + printf("system_info: n_threads = %d / %d | %s\n", + params.n_threads, std::thread::hardware_concurrency(), whisper_print_system_info()); + + printf("\n"); + printf("%s: processing %d samples, %.1f sec, %d threads, %d processors, lang = %s, task = %s ...\n", + __func__, int(pcmf32.size()), float(pcmf32.size())/WHISPER_SAMPLE_RATE, + params.n_threads, 1, + params.language, + params.translate ? "translate" : "transcribe"); + + printf("\n"); + } + + // run whisper + { + whisper_reset_timings(g_context); + whisper_full(g_context, params, pcmf32.data(), pcmf32.size()); + whisper_print_timings(g_context); + } + + return 0; + })); +} diff --git a/bindings/javascript/libwhisper.worker.js b/bindings/javascript/libwhisper.worker.js new file mode 100644 index 0000000..db2083a --- /dev/null +++ b/bindings/javascript/libwhisper.worker.js @@ -0,0 +1 @@ +"use strict";var Module={};var ENVIRONMENT_IS_NODE=typeof process=="object"&&typeof process.versions=="object"&&typeof process.versions.node=="string";if(ENVIRONMENT_IS_NODE){var nodeWorkerThreads=require("worker_threads");var parentPort=nodeWorkerThreads.parentPort;parentPort.on("message",data=>onmessage({data:data}));var fs=require("fs");Object.assign(global,{self:global,require:require,Module:Module,location:{href:__filename},Worker:nodeWorkerThreads.Worker,importScripts:f=>(0,eval)(fs.readFileSync(f,"utf8")+"//# sourceURL="+f),postMessage:msg=>parentPort.postMessage(msg),performance:global.performance||{now:Date.now}})}var initializedJS=false;function threadPrintErr(){var text=Array.prototype.slice.call(arguments).join(" ");if(ENVIRONMENT_IS_NODE){fs.writeSync(2,text+"\n");return}console.error(text)}function threadAlert(){var text=Array.prototype.slice.call(arguments).join(" ");postMessage({cmd:"alert",text:text,threadId:Module["_pthread_self"]()})}var err=threadPrintErr;self.alert=threadAlert;Module["instantiateWasm"]=(info,receiveInstance)=>{var module=Module["wasmModule"];Module["wasmModule"]=null;var instance=new WebAssembly.Instance(module,info);return receiveInstance(instance)};self.onunhandledrejection=e=>{throw e.reason||e};function handleMessage(e){try{if(e.data.cmd==="load"){let messageQueue=[];self.onmessage=e=>messageQueue.push(e);self.startWorker=instance=>{Module=instance;postMessage({"cmd":"loaded"});for(let msg of messageQueue){handleMessage(msg)}self.onmessage=handleMessage};Module["wasmModule"]=e.data.wasmModule;for(const handler of e.data.handlers){Module[handler]=(...args)=>{postMessage({cmd:"callHandler",handler:handler,args:args})}}Module["wasmMemory"]=e.data.wasmMemory;Module["buffer"]=Module["wasmMemory"].buffer;Module["ENVIRONMENT_IS_PTHREAD"]=true;if(typeof e.data.urlOrBlob=="string"){importScripts(e.data.urlOrBlob)}else{var objectUrl=URL.createObjectURL(e.data.urlOrBlob);importScripts(objectUrl);URL.revokeObjectURL(objectUrl)}whisper_factory(Module)}else if(e.data.cmd==="run"){Module["__emscripten_thread_init"](e.data.pthread_ptr,0,0,1);Module["__emscripten_thread_mailbox_await"](e.data.pthread_ptr);Module["establishStackSpace"]();Module["PThread"].receiveObjectTransfer(e.data);Module["PThread"].threadInitTLS();if(!initializedJS){Module["__embind_initialize_bindings"]();initializedJS=true}try{Module["invokeEntryPoint"](e.data.start_routine,e.data.arg)}catch(ex){if(ex!="unwind"){throw ex}}}else if(e.data.cmd==="cancel"){if(Module["_pthread_self"]()){Module["__emscripten_thread_exit"](-1)}}else if(e.data.target==="setimmediate"){}else if(e.data.cmd==="checkMailbox"){if(initializedJS){Module["checkMailbox"]()}}else if(e.data.cmd){err(`worker.js received unknown command ${e.data.cmd}`);err(e.data)}}catch(ex){if(Module["__emscripten_thread_crashed"]){Module["__emscripten_thread_crashed"]()}throw ex}}self.onmessage=handleMessage; diff --git a/bindings/javascript/package-tmpl.json b/bindings/javascript/package-tmpl.json new file mode 100644 index 0000000..33777d1 --- /dev/null +++ b/bindings/javascript/package-tmpl.json @@ -0,0 +1,26 @@ +{ + "name": "whisper.cpp", + "version": "@WHISPER_VERSION@", + "description": "Whisper speech recognition", + "main": "whisper.js", + "scripts": { + "test": "echo \"todo: add tests\" && exit 0" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/ggerganov/whisper.cpp" + }, + "keywords": [ + "openai", + "whisper", + "speech-to-text", + "speech-recognition", + "transformer" + ], + "author": "Georgi Gerganov", + "license": "MIT", + "bugs": { + "url": "https://github.com/ggerganov/whisper.cpp/issues" + }, + "homepage": "https://github.com/ggerganov/whisper.cpp#readme" +} diff --git a/bindings/javascript/whisper.js b/bindings/javascript/whisper.js new file mode 100644 index 0000000..77dd855 --- /dev/null +++ b/bindings/javascript/whisper.js @@ -0,0 +1,19 @@ + +var whisper_factory = (() => { + var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined; + if (typeof __filename !== 'undefined') _scriptDir = _scriptDir || __filename; + return ( +function(moduleArg = {}) { + +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_I16(){if(wasmMemory.buffer!=HEAP8.buffer){updateMemoryViews()}return HEAP16}function GROWABLE_HEAP_U16(){if(wasmMemory.buffer!=HEAP8.buffer){updateMemoryViews()}return HEAPU16}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_F32(){if(wasmMemory.buffer!=HEAP8.buffer){updateMemoryViews()}return HEAPF32}function GROWABLE_HEAP_F64(){if(wasmMemory.buffer!=HEAP8.buffer){updateMemoryViews()}return HEAPF64}var Module=moduleArg;var readyPromiseResolve,readyPromiseReject;Module["ready"]=new Promise((resolve,reject)=>{readyPromiseResolve=resolve;readyPromiseReject=reject});var moduleOverrides=Object.assign({},Module);var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};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=Module["ENVIRONMENT_IS_PTHREAD"]||false;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readAsync,readBinary,setWindowTitle;if(ENVIRONMENT_IS_NODE){var fs=require("fs");var nodePath=require("path");if(ENVIRONMENT_IS_WORKER){scriptDirectory=nodePath.dirname(scriptDirectory)+"/"}else{scriptDirectory=__dirname+"/"}read_=(filename,binary)=>{filename=isFileURI(filename)?new URL(filename):nodePath.normalize(filename);return fs.readFileSync(filename,binary?undefined:"utf8")};readBinary=filename=>{var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret)}return ret};readAsync=(filename,onload,onerror,binary=true)=>{filename=isFileURI(filename)?new URL(filename):nodePath.normalize(filename);fs.readFile(filename,binary?undefined:"utf8",(err,data)=>{if(err)onerror(err);else onload(binary?data.buffer:data)})};if(!Module["thisProgram"]&&process.argv.length>1){thisProgram=process.argv[1].replace(/\\/g,"/")}arguments_=process.argv.slice(2);quit_=(status,toThrow)=>{process.exitCode=status;throw toThrow};Module["inspect"]=()=>"[Emscripten Module object]";let nodeWorkerThreads;try{nodeWorkerThreads=require("worker_threads")}catch(e){console.error('The "worker_threads" module is not supported in this node.js build - perhaps a newer version is needed?');throw e}global.Worker=nodeWorkerThreads.Worker}else 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(_scriptDir){scriptDirectory=_scriptDir}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.replace(/[?#].*/,"").lastIndexOf("/")+1)}else{scriptDirectory=""}if(!ENVIRONMENT_IS_NODE){read_=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};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,onload,onerror)=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=()=>{if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}onerror()};xhr.onerror=onerror;xhr.send(null)}}setWindowTitle=title=>document.title=title}else{}if(ENVIRONMENT_IS_NODE){if(typeof performance=="undefined"){global.performance=require("perf_hooks").performance}}var defaultPrint=console.log.bind(console);var defaultPrintErr=console.error.bind(console);if(ENVIRONMENT_IS_NODE){defaultPrint=(...args)=>fs.writeSync(1,args.join(" ")+"\n");defaultPrintErr=(...args)=>fs.writeSync(2,args.join(" ")+"\n")}var out=Module["print"]||defaultPrint;var err=Module["printErr"]||defaultPrintErr;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 noExitRuntime=Module["noExitRuntime"]||true;if(typeof WebAssembly!="object"){abort("no native wasm support detected")}var wasmMemory;var wasmModule;var ABORT=false;var EXITSTATUS;function assert(condition,text){if(!condition){abort(text)}}var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,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)}var INITIAL_MEMORY=Module["INITIAL_MEMORY"]||16777216;assert(INITIAL_MEMORY>=65536,"INITIAL_MEMORY should be larger than STACK_SIZE, was "+INITIAL_MEMORY+"! (STACK_SIZE="+65536+")");if(ENVIRONMENT_IS_PTHREAD){wasmMemory=Module["wasmMemory"]}else{if(Module["wasmMemory"]){wasmMemory=Module["wasmMemory"]}else{wasmMemory=new WebAssembly.Memory({"initial":INITIAL_MEMORY/65536,"maximum":2147483648/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();INITIAL_MEMORY=wasmMemory.buffer.byteLength;var wasmTable;var __ATPRERUN__=[];var __ATINIT__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeKeepaliveCounter=0;function keepRuntimeAlive(){return noExitRuntime||runtimeKeepaliveCounter>0}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;if(!Module["noFSInit"]&&!FS.init.initialized)FS.init();FS.ignorePermissions=false;TTY.init();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 getUniqueRunDependency(id){return id}function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}function abort(what){if(Module["onAbort"]){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,";function isDataURI(filename){return filename.startsWith(dataURIPrefix)}function isFileURI(filename){return filename.startsWith("file://")}var wasmBinaryFile;wasmBinaryFile="data:application/octet-stream;base64,AGFzbQEAAAAByARKYAF/AX9gAX8AYAJ/fwBgA39/fwF/YAJ/fwF/YAN/f38AYAR/f39/AGAGf39/f39/AX9gBH9/f38Bf2AAAGAFf39/f38Bf2AFf39/f38AYAZ/f39/f38AYAh/f39/f39/fwF/YAABf2AHf39/f39/fwF/YAd/f39/f39/AGABfQF9YAV/fn5+fgBgA39+fwF+YAV/f39/fgF/YAR/f39/AX5gBH9+fn8AYAp/f39/f39/f39/AX9gB39/f39/fn4Bf2AGf39/f35+AX9gBX9/fn9/AGADf39/AXxgBH9/f38BfGAEf39+fgF/YAJ/fgBgAXwBfWACfH8BfGAFf39+fn4Bf2AIf39/f39/f38AYAx/f39/f39/f39/f38Bf2ADf35/AX9gD39/f39/f39/f39/f39/fwBgCn9/f39/f39/f38AYAt/f39/f39/f39/fwF/YAZ/fH9/f38Bf2AJf39/f39/f39/AGAFf39/f3wBf2AAAXxgA39/fgF/YAABfmACf3wAYAN/f30Bf2AEfn5+fgF/YAJ9fQF9YAJ+fwF/YAN/f3wBf2ABfABgCH9/fn5+f39/AX9gBX9/f399AGAGf39+fn9/AX9gAn5+AXxgAnx8AXxgBn9/f39+fgBgBH9/fn4AYAR/f35/AX9gA39/fwF9YAR/f39+AX5gA39/fgBgAn5+AX1gAn9/AX5gA35+fgF/YAF+AX9gAXwBfGABfwF+YAJ9fwF/YAV/f399fQBgBH9/f30AYAl/f39/f39/f38BfwKmAjABYQFiAAkBYQFjAAUBYQFkAAUBYQFlACsBYQFmAAEBYQFnAAsBYQFoABABYQFpAAQBYQFqAAABYQFrAAUBYQFsAAEBYQFtAAEBYQFuAAkBYQFvAAABYQFwAAgBYQFxAAMBYQFyAAIBYQFzAAUBYQF0AAgBYQF1AAABYQF2AAEBYQF3ABsBYQF4AAoBYQF5ABABYQF6AA4BYQFBAA4BYQFCAAoBYQFDAAQBYQFEAAQBYQFFAAABYQFGAAUBYQFHAAgBYQFIABwBYQFJAAEBYQFKAAEBYQFLAAgBYQFMAAMBYQFNAAgBYQFOAAkBYQFPAAEBYQFQAA4BYQFRAAIBYQFSAAYBYQFTAAIBYQFUAAEBYQFVAAYBYQFWAAQBYQFhAgOAAoCAAgOhB58HAQAF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AgQgBSAGGyEGA0ACQAJAAkACQAJAIAQiAigCFCACLQAbIgQgBMBBAEgiBxsiBCAGIAQgBkkiCRsiBQRAIAggAigCECACQRBqIAcbIgcgBRBKIgpFBEAgBCAGSw0CDAMLIApBAE4NAgwBCyAEIAZNDQILIAIhBSACKAIAIgQNBAwFCyAHIAggBRBKIgQNAQsgCQ0BDAQLIARBAE4NAwsgAigCBCIEDQALIAJBBGohBQtBIBAyIgQgAygCACIDKQIANwIQIAQgAygCCDYCGCADQgA3AgAgA0EANgIIIAQgAjYCCCAEQgA3AgAgBEEANgIcIAUgBDYCACAEIQIgASgCACgCACIDBEAgASADNgIAIAUoAgAhAgsgASgCBCACEKQBIAEgASgCCEEBajYCCEEBDAELIAIhBEEACzoABCAAIAQ2AgALBgAgABAvC4cFAgp/AX4jAEFAaiICJAAgAiAALQAIOgA4IAIgACkDADcDMCAAKAIUIQMgACgCECEEIABCADcDECAAKAIYIQUgAEEANgIYIAIgACgCRDYCKCACIAApAjw3AyAgAiAA/QACLP0LAxAgAiAA/QACHP0LAwAgACgCXCEGIAAoAlghByAAQgA3A1ggACgCTCEIIAAoAlAhCSAAKAJUIQogACgCSCELIAD9DAAAAAAAAAAAAAAAAAAAAAD9CwNIIAAgASkDADcDACAAIAEtAAg6AAggACABKAIQNgIQIAAgASgCFDYCFCAAIAEoAhg2AhggACkDYCEMIAFBADYCGCABQgA3AxAgACABKAJENgJEIAAgASkCPDcCPCAAIAH9AAIs/QsCLCAAIAH9AAIc/QsCHCAAQcgAaiABQcgAahCHAiABIAItADg6AAggASACKQMwNwMAIAEoAhAiAARAIAEgADYCFCAAEC8LIAEgBTYCGCABIAM2AhQgASAENgIQIAEgAigCKDYCRCABIAIpAyA3AjwgASAC/QADEP0LAiwgASAC/QADAP0LAhwgASgCSCIEBEAgASgCTCIDIAQiAEcEQANAIANBDGsiACgCACIFBEAgA0EIayAFNgIAIAUQLwsgACIDIARHDQALIAEoAkghAAsgASAENgJMIAAQLwsgASALNgJIIAEgCTYCUCABIAg2AkwgASgCVCIEBEAgASgCWCIDIAQiAEcEQANAIANBDGsiACgCACIFBEAg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//8Ba0GBgH5LDQELIAFQIAJC////////////AIMiC0KAgICAgIDA//8AVCALQoCAgICAgMD//wBRG0UEQCACQoCAgICAgCCEIQoMAgsgA1AgBEL///////////8AgyICQoCAgICAgMD//wBUIAJCgICAgICAwP//AFEbRQRAIARCgICAgICAIIQhCiADIQEMAgsgASALQoCAgICAgMD//wCFhFAEQCACIAOEUARAQoCAgICAgOD//wAhCkIAIQEMAwsgCkKAgICAgIDA//8AhCEKQgAhAQwCCyADIAJCgICAgICAwP//AIWEUARAIAEgC4QhGUIAIQEgGVAEQEKAgICAgIDg//8AIQoMAwsgCkKAgICAgIDA//8AhCEKDAILIAEgC4RQBEBCACEBDAILIAIgA4RQBEBCACEBDAILIAtC////////P1gEQCAFQdAAaiABIA0gASANIA1QIgYbeSAGQQZ0rXynIgZBD2sQZkEQIAZrIQYgBSkDWCINQiCIIQ4gBSkDUCEBCyACQv///////z9WDQAgBUFAayADIAwgAyAMIAxQIggbeSAIQQZ0rXynIghBD2sQZiAGIAhrQRBqIQYgBSkDSCEMIAUpA0AhAwsgA0IPhiILQoCA/v8PgyICIAFCIIgiBH4iECALQiCIIhMgAUL/////D4MiAX58Ig9CIIYiESABIAJ+fCILIBFUrSACIA1C/////w+DIg1+IhUgBCATfnwiESAMQg+GIhIgA0IxiIRC/////w+DIgMgAX58IhQgDyAQVK1CIIYgD0IgiIR8Ig8gAiAOQoCABIQiDH4iFiANIBN+fCIOIBJCIIhCgICAgAiEIgIgAX58IhAgAyAEfnwiEkIghnwiF3whASAHIAlqIAZqQf//AGshBgJAIAIgBH4iGCAMIBN+fCIEIBhUrSAEIAQgAyANfnwiBFatfCACIAx+fCAEIAQgESAVVK0gESAUVq18fCIEVq18IAMgDH4iAyACIA1+fCICIANUrUIghiACQiCIhHwgBCACQiCGfCICIARUrXwgAiACIBAgElatIA4gFlStIA4gEFatfHxCIIYgEkIgiIR8IgJWrXwgAiACIA8gFFStIA8gF1atfHwiAlatfCIEQoCAgICAgMAAg0IAUgRAIAZBAWohBgwBCyALQj+IIRogBEIBhiACQj+IhCEEIAJCAYYg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AisDACADokHAoAIrAwCgoCAEoiABQRd1t0GooAIrAwCiIAJBsJ4CaisDAKAgA6CgtiEACyAAC+4CAgZ/A34jAEFAaiIDJAACQAJAIAEpAxAgAikDEFINACACKQMgIgkgASkDIIFCAFINACACKQMoIgogASkDKIFCAFINACABKAIwIAEoAjRLDQECfwJAIAEoAogBDQAgAigCiAENAEEADAELQQELIQggAyABKQMYNwMgIAIpAxghCyADIAo3AzggAyAJNwMwIAMgCzcDKCAAQQAgASgCDCIEIAIoAgwiByAEIAdKGyADQSBqQQBBABBJIgRBFzYCQCAIBEAgACAEKAIAIAQoAgwgBEEQakEAQQAQSSEFCyAEIAE2AowBIAQgBTYCiAEgBCACNgKQASADQUBrJAAgBA8LQbzDAigCABAwGiADQZTXADYCGCADQecfNgIUIANB5CY2AhBBuMMCKAIAQcvkACADQRBqEDEQAAALQbzDAigCABAwGiADQdvXADYCCCADQegfNgIEIANB5CY2AgBBuMMCKAIAQcvkACADEDEQAAALoQICA38BfgJAIAAoAgwiAkEBcQRAQRgQMiECIAAoAiQoAgQhAyACQfysATYCACACIAM2AgQgAkEIaiAAKAIAIgM2AgAgA0EEakEB/h4CABogAiAAKQIEIgU3AgwgAiAFpyIDIAEgAygCACgCFBEEADoAFCAAKAIkIAI2AgQMAQsgAkEIcQRAQRgQMiECIAAoAiQoAgQhAyACQditATYCACACIAM2AgQgAkEIaiAAKAIAIgM2AgAgA0EEakEB/h4CABogACkCBCEFIAIgAToAFCACIAU3AgwgACgCJCACNgIEDAELQQwQMiECIAAoAiQiAygCBCEEIAIgAToACCACQbSuATYCACACIAQ2AgQgAyACNgIECyAAIAAoAiQoAgQ2AiQLdQEBfyMAQRBrIgIkACACIAE6AA8CQCAALQALQQd2BEAgACgCACEBIABBATYCBAwBCyAAIgEgAS0AC0GAAXFBAXI6AAsgASABLQALQf8AcToACwsgASACLQAPOgAAIAJBADoADiABIAItAA46AAEgAkEQaiQAC6sBAgJ+AX8gACkDICEBIAApAxghAiAAKAIAIgNBEGtBcU0EQCADQSRsQZibAWooAgAgACgCMCAAKAIQQQFrbGogACgCNCACp0EBa2xqIAAoAjggAadBAWtsaiAAKAI8IAAoAihBAWtsag8LIAA1AjQgAkIBfX4gACkDECAANQIwfiADQSRsQZSbAWo1AgB/fCAANQI4IAFCAX1+fCAANQI8IAApAyhCAX1+fKcLDQAgACgCABD7AxogAAsNACAAKAIAEP0DGiAACw4AIABB0ABqEDtB0ABqC8EBAQN/IwBBEGsiBSQAAkAgAiAALQALQQd2BH8gACgCCEH/////B3FBAWsFQQoLIgQCfyAALQALQQd2BEAgACgCBAwBCyAALQALQf8AcQsiA2tNBEAgAkUNAQJ/IAAtAAtBB3YEQCAAKAIADAELIAALIgQgA2ogASACEHcgACACIANqIgEQmQEgBUEAOgAPIAEgBGogBS0ADzoAAAwBCyAAIAQgAiAEayADaiADIANBACACIAEQzAELIAVBEGokACAAC3UBAX4gACABIAR+IAIgA358IANCIIgiAiABQiCIIgR+fCADQv////8PgyIDIAFC/////w+DIgF+IgVCIIggAyAEfnwiA0IgiHwgASACfiADQv////8Pg3wiAUIgiHw3AwggACAFQv////8PgyABQiCGhDcDAAsYACAALQAAQSBxRQRAIAEgAiAAEM4CGgsLqwEBBn8jAEEQayICJAAgACgCBCEDIAEgACgCACIEcCIFIQACQAJAA0ACQCADIABBAnRqIgYoAgAiB0UNACABIAdGDQAgAEEBaiIAQQAgACAERxsiACAFRw0BDAILCyAAQX9HDQELQbzDAigCABAwGiACQbUwNgIIIAJBlvEANgIEIAJB5CY2AgBBuMMCKAIAQcvkACACEDEQAAALIAYgATYCACACQRBqJAAgAAtGAQJ/IwBBEGsiBSQAIAUgAjYCDCAFIAQ2AgggBUEEaiAFQQxqEH8hBiAAIAEgAyAFKAIIELABIQAgBhB+IAVBEGokACAAC+0BAQJ/An8gAC0AC0EHdgRAIAAoAgQMAQsgAC0AC0H/AHELIQQCQCACIAFrQQVIDQAgBEUNACABIAIQ6gEgAkEEayEEAn8gAC0AC0EHdgRAIAAoAgQMAQsgAC0AC0H/AHELAn8gAC0AC0EHdgRAIAAoAgAMAQsgAAsiAmohBQJAA0ACQCACLAAAIQAgASAETw0AAkAgAEEATA0AIABB/wBODQAgACABKAIARw0DCyABQQRqIQEgAiAFIAJrQQFKaiECDAELCyAAQQBMDQEgAEH/AE4NASACLAAAIAQoAgBBAWtLDQELIANBBDYCAAsLdgEBfyMAQRBrIgIkACAALQALQQd2BEAgACAAKAIAIAAoAghB/////wdxEPEBCyAAIAEoAgg2AgggACABKQIANwIAIAEgAS0AC0GAAXE6AAsgASABLQALQf8AcToACyACQQA6AA8gASACLQAPOgAAIAJBEGokAAtQAQF+AkAgA0HAAHEEQCABIANBQGqthiECQgAhAQwBCyADRQ0AIAIgA60iBIYgAUHAACADa62IhCECIAEgBIYhAQsgACABNwMAIAAgAjcDCAtvAQF/IwBBgAJrIgUkAAJAIAIgA0wNACAEQYDABHENACAFIAFB/wFxIAIgA2siA0GAAiADQYACSSIBGxCgASABRQRAA0AgACAFQYACEGEgA0GAAmsiA0H/AUsNAAsLIAAgBSADEGELIAVBgAJqJAALegEDfwJAAkAgACIBQQNxRQ0AIAEtAABFBEBBAA8LA0AgAUEBaiIBQQNxRQ0BIAEtAAANAAsMAQsDQCABIgJBBGohASACKAIAIgNBf3MgA0GBgoQIa3FBgIGChHhxRQ0ACwNAIAIiAUEBaiECIAEtAAANAAsLIAEgAGsLOAIDfwF+IwBBEGsiACQAIAAQ1wEgACkDACEDIAAoAgghAiAAQRBqJAAgAkHoB22sIANCwIQ9fnwL9gIDA38BfAF9IwBBEGsiASQAAn0gALwiA0H/////B3EiAkHan6T6A00EQEMAAIA/IAJBgICAzANJDQEaIAC7EIQBDAELIAJB0aftgwRNBEAgAkHkl9uABE8EQEQYLURU+yEJQEQYLURU+yEJwCADQQBIGyAAu6AQhAGMDAILIAC7IQQgA0EASARAIAREGC1EVPsh+T+gEIMBDAILRBgtRFT7Ifk/IAShEIMBDAELIAJB1eOIhwRNBEAgAkHg27+FBE8EQEQYLURU+yEZQEQYLURU+yEZwCADQQBIGyAAu6AQhAEMAgsgA0EASARARNIhM3982RLAIAC7oRCDAQwCCyAAu0TSITN/fNkSwKAQgwEMAQsgACAAkyACQYCAgPwHTw0AGgJAAkACQAJAIAAgAUEIahCvBEEDcQ4DAAECAwsgASsDCBCEAQwDCyABKwMImhCDAQwCCyABKwMIEIQBjAwBCyABKwMIEIMBCyEFIAFBEGokACAFC9YBAQJ/IwBBEGsiBCQAAkACQCACQQtJBEAgACIDIAAtAAtBgAFxIAJyOgALIAAgAC0AC0H/AHE6AAsMAQsgAkHv////B0sNASAEQQhqIAAgAkELTwR/IAJBEGpBcHEiAyADQQFrIgMgA0ELRhsFQQoLQQFqEMMBIAQoAgwaIAAgBCgCCCIDNgIAIAAgACgCCEGAgICAeHEgBCgCDEH/////B3FyNgIIIAAgACgCCEGAgICAeHI2AgggACACNgIECyADIAEgAkEBahB3IARBEGokAA8LEE0ACwoAIABBlIo1EHkLBABBAAuJAgEHfyABIAAoAggiAyAAKAIEIgJrQQJ1TQRAIAAgAQR/IAJBACABQQJ0IgD8CwAgACACagUgAgs2AgQPCwJAIAIgACgCACIFa0ECdSIHIAFqIgRBgICAgARJBEBB/////wMgAyAFayIDQQF1IgggBCAEIAhJGyADQfz///8HTxsiAwRAIANBgICAgARPDQIgA0ECdBAyIQYLIAdBAnQgBmoiBEEAIAFBAnQiAfwLACABIARqIQEgAiAFRwRAA0AgBEEEayIEIAJBBGsiAioCADgCACACIAVHDQALCyAAIAYgA0ECdGo2AgggACABNgIEIAAgBDYCACAFBEAgBRAvCw8LEDYACxBHAAstACACRQRAIAAoAgQgASgCBEYPCyAAIAFGBEBBAQ8LIAAoAgQgASgCBBCfAUULUgEBfyABQQFrIgJBEE0EfyACQQJ0QdypA2ooAgAFQcYiCyECIABB6LUDNgIAIABB7LYDNgIAIABBBGogAhCKAyAAIAE2AgggAEGooQM2AgAgAAvHCQIEfwZ+IwBB8ABrIgYkACAEQv///////////wCDIQkCQAJAIAFQIgUgAkL///////////8AgyIKQoCAgICAgMD//wB9QoCAgICAgMCAgH9UIApQG0UEQCADQgBSIAlCgICAgICAwP//AH0iC0KAgICAgIDAgIB/ViALQoCAgICAgMCAgH9RGw0BCyAFIApCgICAgICAwP//AFQgCkKAgICAgIDA//8AURtFBEAgAkKAgICAgIAghCEEIAEhAwwCCyADUCAJQoCAgICAgMD//wBUIAlCgICAgICAwP//AFEbRQRAIARCgICA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Qd/bv4UETQRAIAC7IQQgA0EASARAIARE0iEzf3zZEkCgEIQBIQAMAwsgBETSITN/fNkSwKAQhAGMIQAMAgtEGC1EVPshGUBEGC1EVPshGcAgA0EASBsgALugEIMBIQAMAQsgAkGAgID8B08EQCAAIACTIQAMAQsCQAJAAkACQCAAIAFBCGoQrwRBA3EOAwABAgMLIAErAwgQgwEhAAwDCyABKwMIEIQBIQAMAgsgASsDCJoQgwEhAAwBCyABKwMIEIQBjCEACyABQRBqJAAgAAuPBAEDfyACQYAETwRAIAAgASAC/AoAACAADwsgACACaiEEAkAgACABc0EDcUUEQAJ/IAAgAEEDcUUNABogACACRQ0AGiAAIAEgAEF/cyICIAQgAEEBaiIDIAMgBEkbaiIDIAJBA3EiAiACIANLG0EBaiIC/AoAACABIAJqIQEgACACagshAgJAIARBfHEiA0HAAEkNACACIANBQGoiBUsNAANAIAIgASgCADYCACACIAEoAgQ2AgQgAiABKAIINgIIIAIgASgCDDYCDCACIAEoAhA2AhAgAiABKAIUNgIUIAIgASgCGDYCGCACIAEoAhw2AhwgAiABKAIgNgIgIAIgASgCJDYCJCACIAEoAig2AiggAiABKAIsNgIsIAIgASgCMDYCMCACIAEoAjQ2AjQgAiABKAI4NgI4IAIgASgCPDYCPCABQUBrIQEgAkFAayICIAVNDQALCyACIANPDQEgAiABIAJBf3MgAyACQQRqIgUgAyAFSxtqQXxxQQRqIgP8CgAAIAEgA2ohASACIANqIQIMAQsgBEEESQRAIAAhAgwBCyAAIARBBGsiA0sEQCAAIQIMAQsgACECA0AgAiABLQAAOgAAIAIgAS0AAToAASACIAEtAAI6AAIgAiABLQADOgADIAFBBGohASACQQRqIgIgA00NAAsLIAIgBEkEQCACIAEgBCACa/wKAAALIAALIAAjAEEQayIBJAAgAEIANwIAIABBADYCCCABQRBqJAALugcBCH8jAEHQAGsiBCQAIAQgACkCGDcDSAJAAkACQAJ/IwBBIGsiAiQAIAQoAkwhBiABIAQoAkgiB3AiCCEDAkADQAJAIAYgA0ECdGoiCSgCACIFRQ0AIAEgBUYNACADQQFqIgNBACADIAdHGyIDIAhHDQEMAgsLIANBf0YNAAJA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KAIAKAIkEQAADAELIAgtAAALwCIGQQBOBH8gAygCCCAGQf8BcUECdGooAgBBwABxQQBHBUEAC0UNACADIAZBACADKAIAKAIkEQMAIQEDQAJAIAAQXRogAUEwayEBIAAgB0EMahBDDQAgBEECSA0AAn8gACgCACIFKAIMIgYgBSgCEEYEQCAFIAUoAgAoAiQRAAAMAQsgBi0AAAvAIgVBAE4EfyADKAIIIAVB/wFxQQJ0aigCAEHAAHFBAEcFQQALRQ0DIARBAWshBCADIAVBACADKAIAKAIkEQMAIAFBCmxqIQEMAQsLQQIhBSAAIAdBDGoQQ0UNAQsgAiACKAIAIAVyNgIACyAHQRBqJAAgAQuZAQEEfyMAQRBrIgQkACAEIAE2AgwgBCADNgIIIARBBGogBEEMahB/IQcgBCgCCCEDIwBBEGsiASQAIAEgAzYCDCABIAM2AghBfyEFAkBBAEEAIAIgAxCwASIDQQBIDQAgACADQQFqIgMQOyIANgIAIABFDQAgACADIAIgASgCDBCwASEFCyABQRBqJAAgBxB+IARBEGokACAFCy4AAkAgACgCBEHKAHEiAARAIABBwABGBEBBCA8LIABBCEcNAUEQDwtBAA8LQQoL+QECA34CfyMAQRBrIgUkAAJ+IAG9IgNC////////////AIMiAkKAgICAgICACH1C/////////+//AFgEQCACQjyGIQQgAkIEiEKAgICAgICAgDx8DAELIAJCgICAgICAgPj/AFoEQCADQjyGIQQgA0IEiEKAgICAgIDA//8AhAwBCyACUARAQgAMAQsgBSACQgAgA6dnQSBqIAJCIIinZyACQoCAgIAQVBsiBkExahBmIAUpAwAhBCAFKQMIQoCAgICAgMAAhUGM+AAgBmutQjCGhAshAiAAIAQ3AwAgACACIANCgICAgICAgICAf4OENwMIIAVBEGokAAsJACAAQQEQtQELKAEBfyAAQdypATYCACAAKAIEIgEEQCABIAEoAgAoAgQRAQALIAAQLwsMACAAKAIAIAEQ6QQLbAECfyAAKAIEIgEEQCABKAIIIgIEQCACEC8LIAEoAgwiAgRAIAIQLwsgASgCFCICBEAgAhAvCyABKAIYIgIEQCACEC8LIAEQLwsgACgCACIBBEAgAS0ABARAIAEoAgAQpwELIAEQLwsgABAvC40F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AgsgACAINgIcIAAgCTYCGCAAIAU2AhQgAkUNASACEC8PCyAAKAIcIQMgACgCGCECAkAgAC0AWgRAIAIgA0kNBSACIAAoAhQiBmsiB0EBaiIFQQBIDQQgB0H/////ByADIAZrIgNBAXQiBCAFIAQgBUsbIANB/////wNPGyIEBH8gBBAyBUEACyIFaiIDIAE6AAAgBCAFaiEIIANBAWohCQJAIAIgBkYEQCADIQUMAQsCQAJAIAdBEEkNACAGIAIgBWprIAJqQRBJDQAgA0EQayEKIAJBEGshCyACIAdBcHEiBGshAiADIARrIQNBACEBA0AgCiABayALIAFr/QAAAP0LAAAgAUEQaiIBIARHDQALIAQgB0YNAQsgBkF/cyACaiENIAIgBmtBA3EiBARAQQAhAQNAIANBAWsiAyACQQFrIgItAAA6AAAgAUEBaiIBIARHDQALCyANQQNJDQADQCADQQFrIAJBAWstAAA6AAAgA0ECayACQQJrLQAAOgAAIANBA2sgAkEDay0AADoAACADQQRrIgMgAkEEayICLQAAOgAAIAIgBkcNAAsLIAAoAhQhAgsgACAINgIcIAAgCTYCGCAAIAU2AhQgAg0BDAILIAIgA0cNBCACIAAoAhQiB2siBkEBaiIDQQBIDQMgBkH/////ByAGQQF0IgUgAyADIAVJGyAGQf////8DTxsiBAR/IAQQMgVBAAsiBWoiAyABOgAAIAQgBWohCCADQQFqIQkCQCACIAdGBEAgAyEFDAELAkACQCAGQRBJDQAgByACIAVqayACakEQSQ0AIANBEGshCiACQRBrIQsgAiAGQXBxIgRrIQIgAyAEayEDQQAhAQNAIAogAWsgCyABa/0AAAD9CwAAIAFBEGoiASAERw0ACyAEIAZGDQELIAdBf3MgAmohDiACIAdrQQNxIgQEQEEAIQEDQCADQQFrIgMgAkEBayICLQAAOgAAIAFBAWoiASAERw0ACwsgDkEDSQ0AA0AgA0EBayACQQFrLQAAOgAAIANBAmsgAkECay0AADoAACADQQNrIAJBA2stAAA6AAAgA0EEayIDIAJBBGsiAi0AADoAACACIAdHDQALCyAAKAIUIQILIAAgCDYCHCAAIAk2AhggACAFNgIUIAJFDQELIAIQLwsPCxA2AAsQNgALIAIgAToAACAAIAJBAWo2AhgLlAQBBH8gASAAIAFGIgI6AAwCQCACDQADQCABKAIIIgItAAwNAQJAIAIgAigCCCIDKAIAIgRGBEACQCADKAIEIgRFDQAgBC0ADA0ADAILAkAgASACKAIARgRAIAIhAQwBCyACIAIoAgQiASgCACIANgIEIAEgAAR/IAAgAjYCCCACKAIIBSADCzYCCCACKAIIIgAgACgCACACR0ECdGogATYCACABIAI2AgAgAiABNgIIIAEoAggiAygCACECCyABQQE6AAwgA0EAOgAMIAMgAigCBCIANgIAIAAEQCAAIAM2AggLIAIgAygCCDYCCCADKAIIIgAgACgCACADR0ECdGogAjYCACACIAM2AgQgAyACNgIIDwsCQCAERQ0AIAQtAAwNAAwBCwJAIAEgAigCAEcEQCACIQEMAQsgAiABKAIEIgA2AgAgASAABH8gACACNgIIIAIoAggFIAMLNgIIIAIoAggiACAAKAIAIAJHQQJ0aiABNgIAIAEgAjYCBCACIAE2AgggASgCCCEDCyABQQE6AAwgA0EAOgAMIAMgAygCBCIAKAIAIgE2AgQgAQRAIAEgAzYCCAsgACADKAIINgIIIAMoAggiASABKAIAIANHQQJ0aiAANgIAIAAgAzYCACADIAA2AggMAgsgBEEMaiEFIAJBAToADCADIAAgA0Y6AAwgBUEBOgAAIAMiASAARw0ACwsLnAIBBH8gACgCiAEiAQRAIAAgATYCjAEgARAvCyAAKAJ8IgEEQCAAIAE2AoABIAEQLwsgACgCcCIBBEAgACABNgJ0IAEQLwsgACgCZCIBBEAgACABNgJoIAEQLwsgACgCRCIDBEAgAyECIAMgACgCSCIBRwRAA0AgAUEMayICKAIAIgQEQCABQQhrIAQ2AgAgBBAvCyACIgEgA0cNAAsgACgCRCECCyAAIAM2AkggAhAvCyAAKAI4IgMEQCADIQIgAyAAKAI8IgFHBEADQCABQQxrIgIoAgAiBARAIAFBCGsgBDYCACAEEC8LIAIiASADRw0ACyAAKAI4IQILIAAgAzYCPCACEC8LIAAoAgAiAQRAIAAgATYCBCABEC8LC3ABA38gARBoIgJB8P///wdJBEACQCACQQpNBEAgACACOgALIAAhAwwBCyACQQ9yQQFqIgQQMiEDIAAgBEGAgICAeHI2AgggACADNgIAIAAgAjYCBAsgAyABIAL8CgAAIAIgA2pBADoAACAADwsQTQALHgEBfyAABEAgACgCACIBBEAgACABEQEACyAAEC8LC3sBAn8jAEEQayICJAAgACgCBCEDIAAgARB9AkAgAyAAKAIEIgNODQAgACgCDCADQQJ0akEEaygCACABRg0AQbzDAigCABAwGiACQekTNgIIIAJByPkANgIEIAJB5CY2AgBBuMMCKAIAQcvkACACEDEQAAALIAJBEGokAAsTACABQQF0QdCqA2pBAiAAEIEEC84BAQF/An8jAEEwayIDJAAgASgCiAFFBEAgACABKAIAIAEoAgwgAUEQakEAQQAQSSIARQRAQbzDAigCABAwGiADQdcvNgIYIANBxhQ2AhQgA0HkJjYCEEG4wwIoAgBBy+QAIANBEGoQMRAAAAsgACABNgKMASAAQQA2AogBIABBEzYCQCAAIAI4AkQgA0EwaiQAIAAMAQtBvMMCKAIAEDAaIANBmyE2AiggA0HcHjYCJCADQeQmNgIgQbjDAigCAEHL5AAgA0EgahAxEAAACwv0AgIDfwh+IwBBMGsiAyQAAn8CQAJAIAEpAxAiBiACKQMQIgeBQgBSDQAgASkDGCIIIAIpAxgiCYFCAFINACABKQMgIgogAikDICILgUIAUg0AIAEpAygiDCACKQMoIg2BQgBSDQAgAUEQaiEEAkAgASgCiAENACACKAKIAQ0ADAILAkAgBiAHUg0AIAggCVINACAKIAtSDQBBASEFIAwgDVENAgtBvMMCKAIAEDAaIANBq9cANgIYIANByBo2AhQgA0HkJjYCEEG4wwIoAgBBy+QAIANBEGoQMRAAAAtBvMMCKAIAEDAaIANBpdgANgIoIANBwho2AiQgA0HkJjYCIEG4wwIoAgBBy+QAIANBIGoQMRAAAAsgACABKAIAIAEoAgwgBEEAQQAQSSIEQQY2AkBBACAFRQ0AGiAAIAQoAgAgBCgCDCAEQRBqQQBBABBJCyEAIAQgATYCjAEgBCAANgKIASAEIAI2ApABIANBMGokACAEC3YBAX8jAEEQayICJAAgAiAANgIMAkAgACABRg0AA0AgAiABQQFrIgE2AgggACABTw0BIAIoAgwiAC0AACEBIAAgAigCCCIALQAAOgAAIAAgAToAACACIAIoAgxBAWoiADYCDCACKAIIIQEMAAsACyACQRBqJAAL2wgBAX9BAEEB/h4CkNY0QQBKBEADQEEAQQH+JQKQ1jQaEAMQ1gFBAEEB/h4CkNY0QQBKDQALCwJAAkAgAEHguwNGDQAgAEGUvANGBEBBASEBDAELIABByLwDRgRAQQIhAQwBCyAAQfy8A0YEQEEDIQEMAQsgAEGwvQNGBEBBBCEBDAELIABB5L0DRgRAQQUhAQwBCyAAQZi+A0YEQEEGIQEMAQsgAEHMvgNGBEBBByEBDAELIABBgL8DRgRAQQghAQwBCyAAQbS/A0YEQEEJIQEMAQsgAEHovwNGBEBBCiEBDAELIABBnMADRgRAQQshAQwBCyAAQdDAA0YEQEEMIQEMAQsgAEGEwQNGBEBBDSEBDAELIABBuMEDRgRAQQ4hAQwBCyAAQezBA0YEQEEPIQEMAQsgAEGgwgNGBEBBECEBDAELIABB1MIDRgRAQREhAQwBCyAAQYjDA0YEQEESIQEMAQsgAEG8wwNGBEBBEyEBDAELIABB8MMDRgRAQRQhAQwBCyAAQaTEA0YEQEEVIQEMAQsgAEHYxANGBEBBFiEBDAELIABBjMUDRgRAQRchAQwBCyAAQcDFA0YEQEEYIQEMAQsgAEH0xQNGBEBBGSEBDAELIABBqMYDRgRAQRohAQwBCyAAQdzGA0YEQEEbIQEMAQsgAEGQxwNGBEBBHCEBDAELIABBxMcDRgRAQR0hAQwBCyAAQfjHA0YEQEEeIQEMAQsgAEGsyANGBEBBHyEBDAELIABB4MgDRgRAQSAhAQwBCyAAQZTJA0YEQEEhIQEMAQsgAEHIyQNGBEBBIiEBDAELIABB/MkDRgRAQSMhAQwBCyAAQbDKA0YEQEEkIQEMAQsgAEHkygNGBEBBJSEBDAELIABBmMsDRgRAQSYhAQwBCyAAQczLA0YEQEEnIQEMAQsgAEGAzANGBEBBKCEBDAELIABBtMwDRgRAQSkhAQwBCyAAQejMA0YEQEEqIQEMAQsgAEGczQNGBEBBKyEBDAELIABB0M0DRgRAQSwhAQwBCyAAQYTOA0YEQEEtIQEMAQsgAEG4zgNGBEBBLiEBDAELIABB7M4DRgRAQS8hAQwBCyAAQaDPA0YEQEEwIQEMAQsgAEHUzwNGBEBBMSEBDAELIABBiNADRgRAQTIhAQwBCyAAQbzQA0YEQEEzIQEMAQsgAEHw0ANGBEBBNCEBDAELIABBpNEDRgRAQTUhAQwBCyAAQdjRA0YEQEE2IQEMAQsgAEGM0gNGBEBBNyEBDAELIABBwNIDRgRAQTghAQwBCyAAQfTSA0YEQEE5IQEMAQsgAEGo0wNGBEBBOiEBDAELIABB3NMDRgRAQTshAQwBCyAAQZDUA0YEQEE8IQEMAQsgAEHE1ANGBEBBPSEBDAELIABB+NQDRgRAQT4hAQwBCyAAQazVA0cNAUE/IQELIAFBNGxB3LsDakEAOgAAIAAtAAhFDQAgACgCBBAvC0EAQQH+JQKQ1jQaC9sBAgF/An5BASEEAkAgAEIAUiABQv///////////wCDIgVCgICAgICAwP//AFYgBUKAgICAgIDA//8AURsNACACQgBSIANC////////////AIMiBkKAgICAgIDA//8AViAGQoCAgICAgMD//wBRGw0AIAAgAoQgBSAGhIRQBEBBAA8LIAEgA4NCAFkEQEF/IQQgACACVCABIANTIAEgA1EbDQEgACAChSABIAOFhEIAUg8LQX8hBCAAIAJWIAEgA1UgASADURsNACAAIAKFIAEgA4WEQgBSIQQLIAQLUAEBfgJAIANBwABxBEAgAiADQUBqrYghAUIAIQIMAQsgA0UNACACQcAAIANrrYYgASADrSIEiIQhASACIASIIQILIAAgATcDACAAIAI3AwgLqQEBA38jAEGgAWsiBCQAIAQgACAEQZ4BaiABGyIFNgKUAUF/IQAgBCABQQFrIgZBACABIAZPGzYCmAEgBEEAQZAB/AsAIARBfzYCTCAEQc8BNgIkIARBfzYCUCAEIARBnwFqNgIsIAQgBEGUAWo2AlQCQCABQQBIBEAjA0EcakE9NgIADAELIAVBADoAACAEIAIgA0HNAUHOARDDAiEACyAEQaABaiQAIAALqAEAAkAgAUGACE4EQCAARAAAAAAAAOB/oiEAIAFB/w9JBEAgAUH/B2shAQwCCyAARAAAAAAAAOB/oiEAQf0XIAEgAUH9F04bQf4PayEBDAELIAFBgXhKDQAgAEQAAAAAAABgA6IhACABQbhwSwRAIAFByQdqIQEMAQsgAEQAAAAAAABgA6IhAEHwaCABIAFB8GhMG0GSD2ohAQsgACABQf8Haq1CNIa/ogswAQF/IAEjAyICKAJIIABBAnRqIgAoAgBHBEAgACABNgIAIAIgAi0AKkEBcjoAKgsLJgEBfyMAQRBrIgIkACACIAE2AgxBsLoDIAAgARCGBCACQRBqJAALyQUEBH8CfAF9AX4gAbwiBEEBdEGAgIAIakGBgIAISSECAkACQAJAAkAgALwiA0GAgID8B2tBgICAiHhPBEAgAg0BDAMLIAJFDQELQwAAgD8hCCADQYCAgPwDRg0CIARBAXQiAkUNAiACQYGAgHhJIANBAXQiAkGAgIB4TXFFBEAgACABkg8LIAJBgICA+AdGDQJDAAAAACABIAGUIAJB////9wdLIARBAE5zGw8LIANBAXRBgICACGpBgYCACEkEQCAAIACUIQggA0EASARAIAiMIAggBBCjBEEBRhshCAsgBEEATg0CIwBBEGsiAkMAAIA/IAiVOAIMIAIqAgwPCyADQQBIBEAgBBCjBCICRQRAIAAgAJMiACAAlQ8LIANB/////wdxIQMgAkEBRkEQdCEFCyADQf///wNLDQAgAEMAAABLlLxB/////wdxQYCAgNwAayEDCwJAQZDDAisDACADIANBgIDM+QNrIgRBgICAfHFrvrsgBEEPdkHwAXEiAkGQwQJqKwMAokQAAAAAAADwv6AiBqJBmMMCKwMAoCAGIAaiIgcgB6KiQaDDAisDACAGokGowwIrAwCgIAeiQbDDAisDACAGoiACQZjBAmorAwAgBEEXdbegoKCgIAG7oiIHvUKAgICAgIDg//8Ag0KBgICAgIDAr8AAVA0AIAdEcdXR////X0BkBEAjAEEQayICQwAAAPBDAAAAcCAFGzgCDCACKgIMQwAAAHCUDwsgB0QAAAAAAMBiwGVFDQAjAEEQayICQwAAAJBDAAAAECAFGzgCDCACKgIMQwAAABCUDwtB2NoBKwMAIAdB0NoBKwMAIgYgB6AiByAGoaEiBqJB4NoBKwMAoCAGIAaiokHo2gErAwAgBqJEAAAAAAAA8D+goCAHvSIJIAWtfEIvhiAJp0EfcUEDdEHQ2AFqKQMAfL+itiEICyAIC2UBAX8CQCAARQ0AIAFBAEgNACAAQQNxDQAgAUUEQA8LIABBACAAQQD+SAKQ8TQiAiAAIAJGGyECAkAgAUH/////B0YNACAAIAJHDQAgAUECSQ0BIAFBAWshAQsgACAB/gACABoLC4cCAQJ/IwBBEGsiBiQAIAAgAjYCBCAAQeSwATYCACAAQQhqIgIgASgCACIHNgIAIAdBBGpBAf4eAgAaIAAgASkCBDcCDCAAQRRqQQBBxAD8CwAgACAFOgBaIAAgBDoAWSAAIAM6AFggBiACKAIAIgE2AgAgAUEEakEB/h4CABogBkEEaiIDIAYiAigCAEGYAWoQ5wFBASEBIAYoAgggBi0ADyIEIATAIgRBAEgiBRtBAUYEQCAGKAIEIAMgBRstAABBwwBHIQELIARBAEgEQCAGKAIEEC8LIAIoAgAiAkEEakF//h4CAEUEQCACIAIoAgAoAggRAQALIAAgAToAWyAGQRBqJAAgAAsfAEEIEF4gABCJAyIAQdC3AzYCACAAQfC3A0EHEAIACxAAIAAoAgAEQBCZAgALIAALGQAgASACEJ0DIQEgACACNgIEIAAgATYCAAuGAgEEfyMAQRBrIgUkACABEJMDIQIjAEEQayIDJAACQCACQe////8DTQRAAkAgAkECSQRAIAAgAC0AC0GAAXEgAnI6AAsgACAALQALQf8AcToACyAAIQQMAQsgA0EIaiAAIAJBAk8EfyACQQRqQXxxIgQgBEEBayIEIARBAkYbBUEBC0EBahC5ASADKAIMGiAAIAMoAggiBDYCACAAIAAoAghBgICAgHhxIAMoAgxB/////wdxcjYCCCAAIAAoAghBgICAgHhyNgIIIAAgAjYCBAsgBCABIAIQngEgA0EANgIEIAQgAkECdGogAygCBDYCACADQRBqJAAMAQsQTQALIAVBEGokAAvkAQEGfyMAQRBrIgUkACAAKAIEIQMCfyACKAIAIAAoAgBrIgRB/////wdJBEAgBEEBdAwBC0F/CyIEQQQgBBshBCABKAIAIQcgACgCACEIIANB9wFGBH9BAAUgACgCAAsgBBDEASIGBEAgA0H3AUcEQCAAKAIAGiAAQQA2AgALIAVB9gE2AgQgACAFQQhqIAYgBUEEahBRIgMQvgMgAygCACEGIANBADYCACAGBEAgBiADKAIEEQEACyABIAAoAgAgByAIa2o2AgAgAiAAKAIAIARBfHFqNgIAIAVBEGokAA8LEEYACzsBAn8jAEEgayIFJAAgBSAENwMQIAUgAzcDCCAFIAI3AwAgACABQQMgBUEAQQAQSSEGIAVBIGokACAGC5ADAQJ/IwBBEGsiCiQAIAogADYCDAJAAkACQCADKAIAIAJHDQBBKyELIAAgCSgCYEcEQEEtIQsgCSgCZCAARw0BCyADIAJBAWo2AgAgAiALOgAADAELAkACfyAGLQALQQd2BEAgBigCBAwBCyAGLQALQf8AcQtFDQAgACAFRw0AQQAhACAIKAIAIgEgB2tBnwFKDQIgBCgCACEAIAggAUEEajYCACABIAA2AgAMAQtBfyEAIAkgCUHoAGogCkEMahCxAiAJayIGQdwASg0BIAZBAnUhBQJAAkACQCABQQhrDgMAAgABCyABIAVKDQEMAwsgAUEQRw0AIAZB2ABIDQAgAygCACIBIAJGDQIgASACa0ECSg0CIAFBAWstAABBMEcNAkEAIQAgBEEANgIAIAMgAUEBajYCACABIAVB0OoCai0AADoAAAwCCyADIAMoAgAiAEEBajYCACAAIAVB0OoCai0AADoAACAEIAQoAgBBAWo2AgBBACEADAELQQAhACAEQQA2AgALIApBEGokACAAC5UMAgZ/An0jAEFAaiIDJABBAEEB/h4CkNY0QQBKBEADQEEAQQH+JQKQ1jQaEAMQ1gFBAEEB/h4CkNY0QQBKDQALC0GE1gQtAABFBEAgA0EwahDXAQNAIAJBAnRBkNYEaiACQf//AXFBgICA+ANyvkMAAAC/kiACQRF0IgFBBHZBgICAgAdyvkMAAIAHlCABQYCAgMAASRu8IAJBEHRBgICAgHhxciIENgIAIAJBAXQiAUGQ1hRqQYD8ASAEviIHQwAAAD+UIAdDKkJMP5QgB0MTJzc9lCAHlEMAAIA/kpQQjQRDAACAP5KUIgiLQwAAgHeUQwAAgAiUQYCAgIgHIAi8IgRBAXQiBUGAgIB4cSIGIAZBgICAiAdNG0EBdkGAgIA8ar6SvCIGQQ12QYD4AXEgBkH/H3FqIAVBgICAeEsbIARBEHZBgIACcXI7AQAgAUGQ1hxqQYD8AUMAAIA/IAdDI9vZv5QQRUMAAIA/kpUgB5QiCItDAACAd5RDAACACJRBgICAiAcgCLwiBEEBdCIFQYCAgHhxIgYgBkGAgICIB00bQQF2QYCAgDxqvpK8IgZBDXZBgPgBcSAGQf8fcWogBUGAgIB4SxsgBEEQdkGAgAJxcjsBACABQZDWJGpBgPwBIAcgB4wQRUMAAIA/kpUiCItDAACAd5RDAACACJRBgICAiAcgCLwiBEEBdCIFQYCAgHhxIgYgBkGAgICIB00bQQF2QYCAgDxqvpK8IgZBDXZBgPgBcSAGQf8fcWogBUGAgIB4SxsgBEEQdkGAgAJxcjsBACABQZDWLGpBgPwBIAcQRSIHQwAAgHeUQwAAgAiUQYCAgIgHIAe8IgFBAXQiBEGAgIB4cSIFIAVBgICAiAdNG0EBdkGAgIA8ar6SvCIFQQ12QYD4AXEgBUH/H3FqIARBgICAeEsbIAFBEHZBgIACcXI7AQAgAkEBaiICQYCABEcNAAsgA0EwaiIBENcBIAEQ1wFB3LsDQQBBqJoB/AsAIAEQ1wFB5tY0QQE6AABB2NY0QQE6AABBz9Y0QQE6AABBzdY0QQE6AABBxdY0QYECOwAAQcPWNEEBOgAAQbvWNEEBOgAAQbnWNEEBOgAAQbfWNEGBAjsAAEGk1jRBAToAAEHc1jRBAToAAEG21zRBAToAAEGE1gRBAToAAAtBACECAkACQAJAAkADQCACQTRsQdy7A2oiAS0AAEUEQCACIQQMAgsgAkEBciIEQTRsQdy7A2oiAS0AAEUNASACQQJyIgRBNGxB3LsDaiIBLQAARQ0BIAJBA3IiBEE0bEHcuwNqIgEtAABFDQEgAkEEaiICQcAARw0AC0EAIQIMAQsgAUEBOgAAIARBNGxB4LsDaiECIAAoAgAiAUUEQCAAQQQ2AgBBBCEBCyABIAFBA2pBfHEiBSAAKAIEIgQbIQYCQCAEIgENACAFRQRAQQAhAUH8ugMoAgBBAE4EQEGwugMQggEhAQsCQEGe4ABBsLoDEKsEQQBIDQACQEGAuwMoAgBBCkYNAEHEugMoAgAiBUHAugMoAgBGDQBBxLoDIAVBAWo2AgAgBUEKOgAADAELENECCyABBEBBsLoDEIEBC0EAIQEMAQsgA0EANgIwIANBMGpBBCAFEIMEIgEEQCADAn8gAUEwRwRAQZYUIAFBHEcNARpBpB8MAQtBzQgLNgIkIANBgCY2AiAgAyAFuEQAAAAAAACwPqI5AyhB6PgAIANBIGoQogRBACEBDAELIAMoAjAhAQsgAiAALQAIIgA6AAogAiAAOgAJIAIgBEU6AAggAiABNgIEIAIgBjYCACAC/QwAAAAAAAAAAAAAAAAAAAAA/QsACyAC/QwAAAAAAAAAAAAAAAAAAAAA/QsAGyACQgA3ACggAUUNASABQQNxDQILQQBBAf4lApDWNBogA0FAayQAIAIPC0G8wwIoAgAQMBogA0HmLzYCCCADQf8RNgIEIANB5CY2AgBBuMMCKAIAQcvkACADEDEQAAALQbzDAigCABAwGiADQdXBADYCGCADQYESNgIUIANB5CY2AhBBuMMCKAIAQcvkACADQRBqEDEQAAALCgAgAEHcijUQeQuMAwEDfyMAQRBrIgokACAKIAA6AA8CQAJAAkAgAygCACACRw0AQSshCyAAQf8BcSIMIAktABhHBEBBLSELIAktABkgDEcNAQsgAyACQQFqNgIAIAIgCzoAAAwBCwJAAn8gBi0AC0EHdgRAIAYoAgQMAQsgBi0AC0H/AHELRQ0AIAAgBUcNAEEAIQAgCCgCACIBIAdrQZ8BSg0CIAQoAgAhACAIIAFBBGo2AgAgASAANgIADAELQX8hACAJIAlBGmogCkEPahC0AiAJayIFQRdKDQECQAJAAkAgAUEIaw4DAAIAAQsgASAFSg0BDAMLIAFBEEcNACAFQRZIDQAgAygCACIBIAJGDQIgASACa0ECSg0CIAFBAWstAABBMEcNAkEAIQAgBEEANgIAIAMgAUEBajYCACABIAVB0OoCai0AADoAAAwCCyADIAMoAgAiAEEBajYCACAAIAVB0OoCai0AADoAACAEIAQoAgBBAWo2AgBBACEADAELQQAhACAEQQA2AgALIApBEGokACAACwoAIABB1Io1EHkLYwIBfwF+IwBBEGsiAiQAIAACfiABRQRAQgAMAQsgAiABrUIAIAFnIgFB0QBqEGYgAikDCEKAgICAgIDAAIVBnoABIAFrrUIwhnwhAyACKQMACzcDACAAIAM3AwggAkEQaiQACxkAIAEgAhDzAyEBIAAgAjYCBCAAIAE2AgALuQgBC38gAEUEQCABEDsPCyABQUBPBEAjA0EcakEwNgIAQQAPCwJAQbyHNS0AAEECcQRAQcCHNRBWDQELAn9BECABQQtqQXhxIAFBC0kbIQUgAEEIayIEKAIEIghBeHEhAgJAIAhBA3FFBEBBACAFQYACSQ0CGiAFQQRqIAJNBEAgBCEDIAIgBWtB8IM1KAIAQQF0TQ0CC0EADAILIAIgBGohBgJAIAIgBU8EQCACIAVrIgNBEEkNASAEIAhBAXEgBXJBAnI2AgQgBCAFaiICIANBA3I2AgQgBiAGKAIEQQFyNgIEIAIgAxD0AQwBC0GYhDUoAgAgBkYEQEGMhDUoAgAgAmoiAiAFTQ0CIAQgCEEBcSAFckECcjYCBCAEIAVqIgMgAiAFayICQQFyNgIEQYyENSACNgIAQZiENSADNgIADAELQZSENSgCACAGRgRAQYiENSgCACACaiICIAVJDQICQCACIAVrIgNBEE8EQCAEIAhBAXEgBXJBAnI2AgQgBCAFaiIHIANBAXI2AgQgAiAEaiICIAM2AgAgAiACKAIEQX5xNgIEDAELIAQgCEEBcSACckECcjYCBCACIARqIgMgAygCBEEBcjYCBEEAIQMLQZSENSAHNgIAQYiENSADNgIADAELIAYoAgQiB0ECcQ0BIAdBeHEgAmoiCSAFSQ0BIAkgBWshCwJAIAdB/wFNBEAgBigCDCIDIAYoAggiAkYEQEGAhDVBgIQ1KAIAQX4gB0EDdndxNgIADAILIAIgAzYCDCADIAI2AggMAQsgBigCGCEKAkAgBiAGKAIMIgJHBEBBkIQ1KAIAGiAGKAIIIgMgAjYCDCACIAM2AggMAQsCQCAGQRRqIgMoAgAiB0UEQCAGKAIQIgdFDQEgBkEQaiEDCwNAIAMhDCAHIgJBFGoiAygCACIHDQAgAkEQaiEDIAIoAhAiBw0ACyAMQQA2AgAMAQtBACECCyAKRQ0AAkAgBigCHCIDQQJ0QbCGNWoiBygCACAGRgRAIAcgAjYCACACDQFBhIQ1QYSENSgCAEF+IAN3cTYCAAwCCyAKQRBBFCAKKAIQIAZGG2ogAjYCACACRQ0BCyACIAo2AhggBigCECIDBEAgAiADNgIQIAMgAjYCGAsgBigCFCIDRQ0AIAIgAzYCFCADIAI2AhgLIAtBD00EQCAEIAhBAXEgCXJBAnI2AgQgBCAJaiIDIAMoAgRBAXI2AgQMAQsgBCAIQQFxIAVyQQJyNgIEIAQgBWoiAyALQQNyNgIEIAQgCWoiAiACKAIEQQFyNgIEIAMgCxD0AQsgBCEDCyADCyEDQbyHNS0AAEECcQRAQcCHNRBSGgsgAwRAIANBCGoPCyABEDsiA0UEQEEADwsgAyAAQXxBeCAAQQRrKAIAIgRBA3EbIARBeHFqIgQgASABIARLGxB7GiAAEC8LIAMLXwECfyAAQQdqQXhxIQICQANAIAJBAEHEuwP+EAIAIgAgAmoiASAATRsNASABPwBBEHRLBEAgARAdRQ0CC0EAIAAgAf5IAsS7AyAARw0ACyAADwsjA0EcakEwNgIAQX8LgwECBX8BfgJAIABCgICAgBBUBEAgACEHDAELA0AgAUEBayIBIAAgAEIKgCIHQgp+fadBMHI6AAAgAEL/////nwFWIQUgByEAIAUNAAsLIAenIgIEQANAIAFBAWsiASACIAJBCm4iA0EKbGtBMHI6AAAgAkEJSyEGIAMhAiAGDQALCyABCxoAIAAgARCOBCIAQQAgAC0AACABQf8BcUYbC88FAQh/IwBBEGsiBSQAIAACfyAFQQhqIQMgASEGAkACQEG81zQiBEG81zRHBEAgASgCACIHQczXNCgCACIBTg0BC0G81zQoAgAhBEG81zQhAwJAQbjXNCgCAEG81zRHBEACQCAERQRAQbzXNCEBA0AgASgCCCIDKAIAIAFGIQkgAyEBIAkNAAsMAQsgBCEBA0AgASIDKAIEIgENAAsLIAYoAgAiBiADKAIQTA0BCyAERQ0CIAUgAzYCDCADQQRqDAMLQbzXNCgCACIBRQ0BQbzXNCEEA0ACQCABIgMoAhAiASAGSgRAIAMiBCgCACIBDQIMAQsgASAGTg0AIANBBGohBCADKAIEIgENAQsLIAUgAzYCDCAEDAILIAEgB0gEQAJAQcDXNCgCACIGRQRAQbzXNCEBA0AgASgCCCIDKAIAIAFHIQogAyEBIAoNAAsMAQsgBiEBA0AgASIDKAIAIgENAAsLAkAgA0G81zRHBEAgByADKAIQTg0BCyAGRQRAIAVBvNc0NgIMQcDXNAwECyAFIAM2AgwgAwwDC0G81zQoAgAiAUUNAQNAAkAgASIDKAIQIgEgB0oEQCADIgQoAgAiAQ0CDAELIAEgB04NACADQQRqIQQgAygCBCIBDQELCyAFIAM2AgwgBAwCCyAFQbzXNDYCDCADQbzXNDYCACADDAELIAVBvNc0NgIMQbzXNAsiBCgCACIBBH9BAAVBIBAyIgEgAigCADYCECABQRRqIQMCQCACLAAPQQBOBEAgAyACKQIENwIAIAMgAigCDDYCCAwBCyADIAIoAgQgAigCCBBrCyABIAUoAgw2AgggAUIANwIAIAQgATYCACABIQJBuNc0KAIAKAIAIgMEQEG41zQgAzYCACAEKAIAIQILQbzXNCgCACACEKQBQcDXNEHA1zQoAgBBAWo2AgBBAQs6AAQgACABNgIAIAVBEGokAAuIAQEDf0GcEBA7IQEgABDoBCEDIAEgACgCHCICIAIoAgQRAAAiAjYCDCABIAM2AgggAUEANgIEIAEgADYCACABQRxqQQBBgBD8CwAgAUEBNgIQIAEgAyACIAMgAnBrIAJwIgJqNgIUIAEgACgCJCACazYCGEEIEDsiABCCBDYCBCAAIAE2AgAgAAuTwwcF1gF/On4gewZ9BHwjAEFAaiIuJAACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQCAABEACQCABKAJAIgJFDQACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAIAJBAWsOSEMAAQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobRERERBwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ2NzU4OTo7PD0+P0BBQkQLIAEoAowBIQUgASgCkAEhAyMAQYADayIEJAACQAJAIAUoAgAiAkEOSw0AAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkBBASACdEHM+wFxRQRAAkACQAJAIAIEQCACQQFHDRggAygCAA4CAgEDCyAFKQMQItkBINkBIAMpAxAi2gF/It0BINoBflINBSAFKQMYItsBIAMpAxgi3gGBQgBSDQUgBSkDICLYASADKQMgIt8BgUIAUg0FIAUpAygi4AEgAykDKCLhAYFCAFINBSDZASABKQMQUg0FINsBIAEpAxhSDQUg2AEgASkDIFINBSDgASABKQMoUg0FAkAgACgCAA4DBQAFAAsgASgCMEEERw0GIAUoAjBBBEcNByABKAI8IQkgASgCOCEKIAEoAjQhCCADKAI8IQsgAygCOCEMIAMoAjQhDSAFKAI8IQ8gBSgCOCEOIAUoAjQhECDgASDYASDbAX4i3AF+pyICIAAoAggiB2pBAWsgB20iByAAKAIEbCIAIAdqIgcgAiACIAdKGyEHIAMoAjAiAkEERwRAIAAgB04N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y+QAIANBgAJqEDEMTgtBvMMCKAIAEDAaIANBycAANgKYAiADQevMADYClAIgA0HkJjYCkAJBuMMCKAIAQcvkACADQZACahAxDE0LQbzDAigCABAwGiADQb3AADYCGCADQbrOADYCFCADQeQmNgIQQbjDAigCAEHL5AAgA0EQahAxDEwLQbzDAigCABAwGiADQcnAADYCKCADQbnOADYCJCADQeQmNgIgQbjDAigCAEHL5AAgA0EgahAxDEsLQbzDAigCABAwGiADQd3QADYCOCADQbTOADYCNCADQeQmNgIwQbjDAigCAEHL5AAgA0EwahAxDEoLQbzDAigCABAwGiADQdfUADYCSCADQbHOADYCRCADQeQmNgJAQbjDAigCAEHL5AAgA0FAaxAxDEkLQbzDAigCABAwGiADQcg6NgJYIANBrs4ANgJUIANB5CY2AlBBuMMCKAIAQcvkACADQdAAahAxDEgLQbzDAigCABAwGiADQfE8NgJoIANBrc4ANgJkIANB5CY2AmBBuMMCKAIAQcvkACADQeAAahAxDEcLQbzDAigCABAwGiADQdQ6NgJ4IANBrM4ANgJ0IANB5CY2AnBBuMMCKAIAQcvkACADQfAAahAxDEYLQbzDAigCABAwGiADQf08NgKIASADQavOADYChAEgA0HkJjYCgAFBuMMCKAIAQcvkACADQYABahAxDEULINgBINsBfiDiAX4g2gF+pyIAQQBMDQELIAQoAtABQQAgAEECdPwLAAsgA0GgCGokAAwBC0G8wwIoAgAQMBogA0GbITYCCCADQafPADYCBCADQeQmNgIAQbjDAigCAEHL5AAgAxAxDEELDCwLIAEoAowBIQcgASgCkAEhBCABIQIjAEHQAGsiBSQAAkACQCAHKAIARQRAAkAgBygCMEEERw0AIAcoAjQiDK0i2QEgBykDECLYAUIChlINACAHNQI4ItsBINkBIAcpAxgi2gF+Ug0AIAc1Ajwg2wEgBykDICLZAX5SDQACQCABKAIwIgEgAigCAEEkbCIDQZibAWooAgBHDQAgAigCNCIIrSLbASACKQMQItwBIAGtfiADQZSbAWo0AgB/Ug0AIAI1Ajgi3QEg2wEgAikDGCLeAX5SDQAgAjUCPCDdASACKQMgItsBflINAAJAINgBINwBUg0AINoBIN4BUg0AINkBINsBUg0AIAcpAygi2wEgAikDKFINAAJAIAQpAxBCAVINACAEKQMYQgFSDQAgBCkDIEIBUg0AIAQpAyhCAVINAAJAIAAoAgAOAwcABwALINkBINoBfiDbAX6nIgEgACgCCCIDakEBayADbSIGIAAoAgRsIgMgBmoiACABIAAgAUgbIgsgA0wNBiDYAaciBkECdCENIAQoAtABKgIAIrIC/RMhkgIgBkFwcSIBQQBMDQUgASAGQQ9xIg4gBkEDcSIQayIRaiEEIAFBAWsiEkEEdkEBaiIAQf7///8BcSETIABBAXEhFgNAIAMgCGwhACACKALQASIJIAcoAtABIgpHBH8gACAJaiAKIAMgDGxqIA38CgAAIAIoAtABBSAJCyAAaiEKQQAhCUEAIQ8gEkEPRwRAA0AgCiAJQQJ0IhVqIgAgkgIgAP0AAAD95gH9CwAAIAAgkgIgAP0AABD95gH9CwAQIAAgkgIgAP0AACD95gH9CwAgIAAgkgIgAP0AADD95gH9CwAwIAogFUHAAHJqIgAgkgIgAP0AAAD95gH9CwAAIAAgkgIgAP0AABD95gH9CwAQIAAgkgIgAP0AACD95gH9CwAgIAAgkgIgAP0AADD95gH9CwAwIAlBIGohCSAPQQJqIg8gE0cNAAsLIBYEQCAKIAlBAnRqIgAgkgIgAP0AAAD95gH9CwAAIAAgkgIgAP0AABD95gH9CwAQIAAgkgIgAP0AACD95gH9CwAgIAAgkgIgAP0AADD95gH9CwAwCwJAIAEgBk4NAEEAIQkgASEAIA5BBE8EQANAIAogASAJakECdGoiACCSAiAA/QACAP3mAf0LAgAgCUEEaiIJIBFHDQALIAQhACAQRQ0BCwNAIAogAEECdGoiCSCyAiAJKgIAlDgCACAAQQFqIgAgBkcNAAsLIANBAWoiAyALRw0ACwwGC0G8wwIoAgAQMBogBUHU2AA2AgggBUG2zwA2AgQMOgtBvMMCKAIAEDAaIAVBuc8ANgIYIAVBtc8ANgIUDD4LQbzDAigCABAwGiAFQfTLADYCKCAFQbTPADYCJAw+C0G8wwIoAgAQMBogBUHf2QA2AjggBUGzzwA2AjQgBUHkJjYCMEG4wwIoAgBBy+QAIAVBMGoQMQxCC0G8wwIoAgAQMBogBUGbITYCSCAFQeXPADYCRCAFQeQmNgJAQbjDAigCAEHL5AAgBUFAaxAxDEELIAcoAtABIQQgAigC0AEhCSABIAZIBEAgBkEPcSEAIAQgCUcEQCABIAAgBkEDcSIOayIQaiEEIABBBEkhEQNAIAMgCGwhACAHKALQASIKIAlHBEAgACAJaiAKIAMgDGxqIA38CgAAIAIoAtABIQkLIAAgCWohD0EAIQogASEAAkAgEUUEQANAIA8gASAKakECdGoiACCSAiAA/QACAP3mAf0LAgAgCkEEaiIKIBBHDQALIAQhACAORQ0BCwNAIA8gAEECdGoiCiCyAiAKKgIAlDgCACAAQQFqIgAgBkcNAAsLIANBAWoiAyALRw0ACwwCCyABIAAgBkEDcSIHayIMaiECIABBBEkhDQNAIAkgAyAIbGohBEEAIQogASEAAkAgDUUEQANAIAQgASAKakECdGoiACCSAiAA/QACAP3mAf0LAgAgCkEEaiIKIAxHDQALIAIhACAHRQ0BCwNAIAQgAEECdGoiCiCyAiAKKgIAlDgCACAAQQFqIgAgBkcNAAsLIANBAWoiAyALRw0ACwwBCyAEIAlGDQAgA0EBaiG2ASALIANrQQFxBEAgAigC0AEiASAHKALQASIERwRAIAEgAyAIbGogBCADIAxsaiAN/AoAAAsgA0EBaiEDCyC2ASALRg0AA0AgAigC0AEiACAHKALQASIBRwRAIAAgAyAIbGogASADIAxsaiAN/AoAAAsgAigC0AEiACAHKALQASIBRwRAIAAgA0EBaiIEIAhsaiABIAQgDGxqIA38CgAACyADQQJqIgMgC0cNAAsLIAVB0ABqJAAMKwsgASgCjAEhAiABKAKQASEDIwBB0ABrIgQkAAJAAkACQAJAAkAgAigCAEUEQCACKQMQItkBIAEpAxBSDQEgAikDGCLYASABKQMYUg0BIAIpAyAi2gEgASkDIFINASACKQMoItsBIAEpAyhSDQEgASgCMCIFIAEoAgAiC0EkbCIHQZibAWooAgBHDQIgASgCNCIMrSLcASDZASAFrX4i3gEgB0GUmwFqKAIAIg2sf1INAiABKAI4Ig+tIt0BINgBINwBflINAiABKAI8Ig6tIt8BINoBIN0BflINAiACKAIwQQRHDQIgAjUCNCLgASDZAUIChlINAiACNQI4IuEBINgBIOABflINAiACNQI8INoBIOEBflINAiABKAJQIQYgASgCTCEJIAEoAkghCiABKAJEIQgCQCABKAJURQRAIAAoAgAiBw0BIAEoAtABIAIoAtABIAtBEGtBcU0EfyAMINgBp0EBa2wgBSDZAadsaiAPINoBp0EBa2xqIA4g2wGnQQFrbGoFINoBQgF9IN0BfiDYAUIBfSDcAX58INsBQgF9IN8Bfnwg3gEgDa1/fKcL/AoAAAsgACgCACEHCwJAAkAgBw4DAQABAAsgCCADKQMYItgBQgF9ItoBQgAg2AEg2gFaG6dsIAZqIAogAykDICLaAUIBfSLZAUIAINkBINoBWBunbGogCSADKQMoItkBQgF9ItsBQgAg2QEg2wFaG6dsaiACKAIAQSRsQZibAWooAgAgAykDECLbAUIBfSLcAUIAINsBINwBWhunbGohBSADKAI8IQ0gAygCOCEPIAMoAjQhDiABKQMoIdwBIAEpAxAh3QEgASkDICHeASABKQMYId8BIAMoAjAhtwEgACgCCCECIAAoAgQhCwJ/IAEoAgAiAEEQa0FxTQRAIABBJGxBmJsBaigCACABKAIwIN0Bp0EBa2xqIAEoAjQg3wGnQQFrbGogASgCOCDeAadBAWtsaiABKAI8INwBp0EBa2xqDAELIAE1AjQg3wFCAX1+IN0BIAE1AjB+IABBJGxBlJsBajUCAH98IAE1Ajgg3gFCAX1+fCABNQI8INwBQgF9fnynCyAFSQ0EILcBQQRHDQUgAiDZASDYASDaAX4i3AF+pyIAakEBayACbSICIAtsIgcgAiAHaiICIAAgACACShsiAE4NACDbAaciBUEATA0AIAMoAtABIQsgBUEDcSEMIAVBfHEhAiAGIAEoAtABIhBqIREgAKwh2QEgB6wh2gEgBUEQSSESA0AgCyANINoBINwBfyLbAaciAGwiE2ogDyDaASDbAcQg3AF+fSLbASDYAX8i3QGnIgNsIhZqIA4g2wEg2AEg3QF+faciB2wiFWohASAHIAhsIhggAyAKbCIaIBAgACAJbCIZampqIAZqIQNBACEHQQAhAAJAAkAgEg0AIBEgGGogGWogGmogCyAVaiATaiAWamtBEEkNAANAIAMgAEECdCITaiABIBNq/QACAP0LAgAgAEEEaiIAIAJHDQALIAIiACAFRg0BCyAAQX9zIAVqIbgBIAwEQANAIAMgAEECdCIWaiABIBZqKgIAOAIAIABBAWohACAHQQFqIgcgDEcNAAsLILgBQQNJDQADQCADIABBAnQiB2ogASAHaioCADgCACADIAdBBGoiE2ogASATaioCADgCACADIAdBCGoiE2ogASATaioCADgCACADIAdBDGoiB2ogASAHaioCADgCACAAQQRqIgAgBUcNAAsLINoBQgF8ItoBINkBUg0ACwsgBEHQAGokAAwFC0G8wwIoAgAQMBogBEGbITYCSCAEQcvQADYCRAw/C0G8wwIoAgAQMBogBEG5zwA2AjggBEHxzwA2AjQMPwtBvMMCKAIAEDAaIARBxNkANgIoIARB8s8ANgIkDD8LQbzDAigCABAwGiAEQYzMADYCCCAEQZrQADYCBAw2C0G8wwIoAgAQMBogBEGJ0QA2AhggBEGc0AA2AhQMPgsMKgsgACABKAKMASABEPUCDCkLIAAgASgCjAEgARD1AgwoCyABKAKMASEEIAEoApABIQIjAEEQayIFJAACQAJAAkACQAJAAkAgBCgCACIDQQZrQQlJDQAgAw4EAgEAAAQLAkAgACgCAA4DAwADAAsgAikDICLbAUIAVw0CIAIpAxgi3AFCAFcNAiACKQMQIt0BQgBXDQIgASgCPCEHIAEoAjghBiABKAI0IQkgAigCOCEKIAIoAjQhCCAEKAI8IQsgBCgCOCEMIAQoAjQhDSADQSRsQaCbAWooAgAhAyACKAIwIQ8gBCgCECEOA0AgByDaAaciAGwhECAAIAtsIREgACAKbCESQgAh2AEDQCAGINgBpyIAbCETIAAgDGwhFiAAIAhsIQBCACHZAQNAIAQoAtABIAIoAtABIA8g2QGnIhVsaiAAaiASaigCACANbGogFmogEWogASgC0AEgCSAVbGogE2ogEGogDiADEQUAINkBQgF8ItkBIN0BUg0ACyDYAUIBfCLYASDcAVINAAsg2gFCAXwi2gEg2wFSDQALDAILAkAgACgCAA4DAgACAAsgAikDICLbAUIAVw0BIAIpAxgi3AFCAFcNASACKQMQIt0BQgBXDQEgBCgCECIAQQBMDQEgASgCPCEGIAEoAjghCSABKAI0IQogAigCOCEIIAIoAjQhCyAEKAI8IQwgBCgCOCENIAQoAjQhDyACKAIwIQ4gASgC0AEhECAEKALQASERIAIoAtABIRIgAEF8cSETIABBA3EhBCAAQQRJIRYD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JAACQCAEKAIARQRAIAAgBCABQwAAAAAQ7QQgAkEQaiQADAELQbzDAigCABAwGiACQZshNgIIIAJBpdQANgIEDCoLDCMLIAEoAowBIQsgASgCkAEhDCABIQMjAEEQayINJAACQCALKAIARQRAAkACQCAAKAIADgMBAAEACyAAKAIIIQEgACgCBCECIAwEfiAMKQMYBUIBCyHaASABIAspAyggCykDICALKQMYfn6nIgRqQQFrIAFtIgEgAmwiBiABIAZqIgEgBCABIARIGyIJTg0AIAsoAhAiB0FwcSIBIAdBD3EiDyAHQQNxIgprIg5qIQQgACgCECAHQRBqIAJsQQJ0aiIFIAdBAnQiGmohGSAHQXxxIQIgB0EBayEQIAFBAWsiEUEEdkEBaiIAQf7///8BcSESIABBAXEhEyADKgJEIrQC/RMhkgIgCawh2QEgBqwh2AEgB0EISSEWA0AgAygCNCG8ASADKALQASEXIAsoAjQhACALKALQASEGIAwEfyAMKALQASAMKAI0INgBINoBgadsagVBAAshCSDYAachFQJAIAdBAEwiGA0AIAYgACAVbGohCEEAIQZBACEAAkAgFg0AIAUgCGtBEEkNAANAIAUgAEECdCIbaiAIIBtq/QACAP0LAgAgAEEEaiIAIAJHDQALIAcgAiIARg0BCyAQIABrIbsBIAoEQANAIAUgAEECdCIcaiAIIBxqKgIAOAIAIABBAWohACAGQQFqIgYgCkcNAAsLILsBQQNJDQADQCAFIABBAnQiBmogBiAIaioCADgCACAFIAZBBGoiG2ogCCAbaioCADgCACAFIAZBCGoiG2ogCCAbaioCADgCACAFIAZBDGoiBmogBiAIaioCADgCACAAQQRqIgAgB0cNAAsLAkAgAUEATCIbDQBBACEIQQAhBiARQQ9HBEADQCAFIAhBAnQiHGoiACCSAiAA/QAAAP3mAf0LAAAgACCSAiAA/QAAEP3mAf0LABAgACCSAiAA/QAAIP3mAf0LACAgACCSAiAA/QAAMP3mAf0LADAgBSAcQcAAcmoiACCSAiAA/QAAAP3mAf0LAAAgACCSAiAA/QAAEP3mAf0LABAgACCSAiAA/QAAIP3mAf0LACAgACCSAiAA/QAAMP3mAf0LADAgCEEgaiEIIAZBAmoiBiASRw0ACwsgE0UNACAFIAhBAnRq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swIgtAJeGyK0AiCyAiCyAiC0Al0bOAIAIABBAXIhAAsgwwEgDUYNAANAIAMgAEECdCILaiABIAtqKgIAIrQCILMCILMCILQCXhsitAIgsgIgsgIgtAJdGzgCACADIAtBBGoiC2ogASALaioCACK0AiCzAiCzAiC0Al4bIrQCILICILICILQCXRs4AgAgAEECaiIAIAdHDQALCyAGQQFqIQYgBSAKaiIFIAxIDQALCyAEQTBqJAAMAgtBvMMCKAIAEDAaIARBttEANgIIIARBr9cANgIEDCkLQbzDAigCABAwGiAEQd3QADYCGCAEQa7XADYCFAwxCwwdCyABKAKMASECIAEoApABIQMjAEGQAWsiBCQAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAgAigCAA4CAQALCyADKAIADQIgASgCAA0DIAIoAjBBAkcNBCADKAIwQQRHDQUgAikDICLfASACKQMQItwBfiLiASACKQMYIuMBfqchByADKQMYIeEBIAMpAxAh4AECQAJAIAAoAgAOAwABAwELIAMoAjQhCiACKAI4IQYgAigCNCEJIAAoAhBBACAAKAIM/AsAIAAoAhAhBQJAIN8BQgBXDQAg4wFCAFcNACDcAUIAVw0AIN8BQgFSINwBQghUciEIINwBQgODIeQBINwBQniDIdoBINwBQgGGIeUBIAmtIeYBIAatIecBIAIoAtABIgutIegBIAWtIekBA0Ag2QEg5wF+IOgBfCHqASDZAUIBhiDpAXwh6wEgCyAGINkBp2xqIQxCACHdAQNAIAwgCSDdAadsaiEAIAUg3QEg4gF+p0EBdGohAkIAId4BQgAh2wFCACHYAQJAIAgg6wEg3QEg5QF+fKcg6gEg3QEg5gF+fKdrQRBJckUEQANAIAIg2QEg2wF8p0EBdGogACDbAadBAXRq/QABAP0LAQAg2wFCCHwi2wEg2gFSDQALINoBItgBINwBUQ0BCyDcASDYAUJ/hXwhiwIg5AFCAFIEQANAIAIg2AEg3wF+INkBfKdBAXRqIAAg2AGnQQF0ai8BADsBACDYAUIBfCHYASDeAUIBfCLeASDkAVINAAsLIIsCQgNUDQADQCACINgBIN8BfiDZAXynQQF0aiAAINgBp0EBdGovAQA7AQAgAiDYAUIBfCLbASDfAX4g2QF8p0EBdGogACDbAadB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ASAANQIwfiAHQSRsQZSbAWo1AgB/fCAAKAI4IgetINgBQgF9fnwgADUCPCAAKQMoQgF9fnynCyIAQQBMDQAgASkDGCLdAUIAVw0AIAEpAxAi2wFCAFcNAAJAAkAgA0ECRwRAIAAgBGohCSABKALQASEAINsBIN0BfqchCiAIIAtssiGyAiDbAachBiAIQQBMDQEgC0EATA0CIAutItgBQv7///8PgyHiASDYAUIBgyHjASDYAUIBfSHkASAIrSHlASADQQFrIQsDQEIAId8BA0AgACDfAaciASAGbEECdGohECABIA5sIA9rrCHmAUIAIeABA0AgECDgAaciCEECdGohAQJAAkACQCADDgIBAAILIAFBADYCACAIIA1sIAxrrCHhAUIAIdoBA0ACQCDaASDmAXwi2AFCAFMNACDeASDYAUL/////D4NXDQAgBCACINgBp2xqIQhCACHYAUIAIdwBIOQBQgBSBEADQAJAINgBIOEBfCLnAUIAUw0AINkBIOcBQv////8Pg1cNACABIAgg5wGnQQJ0aioCACABKgIAkjgCAAsCQCDYAUIBhCDhAXwi5wFCAFMNACDZASDnAUL/////D4NXDQAgASAIIOcBp0ECdGoqAgAgASoCAJI4AgALINgBQgJ8IdgBINwBQgJ8ItwBIOIBUg0ACwsg4wFQDQAg2AEg4QF8ItgBQgBTDQAg2QEg2AFC/////w+DVw0AIAEgCCDYAadBAnRqKgIAIAEqAgCSOAIACyDaAUIBfCLaASDlAVINAAsMAQsgAUH///97NgIAIAggDWwgDGusIeEBQgAh2gEDQAJAINoBIOYBfCLYAUIAUw0AIN4BINgBQv////8Pg1cNACAEIAIg2AGnbGohCEIAIdgBQgAh3AEg5AFCAFIEQANAAkAg2AEg4QF8IucBQgBTDQAg2QEg5wFC/////w+DVw0AIAgg5wGnQQJ0aioCACKzAiABKgIAXkUNACABILMCOAIACwJAINgBQgGEIOEBfCLnAUIAUw0AINkBIOcBQv////8Pg1cNACAIIOcBp0ECdGoqAgAiswIgASoCAF5FDQAgASCzAjgCAAsg2AFCAnwh2AEg3AFCAnwi3AEg4gFSDQALCyDjAVANACDYASDhAXwi2AFCAFMNACDZASDYAUL/////D4NXDQAgCCDYAadBAnRqKgIAIrMC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IAVBfnEhCQNAIAcgASgC0AEgASgCNCAAbGogAigC0AEgAigCNCAAbGogAxEFACAHIAEoAtABIABBAXIiCiABKAI0bGogAigC0AEgAigCNCAKbGogAxEFACAAQQJqIQAgBkECaiIGIAlHDQALCyAFQQFxRQ0AIAcgASgC0AEgASgCNCAAbGogAigC0AEgAigCNCAAbGogAxEFAAsgBEEgaiQADAILQbzDAigCABAwGiAEQZshNgIYIARB+eoANgIUDCALQbzDAigCABAwGiAEQbnPADYCCCAEQdrqADYCBAwWCwwLCyABKAKMASECIAEoApABIQMgASgCRCEFIwBBEGsiBCQAAkAgAigCAEUEQAJAAkAgACgCAA4DAQABAAsgAikDKCACKQMgIAIpAxh+fqciB0EATA0AIAIoAhAhBkEAIQADQCAGIAEoAtABIAEoAjQgAGxqIAIoAtABIAIoAjQgAGxqIAMoAtABIAMoAjQgAGxqIAURBgAgAEEBaiIAIAdHDQALCyAEQRBqJAAMAQtBvMMCKAIAEDAaIARBmyE2AgggBEGp6wA2AgQMFQsMCgsCQCAAKAIADgMKAAoACyABIAEoAowBIAEoAkQRAgAMCQsCQCAAKAIADgMJAAkACyABIAEoAowBIAEoApABIAEoAkQRBQAMCAsCQCAAKAIADgMIAAgACyABIAEoAowBIAEoApABIAEoApQBIAEoAkQRBgAMBwsgASgCjAEhAgJAAkAgACgCAA4DAQABAAsgASACIAAoAgQgACgCCCABKAJMIAEoAkQRCwALDAYLIAEoAowBIQIgASgCkAEhBAJAAkAgACgCAA4DAQABAAsgASACIAQgACgCBCAAKAIIIAEoAkwgASgCRBEMAAsMBQsgASgCjAEhAiABKAKQASEEIAEoApQBIQMCQAJAIAAoAgAOAwEAAQALIAEgAiAEIAMgACgCBCAAKAIIIAEoAkwgASgCRBEQAAsMBAsgACEEIAEoAowBIQkgASgCkAEhCiMAQeAAayIFJAACQAJAAn0CQCAJKAIARQRAAkAgCSgCMEEERw0AIAk1AjQi2QEgCSkDECLYAUIChlINACAJNQI4ItsBINkBIAkpAxgi2gF+Ug0AIAk1Ajwg2wEgCSkDICLZAX5SDQACQCAKKAIwIgAgCigCAEEkbCICQZibAWooAgBHDQAgCjUCNCLbASAKKQMQItwBIACtfiACQZSbAWo0AgB/Ug0AIAo1Ajgi3QEg2wEgCikDGCLeAX5SDQAgCjUCPCDdASAKKQMgItsBflINAAJAIAEpAxBCAVINACABKQMYQgFSDQAgASkDIEIBUg0AIAEpAyhCAVINAAJAINgBINwBUg0AINoBIN4BUg0AINkBINsBUg0AIAkpAygi2wEgCikDKFINACAEKAIIIgAg2AGnIgZBAnQiE0EEamwiAyAEKAIMTQRAINkBINoBfiDbAX6nIQIgBCgCECEHIAQoAgQhCAJAAkACQCAEKAIADgMAAgECCyAIDQogB0EAIAP8CwAMCgsgCA0JIAEoAtABIQlDAAAAACAAQQBMDQgaIABBA3EhBEEAIQMgAEEESQRAQQAhAAwICyAAQXxxIQpBACEAQQAhBgNAILgCIAcgAEECdCIBaioCALugIAcgAUEEcmoqAgC7oCAHIAFBCHJqKgIAu6AgByABQQxyaioCALugIbgCIABBBGohACAGQQRqIgYgCkcNAAsMBwsgACACakEBayAAbSIBIAhsIg0gASANaiIBIAIgASACSBsiFk4NCCAGQXBxIgIgBkEPcSIVIAZBA3EiDGsiGGohAyAAQQJ0IhogCEECdCIAQQRqIAZsaiEZIAZBfHEhASAGQX5xIRQgBkEBcSEXIAZBAWshDiAAIAdqIRAgAkEBayIbQQR2QQFqIgBB/v///wFxIRwgAEEBcSEdIAYgCGxBAnQhHwNAIAQoAhAiHiAaaiAfaiEHIAooAjQhIyAKKALQASERAkAgBkEATCIlBEBEAAAAAAAAAAAhuAIMAQsgCSgC0AEgCSgCNCANbGohC0MAAID/IbICQQAhD0EAIQBBACESIA5BA08EQANAILICIAsgAEECdCIIaioCACKzAiCyAiCzAl4bIrICIAsgCEEEcmoqAgAiswIgsgIgswJeGyKyAiALIAhBCHJqKgIAIrMCILICILMCXhsisgIgCyAIQQxyaioCACKzAiCyAiCzAl4bIbICIABBBGohACASQQRqIhIgAUcNAAsLIAwEQANAILICIAsgAEECdGoqAgAiswIgsgIgswJeGyGyAiAAQQFqIQAgD0EBaiIPIAxHDQALC0QAAAAAAAAAACG4AkEAIQBBACEIIA4EQANAQwAAAAAhswICQCALIABBAnQi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QQFqIQAgA0EBaiIDIARHDQALCyC4ArYLIbICIAlDAACAvyACspUgsgKUOAIACyAFQeAAaiQADAALDAMLIAEoAowBIQkgASgCkAEhCiABKAKUASECIAEhAyMAQeAAayIFJAACQCAJKAIARQRAAkAgASgCMCIBIAMoAgBBJGwiBEGYmwFqKAIARw0AIAM1AjQi2QEgAykDECLYASABrX4gBEGUmwFqNAIAf1INACADNQI4ItsBINkBIAMpAxgi2gF+Ug0AIAM1Ajwg2wEgAykDICLZAX5SDQACQCAJKAIwQQRHDQAgCTUCNCLdASAJKQMQItsBQgKGUg0AIAk1Ajgi3gEg3QEgCSkDGCLcAX5SDQAgCTUCPCDeASAJKQMgIt0BflINAAJAIAooAjAiASAKKAIAQSRsIgRBmJsBaigCAEcNACAKNQI0It4BIAopAxAi3wEgAa1+IARBlJsBajQCAH9SDQAgCjUCOCLgASDeASAKKQMYIuEBflINACAKNQI8IOABIAopAyAi3gF+Ug0AAkAgAigCMCIBIAIoAgBBJGwiBEGYmwFqKAIARw0AIAI1AjQi4AEgAikDECABrX4gBEGUmwFqNAIAf1INACACNQI4IuIBIAIpAxgg4AF+Ug0AIAI1AjwgAikDICDiAX5SDQACQCDbASDfAVINACDcASDhAVINACDdASDeAVINACDZASDdAVINACDaASDcAVINACDYASDbAVINACAJKQMoItsBIAopAyhSDQAg2wEgAykDKFINAAJAAkAgACgCAA4DAQABAAsg2QEg2gF+INsBfiLZASAANAIIItoBfEIBfSDaAX8i2wEgADQCBH4i2gEg2gEg2wF8ItsBINkBINkBINsBVRsi3AFZDQAgAigC0AEhGCDYAaciBkFwcSIBIAZBD3EiDSAGQQNxIgxrIg9qIQQg2AFCfoMh3QEg2AFCAYMh3gEgBkF8cSECIAZBAnQhDiABQQFrIhBBBHZBAWoiAEH+////AXEhESAAQQFxIRIg2QG0IbUCIAZBAWtBA0khGgNAIAkoAtABINoBpyITIAkoAjRsaiEAIAMoAjQgE2whFkMAAID/IbICAkAgBkEATCIZDQBBACEIQQAhB0EAIRUgGkUEQANAILICIAAgB0ECdCILaioCACKzAiCyAiCzAl4bIrICIAAgC0EEcmoqAgAiswIg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ayIBIAgoAuACIgUgAmtBBHVNBEACQCABRQ0AIAIhAyABQQdxIgQEQEEAIQUDQCADQQA2AgggA0IANwMAIANBEGohAyAFQQFqIgUgBEcNAAsLIAFBBHQgAmohAiABQQFrQf////8AcUEHSQ0AA0AgA0IANwNwIANCADcDYCADQgA3A1AgA0IANwNAIANCADcDMCADQgA3AyAgA0IANwMQIANBADYCCCADQgA3AwAgA0EANgJ4IANBADYCaCADQQA2AlggA0EANgJIIANBADYCOCADQQA2AiggA0EANgIYIANBgAFqIgMgAkcNAAsLIAggAjYC3AIMAQsCQCACIAgoAtgCIgRrQQR1IgsgAWoiA0GAgICAAUkEQEH/////ACAFIARrIgVBA3UiCSADIAMgCUkbIAVB8P///wdPGyIJBEAgCUGAgICAAU8NAiAJQQR0EDIhBwsgByALQQR0aiIFIQMgAUEHcSILBEADQCADQQA2AgggA0IANwMAIANBEGohAyAKQQFqIgogC0cNAAsLIAFBBHQgBWohCiABQQFrQf////8AcUEHTwRAA0AgA0IANwNwIANCADcDYCADQgA3A1AgA0IANwNAIANCADcDMCADQgA3AyAgA0IANwMQIANBADYCCCADQgA3AwAgA0EANgJ4IANBADYCaCADQQA2AlggA0EANgJIIANBADYCOCADQQA2AiggA0EANgIYIANBgAFqIgMgCkcNAAsLIAIgBEcEQANAIAVBEGsiBSACQRBrIgIpAwA3AwAgBSACKAIINgIIIAIgBEcNAAsLIAggByAJQQR0ajYC4AIgCCAKNgLcAiAIKALYAiEBIAggBTYC2AIgAQRAIAEQLwsMAgsMDAsQRwALIAgoAtgCIQQMAQsgASAMTQ0AIAggBCAMQQR0ajYC3AILAkAgDEEATA0AIAgoAsACIQJBACEBIAxBAUcEQCAMQX5xIQVBACELA0AgAiABQQJ0aioCACEaIAQgAUEEdGoiAyABNgIIIAMgGrs5AwAgAiABQQFyIgNBAnRqKgIAIRogBCADQQR0aiIJIAM2AgggCSAauzkDACABQQJqIQEgC0ECaiILIAVHDQALCyAMQQFxRQ0AIAIgAUECdGoqAgAhGiAEIAFBBHRqIgIgATYCCCACIBq7OQMACyAGAn8gDUUEQEEAIQlBAAwBCyAEIA1BBHQiDmohByAIKALcAiEQIA5BBHUhDwJAIA5BEUgiFQ0AIA9BAmtBAXYiCiEBIA5BIEkNAANAAkAgCiABIglIDQAgBCABQQR0aiEDIAQgAUEBdCICQQFyIgVBBHRqIQECQCAPIAJBAmoiAkwEQCAFIQIMAQsgASsDACABKwMQZEUEQCAFIQIMAQsgAUEQaiEBCyADKwMAIh8gASsDAGMNACADKAIIIQsDQAJAIAMiBSABIgMpAwA3AwAgBSABKAIINgIIIAIgCkoNACAEIAJBAXQiAkEBciIFQQR0aiEBAkAgDyACQQJqIgJMBEAgBSECDAELIAErAwAgASsDEGRFBEAgBSECDAELIAFBEGohAQsgASsDACAfZEUNAQsLIAMgCzYCCCADIB85AwALIAlBAWshASAJQQBKDQALCwJAIAcgEEYNACAHIQEgDkEfSgRAIARBIGohCyAEQRBqIQkgD0ECa0EBdiEWIAEhBQNAAkAgBSsDACAEKwMAZEUNACAGIAX9AAMA/QsDCCAFIAQoAgg2AgggBSAEKQMANwMAIAQgBigCEDYCCCAEIAYpAwg3AwBBASECAkAgDkEgRgRAIAkhAQwBCyAJIgErAwAgCysDAGRFDQBBAiECIAshAQsgBCsDACIfIAErAwBjDQAgBCgCCCEXIAQhAwNAAkAgAyIKIAEiAykDADcDACAKIAEoAgg2AgggAiAWSg0AIAQgAkEBdCICQQFyIgpBBHRqIQECQCAPIAJBAmoiAkwEQCAKIQIMAQsgASsDACABKwMQZEUEQCAKIQIMAQsgAUEQaiEBCyABKwMAIB9kRQ0BCwsgAyAXNgIIIAMgHzkDAAsgBUEQaiIFIBBHDQALDAELA0AgASsDACAEKwMAZARAIAYgAf0AAwD9CwMIIAEgBCgCCDYCCCABIAQpAwA3AwAgBCAGKAIQNgIIIAQgBikDCDcDAAsgAUEQaiIBIBBHDQALCyAVRQRAIA1B/////wBxIQEDQCAGIAT9AAMA/QsDCCABIglBAmtBAXYhCkEAIQIgBCEBA0AgAkEBdCILQQFyIQMgASIFIAJBBHRqQRBqIQECQCAJIAtBAmoiAkwEQCADIQIMAQsgASsDACABKwMQZEUEQCADIQIMAQsgAUEQaiEBCyAFIAEpAwA3AwAgBSABKAIINgIIIAIgCkwNAAsCQCAHQRBrIgcgAUYEQCABIAYpAwg3AwAgASAGKAIQNgIIDAELIAEgBykDADcDACABIAcoAgg2AgggByAGKQMINwMAIAcgBigCEDYCCCABIARrQRBqIgJBEUgNACABKwMAIh8gBCACQQR2QQJrQQF2IgtBBHRqIgUrAwBjRQ0AIAEoAgghAwNAAkAgASAFIgIpAwA3AwAgASACKAIINgIIIAtFDQAgAiEBIAQgC0EBa0EBdiILQQR0aiIFKwMAIB9kDQELCyACIAM2AgggAiAfOQMACyAJQQFrIQEgCUECSg0ACwsgBkEANgJ8IAZCADcCdCANQdaq1SpPDQkgDUEwbCIBEDIiCSABagsiAzYCfCAGIAk2AnggBiAJNgJ0IAgoArQCIQREAAAAAAAAAAAhIAJAIBMoAvwBIgUgDE4EQEQAAAAAAAAAACEfDAELIAVBAWohAkQAAAAAAAAAACEfIAwgBSIBa0EBcQRAAkAgBCABQQJ0aioCACIaQwAAgP9bDQAgGrsiH0QAAAAAAAAAAKAhICAaQwAAAABeDQBEAAAAAAAAAAAhHwsgAiEBCyACIAxGDQADQAJ/AkAgBCABQQJ0aioCACIaQwAAgP9bDQAgICAauyIhoCEgIB8gIWNFDQAgAQwBCyAfISEgBQshAgJAIAQgAUEBaiIFQQJ0aioCACIaQwAAgP9cBEAgICAauyIfoCEgIB8gIWQNAQsgISEfIAIhBQsgDCABQQJqIgFHDQALCyAIKAK4AiEHIAZBADYCECAGQgA3AgggBCAHRwRAIAcgBGsiAUH9////B08NCSAGIAFBAXQQMiIKNgIIIAYgCiABQQJ1QQN0ajYCEAJAAkAgAUEEayIBQQRJBEAgBCECIAohAQwBCyAKIAFBAnZBAWoiDkH+////B3EiDEEDdGohASAEIAxBAnRqIQJBACELA0AgCiALQQN0aiAEIAtBAnRq/V0CAP1f/QsDACALQQJqIgsgDEcNAAsgDCAORg0BCwNAIAEgAioCALs5AwAgAUEIaiEBIAJBBGoiAiAHRw0ACwsgBiABNgIMCyAGQQhqEM4EAkAgDUEATARAIAkhCgwBCyAfICBEu73X2d982z2go7YhGiAgtiEbIAhB5AJqIQxBACELIAYoAnwhBCAGKAJ4IQogCSEBAkACQAJAA0AgBkEIaiICIAwgAhDNBCICQQJ0IgcgCCgCzAJqKgIAIRwgCCgCtAIgB2oqAgAhHQJAIAEgA0kEQCABQn83AxggASAbOAIUIAEgGjgCECABIBw4AgwgASAdOAIIIAEgBTYCBCABIAI2AgAgAUEANgIoIAFCfzcDICABQTBqIQoMAQsgASAJa0EwbSIOQQFqIgdB1qrVKk8NAkHVqtUqIAMgCWtBMG0iA0EBdCIPIAcgByAPSRsgA0Gq1aoVTxsiBwR/IAdB1qrVKk8NBCAHQTBsEDIFQQALIgQgDkEwbGoiA0J/NwMYIAMgGzgCFCADIBo4AhAgAyAcOAIMIAMgHTgCCCADIAU2AgQgAyACNgIAIANBADYCKCADQn83AyAgAyECIAEgCUcEQANAIAJBMGsiAiABQTBrIgH9AAMA/QsDACACIAH9AAMg/QsDICACIAH9AAMQ/QsDECABIAlHDQALCyAHQTBsIARqIQQgA0EwaiEKIAkEQCAJEC8LIAQhAyACIQkLIAkgC0EwbGoiASgCACICIBMoAvwBTgRAIAEgAjYCBCABIAEqAgg4AhALIAohASANIAtBAWoiC0cNAAsMAgsgBiAENgJ8IAYgCjYCeCAGIAk2AnQMCwsgBiAENgJ8IAYgCjYCeBBHAAsgBiAENgJ8IAYgCjYCeCAGIAk2AnQLIAYoAggiAQRAIAYgATYCDCABEC8LIAkgCkcEQCAAKAIYKAIAIQsCQAJAA0ACQCAGIBQ2AgggBiAIKAKsAjYCDCAILQCyAiEBIAZBADYCICAGQgA3AxggBiABOgAQIAgoAtQBIgEgCCgC0AEiA2siBEEwbSECIAEgA0cEQCACQdaq1SpPDQEgBiAEEDIiATYCHCAGIAE2AhggBiABIAJBMGxqNgIgIAgoAtABIgIgCCgC1AEiA0cEQANAIAEgAv0AAwD9CwMAIAEgAv0AAyD9CwMgIAEgAv0AAxD9CwMQIAFBMGohASACQTBqIgIgA0cNAAsLIAYgATYCHAsgBiAI/QAC3AH9CwIkIAYgCCgChAI2AkwgBiAIKQL8ATcCRCAGIAj9AALsAf0LAjQCfyASQQA2AgggEkIANwIAIAgoAowCIgIgCCgCiAIiA2siBEEMbSEBAkAgAiADRwRAIAFB1qrVqgFPDQEgEiAEEDIiBzYCBCASIAc2AgAgEiAHIAFBDGxqNgIIIAgoAogCIgUgCCgCjAIiD0cEQANAIAdBADYCCCAHQgA3AgAgBSgCBCIBIAUoAgAiAkcEQAJAAkACQCABIAJrIgFBAE4EQCAHIAEQMiICNgIEIAcgAjYCACAHIAIgAUF4cWo2AgggBSgCACIEIAUoAgQiDUYEQCACIQEMBAsgDSAEa0EIayIBQRhJDQEgAiAEa0EQSQ0BIAIgAUEDdkEBaiIQQf7///8DcSIOQQN0IgNqIQEgAyAEaiEDQQAhDANAIAIgDEEDdCITaiAEIBNq/QACAP0LAgAgDEECaiIMIA5HDQALIA4gEEYNAwwCCwwWCyAEIQMgAiEBCwNAIAEgAykCADcCACABQQhqIQEgA0EIaiIDIA1HDQALCyAHIAE2AgQLIAdBDGohByAFQQxqIgUgD0cNAAsLIBIgBzYCBAsgEgwBCwwOCyENAn8gEUEANgIIIBFCADcCACAIKAKYAiICIAgoApQCIgNrIgRBDG0hAQJAIAIgA0cEQCABQdaq1aoBTw0BIBEgBBAyIgc2AgQgESAHNgIAIBEgByABQQxsajYCCCAIKAKUAiIFIAgoApgCIhBHBEADQCAHQQA2AgggB0IANwIAIAUoAgQiASAFKAIAIgJHBEACQAJAAkAgASACayIBQQBOBEAgByABEDIiAjYCBCAHIAI2AgAgByACIAFBfHFqNgIIIAUoAgAiBCAFKAIEIg5GBEAgAiEBDAQLIA4gBGtBBGsiAUEMSQ0BIAIgBGtBEEkNASACIAFBAnZBAWoiE0H8////B3EiD0ECdCIDaiEBIAMgBGohA0EAIQwDQCACIAxBAnQiFWogBCAVav0AAgD9CwIAIAxBBGoiDCAPRw0ACyAPIBNGDQMMAgsMFgsgBCEDIAIhAQsDQCABIAMoAgA2AgAgAUEEaiEBIANBBGoiAyAORw0ACwsgByABNgIECyAHQQxqIQcgBUEMaiIFIBBHDQALCyARIAc2AgQLIBEMAQsMDgshDCAGIAgpAqACIiI3A2gCQCALIBRBDGwiDmoiAigCBCIBIAIoAggiA0kEQCABIAYpAwg3AwAgASAGLQAQOgAIIAFBADYCGCABQgA3AxAgASAGKAIYNgIQIAEgBigCHDYCFCABIAYoAiA2AhggBkEANgIgIAZCADcDGCABIAYoAkw2AkQgASAGKQJENwI8IAEgBv0AAjT9CwIsIAEgBv0AAiT9CwIcIAH9DAAAAAAAAAAAAAAAAAAAAAD9CwNIIAEgDSgCADYCSCABIAYoAlQ2AkwgBigCWCEDIAFCADcDWCABIAM2AlAgASAMKAIANgJUIAEgBigCYDYCWCABIAYoAmQ2AlwgBkIANwNgIA39DAAAAAAAAAAAAAAAAAAAAAD9CwMAIAEgBikDaDcDYCACIAFB6ABqNgIEDAELIAEgAigCACIEa0HoAG0iBUEBaiIBQePO2BNPDQNB4s7YEyADIARrQegAbSIDQQF0IgQgASABIARJGyADQbGn7AlPGyIBQePO2BNPDQ0gAUHoAGwiAxAyIgQgBUHoAGxqIgEgBikDCDcDACABIAYtABA6AAggASAGKAIYNgIQIAEgBigCHDYCFCABIAYoAiA2AhggBkEANgIgIAZCADcDGCABIAYoAkw2AkQgASAGKQJENwI8IAEgBv0AAjT9CwIsIAEgBv0AAiT9CwIcIAEgDf0AAwD9CwNIIAEgBigCYDYCWCABIAYoAmQ2AlwgBkIANwNgIA39DAAAAAAAAAAAAAAAAAAAAAD9CwMAIAEgIjcDYCADIARqIQQgAUHoAGohBwJAIAIoAgQiAyACKAIAIgVGBEAgAiABNgIAIAIgBzYCBCACIAQ2AggMAQsDQCABQegAayIBIANB6ABrIgMpAwA3AwAgASADLQAIOgAIIAEgAygCEDYCECABIAMoAhQ2AhQgASADKAIYNgIYIANBADYCGCADQgA3AxAgASADKAJENgJEIAEgAykCPDcCPCABIAP9AAIs/QsCLCABIAP9AAIc/QsCHCABIAMoAkg2AkggASADKAJMNgJMIAEgAygCUDYCUCADQQA2AlAgA0IANwNIIAEgAygCVDYCVCABIAMoAlg2AlggASADKAJcNgJcIANBADYCXCADQgA3AlQgASADKQNgNwNgIAMgBUcNAAsgAigCBCEFIAIoAgAhAyACIAE2AgAgAiAHNgIEIAIgBDYCCCADIAVGDQADQCAFQegAayIHKAJUIgQEQCAFQRBrIg8oAgAiAiAEIgFHBEADQCACQQxrIgEoAgAiCwRAIAJBCGsgCzYCACALEC8LIAEiAiAERw0ACyAHKAJUIQELIA8gBDYCACABEC8LIAVBIGsiDygCACIEBEAgBUEcayIQKAIAIgIgBCIBRwRAA0AgAkEMayIBKAIAIgsEQCACQQhrIAs2AgAgCxAvCyABIgIgBEcNAAsgDygCACEBCyAQIAQ2AgAgARAvCyAFQdgAaygCACIBBEAgBUHUAGsgATYCACABEC8LIAciBSADRw0ACwsgA0UNACADEC8LIAwoAgAiAwRAIAYoAmAiAiADIgFHBEADQCACQQxrIgEoAgAiBARAIAJBCGsgBDYCACAEEC8LIAEiAiADRw0ACyAMKAIAIQELIAYgAzYCYCABEC8LIA0oAgAiAwRAIAYoAlQiAiADIgFHBEADQCACQQxrIgEoAgAiBARAIAJBCGsgBDYCACAEEC8LIAEiAiADRw0ACyANKAIAIQELIAYgAzYCVCABEC8LIAYoAhgiAQRAIAYgATYCHCABEC8LAkAgACgCGCgCACAOaigCBCICQegAayIDKAIUIgEgAygCGEcEQCABIAn9AAMA/QsDACABIAn9AAMg/QsDICABIAn9AAMQ/QsDECADIAFBMGo2AhQMAQsgASACQdgAayIFKAIAIgdrQTBtIgJBAWoiBEHWqtUqTw0OQdWq1SogAkEBdCILIAQgBCALSRsgAkGq1aoVTxsiBAR/IARB1qrVKk8NDiAEQTBsEDIFQQALIgsgAkEwbGoiAiAJ/QADAP0LAwAgAiAJ/QADIP0LAyAgAiAJ/QADEP0LAxAgAkEwaiEMIAEgB0cEQANAIAJBMGsiAiABQTBrIgH9AAMA/QsDACACIAH9AAMg/QsDICACIAH9AAMQ/QsDECABIAdHDQALIAUoAgAhAQsgBSACNgIAIAMgDDYCFCADIAsgBEEwbGo2AhggAUUNACABEC8LIAAoAhgoAgAiCyAOaigCBEHIAGsiASABKwMAIAkqAgy7oDkDACAKIAlBMGoiCUcNAQwDCwsMCwsQNgALIAYoAnQhCgsgCkUNBCAGIAo2AnggChAvDAQLIAgoArQCIQQCQCACIApOBEBEAAAAAAAAAAAhH0EAIQVEAAAAAAAAAAAhIAwBCyAKIAJrIgFBAXEhGAJAIAJBAWogCkYEQEQAAAAAAAAAACEgQQAhBUQAAAAAAAAAACEfDAELIAFBfnEhCkQAAAAAAAAAACEgQQAhBUQAAAAAAAAAACEfQQAhAQNAAn8CQCAEIAJBAnRqKgIAIhpDAACA/1sNACAgIBq7IiGgISAgHyAhY0UNACACDAELIB8hISAFCyEDAkAgBCACQQFqIgVBAnRqKgIAIhpDAACA/1wEQCAgIBq7Ih+gISAgHyAhZA0BCyADIQUgISEfCyACQQJqIQIgAUECaiIBIApHDQALCyAYRQ0AIAQgAkECdGoqAgAiGkMAAID/Ww0AICAgGrsiIaAhICAfICFjRQ0AIAIhBSAhIR8LIAgoArgCIQogBkEANgIQIAZCADcCCAJAIAQgCkcEQCAKIARrIgFB/f///wdPDQEgBiABQQF0EDIiCTYCCCAGIAkgAUECdUEDdGo2AhACQAJAIAFBBGsiAUEESQRAIAQhAiAJIQEMAQsgCSABQQJ2QQFqIgxB/v///wdxIgdBA3RqIQEgBCAHQQJ0aiECQQAhAwNAIAkgA0EDdGogBCADQQJ0av1dAgD9X/0LAwAgA0ECaiIDIAdHDQALIAcgDEYNAQsDQCABIAIqAgC7OQMAIAFBCGohASACQQRqIgIgCkcNAAsLIAYgATYCDAsgBkEIaiIBEM4EIAEgCEHkAmogARDNBCIDQQJ0IgEgCCgCzAJqKgIAIRsgCCgCtAIgAWoqAgAhGiAGKAIIIgEEQCAGIAE2AgwgARAvCyAgtiEcIB8gIES7vdfZ33zbPaCjtiAaIAMgCygC/AFIIgEbIR0gBSADIAEbIQkgCCgC1AEiASAIKALYASIFSQRAIAFCfzcDGCABIBw4AhQgASAdOAIQIAEgGzgCDCABIBo4AgggASAJNgIEIAEgAzYCACABQgA3AyggAUJ/NwMgIAggAUEwajYC1AEMBAsgASAIKALQASIEa0EwbSIKQQFqIgJB1qrVKk8NCEHVqtUqIAUgBGtBMG0iBUEBdCIHIAIgAiAHSRsgBUGq1aoVTxsiBQR/IAVB1qrVKk8NCCAFQTBsEDIFQQALIgcgCkEwbGoiAkJ/NwMYIAIgHDgCFCACIB04AhAgAiAbOAIMIAIgGjgCCCACIAk2AgQgAiADNgIAIAJCADcDKCACQn83AyAgAkEwaiEDIAEgBEcEQANAIAJBMGsiAiABQTBrIgH9AAMA/QsDACACIAH9AAMg/QsDICACIAH9AAMQ/QsDECABIARHDQALIAgoAtABIQELIAggByAFQTBsajYC2AEgCCADNgLUASAIIAI2AtABIAFFDQMgARAvDAMLDAcLIAtFDQAgByABQQJ0aioCACIaQwAAgP9bDQAgICAauyIhoCEgIB8gIWNFDQAgASEDICEhHwsgHyAgRLu919nffNs9oKO2IR4CQCAKQQBMBEBDAAAAACEcQwAAAAAhGgwBCyAKQQFxIRkgCCgCzAIhByAIKAK0AiELAkAgCkEBRgRAQwAAAAAhHEMAAAAAIRpBACEBDAELIApBfnEhCkMAAAAAIRxDAAAAACEaQQAhAUEAIQUDQCALIAFBAnQiCWoqAgAiGyAaXgRAIAcgCWoqAgAhHCAbIRogASEECyALIAFBAXIiCUECdCINaioCACIbIBpeBEAgByANaioCACEcIBshGiAJIQQLIAFBAmohASAFQQJqIgUgCkcNAAsLIBlFDQAgGiALIAFBAnQiBWoqAgAiG11FDQAgBSAHaioCACEcIAEhBCAbIRoLICC2IRsgAyAEIAIgBEoiARshCSAeIBogARshHSAIKALUASIBIAgoAtgBIgVJBEAgAUJ/NwMYIAEgGzgCFCABIB04AhAgASAcOAIMIAEgGjgCCCABIAk2AgQgASAENgIAIAFCADcDKCABQn83AyAgCCABQTBqNgLUAQwBCyABIAgoAtABIgNrQTBtIgpBAWoiAkHWqtUqTw0FQdWq1SogBSADa0EwbSIFQQF0IgcgAiACIAdJGyAFQarVqhVPGyIFBH8gBUHWqtUqTw0FIAVBMGwQMgVBAAsiByAKQTBsaiICQn83AxggAiAbOAIUIAIgHTgCECACIBw4AgwgAiAaOAIIIAIgCTYCBCACIAQ2AgAgAkIANwMoIAJCfzcDICACQTBqIQQgASADRwRAA0AgAkEwayICIAFBMGsiAf0AAwD9CwMAIAIgAf0AAyD9CwMgIAIgAf0AAxD9CwMQIAEgA0cNAAsgCCgC0AEhAQsgCCAHIAVBMGxqNgLYASAIIAQ2AtQBIAggAjYC0AEgAUUNACABEC8LIAggCCsD4AEgCCgC1AFBJGsqAgC7oDkD4AELIAAoAgBBAf4eAgAiFCAAKAIEKAIASA0ACwsgBkGAAWokAA8LEEcACxA2AAvvOAQXfwN9AnsBfiMAQeAAayIIJAACQAJAIAAoAtgBIgogACgCwAFGBEAgAigCACEMIAIoAgQhCSACQfAAaiEQAkAgAigCdCACKAJwIgVrQQJ1IgYgCkkEQCAQIAogBmsQbiAQKAIAIQUMAQsgBiAKTQ0AIAIgBSAKQQJ0ajYCdAsgBSABKAKEqAEgAigCWCAKbEECdGogCkECdPwKAAACQCAEQwAAAABeRQ0AIApBAEwNACAQKAIAIQZBACEFIApBBE8EQCAKQXxxIQUgBP0TIR8DQCAGIAdBAnRqIgsgC/0AAgAgH/3nAf0LAgAgB0EEaiIHIAVHDQALIAUgCkYNAQsDQCAGIAVBAnRqIgcgByoCACAElTgCACAFQQFqIgUgCkcNAAsLIAJB5ABqIRUCQCACKAJoIAIoAmQiBmtBAnUiBSAKSQRAIBUgCiAFaxBuDAELIAUgCk0NACACIAYgCkECdGo2AmgLIAJB/ABqIRQCQCACKAKAASACKAJ8IgZrQQJ1IgUgCkkEQCAUIAogBWsQbgwBCyAFIApNDQAgAiAGIApBAnRqNgKAAQsgECgCACEHAkAgCSAMRyIWDQAgAy0AUUUNACAHIAAoAtwBQQJ0akGAgIB8NgIAIAhBIDsBICAIQQE6ACsgAEHEAWogCEEgahCMAiEFIBAoAgAiByAFKAIAQQJ0akGAgIB8NgIAIAgsACtBAE4NACAIKAIgEC8gECgCACEHCyAHIAAoAvgBQQJ0akGAgIB8NgIAAkAgAy0AFkUNACAKIAAoAvwBIgxMDQACQCAKIAxrIglBBEkEQCAMIQUMAQsgDCAJQXxxIgtqIQVBACEGA0AgByAGIAxqQQJ0av0MAACA/wAAgP8AAID/AACA//0LAgAgBkEEaiIGIAtHDQALIAkgC0YNAQsDQCAHIAVBAnRqQYCAgHw2AgAgBUEBaiIFIApHDQALCyAHIAAoAuABIglBAnRqQYCAgHw2AgAgByAAKAL0AUECdGpBgICAfDYCACADLQA8RQRAIAcgACgC7AFBAnRqQYCAgHw2AgALIAcgACgC5AFBAnRqQYCAgHw2AgAgByAAKALoAUECdGpBgICAfDYCACAHIAAoAvABQQJ0aiEYQQAhBQJAQczXNCgCACIMRQ0AIAxBBE8EQCAMQXxxIQVBACEGA0AgByAGQQFyIAlqQQJ0av0MAACA/wAAgP8AAID/AACA//0LAgAgBkEEaiIGIAVHDQALIAUgDEYNAQsDQCAHIAVBAWoiBSAJakECdGpBgICAfDYCACAFIAxHDQALCyAYQYCAgHw2AgAgAygCnAEiBQRAIAAgASACKAIAIgEgAigCBCABa0EwbSAHIAMoAqABIAURDAALIAMtAFJFDQJB4Nc0KAIAIgFB5Nc0KAIAIhdGDQEgAEHIAWohByAIQSBqQQxyIQkDQAJAIAEsAAtBAE4EQCAIIAEpAgA3AyAgCCABKAIINgIoDAELIAhBIGogASgCACABKAIEEGsLIwBBEGsiDSQAQZniABBoIQYCfyABLQALQQd2BEAgASgCBAwBCyABLQALQf8AcQshCwJ/An8jAEEQayIMJAAgBiALaiIFQe////8HTQRAAkAgBUELSQRAIAlCADcCACAJQQA2AgggCSAJLQALQYABcSAFcjoACyAJIAktAAtB/wBxOgALDAELIAkgBUELTwR/IAVBEGpBcHEiDiAOQQFrIg4gDkELRhsFQQoLQQFqIg4Q8wMhEiAJIAkoAghBgICAgHhxIA5B/////wdxcjYCCCAJIAkoAghBgICAgHhyNgIIIAkgEjYCACAJIAU2AgQLIAxBEGokACAJDAELEE0ACyIFLQALQQd2BEAgBSgCAAwBCyAFCyIFQZniACAGEHcgBSAGaiIFAn8gASIMLQALQQd2BEAgASgCAAwBCyAMCyALEHcgBSALakEBQQAQpAIgDUEQaiQAAkAgBygCACIGRQ0AIBAoAgAhEiAIKAIkIAgtACsiASABwEEASCIBGyENIAgoAiAgCEEgaiABGyEOIAchASAGIQUDQAJAIA0gBSgCFCAFLQAbIgsgC8BBAEgiCxsiDyANIA9JIhEbIhMEQCAFKAIQIAVBEGogCxsgDiATEEoiCw0BC0F/IBEgDSAPSxshCwsgASAFIAtBAEgiCxshASAFQQRqIAUgCxsoAgAiBQ0ACwJAAkAgASAHRg0AAkACQCABKAIUIAEtABsiBSAFwEEASCILGyIFIA0gBSANSRsiDwRAIA4gASgCECABQRBqIAsbIA8QSiIBDQELIAUgDU0NAQwCCyABQQBIDQELIAYhBQNAAkACQAJAAkACQAJAIAUoAhQgBS0AGyIBIAHAQQBIIg8bIgEgDSABIA1JIhEbIgsEQCAOIAUoAhAgBUEQaiAPGyIPIAsQSiITRQRAIAEgDUsNAgwDCyATQQBODQIMAQsgASANTQ0CCyAFKAIAIgUNBQwHCyAPIA4gCxBKIgENAQsgEQ0BDAILIAFBAE4NAQsgBSgCBCIFDQEMAwsLIBIgBSgCHEECdGpBgICAfDYCAAsgCCgCLCAJIAgtADciAcBBAEgiBRshDiAIKAIwIAEgBRshDSAHIQEgBiEFA0ACQCANIAUoAhQgBS0AGyILIAvAQQBIIgsbIg8gDSAPSSIRGyITBEAgBSgCECAFQRBqIAsbIA4gExBKIgsNAQtBfyARIA0gD0sbIQsLIAEgBSALQQBIIgsbIQEgBUEEaiAFIAsbKAIAIgUNAAsgASAHRg0BAkACQCABKAIUIAEtABsiBSAFwEEASCILGyIFIA0gBSANSRsiD0UNACAOIAEoAhAgAUEQaiALGyAPEEoiAUUNACABQQBODQEMAwsgBSANSw0CCwNAAkACQAJAAkAgBigCFCAGLQAbIgEgAcBBAEgiCxsiASANIAEgDUkiDxsiBQRAAkAgDiAGKAIQIAZBEGogCxsiCyAFEEoiEQRAIBFBAE4NAQwGCyABIA1LDQULIAsgDiAFEEoiAUUNASABQQBODQIMAwsgASANSw0DCyAPDQELIBIgBigCHEECdGpBgICAfDYCAAwECyAGKAIEIgZFDQIMAQsgBigCACIGDQALC0HxIxC3AQALIAgsADdBAEgEQCAIKAIsEC8LIAgsACtBAEgEQCAIKAIgEC8LIAxBDGoiASAXRw0ACwwBCyAIQa4oNgIYIAhBpSM2AhQgCEGmFTYCEEECQbDkACAIQRBqEDQQAAALIAhBADoAIiAIQaDaADsBICAIQQI6ACsgAEHEAWoiASAIQSBqEPACIQUgCCwAK0EASARAIAgoAiAQLwsCQCAFIABByAFqIgZGDQAgCEEAOgAiIAhBoNoAOwEgIAhBAjoAKyABIAhBIGoQjAIhBSAQKAIAIAUoAgBBAnRqQYCAgHw2AgAgCCwAK0EATg0AIAgoAiAQLwsgCEEAOgAiIAhBoM4AOwEgIAhBAjoAKyABIAhBIGoQ8AIhGSAILAArQQBIBEAgCCgCIBAvCyAZIAZGDQAgCEEAOgAiIAhBoM4AOwEgIAhBAjoAKyABIAhBIGoQjAIhASAQKAIAIAEoAgBBAnRqQYCAgHw2AgAgCCwAK0EATg0AIAgoAiAQLwsgAigCBCIBIAIoAgAiBWtBMG0hBgJAIAEgBUYNACABQTBrKAIAIQcgACgC/AEhAQJAAkAgBkECTwRAIAEgB0oNAyAGQTBsIAVqQeAAaygCACABTg0BIAAoAtwBIgFBAEwNAyAQKAIAIQZBACEFIAFBBE8EQCABQXxxIQVBACEHA0AgBiAHQQJ0av0MAACA/wAAgP8AAID/AACA//0LAgAgB0EEaiIHIAVHDQALIAEgBUYNBAsDQCAGIAVBAnRqQYCAgHw2AgAgBUEBaiIFIAFHDQALDAMLIAEgB0oNAiABIApIDQEMAgsgASAKTg0BCyAQKAIAIQYCQCAKIAFrIgxBBEkEQCABIQUMAQsgASAMQXxxIglqIQVBACEHA0AgBiABIAdqQQJ0av0MAACA/wAAgP8AAID/AACA//0LAgAgB0EEaiIHIAlHDQALIAkgDEYNAQsDQCAGIAVBAnRqQYCAgHw2AgAgBUEBaiIFIApHDQALCwJAIBYNACADKgJYIgRDAAAAAF5FDQACfyAEQwAA8EEgACgCJLKVlRA1IgSLQwAAAE9dBEAgBKgMAQtBgICAgHgLIgUgACgC/AEiB2pBAWoiASAKTg0AIBAoAgAhBgJAIAogBUF/c2ogB2siDEEESQRAIAEhBQwBCyABIAxBfHEiCWohBUEAIQcDQCAGIAEgB2pBAnRq/QwAAID/AACA/wAAgP8AAID//QsCACAHQQRqIgcgCUcNAAsgCSAMRg0BCwNAIAYgBUECdGpBgICAfDYCACAFQQFqIgUgCkgNAAsLAkAgAi0AYkUEQCAQKAIAIQcMAQsgAigCXCIBQQJtIQUgAigCcCEHIAFBAkgNAAJAIAUgACgC/AEiAWoiDCABQQFqIgUgBSAMSBsgAWsiCUEESQRAIAEhBQwBCyABIAlBfHEiC2ohBUEAIQYDQCAHIAEgBmpBAnRq/QwAAID/AACA/wAAgP8AAID//QsCACAGQQRqIgYgC0cNAAsgCSALRg0BCwNAIAcgBUECdGpBgICAfDYCACAFQQFqIgUgDEgNAAsLIAchBgJAIAcgAigCdCIBRg0AIAdBBGoiBSABRg0AIAcqAgAhBANAIAUgBiAEIAUqAgAiHF0iDBshBiAcIAQgDBshBCAFQQRqIgUgAUcNAAsLAkAgCkEATA0AIAYqAgAhHCAKQQFxIQECQCAKQQFGBEBDAAAAACEEQQAhBQwBCyAKQX5xIQxDAAAAACEEQQAhBUEAIQYDQCAHIAVBAnQiCWoqAgAiHUMAAID/XgRAIAQgHSAckxBFkiEECyAHIAlBBHJqKgIAIh1DAACA/14EQCAEIB0gHJMQRZIhBAsgBUECaiEFIAZBAmoiBiAMRw0ACwsCQCABRQ0AIAcgBUECdGoqAgAiHUMAAID/XkUNACAEIB0gHJMQRZIhBAsgBBBXIQQgCkEATA0AIBwgBJIhBCAUKAIAIQxBACEFAkAgCkEESQ0AIAwgB2tBEEkNACAKQXxxIQUgBP0TIR9BACEGA0AgDCAGQQJ0IgFqIAEgB2r9AAIAIiAgH/3lAf0MAACA/wAAgP8AAID/AACA/yAg/QwAAID/AACA/wAAgP8AAID//UT9Uv0LAgAgBkEEaiIGIAVHDQALIAUgCkYNAQsgBUEBciEBIApBAXEEQCAMIAVBAnQiBWogBSAHaioCACIcIASTQwAAgP8gHEMAAID/Xhs4AgAgASEFCyABIApGDQADQCAMIAVBAnQiAWogASAHaioCACIcIASTQwAAgP8gHEMAAID/Xhs4AgAgDCABQQRqIgFqIAEgB2oqAgAiHCAEk0MAAID/IBxDAACA/14bOAIAIAVBAmoiBSAKRw0ACwsgAigCfCIJIAAoAvwBIgxBAnRqIgEhBgJAIAEgAigCgAEiC0YNACABQQRqIgUgC0YNACABKgIAIQQDQCAFIAYgBCAFKgIAIhxdIg0bIQYgHCAEIA0bIQQgBUEEaiIFIAtHDQALC0MAAID/IR0CQCAKIAxMDQAgBioCACEcIAxBAWohGgJ9IAogDGtBAXFFBEAgDCEFQwAAAAAMAQsgDEEBaiEFIAkgDEECdGoqAgAiBEMAAID/XgR9IAQgHJMQRQVDAAAAAAsLIQQgGiAKRwRAA0AgCSAFQQJ0aiIGKgIAIh5DAACA/14EQCAEIB4gHJMQRZIhBAsgBioCBCIeQwAAgP9eBEAgBCAeIByTEEWSIQQLIAVBAmoiBSAKRw0ACwsgBEMAAAAAXkUNACAcIAQQV5IhHQsgCSEGAkAgDEECSQ0AIAZBBGohBSAGKgIAIQQgDEEBa0EDcSINBEBBACELA0AgBSAGIAQgBSoCACIcXSIOGyEGIBwgBCAOGyEEIAVBBGohBSALQQFqIgsgDUcNAAsLIAxB/v///wNqQf////8DcUEDSQ0AA0AgBUEMaiAFQQhqIAVBBGogBSAGIAQgBSoCACIcXSIGGyAcIAQgBhsiBCAFKgIEIhxdIgYbIBwgBCAGGyIEIAUqAggiHF0iBhsgHCAEIAYbIgQgBSoCDCIcXSILGyEGIBwgBCALGyEEIAVBEGoiBSABRw0ACwsCQAJAIAYqAgAgHV0EQCAMQQBMDQFBACEBQQAhBQJAIAxBBEkNACAJIAdrQRBJDQAgDEF8cSEFQQAhBgNAIAcgBkECdCIAav0MAACA/wAAgP8AAID/AACA//0LAgAgACAJav0MAACA/wAAgP8AAID/AACA//0LAgAgBkEEaiIGIAVHDQALIAUgDEYNAgsgDCAFQX9zaiEbIAxBA3EiAgRAA0AgByAFQQJ0IgNqQYCAgHw2AgAgAyAJakGAgIB8NgIAIAVBAWohBSABQQFqIgEgAkcNAAsLIBtBA0kNAQNAIAcgBUECdCIAakGAgIB8NgIAIAAgCWpBgICAfDYCACAHIABBBGoiAWpBgICAfDYCACABIAlqQYCAgHw2AgAgByAAQQhqIgFqQYCAgHw2AgAgASAJakGAgIB8NgIAIAcgAEEMaiIAakGAgIB8NgIAIAAgCWpBgICAfDYCACAFQQRqIgUgDEcNAAsMAQsgAygCqAFFDQACQCACKAI4IAIoAjxGDQAgAkHEAGoiDigCACACKAJIRg0AIAAoAtwBIQsgCEEANgJcIAhCADcCVCAIQQA2AlAgCEIANwJIAkAgC0EATA0AIABB1AFqIQxBACEGAkADQAJAAkAgDCIBIgUoAgAiB0UNAANAIAciBSgCECIBIAZKBEAgBSEBIAUoAgAiBw0BDAILIAEgBk4NAiAFKAIEIgcNAAsgBUEEaiEBC0EgEDIiByAGNgIQIAcgBTYCCCAHQgA3AgAgB0IANwIUIAdBADYCHCABIAc2AgAgByEFIAAoAtABKAIAIgkEQCAAIAk2AtABIAEoAgAhBQsgACgC1AEgBRCkASAAIAAoAtgBQQFqNgLYAQsCQAJAIAcoAhggBy0AHyIBIAHAQQBIIgEbRQ0AIAdBFGoiBSgCACEHIAggAikDUCIhNwMIIAggITcDQCAIQSBqIAcgBSABGyAIQQhqENgEAkAgCCgCWCIBIAgoAlxJBEAgAUEANgIIIAFCADcCACABIAgoAiA2AgAgASAIKAIkNgIEIAEgCCgCKDYCCCAIQQA2AiggCEIANwIgIAEgCCkCLDcCDCAIIAFBFGo2AlgMAQsCQAJAAkAgCCgCWCAIKAJUIgVrQRRtIgdBAWoiAUHNmbPmAEkEQEHMmbPmACAIKAJcIAVrQRRtIgVBAXQiCSABIAEgCUkbIAVB5syZM08bIgFBzZmz5gBPDQEgAUEUbCIBEDIiCSAHQRRsaiIFIAgoAiA2AgAgBSAIKAIkNgIEIAUgCCgCKDYCCCAIQQA2AiggCEIANwIgIAUgCCkCLDcCDCABIAlqIQEgBUEUaiEJIAgoAlgiByAIKAJUIg1GDQIDQCAFQRRrIgUgB0EUayIHKAIANgIAIAUgBygCBDYCBCAFIAcoAgg2AgggB0EANgIIIAdCADcCACAFIAcpAgw3AgwgByANRw0ACyAIIAE2AlwgCCgCWCEBIAggCTYCWCAIKAJUIQcgCCAFNgJUIAEgB0YNAwNAIAFBFGsiBSgCACIJBEAgAUEQayAJNgIAIAkQLwsgBSIBIAdHDQALDAMLEDYACxBHAAsgCCABNgJcIAggCTYCWCAIIAU2AlQLIAcEQCAHEC8LIAgoAiAiAUUNACAIIAE2AiQgARAvCyAIKAJYQRRrIgEoAgAhDSABKQIMISEgCCgCTCIFIAgoAlAiCUkEQCAFICE3AgggBSANNgIEIAUgBjYCACAIIAVBEGo2AkwMAQsgBSAIKAJIIgFrQQR1IhJBAWoiB0GAgICAAU8NAUH/////ACAJIAFrIglBA3UiDyAHIAcgD0kbIAlB8P///wdPGyIJBH8gCUGAgICAAU8NBCAJQQR0EDIFQQALIg8gEkEEdGoiByAhNwIIIAcgDTYCBCAHIAY2AgAgB0EQaiENIAEgBUcEQANAIAdBEGsiByAFQRBrIgX9AAIA/QsCACABIAVHDQALIAEhBQsgCCAPIAlBBHRqNgJQIAggDTYCTCAIIAc2AkggBUUNACAFEC8LIAZBAWoiBiALRw0BDAMLCxA2AAsQRwALIAhBIGogAkE4aiAOIAhByABqEM8EIAgoAiAiACAIKAIkIgFHBEAgAyoCsAEhBCAQKAIAIQMgACEFA0AgAyAFKAIAQQJ0aiIGIAYqAgAgBJM4AgAgBUEQaiIFIAFHDQALCyAABEAgCCAANgIkIAAQLwsgCCgCSCIABEAgABAvCyAIKAJUIgBFDQAgCCgCWCIHIAAiBUcEQANAIAdBFGsiASgCACIDBEAgB0EQayADNgIAIAMQLwsgASIHIABHDQALIAgoAlQhBQsgCCAANgJYIAUQLwsgAigCcCIBIQYCQCABIAIoAnQiAEYNACABQQRqIgUgAEYNACAGKgIAIQQDQCAFIAYgBCAFKgIAIhxdIgIbIQYgHCAEIAIbIQQgBUEEaiIFIABHDQALCyAKQQBMDQEgBioCACEcIApBAXEhAAJAIApBAUYEQEMAAAAAIQRBACEFDAELIApBfnEhAkMAAAAAIQRBACEFQQAhBgNAIAEgBUECdCIDaioCACIdQwAAgP9eBEAgBCAdIByTEEWSIQQLIAEgA0EEcmoqAgAiHUMAAID/XgRAIAQgHSAckxBFkiEECyAFQQJqIQUgBkECaiIGIAJHDQALCwJAIABFDQAgASAFQQJ0aioCACIdQwAAgP9eRQ0AIAQgHSAckxBFkiEECyAEEFchBCAKQQBMDQEgHCAEkiEEIBQoAgAhAkEAIQUCQCAKQQRJDQAgAiABa0EQSQ0AIApBfHEhBSAE/RMhH0EAIQYDQCACIAZBAnQiAGogACABav0AAgAiICAf/eUB/QwAAID/AACA/wAAgP8AAID/ICD9DAAAgP8AAID/AACA/wAAgP/9RP1S/QsCACAGQQRqIgYgBUcNAAsgBSAKRg0BCyAFQQFyIQAgCkEBcQRAIAIgBUECdCIDaiABIANqKgIAIhwgBJNDAACA/yAcQwAAgP9eGzgCACAAIQULIAAgCkYNAANAIAIgBUECdCIAaiAAIAFqKgIAIhwgBJNDAACA/yAcQwAAgP9eGzgCACACIABBBGoiAGogACABaioCACIcIASTQwAAgP8gHEMAAID/Xhs4AgAgBUECaiIFIApHDQALCyAKQQBMDQAgFSgCACEAIBQoAgAhASAQKAIAIQJBACEFIApBAUcEQCAKQX5xIQZBACELA0BDAAAAACEEQwAAAAAhHCACIAVBAnQiA2oqAgBDAACA/1wEQCABIANqKgIAEEUhHAsgACADaiAcOAIAIAIgBUEBckECdCIDaioCAEMAAID/XARAIAEgA2oqAgAQRSEECyAAIANqIAQ4AgAgBUECaiEFIAtBAmoiCyAGRw0ACwsgCkEBcUUNAEMAAAAAIQQgAiAFQQJ0IgNqKgIAQwAAgP9cBEAgASADaioCABBFIQQLIAAgA2ogBDgCAAsgCEHgAGokAAvUEQEQfyMAQSBrIggkAAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAgASgCBCIGIAEoAgBGBEAgAigCBCIHIAIoAghGDQEgB0EANgIIIAdCADcCACABKAIEIgAgASgCACIGRg0MIAAgBmsiBkEASA0CIAcgBhAyIgA2AgQgByAANgIAIAcgACAGQXxxajYCCCABKAIAIgQgASgCBCIBRgRAIAAhBgwMCyABIARrQQRrIgZBDEkNCSAAIARrQRBJDQkgACAGQQJ2QQFqIglB/P///wdxIgpBAnQiA2ohBiADIARqIQMDQCAAIAVBAnQiC2ogBCALav0AAgD9CwIAIAVBBGoiBSAKRw0ACyAJIApGDQsMCgsCQCAGQQRrKAIAIgooAgAiBkEDa0ECTwRAIAZBAkcNASAKQQhqIQsgACgCACAKKAIEQQxsaigCACEGA0AgASgCACEDIAEoAgQhBCAIQQA2AhwgCEIANwIUAkACQCAEQQRrIgQgA0cEQCAEIANrIgVBAEgNEyAIIAUQMiIENgIYIAggBDYCFCAIIAQgBUF8cSIFaiIHNgIcIAQgAyAF/AoAACAIIAQgBWoiAzYCGCAKKAIIQQJJDQIgAyAHTw0BIAMgCzYCACAIIANBBGo2AhgMAgtBACEEQQAhB0EAIQMgCigCCEECSQ0BCyADIARrIgxBAnUiDUEBaiIFQYCAgIAETw0RQf////8DIAcgBGsiB0EBdSIJIAUgBSAJSRsgB0H8////B08bIgkEfyAJQYCAgIAETw0HIAlBAnQQMgVBAAsiDiANQQJ0aiIFIAs2AgAgBUEEaiENIAMgBEcEQAJAIAxBBGsiB0EMTwRAIAVBEGshDyADQRBrIRAgAyAHQQJ2QQFqIhFB/P///wdxIgxBAnQiB2shAyAFIAdrIQVBACEHA0AgDyAHQQJ0IhJrIBAgEmv9AAIA/QsCACAHQQRqIgcgDEcNAAsgDCARRg0BCwNAIAVBBGsiBSADQQRrIgMoAgA2AgAgAyAERw0ACwsgCCgCFCEECyAIIA4gCUECdGo2AhwgCCANNgIYIAggBTYCFCAERQ0AIAQQLwsCQCAGKAIAQQJJDQAgCCgCGCIDIAgoAhxHBEAgAyAGNgIAIAggA0EEajYCGAwBCyADIAgoAhQiDGsiBEECdSIHQQFqIgVBgICAgARPDRFB/////wMgBEEBdSIJIAUgBSAJSRsgBEH8////B08bIgkEfyAJQYCAgIAETw0HIAlBAnQQMgVBAAsiDSAHQQJ0aiIFIAY2AgAgBUEEaiEOIAMgDEcEQAJAAkAgBEEEayIHQSxJDQAgAyAEIA1qa0EQSQ0AIAVBEGshDyADQRBrIRAgAyAHQQJ2QQFqIhFB/P///wdxIgRBAnQiB2shAyAFIAdrIQVBACEHA0AgDyAHQQJ0IhJrIBAgEmv9AAIA/QsCACAHQQRqIgcgBEcNAAsgBCARRg0BCwNAIAVBBGsiBSADQQRrIgMoAgA2AgAgAyAMRw0ACwsgCCgCFCEDCyAIIA0gCUECdGo2AhwgCCAONgIYIAggBTYCFCADRQ0AIAMQLwsgACAIQRRqIAIQiwIDQCAGIgNBCGohBiADKAIAIgRBAUsNAAsgBEEBRiIEQQN0IQUgCCgCFCIGBEAgCCAGNgIYIAYQLwsgAyAFaiEGIAQNAAsMDgsgAigCBCIHIAIoAghGDQEgB0EANgIIIAdCADcCACABKAIEIgAgASgCACIGRg0IIAAgBmsiBkEASA0EIAcgBhAyIgA2AgQgByAANgIAIAcgACAGQXxxajYCCCABKAIAIgQgASgCBCIBRgRAIAAhBgwICyABIARrQQRrIgZBDEkNBSAAIARrQRBJDQUgACAGQQJ2QQFqIglB/P///wdxIgpBAnQiA2ohBiADIARqIQMDQCAAIAVBAnQiC2ogBCALav0AAgD9CwIAIAVBBGoiBSAKRw0ACyAJIApGDQcMBgsgCEGbITYCCCAIQfUfNgIEIAhBphU2AgBBAkGw5AAgCBA0EAAAC0EAIQdBACEKAkACQAJAAkACQAJAIAIoAgQiBCACKAIAIglrQQxtIgZBAWoiAEHWqtWqAUkEQEHVqtWqASACKAIIIAlrQQxtIgNBAXQiBSAAIAAgBUkbIANBqtWq1QBPGyILBEAgC0HWqtWqAU8NAiALQQxsEDIhBwsgByAGQQxsaiIFQQA2AgggBUIANwIAIAEoAgQiDCABKAIAIgFGDQYgDCABayIAQQBIDQIgBSAAEDIiBjYCACAFIAYgAEF8cWo2AgggAEEEayIAQQxJDQMgBiABa0EQSQ0DIAYgAEECdkEBaiIOQfz///8HcSINQQJ0IgNqIQAgASADaiEDA0AgBiAKQQJ0Ig9qIAEgD2r9AAIA/QsCACAKQQRqIgogDUcNAAsgDSAORg0FDAQLEDYACxBHAAsQNgALIAEhAyAGIQALA0AgACADKAIANgIAIABBBGohACADQQRqIgMgDEcNAAsLIAUgADYCBAsgByALQQxsaiEAIAVBDGohAQJAIAQgCUcEQANAIAVBDGsiBUEANgIIIAUgBEEMayIEKAIANgIAIAUgBCgCBDYCBCAFIAQoAgg2AgggBEEANgIIIARCADcCACAEIAlHDQALIAIgADYCCCACKAIEIQAgAiABNgIEIAIoAgAhBCACIAU2AgAgACAERg0BA0AgAEEMayIBKAIAIgIEQCAAQQhrIAI2AgAgAhAvCyABIgAgBEcNAAsMAQsgAiAANgIIIAIgATYCBCACIAU2AgALIAQEQCAEEC8LDAsLEDYACxBHAAsQNgALIAQhAyAAIQYLA0AgBiADKAIANgIAIAZBBGohBiADQQRqIgMgAUcNAAsLIAcgBjYCBAsgAiAHQQxqNgIEDAQLIAQhAyAAIQYLA0AgBiADKAIANgIAIAZBBGohBiADQQRqIgMgAUcNAAsLIAcgBjYCBAsgAiAHQQxqNgIECyAIQSBqJAAPCxA2AAvcAQEGfwJAAkAgACgCBCIARQ0AIAEoAgAgASABLQALIgLAQQBIIgMbIQUgASgCBCACIAMbIQEDQAJAAkACQAJAAkAgACgCFCAALQAbIgIgAsBBAEgiBBsiAiABIAEgAksiBhsiAwRAIAUgACgCECAAQRBqIAQbIgQgAxBKIgdFBEAgASACSQ0CDAMLIAdBAE4NAgwBCyABIAJPDQILIAAoAgAiAA0EDAULIAQgBSADEEoiAg0BCyAGDQEMBAsgAkEATg0DCyAAKAIEIgANAAsLQfEjELcBAAsgAEEcagsxACABBEAgACABKAIAEI0CIAAgASgCBBCNAiABLAAbQQBIBEAgASgCEBAvCyABEC8LCzEAIAEEQCAAIAEoAgAQjgIgACABKAIEEI4CIAEsABtBAEgEQCABKAIQEC8LIAEQLwsLMQAgAQRAIAAgASgCABCPAiAAIAEoAgQQjwIgASwAH0EASARAIAEoAhQQLwsgARAvCwv6AgEDfyABIAEoAggRAAAiAUEBIAEoAgARBAAhA0GcEBA7IQEgAxDoBCEEIAEgAygCHCIFIAUoAgQRAAAiBTYCDCABIAQ2AgggAUEBNgIEIAEgAzYCACABQRxqQQBBgBD8CwAgAygCJBogAUH/////BzYCGCABQQE2AhAgAUEBOgCYECABIAQgBSAEIAVwayAFcGo2AhRBCBA7IgMQggQ2AgQgAyABNgIAIAAgAzYCAEEAIQFBICEDA0AgASADaiIEQQF2IgVBAWogASAEQRhJIgQbIgEgAyAFIAQbIgNJDQALAkAgAUEfTQR/IAFBAnRBgKMBaigCAEECdEHMgAFqBUHQgAILQYCAzwBqIgEgACgCCCAAKAIEIgRrIgNLBEAgAEEEaiABIANrEPECDAELIAEgA08NACAAIAEgBGo2AggLIAIoAhAiAUUEQEEEEF4iAEGoxwI2AgAgAEHQxwJBzAAQAgALIAAoAgAgASABKAIAKAIYEQAAENoBC14BAX8jAEEQayICJAAgACgCAEE8RwRAQbzDAigCABAwGiACQdPLADYCCCACQdIENgIEIAJBmyc2AgBBuMMCKAIAQcvkACACEDEQAAALIAAoAjQgATYCACACQRBqJAALTwECfyAAKAIAIgBBATYCECAAIAAoAggiAiAAKAIMIgEgAiABcGsgAXAiAWo2AhQgACAALQCYEAR/Qf////8HBSAAKAIAKAIkIAFrCzYCGAuoBQEJfyMAQSBrIgMkACAAKAIIIgEoAhghByABKAIEIQUgASgCACEGQX8hAgNAAkACQCAFKAIMIgFFBEAgACgCCCEBDAELIAUoAhAgAREAACEJIAAoAgghASAJRQ0AQQEhAiABQQH+HgIgGgwBCwJAIAFBAf4lAhxBAUYEQCADQQA2AhQgA0ICNwIMIAMgBSgCADYCGCADIAUoAgQ2AhwgAkF/RwRAIAYoAgwgAkECdGooAgAiASgCQEHw1jRqLQAABEAgAyABIAcQ2wE2AhQgA0EMaiABEMoBCyAAKAIIIQQgASABKAK0AUEBajYCtAEgASAB/QADuAEgBP0AAwj90QH9CwO4AQsCQCACQQFqIgEgBigCBE4NAANAIAYoAgwgAUECdGooAgAiAiAHENsBIQQgACgCCP0MAAAAAAAAAAAAAAAAAAAAAP0LAwggAyAENgIUIAIoAkBBoNY0ai0AAARAIANBADYCDCADQQxqIAIQygELIARBAUcNASADQQE2AgwgA0EMaiIIIAIQygEgAigCQEHw1jRqLQAABEAgA0ECNgIMIAggAhDKAQsgACgCCCEEIAIgAigCtAFBAWo2ArQBIAIgAv0AA7gBIAT9AAMI/dEB/QsDuAEgBSgCDCICBEAgBSgCECACEQAADQILIAFBAWoiASAGKAIESA0ACwsgACgCCCAH/hcCHCAAKAIIIAH+FwIgDAELA0AgACgCCP4QAiAiASACRg0ACwsgBigCBCABTARAQQAhAgwBCyAGKAIMIAFBAnRqKAIAIgggBxDbASECIANBATYCDCAAKAIEIQQgAyACNgIUIAMgBDYCECADIAUoAgA2AhggAyAFKAIENgIcIAIgBEoEQCADQQxqIAgQygELIAEhAgwBCwsgA0EgaiQAIAILFQAgAEHstgM2AgAgAEEEahD7AiAACwwAIAAQ/AIaIAAQLwtLAQJ/IAAoAgQiBkEIdSEHIAAoAgAiACABIAIgBkEBcQR/IAcgAygCAGooAgAFIAcLIANqIARBAiAGQQJxGyAFIAAoAgAoAhQRDAALmgEAIABBAToANQJAIAAoAgQgAkcNACAAQQE6ADQCQCAAKAIQIgJFBEAgAEEBNgIkIAAgAzYCGCAAIAE2AhAgA0EBRw0CIAAoAjBBAUYNAQwCCyABIAJGBEAgACgCGCICQQJGBEAgACADNgIYIAMhAgsgACgCMEEBRw0CIAJBAUYNAQwCCyAAIAAoAiRBAWo2AiQLIABBAToANgsLXQEBfyAAKAIQIgNFBEAgAEEBNgIkIAAgAjYCGCAAIAE2AhAPCwJAIAEgA0YEQCAAKAIYQQJHDQEgACACNgIYDwsgAEEBOgA2IABBAjYCGCAAIAAoAiRBAWo2AiQLCxAAQci7A/4QAgARCQAQRgALHQEBf0EYEDIQhAMiAUEMahCEAxogACABNgIAIAALQwACQEHgmDX+EgAAQQFxDQBB4Jg1EFRFDQBB2Jg1Qf0DEJIEBEAQRgALQdyYNUHYmDU2AgBB4Jg1EFMLQdyYNSgCAAuaAQECfwJ/QcitAy4BACIBRQRAIwNBHGpBHDYCAEF/DAELAkACQCABQX5KDQBB6aAMIQACQAJAAkACQAJAAkACQCABQf8BcUEBaw4LCAABAgMEBAUFBgMHC0GAgAgMCAtBgIACDAcLQYCABAwGC0H/////BwwFCxAZDAQLEBhBEHYMAwtBAAwCCyABIQALIAALIgBBACAAQQBKGwsjAQF/AkAgACgCACIBBEAgARCTBEUNAQsQRgALIABBADYCAAsdACAAIAFBwIQ9biIAEKkBIAEgAEHAhD1saxCfAgsdACAAIAFBkM4AbiIAEKkBIAEgAEGQzgBsaxCgAgsbACAAIAFB5ABuIgAQqQEgASAAQeQAbGsQqQEL+wEBA38jAEEQayICJAAgAiABNgIMAkACQAJ/IAAtAAsiA0EHdiIERQRAQQEhASADQf8AcQwBCyAAKAIIQf////8HcUEBayEBIAAoAgQLIgMgAUYEQCAAIAFBASABIAEQhgMCfyAALQALQQd2BEAgACgCAAwBC0EACxoMAQsCfyAALQALQQd2BEAgACgCAAwBC0EACxogBA0AIAAiASADQQFqIAAtAAtBgAFxcjoACyAAIAAtAAtB/wBxOgALDAELIAAoAgAhASAAIANBAWo2AgQLIAEgA0ECdGoiACACKAIMNgIAIAJBADYCCCAAIAIoAgg2AgQgAkEQaiQAC/gBAQN/IwBBEGsiAiQAIAIgAToADwJAAkACfyAALQALIgNBB3YiBEUEQEEKIQEgA0H/AHEMAQsgACgCCEH/////B3FBAWshASAAKAIECyIDIAFGBEAgACABQQEgASABEKUCAn8gAC0AC0EHdgRAIAAoAgAMAQtBAAsaDAELAn8gAC0AC0EHdgRAIAAoAgAMAQtBAAsaIAQNACAAIgEgA0EBaiAALQALQYABcXI6AAsgACAALQALQf8AcToACwwBCyAAKAIAIQEgACADQQFqNgIECyABIANqIgAgAi0ADzoAACACQQA6AA4gACACLQAOOgABIAJBEGokAAvgAgIFfwJ+An8jAEHwAGsiAyQAAkACQAJAIAEoAjAiAiABKAIAIgVBJGwiBEGYmwFqKAIARw0AIAE1AjQiByABKQMQIAKtfiAEQZSbAWo0AgB/Ug0AIAE1AjgiCCAHIAEpAxh+Ug0AIAE1AjwgASkDICAIflINACABKAKIASEGIAAgBSABKAIMIAFBEGpBAEEAEEkiAkUNASACQSc2AkAgAkMAAIA/OAJEIAYEfyAAIAIoAgAgAigCDCACQRBqQQBBABBJBUEACyEAIAIgATYCjAEgAiAANgKIASACQQA2ApABIANB8ABqJAAgAgwDC0G8wwIoAgAQMBogA0HF1wA2AmggA0GvJjYCZCADQeQmNgJgQbjDAigCAEHL5AAgA0HgAGoQMQwBC0G8wwIoAgAQMBogA0HXLzYCGCADQcYUNgIUIANB5CY2AhBBuMMCKAIAQcvkACADQRBqEDELEAAACws9AQF/IwBBEGsiAyQAIAMgAjoADwNAIAEEQCAAIAMtAA86AAAgAUEBayEBIABBAWohAAwBCwsgA0EQaiQAC8MCAQV/IwBBEGsiBSQAIAJB7////wcgAWtNBEACfyAALQALQQd2BEAgACgCAAwBCyAACyEGIAVBBGoiByAAIAFB5////wNJBH8gBSABQQF0NgIMIAUgASACajYCBCMAQRBrIgIkACAHKAIAIAVBDGoiCCgCAEkhCSACQRBqJAAgCCAHIAkbKAIAIgJBC08EfyACQRBqQXBxIgIgAkEBayICIAJBC0YbBUEKC0EBagVB7////wcLEMMBIAUoAgQhAiAFKAIIGiAEBEAgAiAGIAQQdwsgAyAERwRAIAIgBGogBCAGaiADIARrEHcLIAFBAWoiAUELRwRAIAAgBiABEPEBCyAAIAI2AgAgACAAKAIIQYCAgIB4cSAFKAIIQf////8HcXI2AgggACAAKAIIQYCAgIB4cjYCCCAFQRBqJAAPCxBNAAswACAAKAIARQRAIABBfxCVBA8LIAAoAgwEQCAAQQhqIgBBAf4eAgAaIAAQ+gELQQAL5wEBB38jAEEgayIEJAAgASgCiAEhCCAAIAEoAgAgASgCDCABQRBqIAFBABBJIQcgBCABQdQBaiICNgIQIAdBycsAIARBEGoQcyIDIAEoAjA2AjAgAyABKAI0NgI0IAMgASgCODYCOCADIAEoAjw2AjwgBCACNgIAIANBgtUAIAQQcyICIAEpAxg3AxAgAiABKQMQNwMYIAMgASgCNDYCMCADIAEoAjA2AjQgAkEhNgJAIAgEQCAAIAIoAgAgAigCDCACQRBqQQBBABBJIQULIAIgATYCjAEgAiAFNgKIASAEQSBqJAAgAgsNACAAIAEgAkJ/EOADCxcAIAAoAggQREcEQCAAKAIIEOMDCyAAC0wBAX8jAEEQayIGJAAgBiACNwMAIAYgAzcDCCAAIAFBAiAGIAUQqwIiACADpyAEbCIBNgI8IAAgATYCOCAAIAQ2AjQgBkEQaiQAIAALwgEBA38jAEEgayIFJAAgASgCiAEhBiAAIAEoAgAgAiADIAEgBBBJIQcgBSABQdQBajYCECAHQcnLACAFQRBqEHMiAgRAIAJBHzYCQCACIAQ2AkQgBgR/IAAgAigCACACKAIMIAJBEGpBAEEAEEkFQQALIQQgAiABNgKMASACIAQ2AogBIAVBIGokACACDwtBvMMCKAIAEDAaIAVB1y82AgggBUHGFDYCBCAFQeQmNgIAQbjDAigCAEHL5AAgBRAxEAAACzgBAn8jAEEQayIDJAAgAyACNgIMIANBCGogA0EMahB/IQQgACABEMICIQAgBBB+IANBEGokACAACwQAQQELNwECfyMAQRBrIgIkACACIAAoAgA2AgwgAiACKAIMIAFBAnRqNgIMIAIoAgwhAyACQRBqJAAgAws0AQJ/IwBBEGsiAiQAIAIgACgCADYCDCACIAIoAgwgAWo2AgwgAigCDCEDIAJBEGokACADC4QCAQV/IwBBIGsiAyQAAkACQCAAKAIAIgUgAkEDakF8cSIHIAAoAhQiBAR/IAQoAgQgBCgCAGoFQQALIgZqIgJBFGpJBEAgAyAFNgIIIAMgAjYCBCADQb4PNgIAQe/yACADELMBQQAhAgwBCyAAKAIEIgUgBmoiAkEANgIQIAIgATYCDCACQQA2AgggAiAHNgIEIAIgBkEUaiIBNgIAIAEgBWpBA3ENASAEQQhqIABBEGogBBsgAjYCACAAIAI2AhQLIANBIGokACACDwtBvMMCKAIAEDAaIANBlsEANgIYIANBjBM2AhQgA0HkJjYCEEG4wwIoAgBBy+QAIANBEGoQMRAAAAsxACACKAIAIQIDQAJAIAAgAUcEfyAAKAIAIAJHDQEgAAUgAQsPCyAAQQRqIQAMAAsAC/oEAQF/IwBBEGsiDCQAIAwgADYCDAJAAkAgACAFRgRAIAEtAABFDQFBACEAIAFBADoAACAEIAQoAgAiAUEBajYCACABQS46AAACfyAHLQALQQd2BEAgBygCBAwBCyAHLQALQf8AcQtFDQIgCSgCACIBIAhrQZ8BSg0CIAooAgAhAiAJIAFBBGo2AgAgASACNgIADAILAkAgACAGRw0AAn8gBy0AC0EHdgRAIAcoAgQMAQsgBy0AC0H/AHELRQ0AIAEtAABFDQFBACEAIAkoAgAiASAIa0GfAUoNAiAKKAIAIQAgCSABQQRqNgIAIAEgADYCAEEAIQAgCkEANgIADAILQX8hACALIAtBgAFqIAxBDGoQsQIgC2siBkH8AEoNASAGQQJ1QdDqAmosAAAhBQJAAkAgBkF7cSIAQdgARwRAIABB4ABHDQEgAyAEKAIAIgFHBEBBfyEAIAFBAWssAAAiA0HfAHEgAyADQeEAa0EaSRsgAiwAACICQd8AcSACIAJB4QBrQRpJG0cNBQsgBCABQQFqNgIAIAEgBToAAEEAIQAMBAsgAkHQADoAAAwBCyAFQd8AcSAFIAVB4QBrQRpJGyIAIAIsAABHDQAgAiAAQSByIAAgAEHBAGtBGkkbOgAAIAEtAABFDQAgAUEAOgAAAn8gBy0AC0EHdgRAIAcoAgQMAQsgBy0AC0H/AHELRQ0AIAkoAgAiACAIa0GfAUoNACAKKAIAIQEgCSAAQQRqNgIAIAAgATYCAAsgBCAEKAIAIgBBAWo2AgAgACAFOgAAQQAhACAGQdQASg0BIAogCigCAEEBajYCAAwBC0F/IQALIAxBEGokACAAC6YBAQJ/IwBBEGsiBiQAIAZBDGoiBSABKAIcIgE2AgAgAUEEakEB/h4CABogBRBsIgFB0OoCQfDqAiACIAEoAgAoAjARCAAaIAMgBRC/ASIBIAEoAgAoAgwRAAA2AgAgBCABIAEoAgAoAhARAAA2AgAgACABIAEoAgAoAhQRAgAgBSgCACIAQQRqQX/+HgIARQRAIAAgACgCACgCCBEBAAsgBkEQaiQACzEAIAItAAAhAgNAAkAgACABRwR/IAAtAAAgAkcNASAABSABCw8LIABBAWohAAwACwAL7gQBAX8jAEEQayIMJAAgDCAAOgAPAkACQCAAIAVGBEAgAS0AAEUNAUEAIQAgAUEAOgAAIAQgBCgCACIBQQFqNgIAIAFBLjoAAAJ/IActAAtBB3YEQCAHKAIEDAELIActAAtB/wBxC0UNAiAJKAIAIgEgCGtBnwFKDQIgCigCACECIAkgAUEEajYCACABIAI2AgAMAgsCQCAAIAZHDQACfyAHLQALQQd2BEAgBygCBAwBCyAHLQALQf8AcQtFDQAgAS0AAEUNAUEAIQAgCSgCACIBIAhrQZ8BSg0CIAooAgAhACAJIAFBBGo2AgAgASAANgIAQQAhACAKQQA2AgAMAgtBfyEAIAsgC0EgaiAMQQ9qELQCIAtrIgZBH0oNASAGQdDqAmosAAAhBQJAAkACQAJAIAZBfnFBFmsOAwECAAILIAMgBCgCACIBRwRAIAFBAWssAAAiA0HfAHEgAyADQeEAa0EaSRsgAiwAACICQd8AcSACIAJB4QBrQRpJG0cNBQsgBCABQQFqNgIAIAEgBToAAEEAIQAMBAsgAkHQADoAAAwBCyAFQd8AcSAFIAVB4QBrQRpJGyIAIAIsAABHDQAgAiAAQSByIAAgAEHBAGtBGkkbOgAAIAEtAABFDQAgAUEAOgAAAn8gBy0AC0EHdgRAIAcoAgQMAQsgBy0AC0H/AHELRQ0AIAkoAgAiACAIa0GfAUoNACAKKAIAIQEgCSAAQQRqNgIAIAAgATYCAAsgBCAEKAIAIgBBAWo2AgAgACAFOgAAQQAhACAGQRVKDQEgCiAKKAIAQQFqNgIADAELQX8hAAsgDEEQaiQAIAALpgEBAn8jAEEQayIGJAAgBkEMaiIFIAEoAhwiATYCACABQQRqQQH+HgIAGiAFEHIiAUHQ6gJB8OoCIAIgASgCACgCIBEIABogAyAFEMEBIgEgASgCACgCDBEAADoAACAEIAEgASgCACgCEBEAADoAACAAIAEgASgCACgCFBECACAFKAIAIgBBBGpBf/4eAgBFBEAgACAAKAIAKAIIEQEACyAGQRBqJAALfwICfwJ+IwBBoAFrIgQkACAEIAE2AjwgBCABNgIUIARBfzYCGCAEQRBqIgVCABCAASAEIAUgA0EBEOoDIAQpAwghBiAEKQMAIQcgAgRAIAIgASAEKAIUIAQoAogBaiAEKAI8a2o2AgALIAAgBjcDCCAAIAc3AwAgBEGgAWokAAvbAQEIfyAAIABBPRCOBCIBRgRAQQAPCwJAIAAgASAAayIFai0AAA0AQYyINSgCACICRQ0AIAIoAgAiAUUNAANAAkACfyAAIQRBACAFIgZFDQAaIAAtAAAiAwR/AkADQCADIAEtAAAiB0cNASAHRQ0BIAZBAWsiBkUNASABQQFqIQEgBC0AASEDIARBAWohBCADDQALQQAhAwsgAwVBAAsgAS0AAGsLRQRAIAIoAgAgBWoiAS0AAEE9Rg0BCyACKAIEIQEgAkEEaiECIAENAQwCCwsgAUEBaiEICyAIC0QBAX8jAEEQayIFJAAgBSABIAIgAyAEQoCAgICAgICAgH+FEHEgBSkDACEBIAAgBSkDCDcDCCAAIAE3AwAgBUEQaiQAC4QBAQJ/IABBqMwCNgIAIAAoAighAQNAIAEEQEEAIAAgAUEBayIBQQJ0IgIgACgCJGooAgAgACgCICACaigCABEFAAwBCwsgACgCHCIBQQRqQX/+HgIARQRAIAEgASgCACgCCBEBAAsgACgCIBAvIAAoAiQQLyAAKAIwEC8gACgCPBAvIAALIAAgACAAKAIYRSABciIBNgIQIAAoAhQgAXEEQBBGAAsLRgAjAEEQayIBJAAgASADNgIMIAQgAiADIAJrIgL8CgAAIAEgAiAEajYCCCAAIAEoAgw2AgAgACABKAIINgIEIAFBEGokAAs2AQF/IwBBEGsiAyQAIAMgATYCDCADIAI2AgggACADKAIMNgIAIAAgAygCCDYCBCADQRBqJAALOwEBfyAAQfDKAigCACIBNgIAIAAgAUEMaygCAGpB/MoCKAIANgIAIABBCGoQ8gEaIABB7ABqEMACIAALDAAgAEEIahDAAiAACwgAIAAQugIaC9IDAgJ+An8jAEEgayIEJAACQCABQv///////////wCDIgNCgICAgICAwIA8fSADQoCAgICAgMD/wwB9VARAIAFCBIYgAEI8iIQhAyAAQv//////////D4MiAEKBgICAgICAgAhaBEAgA0KBgICAgICAgMAAfCECDAILIANCgICAgICAgIBAfSECIABCgICAgICAgIAIUg0BIAIgA0IBg3whAgwBCyAAUCADQoCAgICAgMD//wBUIANCgICAgICAwP//AFEbRQRAIAFCBIYgAEI8iIRC/////////wODQoCAgICAgID8/wCEIQIMAQtCgICAgICAgPj/ACECIANC////////v//DAFYNAEIAIQIgA0IwiKciBUGR9wBJDQAgBEEQaiAAIAFC////////P4NCgICAgICAwACEIgIgBUGB9wBrEGYgBCAAIAJBgfgAIAVrEK8BIAQpAwhCBIYgBCkDACIAQjyIhCECIAQpAxAgBCkDGIRCAFKtIABC//////////8Pg4QiAEKBgICAgICAgAhaBEAgAkIBfCECDAELIABCgICAgICAgIAIUg0AIAJCAYMgAnwhAgsgBEEgaiQAIAIgAUKAgICAgICAgIB/g4S/C4gCAAJAIAAEfyABQf8ATQ0BAkAjAygCYCgCAEUEQCABQYB/cUGAvwNGDQMMAQsgAUH/D00EQCAAIAFBP3FBgAFyOgABIAAgAUEGdkHAAXI6AABBAg8LIAFBgEBxQYDA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fyMAQRBrIgEkACAAQQE2AiAgAEEEaiICEFYaIAAoAiwgACgCMEcEQANAIAFBBGogABCfBCACEFIaIAEoAgwgASgCBBEBACACEFYaIAAoAiwgACgCMEcNAAsLIAIQUhogAEEANgIgIAFBEGokAAueDAMGfAN+CH8jAEEQayIOJAACQAJAIAG9IglCNIinIg1B/w9xIg9BvghrIhBB/35LIAC9IghCNIinIgtB/w9rQYJwT3ENACAJQgGGIgpCgICAgICAgBB8QoGAgICAgIAQVARARAAAAAAAAPA/IQIgCEKAgICAgICA+D9RDQIgClANAiAKQoGAgICAgIBwVCAIQgGGIghCgICAgICAgHBYcUUEQCAAIAGgIQIMAwsgCEKAgICAgICA8P8AUQ0CRAAAAAAAAAAAIAEgAaIgCEL/////////7/8AViAJQgBZcxshAgwCCyAIQgGGQoCAgICAgIAQfEKBgICAgICAEFQEQCAAIACiIQIgCEIAUwRAIAKaIAIgCRCkBEEBRhshAgsgCUIAWQ0CIwBBEGsiC0QAAAAAAADwPyACozkDCCALKwMIIQIMAgsgCEIAUwRAIAkQpAQiDEUEQCAAIAChIgAgAKMhAgwDCyALQf8PcSELIAxBAUZBEnQhDCAIQv///////////wCDIQgLIBBB/35NBEBEAAAAAAAA8D8hAiAIQoCAgICAgID4P1ENAiAPQb0HTQRAIAEgAZogCEKAgICAgICA+D9WG0QAAAAAAADwP6AhAgwDCyANQYAQSSAIQoGAgICAgID4P1RHBEAjAEEQayILRAAAAAAAAABwOQMIIAsrAwhEAAAAAAAAAHCiIQIMAwsjAEEQayILRAAAAAAAAAAQOQMIIAsrAwhEAAAAAAAAABCiIQIMAgsgCw0AIABEAAAAAAAAMEOivUL///////////8Ag0KAgICAgICAoAN9IQgLAnwgCUKAgIBAg78iBSEHIA4gCEKAgICA0Kql8z99IglCNIentyIDQdCgAisDAKIgCUItiKdB/wBxQQV0IgtBqKECaisDAKAgCCAJQoCAgICAgIB4g30iCEKAgICACHxCgICAgHCDvyIAIAtBkKECaisDACIEokQAAAAAAADwv6AiAiAIvyAAoSAEoiIEoCIAIANByKACKwMAoiALQaChAmorAwCgIgMgACADoCIDoaCgIAQgAEHYoAIrAwAiBKIiBiACIASiIgSgoqAgAiAEoiICIAMgAyACoCICoaCgIAAgACAGoiIDoiADIAMgAEGIoQIrAwCiQYChAisDAKCiIABB+KACKwMAokHwoAIrAwCgoKIgAEHooAIrAwCiQeCgAisDAKCgoqAiACACIAIgAKAiAqGgOQMIIAcgAr1CgICAQIO/IgOiIQAgASAFoSADoiAOKwMIIAIgA6GgIAGioCEBAkAgAL1CNIinQf8PcSILQckHa0E/SQ0AIAtByQdJBEAgAEQAAAAAAADwP6AiAJogACAMGwwCCyALQYkISSERQQAhCyARDQAgAL1CAFMEQCMAQRBrIgtEAAAAAAAAAJBEAAAAAAAAABAgDBs5AwggCysDCEQAAAAAAAAAEKIMAgsjAEEQayILRAAAAAAAAADwRAAAAAAAAABwIAwbOQMIIAsrAwhEAAAAAAAAAHCiDAELQZjbASsDACAAokGg2wErAwAiAqAiAyACoSICQbDbASsDAKIgAkGo2wErAwCiIACgoCABoCIAIACiIgEgAaIgAEHQ2wErAwCiQcjbASsDAKCiIAEgAEHA2wErAwCiQbjbASsDAKCiIAO9IgmnQQR0QfAPcSINQYjcAWorAwAgAKCgoCEAIA1BkNwBaikDACAJIAytfEIthnwhCCALRQRAAnwgCUKAgICACINQBEAgCEKAgICAgICAiD99vyIBIACiIAGgRAAAAAAAAAB/ogwBCyAIQoCAgICAgIDwP3wiCL8iASAAoiIDIAGgIgCZRAAAAAAAAPA/YwR8IwBBEGsiCyESIAtEAAAAAAAAEAA5AwggEiALKwMIRAAAAAAAABAAojkDCCAIQoCAgICAgICAgH+DvyAARAAAAAAAAPC/RAAAAAAAAPA/IABEAAAAAAAAAABjGyICoCIFIAMgASAAoaAgACACIAWhoKCgIAKhIgAgAEQAAAAAAAAAAGEbBSAAC0QAAAAAAAAQAKILDAELIAi/IgEgAKIgAaALIQILIA5BEGokACACC8EBAQN/AkAgASACKAIQIgMEfyADBSACENICDQEgAigCEAsgAigCFCIFa0sEQCACIAAgASACKAIkEQMADwsCQCACKAJQQQBIBEBBACEDDAELIAEhBANAIAQiA0UEQEEAIQMMAgsgACADQQFrIgRqLQAAQQpHDQALIAIgACADIAIoAiQRAwAiBCADSQ0BIAAgA2ohACABIANrIQEgAigCFCEFCyAFIAAgARB7GiACIAIoAhQgAWo2AhQgASADaiEECyAECzcBAn8gACgCTEEASARAIAAgASACEKkEDwsgABCCASEEIAAgASACEKkEIQIgBARAIAAQgQELIAILfAECfyAAIAAoAkgiAUEBayABcjYCSCAAKAIUIAAoAhxHBEAgAEEAQQAgACgCJBEDABoLIABBADYCHCAAQgA3AxAgACgCACIBQQRxBEAgACABQSByNgIAQX8PCyAAIAAoAiwgACgCMGoiAjYCCCAAIAI2AgQgAUEbdEEfdQuNAQECfyMAQRBrIgAkACAAQQo6AA8CQAJAQcC6AygCACIBBH8gAQVBsLoDENICDQJBwLoDKAIAC0HEugMoAgAiAUYNAEGAuwMoAgBBCkYNAEHEugMgAUEBajYCACABQQo6AAAMAQtBsLoDIABBD2pBAUHUugMoAgARAwBBAUcNACAALQAPGgsgAEEQaiQAC1kBAX8gACAAKAJIIgFBAWsgAXI2AkggACgCACIBQQhxBEAgACABQSByNgIAQX8PCyAAQgA3AgQgACAAKAIsIgE2AhwgACABNgIUIAAgASAAKAIwajYCEEEAC9MBAgF/AnwgAisDICEFAn8CQCABKwMgIgYgACsDIGRFBEBBACAFIAZkRQ0CGiABIAIQPkEBIAErAyAgACsDIGRFDQIaIAAgARA+DAELIAUgBmQEQCAAIAIQPkEBDAILIAAgARA+QQEgAisDICABKwMgZEUNARogASACED4LQQILIQQgAysDICACKwMgZAR/IAIgAxA+IAIrAyAgASsDIGRFBEAgBEEBag8LIAEgAhA+IAErAyAgACsDIGRFBEAgBEECag8LIAAgARA+IARBA2oFIAQLC34BAX8gACABIAIgAxDTAiEFIAQrAyAgAysDIGQEfyADIAQQPiADKwMgIAIrAyBkRQRAIAVBAWoPCyACIAMQPiACKwMgIAErAyBkRQRAIAVBAmoPCyABIAIQPiABKwMgIAArAyBkRQRAIAVBA2oPCyAAIAEQPiAFQQRqBSAFCwtIAQF/IABBwLMBNgIAIAAoAggiAQRAIAEgASgCACgCBBEBAAsgAEHcqQE2AgAgACgCBCIBBEAgASABKAIAKAIEEQEACyAAEC8L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A0AgBEEEayIEIAFBBGsiASgCADYCACABIAZHDQALCyAHIA0gCyANayIB/AoAACAAIAU2AgggACABIAdqNgIEIAAgBDYCACAGBEAgBhAvCwsPCxA2AAsQRwALIAohBSAEIQELA0AgASAFKAIANgIAIAFBBGohASAFQQRqIgUgC0kNAAsLIAAgATYCBCAEIAlBAnRrIA0gCPwKAAAgDSACIAcgAmv8CgAAC+kaAgl/A3wjAEEQayIDJAADQCABQRBrIQcDQCAAIQQDQAJAAkACQAJAAkACQAJAAkAgASAEayIIQQR1IgkOBgcHAAEEAgMLIAFBEGsiACsDACAEKwMAZEUNBiADIAT9AAMA/QsDACAEIAAoAgg2AgggBCAAKQMANwMAIAAgAygCCDYCCCAAIAMpAwA3AwAMBgsgBEEQaiEAIAFBEGsiASsDACEMIAQrAxAiDSAEKwMAZEUEQCAMIA1kRQ0GIAMgAP0AAwD9CwMAIAAgASgCCDYCCCAAIAEpAwA3AwAgASADKAIINgIIIAEgAykDADcDACAEKwMQIAQrAwBkRQ0GIAMgBP0AAwD9CwMAIAQgACgCCDYCCCAEIAApAwA3AwAgACADKAIINgIIIAAgAykDADcDAAwGCyAMIA1kBEAgAyAE/QADAP0LAwAgBCABKAIINgIIIAQgASkDADcDACABIAMoAgg2AgggASADKQMANwMADAYLIAMgBP0AAwD9CwMAIAQgACgCCDYCCCAEIAApAwA3AwAgACADKAIINgIIIAAgAykDADcDACABKwMAIAQrAxBkRQ0FIAMgAP0AAwD9CwMAIAAgASgCCDYCCCAAIAEpAwA3AwAgASADKAIINgIIIAEgAykDADcDAAwFCyAEIARBEGoiAiAEQSBqIgAgBEEwaiIFENgBGiABQRBrIgErAwAgBCsDMGRFDQQgAyAF/QADAP0LAwAgBSABKAIINgIIIAUgASkDADcDACABIAMoAgg2AgggASADKQMANwMAIAUrAwAgACsDAGRFDQQgAyAA/QADAP0LAwAgACAFKAIINgIIIAAgBSkDADcDACAFIAMoAgg2AgggBSADKQMANwMAIAArAwAgAisDAGRFDQQgAyAC/QADAP0LAwAgAiAAKAIINgIIIAIgACkDADcDACAAIAMoAgg2AgggACADKQMANwMAIAQrAxAgBCsDAGRFDQQgAyAE/QADAP0LAwAgBCACKAIINgIIIAQgAikDADcDACACIAMoAgg2AgggAiADKQMANwMADAQLIAhB7wNMBEAgBEEQaiEAIARBIGohBSAEKwMgIQwCQCAEKwMQIg0gBCsDACIOZEUEQCAMIA1kRQ0BIAMgAP0AAwD9CwMAIAAgBUEIaigCADYCCCAAIAUpAwA3AwAgBSADKAIINgIIIAUgAykDADcDACAAKwMAIA5kRQ0BIAMgBP0AAwD9CwMAIAQgACgCCDYCCCAEIAApAwA3AwAgACADKAIINgIIIAAgAykDADcDAAwBCyAMIA1kBEAgAyAE/QADAP0LAwAgBCAFQQhqKAIANgIIIAQgBSkDADcDACAFIAMoAgg2AgggBSADKQMANwMADAELIAMgBP0AAwD9CwMAIAQgACgCCDYCCCAEIAApAwA3AwAgACADKAIINgIIIAAgAykDADcDACAMIAQrAxBkRQ0AIAMgAP0AAwD9CwMAIAAgBUEIaigCADYCCCAAIAUpAwA3AwAgBSADKAIINgIIIAUgAykDADcDAAsgBEEwaiIGIAFGDQQDQCAGKwMAIgwgBSsDAGQEQCAGKAIIIQcgBiECA0ACQCACIAUiACkDADcDACACIAAoAgg2AgggACAERgRAIAQhAAwBCyAAIQIgDCAAQRBrIgUrAwBkDQELCyAAIAc2AgggACAMOQMACyAGIgVBEGoiACEGIAAgAUcNAAsMBAsgAkUEQCABIARGDQQgCUECa0EBdiIKIQADQAJAIAogACIHSA0AIAQgAEEEdGohBSAEIABBAXQiAkEBciIGQQR0aiEAAkAgCSACQQJqIgJMBEAgBiECDAELIAArAwAgACsDEGRFBEAgBiECDAELIABBEGohAAsgBSsDACIMIAArAwBjDQAgBSgCCCELA0ACQCAFIgYgACIFKQMANwMAIAYgACgCCDYCCCACIApKDQAgBCACQQF0IgJBAXIiBkEEdGohAAJAIAkgAkECaiICTARAIAYhAgwBCyAAKwMAIAArAxBkRQRAIAYhAgwBCyAAQRBqIQALIAArAwAgDGRFDQELCyAFIAs2AgggBSAMOQMACyAHQQFrIQAgB0EASg0ACyAIQQR2IQADQCADIAT9AAMA/QsDACAAIgdBAmtBAXYhCUEAIQIgBCEAA0AgAkEBdCIIQQFyIQUgACIGIAJBBHRqQRBqIQACQCAHIAhBAmoiAkwEQCAFIQIMAQsgACsDACAAKwMQZEUEQCAFIQIMAQsgAEEQaiEACyAGIAApAwA3AwAgBiAAQQhqKAIANgIIIAIgCUwNAAsCQCABQRBrIgEgAEYEQCAAIAMpAwA3AwAgACADKAIINgIIDAELIAAgASkDADcDACAAIAFBCGooAgA2AgggASADKQMANwMAIAEgAygCCDYCCCAAIARrQRBqIgJBEUgNACAAKwMAIgwgBCACQQR2QQJrQQF2IgZBBHRqIggrAwBjRQ0AIAAoAgghBQNAAkAgACAIIgIpAwA3AwAgACACKAIINgIIIAZFDQAgAiEAIAQgBkEBa0EBdiIGQQR0aiIIKwMAIAxkDQELCyACIAU2AgggAiAMOQMACyAHQQFrIQAgB0ECSg0ACwwECyAEIAlBA3RBcHFqIQYCQCAIQfH8AE8EQCAEIAQgCUECdEFwcSIFaiIAIAYgBSAGaiIFENgBIQggBysDACAFKwMAZEUNASADIAX9AAMA/QsDACAFIAcoAgg2AgggBSAHKQMANwMAIAcgAygCCDYCCCAHIAMpAwA3AwAgBSsDACAGKwMAZEUEQCAIQQFqIQgMAgsgAyAG/QADAP0LAwAgBkEIaiAFKAIINgIAIAYgBSkDADcDACAFIAMoAgg2AgggBSADKQMANwMAIAYrAwAgACsDAGRFBEAgCEECaiEIDAILIAMgAP0AAwD9CwMAIAAgBigCCDYCCCAAIAYpAwA3AwAgBiADKAIINgIIIAYgAykDADcDACAAKwMAIAQrAwBkRQRAIAhBA2ohCAwCCyADIAT9AAMA/QsDACAEIAAoAgg2AgggBCAAKQMANwMAIAAgAygCCDYCCCAAIAMpAwA3AwAgCEEEaiEIDAELIAcrAwAhDAJAIAYrAwAiDSAEKwMAZEUEQEEAIQggDCANZEUNAiADIAb9AAMA/QsDACAGQQhqIAcoAgg2AgAgBiAHKQMANwMAIAcgAygCCDYCCCAHIAMpAwA3AwBBASEIIAYrAwAgBCsDAGRFDQIgAyAE/QADAP0LAwAgBCAGKAIINgIIIAQgBikDADcDACAGIAMoAgg2AgggBiADKQMANwMADAELIAwgDWQEQCADIAT9AAMA/QsDACAEIAcoAgg2AgggBCAHKQMANwMAIAcgAygCCDYCCCAHIAMpAwA3AwBBASEIDAILIAMgBP0AAwD9CwMAIAQgBkEIaigCADYCCCAEIAYpAwA3AwAgBiADKAIINgIIIAYgAykDADcDAEEBIQggBysDACAGKwMAZEUNASADIAb9AAMA/QsDACAGIAcoAgg2AgggBiAHKQMANwMAIAcgAygCCDYCCCAHIAMpAwA3AwALQQIhCAsgAkEBayECIAchACAEKwMAIgwgBisDACINZEUEQANAIABBEGsiACAERgRAIARBEGohBSAMIAcrAwBkDQUgBSAHRg0GA0AgBSsDACAMYwRAIAMgBf0AAwD9CwMAIAUgBygCCDYCCCAFIAcpAwA3AwAgByADKAIINgIIIAcgAykDADcDACAFQRBqIQUMBwsgBUEQaiIFIAdHDQALDAYLIAArAwAgDWRFDQALIAMgBP0AAwD9CwMAIAQgAEEIaigCADYCCCAEIAApAwA3AwAgACADKAIINgIIIAAgAykDADcDACAIQQFqIQgLIARBEGoiBSAATw0BA0AgBisDACEMA0AgBSIJQRBqIQUgCSsDACAMZA0ACwNAIABBEGsiACsDACAMZEUNAAsgACAJSQRAIAkhBQwDBSADIAn9AAMA/QsDACAJIABBCGooAgA2AgggCSAAKQMANwMAIAAgAygCCDYCCCAAIAMpAwA3AwAgACAGIAYgCUYbIQYgCEEBaiEIDAELAAsACyAEIARBEGogBEEgaiABQRBrENgBGgwCCwJAIAUgBkYNACAGKwMAIAUrAwBkRQ0AIAMgBf0AAwD9CwMAIAUgBkEIaigCADYCCCAFIAYpAwA3AwAgBiADKAIINgIIIAYgAykDADcDACAIQQFqIQgLIAhFBEAgBCAFELIEIQYgBUEQaiIAIAEQsgQEQCAEIQAgBSEBIAZFDQYMAwsgBg0ECyAFIARrIAEgBWtIBEAgBCAFIAIQ6wIgBUEQaiEADAQLIAVBEGogASACEOsCIAQhACAFIQEMBAsgByIAIAVGDQADQCAEKwMAIQwDQCAFIgZBEGohBSAMIAYrAwBkRQ0ACwNAIAwgAEEQayIAKwMAZA0ACyAAIAZNBEAgBiEEDAMFIAMgBv0AAwD9CwMAIAYgAEEIaigCADYCCCAGIAApAwA3AwAgACADKAIINgIIIAAgAykDADcDAAwBCwALAAsLCwsgA0EQaiQACwkAQcEdELcBAAuSCQEEf0EEEDIiBEHspQE2AgBBCBAyIgNByKgBNgIAIAMgBDYCBEEQEDIiBCADNgIMIARBxKYBNgIAIARCADcCBCAAIAM2AhwgACgCICEDIAAgBDYCIAJAIANFDQAgA0F//h4CBA0AIAMgAygCACgCCBEBAAJAIANBCGoiBP4QAgAEQCAEQX/+HgIADQELIAMgAygCACgCEBEBAAsLIAAgACgCHDYCJAJAAkACQAJAIAAoAgxB8AdxIgNB/wBNBEAgA0EQaw4RAwICAgICAgICAgICAgICAgQBCwJAIANBgAFHBEAgA0GAAkYNASADQYAERw0DIAAgASACEOUCDwsgACIDKAIkIQYCQAJAIAEgAkYNACABIQACQANAIAAtAABBCkYNASAAQQFqIgAgAkcNAAsgAiEACyAAIAFGDQAgAyABIAAQ5AIaIAAhAQwBC0EIEDIhACAGKAIEIQQgAEHIqAE2AgAgACAENgIEIAYgADYCBCADIAMoAiQoAgQ2AiQLIAIgASABIAJHaiIBRwRAA0AgASEAAkADQCAALQAAQQpGDQEgAEEBaiIAIAJHDQALIAIhAAsgAygCJCEEAkAgACABRwRAIAMgASAAEOQCGgwBC0EIEDIhASAEKAIEIQUgAUHIqAE2AgAgASAFNgIEIAQgATYCBCADIAMoAiQoAgQ2AiQLQQwQMiEBIAYoAgQhBSABIAQoAgQ2AgggASAFNgIEIAFBnLQBNgIAIAYgATYCBCAEQQA2AgRBCBAyIQEgAygCJCgCBCEFIAFByKgBNgIAIAEgBTYCBCAEIAE2AgQgAygCJEEANgIEQQgQMiEBIAQoAgQhBSABQdy0ATYCACABIAU2AgQgAygCJCABNgIEIAMgBCgCBDYCJCAAIAAgAkdqIgEgAkcNAAsLIAIPCyAAIgMoAiQhBgJAAkAgASACRg0AIAEhAAJAA0AgAC0AAEEKRg0BIABBAWoiACACRw0ACyACIQALIAAgAUYNACADIAEgABCGAhogACEBDAELQQgQMiEAIAYoAgQhBCAAQcioATYCACAAIAQ2AgQgBiAANgIEIAMgAygCJCgCBDYCJAsgAiABIAEgAkdqIgFHBEADQCABIQACQANAIAAtAABBCkYNASAAQQFqIgAgAkcNAAsgAiEACyADKAIkIQQCQCAAIAFHBEAgAyABIAAQhgIaDAELQQgQMiEBIAQoAgQhBSABQcioATYCACABIAU2AgQgBCABNgIEIAMgAygCJCgCBDYCJAtBDBAyIQEgBigCBCEFIAEgBCgCBDYCCCABIAU2AgQgAUGctAE2AgAgBiABNgIEIARBADYCBEEIEDIhASADKAIkKAIEIQUgAUHIqAE2AgAgASAFNgIEIAQgATYCBCADKAIkQQA2AgRBCBAyIQEgBCgCBCEFIAFB3LQBNgIAIAEgBTYCBCADKAIkIAE2AgQgAyAEKAIENgIkIAAgACACR2oiASACRw0ACwsgAg8LIANBwABGDQILQQwQXkEOEHBB0KkDQdIAEAIACyAAIAEgAhDkAg8LIAAgASACEIYCC/gLAhF/AX4jAEEQayINJAAQaSEXAn8CQAJAIAIoAgAiCiABKAJQIgtNBEAgACgCICEQIAEoAlghCSABKAJMIQwgCkUNAQNAQQAhBiALIAogDGpJBEAgAUEANgJMIAsgDGsgCGohCEEAIQwMAQsCQANAIAZBAWohByAJIAYgDGpBBHRqKAIAQQBODQEgByIGIApHDQALIAIoAgwhCANAIAwgEWpBBHQiFSABKAJYaiARQQJ0IhIgAigCCGooAgA2AgBBACETIAggEmooAgBBAEoEQANAIAIoAhAgEmooAgAgE0ECdGooAgAhFCABKAJYIBVqIg9BCGoiDiEJAkACQCAOIgYoAgAiB0UNAANAIAciBigCECIHIBRKBEAgBiEJIAYoAgAiBw0BDAILIAcgFE4NAiAGKAIEIgcNAAsgBkEEaiEJC0EUEDIiCCAGNgIIIAhCADcCACAIIBQ2AhAgCSAINgIAIA8oAgQoAgAiBgRAIA8gBjYCBCAJKAIAIQgLIAggCCAOKAIAIg5GIgY6AAwCQCAGDQADQCAIKAIIIgctAAwNAQJAIAcgBygCCCIGKAIAIglGBEACQCAGKAIEIglFDQAgCS0ADA0ADAILAkAgCCAHKAIARgRAIAchCQwBCyAHIAcoAgQiCSgCACIINgIEIAkgCAR/IAggBzYCCCAHKAIIBSAGCzYCCCAHKAIIIgYgBigCACAHR0ECdGogCTYCACAJIAc2AgAgByAJNgIIIAkoAggiBigCACEHCyAJQQE6AAwgBkEAOgAMIAYgBygCBCIINgIAIAgEQCAIIAY2AggLIAcgBigCCDYCCCAGKAIIIgggCCgCACAGR0ECdGogBzYCACAHIAY2AgQgBiAHNgIIDAMLAkAgCUUNACAJLQAMDQAMAQsCQCAIIAcoAgBHBEAgByEIDAELIAcgCCgCBCIJNgIAIAggCQR/IAkgBzYCCCAHKAIIBSAGCzYCCCAHKAIIIgYgBigCACAHR0ECdGogCDYCACAIIAc2AgQgByAINgIIIAgoAgghBgsgCEEBOgAMIAZBADoADCAGIAYoAgQiBygCACIINgIEIAgEQCAIIAY2AggLIAcgBigCCDYCCCAGKAIIIgggCCgCACAGR0ECdGogBzYCACAHIAY2AgAgBiAHNgIIDAILIAdBAToADCAGIAYgDkY6AAwgCUEBOgAMIA4gBiIIRw0ACwsgDyAPKAIMQQFqNgIMIAIoAgwhCAsgE0EBaiITIAggEmooAgBIDQALCyARQQFqIhEgCkcNAAsgASgCWCEJDAQLIAEgByAMaiIMNgJMIAcgCGoiCCALSQ0AC0EADAMLIA0gCzYCCCANIAo2AgQgDUGKCzYCAEECQbvqACANEDRBAAwCCyALIAxPDQAgAUEANgJMCwJAIAtBAWsiBgRAA0AgCSAGQQR0aiIHKAIAQQBOBEAgBygCDA0DCyAGIgtBAWsiBg0ACwtBASELCyABIAs2AlQgASgC0KcBEJICIAAgASACENoEIQYgASgC0KcBIAYQ2gEgBigCDCAGKAIEQQJ0akEEaygCACEHIAEoApCnASIAKAIAQTxGBEAgACADEJECCyABQYSoAWohAyAAIAYgACgCLBECACAAKAIcIgYEQCAAIAYRAQALAkAgCiAQbCIAIAFBiKgBaigCACABKAKEqAEiCGtBAnUiBksEQCADIAAgBmsQbgwBCyAAIAZPDQAgASAIIABBAnRqNgKIqAELIApBAEoEQCAQQQJ0IQBBACEGA0AgAigCFCAGai0AAARAIAcgBiAQbEECdCIIIAMoAgBqIAggABDmBAsgBkEBaiIGIApHDQALCwJAIAIoAgAiAEEBRgRAIAEQaSAXfSABKQMQfDcDECABIAEoAjhBAWo2AjgMAQsQaSAXfSEXIABBD0wEQCABIBcgASkDGHw3AxggASABKAI8IApqNgI8DAELIAEgFyABKQMgfDcDICABIAEoAkAgCmo2AkALQQEgBEUNABogBSAEEQAAQQFzCyEWIA1BEGokACAWC7oNAQx/AkAgACgCBCIDRQ0AIAJBACACQQBKGyEMIAAoAgwhBwJAIAFBAEgEQCADIQgDQAJAIAcgCUEEdCICaiIBKAIAIgUgDEgNACAFQf////8HRg0AIAFBBGogAUEIaiIDKAIAEJYBIAEgAzYCBCABQgA3AgggACgCBCEDIAAoAgwiByACaiIBKAIMDQAgAUF/NgIAIAkgCCADIAhGGyEICyAJQQFqIgkgA0kNAAsMAQsgAyEIA0ACQCAHIAlBBHQiDWoiBigCACICIAxIDQAgAkH/////B0YNACAGQQhqIgohBCAKKAIAIgUhAiAFRQ0AA0AgBCACIAIoAhAgAUgiCxshBCACQQRqIAIgCxsoAgAiAg0ACyAEIApGDQAgBCgCECABSg0AIAZBCGoiCiEEIAUhAgNAIAQgAiACKAIQIAFIIgsbIQQgAkEEaiACIAsbKAIAIgINAAsCQCAEIApGDQAgBCgCECABSg0AAkAgBCIDKAIEIgcEQANAIAciAigCACIHDQAMAgsACwNAIAMoAggiAigCACADRyEOIAIhAyAODQALCyAEIAYoAgRGBEAgBiACNgIECyAGIAYoAgxBAWs2AgwCfwJAIAQiByIDKAIAIgQEQCADKAIEIgJFDQEDQCACIgMoAgAiAg0ACwsgAygCBCIEDQBBACEEQQEMAQsgBCADKAIINgIIQQALIQoCQCADIAMoAggiBigCACICRgRAIAYgBDYCACADIAVGBEBBACECIAQhBQwCCyAGKAIEIQIMAQsgBiAENgIECyADLQAMIQsgAyAHRwRAIAMgBygCCCIGNgIIIAYgBygCCCgCACAHR0ECdGogAzYCACADIAcoAgAiBjYCACAGIAM2AgggAyAHKAIEIgY2AgQgBgRAIAYgAzYCCAsgAyAHLQAMOgAMIAMgBSAFIAdGGyEFCwJAIAtFDQAgBUUNACAKBEADQCACLQAMIQQCQCACIAIoAggiAygCAEcEQCAERQRAIAJBAToADCADQQA6AAwgAyADKAIEIgQoAgAiBjYCBCAGBEAgBiADNgIICyAEIAMoAgg2AgggAygCCCIGIAYoAgAgA0dBAnRqIAQ2AgAgBCADNgIAIAMgBDYCCCACIAUgBSACKAIAIgJGGyEFIAIoAgQhAgsCQAJAAkACQCACKAIAIgMEQCADLQAMRQ0BCyACKAIEIgQEQCAELQAMRQ0CCyACQQA6AAwCQCAFIAIoAggiAkYEQCAFIQIMAQsgAi0ADA0GCyACQQE6AAwMCAsgAigCBCIERQ0BCyAELQAMDQAgAiEDDAELIANBAToADCACQQA6AAwgAiADKAIEIgU2AgAgBQRAIAUgAjYCCAsgAyACKAIINgIIIAIoAggiBSAFKAIAIAJHQQJ0aiADNgIAIAMgAjYCBCACIAM2AgggAiEECyADIAMoAggiAi0ADDoADCACQQE6AAwgBEEBOgAMIAIgAigCBCIDKAIAIgU2AgQgBQRAIAUgAjYCCAsgAyACKAIINgIIIAIoAggiBSAFKAIAIAJHQQJ0aiADNgIAIAMgAjYCACACIAM2AggMBAsgBEUEQCACQQE6AAwgA0EAOgAMIAMgAigCBCIENgIAIAQEQCAEIAM2AggLIAIgAygCCDYCCCADKAIIIgQgBCgCACADR0ECdGogAjYCACACIAM2AgQgAyACNgIIIAIgBSADIAVGGyEFIAMoAgAhAgsCQAJAIAIoAgAiBEUNACAELQAMDQAgAiEDDAELAkAgAigCBCIDBEAgAy0ADEUNAQsgAkEAOgAMIAIoAggiAi0ADEEAIAIgBUcbDQIgAkEBOgAMDAULIAQEQCAELQAMRQRAIAIhAwwCCyACKAIEIQMLIANBAToADCACQQA6AAwgAiADKAIAIgU2AgQgBQRAIAUgAjYCCAsgAyACKAIINgIIIAIoAggiBSAFKAIAIAJHQQJ0aiADNgIAIAMgAjYCACACIAM2AgggAiEECyADIAMoAggiAi0ADDoADCACQQE6AAwgBEEBOgAMIAIgAigCACIDKAIEIgU2AgAgBQRAIAUgAjYCCAsgAyACKAIINgIIIAIoAggiBSAFKAIAIAJHQQJ0aiADNgIAIAMgAjYCBCACIAM2AggMAwsgAigCCCIDIAMoAgAgAkZBAnRqKAIAIQIMAAsACyAEQQE6AAwLIAcQLyAAKAIEIQMgACgCDCEHCyAHIA1qIgIoAgwNACACQX82AgAgCSAIIAMgCEYbIQgLIAlBAWoiCSADSQ0ACwsgAyAIRg0AIAAgCDYCAAsLiwIBB38gAEEEaiEGAkACQCAAKAIEIgBFDQAgASgCACABIAEtAAsiA8BBAEgiAhshBSABKAIEIAMgAhshAyAGIQEDQAJAIAMgACgCFCAALQAbIgIgAsBBAEgiBBsiAiACIANLIgcbIggEQCAAKAIQIABBEGogBBsgBSAIEEoiBA0BC0F/IAcgAiADSRshBAsgASAAIARBAEgiAhshASAAQQRqIAAgAhsoAgAiAA0ACyABIAZGDQACQCABKAIUIAEtABsiACAAwEEASCICGyIAIAMgACADSRsiBARAIAUgASgCECABQRBqIAIbIAQQSiIFDQELIAAgA0sNAQwCCyAFQQBODQELIAYhAQsgAQvOAwELfyABIAAoAggiBCAAKAIEIgJrTQRAIAAgAQR/IAJBACAB/AsAIAEgAmoFIAILNgIEDwsgAiAAKAIAIgVrIgYgAWoiA0EATgRAQf////8HIAQgBWsiBEEBdCIIIAMgAyAISRsgBEH/////A08bIgQEQCAEEDIhBwsgBiAHaiIDQQAgAfwLACAEIAdqIQggASADaiEJAkAgAiAFRgRAIAMhBwwBCwJAAkAgBkEQSQ0AIAUgAiAHamsgAmpBEEkNACADQRBrIQogAkEQayELIAIgBkFwcSIEayECIAMgBGshA0EAIQEDQCAKIAFrIAsgAWv9AAAA/QsAACABQRBqIgEgBEcNAAsgBCAGRg0BCyAFQX9zIAJqIQwgAiAFa0EDcSIEBEBBACEBA0AgA0EBayIDIAJBAWsiAi0AADoAACABQQFqIgEgBEcNAAsLIAxBA0kNAANAIANBAWsgAkEBay0AADoAACADQQJrIAJBAmstAAA6AAAgA0EDayACQQNrLQAAOgAAIANBBGsiAyACQQRrIgItAAA6AAAgAiAFRw0ACwsgACgCACECCyAAIAg2AgggACAJNgIEIAAgBzYCACACBEAgAhAvCw8LEDYAC5AFAQR/IAAoAsyoASIBBEAgAEHQqAFqIAE2AgAgARAvCyAALAC3qAFBAEgEQCAAKAKsqAEQLwsgACgCnKgBIgEEQCAAQaCoAWogATYCACABEC8LIAAoApCoASIDBEAgAEGUqAFqKAIAIgIgAyIBRwRAA0AgAkEwayIBKAIcIgQEQCACQRBrIAQ2AgAgBBAvCyACQRVrLAAAQQBIBEAgAkEgaygCABAvCyABIgIgA0cNAAsgACgCkKgBIQELIAAgAzYClKgBIAEQLwsgACgChKgBIgEEQCAAQYioAWogATYCACABEC8LIAAoAvinASIBBEAgAEH8pwFqIAE2AgAgARAvCyAAKALspwEiAQRAIABB8KcBaiABNgIAIAEQLwsgAEHUpwFqKAIAIgEEQCAAQdinAWogATYCACABEC8LIABBwKcBaigCACIBBEAgAEHEpwFqIAE2AgAgARAvCyAAQaynAWooAgAiAQRAIABBsKcBaiABNgIAIAEQLwsgAEGYpwFqKAIAIgEEQCAAQZynAWogATYCACABEC8LIABBuJIBahClASAAQeD9AGoQpQEgAEGI6QBqEKUBIABBsNQAahClASAAQdg/ahClASAAQYArahClASAAQagWahClASAAQdABahClASAAKAKoASIBBEAgACABNgKsASABEC8LIAAoAoABIgMEQCAAKAKEASICIAMiAUcEQANAIAJBDGsgAkEQayICKAIIEJYBIAIgA0cNAAsgACgCgAEhAQsgACADNgKEASABEC8LIAAoAlgiAwRAIAAoAlwiAiADIgFHBEADQCACQQxrIAJBEGsiAigCCBCWASACIANHDQALIAAoAlghAQsgACADNgJcIAEQLwsgAAtDACABBEAgACABKAIAEPMCIAAgASgCBBDzAiABLAArQQBIBEAgASgCIBAvCyABLAAbQQBIBEAgASgCEBAvCyABEC8LCzEAIAEEQCAAIAEoAgAQ9AIgACABKAIEEPQCIAEsAB9BAEgEQCABKAIUEC8LIAEQLwsLmUgEF34XfwR7AX0jAEGQAWsiIyQAAkACQAJAAkACQAJAAkACQAJAAkACQAJAIAEoAjAiHSABKAIAIhpBJGwiG0GYmwFqKAIARyImDQAgATUCNCIDIAEpAxAgHa1+IBtBlJsBajQCAH9SDQAgATUCOCIFIAEpAxggA35SDQAgATUCPCABKQMgIAV+Ug0AIAIoAjAiGyACKAIAIhxBJGwiIkGYmwFqKAIARw0AIAI1AjQiAyACKQMQIButfiAiQZSbAWo0AgB/Ug0AIAI1AjgiBSACKQMYIAN+Ug0AIBogHEcNACACNQI8IAIpAyAgBX5RDQELAkACQAJAIBoOAgIAAQsgAikDKCIRIAIpAyAiDyACKQMYIhAgAikDECIMfn5+IAEpAygiDSABKQMgIgcgASkDGCIOIAEpAxAiCX5+flEEQAJAIAAoAgAOAw0ADQALIAIoAjwhISACKAI4IR8gAigCNCElIAEoAjwhKCABKAI4ISQgASgCNCEiIAAoAgghGyAAKAIEIScgAigCMCEaAkAgJg0AICKtIgMgCSAdrX5SDQAgJK0iBSADIA5+Ug0AICitIAUgB35SDQAgGiACKAIAIhxBJGwiHkGYmwFqKAIARw0AICWtIgMgDCAarX4gHkGUmwFqNAIAf1INACAfrSIFIAMgEH5SDQAgIa0gBSAPflINACAcQQFGDQQLIA6nIh4gG2pBAWsgG20iKSAnbCIbIClqIhwgHiAcIB5IGyEcIAIoAgAhIAJAICYNACAJIAxSDQAgIEEBRw0AIBogHUcNACANQgBXDQ0gB0IAVw0NIBsgHE4NDSAdIAynbCEAIBysIQsgG6whBQNAICggBKciGmwhGyAaICFsIRpCACEGA0AgJCAGpyIdbCEcIB0gH2whHSAFIQMDQCACKALQASAlIAOnIh5saiAdaiAaaiABKALQASAeICJsaiAcaiAbaiAA/AoAACADQgF8IgMgC1INAAsgBkIBfCIGIAdSDQALIARCAXwiBCANUg0ACwwNCyAaICBBJGwiJkGYmwFqKAIARw0IICWtIgMgDCAarX4gJkGUmwFqNAIAIgV/Ug0IIB+tIgsgAyAQflINCCAhrSALIA9+Ug0IIB1BAkcNCQJAICAOAgwACwsgDUIAVw0MIAdCAFcNDCACKALQASEdIBsgCaciAkEBdCIAbCEhIB4gHGsgAGwhHyAHpyAbIB5qIBxrbCACbEEBdCElIBsgImwhJiAcIBtrQQFxISdBACECIBwgG0EBaiIpRiEqA0ACQCAbIBxIBEAgKCAIp2whHkIAIQMDQCACICFqIRogJCADp2whICAnBH8gGiAdaiABKALQASAmaiAgaiAeaiAA/AoAACAAIBpqIRogKQUgGwshAiAqRQRAA0AgGiAdaiABKALQASACICJsaiAgaiAeaiAA/AoAACAdIAAgGmoiGmogASgC0AEgAkEBaiAibGogIGogHmogAPwKAAAgACAaaiEaIAJBAmoiAiAcRw0ACwsgGiAfaiECIANCAXwiAyAHUg0ACwwBCyACICVqIQILIAhCAXwiCCANUg0ACwwMC0G8wwIoAgAQMBogI0H42QA2AkggI0GXMjYCRCAjQeQmNgJAQbjDAigCAEHL5AAgI0FAaxAxDAwLQbzDAigCABAwGiAjQZshNgIIICNBrjY2AgQgI0HkJjYCAEG4wwIoAgBBy+QAICMQMQwLCyACKQMoIhEgAikDICIPIAIpAxgiECACKQMQIgx+fn4gASkDKCIOIAEpAyAiDSABKQMYIgMgASkDECIHfn5+Ug0CAkAgACgCAA4DCgAKAAsgAigCPCEkIAIoAjghICACKAI0ISEgASgCPCEeIAEoAjghKCABKAI0ISIgACgCCCEbIAAoAgQhJSACKAIwIRogJg0BICKtIgUgByAdrX5SDQEgKK0iCyADIAV+Ug0BIB6tIAsgDX5SDQEgGiACKAIAIhxBJGwiH0GYmwFqKAIARw0BICGtIgUgDCAarX4gH0GUmwFqNAIAf1INASAgrSILIAUgEH5SDQEgJK0gCyAPflINASAcDQELIwBBMGsiGiQAAkACQAJAIAIpAyggAikDICIDIAIpAxgiBSACKQMQIgt+fn4iCSABKQMoIAEpAyAiBCABKQMYIgYgASkDECIIfn5+UQRAIAIoAjAiHSACKAIAIhxBJGwiG0GYmwFqKAIARw0BIAI1AjQiCiALIB2tfiAbQZSbAWo0AgB/Ug0BIAI1AjgiCyAFIAp+Ug0BIAI1AjwgAyALflINASABKAIwIhsgASgCACIiQSRsIh5BmJsBaigCAEcNASABNQI0IgMgCCAbrX4gHkGUmwFqNAIAf1INASABNQI4IgUgAyAGflINASABNQI8IAQgBX5SDQEgHCAiRw0CAkACQCAAKAIADgMBAAEACyAJpyIcIAAoAggiImpBAWsgIm0iIiAAKAIEbCIAICJqIiIgHCAcICJKGyIcIABMDQAgAigC0AEgACAdbGogASgC0AEgACAbbGogHCAAayAbbPwKAAALIBpBMGokAAwDC0G8wwIoAgAQMBogGkH42QA2AiggGkH3MTYCJCAaQeQmNgIgQbjDAigCAEHL5AAgGkEgahAxEAAAC0G8wwIoAgAQMBogGkHE2QA2AhggGkH4MTYCFCAaQeQmNgIQQbjDAigCAEHL5AAgGkEQahAxEAAAC0G8wwIoAgAQMBogGkGWIjYCCCAaQfkxNgIEIBpB5CY2AgBBuMMCKAIAQcvkACAaEDEQAAALDAgLIAOnIh8gG2pBAWsgG20iJyAlbCIbICdqIgAgHyAAIB9IGyEcIAIoAgAhAAJAICYNACAHIAxSDQAgAA0AIBogHUcNACAOQgBXDQggDUIAVw0IIBsgHE4NCCAdIAynbCEAIBysIQsgG6whBQNAIB4gBKciGmwhGyAaICRsIRpCACEGA0AgKCAGpyIdbCEcIB0gIGwhHSAFIQMDQCACKALQASAhIAOnIh9saiAdaiAaaiABKALQASAfICJsaiAcaiAbaiAA/AoAACADQgF8IgMgC1INAAsgBkIBfCIGIA1SDQALIA4gBEIBfCIEUg0ACwwICwJAIBogAEEkbCImQZibAWooAgBHDQAgIa0iBSAMIBqtfiAmQZSbAWo0AgAiC39SDQAgIK0iCSAFIBB+Ug0AICStIAkgD35SDQAgHUEERgRAIABFBEAgDkIAVw0KIA1CAFcNCiAbIBxODQogAigC0AEhHSAbIAenQQJ0IgBsISEgHyAcayAAbCEfIBsgImwhJSAcIBtrQQFxISZBACECIBwgG0EBaiInRiEpA0AgHiAIp2whJEIAIQMDQCACICFqIRogKCADp2whICAmBH8gGiAdaiABKALQASAlaiAgaiAkaiAA/AoAACAAIBpqIRogJwUgGwshAiApRQRAA0AgGiAdaiABKALQASACICJsaiAgaiAkaiAA/AoAACAdIAAgGmoiGmogASgC0AEgAkEBaiAibGogIGogJGogAPwKAAAgACAaaiEaIAJBAmoiAiAcRw0ACwsgGiAfaiECIANCAXwiAyANUg0ACyAOIAhCAXwiCFINAAsMCgtBsYAcIAB2QQFxRQRAIAcgC38hAyAOQgBXDQogDUIAVw0KIBsgHE4NCiAAQSRsQaSbAWooAgAhHSACKALQASEkIBogA6dsIhogG2whJSAaIB8gHGtsISYgB6chICAbQQFqIScgGyAibCEpIBwgG2siKkEBcSErQQAhAANAIB4gCKdsISFCACEDA0AgACAlaiECICggA6dsIR8gKwR/IAEoAtABIClqIB9qICFqIAIgJGogICAdEQUAIAIgGmohAiAnBSAbCyEAICpBAUcEQANAIAEoAtABIAAgImxqIB9qICFqIAIgJGogICAdEQUAIAEoAtABIABBAWogImxqIB9qICFqICQgAiAaaiICaiAgIB0RBQAgAiAaaiECIABBAmoiACAcRw0ACwsgAiAmaiEAIANCAXwiAyANUg0ACyAOIAhCAXwiCFINAAsMCgtBvMMCKAIAEDAa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KAIMNgIAIAhBEGokAA8LEE0ACw0AIAAgASABEGgQywELIAAgAEHotQM2AgAgAEHYtgM2AgAgAEEEaiABEIoDIAALPQECfyABEGgiA0ENahAyIgJBADYCCCACIAM2AgQgAiADNgIAIAJBDGoiAiABIANBAWr8CgAAIAAgAjYCAAsSACAAKAIAIAEoAgAQnwFBH3YLgAMCBX8DfiMAQdAAayIDJAACQAJAIAEpAyAiCCACKQMYUQRAIAIpAyhCAVINASACKAIAQRJHDQICfwJAIAEoAogBDQAgAigCiAENAEEADAELQQELIQcgASkDECEJIAIpAxAhCiADIAIpAyA3A0ggAyAINwNAIAMgCjcDOCADIAk3AzAgAEEAQQQgA0EwakEAQQAQSSIEQSI2AkAgBwRAIAAgBCgCACAEKAIMIARBEGpBAEEAEEkhBQsgBCABNgKMASAEIAU2AogBIAQgAjYCkAEgA0HQAGokACAEDwtBvMMCKAIAEDAaIANBkyo2AiggA0GRJTYCJCADQeQmNgIgQbjDAigCAEHL5AAgA0EgahAxEAAAC0G8wwIoAgAQMBogA0HLPjYCGCADQZIlNgIUIANB5CY2AhBBuMMCKAIAQcvkACADQRBqEDEQAAALQbzDAigCABAwGiADQfE7NgIIIANBkyU2AgQgA0HkJjYCAEG4wwIoAgBBy+QAIAMQMRAAAAsMACAAEJQCGiAAEC8LCQAgACABEJQECwcAIAAQUhoLCAAgABCmAhoLFgAgACABIAJCgICAgICAgICAfxDgAwsJACAAEEQ2AgALIwECfyAAIQEDQCABIgJBBGohASACKAIADQALIAIgAGtBAnULBwAgACgCBAswACMAQRBrIgIkAAJAIAAgAUYEQCABQQA6AHgMAQsgAkEPaiABEJsDCyACQRBqJAALJgEBfyAAKAIEIQIDQCABIAJHBEAgAkEEayECDAELCyAAIAE2AgQLSwEBfyMAQRBrIgMkAAJAAkAgAkEeSw0AIAEtAHgNACABQQE6AHgMAQsgA0EPaiACEJ0DIQELIANBEGokACAAIAI2AgQgACABNgIAC18BBX8jAEEQayIAJAAgAEH/////AzYCDCAAQf////8HNgIIIwBBEGsiASQAIABBCGoiAigCACAAQQxqIgMoAgBJIQQgAUEQaiQAIAIgAyAEGygCACEF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AyAAIAJBAWo2AgggAiABQQx2QeABcjoAACAAIAAoAggiAkEBajYCCCACIAFBBnZBP3FBgAFyOgAAIAAgACgCCCICQQFqNgIIIAIgAUE/cUGAAXI6AAALIAAgACgCDEECaiICNgIMDAELC0ECDAILQQEMAQsgBQshCSAEIAAoAgw2AgAgByAAKAIINgIAIABBEGokACAJCz4BA38jAEEQayIBJAAgASAANgIMIAFBCGogAUEMahB/IQNBBEEBIwMoAmAoAgAbIQIgAxB+IAFBEGokACACCzwBAn8jAEEQayIFJAAgBSAENgIMIAVBCGogBUEMahB/IQYgACABIAIgAxDwASEAIAYQfiAFQRBqJAAgAAsSACAEIAI2AgAgByAFNgIAQQMLKAEBfyAAQdzsAjYCAAJAIAAoAggiAUUNACAALQAMRQ0AIAEQLwsgAAsEACABC0ABAn8gACgCACgCACIAKAIAIAAoAggiAkEBdWohASAAKAIEIQAgASACQQFxBH8gASgCACAAaigCAAUgAAsRAQALLgAgASAAQQhqIgAoAgQgACgCACIAa0ECdUkEfyABQQJ0IABqKAIAQQBHBUEACwvLAQEDfyAAQcjsAjYCACAAQQhqIQMDQCACIAAoAgwgACgCCCIBa0ECdUkEQCACQQJ0IAFqKAIAIgEEQCABQQRqQX/+HgIARQRAIAEgASgCACgCCBEBAAsLIAJBAWohAgwBCwsgAEGYAWoQMxojAEEQayICJAAgAiADNgIMIAIoAgwiASgCBBogASgCCBogASgCABogASgCAARAIAEQsAMgAigCDEEQaiACKAIMIgEoAgAgASgCCCABKAIAa0ECdRCVAwsgAkEQaiQAIAALDAAgACAAKAIAEJYDC3ABAX8jAEEQayICJAAgAiAANgIEIAIgACgCBCIANgIIIAIgACABQQJ0ajYCDCACKAIIIQEgAigCDCEAA0AgACABRgRAIAIoAgQgAigCCDYCBCACQRBqJAAFIAFBADYCACACIAFBBGoiATYCCAwBCwsLIAAgAEGY9QI2AgAgACgCCBBERwRAIAAoAggQ4wMLIAALBABBfwvgAQEIfyMAQRBrIgUkACMAQSBrIgMkACADQRhqIAAgARCaAyADQRBqIANBDGogAygCGCADKAIcIAIQvAIgAygCECEEIwBBEGsiASQAIAEg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DUIANwIAIA1BADYCCCABQRBqJAAjAEEQayIBJAAgC0EkaiIMQgA3AgAgDEEANgIIIAFBEGokACMAQRBrIgEkACALQRhqIhBCADcCACAQQQA2AgggAUEQaiQAIwBBEGsiCiQAIAsCfyACBEAgCkEEaiICIAMQuwMiASABKAIAKAIsEQIAIAsgCigCBDYAXCACIAEgASgCACgCIBECACAMIAIQiAEgAhBQGiACIAEgASgCACgCHBECACANIAIQiAEgAhBQGiALIAEgASgCACgCDBEAADYCWCALIAEgASgCACgCEBEAADYCVCACIAEgASgCACgCFBECACAPIAIQZSACEDMaIAIgASABKAIAKAIYEQIAIA4gAhCIASACEFAaIAEgASgCACgCJBEAAAwBCyAKQQRqIgIgAxC6AyIBIAEoAgAoAiwRAgAgCyAKKAIENgBcIAIgASABKAIAKAIgEQIAIAwgAhCIASACEFAaIAIgASABKAIAKAIcEQIAIA0gAhCIASACEFAaIAsgASABKAIAKAIMEQAANgJYIAsgASABKAIAKAIQEQAANgJUIAIgASABKAIAKAIUEQIAIA8gAhBlIAIQMxogAiABIAEoAgAoAhgRAgAgDiACEIgBIAIQUBogASABKAIAKAIkEQAACzYCFCAKQRBqJAAgCSAIKAIANgIAIARBgARxIRJBACEDQQAhAQNAIAEhAgJAAkACQAJAIANBBEYNACAAIAtBjARqEEINAEEAIQoCQAJAAkACQAJAAkAgC0HcAGogA2osAAAOBQEABAMFCQsgA0EDRg0HIAdBAQJ/IAAoAgAiASgCDCIEIAEoAhBGBEAgASABKAIAKAIkEQAADAELIAQoAgALIAcoAgAoAgwRAwAEQCALQQxqIAAQvAMgECALKAIMEKECDAILIAUgBSgCAEEEcjYCAEEAIQAMBgsgA0EDRg0GCwNAIAAgC0GMBGoQQg0GIAdBAQJ/IAAoAgAiASgCDCIEIAEoAhBGBEAgASABKAIAKAIkEQAADAELIAQoAgALIAcoAgAoAgwRAwBFDQYgC0EMaiAAELwDIBAgCygCDBChAgwACwALAkACfyANLQALQQd2BEAgDSgCBAwBCyANLQALQf8AcQtFDQACfyAAKAIAIgEoAgwiBCABKAIQRgRAIAEgASgCACgCJBEAAAwBCyAEKAIACwJ/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CyADKAIACwJ/IAItAAtBB3YEQCACKAIADAELIAILIApBAnRqKAIARg0BCyAFIAUoAgBBBHI2AgBBACEADAMLIAAQXBogCkEBaiEKDAALAAtBASEAIBEoAgAgCygCZEYNAEEAIQAgC0EANgIMIA8gESgCACALKAJkIAtBDGoQZCALKAIMBEAgBSAFKAIAQQRyNgIADAELQQEhAAsgEBBQGiAMEFAaIA0QUBogDhBQGiAPEDMaIBEoAgAhASARQQA2AgAgAQRAIAEgESgCBBEBAAsMAwsgAiEBCyADQQFqIQMMAAsACyALQZAEaiQAIAALOQECfyABKAIAIQMgAUEANgIAIAAoAgAhAiAAIAM2AgAgAgRAIAIgACgCBBEBAAsgACABKAIENgIECwoAIABBoIk1EHkLCgAgAEGoiTUQeQvkAQEGfyMAQRBrIgUkACAAKAIEIQNBAQJ/IAIoAgAgACgCAGsiBEH/////B0kEQCAEQQF0DAELQX8LIgQgBEEBTRshBCABKAIAIQcgACgCACEIIANB9wFGBH9BAAUgACgCAAsgBBDEASIGBEAgA0H3AUcEQCAAKAIAGiAAQQA2AgALIAVB9gE2AgQgACAFQQhqIAYgBUEEahBRIgMQvgMgAygCACEGIANBADYCACAGBEAgBiADKAIEEQEACyABIAAoAgAgByAIa2o2AgAgAiAEIAAoAgBqNgIAIAVBEGokAA8LEEYACyABAX8gASgCABD9A8AhAiAAIAEoAgA2AgQgACACOgAAC6kZAQl/IwBBkARrIgskACALIAo2AogEIAsgATYCjAQCQCAAIAtBjARqEEMEQCAFIAUoAgBBBHI2AgBBACEADAELIAtB9wE2AkwgCyALQegAaiALQfAAaiALQcwAaiIPEFEiESgCACIBNgJkIAsgAUGQA2o2AmAjAEEQayIBJAAgD0IANwIAIA9BADYCCCABQRBqJAAjAEEQayIBJAAgC0FAayIOQgA3AgAgDkEANgIIIAFBEGokACMAQRBrIgEkACALQTRqIg1CADcCACANQQA2AgggAUEQaiQAIwBBEGsiASQAIAtBKGoiDEIANwIAIAxBADYCCCABQRBqJAAjAEEQayIBJAAgC0EcaiIQQgA3AgAgEEEANgIIIAFBEGokACMAQRBrIgokACALAn8gAgRAIApBBGoiAiADEMAD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fHwhFiAOIAhBAEdqIQ4LIAFBAWohBCABLQABIgENAQwICwsgBSEADAELQQEhB0EAIQpBACEADAILIAwhBwwDCyAMIQcLIA4NAQtBfyEOCyAHRQ0AIAoQLyAAEC8LIBEEQCADEIEBCyAGQbACaiQAIANBkAFqJAAgDgtDAAJAIABFDQACQAJAAkACQCABQQJqDgYAAQICBAMECyAAIAI8AAAPCyAAIAI9AQAPCyAAIAI+AgAPCyAAIAI3AwALC7UDAgN/AX4jAEEgayIDJAACQCABQv///////////wCDIgVCgICAgICAwMA/fSAFQoCAgICAgMC/wAB9VARAIAFCGYinIQQgAFAgAUL///8PgyIFQoCAgAhUIAVCgICACFEbRQRAIARBgYCAgARqIQIMAgsgBEGAgICABGohAiAAIAVCgICACIWEQgBSDQEgAiAEQQFxaiECDAELIABQIAVCgICAgICAwP//AFQgBUKAgICAgIDA//8AURtFBEAgAUIZiKdB////AXFBgICA/gdyIQIMAQtBgICA/AchAiAFQv///////7+/wABWDQBBACECIAVCMIinIgRBkf4ASQ0AIANBEGogACABQv///////z+DQoCAgICAgMAAhCIFIARBgf4AaxBmIAMgACAFQYH/ACAEaxCvASADKQMIIgBCGYinIQIgAykDACADKQMQIAMpAxiEQgBSrYQiBVAgAEL///8PgyIAQoCAgAhUIABCgICACFEbRQRAIAJBAWohAgwBCyAFIABCgICACIWEQgBSDQAgAkEBcSACaiECCyADQSBqJAAgAiABQiCIp0GAgICAeHFyvguNBAIFfwF+AkACQAJAAkACQAJ/IAAoAgQiAiAAKAJoRwRAIAAgAkEBajYCBCACLQAADAELIAAQPwsiAkEraw4DAAEAAQsgAkEtRiEFAn8gACgCBCIDIAAoAmhHBEAgACADQQFqNgIEIAMtAAAMAQsgABA/CyIDQTprIQQgAUUNASAEQXVLDQEgACkDcEIAUw0CIAAgACgCBEEBazYCBAwCCyACQTprIQQgAiEDCyAEQXZJDQACQCADQTBrQQpPDQBBACECA0AgAyACQQpsaiEGAn8gACgCBCICIAAoAmhHBEAgACACQQFqNgIEIAItAAAMAQsgABA/CyEDIAZBMGshAiACQcyZs+YASCADQTBr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IwNBHGpBxAA2AgALIARB8AJqIBcgFiAPEO0DIAQpA/gCIRUgBCkD8AILIRYgDiAVNwMoIA4gFjcDICAEQZDGAGokACAOKQMoIRUgDikDICEWDAQLIAEpA3BCAFkEQCABIAEoAgRBAWs2AgQLDAELAkACfyABKAIEIgIgASgCaEcEQCABIAJBAWo2AgQgAi0AAAwBCyABED8LQShGBEBBASEGDAELQoCAgICAgOD//wAhFSABKQNwQgBTDQMgASABKAIEQQFrNgIEDAMLA0ACfyABKAIEIgIgASgCaEcEQCABIAJBAWo2AgQgAi0AAAwBCyABED8LIglBwQBrIQICQAJAIAlBMGtBCkkNACACQRpJDQAgCUHfAEYNACAJQeEAa0EaTw0BCyAGQQFqIQYMAQsLQoCAgICAgOD//wAhFSAJQSlGDQIgASkDcCIYQgBZBEAgASABKAIEQQFrNgIECwJAIAMEQCAGDQEMBAsMAQsDQCAYQgBZBEAgASABKAIEQQFrNgIECyAGQQFrIgYNAAsMAgsjA0EcakEcNgIAIAFCABCAAQtCACEVCyAAIBY3AwAgACAVNwMIIA5BMGokAAvKBgIFfwR+IwBBgAFrIgUkAAJAAkACQCADIARCAEIAEK4BRQ0AAn8gBEL///////8/gyELAn8gBEIwiKdB//8BcSIGQf//AUcEQEEEIAYNARpBAkEDIAMgC4RQGwwCCyADIAuEUAsLIQkgAkIwiKciCEH//wFxIgdB//8BRg0AIAkNAQsgBUEQaiABIAIgAyAEEEsgBSAFKQMQIgIgBSkDGCIBIAIgARDsAyAFKQMIIQIgBSkDACEEDAELIAEgAkL///////////8AgyILIAMgBEL///////////8AgyIKEK4BQQBMBEAgASALIAMgChCuAQRAIAEhBAwCCyAFQfAAaiABIAJCAEIAEEsgBSkDeCECIAUpA3AhBAwBCyAEQjCIp0H//wFxIQYgBwR+IAEFIAVB4ABqIAEgC0IAQoCAgICAgMC7wAAQSyAFKQNoIgtCMIinQfgAayEHIAUpA2ALIQQgBkUEQCAFQdAAaiADIApCAEKAgICAgIDAu8AAEEsgBSkDWCIKQjCIp0H4AGshBiAFKQNQIQMLIApC////////P4NCgICAgICAwACEIQwgC0L///////8/g0KAgICAgIDAAIQhCyAGIAdIBEADQAJ+IAsgDH0gAyAEVq19IgpCAFkEQCAKIAQgA30iBIRQBEAgBUEgaiABIAJCAEIAEEsgBSkDKCECIAUpAyAhBAwFCyAKQgGGIARCP4iEDAELIAtCAYYgBEI/iIQLIQsgBEIBhiEEIAdBAWsiByAGSg0ACyAGIQcLAkAgCyAMfSADIARWrX0iCkIAUwRAIAshCgwBCyAKIAQgA30iBIRCAFINACAFQTBqIAEgAkIAQgAQSyAFKQM4IQIgBSkDMCEEDAELIApC////////P1gEQANAIARCP4ghDSAHQQFrIQcgBEIBhiEEIA0gCkIBhoQiCkKAgICAgIDAAFQNAAsLIAhBgIACcSEGIAdBAEwEQCAFQUBrIAQgCkL///////8/gyAHQfgAaiAGcq1CMIaEQgBCgICAgICAwMM/EEsgBSkDSCECIAUpA0AhBAwBCyAKQv///////z+DIAYgB3KtQjCGhCECCyAAIAQ3AwAgACACNwMIIAVBgAFqJAALqg8CBX8PfiMAQdACayIFJAAgBEL///////8/gyELIAJC////////P4MhCiACIASFQoCAgICAgICAgH+DIQ0gBEIwiKdB//8BcSEIAkACQCACQjCIp0H//wFxIglB//8Ba0GCgH5PBEAgCEH//wFrQYGAfksNAQsgAVAgAkL///////////8AgyIMQoCAgICAgMD//wBUIAxCgICAgICAwP//AFEbRQRAIAJCgICAgICAIIQhDQwCCyADUCAEQv///////////wCDIgJCgICAgICAwP//AFQgAkKAgICAgIDA//8AURtFBEAgBEKAgICAgIAghCENIAMhAQwCCyABIAxCgICAgICAwP//AIWEUARAIAMgAkKAgICAgIDA//8AhYRQBEBCACEBQoCAgICAgOD//wAhDQwDCyANQoCAgICAgMD//wCEIQ1CACEBDAILIAMgAkKAgICAgIDA//8AhYRQBEBCACEBDAILIAEgDIRQBEBCgICAgICA4P//ACANIAIgA4RQGyENQgAhAQwCCyACIAOEUARAIA1CgICAgICAwP//AIQhDUIAIQEMAgsgDEL///////8/WARAIAVBwAJqIAEgCiABIAogClAiBht5IAZBBnStfKciBkEPaxBmQRAgBmshBiAFKQPIAiEKIAUpA8ACIQELIAJC////////P1YNACAFQbACaiADIAsgAyALIAtQIgcbeSAHQQZ0rXynIgdBD2sQZiAGIAdqQRBrIQYgBSkDuAIhCyAFKQOwAiEDCyAFQaACaiALQoCAgICAgMAAhCISQg+GIANCMYiEIgJCAEKAgICAsOa8gvUAIAJ9IgRCABBgIAVBkAJqQgAgBSkDqAJ9QgAgBEIAEGAgBUGAAmogBSkDmAJCAYYgBSkDkAJCP4iEIgRCACACQgAQYCAFQfABaiAEQgBCACAFKQOIAn1CABBgIAVB4AFqIAUpA/gBQgGGIAUpA/ABQj+IhCIEQgAgAkIAEGAgBUHQAWogBEIAQgAgBSkD6AF9QgAQYCAFQcABaiAFKQPYAUIBhiAFKQPQAUI/iIQiBEIAIAJCABBgIAVBsAFqIARCAEIAIAUpA8gBfUIAEGAgBUGgAWogAkIAIAUpA7gBQgGGIAUpA7ABQj+IhEIBfSICQgAQYCAFQZABaiADQg+GQgAgAkIAEGAgBUHwAGogAkIAQgAgBSkDqAEgBSkDoAEiDCAFKQOYAXwiBCAMVK18IARCAVatfH1CABBgIAVBgAFqQgEgBH1CACACQgAQYCAGIAkgCGtqIQYCfyAFKQNwIhNCAYYiDiAFKQOIASIPQgGGIAUpA4ABQj+IhHwiEELn7AB9IhRCIIgiAiAKQoCAgICAgMAAhCIVQgGGIhZCIIgiBH4iESABQgGGIgxCIIgiCyAQIBRWrSAOIBBWrSAFKQN4QgGGIBNCP4iEIA9CP4h8fHxCAX0iE0IgiCIQfnwiDiARVK0gDiAOIBNC/////w+DIhMgAUI/iCIXIApCAYaEQv////8PgyIKfnwiDlatfCAEIBB+fCAEIBN+IhEgCiAQfnwiDyARVK1CIIYgD0IgiIR8IA4gDiAPQiCGfCIOVq18IA4gDiAUQv////8PgyIUIAp+IhEgAiALfnwiDyARVK0gDyAPIBMgDEL+////D4MiEX58Ig9WrXx8Ig5WrXwgDiAEIBR+IhggECARfnwiBCACIAp+fCIKIAsgE358IhBCIIggCiAQVq0gBCAYVK0gBCAKVq18fEIghoR8IgQgDlStfCAEIA8gAiARfiICIAsgFH58IgtCIIggAiALVq1CIIaEfCICIA9UrSACIBBCIIZ8IAJUrXx8IgIgBFStfCIEQv////////8AWARAIBYgF4QhFSAFQdAAaiACIAQgAyASEGAgAUIxhiAFKQNYfSAFKQNQIgFCAFKtfSEKQgAgAX0hCyAGQf7/AGoMAQsgBUHgAGogBEI/hiACQgGIhCICIARCAYgiBCADIBIQYCABQjCGIAUpA2h9IAUpA2AiDEIAUq19IQpCACAMfSELIAEhDCAGQf//AGoLIgZB//8BTgRAIA1CgICAgICAwP//AIQhDUIAIQEMAQsCfiAGQQBKBEAgCkIBhiALQj+IhCEKIARC////////P4MgBq1CMIaEIQwgC0IBhgwBCyAGQY9/TARAQgAhAQwCCyAFQUBrIAIgBEEBIAZrEK8BIAVBMGogDCAVIAZB8ABqEGYgBUEgaiADIBIgBSkDQCICIAUpA0giDBBgIAUpAzggBSkDKEIBhiAFKQMgIgFCP4iEfSAFKQMwIgQgAUIBhiIBVK19IQogBCABfQshBCAFQRBqIAMgEkIDQgAQYCAFIAMgEkIFQgAQYCAMIAIgAiADIAJCAYMiASAEfCIDVCAKIAEgA1atfCIBIBJWIAEgElEbrXwiAlatfCIEIAIgAiAEQoCAgICAgMD//wBUIAMgBSkDEFYgASAFKQMYIgRWIAEgBFEbca18IgJWrXwiBCACIARCgICAgICAwP//AFQgAyAFKQMAViABIAUpAwgiA1YgASADURtxrXwiASACVK18IA2EIQ0LIAAgATcDACAAIA03AwggBUHQAmokAAu/AgEBfyMAQdAAayIEJAACQCADQYCAAU4EQCAEQSBqIAEgAkIAQoCAgICAgID//wAQSyAEKQMoIQIgBCkDICEBIANB//8BSQRAIANB//8AayEDDAILIARBEGogASACQgBCgICAgICAgP//ABBLQf3/AiADIANB/f8CThtB/v8BayEDIAQpAxghAiAEKQMQIQEMAQsgA0GBgH9KDQAgBEFAayABIAJCAEKAgICAgICAORBLIAQpA0ghAiAEKQNAIQEgA0H0gH5LBEAgA0GN/wBqIQMMAQsgBEEwaiABIAJCAEKAgICAgICAORBLQeiBfSADIANB6IF9TBtBmv4BaiEDIAQpAzghAiAEKQMwIQELIAQgASACQgAgA0H//wBqrUIwhhBLIAAgBCkDCDcDCCAAIAQpAwA3AwAgBEHQAGokAAs1ACAAIAE3AwAgACACQv///////z+DIARCMIinQYCAAnEgAkIwiKdB//8BcXKtQjCGhDcDCAvAAQIBfwJ+QX8hAwJAIABCAFIgAUL///////////8AgyIEQoCAgICAgMD//wBWIARCgICAgICAwP//AFEbDQAgAkL///////////8AgyIFQoCAgICAgMD//wBWIAVCgICAgICAwP//AFJxDQAgACAEIAWEhFAEQEEADwsgASACg0IAWQRAIAEgAlIgASACU3ENASAAIAEgAoWEQgBSDwsgAEIAUiABIAJVIAEgAlEbDQAgACABIAKFhEIAUiEDCyADC0sBAn8gACgCACIBBEACfyABKAIMIgIgASgCEEYEQCABIAEoAgAoAiQRAAAMAQsgAigCAAtBf0cEQCAAKAIARQ8LIABBADYCAAtBAQtLAQJ/IAAoAgAiAQRAAn8gASgCDCICIAEoAhBGBEAgASABKAIAKAIkEQAADAELIAItAAALQX9HBEAgACgCAEUPCyAAQQA2AgALQQELpAEBA38gAUEISwRAQQQgASABQQRNGyEBQQEgACAAQQFNGyEAA0ACQCAAIAFqQQFrQQAgAWtxIgIgACAAIAJJGyEDQQAhBCMAQRBrIgIkAAJAIAFBA3ENACADIAFwDQAgAkEMaiABIAMQgwQhA0EAIAIoAgwgAxshBAsgAkEQaiQAIAQiAg0AQayZNf4QAgAiA0UNACADEQkADAELCyACDwsgABAyCwkAIAFBARDyAwsTACABQQhLBEAgABAvDwsgABAvC4YBAQN/IwBBEGsiBCQAIwBBIGsiAyQAIANBGGogACABEL0CIANBEGogA0EMaiADKAIYIAMoAhwgAhC8AiADIAAgAygCECAAa2o2AgwgAyACIAMoAhQgAmtqNgIIIAQgAygCDDYCCCAEIAMoAgg2AgwgA0EgaiQAIAQoAgwhBSAEQRBqJAAgBQsJACAAEL4CEC8LpQEBB38jAEEQayICJAAgACgCQCIBBH8gAkHSATYCBCACQQhqIAEgAkEEahBRIQEgACAAKAIAKAIYEQAAIQQgASgCACEGIAFBADYCACAGEKwEIQUgAEEANgJAIABBAEEAIAAoAgAoAgwRAwAaIAEoAgAhAyABQQA2AgAgAwRAIAMgAUEEaigCABEAABoLQQAgACAEIAVyGwVBAAshByACQRBqJAAgBwsKACAAQaSKNRB5C4YC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KAIANgIADwsgAiACKAIAIgFBBGo2AgAgACABMgEANwMADwsgAiACKAIAIgFBBGo2AgAgACABMwEANwMADwsgAiACKAIAIgFBBGo2AgAgACABMAAANwMADwsgAiACKAIAIgFBBGo2AgAgACABMQAANwMADwsgAiACKAIAQQdqQXhxIgFBCGo2AgAgACABKwMAOQMADwsgACACIAMRAgALDwsgAiACKAIAIgFBBGo2AgAgACABNAIANwMADwsgAiACKAIAIgFBBGo2AgAgACABNQIANwMADwsgAiACKAIAQQdqQXhxIgFBCGo2AgAgACABKQMANwMAC3IBA38gACgCACwAAEEwa0EKTwRAQQAPCwNAIAAoAgAhA0F/IQEgAkHMmbPmAE0EQEF/IAMsAABBMGsiASACQQpsIgJqIAEgAkH/////B3NKGyEBCyAAIANBAWo2AgAgASECIAMsAAFBMGtBCkkNAAsgAguZEwIWfwF+IwBB0ABrIggkACAIIAE2AkwgCEE3aiEYIAhBOGohEgJAAkACQANAQQAhBwNAIAEhDSAHIBFB/////wdzSg0CIAcgEWohEQJAAkACQCABIgctAAAiCQRAA0ACQAJAIAlB/wFxIgFFBEAgByEBDAELIAFBJUcNASAHIQkDQCAJLQABQSVHBEAgCSEBDAILIAdBAWohByAJLQACIRogCUECaiIBIQkgGkElRg0ACwsgByANayIHIBFB/////wdzIhlKDQggAARAIAAgDSAHEGELIAcNBiAIIAE2AkwgAUEBaiEHQX8hDgJAIAEsAAFBMGsiC0EKTw0AIAEtAAJBJEcNACABQQNqIQcgCyEOQQEhEwsgCCAHNgJMQQAhDAJAIAcsAAAiCUEgayIBQR9LBEAgByELDAELIAchC0EBIAF0IgFBidEEcUUNAANAIAggB0EBaiILNgJMIAEgDHIhDCAHLAABIglBIGsiAUEgTw0BIAshB0EBIAF0IgFBidEEcQ0ACwsCQCAJQSpGBEAgC0EBaiEJAn8CQCALLAABQTBrQQpPDQAgCy0AAkEkRw0AIAksAABBMGshASALQQNqIQlBASETAn8gAEUEQCAEIAFBAnRqQQo2AgBBAAwBCyADIAFBA3RqKAIACwwBCyATDQYgAEUEQCAIIAk2AkxBACETQQAhDwwDCyACIAIoAgAiAUEEajYC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BQUAAQIDBAsgAUEQayIBKwMAIAArAwBkRQ0EIAIgAP0AAwD9CwMAIAAgASgCCDYCCCAAIAEpAwA3AwAgASACKAIINgIIIAEgAikDADcDAAwECyAAQRBqIQMgAUEQayIBKwMAIQkgACsDECIKIAArAwBkRQRAIAkgCmRFDQQgAiAD/QADAP0LAwAgAyABKAIINgIIIAMgASkDADcDACABIAIoAgg2AgggASACKQMANwMAIAArAxAgACsDAGRFDQQgAiAA/QADAP0LAwAgACADKAIINgIIIAAgAykDADcDACADIAIoAgg2AgggAyACKQMANwMADAQLIAkgCmQEQCACIAD9AAMA/QsDACAAIAEoAgg2AgggACABKQMANwMAIAEgAigCCDYCCCABIAIpAwA3AwAMBAsgAiAA/QADAP0LAwAgACADKAIINgIIIAAgAykDADcDACADIAIoAgg2AgggAyACKQMANwMAIAErAwAgACsDEGRFDQMgAiAD/QADAP0LAwAgAyABKAIINgIIIAMgASkDADcDACABIAIoAgg2AgggASACKQMANwMADAMLIAAgAEEQaiAAQSBqIAFBEGsQ2AEaDAILIAAgAEEQaiIEIABBIGoiAyAAQTBqIgUQ2AEaIAFBEGsiASsDACAAKwMwZEUNASACIAX9AAMA/QsDACAFIAEoAgg2AgggBSABKQMANwMAIAEgAigCCDYCCCABIAIpAwA3AwAgBSsDACADKwMAZEUNASACIAP9AAMA/QsDACADIAUoAgg2AgggAyAFKQMANwMAIAUgAigCCDYCCCAFIAIpAwA3AwAgAysDACAEKwMAZEUNASACIAT9AAMA/QsDACAEIAMoAgg2AgggBCADKQMANwMAIAMgAigCCDYCCCADIAIpAwA3AwAgACsDECAAKwMAZEUNASACIAD9AAMA/QsDACAAIAQoAgg2AgggACAEKQMANwMAIAQgAigCCDYCCCAEIAIpAwA3AwAMAQsgAEEQaiEEIABBIGohAyAAKwMgIQkCQCAAKwMQIgogACsDACILZEUEQCAJIApkRQ0BIAIgBP0AAwD9CwMAIAQgA0EIaigCADYCCCAEIAMpAwA3AwAgAyACKAIINgIIIAMgAikDADcDACAEKwMAIAtkRQ0BIAIgAP0AAwD9CwMAIAAgBCgCCDYCCCAAIAQpAwA3AwAg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IABBhBlqIABBlBJqKAIANgIAIABB/BhqIAApAowSNwIAIABBADoA/hEgAEHpyAE7AfwRIABBAjoAhxIgAEH4EWoiAkHaGC8AADsBACAAQYAUOwH6ESAAQRA2AuwRIABB0hgpAAAiEzcC8BEgAEGQGWogAEGEEmooAgA2AgAgACAAKQL8ETcDiBkgAEGUGWpBEDYCACAAQaAZaiACKAIANgIAIABBmBlqIBM3AwAgAEEAOgDiESAAQejSATsB4BEgAEECOgDrESAAQdgRakHtGy0AADoAACAAQQU6AN8RIABBETYC0BEgAEEAOgDZESAAQekbKAAANgLUESAAQawZaiAAQegRaigCADYCACAAIAApAuARNwKkGSAAQbAZakERNgIAIABBvBlqIABB3BFqKAIANgIAIABBtBlqIAApAtQRNwIAIABBADoAxhEgAEHm0gE7AcQRIABBAjoAzxEgAEG7EWpBlRwoAAA2AAAgAEEHOgDDESAAQRI2ArQRIABBADoAvxEgAEGSHCgAADYCuBEgAEHIGWogAEHMEWooAgA2AgAgACAAKQLEETcDwBkgAEHMGWpBEjYCACAAQdgZaiAAQcARaigCADYCACAAQdAZaiAAKQK4ETcDACAAQQA6AKoRIABB9tIBOwGoESAAQQI6ALMRIABBpBFqIgJB4CEvAAA7AQAgAEGAFDsBphEgAEETNgKYESAAQdghKQAAIhM3ApwRIABB5BlqIABBsBFqKAIANgIAIAAgACkCqBE3AtwZIABB6BlqQRM2AgAgAEH0GWogAigCADYCACAAQewZaiATNwIAIABBADoAjhEgAEHoygE7AYwRIABBAjoAlxEgAEGEEWpBtwovAAA7AQAgAEEGOgCLESAAQRQ2AvwQIABBADoAhhEgAEGzCigAADYCgBEgAEGAGmogAEGUEWooAgA2AgAgACAAKQKMETcD+BkgAEGEGmpBFDYCACAAQZAaaiAAQYgRaigCADYCACAAQYgaaiAAKQKAETcDACAAQQA6APIQIABB9dYBOwHwECAAQQI6APsQIABB7BBqIgJBjBktAAA6AAAgAEEJOgDvECAAQRU2AuAQIABBADoA7RAgAEGEGSkAACITNwLkECAAQZwaaiAAQfgQaigCADYCACAAIAApAvAQNwKUGiAAQaAaakEVNgIAIABBrBpqIAIoAgA2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IABB4B9qQY4ZKQAAIhM3AwAgAEHYH2ogAEHMC2ooAgA2AgAgAEEJOgDDCyAAQQA6AMELIABB6B9qIAIoAgA2AgAgAEEuNgK0CyAAIBM3ArgLIAAgACkCxAs3A9AfIABBADoAqgsgAEHr3AE7AagLIABBAjoAswsgAEGfC2pBmCkoAAA2AAAgAEEHOgCnCyAAQS82ApgLIABBADoAowsgAEGVKSgAADYCnAsgAEH0H2ogAEGwC2ooAgA2AgAgACAAKQKoCzcC7B8gAEH4H2pBLzYCACAAQYQgaiAAQaQLaigCADYCACAAQfwfaiAAKQKcCzcCACAAQQA6AI4LIABB5egBOwGMCyAAQQI6AJcLIABBiAtqIgJBADoAACAAQQg6AIsLIABBMDYC/AogAELl5tH75q3asO4ANwKACyAAQZAgaiAAQZQLaigCADYCACAAIAApAowLNwOIICAAQZQgakEwNgIAIABBoCBqIAIoAgA2AgAgAEGYIGpC5ebR++at2rDuADcDACAAQQA6APIKIABB7dYBOwHwCiAAQQI6APsKIABB7ApqIgJBgRkvAAA7AQAgAEEKOgDvCiAAQTE2AuAKIABBADoA7gogAEH5GCkAACITNwLkCiAAQawgaiAAQfgKaigCADYCACAAIAApAvAKNwKkICAAQbAgakExNgIAIABBvCBqIAIoAgA2AgAgAEG0IGogEzcCACAAQQA6ANYKIABB4uQBOwHUCiAAQQI6AN8KIABBzApqQbkWLwAAOwEAIABBBjoA0wogAEEyNgLECiAAQQA6AM4KIABBtRYoAAA2AsgKIABByCBqIABB3ApqKAIANgIAIAAgACkC1Ao3A8AgIABBzCBqQTI2AgAgAEHYIGogAEHQCmooAgA2AgAgAEHQIGogACkCyAo3AwAgAEEAOgC6CiAAQeXqATsBuAogAEECOgDDCiAAQbAKakGhHy8AADsBACAAQQY6ALcKIABBMzYCqAogAEEAOgCyCiAAQZ0fKAAANgKsCiAAQeQgaiAAQcAKaigCADYCACAAIAApArgKNwLcICAAQeggakEzNgIAIABB9CBqIABBtApqKAIANgIAIABB7CBqIAApAqwKNwIAIABBADoAngogAEHp5gE7AZwKIABBAjoApwogAEGYCmoiAkHXJi0AADoAACAAQQk6AJsKIABBNDYCjAogAEEAOgCZCiAAQc8mKQAAIhM3ApAKIABBgCFqIABBpApqKAIANgIAIAAgACkCnAo3A/ggIABBhCFqQTQ2AgAgAEGQIWogAigCADYCACAAQYghaiATNwMAIABBADoAggogAEHo8gE7AYAKIABBAjoAiwogAEH8CWoiAkEAOgAAIABBCDoA/wkgAEE1NgLwCSAAQuHktavmrdqw7gA3AvQJIABBnCFqIABBiApqKAIANgIAIAAgACkCgAo3ApQhIABBoCFqQTU2AgAgAEGsIWogAigCADYCACAAQaQhakLh5LWr5q3asO4ANwIAIABBADoA5gkgAEHuygE7AeQJIABBAjoA7wkgAEHcCWpByBsvAAA7AQAgAEEGOgDjCSAAQTY2AtQJIABBADoA3gkgAEHEGygAADYC2AkgAEG4IWogAEHsCWooAgA2AgAgACAAKQLkCTcDsCEgAEG8IWpBNjYCACAAQcghaiAAQeAJaigCADYCACAAQcAhaiAAKQLYCTcDACAAQQA6AMoJIABB7dwBOwHICSAAQQI6ANMJIABBxAlqIgJBqxktAAA6AAAgAEEJOgDHCSAAQTc2ArgJIABBADoAxQkgAEGjGSkAACITNwK8CSAAQdQhaiAAQdAJaigCADYCACAAIAApAsgJNwLMISAAQdghakE3NgIAIABB5CFqIAIoAgA2AgAgAEHcIWogEzcCACAAQQA6AK4JIABB4uYBOwGsCSAAQQI6ALcJIABBowlqQfQYKAAANgAAIABBBzoAqwkgAEE4NgKcCSAAQQA6AKcJIABB8RgoAAA2AqAJIABB8CFqIABBtAlqKAIANgIAIAAgACkCrAk3A+ghIABB9CFqQTg2AgAgAEGAImogAEGoCWooAgA2AgAgAEH4IWogACkCoAk3AwAgAEEAOgCSCSAAQevWATsBkAkgAEECOgCbCSAAQYgJakHyHC8AADsBACAAQQY6AI8JIABBOTYCgAkgAEEAOgCKCSAAQe4cKAAANgKECSAAQYwiaiAAQZgJaigCADYCACAAIAApApAJNwKEIiAAQZAiakE5NgIAIABBnCJqIABBjAlqKAIANgIAIABBlCJqIAApAoQJNwIAIABBADoA9gggAEHz4gE7AfQIIABBAjoA/wggAEHwCGoiAkEAOgAAIABBCDoA8wggAEE6NgLkCCAAQuHYiYvmrdqw7gA3AugIIABBqCJqIABB/AhqKAIANgIAIAAgACkC9Ag3A6AiIABBrCJqQTo2AgAgAEG4ImogAigCADYCACAAQbAiakLh2ImL5q3asO4ANwMAIABBADoA2gggAEHz7gE7AdgIIABBAjoA4wggAEHPCGpBvxsoAAA2AAAgAEEHOgDXCCAAQTs2AsgIIABBADoA0wggAEG8GygAADYCzAggAEHEImogAEHgCGooAgA2AgAgACAAKQLYCDcCvCIgAEHIImpBOzYCACAAQdQiaiAAQdQIaigCADYCACAAQcwiaiAAKQLMCDcCACAAQQA6AL4IIABB59gBOwG8CCAAQQI6AMcIIABBuAhqIgJBADoAACAAQQg6ALsIIABBPDYCrAggAELnwrHLtqzasO4ANwKwCCAAQeAiaiAAQcQIaigCADYCACAAIAApArwINwPYIiAAQeQiakE8NgIAIABB8CJqIAIoAgA2AgAgAEHoImpC58Kxy7as2rDuADcDACAAQQA6AKIIIABB7eQBOwGgCCAAQQI6AKsIIABBlwhqQd0bKAAANgAAIABBBzoAnwggAEE9NgKQCCAAQQA6AJsIIABB2hsoAAA2ApQIIABB/CJqIABBqAhqKAIANgIAIAAgACkCoAg3AvQiIABBgCNqQT02AgAgAEGMI2ogAEGcCGooAgA2AgAgAEGEI2ogACkClAg3AgAgAEEAOgCGCCAAQfDCATsBhAggAEECOgCPCCAAQfIbKAAANgD7ByAAQQc6AIMIIABBPjYC9AcgAEEAOgD/ByAAQe8bKAAANgL4ByAAQZgjaiAAQYwIaigCADYCACAAIAApAoQINwOQIyAAQZwjakE+NgIAIABBqCNqIABBgAhqKAIANgIAIABBoCNqIAApAvgHNwMAIABBADoA6gcgAEHz0gE7AegHIABBAjoA8wcgAEGCKSgAADYA3wcgAEEHOgDnByAAQT82AtgHIABBADoA4wcgAEH/KCgAADYC3AcgAEG0I2ogACgC8Ac2AgAgACAAKQLoBzcCrCMgAEG4I2pBPzYCACAAQcQjaiAAKALkBzYCACAAQbwjaiAAKQLcBzcCACAAQQA6AM4HIABB69oBOwHMByAAQQI6ANcHIABBxxQtAAA6AMQHIABBBToAywcgAEHAADYCvAcgAEEAOgDFByAAQcMUKAAANgLAByAAQdAjaiAAKALUBzYCACAAIAApAswHNwPIIyAAQdQjakHAADYCACAAQeAjaiAAKALIBzYCACAAQdgjaiAAKQLABzcDACAAQQA6ALIHIABB89wBOwGwByAAQQI6ALsHIABB9ygtAAA6AKgHIABBBToArwcgAEHBADYCoAcgAEEAOgCpByAAQfMoKAAANgKkByAAQewjaiAAKAK4BzYCACAAIAApArAHNwLkIyAAQfAjakHBADYCACAAQfwjaiAAKAKsBzYCACAAQfQjaiAAKQKkBzcCACAAQQA6AJYHIABB+d4BOwGUByAAQQI6AJ8HIABBoSkvAAA7AYwHIABBBjoAkwcgAEHCADYChAcgAEEAOgCOByAAQZ0pKAAANgKIByAAQYgkaiAAKAKcBzYCACAAIAApApQHNwOAJCAAQYwkakHCADYCACAAQZgkaiAAKAKQBzYCACAAQZAkaiAAKQKIBzcDACAAQQA6APoGIABB894BOwH4BiAAQQI6AIMHIABBzxsvAAA7AfAGIABBBjoA9wYgAEHDADYC6AYgAEEAOgDyBiAAQcsbKAAANgLsBiAAQaQkaiAAKAKABzYCACAAIAApAvgGNwKcJCAAQagkakHDADYCACAAQbQkaiAAKAL0BjYCACAAQawkaiAAKQLsBjcCACAAQQA6AN4GIABB4cwBOwHcBiAAQQI6AOcGIABBwxAtAAA6ANgGIABBCToA2wYgAEHEADYCzAYgAEEAOgDZBiAAQbsQKQAAIhM3AtAGIABBwCRqIAAoAuQGNgIAIAAgACkC3AY3A7gkIABBxCRqQcQANgIAIABB0CRqIAAoAtgGNgIAIABByCRqIBM3AwAgAEEAOgDCBiAAQe/GATsBwAYgAEECOgDLBiAAQYkYKAAANgC3BiAAQQc6AL8GIABBxQA2ArAGIABBADoAuwYgAEGGGCgAADYCtAYgAEHcJGogACgCyAY2AgAgACAAKQLABjcC1CQgAEHgJGpBxQA2AgAgAEHsJGogACgCvAY2AgAgAEHkJGogACkCtAY3AgAgAEEAOgCmBiAAQevCATsBpAYgAEECOgCvBiAAQQA6AKAGIABBCDoAowYgAEHGADYClAYgAELnyr2T96zasO4ANwKYBiAAQfgkaiAAKAKsBjYCACAAIAApAqQGNwPwJCAAQfwkakHGADYCACAAQYglaiAAKAKgBjYCACAAQYAlakLnyr2T96zasO4ANwMAIABBADoAigYgAEHiygE7AYgGIABBAjoAkwYgAEG/GC8AADsBhAYgAEEKOgCHBiAAQccANgL4BSAAQQA6AIYGIABBtxgpAAAiEzcC/AUgAEGUJWogACgCkAY2AgAgACAAKQKIBjcCjCUgAEGYJWpBxwA2AgAgAEGkJWogACgChAY2AgAgAEGcJWogEzcCACAAQQA6AO4FIABB9M4BOwHsBSAAQQI6APcFIABBjxstAAA6AOQFIABBBToA6wUgAEHIADYC3AUgAEEAOgDlBSAAQYsbKAAANgLgBSAAQbAlaiAAKAL0BTYCACAAIAApAuwFNwOoJSAAQbQlakHIADYCACAAQcAlaiAAKALoBTYCACAAQbglaiAAKQLgBTcDACAAQQA6ANIFIABB88gBOwHQBSAAQQI6ANsFIABB5hsvAAA7AcgFIABBBjoAzwUgAEHJADYCwAUgAEEAOgDKBSAAQeIbKAAANgLEBSAAQcwlaiAAKALYBTYCACAAIAApAtAFNwLEJSAAQdAlakHJADYCACAAQdwlaiAAKALMBTYCACAAQdQlaiAAKQLEBTcCACAAQQA6ALYFIABB5+oBOwG0BSAAQQI6AL8FIABBADoAsAUgAEEIOgCzBSAAQcoANgKkBSAAQufqqYumrpi66QA3AqgFIABB6CVqIAAoArwFNgIAIAAgACkCtAU3A+AlIABB7CVqQcoANgIAIABB+CVqIAAoArAFNgIAIABB8CVqQufqqYumrpi66QA3AwAgAEEAOgCaBSAAQeHaATsBmAUgAEECOgCjBSAAQcomKAAANgCPBSAAQQc6AJcFIABBywA2AogFIABBADoAkwUgAEHHJigAADYCjAUgAEGEJmogACgCoAU2AgAgACAAKQKYBTcC/CUgAEGIJmpBywA2AgAgAEGUJmogACgClAU2AgAgAEGMJmogACkCjAU3AgAgAEEAOgD+BCAAQfnSATsB/AQgAEECOgCHBSAAQdkcKAAANgDzBCAAQQc6APsEIABBzAA2AuwEIABBADoA9wQgAEHWHCgAADYC8AQgAEGgJmogACgChAU2AgAgACAAKQL8BDcDmCYgAEGkJmpBzAA2AgAgAEGwJmogACgC+AQ2AgAgAEGoJmogACkC8AQ3AwAgAEEAOgDiBCAAQezeATsB4AQgAEECOgDrBCAAQZMWLQAAOgDWBCAAQQM6AN8EIABBzQA2AtAEIABBADoA1wQgAEGRFi8AADsB1AQgAEG8JmogACgC6AQ2AgAgACAAKQLgBDcCtCYgAEHAJmpBzQA2AgAgAEHMJmogACgC3AQ2AgAgAEHEJmogACkC1AQ3AgAgAEEAOgDGBCAAQfX0ATsBxAQgAEECOgDPBCAAQZsbLQAAOgC8BCAAQQU6AMMEIABBzgA2ArQEIABBADoAvQQgAEGXGygAADYCuAQgAEHYJmogACgCzAQ2AgAgACAAKQLEBDcD0CYgAEHcJmpBzgA2AgAgAEHoJmogACgCwAQ2AgAgAEHgJmogACkCuAQ3AwAgAEEAOgCqBCAAQebeATsBqAQgAEECOgCzBCAAQbchKAAANgCfBCAAQQc6AKcEIABBzwA2ApgEIABBADoAowQgAEG0ISgAADYCnAQgAEH0JmogACgCsAQ2AgAgACAAKQKoBDcC7CYgAEH4JmpBzwA2AgAgAEGEJ2ogACgCpAQ2AgAgAEH8JmogACkCnAQ3AgAgAEEAOgCOBCAAQejoATsBjAQgAEECOgCXBEEQEDIiDEEAOgAOIAxBjCMpAAA3AAYgDEGGIykAADcAACAAQZQnakHQADYCACAAQZAnaiAAKAKUBDYCACAAIAApAowENwOIJyAAQZgnaiAMQQ4QayAAQQA6AIIEIABB8OYBOwGABCAAQQI6AIsEIABBiRYvAAA7AfgDIABBsCdqQdEANgIAIABBrCdqIAAoAogENgIAIABBhRYoAAA2AvQDIABBADoA+gMgAEG0J2ogACkC9AM3AgAgAEEGOgD/AyAAQbwnaiAAKAL8AzYCACAAQdEANgLwAyAAIAApAoAENwKkJyAAQQA6AOYDIABB9NYBOwHkAyAAQQI6AO8DIABB+hcoAAA2ANsDIABBBzoA4wMgAEHSADYC1AMgAEEAOgDfAyAAQfcXKAAANgLYAyAAQcgnaiAAKALsAzYCACAAIAApAuQDNwPAJyAAQcwnakHSADYCACAAQdgnaiAAKALgAzYCACAAQdAnaiAAKQLYAzcDACAAQQA6AMoDIABB7twBOwHIAyAAQQI6ANMDIABByRooAAA2AL8DIABBBzoAxwMgAEHTADYCuAMgAEEAOgDDAyAAQcYaKAAANgK8AyAAQeQnaiAAKALQAzYCACAAIAApAsgDNwLcJyAAQegnakHTADYCACAAQfQnaiAAKALEAzYCACAAQewnaiAAKQK8AzcCACAAQQA6AK4DIABB7egBOwGsAyAAQQI6ALcDIABBryEoAAA2AKMDIABBBzoAqwMgAEHUADYCnAMgAEEAOgCnAyAAQawhKAAANgKgAyAAQYAoaiAAKAK0AzYCACAAIAApAqwDNwP4JyAAQYQoakHUADYCACAAQZAoaiAAKAKoAzYCACAAQYgoaiAAKQKgAzcDACAAQQA6AJIDIABB88IBOwGQAyAAQQI6AJsDIABBADoAjAMgAEEIOgCPAyAAQdUANgKAAyAAQvPCuZu3zdy09AA3AoQDIABBnChqIAAoApgDNgIAIAAgACkCkAM3ApQoIABBoChqQdUANgIAIABBrChqIAAoAowDNgIAIABBpChqQvPCuZu3zdy09AA3AgAgAEEAOgD2AiAAQezEATsB9AIgAEECOgD/AkEQEDIiDUEAOgANIA1BxRwpAAA3AAUgDUHAHCkAADcAACAAQbwoakHWADYCACAAQbgoaiAAKAL8AjYCACAAIAApAvQCNwOwKCAAQcAoaiANQQ0QayAAQQA6AOoCIABB7fIBOwHoAiAAQQI6APMCIABB/RQoAAA2AN8CIABB2ChqQdcANgIAIABB1ChqIAAoAvACNgIAIABB+hQoAAA2AtwCIABBADoA4wIgAEHcKGogACkC3AI3AgAgAEEHOgDnAiAAQeQoaiAAKALkAjYCACAAQdcANgLYAiAAIAApAugCNwLMKCAAQQA6AM4CIABB4t4BOwHMAiAAQQI6ANcCIABBkRgoAAA2AMMCIABBBzoAywIgAEHYADYCvAIgAEEAOgDHAiAAQY4YKAAANgLAAiAAQfAoaiAAKALUAjYCACAAIAApAswCNwPoKCAAQfQoakHYADYCACAAQYApaiAAKALIAjYCACAAQfgoaiAAKQLAAjcDACAAQQA6ALICIABB9NgBOwGwAiAAQQI6ALsCIABBlR0oAAA2AKcCIABBBzoArwIgAEHZADYCoAIgAEEAOgCrAiAAQZIdKAAANgKkAiAAQYwpaiAAKAK4AjYCACAAIAApArACNwKEKSAAQZApakHZADYCACAAQZwpaiAAKAKsAjYCACAAQZQpaiAAKQKkAjcCACAAQQA6AJYCIABB7c4BOwGUAiAAQQI6AJ8CIABBADoAkAIgAEEIOgCTAiAAQdoANgKEAiAAQu3CsYv2rNi5+QA3AogCIABBqClqIAAoApwCNgIAIAAgACkClAI3A6ApIABBrClqQdoANgIAIABBuClqIAAoApACNgIAIABBsClqQu3CsYv2rNi5+QA3AwAgAEEAOgD6ASAAQeHmATsB+AEgAEECOgCDAiAAQQA6APQBIABBCDoA9wEgAEHbADYC6AEgAELh5s2L1q3ZueUANwLsASAAQcQpaiAAKAKAAjYCACAAIAApAvgBNwK8KSAAQcgpakHbADYCACAAQdQpaiAAKAL0ATYCACAAQcwpakLh5s2L1q3ZueUANwIAIABBADoA3gEgAEH06AE7AdwBIABBAjoA5wEgAEH4FC0AADoA1AEgAEEFOgDbASAAQdwANgLMASAAQQA6ANUBIABB9BQoAAA2AtABIABB4ClqIAAoAuQBNgIAIAAgACkC3AE3A9gpIABB5ClqQdwANgIAIABB8ClqIAAoAtgBNgIAIABB6ClqIAApAtABNwMAIABBAzoAywEgAEEAOgDDASAAQbwKLQAAOgDCASAAQboKLwAAOwHAASAAQQA6ALwBIABBCDoAvwEgAEHdADYCsAEgAELowt2Llq3asO4ANwK0ASAAQfwpaiAAKALIATYCACAAIAApAsABNwL0KSAAQYAqakHdADYCACAAQYwqaiAAKAK8ATYCACAAQYQqakLowt2Llq3asO4ANwIAIABBADoApgEgAEHs3AE7AaQBIABBAjoArwEgAEGKKSgAADYAmwEgAEEHOgCjASAAQd4ANgKUASAAQQA6AJ8BIABBhykoAAA2ApgBIABBmCpqIAAoAqwBNgIAIAAgACkCpAE3A5AqIABBnCpqQd4ANgIAIABBqCpqIAAoAqABNgIAIABBoCpqIAApApgBNwMAIABBADoAigEgAEHowgE7AYgBIABBAjoAkwEgAEHxKC0AADoAgAEgAEEFOgCHASAAQd8ANgJ4IABBADoAgQEgAEHtKCgAADYCfCAAQbQqaiAAKAKQATYCACAAIAApAogBNwKsKiAAQbgqakHfADYCACAAQcQqaiAAKAKEATYCACAAQbwqaiAAKQJ8NwIAIABBADoAbiAAQeLCATsBbCAAQQI6AHcgAEGyFCgAADYAYyAAQQc6AGsgAEHgADYCXCAAQQA6AGcgAEGvFCgAADYCYCAAQdAqaiAAKAJ0NgIAIAAgACkCbDcDyCogAEHUKmpB4AA2AgAgAEHgKmogACgCaDYCACAAQdgqaiAAKQJgNwMAIABBADoAUiAAQeruATsBUCAAQQI6AFsgAEEAOgBMIABBCDoATyAAQeEANgJAIABC6sLZi+at2bnlADcCRCAAQewqaiAAKAJYNgIAIAAgACkCUDcC5CogAEHwKmpB4QA2AgAgAEH8KmogACgCTDYCACAAQfQqakLqwtmL5q3ZueUANwIAIABBADoANiAAQfPqATsBNCAAQQI6AD8gAEHWIS0AADoAMCAAQQk6ADMgAEHiADYCJCAAQQA6ADEgAEHOISkAACITNwIoIABBiCtqIAAoAjw2AgAgACAAKQI0NwOAKyAAQYwrakHiADYCACAAQZgraiAAKAIwNgIAIABBkCtqIBM3AwAgAEEDOgAjIABBADoAGyAAQZYfLQAAOgAaIABBlB8vAAA7ARggAEHEIS0AADoAFCAAQQk6ABcgAEHjADYCCCAAQQA6ABUgAEG8ISkAACITNwIMIABBpCtqIAAoAiA2AgAgACAAKQIYNwKcKyAAQagrakHjADYCACAAQbQraiAAKAIUNgIAIABBrCtqIBM3AgBByNc0QgA3AgBBxNc0QcjXNDYCAANAIwBBEGsiCSQAIABBuCtqIhACfyAAQcgVaiAEQRxsaiEFQcjXNCgCACEGAkACQAJAQcjXNCIDQcTXNCgCAEYNAAJAIAZFBEBByNc0IQIDQCACKAIIIgMoAgAgAkYhEiADIQIgEg0ACwwBCyAGIQIDQCACIgMoAgQiAg0ACwsCQCAFKAIEIAUtAAsiAiACwCIOQQBIIggbIgcgAygCFCADLQAbIgIgAsBBAEgiChsiAiACIAdLGyIPBEAgAygCECADQRBqIAobIAUoAgAgBSAIGyAPEEoiCA0BCyACIAdJDQEMAgsgCEEATg0BCyAGRQ0BIAkgAzYCDCADQQRqDAILQcjXNCgCACICRQ0AIAUoAgAgBSAOQQBIGyEOQcjXNCEGA0ACQAJAAkACQAJAAkAgAiIDKAIUIAItABsiAiACwEEASCIKGyICIAcgAiAHSSIPGyIIBEAgDiADKAIQIANBEGogChsiCiAIEEoiEUUEQCACIAdLDQIMAwsgEUEATg0CDAELIAIgB00NAgsgAyEGIAMoAgAiAg0FDAQLIAogDiAIEEoiAg0BCyAPDQEMAgsgAkEATg0BCyADQQRqIQYgAygCBCICDQELCyAJIAM2AgwgBgwBCyAJQcjXNDYCDEHI1zQLIgYoAgAiAgR/QQAFQSwQMiICQRBqIQMCQCAFLAALQQBOBEAgAyAFKQIANwIAIAMgBSgCCDYCCAwBCyADIAUoAgAgBSgCBBBrCyACIAUoAgw2AhwgAkEgaiEDAkAgBSwAG0EATgRAIAMgBSkCEDcCACADIAUoAhg2AggMAQsgAyAFKAIQIAUoAhQQawsgAiAJKAIMNgIIIAJCADcCACAGIAI2AgAgAiEDQcTXNCgCACgCACIFBEBBxNc0IAU2AgAgBigCACEDC0HI1zQoAgAgAxCkAUHM1zRBzNc0KAIAQQFqNgIAQQELOgAEIBAgAjYCACAJQRBqJAAgBEEBaiIEQeQARw0ACyAQIQQDQCAEQQFrLAAAQQBIBEAgBEEMaygCABAvCyAEQRxrIQIgBEERaywAAEEASARAIAIoAgAQLwsgAiIEIABByBVqRw0ACyAALAAXQQBIBEAgACgCDBAvCyAALAAjQQBIBEAgACgCGBAvCyAALAAzQQBIBEAgACgCKBAvCyAALAA/QQBIBEAgACgCNBAvCyAALABPQQBIBEAgACgCRBAvCyAALABbQQBIBEAgACgCUBAvCyAALABrQQBIBEAgACgCYBAvCyAALAB3QQBIBEAgACgCbBAvCyAALACHAUEASARAIAAoAnwQLwsgACwAkwFBAEgEQCAAKAKIARAvCyAALACjAUEASARAIAAoApgBEC8LIAAsAK8BQQBIBEAgACgCpAEQLwsgACwAvwFBAEgEQCAAKAK0ARAvCyAALADLAUEASARAIAAoAsABEC8LIAAsANsBQQBIBEAgACgC0AEQLwsgACwA5wFBAEgEQCAAKALcARAvCyAALAD3AUEASARAIAAoAuwBEC8LIAAsAIMCQQBIBEAgACgC+AEQLwsgACwAkwJBAEgEQCAAKAKIAhAvCyAALACfAkEASARAIAAoApQCEC8LIAAsAK8CQQBIBEAgACgCpAIQLwsgACwAuwJBAEgEQCAAKAKwAhAvCyAALADLAkEASARAIAAoAsACEC8LIAAsANcCQQBIBEAgACgCzAIQLwsgACwA5wJBAEgEQCAAKALcAhAvCyAALADzAkEASARAIAAoAugCEC8LIA0QLyAALAD/AkEASARAIAAoAvQCEC8LIAAsAI8DQQBIBEAgACgChAMQLwsgACwAmwNBAEgEQCAAKAKQAxAvCyAALACrA0EASARAIAAoAqADEC8LIAAsALcDQQBIBEAgACgCrAMQLwsgACwAxwNBAEgEQCAAKAK8AxAvCyAALADTA0EASARAIAAoAsgDEC8LIAAsAOMDQQBIBEAgACgC2AMQLwsgACwA7wNBAEgEQCAAKALkAxAvCyAALAD/A0EASARAIAAoAvQDEC8LIAAsAIsEQQBIBEAgACgCgAQQLwsgDBAvIAAsAJcEQQBIBEAgACgCjAQQLwsgACwApwRBAEgEQCAAKAKcBBAvCyAALACzBEEASARAIAAoAqgEEC8LIAAsAMMEQQBIBEAgACgCuAQQLwsgACwAzwRBAEgEQCAAKALEBBAvCyAALADfBEEASARAIAAoAtQEEC8LIAAsAOsEQQBIBEAgACgC4AQQLwsgACwA+wRBAEgEQCAAKALwBBAvCyAALACHBUEASARAIAAoAvwEEC8LIAAsAJcFQQBIBEAgACgCjAUQLwsgACwAowVBAEgEQCAAKAKYBRAvCyAALACzBUEASARAIAAoAqgFEC8LIAAsAL8FQQBIBEAgACgCtAUQLwsgACwAzwVBAEgEQCAAKALEBRAvCyAALADbBUEASARAIAAoAtAFEC8LIAAsAOsFQQBIBEAgACgC4AUQLwsgACwA9wVBAEgEQCAAKALsBRAvCyAALACHBkEASARAIAAoAvwFEC8LIAAsAJMGQQBIBEAgACgCiAYQLwsgACwAowZBAEgEQCAAKAKYBhAvCyAALACvBkEASARAIAAoAqQGEC8LIAAsAL8GQQBIBEAgACgCtAYQLwsgACwAywZBAEgEQCAAKALABhAvCyAALADbBkEASARAIAAoAtAGEC8LIAAsAOcGQQBIBEAgACgC3AYQLwsgACwA9wZBAEgEQCAAKALsBhAvCyAALACDB0EASARAIAAoAvgGEC8LIAAsAJMHQQBIBEAgACgCiAcQLwsgACwAnwdBAEgEQCAAKAKUBxAvCyAALACvB0EASARAIAAoAqQHEC8LIAAsALsHQQBIBEAgACgCsAcQLwsgACwAywdBAEgEQCAAKALABxAvCyAALADXB0EASARAIAAoAswHEC8LIAAsAOcHQQBIBEAgACgC3AcQLwsgACwA8wdBAEgEQCAAKALoBxAvCyAALACDCEEASARAIAAoAvgHEC8LIAAsAI8IQQBIBEAgACgChAgQLwsgACwAnwhBAEgEQCAAKAKUCBAvCyAALACrCEEASARAIAAoAqAIEC8LIAAsALsIQQBIBEAgACgCsAgQLwsgACwAxwhBAEgEQCAAKAK8CBAvCyAALADXCEEASARAIAAoAswIEC8LIAAsAOMIQQBIBEAgACgC2AgQLwsgACwA8whBAEgEQCAAKALoCBAvCyAALAD/CEEASARAIAAoAvQIEC8LIAAsAI8JQQBIBEAgACgChAkQLwsgACwAmwlBAEgEQCAAKAKQCRAvCyAALACrCUEASARAIAAoAqAJEC8LIAAsALcJQQBIBEAgACgCrAkQLwsgACwAxwlBAEgEQCAAKAK8CRAvCyAALADTCUEASARAIAAoAsgJEC8LIAAsAOMJQQBIBEAgACgC2AkQLwsgACwA7wlBAEgEQCAAKALkCRAvCyAALAD/CUEASARAIAAoAvQJEC8LIAAsAIsKQQBIBEAgACgCgAoQLwsgACwAmwpBAEgEQCAAKAKQChAvCyAALACnCkEASARAIAAoApwKEC8LIAAsALcKQQBIBEAgACgCrAoQLwsgACwAwwpBAEgEQCAAKAK4ChAvCyAALADTCkEASARAIAAoAsgKEC8LIAAsAN8KQQBIBEAgACgC1AoQLwsgACwA7wpBAEgEQCAAKALkChAvCyAALAD7CkEASARAIAAoAvAKEC8LIAAsAIsLQQBIBEAgACgCgAsQLwsgACwAlwtBAEgEQCAAKAKMCxAvCyAALACnC0EASARAIAAoApwLEC8LIAAsALMLQQBIBEAgACgCqAsQLwsgACwAwwtBAEgEQCAAKAK4CxAvCyAALADPC0EASARAIAAoAsQLEC8LIAsQLyAALADbC0EASARAIAAoAtALEC8LIAAsAOsLQQBIBEAgACgC4AsQLwsgACwA9wtBAEgEQCAAKALsCxAvCyAALACHDEEASARAIAAoAvwLEC8LIAAsAJMMQQBIBEAgACgCiAwQLwsgACwAowxBAEgEQCAAKAKYDBAvCyAALACvDEEASARAIAAoAqQMEC8LIAAsAL8MQQBIBEAgACgCtAwQLwsgACwAywxBAEgEQCAAKALADBAvCyAALADbDEEASARAIAAoAtAMEC8LIAAsAOcMQQBIBEAgACgC3AwQLwsgACwA9wxBAEgEQCAAKALsDBAvCyAALACDDUEASARAIAAoAvgMEC8LIAAsAJMNQQBIBEAgACgCiA0QLwsgACwAnw1BAEgEQCAAKAKUDRAvCyAALACvDUEASARAIAAoAqQNEC8LIAAsALsNQQBIBEAgACgCsA0QLwsgACwAyw1BAEgEQCAAKALADRAvCyAALADXDUEASARAIAAoAswNEC8LIAAsAOcNQQBIBEAgACgC3A0QLwsgACwA8w1BAEgEQCAAKALoDRAvCyAALACDDkEASARAIAAoAvgNEC8LIAAsAI8OQQBIBEAgACgChA4QLwsgACwAnw5BAEgEQCAAKAKUDhAvCyAALACrDkEASARAIAAoAqAOEC8LIAAsALsOQQBIBEAgACgCsA4QLwsgACwAxw5BAEgEQCAAKAK8DhAvCyAALADXDkEASARAIAAoAswOEC8LIAAsAOMOQQBIBEAgACgC2A4QLwsgACwA8w5BAEgEQCAAKALoDhAvCyAALAD/DkEASARAIAAoAvQOEC8LIAAsAI8PQQBIBEAgACgChA8QLwsgACwAmw9BAEgEQCAAKAKQDxAvCyAALACrD0EASARAIAAoAqAPEC8LIAAsALcPQQBIBEAgACgCrA8QLwsgACwAxw9BAEgEQCAAKAK8DxAvCyAALADTD0EASARAIAAoAsgPEC8LIAAsAOMPQQBIBEAgACgC2A8QLwsgACwA7w9BAEgEQCAAKALkDxAvCyAALAD/D0EASARAIAAoAvQPEC8LIAAsAIsQQQBIBEAgACgCgBAQLwsgACwAmxBBAEgEQCAAKAKQEBAvCyAALACnEEEASARAIAAoApwQEC8LIAAsALcQQQBIBEAgACgCrBAQLwsgACwAwxBBAEgEQCAAKAK4EBAvCyAALADTEEEASARAIAAoAsgQEC8LIAAsAN8QQQBIBEAgACgC1BAQLwsgACwA7xBBAEgEQCAAKALkEBAvCyAALAD7EEEASARAIAAoAvAQEC8LIAAsAIsRQQBIBEAgACgCgBEQLwsgACwAlxFBAEgEQCAAKAKMERAvCyAALACnEUEASARAIAAoApwREC8LIAAsALMRQQBIBEAgACgCqBEQLwsgACwAwxFBAEgEQCAAKAK4ERAvCyAALADPEUEASARAIAAoAsQREC8LIAAsAN8RQQBIBEAgACgC1BEQLwsgACwA6xFBAEgEQCAAKALgERAvCyAALAD7EUEASARAIAAoAvAREC8LIAAsAIcSQQBIBEAgACgC/BEQLwsgACwAlxJBAEgEQCAAKAKMEhAvCyAALACjEkEASARAIAAoApgSEC8LIAAsALMSQQBIBEAgACgCqBIQLwsgACwAvxJBAEgEQCAAKAK0EhAvCyAALADPEkEASARAIAAoAsQSEC8LIAAsANsSQQBIBEAgACgC0BIQLwsgACwA6xJBAEgEQCAAKALgEhAvCyAALAD3EkEASARAIAAoAuwSEC8LIAAsAIcTQQBIBEAgACgC/BIQLwsgACwAkxNBAEgEQCAAKAKIExAvCyAALACjE0EASARAIAAoApgTEC8LIAAsAK8TQQBIBEAgACgCpBMQLwsgACwAvxNBAEgEQCAAKAK0ExAvCyAALADLE0EASARAIAAoAsATEC8LIAAsANsTQQBIBEAgACgC0BMQLwsgACwA5xNBAEgEQCAAKALcExAvCyAALAD3E0EASARAIAAoAuwTEC8LIAAsAIMUQQBIBEAgACgC+BMQLwsgACwAkxRBAEgEQCAAKAKIFBAvCyAALACfFEEASARAIAAoApQUEC8LIAAsAK8UQQBIBEAgACgCpBQQLwsgACwAuxRBAEgEQCAAKAKwFBAvCyAALADLFEEASARAIAAoAsAUEC8LIAAsANcUQQBIBEAgACgCzBQQLwsgACwA5xRBAEgEQCAAKALcFBAvCyAALADzFEEASARAIAAoAugUEC8LIAAsAIMVQQBIBEAgACgC+BQQLwsgACwAjxVBAEgEQCAAKAKEFRAvCyAALACfFUEASARAIAAoApQVEC8LIAAsAKsVQQBIBEAgACgCoBUQLwsgACwAuxVBAEgEQCAAKAKwFRAvCyAALADHFUEASARAIAAoArwVEC8LIABBwCtqJAAgAUEBOgAfIAFBIjsBCCABQYHGADsAEyABQQE6ACsgAUEAOgAVIAFBAToANyABQSg7ASAgAUEBOgBDIAFBKTsBLCABQQE6AE8gAUEqOwE4IAFBAToAWyABQSs7AUQgAUEBOgBnIAFBLzsBUCABQTo7AVwgAUEBOgBzIAFBOzsBaCABQQE6AH8gAUEBOgCLASABQTw7AXQgAUE9OwGAASABQQE6AJcBIAFBPjsBjAEgAUEBOgCjASABQcAAOwGYASABQQE6AK8BIAFB2wA7AaQBIAFBAToAuwEgAUHcADsBsAEgAUEBOgDHASABQd0AOwG8ASABQQE6ANMBIAFB3gA7AcgBIAFBAToA3wEgAUHfADsB1AEgAUEBOgDrASABQcAILQAAOgCeAiABQbwILQAAOgCqAiABQQE6APcBIAFB4AA7AeABIAFBAToAgwIgAUH7ADsB7AEgAUH8ADsB+AEgAUEBOgCPAiABQf0AOwGEAiABQQE6AJsCIAFB/gA7AZACIAFBAzoApwIgAUEDOgCzAiABQQA6AJ8CIAFBvggvAAA7AZwCIAFBuggvAAA7AagCIAFBuAgtAAA6ALYCIAFBtAgtAAA6AMICIAFBAzoAvwIgAUEAOgCrAiABQQM6AMsCIAFBADoAtwIgAUECOgDXAiABQQA6AMMCIAFBvPgAOwHMAiABQQA6AM4CIAFBAjoA4wIgAUEDOgDvAiABQQA6ANoCIAFBvvwAOwHYAiABQbYILwAAOwG0AiABQbIILwAAOwHAAiABQZY5LQAAOgDmAiABQZQ5LwAAOwHkAiABQQM6APsCIAFBADoA5wIgAUGSOS0AADoA8gIgAUGQOS8AADsB8AIgAUECOgCHAyABQQA6APMCIAFBAzoAkwMgAUEAOgD+AiABQa3aADsB/AIgAUHVygAtAAA6AIoDIAFB08oALwAAOwGIAyABQQI6AJ8DIAFBADoAiwMgAUECOgCrAyABQQA6AJYDIAFBrdAAOwGUAyABQQI6ALcDIAFBADoAogMgAUGttgE7AaADIAFBAjoAwwMgAUEAOgCuAyABQajOADsBrAMgAUECOgDPAyABQQA6ALoDIAFBqMQAOwG4AyABQQI6ANsDIAFBADoAxgMgAUGo0AA7AcQDIAFBAzoA5wMgAUEAOgDSAyABQanSADsB0AMgAUGR3AAtAAA6AN4DIAFBj9wALwAAOwHcAyABQQM6APMDIAFBADoA3wMgAUGC3AAtAAA6AOoDIAFBgNwALwAAOwHoAyABQQI6AP8DIAFBADoA6wMgAUECOgCLBCABQQA6APYDIAFB27YBOwH0AyABQQI6AJcEIAFBADoAggQgAUHdugE7AYAEIAFBAjoAowQgAUEAOgCOBCABQfv2ATsBjAQgAUEGOgCvBCABQQA6AJoEIAFB/foBOwGYBCABQasILwAAOwGoBCABQacIKAAANgKkBCABQQk6ALsEIAFBADoAqgQgAUGsCC0AADoAuAQgAUGkCCkAADcCsAQgAUEDOgDHBCABQQA6ALkEIAFBsAgtAAA6AL4EIAFBrggvAAA7AbwEIAFBAzoA0wQgAUEAOgC/BCABQawILQAAOgDKBCABQaoILwAAOwHIBCABQQM6AN8EIAFBADoAywQgAUGiCC0AADoA1gQgAUGgCC8AADsB1AQgAUEDOgDrBCABQQA6ANcEIAFBnggtAAA6AOIEIAFBnAgvAAA7AeAEIAFBAzoA9wQgAUEAOgDjBCABQZoILQAAOgDuBCABQZgILwAAOwHsBCABQQM6AIMFIAFBADoA7wQgAUGWCC0AADoA+gQgAUGUCC8AADsB+AQgAUEDOgCPBSABQQA6APsEIAFBkggtAAA6AIYFIAFBkAgvAAA7AYQFIAFBADoAhwVB4Nc0QQA2AgBB5Nc0QQA2AgBB5Nc0QYgFEDIiAjYCAEHg1zQgAjYCAEHo1zQgAkGIBWo2AgBBACEEA0ACQCABQQhqIARBDGxqIgMsAAtBAE4EQCACIAMpAgA3AgAgAiADKAIINgIIDAELIAIgAygCACADKAIEEGsLIAJBDGohAiAEQQFqIgRBNkcNAAtB5Nc0IAI2AgAgAUGQBWohBANAIARBDGshAiAEQQFrLAAAQQBIBEAgAigCABAvCyACIgQgAUEIakcNAAsgAUGQBWokAEGE8TRBuQE2AgBBiPE0QQA2AgAQsARBiPE0QYDxNCgCADYCAEGA8TRBhPE0NgIAC5sHBAR/BHsBfAF9IABBcHEiBkEASgRAA0AgCCACIAdBAXQiBWoiBC8BHkECdEGQ1gRqIAQvARxBAnRBkNYEaiAELwEaQQJ0QZDWBGogBC8BGEECdEGQ1gRq/QkCAP1WAgAB/VYCAAL9VgIAAyADIAVqIgUvAR5BAnRBkNYEaiAFLwEcQQJ0QZDWBGogBS8BGkECdEGQ1gRqIAUvARhBAnRBkNYEav0JAgD9VgIAAf1WAgAC/VYCAAP95gH95AEhCCAJIAQvARZBAnRBkNYEaiAELwEUQQJ0QZDWBGogBC8BEkECdEGQ1gRqIAQvARBBAnRBkNYEav0JAgD9VgIAAf1WAgAC/VYCAAMgBS8BFkECdEGQ1gRqIAUvARRBAnRBkNYEaiAFLwESQQJ0QZDWBGogBS8BEEECdEGQ1gRq/QkCAP1WAgAB/VYCAAL9VgIAA/3mAf3kASEJIAogBC8BDkECdEGQ1gRqIAQvAQxBAnRBkNYEaiAELwEKQQJ0QZDWBGogBC8BCEECdEGQ1gRq/QkCAP1WAgAB/VYCAAL9VgIAAyAFLwEOQQJ0QZDWBGogBS8BDEECdEGQ1gRqIAUvAQpBAnRBkNYEaiAFLwEIQQJ0QZDWBGr9CQIA/VYCAAH9VgIAAv1WAgAD/eYB/eQBIQogCyAELwEGQQJ0QZDWBGogBC8BBEECdEGQ1gRqIAQvAQJBAnRBkNYEaiAELwEAQQJ0QZDWBGr9CQIA/VYCAAH9VgIAAv1WAgADIAUvAQZBAnRBkNYEaiAFLwEEQQJ0QZDWBGogBS8BAkECdEGQ1gRqIAUvAQBBAnRBkNYEav0JAgD9VgIAAf1WAgAC/VYCAAP95gH95AEhCyAHQRBqIgcgBkgNAAsgCyAJ/eQBIAogCP3kAf3kASEICyAI/R8DIAj9HwIgCP0fACAI/R8BkpKSIQ0gASAAIAZKBH0gBkF/cyEEIA27IQwgAEEBcQRAIAwgAiAGQQF0IgVqLwEAQQJ0QZDWBGoqAgAgAyAFai8BAEECdEGQ1gRqKgIAlLugIQwgBkEBciEGC0EAIABrIARHBEADQCAMIAIgBkEBdCIEai8BAEECdEGQ1gRqKgIAIAMgBGovAQBBAnRBkNYEaioCAJS7oCACIARBAmoiBGovAQBBAnRBkNYEaioCACADIARqLwEAQQJ0QZDWBGoqAgCUu6AhDCAGQQJqIgYgAEcNAAsLIAy2BSANCzgCAAuHAwMGfwR7AX0gAEFwcSIGQQBKBEADQCACIARBAnQiB2oiBf0AADAgAyAHaiIH/QAAMP3mASAK/eQBIQogBf0AACAgB/0AACD95gEgC/3kASELIAX9AAAQIAf9AAAQ/eYBIAz95AEhDCAF/QAAACAH/QAAAP3mASAN/eQBIQ0gBEEQaiIEIAZIDQALIA0gC/3kASAMIAr95AH95AEhCgsgCv0fAyAK/R8CIAr9HwAgCv0fAZKSkiEOAkAgACAGTA0AIAZBf3MgAGohCSAAQQNxIgcEQEEAIQQDQCACIAZBAnQiCGoqAgAgAyAIaioCAJQgDpIhDiAGQQFqIQYgBEEBaiIEIAdHDQALCyAJQQJNDQADQCACIAZBAnQiBEEMaiIFaioCACADIAVqKgIAlCACIARBCGoiBWoqAgAgAyAFaioCAJQgAiAEQQRqIgVqKgIAIAMgBWoqAgCUIAIgBGoqAgAgAyAEaioCAJQgDpKSkpIhDiAGQQRqIgYgAEcNAAsLIAEgDjgCAAslACABIAIgAyAEIAUgBq0gB61CIIaEIAitIAmtQiCGhCAAERgACyMAIAEgAiADIAQgBa0gBq1CIIaEIAetIAitQiCGhCAAERkACxkAIAEgAiADIAQgBa0gBq1CIIaEIAARFAALGQAgASACIAOtIAStQiCGhCAFIAYgABEaAAsiAQF+IAEgAq0gA61CIIaEIAQgABETACIFQiCIpyQJIAWnCygAIAAkAyABJAQgAiQFIAMkBgJAIAJFDQAgBEUNAEGMuQMgBDYCAAsLEAAjACAAa0FwcSIAJAAgAAsGACAAJAALBAAjAAsFAEH3GwsFAEGnJgsFAEHGFgsXACAARQRAQQAPCyAAQcixAxD/AkEARwsbACAAIAEoAgggBRBvBEAgASACIAMgBBCXAgsLOAAgACABKAIIIAUQbwRAIAEgAiADIAQQlwIPCyAAKAIIIgAgASACIAMgBCAFIAAoAgAoAhQRDAALkAIBB38gACABKAIIIAUQbwRAIAEgAiADIAQQlwIPCyABLQA1IQYgACgCDCEIIAFBADoANSABLQA0IQcgAUEAOgA0IABBEGoiDCABIAIgAyAEIAUQlgIgAS0ANCIKIAdyQQBHIQcgAS0ANSILIAZyQQBHIQYCQCAAQRhqIgkgDCAIQQN0aiIITw0AA0AgAS0ANg0BAkAgCgRAIAEoAhhBAUYNAyAALQAIQQJxDQEMAwsgC0UNACAALQAIQQFxRQ0CCyABQQA7ATQgCSABIAIgAyAEIAUQlgIgBiABLQA1IgtyQQBHIQYgByABLQA0IgpyQQBHIQcgCUEIaiIJIAhJDQALCyABIAY6ADUgASAHOgA0C6cBACAAIAEoAgggBBBvBEACQCABKAIEIAJHDQAgASgCHEEBRg0AIAEgAzYCHAsPCwJAIAAgASgCACAEEG9FDQACQCACIAEoAhBHBEAgASgCFCACRw0BCyADQQFHDQEgAUEBNgIgDwsgASACNgIUIAEgAzYCICABIAEoAihBAWo2AigCQCABKAIkQQFHDQAgASgCGEECRw0AIAFBAToANgsgAUEENgIsCwuIAgAgACABKAIIIAQQbwRAAkAgASgCBCACRw0AIAEoAhxBAUYNACABIAM2AhwLDwsCQCAAIAEoAgAgBBBvBEACQCACIAEoAhBHBEAgASgCFCACRw0BCyADQQFHDQIgAUEBNgIgDwsgASADNgIgAkAgASgCLEEERg0AIAFBADsBNCAAKAIIIgAgASACIAJBASAEIAAoAgAoAhQRDAAgAS0ANQRAIAFBAzYCLCABLQA0RQ0BDAMLIAFBBDYCLAsgASACNgIUIAEgASgCKEEBajYCKCABKAIkQQFHDQEgASgCGEECRw0BIAFBAToANg8LIAAoAggiACABIAIgAyAEIAAoAgAoAhgRCwALC7IEAQN/IAAgASgCCCAEEG8EQAJAIAEoAgQgAkcNACABKAIcQQFGDQAgASADNgIcCw8LAkAgACABKAIAIAQQbwRAAkAgAiABKAIQRwRAIAEoAhQgAkcNAQsgA0EBRw0CIAFBATYCIA8LIAEgAzYCICABKAIsQQRHBEAgAEEQaiIFIAAoAgxBA3RqIQZBACEDIAECfwJAA0ACQCAFIAZPDQAgAUEAOwE0IAUgASACIAJBASAEEJYCIAEtADYNAAJAIAEtADVFDQAgAS0ANARAIAEoAhhBAUcEQEEBIQNBASEHIAAtAAhBAnENAgsgAUEDNgIsDwtBASEDIAAtAAhBAXFFDQMLIAVBCGohBQwBCwtBBCADRQ0BGgtBAws2AiwgBw0CCyABIAI2AhQgASABKAIoQQFqNgIoIAEoAiRBAUcNASABKAIYQQJHDQEgAUEBOgA2DwsgACgCDCEGIABBEGoiByABIAIgAyAEENwBIABBGGoiBSAHIAZBA3RqIgZPDQACQCAAKAIIIgBBAnFFBEAgASgCJEEBRw0BCwNAIAEtADYNAiAFIAEgAiADIAQQ3AEgBUEIaiIFIAZJDQALDAELIABBAXFFBEADQCABLQA2DQIgASgCJEEBRg0CIAUgASACIAMgBBDcASAFQQhqIgUgBkkNAAwCCwALA0AgAS0ANg0BIAEoAiRBAUYEQCABKAIYQQFGDQILIAUgASACIAMgBBDcASAFQQhqIgUgBkkNAAsLC2sBAn8gACABKAIIQQAQbwRAIAEgAiADEJgCDwsgACgCDCEEIABBEGoiBSABIAIgAxD+AgJAIABBGGoiACAFIARBA3RqIgRPDQADQCAAIAEgAiADEP4CIAEtADYNASAAQQhqIgAgBEkNAAsLCzIAIAAgASgCCEEAEG8EQCABIAIgAxCYAg8LIAAoAggiACABIAIgAyAAKAIAKAIcEQYACxkAIAAgASgCCEEAEG8EQCABIAIgAxCYAgsLngEBAn8jAEFAaiIDJAACf0EBIAAgAUEAEG8NABpBACABRQ0AGkEAIAFB6LADEP8CIgFFDQAaIANBDGpBAEE0/AsAIANBATYCOCADQX82AhQgAyAANgIQIAMgATYCCCABIANBCGogAigCAEEBIAEoAgAoAhwRBgAgAygCICIAQQFGBEAgAiADKAIYNgIACyAAQQFGCyEEIANBQGskACAECwoAIAAgAUEAEG8LjAUBB38jAEEQayIDJAAgAEEMaiIEKAIAIQIjAEEQayIBJAAgASACNgIMIAEoAgwhAiABQRBqJAAgAyACNgIMIAAoAhAhAiMAQRBrIgEkACABIAI2AgwgASgCDCECIAFBEGokACADIAI2AggDQCADKAIMIgEgAygCCEcEQCABKAIAEJADIAMoAgwoAgQQjwMgAyADKAIMQQhqNgIMDAEFAkAgACgCACECIwBBEGsiASQAIAEgAjYCDCABKAIMIQIgAUEQaiQAIAMgAjYCDCAAKAIEIQIjAEEQayIBJAAgASACNgIMIAEoAgwhAiABQRBqJAAgAyACNgIIA0AgAygCDCIBIAMoAghGDQEgASgCACECIwBBEGsiASQAIAFBAToADCABIAJBDGoiBTYCCCAFEFYEQBBGAAsgAiACKAJUQQRyNgJUIAJBJGoQkAMgAS0ADARAIAEoAggQjwMLIAFBEGokACADKAIMKAIAIgFBBGpBf/4eAgBFBEAgASABKAIAKAIIEQEACyADIAMoAgxBBGo2AgwMAAsACwsLIwBBEGsiAiQAIAIgBDYCDCACKAIMIgEoAgAaIAEoAgQhBCABKAIIGiABKAIAIgUEQANAIAQgBUcEQCAEQQhrIQQMAQsLIAEgBTYCBCACKAIMIgEoAgAhBiABKAIIGiABKAIAGiAGEC8LIAJBEGokACMAQRBrIgEkACABIAA2AgwgASgCDCIAKAIEGiAAKAIIGiAAKAIAGiAAKAIABEAgACgCACEEIAAoAgQhAgNAIAIgBEcEQCACQQRrIQIMAQsLIAAgBDYCBCABKAIMIgAoAgAhByAAKAIIGiAAKAIAGiAHEC8LIAFBEGokACADQRBqJAALEQAgAARAIAAQ3QEaCyAAEC8LVAEBfyABAn8gASgCCCICIAEoAgxHBEACQAJAIAIsAABBCmsOBAEAAAEACyABQZ14NgIAIAEgAkEBajYCCCAAKAIEDAILCyABQZ94NgIAQQALNgIoCwcAIAAQlAILAwAACwkAQYSMNRBQGgswAAJAQZCMNf4SAABBAXENAEGQjDUQVEUNAEGEjDVB2PcCELoBQZCMNRBTC0GEjDULCQBB9Is1EDMaCzAAAkBBgIw1/hIAAEEBcQ0AQYCMNRBURQ0AQfSLNUHwFRCmARpBgIw1EFMLQfSLNQsJAEHkizUQUBoLMAACQEHwizX+EgAAQQFxDQBB8Is1EFRFDQBB5Is1QYT3AhC6AUHwizUQUwtB5Is1CwkAQdSLNRAzGgswAAJAQeCLNf4SAABBAXENAEHgizUQVEUNAEHUizVB9CoQpgEaQeCLNRBTC0HUizULCQBBxIs1EFAaCzAAAkBB0Is1/hIAAEEBcQ0AQdCLNRBURQ0AQcSLNUHg9gIQugFB0Is1EFMLQcSLNQsJAEG0izUQMxoLMAACQEHAizX+EgAAQQFxDQBBwIs1EFRFDQBBtIs1QZcuEKYBGkHAizUQUwtBtIs1CwkAQaSLNRBQGgswAAJAQbCLNf4SAABBAXENAEGwizUQVEUNAEGkizVBvPYCELoBQbCLNRBTC0GkizULCQBBlIs1EDMaCzAAAkBBoIs1/hIAAEEBcQ0AQaCLNRBURQ0AQZSLNUG6CRCmARpBoIs1EFMLQZSLNQsbAEGYlDUhAANAIABBDGsQUCIAQYCUNUcNAAsLZgACQEGQizX+EgAAQQFxDQBBkIs1EFRFDQACQEGYlDX+EgAAQQFxDQBBmJQ1EFRFDQBBmJQ1EFMLQYCUNUHQnwMQQEGMlDVB3J8DEEBBjIs1QYCUNTYCAEGQizUQUwtBjIs1KAIACxsAQfiTNSEAA0AgAEEMaxAzIgBB4JM1Rw0ACwtkAAJAQYiLNf4SAABBAXENAEGIizUQVEUNAAJAQfiTNf4SAABBAXENAEH4kzUQVEUNAEH4kzUQUwtB4JM1QYEvEEFB7JM1Qf4uEEFBhIs1QeCTNTYCAEGIizUQUwtBhIs1KAIACxsAQdCTNSEAA0AgAEEMaxBQIgBBsJE1Rw0ACwvCAgACQEGAizX+EgAAQQFxDQBBgIs1EFRFDQACQEHQkzX+EgAAQQFxDQBB0JM1EFRFDQBB0JM1EFMLQbCRNUHImwMQQEG8kTVB6JsDEEBByJE1QYycAxBAQdSRNUGknAMQQEHgkTVBvJwDEEBB7JE1QcycAxBAQfiRNUHgnAMQQEGEkjVB9JwDEEBBkJI1QZCdAxBAQZySNUG4nQMQQEGokjVB2J0DEEBBtJI1QfydAxBAQcCSNUGgngMQQEHMkjVBsJ4DEEBB2JI1QcCeAxBAQeSSNUHQngMQQEHwkjVBvJwDEEBB/JI1QeCeAxBAQYiTNUHwngMQQEGUkzVBgJ8DEEBBoJM1QZCfAxBAQayTNUGgnwMQQEG4kzVBsJ8DEEBBxJM1QcCfAxBAQfyKNUGwkTU2AgBBgIs1EFMLQfyKNSgCAAu+wQIFP38KfAJ+AX0DeyMAQdADayISJAACQAJAQdC7AygCAEUEQEF/IQAMAQsgEkEANgKEAhCcAiEDIBJCADcCkAIgEkGAgAE2AowCIBJBADoAmAIgEkL/////j4CAwL9/NwL4AiASQpqz5vhzNwLwAiASQpqz5oCEgIDAv383AugCIBL9DAAAAAAAAIA/AACAv83MTD79CwLYAiASQQA6ANYCIBJBgAI7AdQCIBJBgxg2AtACIBJBADYCzAIgEkIANwLEAiASQQA6AMACIBJBADYCvAIgEkEAOwG4AiASQQA2ArQCIBJBADoAsAIgEkEANgKsAiASQoquj+Gj4fWRPDcCpAIgEkKBgICAkIDAADcAmQIgEkEEIAMgA0EEThs2AogCIBL9DAAAAAAAAAAAAAAAAAAAAAD9CwKgAyAS/QwAAAAAAAAAAAAAAAAAAAAA/QsCkAMgEv0MAAAAAAAAAAAAAAAAAAAAAP0LAoADIBJCgICAgICAgOTCADcCsAMgEkEFNgL0AiASQYCAhAg2ApwCIBIgAjoAmAIgEkGDGCABKAIAIAEgASwAC0EASBtB0LsDKAIAKALAAUGYlQNMGzYC0AIQnAIhASASQQA2ApACIBJBCCABIAFBCE4bNgKIAiASQQA2AoACIBJCADcC+AEgACgCAEGFHBAIIgIQByEBIAIQBCABQfyyAyASQbgDahAVIUMgEigCuAMQFCABEARBpjkQEyIvQckUEAgiARAHISkgARAEAn8gQ5lEAAAAAAAA4EFjBEAgQ6oMAQtBgICAgHgLIgEEQCASQfgBaiABEG4LIAAoAgBB1hMQCCIDEAchAiADEAQgEigC+AEhAyApEAogEiABNgLIAyASIAM2AsADIBIgKTYCuAMgAkEDQfT6ACASQbgDahASISsgAhAEAkAjCi0AAEEBcQRAIwshAQwBCyMKITFBAkGA+wAQLiECIDFBAToAACMLIgEgAjYCAAsgASgCACEyIAAoAgAQCiASIAAoAgA2ArgDIDIgK0HkDiASQbgDahAtEMYCIBIoAogCIQIQnAIhAyMAQTBrIgAkAAJAQdzXNP4SAABBAXENAEHc1zQQVEUNAEHQ1zRCADcCAEHY1zRBADYCAEHc1zQQUwsCf0Hb1zQsAABBAEgEQEHU1zRBADYCAEHQ1zQoAgAMAQtB29c0QQA6AABB0Nc0C0EAOgAAIABBBGoiAUEAEDkgACABQffgABA4IgEoAgg2AhggACABKQIANwMQIAFCADcCACABQQA2AgggACAAQRBqQfPgABA3IgEoAgg2AiggACABKQIANwMgIAFCADcCACABQQA2AghB0Nc0IAAoAiAgAEEgaiAALQArIgHAQQBIIgQbIAAoAiQgASAEGxBfGiAALAArQQBIBEAgACgCIBAvCyAALAAbQQBIBEAgACgCEBAvCyAALAAPQQBIBEAgACgCBBAvCyAAQQRqIgFBABA5IAAgAUHw4QAQOCIBKAIINgIYIAAgASkCADcDECABQgA3AgAgAUEANgIIIAAgAEEQakHz4AAQNyIBKAIINgIoIAAgASkCADcDICABQgA3AgAgAUEANgIIQdDXNCAAKAIgIABBIGogAC0AKyIBwEEASCIEGyAAKAIkIAEgBBsQXxogACwAK0EASARAIAAoAiAQLwsgACwAG0EASARAIAAoAhAQLwsgACwAD0EASARAIAAoAgQQLwsgAEEEaiIBQQAQOSAAIAFB+OEAEDgiASgCCDYCGCAAIAEpAgA3AxAgAUIANwIAIAFBADYCCCAAIABBEGpB8+AAEDciASgCCDYCKCAAIAEpAgA3AyAgAUIANwIAIAFBADYCCEHQ1zQgACgCICAAQSBqIAAtACsiAcBBAEgiBBsgACgCJCABIAQbEF8aIAAsACtBAEgEQCAAKAIgEC8LIAAsABtBAEgEQCAAKAIQEC8LIAAsAA9BAEgEQCAAKAIEEC8LIABBBGoiAUEAEDkgACABQdjhABA4IgEoAgg2AhggACABKQIANwMQIAFCADcCACABQQA2AgggACAAQRBqQfPgABA3IgEoAgg2AiggACABKQIANwMgIAFCADcCACABQQA2AghB0Nc0IAAoAiAgAEEgaiAALQArIgHAQQBIIgQbIAAoAiQgASAEGxBfGiAALAArQQBIBEAgACgCIBAvCyAALAAbQQBIBEAgACgCEBAvCyAALAAPQQBIBEAgACgCBBAvCyAAQQRqIgFBABA5IAAgAUGZ4QAQOCIBKAIINgIYIAAgASkCADcDECABQgA3AgAgAUEANgIIIAAgAEEQakHz4AAQNyIBKAIINgIoIAAgASkCADcDICABQgA3AgAgAUEANgIIQdDXNCAAKAIgIABBIGogAC0AKyIBwEEASCIEGyAAKAIkIAEgBBsQXxogACwAK0EASARAIAAoAiAQLwsgACwAG0EASARAIAAoAhAQLwsgACwAD0EASARAIAAoAgQQLwsgAEEEaiIBQQAQOSAAIAFB1OEAEDgiASgCCDYCGCAAIAEpAgA3AxAgAUIANwIAIAFBADYCCCAAIABBEGpB8+AAEDciASgCCDYCKCAAIAEpAgA3AyAgAUIANwIAIAFBADYCCEHQ1zQgACgCICAAQSBqIAAtACsiAcBBAEgiBBsgACgCJCABIAQbEF8aIAAsACtBAEgEQCAAKAIgEC8LIAAsABtBAEgEQCAAKAIQEC8LIAAsAA9BAEgEQCAAKAIEEC8LIABBBGoiAUEAEDkgACABQavhABA4IgEoAgg2AhggACABKQIANwMQIAFCADcCACABQQA2AgggACAAQRBqQfPgABA3IgEoAgg2AiggACABKQIANwMgIAFCADcCACABQQA2AghB0Nc0IAAoAiAgAEEgaiAALQArIgHAQQBIIgQbIAAoAiQgASAEGxBfGiAALAArQQBIBEAgACgCIBAvCyAALAAbQQBIBEAgACgCEBAvCyAALAAPQQBIBEAgACgCBBAvCyAAQQRqIgFBABA5IAAgAUHB4QAQOCIBKAIINgIYIAAgASkCADcDECABQgA3AgAgAUEANgIIIAAgAEEQakHz4AAQNyIBKAIINgIoIAAgASkCADcDICABQgA3AgAgAUEANgIIQdDXNCAAKAIgIABBIGogAC0AKyIBwEEASCIEGyAAKAIkIAEgBBsQXxogACwAK0EASARAIAAoAiAQLwsgACwAG0EASARAIAAoAhAQLwsgACwAD0EASARAIAAoAgQQLwsgAEEEaiIBQQAQOSAAIAFByeEAEDgiASgCCDYCGCAAIAEpAgA3AxAgAUIANwIAIAFBADYCCCAAIABBEGpB8+AAEDciASgCCDYCKCAAIAEpAgA3AyAgAUIANwIAIAFBADYCCEHQ1zQgACgCICAAQSBqIAAtACsiAcBBAEgiBBsgACgCJCABIAQbEF8aIAAsACtBAEgEQCAAKAIgEC8LIAAsABtBAEgEQCAAKAIQEC8LIAAsAA9BAEgEQCAAKAIEEC8LIABBBGoiAUEBEDkgACABQbThABA4IgEoAgg2AhggACABKQIANwMQIAFCADcCACABQQA2AgggACAAQRBqQfPgABA3IgEoAgg2AiggACABKQIANwMgIAFCADcCACABQQA2AghB0Nc0IAAoAiAgAEEgaiAALQArIgHAQQBIIgQbIAAoAiQgASAEGxBfGiAALAArQQBIBEAgACgCIBAvCyAALAAbQQBIBEAgACgCEBAvCyAALAAPQQBIBEAgACgCBBAvCyAAQQRqIgFBABA5IAAgAUGF4QAQOCIBKAIINgIYIAAgASkCADcDECABQgA3AgAgAUEANgIIIAAgAEEQakHz4AAQNyIBKAIINgIoIAAgASkCADcDICABQgA3AgAgAUEANgIIQdDXNCAAKAIgIABBIGogAC0AKyIBwEEASCIEGyAAKAIkIAEgBBsQXxogACwAK0EASARAIAAoAiAQLwsgACwAG0EASARAIAAoAhAQLwsgACwAD0EASARAIAAoAgQQLwsgAEEEaiIBQQAQOSAAIAFB6OEAEDgiASgCCDYCGCAAIAEpAgA3AxAgAUIANwIAIAFBADYCCCAAIABBEGpB8+AAEDciASgCCDYCKCAAIAEpAgA3AyAgAUIANwIAIAFBADYCCEHQ1zQgACgCICAAQSBqIAAtACsiAcBBAEgiBBsgACgCJCABIAQbEF8aIAAsACtBAEgEQCAAKAIgEC8LIAAsABtBAEgEQCAAKAIQEC8LIAAsAA9BAEgEQCAAKAIEEC8LIABBBGoiAUEAEDkgACABQefhABA4IgEoAgg2AhggACABKQIANwMQIAFCADcCACABQQA2AgggACAAQRBqQfPgABA3IgEoAgg2AiggACABKQIANwMgIAFCADcCACABQQA2AghB0Nc0IAAoAiAgAEEgaiAALQArIgHAQQBIIgQbIAAoAiQgASAEGxBfGiAALAArQQBIBEAgACgCIBAvCyAALAAbQQBIBEAgACgCEBAvCyAALAAPQQBIBEAgACgCBBAvCyAAQQRqIgFBABA5IAAgAUH+4AAQOCIBKAIINgIYIAAgASkCADcDECABQgA3AgAgAUEANgIIIAAgAEEQakHz4AAQNyIBKAIINgIoIAAgASkCADcDICABQgA3AgAgAUEANgIIQdDXNCAAKAIgIABBIGogAC0AKyIBwEEASCIEGyAAKAIkIAEgBBsQXxogACwAK0EASARAIAAoAiAQLwsgACwAG0EASARAIAAoAhAQLwsgACwAD0EASARAIAAoAgQQLwsgAEEEaiIBQQAQOSAAIAFB3+EAEDgiASgCCDYCGCAAIAEpAgA3AxAgAUIANwIAIAFBADYCCCAAIABBEGpB8+AAEDciASgCCDYCKCAAIAEpAgA3AyAgAUIANwIAIAFBADYCCEHQ1zQgACgCICAAQSBqIAAtACsiAcBBAEgiBBsgACgCJCABIAQbEF8aIAAsACtBAEgEQCAAKAIgEC8LIAAsABtBAEgEQCAAKAIQEC8LIAAsAA9BAEgEQCAAKAIEEC8LIABBBGoiAUEAEDkgACABQaHhABA4IgEoAgg2AhggACABKQIANwMQIAFCADcCACABQQA2AgggACAAQRBqQfPgABA3IgEoAgg2AiggACABKQIANwMgIAFCADcCACABQQA2AghB0Nc0IAAoAiAgAEEgaiAALQArIgHAQQBIIgQbIAAoAiQgASAEGxBfGiAALAArQQBIBEAgACgCIBAvCyAALAAbQQBIBEAgACgCEBAvCyAALAAPQQBIBEAgACgCBBAvCyAAQQRqIgFBABA5IAAgAUGN4QAQOCIBKAIINgIYIAAgASkCADcDECABQgA3AgAgAUEANgIIIAAgAEEQakHz4AAQNyIBKAIINgIoIAAgASkCADcDICABQgA3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QTBqIQEgAkEwaiICIA1HDQALCyADIAE2AgQMAgsgASACIBH8CgAAIAMgASAMQTBsajYCBAwBCyABBEAgAyABNgIEIAEQLyADQQA2AgggA0IANwIAQQAhBwsgDEHWqtUqTw0CQdWq1SogB0EwbSIBQQF0IgcgDCAHIAxLGyABQarVqhVPGyIBQdaq1SpPDQIgAyABQTBsIgcQMiIBNgIEIAMgATYCACADIAEgB2o2AgggAyACIA1HBH8gASACIBFBMGsiAiACQTBwa0EwaiIC/AoAACABIAJqBSABCzYCBAsgAyAEKAJENgI0IAMgBCkCPDcCLCADIAT9AAIs/QsCHCADIAT9AAIc/QsCDCAIQYgCaiIBIARByABqRwRAIAEgBCgCSCAEKAJMENQEIAhBlAJqIAQoAlQgBCgCWBDTBAsgCCAEKQJgNwKgAiAEKAIAIRQgBSgCnBoiCEEANgJMIAgoAlAiEUUNACAGQQhqIQ1BACEMA0AgCCgCWCAMQQR0aiIEQQhqIgMhAiADKAIAIgchAQJAIAdFDQADQCACIAEgASgCECAUSCIPGyECIAFBBGogASAPGygCACIBDQALIAIgA0YNACACKAIQIBRKDQAgBCgCAEH+////B0sNAAJ/A0AgDSAHIgEoAhAiAkgEQCABKAIAIgcNASABDAILIAIgDU4NAiABKAIEIgcNAAsgAUEEagshAkEUEDIiAyABNgIIIANCADcCACADIA02AhAgAiADNgIAIAQoAgQoAgAiAQRAIAQgATYCBCACKAIAIQMLIAMgAyAEKAIIIhFGIgE6AAwCQCABDQADQCADKAIIIgItAAwNAQJAIAIgAigCCCIBKAIAIgdGBEACQCABKAIEIgdFDQAgBy0ADA0ADAILAkAgAyACKAIARgRAIAIhAwwBCyACIAIoAgQiAygCACIHNgIEIAMgBwR/IAcgAjYCCCACKAIIBSABCzYCCCACKAIIIgEgASgCACACR0ECdGogAzYCACADIAI2AgAgAiADNgIIIAMoAggiASgCACECCyADQQE6AAwgAUEAOgAMIAEgAigCBCIDNgIAIAMEQCADIAE2AggLIAIgASgCCDYCCCABKAIIIgMgAygCACABR0ECdGogAjYCACACIAE2AgQgASACNgIIDAMLAkAgB0UNACAHLQAMDQAMAQsCQCADIAIoAgBH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JAAgBSABNgIcAkAgAigCBEEBcUUEQCAAIAEgAiADIAQgACgCACgCGBEKACECDAELIAVBEGoiASACKAIcIgA2AgAgAEEEakEB/h4CABogARDBASEAIAEoAgAiAkEEakF//h4CAEUEQCACIAIoAgAoAggRAQALAkAgBARAIAEgACAAKAIAKAIYEQIADAELIAVBEGogACAAKAIAKAIcEQIACyAFIAVBEGoQdTYCDANAIAUgBUEQaiIAEJ0BNgIIIAUoAgwiASAFKAIIRwRAIAVBHGogASwAABD8AyAFIAUoAgxBAWo2AgwMAQUgBSgCHCECIAAQMxoLCwsgBUEgaiQAIAILwQUBBn8jAEHAAmsiACQAIAAgAjYCuAIgACABNgK8AiMAQRBrIgIkACAAQcQBaiIBQgA3AgAgAUEANgIIIAJBEGokACAAQRBqIgYgAygCHCICNgIAIAJBBGpBAf4eAgAaIAYQbCICQdDqAkHq6gIgAEHQAWogAigCACgCMBEIABogBigCACICQQRqQX/+HgIARQRAIAIgAigCACgCCBEBAAsgASEDIwBBEGsiASQAIABBuAFqIgJCADcCACACQQA2AgggAUEQaiQAIAIgAi0AC0EHdgR/IAIoAghB/////wdxQQFrBUEKCxA6IAACfyACLQALQQd2BEAgAigCAAwBCyACCyIBNgK0ASAAIAY2AgwgAEEANgIIA0ACQCAAQbwCaiAAQbgCahBCDQAgACgCtAECfyACLQALQQd2BEAgAigCBAwBCyACLQALQf8AcQsgAWpGBEACfyACLQALQQd2BEAgAigCBAwBCyACLQALQf8AcQshBiACAn8gAi0AC0EHdgRAIAIoAgQMAQsgAi0AC0H/AHELQQF0EDogAiACLQALQQd2BH8gAigCCEH/////B3FBAWsFQQoLEDogACAGAn8gAi0AC0EHdgRAIAIoAgAMAQsgAgsiAWo2ArQBCwJ/IABBvAJqIgcoAgAiBigCDCIIIAYoAhBGBEAgBiAGKAIAKAIkEQAADAELIAgoAgALQRAgASAAQbQBaiAAQQhqQQAgAyAAQRBqIABBDGogAEHQAWoQvQENACAHEFwaDAELCyACIAAoArQBIAFrEDoCfyACLQALQQd2BEAgAigCAAwBCyACCyELEEQhCSAAIAU2AgAgCyAJIAAQ1ANBAUcEQCAEQQQ2AgALIABBvAJqIABBuAJqEEIEQCAEIAQoAgBBAnI2AgALIAAoArwCIQogAhAzGiADEDMaIABBwAJqJAAgCgvQBQIDfwF+IwBBgANrIgAkACAAIAI2AvgCIAAgATYC/AIgAEHcAWogAyAAQfABaiAAQewBaiAAQegBahCzAiMAQRBrIgIkACAAQdABaiIBQgA3AgAgAUEANgIIIAJBEGokACABIAEtAAtBB3YEfyABKAIIQf////8HcUEBawVBCgsQOiAAAn8gAS0AC0EHdgRAIAEoAgAMAQsgAQsiAjYCzAEgACAAQSBqNgIcIABBADYCGCAAQQE6ABcgAEHFADoAFgNAAkAgAEH8AmogAEH4AmoQQg0AIAAoAswBAn8gAS0AC0EHdgRAIAEoAgQMAQsgAS0AC0H/AHELIAJqRgRAAn8gAS0AC0EHdgRAIAEoAgQMAQsgAS0AC0H/AHELIQMgAQJ/IAEtAAtBB3YEQCABKAIEDAELIAEtAAtB/wBxC0EBdBA6IAEgAS0AC0EHdgR/IAEoAghB/////wdxQQFrBUEKCxA6IAAgAwJ/IAEtAAtBB3YEQCABKAIADAELIAELIgJqNgLMAQsCfyAAQfwCaiIGKAIAIgMoAgwiByADKAIQRgRAIAMgAygCACgCJBEAAAwBCyAHKAIACyAAQRdqIABBFmogAiAAQcwBaiAAKALsASAAKALoASAAQdwBaiAAQSBqIABBHGogAEEYaiAAQfABahCyAg0AIAYQXBoMAQsLAkACfyAALQDnAUEHdgRAIAAoAuABDAELIAAtAOcBQf8AcQtFDQAgAC0AF0UNACAAKAIcIgMgAEEgamtBnwFKDQAgACADQQRqNgIcIAMgACgCGDYCAAsgACACIAAoAswBIAQQ1QMgACkDACEJIAUgACkDCDcDCCAFIAk3AwAgAEHcAWogAEEgaiAAKAIcIAQQZCAAQfwCaiAAQfgCahBCBEAgBCAEKAIAQQJyNgIACyAAKAL8AiEIIAEQMxogAEHcAWoQMxogAEGAA2okACAIC7kFAQN/IwBB8AJrIgAkACAAIAI2AugCIAAgATYC7AIgAEHMAWogAyAAQeABaiAAQdwBaiAAQdgBahCzAiMAQRBrIgIkACAAQcABaiIBQgA3AgAgAUEANgIIIAJBEGokACABIAEtAAtBB3YEfyABKAIIQf////8HcUEBawVBCgsQOiAAAn8gAS0AC0EHdgRAIAEoAgAMAQsgAQsiAjYCvAEgACAAQRBqNgIMIABBADYCCCAAQQE6AAcgAEHFADoABgNAAkAgAEHsAmogAEHoAmoQQg0AIAAoArwBAn8gAS0AC0EHdgRAIAEoAgQMAQsgAS0AC0H/AHELIAJqRgRAAn8gAS0AC0EHdgRAIAEoAgQMAQsgAS0AC0H/AHELIQMgAQJ/IAEtAAtBB3YEQCABKAIEDAELIAEtAAtB/wBxC0EBdBA6IAEgAS0AC0EHdgR/IAEoAghB/////wdxQQFrBUEKCxA6IAAgAwJ/IAEtAAtBB3YEQCABKAIADAELIAELIgJqNgK8AQsCfyAAQewCaiIGKAIAIgMoAgwiByADKAIQRgRAIAMgAygCACgCJBEAAAwBCyAHKAIACyAAQQdqIABBBmogAiAAQbwBaiAAKALcASAAKALYASAAQcwBaiAAQRBqIABBDGogAEEIaiAAQeABahCyAg0AIAYQXBoMAQsLAkACfyAALQDXAUEHdgRAIAAoAtABDAELIAAtANcBQf8AcQtFDQAgAC0AB0UNACAAKAIMIgMgAEEQamtBnwFKDQAgACADQQRqNgIMIAMgACgCCDYCAAsgBSACIAAoArwBIAQQ1gM5AwAgAEHMAWogAEEQaiAAKAIMIAQQZCAAQewCaiAAQegCahBCBEAgBCAEKAIAQQJyNgIACyAAKALsAiEIIAEQMxogAEHMAWoQMxogAEHwAmokACAIC7kFAQN/IwBB8AJrIgAkACAAIAI2AugCIAAgATYC7AIgAEHMAWogAyAAQeABaiAAQdwBaiAAQdgBahCzAiMAQRBrIgIkACAAQcABaiIBQgA3AgAgAUEANgIIIAJBEGokACABIAEtAAtBB3YEfyABKAIIQf////8HcUEBawVBCgsQOiAAAn8gAS0AC0EHdgRAIAEoAgAMAQsgAQsiAjYCvAEgACAAQRBqNgIMIABBADYCCCAAQQE6AAcgAEHFADoABgNAAkAgAEHsAmogAEHoAmoQQg0AIAAoArwBAn8gAS0AC0EHdgRAIAEoAgQMAQsgAS0AC0H/AHELIAJqRgRAAn8gAS0AC0EHdgRAIAEoAgQMAQsgAS0AC0H/AHELIQMgAQJ/IAEtAAtBB3YEQCABKAIEDAELIAEtAAtB/wBxC0EBdBA6IAEgAS0AC0EHdgR/IAEoAghB/////wdxQQFrBUEKCxA6IAAgAwJ/IAEtAAtBB3YEQCABKAIADAELIAELIgJqNgK8AQsCfyAAQewCaiIGKAIAIgMoAgwiByADKAIQRgRAIAMgAygCACgCJBEAAAwBCyAHKAIACyAAQQdqIABBBmogAiAAQbwBaiAAKALcASAAKALYASAAQcwBaiAAQRBqIABBDGogAEEIaiAAQeABahCyAg0AIAYQXBoMAQsLAkACfyAALQDXAUEHdgRAIAAoAtABDAELIAAtANcBQf8AcQtFDQAgAC0AB0UNACAAKAIMIgMgAEEQamtBnwFKDQAgACADQQRqNgIMIAMgACgCCDYCAAsgBSACIAAoArwBIAQQ1wM4AgAgAEHMAWogAEEQaiAAKAIMIAQQZCAAQewCaiAAQegCahBCBEAgBCAEKAIAQQJyNgIACyAAKALsAiEIIAEQMxogAEHMAWoQMxogAEHwAmokACAIC5oFAQV/IwBB0AJrIgAkACAAIAI2AsgCIAAgATYCzAIgAxCMASEGIAMgAEHQAWoQ0AEhByAAQcQBaiADIABBxAJqEM8BIwBBEGsiAiQAIABBuAFqIgFCADcCACABQQA2AgggAkEQaiQAIAEgAS0AC0EHdgR/IAEoAghB/////wdxQQFrBUEKCxA6IAACfyABLQALQQd2BEAgASgCAAwBCyABCyICNgK0ASAAIABBEGo2AgwgAEEANgIIA0ACQCAAQcwCaiAAQcgCahBCDQAgACgCtAECfyABLQALQQd2BEAgASgCBAwBCyABLQALQf8AcQsgAmpGBEACfyABLQALQQd2BEAgASgCBAwBCyABLQALQf8AcQshAyABAn8gAS0AC0EHdgRAIAEoAgQMAQsgAS0AC0H/AHELQQF0EDogASABLQALQQd2BH8gASgCCEH/////B3FBAWsFQQoLEDogACADAn8gAS0AC0EHdgRAIAEoAgAMAQsgAQsiAmo2ArQBCwJ/IABBzAJqIggoAgAiAygCDCIJIAMoAhBGBEAgAyADKAIAKAIkEQAADAELIAkoAgALIAYgAiAAQbQBaiAAQQhqIAAoAsQCIABBxAFqIABBEGogAEEMaiAHEL0BDQAgCBBcGgwBCwsCQAJ/IAAtAM8BQQd2BEAgACgCyAEMAQsgAC0AzwFB/wBxC0UNACAAKAIMIgMgAEEQamtBnwFKDQAgACADQQRqNgIMIAMgACgCCDYCAAsgBSACIAAoArQBIAQgBhDYAzcDACAAQcQBaiAAQRBqIAAoAgwgBBBkIABBzAJqIABByAJqEEIEQCAEIAQoAgBBAnI2AgALIAAoAswCIQogARAzGiAAQcQBahAzGiAAQdACaiQAIAoLmgUBBX8jAEHQAmsiACQAIAAgAjYCyAIgACABNgLMAiADEIwBIQYgAyAAQdABahDQASEHIABBxAFqIAMgAEHEAmoQzwEjAEEQayICJAAgAEG4AWoiAUIANwIAIAFBADYCCCACQRBqJAAgASABLQALQQd2BH8gASgCCEH/////B3FBAWsFQQoLEDogAAJ/IAEtAAtBB3YEQCABKAIADAELIAELIgI2ArQBIAAgAEEQajYCDCAAQQA2AggDQAJAIABBzAJqIABByAJqEEINACAAKAK0AQJ/IAEtAAtBB3YEQCABKAIEDAELIAEtAAtB/wBxCyACakYEQAJ/IAEtAAtBB3YEQCABKAIEDAELIAEtAAtB/wBxCyEDIAECfyABLQALQQd2BEAgASgCBAwBCyABLQALQf8AcQtBAXQQOiABIAEtAAtBB3YEfyABKAIIQf////8HcUEBawVBCgsQOiAAIAMCfyABLQALQQd2BEAgASgCAAwBCyABCyICajYCtAELAn8gAEHMAmoiCCgCACIDKAIMIgkgAygCEEYEQCADIAMoAgAoAiQRAAAMAQsgCSgCAAsgBiACIABBtAFqIABBCGogACgCxAIgAEHEAWogAEEQaiAAQQxqIAcQvQENACAIEFwaDAELCwJAAn8gAC0AzwFBB3YEQCAAKALIAQwBCyAALQDPAUH/AHELRQ0AIAAoAgwiAyAAQRBqa0GfAUoNACAAIANBBGo2AgwgAyAAKAIINgIACyAFIAIgACgCtAEgBCAGENsDOwEAIABBxAFqIABBEGogACgCDCAEEGQgAEHMAmogAEHIAmoQQgRAIAQgBCgCAEECcjYCAAsgACgCzAIhCiABEDMaIABBxAFqEDMaIABB0AJqJAAgCguaBQEFfyMAQdACayIAJAAgACACNgLIAiAAIAE2AswCIAMQjAEhBiADIABB0AFqENABIQcgAEHEAWogAyAAQcQCahDPASMAQRBrIgIkACAA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AUEQaiQAIAIgAi0AC0EHdgR/IAIoAghB/////wdxQQFrBUEKCxA6IAACfyACLQALQQd2BEAgAigCAAwBCyACCyIBNgK0ASAAIAY2AgwgAEEANgIIA0ACQCAAQfwBaiAAQfgBahBDDQAgACgCtAECfyACLQALQQd2BEAgAigCBAwBCyACLQALQf8AcQsgAWpGBEACfyACLQALQQd2BEAgAigCBAwBCyACLQALQf8AcQshBiACAn8gAi0AC0EHdgRAIAIoAgQMAQsgAi0AC0H/AHELQQF0EDogAiACLQALQQd2BH8gAigCCEH/////B3FBAWsFQQoLEDogACAGAn8gAi0AC0EHdgRAIAIoAgAMAQsgAgsiAWo2ArQBCwJ/IABB/AFqIgcoAgAiBigCDCIIIAYoAhBGBEAgBiAGKAIAKAIkEQAADAELIAgtAAALwEEQIAEgAEG0AWogAEEIakEAIAMgAEEQaiAAQQxqIABB0AFqEMABDQAgBxBdGgwBCwsgAiAAKAK0ASABaxA6An8gAi0AC0EHdgRAIAIoAgAMAQsgAgshCxBEIQkgACAFNgIAIAsgCSAAENQDQQFHBEAgBEEENgIACyAAQfwBaiAAQfgBahBDBEAgBCAEKAIAQQJyNgIACyAAKAL8ASEKIAIQMxogAxAzGiAAQYACaiQAIAoLHgEBf0HQuwMoAgAiAARAIAAQ4ARB0LsDQQA2AgALC9EFAgN/AX4jAEGQAmsiACQAIAAgAjYCiAIgACABNgKMAiAAQdABaiADIABB4AFqIABB3wFqIABB3gFqELYCIwBBEGsiAiQAIABBxAFqIgFCADcCACABQQA2AgggAkEQaiQAIAEgAS0AC0EHdgR/IAEoAghB/////wdxQQFrBUEKCxA6IAACfyABLQALQQd2BEAgASgCAAwBCyABCyICNgLAASAAIABBIGo2AhwgAEEANgIYIABBAToAFyAAQcUAOgAWA0ACQCAAQYwCaiAAQYgCahBDDQAgACgCwAECfyABLQALQQd2BEAgASgCBAwBCyABLQALQf8AcQsgAmpGBEACfyABLQALQQd2BEAgASgCBAwBCyABLQALQf8AcQshAyABAn8gAS0AC0EHdgRAIAEoAgQMAQsgAS0AC0H/AHELQQF0EDogASABLQALQQd2BH8gASgCCEH/////B3FBAWsFQQoL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QQNxbGogACwADiAxIAV2QQNxbGogACwADyAwIAV2QQNxbGogBiAHai0AAEEPcWwgCmogACwAESAuIAV2QQNxbCAALAAQIC8gBXZBA3FsaiAALAASIC0gBXZBA3FsaiAALAATICwgBXZBA3FsaiAALAAUICsgBXZBA3FsaiAALAAVICogBXZBA3FsaiAALAAWICkgBXZBA3FsaiAALAAXICggBXZBA3FsaiAALAAYICcgBXZBA3FsaiAALAAZICYgBXZBA3FsaiAALAAaICUgBXZBA3FsaiAALAAbICQgBXZBA3FsaiAALAAcICMgBXZBA3FsaiAALAAdICIgBXZBA3FsaiAALAAeICEgBXZBA3FsaiAALAAfICAgBXZBA3FsaiAHIAZBAXJqLQAAQQ9xbGohCiAAQSBqIQAgBUECaiEFIAZBAmohBiAMQQFqIgxBBEcNAAsgBEEgaiEEIAlBCGohCSALIQZBACELIEAhACAGDQALIEEgQiBElCAKspQgQyBClCAOIA8gECARIBIgEyAUIBUgFiAXIBggGSAaIBsgHCAdIB5sampqampqampqampqampqspSTkiFBIAhBAWoiCCANRw0ACwsgASBBOAIAC6YCAQF/IAAgACgCACgCGBEAABogACABEPgDIgE2AkQgAC0AYiECIAAgASABKAIAKAIcEQAAIgE6AGIgASACRwRAIABBADYCECAAQQA2AgwgAEEANgIIIABBADYCHCAAQQA2AhQgAEEANgIYIAAtAGAhASAALQBiBEACQCABRQ0AIAAoAiAiAUUNACABEC8LIAAgAC0AYToAYCAAIAAoAjw2AjQgACgCOCEBIABCADcCOCAAIAE2AiAgAEEAOgBhDwsCQCABDQAgACgCICIBIABBLGpGDQAgAEEAOgBhIAAgATYCOCAAIAAoAjQiATYCPCABEDIhASAAQQE6AGAgACABNgIgDwsgACAAKAI0IgE2AjwgARAyIQEgAEEBOgBhIAAgATYCOAsL8QMCBX8BfiMAQRBrIgMkAAJAIAAoAkBFDQACQCAAKAJEIgQEQCAAKAJcIgJBEHEEQCAAKAIYIAAoAhRHBEBBfyEBIABBfyAAKAIAKAI0EQQAQX9GDQQLIABByABqIQEDQCAAKAJEIgQgASAAKAIgIgIgAiAAKAI0aiADQQxqIAQoAgAoAhQRCgAh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AgAhAAsgAygC1AEgABCkASADIAMoAtgBQQFqNgLYAQsCQCAEQRRqIgAgAUHwA2pGDQAgAS0A+wMiCMAhAiAELAAfQQBOBEAgAkEATgRAIAAgASkD8AM3AgAgACABKAL4AzYCCAwCCyAAIAEoAvADIAEoAvQDEN4BDAELIAAgASgC8AMgAUHwA2ogAkEASCIAGyABKAL0AyAIIAAbEN8BCyAGQQFqIgYgASgCyAQiAEgNAAsLIAMgAygCICICNgLAASACQZiVA0oEQCADIAMoAtwBQQFqNgLcASADIAMoAuABQQFqNgLgASADIAP9AALkASACQZiVA2siBP0R/a4B/QsC5AEgAyADKAL0ASAEajYC9AEgAyADKAL4ASAEajYC+AEgAyADKAL8ASAEajYC/AELAkAgACACTg0AIAFByCU2AuABIAEgAiAAazYC5AFBBEGT4wAgAUHgAWoQNCABKALIBCIGIAMoAiBODQAgA0HUAWohBSADQcQBaiELIAFB8ANqQQRyIQgDQAJAIAMoAvwBIgIgBkgEQCABQZQEaiIAIAYgAmsQOSABIABBsykQOCIAKAIINgKoBCABIAApAgA3A6AEIABCADcCACAAQQA2AgggAUGgBGpBuyoQNyIAKAIAIQIgASAAKAIENgLkAyABIAAoAAc2AOcDIABCADcCACAALQALIQQgAEEANgIIIAEsAPsDQQBIBEAgASgC8AMQLwsgASACNgLwAyAIIAEoAOcDNgADIAggASgC5AM2AgAgASAEOgD7AyABLACrBEEASARAIAEoAqAEEC8LIAEsAJ8EQQBODQEgASgClAQQLwwBCyADKALcASAGRgRAAn8gASwA+wNBAEgEQCABQQc2AvQDIAEoAvADDAELIAFBBzoA+wMgAUHwA2oLIgBBADoAByAAQdQpKAAANgADIABB0SkoAAA2AAAMAQsgAygC4AEiACAGRgRAAn8gASwA+wNBAEgEQCABQQc2AvQDIAEoAvADDAELIAFBBzoA+wMgAUHwA2oLIgBBADoAByAAQcQpKAAANgADIABBwSkoAAA2AAAMAQsgAygC5AEgBkYEQCABQfADakHhKUENEMsBDAELIAMoAugBIAZGBEAgAUHwA2pB7ylBDhDLAQwBCyADKALsASAGRgRAAn8gASwA+wNBAEgEQCABQQg2AvQDIAEoAvADDAELIAFBCDoA+wMgAUHwA2oLIgBBADoACCAAQtu+zfrEqdOv3QA3AAAMAQsgAygC8AEgBkYEQAJ/IAEsAPsDQQBIBEAgAUEINgL0AyABKALwAwwBCyABQQg6APsDIAFB8ANqCyIAQQA6AAggAELbvsGS1cjVr90ANwAADAELIAMoAvQBIAZGBEACfyABLAD7A0EASARAIAFBCDYC9AMgASgC8AMMAQsgAUEIOgD7AyABQfADagsiAEEAOgAIIABC2765+rSK1K/dADcAAAwBCyADKAL4ASAGRgRAAn8gASwA+wNBAEgEQCABQQc2AvQDIAEoAvADDAELIAFBBzoA+wMgAUHwA2oLIgBBADoAByAAQcwpKAAANgADIABBySkoAAA2AAAMAQsgAiAGRgRAAn8gASwA+wNBAEgEQCABQQc2AvQDIAEoAvADDAELIAFBBzoA+wMgAUHwA2oLIgBBADoAByAAQdwpKAAANgADIABB2SkoAAA2AAAMAQsCQCAAIAZODQAgBiAAIAMoAsABIgJqIAJBmJUDSmtBtZQDa0oNACAGIABBf3NqIQxBACEEIwBBEGsiCiQAAkACQEHE1zQoAgAiAkHI1zRHBEADQCACKAIcIAxGDQICQCACKAIEIgAEQANAIAAiAigCACIADQAMAgsACwNAIAIgAigCCCICKAIARw0ACwsgAkHI1zRHDQALCyAKIAw2AgQgCkHBEzYCAEECQaDrACAKEDQMAQsgAigCECACQRBqIAIsABtBAEgbIQQLIApBEGokACABIAFBlARqIAQQpgEiAkG5KRA4IgAoAgg2AqgEIAEgACkCADcDoAQgAEIANwIAIABBADYCCCABQaAEakG7KhA3IgAoAgAhBCABIAAoAgQ2AuQDIAEgACgABzYA5wMgAEIANwIAIAAtAAshCiAAQQA2AgggASwA+wNBAEgEQCABKALwAxAvCyABIAQ2AvADIAggASgA5wM2AAMgCCABKALkAzYCACABIAo6APsDIAEsAKsEQQBIBEAgASgCoAQQLwsgASwAnwRBAE4NASACKAIAEC8MAQsgAUGUBGoiACAGEDkgASAAQaQpEDgiACgCCDYCqAQgASAAKQIANwOgBCAAQgA3AgAgAEEANgIIIAFBoARqQbsqEDciACgCACECIAEgACgCBDYC5AMgASAAKAAHNgDnAyAAQgA3AgAgAC0ACyEEIABBADYCCCABLAD7A0EASARAIAEoAvADEC8LIAEgAjYC8AMgCCABKADnAzYAAyAIIAEoAuQDNgIAIAEgBDoA+wMgASwAqwRBAEgEQCABKAKgBBAvCyABLACfBEEATg0AIAEoApQEEC8LIAEgAUHwA2oiADYClAQgAUGgBGogCyAAIAFBlARqEOIEIAEoAqAEIAY2AhwCQAJAIAUiAiIAKAIAIgRFDQADQCAEIgAoAhAiAiAGSgRAIAAiAigCACIEDQEMAgsgAiAGTg0CIAAoAgQiBA0ACyAAQQRqIQILQSAQMiIEIAY2AhAgBCAANgIIIARCADcCACAEQgA3AhQgBEEANgIcIAIgBDYCACAEIQAgAygC0AEoAgAiCgRAIAMgCjYC0AEgAigCACEACyADKALUASAAEKQBIAMgAygC2AFBAWo2AtgBCwJAIARBFGoiACABQfADakYNACABLQD7AyIKwCECIAQsAB9BAE4EQCACQQBOBEAgACABKQPwAzcCACAAIAEoAvgDNgIIDAILIAAgASgC8AMgASgC9AMQ3gEMAQsgACABKALwAyABQfADaiACQQBIIgAbIAEoAvQDIAogABsQ3wELIAZBAWoiBiADKAIgSA0ACwsgAygCwAEhACABQcglNgLQASABIAAgAEGYlQNKa0G1lANrNgLUAUEEQaztACABQdABahA0IAEoArAEIgAEQCABIAA2ArQEIAAQLwsgASwA+wNBAEgEQCABKALwAxAvCyADKAIQIQggAygCMCEAIAMoAkAhAiABQQE6APgDIAEgASgC+AM2AsgBIAEgAEEPbCACQRhsakEZakG8Amw2AvADQQAhACABQQA2AvQDIAEgASkC8AM3A8ABIAMgAUHAAWoQvgEiAjYCqAEgAkUEQCABQcglNgIAQQJBo+oAIAEQNAwBCyADNAJEISUgAygCQCEKIAMoAjghEiADNAI0IScgAygCKCETIAM0AiQhKCADNAIgISkCQCADKAIwIgwgAygClAEiACADKAKQASIEa0E8bSICSwRAQQAhBiAMIAJrIgQgAygCmAEiCyAAa0E8bU0EQCADIAQEfyAAQQAgBEE8bEE8ayICIAJBPHBrQTxqIgL8CwAgACACagUgAAs2ApQBDAILAkAgACADKAKQASIFa0E8bSIQIARqIgJBxYiRIkkEQEHEiJEiIAsgBWtBPG0iC0EBdCIRIAIgAiARSRsgC0GixIgRTxsiCwRAIAtBxYiRIk8NAiALQTxsEDIhBgsgEEE8bCAGaiICQQAgBEE8bEE8ayIEIARBPHBrQTxqIgT8CwAgAiAEaiEEIAAgBUcEQANAIAJBPGsiAiAAQTxrIgD9AAIA/QsCACACIAAoAjg2AjggAiAAKQIwNwIwIAIgAP0AAiD9CwIgIAIgAP0AAhD9CwIQIAAgBUcNAAsgAygCkAEhAAsgAyAGIAtBPGxqNgKYASADIAQ2ApQBIAMgAjYCkAEgAARAIAAQLwsMAwsQNgALEEcACyACIAxNDQAgAyAEIAxBPGxqNgKUAQsgCEEARyEQAkAgAygCoAEiACADKAKcASIEa0HgAG0iAiAKSQRAQQAhBSAKIAJrIgQgAygCpAEiCyAAa0HgAG1NBEAgAyAEBH8gAEEAIARB4ABsQeAAayICIAJB4ABwa0HgAGoiAvwLACAAIAJqBSAACzYCoAEMAgsCQCAAIAMoApwBIgZrQeAAbSIRIARqIgJBq9WqFUkEQEGq1aoVIAsgBmtB4ABtIgtBAXQiGCACIAIgGEkbIAtB1arVCk8bIgsEQCALQavVqhVPDQIgC0HgAGwQMiEFCyARQeAAbCAFaiICQQAgBEHgAGxB4ABrIgQgBEHgAHBrQeAAaiIE/AsAIAIgBGohBCAAIAZHBEADQCACQeAAayICIABB4ABrIgBB4AD8CgAAIAAgBkcNAAsgAygCnAEhAAsgAyAFIAtB4ABsajYCpAEgAyAENgKgASADIAI2ApwBIAAEQCAAEC8LDAMLEDYACxBHAAsgAiAKTQ0AIAMgBCAKQeAAbGo2AqABCyADIAMoAqgBQQAgE6wiJCAoEFU2AmQgAyADKAKoASAQQgMgJSAkELwBNgJoIAMgAygCqAFBAEIBICQQVTYCbCADIAMoAqgBIBBCAyAkICQQvAE2AnAgAyADKAKoAUEAQgEgJBBVNgJ0IAMgAygCqAFBACAkEEg2AnggAyADKAKoAUEAICQQSDYCfCADKAJkIQIgAUEgEDIiADYC8AMgAUKcgICAgISAgIB/NwL0AyAAQZAeKAAANgAYIABBiB4pAAA3ABAgAEH4Hf0AAAD9CwAAIABBADoAHCABIAFB8ANqIgA2AqAEIAFBsARqIANBtAFqIgUgACABQaAEahA8IAEoArAEIAI2AhwgASwA+wNBAEgEQCABKALwAxAvCyADKAJoIQIgAUEgEDIiADYC8AMgAUKUgICAgISAgIB/NwL0AyAAQdEOKAAANgAQIABBwQ79AAAA/QsAACAAQQA6ABQgASABQfADaiIANgKgBCABQbAEaiAFIAAgAUGgBGoQPCABKAKwBCACNgIcIAEsAPsDQQBIBEAgASgC8AMQLwsgAygCbCECIAFBIBAyIgA2AvADIAFCkoCAgICEgICAfzcC9AMgAEGNEy8AADsAECAAQf0S/QAAAP0LAAAgAEEAOgASIAEgAUHwA2oiADYCoAQgAUGwBGogBSAAIAFBoARqEDwgASgCsAQgAjYCHCABLAD7A0EASARAIAEoAvADEC8LIAMoAnAhAiABQSAQMiIANgLwAyABQpSAgICAhICAgH83AvQDIABBrg4oAAA2ABAgAEGeDv0AAAD9CwAAIABBADoAFCABIAFB8ANqIgA2AqAEIAFBsARqIAUgACABQaAEahA8IAEoArAEIAI2AhwgASwA+wNBAEgEQCABKALwAxAvCyADKAJ0IQIgAUEgEDIiADYC8AMgAUKSgICAgISAgIB/NwL0AyAAQe4SLwAAOwAQIABB3hL9AAAA/QsAACAAQQA6ABIgASABQfADaiIANgKgBCABQbAEaiAFIAAgAUGgBGoQPCABKAKwBCACNgIcIAEsAPsDQQBIBEAgASgC8AMQLwsgAygCeCECIAFBIBAyIgA2AvADIAFCloCAgICEgICAfzcC9AMgAEGDDSkAADcADiAAQfUM/QAAAP0LAAAgAEEAOgAWIAEgAUHwA2oiADYCoAQgAUGwBGogBSAAIAFBoARqEDwgASgCsAQgAjYCHCABLAD7A0EASARAIAEoAvADEC8LIAMoAnwhAiABQSAQMiIANgLwAyABQpSAgICAhICAgH83AvQDIABB8hEoAAA2ABAgAEHiEf0AAAD9CwAAIABBADoAFCABIAFB8ANqIgA2AqAEIAFBsARqIAUgACABQaAEahA8IAEoArAEIAI2AhwgASwA+wNBAEgEQCABKALwAxAvCyAMQQBKBEAgE0ECdKwhJUEAIQQDQCADKAKQASAEQTxsaiIAIAMoAqgBQQAgJBBINgIkIAAgAygCqAFBACAkEEg2AiggACADKAKoASAIICQgJRBVNgIsIAAgAygCqAFBACAlEEg2AjAgACADKAKoASAIICUgJBBVNgI0IAAgAygCqAFBACAkEEg2AjggACADKAKoAUEAICQQSDYCACAAIAMoAqgBQQAgJBBINgIEIAAgAygCqAEgCCAkICQQVTYCECAAIAMoAqgBQQAgJBBINgIUIAAgAygCqAEgCCAkICQQVTYCGCAAIAMoAqgBIAggJCAkEFU2AhwgACADKAKoAUEAICQQSDYCICAAIAMoAqgBIAggJCAkEFU2AgggACADKAKoAUEAICQQSDYCDCAAKAIkIQYgAUGgBGoiAiAEEDkgASACQc7CABA4IgIoAgg2ArgEIAEgAikCADcDsAQgAkIANwIAIAJBADYCCCABIAFBsARqQYwNEDciAigCCDYC+AMgASACKQIANwPwAyACQgA3AgAgAkEANgIIIAEgAUHwA2oiAjYC5AMgAUGUBGogBSACIAFB5ANqEDwgASgClAQgBjYCHCABLAD7A0EASARAIAEoAvADEC8LIAEsALsEQQBIBEAgASgCsAQQLwsgASwAqwRBAEgEQCABKAKgBBAvCyAAKAIoIQYgAUGgBGoiAiAEEDkgASACQc7CABA4IgIoAgg2ArgEIAEgAikCADcDsAQgAkIANwIAIAJBADYCCCABIAFBsARqQfcREDciAigCCDYC+AMgASACKQIANwPwAyACQgA3AgAgAkEANgIIIAEgAUHwA2oiAjYC5AMgAUGUBGogBSACIAFB5ANqEDwgASgClAQgBjYCHCABLAD7A0EASARAIAEoAvADEC8LIAEsALsEQQBIBEAgASgCsAQQLwsgASwAqwRBAEgEQCABKAKgBBAvCyAAKAIsIQYgAUGgBGoiAiAEEDkgASACQc7CABA4IgIoAgg2ArgEIAEgAikCADcDsAQgAkIANwIAIAJBADYCCCABIAFBsARqQdYOEDciAigCCDYC+AMgASACKQIANwPwAyACQgA3AgAgAkEANgIIIAEgAUHwA2oiAjYC5AMgAUGUBGogBSACIAFB5ANqEDwgASgClAQgBjYCHCABLAD7A0EASARAIAEoAvADEC8LIAEsALsEQQBIBEAgASgCsAQQLwsgASwAqwRBAEgEQCABKAKgBBAvCyAAKAIwIQYgAUGgBGoiAiAEEDkgASACQc7CABA4IgIoAgg2ArgEIAEgAikCADcDsAQgAkIANwIAIAJBADYCCCABIAFBsARqQZATEDciAigCCDYC+AMgASACKQIANwPwAyACQgA3AgAgAkEANgIIIAEgAUHwA2oiAjYC5AMgAUGUBGogBSACIAFB5ANqEDwgASgClAQgBjYCHCABLAD7A0EASARAIAEoAvADEC8LIAEsALsEQQBIBEAgASgCsAQQLwsgASwAqwRBAEgEQCABKAKgBBAvCyAAKAI0IQYgAUGgBGoiAiAEEDkgASACQc7CABA4IgIoAgg2ArgEIAEgAikCADcDsAQgAkIANwIAIAJBADYCCCABIAFBsARqQbMOEDciAigCCDYC+AMgASACKQIANwPwAyACQgA3AgAgAkEANgIIIAEgAUHwA2oiAjYC5AMgAUGUBGogBSACIAFB5ANqEDwgASgClAQgBjYCHCABLAD7A0EASARAIAEoAvADEC8LIAEsALsEQQBIBEAgASgCsAQQLwsgASwAqwRBAEgEQCABKAKgBBAvCyAAKAI4IQYgAUGgBGoiAiAEEDkgASACQc7CABA4IgIoAgg2ArgEIAEgAikCADcDsAQgAkIANwIAIAJBADYCCCABIAFBsARqQfESEDciAigCCDYC+AMgASACKQIANwPwAyACQgA3AgAgAkEANgIIIAEgAUHwA2oiAjYC5AMgAUGUBGogBSACIAFB5ANqEDwgASgClAQgBjYCHCABLAD7A0EASARAIAEoAvADEC8LIAEsALsEQQBIBEAgASgCsAQQLwsgASwAqwRBAEgEQCABKAKgBBAvCyAAKAIAIQYgAUGgBGoiAiAEEDkgASACQc7CABA4IgIoAgg2ArgEIAEgAikCADcDsAQgAkIANwIAIAJBADYCCCABIAFBsARqQbENEDciAigCCDYC+AMgASACKQIANwPwAyACQgA3AgAgAkEANgIIIAEgAUHwA2oiAjYC5AMgAUGUBGogBSACIAFB5ANqEDwgASgClAQgBjYCHCABLAD7A0EASARAIAEoAvADEC8LIAEsALsEQQBIBEAgASgCsAQQLwsgASwAqwRBAEgEQCABKAKgBBAvCyAAKAIEIQYgAUGgBGoiAiAEEDkgASACQc7CABA4IgIoAgg2ArgEIAEgAikCADcDsAQgAkIANwIAIAJBADYCCCABIAFBsARqQZgSEDciAigCCDYC+AMgASACKQIANwPwAyACQgA3AgAgAkEANgIIIAEgAUHwA2oiAjYC5AMgAUGUBGogBSACIAFB5ANqEDwgASgClAQgBjYCHCABLAD7A0EASARAIAEoAvADEC8LIAEsALsEQQBIBEAgASgCsAQQLwsgASwAqwRBAEgEQCABKAKgBBAvCyAAKAIQIQYgAUGgBGoiAiAEEDkgASACQc7CABA4IgIoAgg2ArgEIAEgAikCADcDsAQgAkIANwIAIAJBADYCCCABIAFBsARqQZIMEDciAigCCDYC+AMgASACKQIANwPwAyACQgA3AgAgAkEANgIIIAEgAUHwA2oiAjYC5AMgAUGUBGogBSACIAFB5ANqEDwgASgClAQgBjYCHCABLAD7A0EASARAIAEoAvADEC8LIAEsALsEQQBIBEAgASgCsAQQLwsgASwAqwRBAEgEQCABKAKgBBAvCyAAKAIUIQYgAUGgBGoiAiAEEDkgASACQc7CABA4IgIoAgg2ArgEIAEgAikCADcDsAQgAkIANwIAIAJBADYCCCABIAFBsARqQa0REDciAigCCDYC+AMgASACKQIANwPwAyACQgA3AgAgAkEANgIIIAEgAUHwA2oiAjYC5AMgAUGUBGogBSACIAFB5ANqEDwgASgClAQgBjYCHCABLAD7A0EASARAIAEoAvADEC8LIAEsALsEQQBIBEAgASgCsAQQLwsgASwAqwRBAEgEQCABKAKgBBAvCyAAKAIYIQYgAUGgBGoiAiAEEDkgASACQc7CABA4IgIoAgg2ArgEIAEgAikCADcDsAQgAkIANwIAIAJBADYCCCABIAFBsARqQbwMEDciAigCCDYC+AMgASACKQIANwPwAyACQgA3AgAgAkEANgIIIAEgAUHwA2oiAjYC5AMgAUGUBGogBSACIAFB5ANqEDwgASgClAQgBjYCHCABLAD7A0EASARAIAEoAvADEC8LIAEsALsEQQBIBEAgASgCsAQQLwsgASwAqwRBAEgEQCABKAKgBBAvCyAAKAIcIQYgAUGgBGoiAiAEEDkgASACQc7CABA4IgIoAgg2ArgEIAEgAikCADcDsAQgAkIANwIAIAJBADYCCCABIAFBsARqQYsOEDciAigCCDYC+AMgASACKQIANwPwAyACQgA3AgAgAkEANgIIIAEgAUHwA2oiAjYC5AMgAUGUBGogBSACIAFB5ANqEDwgASgClAQgBjYCHCABLAD7A0EASARAIAEoAvADEC8LIAEsALsEQQBIBEAgASgCsAQQLwsgASwAqwRBAEgEQCABKAKgBBAvCyAAKAIgIQYgAUGgBGoiAiAEEDkgASACQc7CABA4IgIoAgg2ArgEIAEgAikCADcDsAQgAkIANwIAIAJBADYCCCABIAFBsARqQc0SEDciAigCCDYC+AMgASACKQIANwPwAyACQgA3AgAgAkEANgIIIAEgAUHwA2oiAjYC5AMgAUGUBGogBSACIAFB5ANqEDwgASgClAQgBjYCHCABLAD7A0EASARAIAEoAvADEC8LIAEsALsEQQBIBEAgASgCsAQQLwsgASwAqwRBAEgEQCABKAKgBBAvCyAAKAIIIQYgAUGgBGoiAiAEEDkgASACQc7CABA4IgIoAgg2ArgEIAEgAikCADcDsAQgAkIANwIAIAJBADYCCCABIAFBsARqQeQMEDciAigCCDYC+AMgASACKQIANwPwAyACQgA3AgAgAkEANgIIIAEgAUHwA2oiAjYC5AMgAUGUBGogBSACIAFB5ANqEDwgASgClAQgBjYCHCABLAD7A0EASARAIAEoAvADEC8LIAEsALsEQQBIBEAgASgCsAQQLwsgASwAqwRBAEgEQCABKAKgBBAvCyAAKAIMIQIgAUGgBGoiACAEEDkgASAAQc7CABA4IgAoAgg2ArgEIAEgACkCADcDsAQgAEIANwIAIABBADYCCCABIAFBsARqQdMREDciACgCCDYC+AMgASAAKQIANwPwAyAAQgA3AgAgAEEANgIIIAEgAUHwA2oiADYC5AMgAUGUBGogBSAAIAFB5ANqEDwgASgClAQgAjYCHCABLAD7A0EASARAIAEoAvADEC8LIAEsALsEQQBIBEAgASgCsAQQLwsgASwAqwRBAEgEQCABKAKgBBAvCyAEQQFqIgQgDEcNAAsLIAMgAygCqAFBACASrCIkICcQVTYCgAEgAyADKAKoASAIICQgKRBVNgKEASADIAMoAqgBQQAgJBBINgKIASADIAMoAqgBQQAgJBBINgKMASADKAKAASECIAFBIBAyIgA2AvADIAFCnICAgICEgICAfzcC9AMgAEGtHigAADYAGCAAQaUeKQAANwAQIABBlR79AAAA/QsAACAAQQA6ABwgASABQfADaiIANgKgBCABQbAEaiAFIAAgAUGgBGoQPCABKAKwBCACNgIcIAEsAPsDQQBIBEAgASgC8AMQLwsgAygChAEhAiABQSAQMiIANgLwAyABQp6AgICAhICAgH83AvQDIABB6Q0pAAA3ABYgAEHjDSkAADcAECAAQdMN/QAAAP0LAAAgAEEAOgAeIAEgAUHwA2oiADYCoAQgAUGwBGogBSAAIAFBoARqEDwgASgCsAQgAjYCHCABLAD7A0EASARAIAEoAvADEC8LIAMoAogBIQIgAUEgEDIiADYC8AMgAUKRgICAgISAgIB/NwL0AyAAQdENLQAAOgAQIABBwQ39AAAA/QsAACAAQQA6ABEgASABQfADaiIANgKgBCABQbAEaiAFIAAgAUGgBGoQPCABKAKwBCACNgIcIAEsAPsDQQBIBEAgASgC8AMQLwsgAygCjAEhAiABQRAQMiIANgLwAyABQo+AgICAgoCAgH83AvQDIABBrRIpAAA3AAcgAEGmEikAADcAACAAQQA6AA8gASABQfADaiIANgKgBCABQbAEaiAFIAAgAUGgBGoQPCABKAKwBCACNgIcIAEsAPsDQQBIBEAgASgC8AMQLwsgCkEASgRAIBJBAnSsISVBACEEA0AgAygCnAEgBEHgAGxqIgAgAygCqAFBACAkEEg2AkggACADKAKoAUEAICQQSDYCTCAAIAMoAqgBIAggJCAlEFU2AlAgACADKAKoAUEAICUQSDYCVCAAIAMoAqgBIAggJSAkEFU2AlggACADKAKoAUEAICQQSDYCXCAAIAMoAqgBQQAgJBBINgIAIAAgAygCqAFBACAkEEg2AgQgACADKAKoASAIICQgJBBVNgIQIAAgAygCqAFBACAkEEg2AhQgACADKAKoASAIICQgJBBVNgIYIAAgAygCqAEgCCAkICQQVTYCHCAAIAMoAqgBQQAgJBBINgIgIAAgAygCqAEgCCAkICQQVTYCCCAAIAMoAqgBQQAgJBBINgIMIAAgAygCqAFBACAkEEg2AiQgACADKAKoAUEAICQQSDYCKCAAIAMoAqgBIAggJCAkEFU2AjQgACADKAKoAUEAICQQSDYCOCAAIAMoAqgBIAggJCAkEFU2AjwgACADKAKoASAIICQgJBBVNgJAIAAgAygCqAFBACAkEEg2AkQgACADKAKoASAIICQgJBBVNgIsIAAgAygCqAFBACAkEEg2AjAgACgCSCEGIAFBoARqIgIgBBA5IAEgAkHewgAQOCICKAIINgK4BCABIAIpAgA3A7AEIAJCADcCACACQQA2AgggASABQbAEakGMDRA3IgIoAgg2AvgDIAEgAikCADcD8AMgAkIANwIAIAJBADYCCCABIAFB8ANqIgI2AuQDIAFBlARqIAUgAiABQeQDahA8IAEoApQEIAY2AhwgASwA+wNBAEgEQCABKALwAxAvCyABLAC7BEEASARAIAEoArAEEC8LIAEsAKsEQQBIBEAgASgCoAQQLwsgACgCTCEGIAFBoARqIgIgBBA5IAEgAkHewgAQOCICKAIINgK4BCABIAIpAgA3A7AEIAJCADcCACACQQA2AgggASABQbAEakH3ERA3IgIoAgg2AvgDIAEgAikCADcD8AMgAkIANwIAIAJBADYCCCABIAFB8ANqIgI2AuQDIAFBlARqIAUgAiABQeQDahA8IAEoApQEIAY2AhwgASwA+wNBAEgEQCABKALwAxAvCyABLAC7BEEASARAIAEoArAEEC8LIAEsAKsEQQBIBEAgASgCoAQQLwsgACgCUCEGIAFBoARqIgIgBBA5IAEgAkHewgAQOCICKAIINgK4BCABIAIpAgA3A7AEIAJCADcCACACQQA2AgggASABQbAEakHWDhA3IgIoAgg2AvgDIAEgAikCADcD8AMgAkIANwIAIAJBADYCCCABIAFB8ANqIgI2AuQDIAFBlARqIAUgAiABQeQDahA8IAEoApQEIAY2AhwgASwA+wNBAEgEQCABKALwAxAvCyABLAC7BEEASARAIAEoArAEEC8LIAEsAKsEQQBIBEAgASgCoAQQLwsgACgCVCEGIAFBoARqIgIgBBA5IAEgAkHewgAQOCICKAIINgK4BCABIAIpAgA3A7AEIAJCADcCACACQQA2AgggASABQbAEakGQExA3IgIoAgg2AvgDIAEgAikCADcD8AMgAkIANwIAIAJBADYCCCABIAFB8ANqIgI2AuQDIAFBlARqIAUgAiABQeQDahA8IAEoApQEIAY2AhwgASwA+wNBAEgEQCABKALwAxAvCyABLAC7BEEASARAIAEoArAEEC8LIAEsAKsEQQBIBEAgASgCoAQQLwsgACgCWCEGIAFBoARqIgIgBBA5IAEgAkHewgAQOCICKAIINgK4BCABIAIpAgA3A7AEIAJCADcCACACQQA2AgggASABQbAEakGzDhA3IgIoAgg2AvgDIAEgAikCADcD8AMgAkIANwIAIAJBADYCCCABIAFB8ANqIgI2AuQDIAFBlARqIAUgAiABQeQDahA8IAEoApQEIAY2AhwgASwA+wNBAEgEQCABKALwAxAvCyABLAC7BEEASARAIAEoArAEEC8LIAEsAKsEQQBIBEAgASgCoAQQLwsgACgCXCEGIAFBoARqIgIgBBA5IAEgAkHewgAQOCICKAIINgK4BCABIAIpAgA3A7AEIAJCADcCACACQQA2AgggASABQbAEakHxEhA3IgIoAgg2AvgDIAEgAikCADcD8AMgAkIANwIAIAJBADYCCCABIAFB8ANqIgI2AuQDIAFBlARqIAUgAiABQeQDahA8IAEoApQEIAY2AhwgASwA+wNBAEgEQCABKALwAxAvCyABLAC7BEEASARAIAEoArAEEC8LIAEsAKsEQQBIBEAgASgCoAQQLwsgACgCACEGIAFBoARqIgIgBBA5IAEgAkHewgAQOCICKAIINgK4BCABIAIpAgA3A7AEIAJCADcCACACQQA2AgggASABQbAEakGxDRA3IgIoAgg2AvgDIAEgAikCADcD8AMgAkIANwIAIAJBADYCCCABIAFB8ANqIgI2AuQDIAFBlARqIAUgAiABQeQDahA8IAEoApQEIAY2AhwgASwA+wNBAEgEQCABKALwAxAvCyABLAC7BEEASARAIAEoArAEEC8LIAEsAKsEQQBIBEAgASgCoAQQLwsgACgCBCEGIAFBoARqIgIgBBA5IAEgAkHewgAQOCICKAIINgK4BCABIAIpAgA3A7AEIAJCADcCACACQQA2AgggASABQbAEakGYEhA3IgIoAgg2AvgDIAEgAikCADcD8AMgAkIANwIAIAJBADYCCCABIAFB8ANqIgI2AuQDIAFBlARqIAUgAiABQeQDahA8IAEoApQEIAY2AhwgASwA+wNBAEgEQCABKALwAxAvCyABLAC7BEEASARAIAEoArAEEC8LIAEsAKsEQQBIBEAgASgCoAQQLwsgACgCECEGIAFBoARqIgIgBBA5IAEgAkHewgAQOCICKAIINgK4BCABIAIpAgA3A7AEIAJCADcCACACQQA2AgggASABQbAEakGSDBA3IgIoAgg2AvgDIAEgAikCADcD8AMgAkIANwIAIAJBADYCCCABIAFB8ANqIgI2AuQDIAFBlARqIAUgAiABQeQDahA8IAEoApQEIAY2AhwgASwA+wNBAEgEQCABKALwAxAvCyABLAC7BEEASARAIAEoArAEEC8LIAEsAKsEQQBIBEAgASgCoAQQLwsgACgCFCEGIAFBoARqIgIgBBA5IAEgAkHewgAQOCICKAIINgK4BCABIAIpAgA3A7AEIAJCADcCACACQQA2AgggASABQbAEakGtERA3IgIoAgg2AvgDIAEgAikCADcD8AMgAkIANwIAIAJBADYCCCABIAFB8ANqIgI2AuQDIAFBlARqIAUgAiABQeQDahA8IAEoApQEIAY2AhwgASwA+wNBAEgEQCABKALwAxAvCyABLAC7BEEASARAIAEoArAEEC8LIAEsAKsEQQBIBEAgASgCoAQQLwsgACgCGCEGIAFBoARqIgIgBBA5IAEgAkHewgAQOCICKAIINgK4BCABIAIpAgA3A7AEIAJCADcCACACQQA2AgggASABQbAEakG8DBA3IgIoAgg2AvgDIAEgAikCADcD8AMgAkIANwIAIAJBADYCCCABIAFB8ANqIgI2AuQDIAFBlARqIAUgAiABQeQDahA8IAEoApQEIAY2AhwgASwA+wNBAEgEQCABKALwAxAvCyABLAC7BEEASARAIAEoArAEEC8LIAEsAKsEQQBIBEAgASgCoAQQLwsgACgCHCEGIAFBoARqIgIgBBA5IAEgAkHewgAQOCICKAIINgK4BCABIAIpAgA3A7AEIAJCADcCACACQQA2AgggASABQbAEakGLDhA3IgIoAgg2AvgDIAEgAikCADcD8AMgAkIANwIAIAJBADYCCCABIAFB8ANqIgI2AuQDIAFBlARqIAUgAiABQeQDahA8IAEoApQEIAY2AhwgASwA+wNBAEgEQCABKALwAxAvCyABLAC7BEEASARAIAEoArAEEC8LIAEsAKsEQQBIBEAgASgCoAQQLwsgACgCICEGIAFBoARqIgIgBBA5IAEgAkHewgAQOCICKAIINgK4BCABIAIpAgA3A7AEIAJCADcCACACQQA2AgggASABQbAEakHNEhA3IgIoAgg2AvgDIAEgAikCADcD8AMgAkIANwIAIAJBADYCCCABIAFB8ANqIgI2AuQDIAFBlARqIAUgAiABQeQDahA8IAEoApQEIAY2AhwgASwA+wNBAEgEQCABKALwAxAvCyABLAC7BEEASARAIAEoArAEEC8LIAEsAKsEQQBIBEAgASgCoAQQLwsgACgCCCEGIAFBoARqIgIgBBA5IAEgAkHewgAQOCICKAIINgK4BCABIAIpAgA3A7AEIAJCADcCACACQQA2AgggASABQbAEakHkDBA3IgIoAgg2AvgDIAEgAikCADcD8AMgAkIANwIAIAJBADYCCCABIAFB8ANqIgI2AuQDIAFBlARqIAUgAiABQeQDahA8IAEoApQEIAY2AhwgASwA+wNBAEgEQCABKALwAxAvCyABLAC7BEEASARAIAEoArAEEC8LIAEsAKsEQQBIBEAgASgCoAQQLwsgACgCDCEGIAFBoARqIgIgBBA5IAEgAkHewgAQOCICKAIINgK4BCABIAIpAgA3A7AEIAJCADcCACACQQA2AgggASABQbAEakHTERA3IgIoAgg2AvgDIAEgAikCADcD8AMgAkIANwIAIAJBADYCCCABIAFB8ANqIgI2AuQDIAFBlARqIAUgAiABQeQDahA8IAEoApQEIAY2AhwgASwA+wNBAEgEQCABKALwAxAvCyABLAC7BEEASARAIAEoArAEEC8LIAEsAKsEQQBIBEAgASgCoAQQLwsgACgCJCEGIAFBoARqIgIgBBA5IAEgAkHewgAQOCICKAIINgK4BCABIAIpAgA3A7AEIAJCADcCACACQQA2AgggASABQbAEakGbDRA3IgIoAgg2AvgDIAEgAikCADcD8AMgAkIANwIAIAJBADYCCCABIAFB8ANqIgI2AuQDIAFBlARqIAUgAiABQeQDahA8IAEoApQEIAY2AhwgASwA+wNBAEgEQCABKALwAxAvCyABLAC7BEEASARAIAEoArAEEC8LIAEsAKsEQQBIBEAgASgCoAQQLwsgACgCKCEGIAFBoARqIgIgBBA5IAEgAkHewgAQOCICKAIINgK4BCABIAIpAgA3A7AEIAJCADcCACACQQA2AgggASABQbAEakGEEhA3IgIoAgg2AvgDIAEgAikCADcD8AMgAkIANwIAIAJBADYCCCABIAFB8ANqIgI2AuQDIAFBlARqIAUgAiABQeQDahA8IAEoApQEIAY2AhwgASwA+wNBAEgEQCABKALwAxAvCyABLAC7BEEASARAIAEoArAEEC8LIAEsAKsEQQBIBEAgASgCoAQQLwsgACgCNCEGIAFBoARqIgIgBBA5IAEgAkHewgAQOCICKAIINgK4BCABIAIpAgA3A7AEIAJCADcCACACQQA2AgggASABQbAEakH5CxA3IgIoAgg2AvgDIAEgAikCADcD8AMgAkIANwIAIAJBADYCCCABIAFB8ANqIgI2AuQDIAFBlARqIAUgAiABQeQDahA8IAEoApQEIAY2AhwgASwA+wNBAEgEQCABKALwAxAvCyABLAC7BEEASARAIAEoArAEEC8LIAEsAKsEQQBIBEAgASgCoAQQLwsgACgCOCEGIAFBoARqIgIgBBA5IAEgAkHewgAQOCICKAIINgK4BCABIAIpAgA3A7AEIAJCADcCACACQQA2AgggASABQbAEakGWERA3IgIoAgg2AvgDIAEgAikCADcD8AMgAkIANwIAIAJBADYCCCABIAFB8ANqIgI2AuQDIAFBlARqIAUgAiABQeQDahA8IAEoApQEIAY2AhwgASwA+wNBAEgEQCABKALwAxAvCyABLAC7BEEASARAIAEoArAEEC8LIAEsAKsEQQBIBEAgASgCoAQQLwsgACgCPCEGIAFBoARqIgIgBBA5IAEgAkHewgAQOCICKAIINgK4BCABIAIpAgA3A7AEIAJCADcCACACQQA2AgggASABQbAEakGlDBA3IgIoAgg2AvgDIAEgAikCADcD8AMgAkIANwIAIAJBADYCCCABIAFB8ANqIgI2AuQDIAFBlARqIAUgAiABQeQDahA8IAEoApQEIAY2AhwgASwA+wNBAEgEQCABKALwAxAvCyABLAC7BEEASARAIAEoArAEEC8LIAEsAKsEQQBIBEAgASgCoAQQLwsgAEFAaygCACEGIAFBoARqIgIgBBA5IAEgAkHewgAQOCICKAIINgK4BCABIAIpAgA3A7AEIAJCADcCACACQQA2AgggASABQbAEakHyDRA3IgIoAgg2AvgDIAEgAikCADcD8AMgAkIANwIAIAJBADYCCCABIAFB8ANqIgI2AuQDIAFBlARqIAUgAiABQeQDahA8IAEoApQEIAY2AhwgASwA+wNBAEgEQCABKALwAxAvCyABLAC7BEEASARAIAEoArAEEC8LIAEsAKsEQQBIBEAgASgCoAQQLwsgACgCRCEGIAFBoARqIgIgBBA5IAEgAkHewgAQOCICKAIINgK4BCABIAIpAgA3A7AEIAJCADcCACACQQA2AgggASABQbAEakG2EhA3IgIoAgg2AvgDIAEgAikCADcD8AMgAkIANwIAIAJBADYCCCABIAFB8ANqIgI2AuQDIAFBlARqIAUgAiABQeQDahA8IAEoApQEIAY2AhwgASwA+wNBAEgEQCABKALwAxAvCyABLAC7BEEASARAIAEoArAEEC8LIAEsAKsEQQBIBEAgASgCoAQQLwsgACgCLCEGIAFBoARqIgIgBBA5IAEgAkHewgAQOCICKAIINgK4BCABIAIpAgA3A7AEIAJCADcCACACQQA2AgggASABQbAEakHNDBA3IgIoAgg2AvgDIAEgAikCADcD8AMgAkIANwIAIAJBADYCCCABIAFB8ANqIgI2AuQDIAFBlARqIAUgAiABQeQDahA8IAEoApQEIAY2AhwgASwA+wNBAEgEQCABKALwAxAvCyABLAC7BEEASARAIAEoArAEEC8LIAEsAKsEQQBIBEAgASgCoAQQLwsgACgCMCECIAFBoARqIgAgBBA5IAEgAEHewgAQOCIAKAIINgK4BCABIAApAgA3A7AEIABCADcCACAAQQA2AgggASABQbAEakG+ERA3IgAoAgg2AvgDIAEgACkCADcD8AMgAEIANwIAIABBADYCCCABIAFB8ANqIgA2AuQDIAFBlARqIAUgACABQeQDahA8IAEoApQEIAI2AhwgASwA+wNBAEgEQCABKALwAxAvCyABLAC7BEEASARAIAEoArAEEC8LIAEsAKsEQQBIBEAgASgCoAQQLwsgBEEBaiIEIApHDQALCyADEOUEIgA2AoQCQQAhBCADKAK0ASICIANBuAFqIgZHBEADQCACKAIcEFsgBGohHAJAIAIoAgQiBARAA0AgBCIAKAIAIgQNAAwCCwALA0AgAigCCCIAKAIAIAJHIRsgACECIBsNAAsLIBxBvAJqIQQgBiAAIgJHDQALIAMoAoQCIQALIAMgACAAKAIIEQAAIgAgBCAAKAIAEQQANgKsASADKAKEAiIABH8gACAAKAIAEQAABUGwMAshACABIAS4RAAAAACAhC5BozkDuAEgASAANgK0ASABQcglNgKwAUEEQa3vACABQbABahA0IAMoAqwBEMkBIQwgBiADKAK0ASICRwRAA0AgDCACKAIcEJABAkAgAigCBCIEBEADQCAEIgAoAgAiBA0ADAILAAsDQCACKAIIIgAoAgAgAkchHSAAIQIgHQ0ACwsgBiAAIgJHDQALCyADQQA2ArABIAFBADYCuAQgAUIANwKwBEEAIQoDQAJAIAcoAiQgAUGQBGpBBCAHKAIoEQMAGiAHKAIkIAFBjARqQQQgBygCKBEDABogBygCJCABQYgEakEEIAcoAigRAwAaAkACQAJAIAcoAiQgBygCLBEAAARAIAFByCU2AjAgASAKuEQAAAAAgIQuQaM5AzhBBEGp8QAgAUEwahA0IAMoArABIgANASABQcglNgIQQQNBxOYAIAFBEGoQNEEAIQIMBAtBACEAIAFB0KUB/QAEAP0LBPADQQEhBCABKAKQBEEASg0BDAILQQAhAiAAIAMoArwBIgRGDQIgASAANgIoIAEgBDYCJCABQcglNgIgQQJB1+oAIAFBIGoQNEEBIQIMAgsDQCAHKAIkIAFB8ANqIABBAnRqIgJBBCAHKAIoEQMAGiACKAIAIARsIQQgAEEBaiIAIAEoApAESA0ACwtBACECIAFBADYCqAQgAUIANwOgBCABQQA2ApwEIAFCADcClARBACEAIAEoAowEIggEQCAIQQBIDQQgASAIEDIiADYClAQgASAAIAhqIgI2ApwEIABBACAI/AsAIAEgAjYCmAQLIAcoAiQgACACIABrIgggBygCKBEDABogAUGgBGoiAiAAIAgQywECfyAFIAIQ8AIgBkYEQCABQcglNgJAQQAhBCABIAEoAqAEIAIgASwAqwRBAEgbNgJEQQJB9+cAIAFBQGsQNEEBDAELIAEoAqAEIAFBoARqIAEsAKsEQQBIGyIIEGgiAEHw////B08NBQJAIABBCk0EQCABIAA6AO8DIAFB5ANqIQIMAQsgAEEPckEBaiILEDIhAiABIAtBgICAgHhyNgLsAyABIAI2AuQDIAEgADYC6AMLIAIgCCAA/AoAACAAIAJqQQA6AAAgASABQeQDaiIANgLEBCABQcgEaiAFIAAgAUHEBGoQPCABKALIBCgCHCEAIAEsAO8DQQBIBEAgASgC5AMQLwsgBKwgACkDKCAAKQMgIAApAxggACkDEH5+flIEQCABQcglNgKgAUEAIQQgASABKAKgBCABQaAEaiABLACrBEEASBs2AqQBQQJByecAIAFBoAFqEDQgACkDICEkIAApAxghJSABIAApAxA+ApABIAEgJT4ClAEgASAkPgKYASABQcglNgKAASABIAEoAvADNgKEASABIAEpAvQDNwOIAUECQfzuACABQYABahA0QQEMAQsgACkDGCEkIAEoAvQDIQgCQAJAIAApAxAiJSABKALwAyILrFIEQCABKAL4AyECDAELIAEoAvgDIQIgJCAIrFINACAAKQMgIAKsUQ0BCyABIAApAyA+AnAgASALNgJ0IAEgCDYCeCABIAI2AnwgAUHIJTYCYEEAIQQgASABKAKgBCABQaAEaiABLACrBEEASBs2AmQgASAlPgJoIAEgJD4CbEECQaTuACABQeAAahA0QQEMAQsgBCABKAKIBEEkbEGYmwFqKAIAbCICIAAoAgBBJGxBlJsBaigCAG4gABBbRwRAIAEoAqAEIQggASwAqwQhCyAAEFshACABIAI2AlwgASAANgJYIAFByCU2AlBBACEEIAEgCCABQaAEaiALQQBIGzYCVEECQZviACABQdAAahA0QQEMAQsCQCADKAKEAigCAEE8RgRAIAcoAighAiAHKAIkIAAoAtABIAAQWyACEQMAGgwBCwJAIAAQWyICIAFBsARqIgQoAgQgBCgCACILayIISwRAIAQgAiAIaxDxAgwBCyACIAhJBEAgBCACIAtqNgIECwsgBygCJCABKAKwBCICIAEoArQEIAJrIAcoAigRAwAaIAAgASgCsARBACAAEFsQlwELIAAQWyEeQQEhBCADIAMoArABQQFqNgKwASAeIApqIQpBAAshAiABKAKUBCIABEAgABAvCyABLACrBEEASARAIAEoAqAEEC8LIAQNAQsLIAEoArAEIgAEQCABIAA2ArQEIAAQLwtBACEAIAINACAMEJEBIAMQaSAmfTcDAEEBIQALIAFB0ARqJAAgAAwCCxA2AAsQTQALIR8gBygCJCAHKAIwEQEAIB9FBEAgD0HTHzYCAEECQfPlACAPEDQgAywAkwJBAEgEQCADKAKIAhAvCyAXIAMoAtQBEI8CIBYgAygCyAEQjgIgFSADKAK4ARCNAiADKAKcASIABEAgAyAANgKgASAAEC8LIAMoApABIgAEQCADIAA2ApQBIAAQLwsgAygCWCIABEAgAyAANgJcIAAQLwsgAxAvQQAhAwsgD0EQaiQAIANFDQAgA0GIAmogDhCIAwsgB0HwygIoAgAiADYCNCAAQQxrKAIAIAdBNGpqQfzKAigCADYCACAJEPIBGiAgEMACIAdB8AFqJAAgAyIABEAgAAJ/QQAhAyMAQdAUayIBJAAgASAAIgk2AswUQfDXNC0AAEUEQP0MAAAAAAEAAAACAAAAAwAAACEqA0AgA0ECdCIAQYDYNGogKv3+Af0MGC1EVPshGUAYLURU+yEZQP3yAf0MAAAAAAAAeUAAAAAAAAB5QP3zASIr/SEAtiIsEHr9EyAr/SEBtiItEHr9IAEgKiAq/Q0ICQoLDA0ODwABAgMAAQID/f4B/QwYLURU+yEZQBgtRFT7IRlA/fIB/QwAAAAAAAB5QAAAAAAAAHlA/fMBIiv9IQC2Ii4Qev0gAiAr/SEBtiIvEHr9IAP9CwQAIABBwOQ0aiAsEGr9EyAtEGr9IAEgLhBq/SACIC8Qav0gA/0LBAAgKv0MBAAAAAQAAAAEAAAABAAAAP2uASEqIANBBGoiA0GQA0cNAAtB8Nc0QQE6AAALQeCoARAyIgX9DAAAAAAAAAAAAAAAAAAAAAD9CwJ0IAVCADcD0AEgBUIANwKEASAFQgA3A4gCIAVBADYC2AEgBUEANgKwASAFQgA3A6gBIAX9DAAAAAAAAAAAAAAAAAAAAAD9CwOQAiAF/QwAAAAAAAAAAAAAAAAAAAAA/QsCtAIgBf0MAAAAAAAAAAAAAAAAAAAAAP0LAsQCIAX9DAAAAAAAAAAAAAAAAAAAAAD9CwLUAiAFQQBB5AD8CwBB8SohAiAFQeQCaiIAQfEqNgIAQQEhAwNAIAAgA0ECdGogAkEediACc0Hlkp7gBmwgA2oiAjYCACAAIANBAWoiBEECdGogAkEediACc0Hlkp7gBmwgBGoiAjYCACAAIANBAmoiBEECdGogAkEediACc0Hlkp7gBmwgBGoiAjYCACADQQNqIgRB8ARHBEAgACAEQQJ0aiACQR52IAJzQeWSnuAGbCAEaiICNgIAIANBBGohAwwBCwsgBUHwFmpCADcDACAFQeAWav0MAAAAAAAAAAAAAAAAAAAAAP0LAwAgBUGMF2r9DAAAAAAAAAAAAAAAAAAAAAD9CwIAIAVBnBdq/QwAAAAAAAAAAAAAAAAAAAAA/QsCACAFQawXav0MAAAAAAAAAAAAAAAAAAAAAP0LAgAgBUGkFmr9DAAAAAAAAAAAAAAAAAAAAAD9CwIAQfEqIQIgBUG8F2oiAEHxKjYCAEEBIQMDQCAAIANBAnRqIAJBHnYgAnNB5ZKe4AZsIANqIgI2AgAgACADQQFqIgRBAnRqIAJBHnYgAnNB5ZKe4AZsIARqIgI2AgAgACADQQJqIgRBAnRqIAJBHnYgAnNB5ZKe4AZsIARqIgI2AgAgA0EDaiIEQfAERwRAIAAgBEECdGogAkEediACc0Hlkp7gBmwgBGoiAjYCACADQQRqIQMMAQsLIAVByCtqQgA3AwAgBUG4K2r9DAAAAAAAAAAAAAAAAAAAAAD9CwMAIAVB5Ctq/QwAAAAAAAAAAAAAAAAAAAAA/QsCACAFQfQrav0MAAAAAAAAAAAAAAAAAAAAAP0LAgAgBUGELGr9DAAAAAAAAAAAAAAAAAAAAAD9CwIAIAVB/Cpq/QwAAAAAAAAAAAAAAAAAAAAA/QsCAEHxKiECIAVBlCxqIgBB8So2AgBBASEDA0AgACADQQJ0aiACQR52IAJzQeWSnuAGbCADaiICNgIAIAAgA0EBaiIEQQJ0aiACQR52IAJzQeWSnuAGbCAEaiICNgIAIAAgA0ECaiIEQQJ0aiACQR52IAJzQeWSnuAGbCAEaiICNgIAIANBA2oiBEHwBEcEQCAAIARBAnRqIAJBHnYgAnNB5ZKe4AZsIARqIgI2AgAgA0EEaiEDDAELCyAFQaDAAGpCADcDACAFQZDAAGr9DAAAAAAAAAAAAAAAAAAAAAD9CwMAIAVBvMAAav0MAAAAAAAAAAAAAAAAAAAAAP0LAgAgBUHMwABq/QwAAAAAAAAAAAAAAAAAAAAA/QsCACAFQdzAAGr9DAAAAAAAAAAAAAAAAAAAAAD9CwIAIAVB1D9q/QwAAAAAAAAAAAAAAAAAAAAA/QsCAEHxKiECIAVB7MAAaiIAQfEqNgIAQQEhAwNAIAAgA0ECdGogAkEediACc0Hlkp7gBmwgA2oiAjYCACAAIANBAWoiBEECdGogAkEediACc0Hlkp7gBmwgBGoiAjYCACAAIANBAmoiBEECdGogAkEediACc0Hlkp7gBmwgBGoiAjYCACADQQNqIgRB8ARHBEAgACAEQQJ0aiACQR52IAJzQeWSnuAGbCAEaiICNgIAIANBBGohAwwBCwsgBUH41ABqQgA3AwAgBUHo1ABq/QwAAAAAAAAAAAAAAAAAAAAA/QsDACAFQZTVAGr9DAAAAAAAAAAAAAAAAAAAAAD9CwIAIAVBpNUAav0MAAAAAAAAAAAAAAAAAAAAAP0LAgAgBUG01QBq/QwAAAAAAAAAAAAAAAAAAAAA/QsCACAFQazUAGr9DAAAAAAAAAAAAAAAAAAAAAD9CwIAQfEqIQIgBUHE1QBqIgBB8So2AgBBASEDA0AgACADQQJ0aiACQR52IAJzQeWSnuAGbCADaiICNgIAIAAgA0EBaiIEQQJ0aiACQR52IAJzQeWSnuAGbCAEaiICNgIAIAAgA0ECaiIEQQJ0aiACQR52IAJzQeWSnuAGbCAEaiICNgIAIANBA2oiBEHwBEcEQCAAIARBAnRqIAJBHnYgAnNB5ZKe4AZsIARqIgI2AgAgA0EEaiEDDAELCyAFQdDpAGpCADcDACAFQcDpAGr9DAAAAAAAAAAAAAAAAAAAAAD9CwMAIAVB7OkAav0MAAAAAAAAAAAAAAAAAAAAAP0LAgAgBUH86QBq/QwAAAAAAAAAAAAAAAAAAAAA/QsCACAFQYzqAGr9DAAAAAAAAAAAAAAAAAAAAAD9CwIAIAVBhOkAav0MAAAAAAAAAAAAAAAAAAAAAP0LAgBB8SohAiAFQZzqAGoiAEHxKjYCAEEBIQMDQCAAIANBAnRqIAJBHnYgAnNB5ZKe4AZsIANqIgI2AgAgACADQQFqIgRBAnRqIAJBHnYgAnNB5ZKe4AZsIARqIgI2AgAgACADQQJqIgRBAnRqIAJBHnYgAnNB5ZKe4AZsIARqIgI2AgAgA0EDaiIEQfAERwRAIAAgBEECdGogAkEediACc0Hlkp7gBmwgBGoiAjYCACADQQRqIQMMAQsLIAVBqP4AakIANwMAIAVBmP4Aav0MAAAAAAAAAAAAAAAAAAAAAP0LAwAgBUHE/gBq/QwAAAAAAAAAAAAAAAAAAAAA/QsCACAFQdT+AGr9DAAAAAAAAAAAAAAAAAAAAAD9CwIAIAVB5P4Aav0MAAAAAAAAAAAAAAAAAAAAAP0LAgAgBUHc/QBq/QwAAAAAAAAAAAAAAAAAAAAA/QsCAEHxKiECIAVB9P4AaiIAQfEqNgIAQQEhAwNAIAAgA0ECdGogAkEediACc0Hlkp7gBmwgA2oiAjYCACAAIANBAWoiBEECdGogAkEediACc0Hlkp7gBmwgBGoiAjYCACAAIANBAmoiBEECdGogAkEediACc0Hlkp7gBmwgBGoiAjYCACADQQNqIgRB8ARHBEAgACAEQQJ0aiACQR52IAJzQeWSnuAGbCAEaiICNgIAIANBBGohAwwBCwsgBUGAkwFqQgA3AwAgBUHwkgFq/QwAAAAAAAAAAAAAAAAAAAAA/QsDACAFQZyTAWr9DAAAAAAAAAAAAAAAAAAAAAD9CwIAIAVBrJMBav0MAAAAAAAAAAAAAAAAAAAAAP0LAgAgBUG8kwFq/QwAAAAAAAAAAAAAAAAAAAAA/QsCACAFQbSSAWr9DAAAAAAAAAAAAAAAAAAAAAD9CwIAQfEqIQIgBUHMkwFqIgBB8So2AgBBASEDA0AgACADQQJ0aiACQR52IAJzQeWSnuAGbCADaiICNgIAIAAgA0EBaiIEQQJ0aiACQR52IAJzQeWSnuAGbCAEaiICNgIAIAAgA0ECaiIEQQJ0aiACQR52IAJzQeWSnuAGbCAEaiICNgIAIANBA2oiBEHwBEcEQCAAIARBAnRqIAJBHnYgAnNB5ZKe4AZsIARqIgI2AgAgA0EEaiEDDAELCyAF/QwAAAAAAAAAAAAAAAAAAAAA/QsDqKcBIAX9DAAAAAAAAAAAAAAAAAAAAAD9CwK8pwEgBf0MAAAAAAAAAAAAAAAAAAAAAP0LA9CnASAFQYynAWpCADcCACAFQZSnAWr9DAAAAAAAAAAAAAAAAAAAAAD9CwIAIAVB5KcBakEAQeQA/AsAIAX9DAAAAAAAAAAAAAAAAAAAAAD9CwLMqAEgASAFNgLIFCAFEOUENgKQpwECQAJAIAkoAjggCUFAayIAKAIAIAVBzABqIAkoAoQCIAkoAhQgCSgCNEEDbBDjBEUEQCABQcAfNgJwQQJBnukAIAFB8ABqEDQgBRDyAhAvQQAhAwwBCyAFKAJkEFshAiAFKAJoEFshBCABQcAfNgJgIAEgAiAEarhEAAAAAICELkGjOQNoQQRBu/AAIAFB4ABqEDQgCSgCOCAAKAIAIAVB9ABqIAkoAoQCIAkoAhQgCSgCJBDjBEUEQCABQcAfNgJQQQJB6OgAIAFB0ABqEDQgBRDyAhAvQQAhAwwBCyAFKAKMARBbIQAgBSgCkAEQWyECIAFBwB82AkAgASAAIAJquEQAAAAAgIQuQaM5A0hBBEHN7wAgAUFAaxA0AkAgCSgCNCIAIAkoAsABbCICIAVBjKgBaigCACAFKAKEqAEiB2tBAnVNDQAgAkGAgICABE8NAiAFQYioAWooAgAhAyACQQJ0IgIQMiIGIAJqIQogBiADIAdrIghBfHFqIgQhAgJAIAMgB0YNAAJAIAhBBGsiAkEsSQRAIAQhAgwBCyADIAhBfHEgBmprQRBJBEAgBCECDAELIARBEGshCCADQRBrIQwgAyACQQJ2QQFqIg5B/P///wdxIgZBAnQiAmshAyAEIAJrIQIDQCAIIA1BAnQiD2sgDCAPa/0AAgD9CwIAIA1BBGoiDSAGRw0ACyAGIA5GDQELA0AgAkEEayICIANBBGsiAyoCADgCACADIAdHDQALCyAFIAo2AoyoASAFIAQ2AoioASAFIAI2AoSoASAHRQ0AIAcQLyAJKAI0IQALIABBAnQiAhA7IQQgAhA7IQcgAhA7IQYgAkEEahA7IQIgAEEASgRAQQAhAwNAIAIgA0ECdGpBIBA7NgIAIANBAWoiAyAARw0ACwsgAiAAQQJ0akEANgIAIAUgABA7NgLIASAFIAI2AsQBIAUgBjYCwAEgBSAHNgK8ASAFIAQ2ArgBIAVBADYCtAECQCAFKALYASAFKALQASICa0EwbSAATw0AIABB1qrVKk8NAiAFKALUASEDIABBMGwiABAyIgQgAGohByAEIAMgAmtBMG1BMGxqIgQhACACIANHBEADQCAAQTBrIgAgA0EwayID/QADAP0LAwAgACAD/QADIP0LAyAgACAD/QADEP0LAxAgAiADRw0ACwsgBSAHNgLYASAFIAQ2AtQBIAUgADYC0AEgAkUNACACEC8LAkAgCSgCwAEiDSAFKAK8AiAFKAK0AiIHa0ECdU0NACANQYCAgIAETw0CIAUoArgCIQMgDUECdCIAEDIiBCAAaiEIIAQgAyAHayIGQXxxaiICIQACQCADIAdGDQACQCAGQQRrIgBBLEkEQCACIQAMAQsgAyAGQXxxIARqa0EQSQRAIAIhAAwBCyACQRBrIQogA0EQayEMIAMgAEECdkEBaiIOQfz///8HcSIGQQJ0IgBrIQMgAiAAayEAQQAhBANAIAogBEECdCIPayAMIA9r/QACAP0LAgAgBEEEaiIEIAZHDQALIAYgDkYNAQsDQCAAQQRrIgAgA0EEayIDKgIAOAIAIAMgB0cNAAsLIAUgCDYCvAIgBSACNgK4AiAFIAA2ArQCIAdFDQAgBxAvIAkoAsABIQ0LAkAgBSgCyAIgBSgCwAIiB2tBAnUgDU8NACANQYCAgIAETw0CIAUoAsQCIQMgDUECdCIAEDIiBCAAaiEIIAQgAyAHayIGQXxxaiICIQACQCADIAdGDQACQCAGQQRrIgBBLEkEQCACIQAMAQsgAyAGQXxxIARqa0EQSQRAIAIhAAwBCyACQRBrIQogA0EQayEMIAMgAEECdkEBaiIOQfz///8HcSIGQQJ0IgBrIQMgAiAAayEAQQAhBANAIAogBEECdCIPayAMIA9r/QACAP0LAgAgBEEEaiIEIAZHDQALIAYgDkYNAQsDQCAAQQRrIgAgA0EEayIDKgIAOAIAIAMgB0cNAAsLIAUgCDYCyAIgBSACNgLEAiAFIAA2AsACIAdFDQAgBxAvIAkoAsABIQ0LAkAgBSgC1AIgBSgCzAIiB2tBAnUgDU8NACANQYCAgIAETw0CIAUoAtACIQMgDUECdCIAEDIiBCAAaiEIIAQgAyAHayIGQXxxaiICIQACQCADIAdGDQACQCAGQQRrIgBBLEkEQCACIQAMAQsgAyAGQXxxIARqa0EQSQRAIAIhAAwBCyACQRBrIQ0gA0EQayEKIAMgAEECdkEBaiIMQfz///8HcSIGQQJ0IgBrIQMgAiAAayEAQQAhBANAIA0gBEECdCIOayAKIA5r/QACAP0LAgAgBEEEaiIEIAZHDQALIAYgDEYNAQsDQCAAQQRrIgAgA0EEayIDKgIAOAIAIAMgB0cNAAsLIAUgCDYC1AIgBSACNgLQAiAFIAA2AswCIAdFDQAgBxAvCwJAIAkoAiAiACAFKALgAiAFKALYAiICa0EEdU0NACAAQYCAgIABTw0CIAUoAtwCIQMgAEEEdCIAEDIiBCAAaiEHIAQgAyACa2oiBCEAIAIgA0cEQANAIABBEGsiACADQRBrIgMpAwA3AwAgACADKAIINgIIIAIgA0cNAAsLIAUgBzYC4AIgBSAENgLcAiAFIAA2AtgCIAJFDQAgAhAvC0EAIQAgAUEANgKAAUEBIQMDQCABQYABaiICIANBAnRqIABBHnYgAHNB5ZKe4AZsIANqIgA2AgAgA0EBaiIEQQJ0IAJqIABBHnYgAHNB5ZKe4AZsIARqIgA2AgAgA0ECaiIEQQJ0IAJqIABBHnYgAHNB5ZKe4AZsIARqIgA2AgAgA0EDaiIEQfAERwRAIARBAnQgAmogAEEediAAc0Hlkp7gBmwgBGoiADYCACADQQRqIQMMAQsLIAFBADYCwBQgBUHkAmogAUGAAWoiAEHEE/wKAAAgCSgChAIhAiABIAFByBRqNgKIASABQeS1ATYCgAEgASAANgKQASABIAFBzBRqNgKEASAFQZSnAWogAiAAEJACAkACfyAAIAEoApABIgNGBEAgACEDIAEoAoABQRBqDAELIANFDQEgAygCAEEUagshACADIAAoAgARAQALIAEoAsgUIgBBmKcBaigCACECIABBnKcBaigCACEEIAAoApSnASgCACgClBAhACABQcAfNgIwIAEgACAEIAJrarhEAAAAAICELkGjOQM4QQRBgfEAIAFBMGoQNCABKALMFCgChAIhAiABKALIFCEhIAEgAUHIFGo2AogBIAFB1LcBNgKAASABIAFBgAFqIgA2ApABIAEgAUHMFGo2AoQBICFBqKcBaiACIAAQkAICQAJ/IAAgASgCkAEiA0YEQCAAIQMgASgCgAFBEGoMAQsgA0UNASADKAIAQRRqCyEAIAMgACgCABEBAAsgASgCyBQiAEGspwFqKAIAIQIgAEGwpwFqKAIAIQQgACgCqKcBKAIAKAKUECEAIAFBwB82AiAgASAAIAQgAmtquEQAAAAAgIQuQaM5AyhBBEHr7wAgAUEgahA0IAEoAswUKAKEAiECIAEoAsgUISIgASABQcgUajYCiAEgAUGMuQE2AoABIAEgAUGAAWoiADYCkAEgASABQcwUajYChAEgIkG8pwFqIAIgABCQAgJAAn8gACABKAKQASIDRgRAIAAhAyABKAKAAUEQagwBCyADRQ0BIAMoAgBBFGoLIQAgAyAAKAIAEQEACyABKALIFCIAQcCnAWooAgAhAiAAQcSnAWooAgAhBCAAKAK8pwEoAgAoApQQIQAgAUHAHzYCECABIAAgBCACa2q4RAAAAACAhC5BozkDGEEEQdnwACABQRBqEDQgASgCzBQoAoQCIQIgASgCyBQhIyABIAFByBRqNgKIASABQcS6ATYCgAEgASABQYABaiIANgKQASABIAFBzBRqNgKEASAjQdCnAWogAiAAEJACAkACfyAAIAEoApABIgNGBEAgACEDIAEoAoABQRBqDAELIANFDQEgAygCAEEUagshACADIAAoAgARAQALIAEoAsgUIgBB1KcBaigCACECIABB2KcBaigCACEEIAAoAtCnASgCACgClBAhACABQcAfNgIAIAEgACAEIAJrarhEAAAAAICELkGjOQMIQQRBk/AAIAEQNCABKALIFCIDKAKUpwEiAgRAIAEoAswUKAKEAiEAIAIoAgAoApQQIQIgAygClKcBEJEBIANBpKcBaiAAIAAoAggRAAAiACACIAAoAgARBAAiADYCACADIAAQyQE2ApSnASABKALIFCEDCyADKAKopwEiAARAIAEoAswUKAKEAiECIAAoAgAoApQQIQQgABCRASADQbinAWogAiACKAIIEQAAIgAgBCAAKAIAEQQAIgA2AgAgAyAAEMkBNgKopwEgASgCyBQhAwsgAygCvKcBIgAEQCABKALMFCgChAIhAiAAKAIAKAKUECEEIAAQkQEgA0HMpwFqIAIgAigCCBEAACIAIAQgACgCABEEACIANgIAIAMgABDJATYCvKcBIAEoAsgUIQMLIAMoAtCnASIARQ0AIAEoAswUKAKEAiECIAAoAgAoApQQIQQgABCRASADQeCnAWogAiACKAIIEQAAIgAgBCAAKAIAEQQAIgA2AgAgAyAAEMkBNgLQpwEgASgCyBQhAwsgAUHQFGokACADDAELEDYACyIANgKAAiAJIAANARogCRDgBAtBAAsiADYCACAAQQBHCwvqBQIEfwJ8IwBBIGsiBCQAIAQgADYCACAEQQA6ABggBEIANwMQIAQgAjYCDCAEIAE2AgggBCMDNgIEAnwgAwRAIwBBEGsiAyQAIAMgBDYCDCADQQA2AgggA0HIATYCBCADQQRqIQUjAEGAAWsiACQAIwBB4ABrIgEkAAJAQYTzNCgCAEECRgRAIwBBEGtBADYCDAwBCyMAQRBrIgIkAANAAkACQAJAAkACQEGE8zRBAEEB/kgCAA4EAAIBAwULIAJBBGoiBkGE8zQ2AgQgAkHKATYCBCACIwMiBygCRDYCDCAHIAY2AkQQmAQjAyACKAIMNgJEQYTzNEEC/kECAEEDRw0AQYTzNBD6AQsgAkEQaiQADAILQYTzNEEBQQP+SAIAGgtBhPM0QQBBAxChAQwBCwsLIAFBAEHQAPwL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QQAhBgNAIAEgICAEIA/9GwFqIgosAABBIGuylP0TIg39DPz////8/////P////z////9DAAAAAAAAAAAAAAAAAAAAAAgFCAH/Q8iDv1O/QwAAAAAAAAAAAAAAAAAAAAA/SP9hwH9pwH9UiAcIA/9GwAiAv2tAf0MAwAAAAMAAAADAAAAAwAAAP1O/VD9+gH95gH9CwIwIAEgDf0M/P////z////8/////P////0MAAAAAAAAAAAAAAAAAAAAACAVIA79Tv0MAAAAAAAAAAAAAAAAAAAAAP0j/YcB/acB/VIgHSAC/a0B/QwDAAAAAwAAAAMAAAADAAAA/U79UP36Af3mAf0LAiAgASAN/Qz8/////P////z////8/////QwAAAAAAAAAAAAAAAAAAAAAIBYgDv1O/QwAAAAAAAAAAAAAAAAAAAAA/SP9hwH9pwH9UiAeIAL9rQH9DAMAAAADAAAAAwAAAAMAAAD9Tv1Q/foB/eYB/QsCECABIA39DPz////8/////P////z////9DAAAAAAAAAAAAAAAAAAAAAAgFyAO/U79DAAAAAAAAAAAAAAAAAAAAAD9I/2HAf2nAf1SIB8gAv2tAf0MAwAAAAMAAAADAAAAAwAAAP1O/VD9+gH95gH9CwIAIAEgICAKLAABQSBrspT9EyIN/Qz8/////P////z////8/////QwAAAAAAAAAAAAAAAAAAAAAIBAgDv1O/QwAAAAAAAAAAAAAAAAAAAAA/SP9hwH9pwH9UiAYIAL9rQH9DAMAAAADAAAAAwAAAAMAAAD9Tv1Q/foB/eYB/QsCcCABIA39DPz////8/////P////z////9DAAAAAAAAAAAAAAAAAAAAAAgESAO/U79DAAAAAAAAAAAAAAAAAAAAAD9I/2HAf2nAf1SIBkgAv2tAf0MAwAAAAMAAAADAAAAAwAAAP1O/VD9+gH95gH9CwJgIAEgDf0M/P////z////8/////P////0MAAAAAAAAAAAAAAAAAAAAACASIA79Tv0MAAAAAAAAAAAAAAAAAAAAAP0j/YcB/acB/VIgGiAC/a0B/QwDAAAAAwAAAAMAAAADAAAA/U79UP36Af3mAf0LAlAgASAN/Qz8/////P////z////8/////QwAAAAAAAAAAAAAAAAAAAAAIBMgDv1O/QwAAAAAAAAAAAAA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JCACIANGIQkgAkEEaiECIAlFDQALDAELIAEgACgCCDYCKAsLjgcCBH8EeyACQR9KBEAgAkEgbSEGA0AgASAFQQd0aiIDQUBrIAAgBUEWbGoiBC8BAEECdEGQ1gRq/QkCACIHIAQoAQIiAkEMdv0RIAJBDXb9HAEgAkEOdv0cAiACQQ92/RwDIgn9DBAAAAAQAAAAEAAAABAAAAD9TiAE/VwABv2JAf2pASIIQQT9rQH9UP0M8P////D////w////8P////2uAf36Af3mAf0LAgAgAyAHIAJBBHT9ESACQQN0/RwBIAJBAnT9HAIgAkEBdP0cA/0MEAAAABAAAAAQAAAAEAAAAP1OIAj9DA8AAAAPAAAADwAAAA8AAAD9Tv1Q/Qzw////8P////D////w/////a4B/foB/eYB/QsCACADIAcgAkEQdv0RIAJBEXb9HAEgAkESdv0cAiACQRN2/RwD/QwQAAAAEAAAABAAAAAQAAAA/U4gBEEKav1cAAD9iQH9qQEiCEEE/a0B/VD9DPD////w////8P////D////9rgH9+gH95gH9CwJQIAMgByACQQR2/REgAkEFdv0cASACQQZ2/RwCIAJBB3b9HAMiCkEE/asB/QwQAAAAEAAAABAAAAAQAAAA/U4gCP0MDwAAAA8AAAAPAAAADwAAAP1O/VD9DPD////w////8P////D////9rgH9+gH95gH9CwIQIAMgByACQRR2/REgAkEVdv0cASACQRZ2/RwCIAJBF3b9HAP9DBAAAAAQAAAAEAAAABAAAAD9TiAEQQ5q/VwAAP2JAf2pASIIQQT9rQH9UP0M8P////D////w////8P////2uAf36Af3mAf0LAmAgAyAHIAr9DBAAAAAQAAAAEAAAABAAAAD9TiAI/QwPAAAADwAAAA8AAAAPAAAA/U79UP0M8P////D////w////8P////2uAf36Af3mAf0LAiAgAyAHIAJBGHb9ESACQRl2/RwBIAJBGnb9HAIgAkEbdv0cA/0MEAAAABAAAAAQAAAAEAAAAP1OIARBEmr9XAAA/YkB/akBIghBBP2tAf1Q/Qzw////8P////D////w/////a4B/foB/eYB/QsCcCADIAcgCUEE/asB/QwQAAAAEAAAABAAAAAQAAAA/U4gCP0MDwAAAA8AAAAPAAAADwAAAP1O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IAAoAgQ2AigPCwsgAUGfeDYCACABQQA2AigPCxD/AQALnQEBBH8CQAJAIAEoAhAgACgCFEEBa0EMbGoiAi0ACEUNASACKAIEIAIoAgAiBWsiAyABKAIMIAEoAggiBGtKDQFBACECIANBAEwNAANAIAIgBWotAAAgAiAEai0AAEcNAiADIAJBAWoiAkcNAAsMAAsgAUGeeDYCACABIAMgBGo2AgggASAAKAIENgIoDwsgAUGfeDYCACABQQA2AigLUgEBfyAAQcyvATYCACAAKAIIIgFBBGpBf/4eAgBFBEAgASABKAIAKAIIEQEACyAAQdypATYCACAAKAIEIgEEQCABIAEoAgAoAgQRAQALIAAQLwtQAQF/IABBzK8BNgIAIAAoAggiAUEEakF//h4CAEUEQCABIAEoAgAoAggRAQALIABB3KkBNgIAIAAoAgQiAQRAIAEgASgCACgCBBEBAAsgAAvPAQEEfwJAAkACQCABKAIQIAAoAhRBDGxqQQxrIgMtAAhFDQIgAygCBCADKAIAayIEIAEoAgwgASgCCCICa0oNAiAEQQBMDQFBACECA0AgACgCDCIFIAMoAgAgAmosAAAgBSgCACgCFBEEACAAKAIMIgUgASgCCCACaiwAACAFKAIAKAIUEQQARw0DIAQgAkEBaiICRw0ACwwACyABKAIIIQILIAFBnng2AgAgASACIARqNgIIIAEgACgCBDYCKA8LIAFBn3g2AgAgAUEANgIoC1IBAX8gAEH0rgE2AgAgACgCCCIBQQRqQX/+HgIARQRAIAEgASgCACgCCBEBAAsgAEHcqQE2AgAgACgCBCIBBEAgASABKAIAKAIEEQEACyAAEC8LUAEBfyAAQfSuATYCACAAKAIIIgFBBGpBf/4eAgBFBEAgASABKAIAKAIIEQEACyAAQdypATYCACAAKAIEIgEEQCABIAEoAgAoAgQRAQALIAALjQQCAnsDfyACQR9KBEAgAkEgbSEHA0AgASAFQQd0aiICQUBrIAAgBUESbGoiBi8BAEECdEGQ1gRq/QkCACIDIAb9XAAC/YkB/akBIgRBBP2tAf0M+P////j////4////+P////2uAf36Af3mAf0LAgAgAiADIAT9DA8AAAAPAAAADwAAAA8AAAD9Tv0M+P////j////4////+P////2uAf36Af3mAf0LAgAgAiADIAZBBmr9XAAA/YkB/akBIgRBBP2tAf0M+P////j////4////+P////2uAf36Af3mAf0LAlAgAiADIAT9DA8AAAAPAAAADwAAAA8AAAD9Tv0M+P////j////4////+P////2uAf36Af3mAf0LAhAgAiADIAZBCmr9XAAA/YkB/akBIgRBBP2tAf0M+P////j////4////+P////2uAf36Af3mAf0LAmAgAiADIAT9DA8AAAAPAAAADwAAAA8AAAD9Tv0M+P////j////4////+P////2uAf36Af3mAf0LAiAgAiADIAZBDmr9XAAA/YkB/akBIgRBBP2tAf0M+P////j////4////+P////2uAf36Af3mAf0LAnAgAiADIAT9DA8AAAAPAAAADwAAAA8AAAD9Tv0M+P////j////4////+P////2uAf36Af3mAf0LAjAgBUEBaiIFIAdHDQALCwtPAQF/AkAgASgCCCICIAEoAgxGDQAgAi0AACAALQAIRw0AIAFBnXg2AgAgASACQQFqNgIIIAEgACgCBDYCKA8LIAFBn3g2AgAgAUEANgIoC08BAX8CQCABKAIIIgIgASgCDEYNACACLQAAIAAtABRHDQAgAUGdeDYCACABIAJBAWo2AgggASAAKAIENgIoDwsgAUGfeDYCACABQQA2AigLUgEBfyAAQditATYCACAAKAIIIgFBBGpBf/4eAgBFBEAgASABKAIAKAIIEQEACyAAQdypATYCACAAKAIEIgEEQCABIAEoAgAoAgQRAQALIAAQLwtQAQF/IABB2K0BNgIAIAAoAggiAUEEakF//h4CAEUEQCABIAEoAgAoAggRAQALIABB3KkBNgIAIAAoAgQiAQRAIAEgASgCACgCBBEBAAsgAAtoAQJ/AkAgASgCCCICIAEoAgxGDQAgACgCDCIDIAIsAAAgAygCACgCFBEEAEH/AXEgAC0AFEcNACABQZ14NgIAIAEgASgCCEEBajYCCCABIAAoAgQ2AigPCyABQZ94NgIAIAFBADYCKAtSAQF/IABB/KwBNgIAIAAoAggiAUEEakF//h4CAEUEQCABIAEoAgAoAggRAQALIABB3KkBNgIAIAAoAgQiAQRAIAEgASgCACgCBBEBAAsgABAvC1ABAX8gAEH8rAE2AgAgACgCCCIBQQRqQX/+HgIARQRA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b2FkY2FzdAB1bnNpZ25lZCBzaG9ydABhbGVydAB3aGlzcGVyX2t2X2NhY2hlX2ZpbmRfc2xvdABwcmludAB1bnNpZ25lZCBpbnQAY2lyY3VtZmxleC1hY2NlbnQAZ3JhdmUtYWNjZW50AGZ1bGxfZGVmYXVsdABrdl9jYWNoZV9pbml0AHhkaWdpdAAuY3Jvc3NfYXR0bi5xdWVyeS53ZWlnaHQALmF0dG4ucXVlcnkud2VpZ2h0AC5jcm9zc19hdHRuLmtleS53ZWlnaHQALmF0dG4ua2V5LndlaWdodAAuY3Jvc3NfYXR0bi5vdXQud2VpZ2h0AC5hdHRuLm91dC53ZWlnaHQAZW5jb2Rlci5sbl9wb3N0LndlaWdodAAubWxwX2xuLndlaWdodAAuY3Jvc3NfYXR0bl9sbi53ZWlnaHQALmF0dG5fbG4ud2VpZ2h0AGRlY29kZXIubG4ud2VpZ2h0AGRlY29kZXIudG9rZW5fZW1iZWRkaW5nLndlaWdodAAuY3Jvc3NfYXR0bi52YWx1ZS53ZWlnaHQALmF0dG4udmFsdWUud2VpZ2h0AGVuY29kZXIuY29udjIud2VpZ2h0AC5tbHAuMi53ZWlnaHQAZW5jb2Rlci5jb252MS53ZWlnaHQALm1scC4wLndlaWdodABzZXQAcmlnaHQtY3VybHktYnJhY2tldABsZWZ0LWN1cmx5LWJyYWNrZXQAcmlnaHQtc3F1YXJlLWJyYWNrZXQAbGVmdC1zcXVhcmUtYnJhY2tldABwdW5jdABnZ21sX25ld19vYmplY3QAT2N0AGZsb2F0AFNhdABjb21tZXJjaWFsLWF0AHVpbnQ2NF90AGh5cGhlbi1taW51cwByZXZlcnNlLXNvbGlkdXMAd2hpc3Blcl9leHBfY29tcHV0ZV90b2tlbl9sZXZlbF90aW1lc3RhbXBzAGFmcmlrYWFucwBwYXJhbXMAZ2dtbF9nZXRfbl90YXNrcwByaWdodC1wYXJlbnRoZXNpcwBsZWZ0LXBhcmVudGhlc2lzAHdoaXNwZXJfcHJpbnRfdGltaW5ncwAuY3Jvc3NfYXR0bi5xdWVyeS5iaWFzAC5hdHRuLnF1ZXJ5LmJpYXMALmNyb3NzX2F0dG4ub3V0LmJpYXMALmF0dG4ub3V0LmJpYXMAZW5jb2Rlci5sbl9wb3N0LmJpYXMALm1scF9sbi5iaWFzAC5jcm9zc19hdHRuX2xuLmJpYXMALmF0dG5fbG4uYmlhcwBkZWNvZGVyLmxuLmJpYXMALmNyb3NzX2F0dG4udmFsdWUuYmlhcwAuYXR0bi52YWx1ZS5iaWFzAGVuY29kZXIuY29udjIuYmlhcwAubWxwLjIuYmlhcwBlbmNvZGVyLmNvbnYxLmJpYXMALm1scC4wLmJpYXMAcm93X2lkID49IDAgJiYgcm93X2lkIDwgbl9hcwAlcwBmb3VyAHdoaXNwZXJfbGFuZ19zdHIAQXByAGNvbnN0cnVjdG9yAHZlY3RvcgBjZ3JhcGgtPm5vZGVzW2NncmFwaC0+bl9ub2RlcyAtIDFdID09IHRlbnNvcgB1bmtub3duIGFsbG9jYXRpb24gZXJyb3IAYmFzaGtpcgBsb3dlcgB1cHBlcgBraG1lcgBidWZmZXIAT2N0b2JlcgBOb3ZlbWJlcgBTZXB0ZW1iZXIARGVjZW1iZXIAdGF0YXIAbXlhbm1hcgB1bnNpZ25lZCBjaGFyAGlvc19iYXNlOjpjbGVhcgBNYXIAcQAvVXNlcnMvZ2dlcmdhbm92L2RldmVsb3BtZW50L2dpdGh1Yi93aGlzcGVyLmNwcC93aGlzcGVyLmNwcABmdWxsLXN0b3AAU2VwACVJOiVNOiVTICVwAHR3bwBhdXRvAHBhc2h0bwB6ZXJvAGxhbwB1bmtub3duAFN1bgBKdW4AY2FycmlhZ2UtcmV0dXJuAGJyZXRvbgBzZW1pY29sb24Ac3RkOjpleGNlcHRpb24AX19jeGFfZ3VhcmRfYWNxdWlyZSBkZXRlY3RlZCByZWN1cnNpdmUgaW5pdGlhbGl6YXRpb24ATW9uAGxhdGluAHBlcmNlbnQtc2lnbgBwbHVzLXNpZ24AZXF1YWxzLXNpZ24AbnVtYmVyLXNpZ24AZG9sbGFyLXNpZ24AbGVzcy10aGFuLXNpZ24AZ3JlYXRlci10aGFuLXNpZ24Ac2V2ZW4AdHVya21lbgBoeXBoZW4Ab2NjaXRhbgB0aWJldGFuAG5hbgBnZXJtYW4AY3BsYW4AY2F0YWxhbgBsYXR2aWFuAGJlbGFydXNpYW4AcnVzc2lhbgBwZXJzaWFuAGluZG9uZXNpYW4AaHVuZ2FyaWFuAGJ1bGdhcmlhbgBib3NuaWFuAG1hY2Vkb25pYW4AdWtyYWluaWFuAHNsb3ZlbmlhbgBsaXRodWFuaWFuAG1vbmdvbGlhbgBpdGFsaWFuAG5vcndlZ2lhbgBzZXJiaWFuAGtvcmVhbgBKYW4AYWxudW0AbWVkaXVtAG1hbGF5YWxhbQBKdWwAY250cmwAZ2dtbF9uZXdfdGVuc29yX2ltcGwAYm9vbABzbWFsbABzdGQ6OmJhZF9mdW5jdGlvbl9jYWxsAEFwcmlsAHRhbWlsAGVtc2NyaXB0ZW46OnZhbABueW5vcnNrAGFzdGVyaXNrAHF1ZXN0aW9uLW1hcmsAcXVvdGF0aW9uLW1hcmsAZXhjbGFtYXRpb24tbWFyawBibGFuawB0YWppawBncmVlawB1emJlawBzbG92YWsAagBtYW9yaQBGcmkAYXplcmJhaWphbmkAc3dhaGlsaQBuZXBhbGkAc29tYWxpAGJlbmdhbGkAbWFyYXRoaQBzaW5kaGkAaGluZGkAcHVuamFiaQBiYWRfYXJyYXlfbmV3X2xlbmd0aAB3ZWxzaABmaW5uaXNoAHNwYW5pc2gAZGFuaXNoAHBvbGlzaABlbmdsaXNoAHR1cmtpc2gAbHV4ZW1ib3VyZ2lzaABzd2VkaXNoAHlpZGRpc2gAYmFja3NsYXNoAGdyYXBoAGthemFraABkdXRjaABNYXJjaABmcmVuY2gAY3plY2gAQXVnAHRhZ2Fsb2cAdW5zaWduZWQgbG9uZwB0ZXJtaW5hdGluZwBzdGQ6OndzdHJpbmcAYmFzaWNfc3RyaW5nAHN0ZDo6c3RyaW5nAHN0ZDo6dTE2c3RyaW5nAHN0ZDo6dTMyc3RyaW5nAGVuY29kZXIucG9zaXRpb25hbF9lbWJlZGRpbmcAZGVjb2Rlci5wb3NpdGlvbmFsX2VtYmVkZGluZwBpbmYAJS4wTGYAJUxmAGNncmFwaC0+bl9sZWFmcyA8IGNncmFwaC0+c2l6ZQBjZ3JhcGgtPm5fbm9kZXMgPCBjZ3JhcGgtPnNpemUAd2hpc3Blcl90b2tlbml6ZQBmaXZlAHl1ZQB0cnVlAGJhc3F1ZQBpbnZhbGlkIGFsaWdubWVudCB2YWx1ZQBUdWUAd2hpc3Blcl9pbml0X3N0YXRlAHdoaXNwZXJfaW5pdF93aXRoX3BhcmFtc19ub19zdGF0ZQB3aGlzcGVyX2luaXRfZnJvbV9maWxlX3dpdGhfcGFyYW1zX25vX3N0YXRlAHdoaXNwZXJfbGFuZ19hdXRvX2RldGVjdF93aXRoX3N0YXRlAHdoaXNwZXJfZnVsbF93aXRoX3N0YXRlAHdoaXNwZXJfZW5jb2RlX3dpdGhfc3RhdGUAd2hpc3Blcl9kZWNvZGVfd2l0aF9zdGF0ZQB0cmFuc2xhdGUAZmFsc2UAcG9ydHVndWVzZQBtYWx0ZXNlAGZhcm9lc2UAY2FudG9uZXNlAGNoaW5lc2UAc3VuZGFuZXNlAHZpZXRuYW1lc2UAX19jeGFfZ3VhcmRfcmVsZWFzZQB1bmRlcnNjb3JlAF9fY3hhX2d1YXJkX2FjcXVpcmUAc3JjMC0+dHlwZSA9PSBkc3QtPnR5cGUAZHN0LT50eXBlID09IHNyYzAtPnR5cGUAVW5rbm93biBlcnJvciB0eXBlAEp1bmUAb25lAG5pbmUAbmV3bGluZQBsb3ctbGluZQB2ZXJ0aWNhbC1saW5lAGhhaXRpYW4gY3Jlb2xlAGRvdWJsZQBhcG9zdHJvcGhlAGxhcmdlAHRocmVlAGZyZWUAdGlsZGUAcmlnaHQtYnJhY2UAbGVmdC1icmFjZQBiYWNrc3BhY2UAdHJhbnNjcmliZQBwZXJpb2QAbWFwOjphdDogIGtleSBub3QgZm91bmQAYW1wZXJzYW5kAHZvaWQAd2hpc3Blcl9sYW5nX2lkAHRlcm1pbmF0ZV9oYW5kbGVyIHVuZXhwZWN0ZWRseSByZXR1cm5lZAB0aHJlYWQgY29uc3RydWN0b3IgZmFpbGVkAF9fdGhyZWFkX3NwZWNpZmljX3B0ciBjb25zdHJ1Y3Rpb24gZmFpbGVkAHRocmVhZDo6am9pbiBmYWlsZWQAbXV0ZXggbG9jayBmYWlsZWQAZm9ybS1mZWVkAFdlZAB3aGlzcGVyX21vZGVsX2xvYWQAJTAyZDolMDJkOiUwMmQlcyUwM2QAbGVhZl8lZABub2RlXyVkAGdnbWxfYWxpZ25lZF9tYWxsb2MAZ2dtbF90YWxsb2NyX2FsbG9jAHN0ZDo6YmFkX2FsbG9jAGRzdC0+bmVbMF0gPT0gbmMAYW1oYXJpYwBpY2VsYW5kaWMAYXJhYmljAERlYwAvVXNlcnMvZ2dlcmdhbm92L2RldmVsb3BtZW50L2dpdGh1Yi93aGlzcGVyLmNwcC9nZ21sLmMAL1VzZXJzL2dnZXJnYW5vdi9kZXZlbG9wbWVudC9naXRodWIvd2hpc3Blci5jcHAvZ2dtbC1iYWNrZW5kLmMAL1VzZXJzL2dnZXJnYW5vdi9kZXZlbG9wbWVudC9naXRodWIvd2hpc3Blci5jcHAvZ2dtbC1hbGxvYy5jAHdiAHJiAEZlYgB2ZXJ0aWNhbC10YWIAbl9sb2dpdHMgPT0gY3R4LnZvY2FiLm5fdm9jYWIAdytiAHIrYgBhK2IAcndhAGNwbGFuLT53b3JrX2RhdGEAaGF1c2EAc2hvbmEAY29tbWEAc2luaGFsYQBsaW5nYWxhAGFscGhhAGthbm5hZGEAeW9ydWJhAFtfZXh0cmFfdG9rZW5fAFtfVFRfAFtfTEFOR18AW19TT1RfXQBbX05PVF9dAFtfRU9UX10AW19CRUdfXQBbX1RSQU5TTEFURV9dAFtfVFJBTlNDUklCRV9dAGEtPm5lWzJdID09IGItPm5lWzJdAGEtPm5lWzJdID09IGItPm5lWzFdAGEtPm5lWzFdID09IGItPm5lWzFdAFoAdGVuc29yLT5vcCA9PSBHR01MX09QX1VOQVJZAE1BUF9VTkFSWQBNQVBfQklOQVJZAENQWQAlYSAlYiAlZCAlSDolTTolUyAlWQBQT1NJWABTT0ZUX01BWABBUkdNQVgAVklFVwBESVYAQ1BVAExFQUtZX1JFTFUAU1FSVABBUkdTT1JUAFdJTl9QQVJUAFdJTl9VTlBBUlQAaXNfcG9zaXRpdmVfY2hhciB8fCBwb3MtPnR5cGUgPT0gV0hJU1BFUl9HUkVUWVBFX0NIQVJfTk9UAHd0eXBlICE9IEdHTUxfVFlQRV9DT1VOVABDT05UAFNFVABNVUxfTUFUAFJFUEVBVABDT05DQVQAR0VUX1JPV1MAU1VNX1JPV1MAQ1JPU1NfRU5UUk9QWV9MT1NTAEdFVF9SRUxfUE9TAEFERF9SRUxfUE9TAGF4aXMzID49IDAgJiYgYXhpczMgPCBHR01MX01BWF9ESU1TAGF4aXMyID49IDAgJiYgYXhpczIgPCBHR01MX01BWF9ESU1TAGF4aXMxID49IDAgJiYgYXhpczEgPCBHR01MX01BWF9ESU1TAGF4aXMwID49IDAgJiYgYXhpczAgPCBHR01MX01BWF9ESU1TACVIOiVNOiVTAFNRUgBRAERVUABDTEFNUABESUFHX01BU0tfWkVSTwBGTEFTSF9BVFROAE5BTgBNRUFOAG5lMSA9PSBOAG5lZDEgPT0gTgBTVU0AUk1TX05PUk0AR1JPVVBfTk9STQBQTQBBTQBuZWIxMCA9PSBNAG5lYzAwID09IE0ATlVMAE1VTABJTTJDT0wAdGVuc29yLT5kYXRhID09IE5VTEwAaGFzaF9zZXQua2V5c1tpXSA9PSBOVUxMAHRlbnNvciAhPSBOVUxMAGN0eC0+bWVtX2J1ZmZlciAhPSBOVUxMAHZpZXctPnZpZXdfc3JjICE9IE5VTEwgJiYgdmlldy0+dmlld19zcmMtPmRhdGEgIT0gTlVMTABpICE9IEdHTUxfSEFTSFRBQkxFX0ZVTEwATENfQUxMAHE4X0sAcTZfSwBxNV9LAHE0X0sAcTNfSwBxMl9LAFNPRlRfTUFYX0JBQ0sAU0lMVV9CQUNLAFJFUEVBVF9CQUNLAEdFVF9ST1dTX0JBQ0sAQ1JPU1NfRU5UUk9QWV9MT1NTX0JBQ0sARkxBU0hfQVRUTl9CQUNLAFJNU19OT1JNX0JBQ0sAUk9QRV9CQUNLAEoAQUxJQkkASABMT0cATEFORwBESUFHAERJQUdfTUFTS19JTkYARkxBU0hfRkYAUEVSTVVURQBUUkFOU1BPU0UAUk9QRQBSRVNIQVBFAE5PTkUAVVBTQ0FMRQBPVVRfUFJPRABNVUxfTUFUX0lEAERFUFJFQ0FURUQAQUREAFBBRABQT09MXzJEAENPTlZfVFJBTlNQT1NFXzJEAFBPT0xfMUQAQ09OVl9UUkFOU1BPU0VfMUQAbmV2MSA9PSBEAG5lYzAxID09IEQAbmVrMCA9PSBEAG5lMCA9PSBEAG5lZDAgPT0gRABuZWMxMCA9PSBEAG5lYjAwID09IEQAQUNDAFNVQgBBAGVtc2NyaXB0ZW46Om1lbW9yeV92aWV3PHNob3J0PgBlbXNjcmlwdGVuOjptZW1vcnlfdmlldzx1bnNpZ25lZCBzaG9ydD4AZW1zY3JpcHRlbjo6bWVtb3J5X3ZpZXc8aW50PgBlbXNjcmlwdGVuOjptZW1vcnlfdmlldzx1bnNpZ25lZCBpbnQ+AGVtc2NyaXB0ZW46Om1lbW9yeV92aWV3PGZsb2F0PgBlbXNjcmlwdGVuOjptZW1vcnlfdmlldzx1aW50OF90PgBlbXNjcmlwdGVuOjptZW1vcnlfdmlldzxpbnQ4X3Q+AGVtc2NyaXB0ZW46Om1lbW9yeV92aWV3PHVpbnQxNl90PgBlbXNjcmlwdGVuOjptZW1vcnlfdmlldzxpbnQxNl90PgBlbXNjcmlwdGVuOjptZW1vcnlfdmlldzx1aW50NjRfdD4AZW1zY3JpcHRlbjo6bWVtb3J5X3ZpZXc8aW50NjRfdD4AZW1zY3JpcHRlbjo6bWVtb3J5X3ZpZXc8dWludDMyX3Q+AGVtc2NyaXB0ZW46Om1lbW9yeV92aWV3PGludDMyX3Q+AGVtc2NyaXB0ZW46Om1lbW9yeV92aWV3PGNoYXI+AGVtc2NyaXB0ZW46Om1lbW9yeV92aWV3PHVuc2lnbmVkIGNoYXI+AHN0ZDo6YmFzaWNfc3RyaW5nPHVuc2lnbmVkIGNoYXI+AGVtc2NyaXB0ZW46Om1lbW9yeV92aWV3PHNpZ25lZCBjaGFyPgBlbXNjcmlwdGVuOjptZW1vcnlfdmlldzxsb25nPgBlbXNjcmlwdGVuOjptZW1vcnlfdmlldzx1bnNpZ25lZCBsb25nPgBlbXNjcmlwdGVuOjptZW1vcnlfdmlldzxkb3VibGU+AD4+PgA8PDwAMDEyMzQ1Njc4OQBpOABIRUFQVTgAQy5VVEYtOABpMTYAZjE2AGRzdC0+dHlwZSA9PSBHR01MX1RZUEVfRjE2AHNyYzAtPnR5cGUgPT0gR0dNTF9UWVBFX0YxNgAgdjMAYXhpczIgIT0gYXhpczMAYXhpczEgIT0gYXhpczMAYXhpczAgIT0gYXhpczMAbmUwMyA9PSBuZTMAbmIyIDw9IG5iMwBNQVBfQ1VTVE9NMwBuZTMgPT0gbmUxMwBuZTAzID09IG5lMTMAbmUzID09IG5lMDMAYXhpczEgIT0gYXhpczIAYXhpczAgIT0gYXhpczIAZ2dtbF9uZWxlbWVudHMoYSkgPT0gbmUwKm5lMSpuZTIAbl9oZWFkID09IG5lMgBuZTAyID09IG5lMgBuYjEgPD0gbmIyAG5lMiA9PSBuZWEyAE1BUF9DVVNUT00yAGkzMgBmMzIAYi0+dHlwZSA9PSBHR01MX1RZUEVfSTMyAGRzdC0+dHlwZSA9PSBHR01MX1RZUEVfRjMyAHNyYzEtPnR5cGUgPT0gR0dNTF9UWVBFX0YzMgBNQVBfQ1VTVE9NM19GMzIATUFQX0NVU1RPTTJfRjMyAE1BUF9DVVNUT00xX0YzMgBuZTIgPT0gbmUxMgBuZTAyID09IG5lMTIAbmUyID09IG5lMDIAYXhpczAgIT0gYXhpczEAZ2dtbF9uZWxlbWVudHMoYSkgPT0gbmUwKm5lMQBuZTAwID09IG5lMQBuYjAgPD0gbmIxAG5lMSA9PSBuZWExAHE4XzEAcTVfMQBxNF8xAE1BUF9DVVNUT00xAEFERDEAbmUxID09IG5lMTEAbmUxID09IG5lMDEAbmUwID09IG5lMDEAdCA9PSAwIHx8IHQgPT0gMQBtYXNrLT5uZVszXSA9PSAxAGItPm5lWzNdID09IDEAbm9kZS0+c3JjWzFdLT5uZVszXSA9PSAxAG5vZGUtPnNyY1swXS0+bmVbM10gPT0gMQBtYXNrLT5uZVsyXSA9PSAxAG5vZGUtPnNyY1sxXS0+bmVbMl0gPT0gMQBuZWMxMSA9PSAxAG5lYjExID09IDEAbmUwMSA9PSAxAG5lMCA9PSAxAGdnbWxfYmxja19zaXplKHJlc3VsdF90eXBlKSA9PSAxAGswID09IHMwAG5lMDAgPT0gbmUwAG5fZGltcyA8PSBuZTAAbmUwID09IG5lYTAAcThfMABxNV8wAHE0XzAAbmUxID09IG5lMTAAbmUwID09IG5lMDAAY3BsYW4tPm5fdGhyZWFkcyA+IDAAbl9wYXN0ID49IDAAUCA+PSAwAHBhcmFtcy0+aXRoID09IDAAcmMgPT0gMAAoKHVpbnRwdHJfdCkgKG1lbV9idWZmZXIgKyBvYmpfbmV3LT5vZmZzKSklR0dNTF9NRU1fQUxJR04gPT0gMAAoKHVpbnRwdHJfdCkgKGN0eC0+bWVtX2J1ZmZlcikpJUdHTUxfTUVNX0FMSUdOID09IDAAbl9kaW1zICUgMiA9PSAwAHAwID09IDAAVGhlIGV4cHJlc3Npb24gY29udGFpbmVkIG1pc21hdGNoZWQgeyBhbmQgfS4AZW5jb2Rlci5ibG9ja3MuAGRlY29kZXIuYmxvY2tzLgBUaGUgZXhwcmVzc2lvbiBjb250YWluZWQgYW4gaW52YWxpZCBjaGFyYWN0ZXIgcmFuZ2UsIHN1Y2ggYXMgW2ItYV0gaW4gbW9zdCBlbmNvZGluZ3MuAEFuIGVtcHR5IHJlZ2V4IGlzIG5vdCBhbGxvd2VkIGluIHRoZSBQT1NJWCBncmFtbWFyLgBUaGUgZXhwcmVzc2lvbiBjb250YWluZWQgYW4gaW52YWxpZCByYW5nZSBpbiBhIHt9IGV4cHJlc3Npb24uAFRoZSBwYXJzZXIgZGlkIG5vdCBjb25zdW1lIHRoZSBlbnRpcmUgcmVndWxhciBleHByZXNzaW9uLgBPbmUgb2YgKj8reyB3YXMgbm90IHByZWNlZGVkIGJ5IGEgdmFsaWQgcmVndWxhciBleHByZXNzaW9uLgBUaGUgY29tcGxleGl0eSBvZiBhbiBhdHRlbXB0ZWQgbWF0Y2ggYWdhaW5zdCBhIHJlZ3VsYXIgZXhwcmVzc2lvbiBleGNlZWRlZCBhIHByZS1zZXQgbGV2ZWwuAFRoZSBleHByZXNzaW9uIGNvbnRhaW5lZCBhbiBpbnZhbGlkIGVzY2FwZWQgY2hhcmFjdGVyLCBvciBhIHRyYWlsaW5nIGVzY2FwZS4AVGhlcmUgd2FzIGluc3VmZmljaWVudCBtZW1vcnkgdG8gY29udmVydCB0aGUgZXhwcmVzc2lvbiBpbnRvIGEgZmluaXRlIHN0YXRlIG1hY2hpbmUuAFRoZSBleHByZXNzaW9uIGNvbnRhaW5lZCBhbiBpbnZhbGlkIGNvbGxhdGluZyBlbGVtZW50IG5hbWUuAFRoZSBleHByZXNzaW9uIGNvbnRhaW5lZCBhbiBpbnZhbGlkIGNoYXJhY3RlciBjbGFzcyBuYW1lLgBUaGVyZSB3YXMgaW5zdWZmaWNpZW50IG1lbW9yeSB0byBkZXRlcm1pbmUgd2hldGhlciB0aGUgcmVndWxhciBleHByZXNzaW9uIGNvdWxkIG1hdGNoIHRoZSBzcGVjaWZpZWQgY2hhcmFjdGVyIHNlcXVlbmNlLgBUaGUgZXhwcmVzc2lvbiBjb250YWluZWQgYW4gaW52YWxpZCBiYWNrIHJlZmVyZW5jZS4AQW4gaW52YWxpZCByZWdleCBncmFtbWFyIGhhcyBiZWVuIHJlcXVlc3RlZC4AVGhlIGV4cHJlc3Npb24gY29udGFpbmVkIG1pc21hdGNoZWQgWyBhbmQgXS4AVGhlIGV4cHJlc3Npb24gY29udGFpbmVkIG1pc21hdGNoZWQgKCBhbmQgKS4ALS0tAHcrACdzfCd0fCdyZXwndmV8J218J2xsfCdkfCA/W1s6YWxwaGE6XV0rfCA/W1s6ZGlnaXQ6XV0rfCA/W15cc1s6YWxwaGE6XVs6ZGlnaXQ6XV0rfFxzKyg/IVxTKXxccysAcisAYSsAJXMgKGNvcHkpACVzICh2aWV3KQBnZ21sX2JhY2tlbmRfaXNfY3B1KGJhY2tlbmRfY3B1KQBnZ21sX2lzX2NvbnRpZ3VvdXMoZHN0KQBvZmZzZXQgKyBpbTAqbmIwICsgaW0xKm5iMSArIGltMipuYjIgKyBpbTMqbmIzIDw9IGdnbWxfbmJ5dGVzKGRzdCkAb2Zmc2V0ICsgKG5lMTAgPT0gMCA/IDAgOiBuZTEwLTEpKm5iMCArIChuZTExID09IDAgPyAwIDogbmUxMS0xKSpuYjEgKyAobmUxMiA9PSAwID8gMCA6IG5lMTItMSkqbmIyICsgKG5lMTMgPT0gMCA/IDAgOiBuZTEzLTEpKm5iMyA8IGdnbWxfbmJ5dGVzKGRzdCkAZ2dtbF9pc19zY2FsYXIoZHN0KQBnZ21sX2lzX2NvbnRpZ3VvdXNfZXhjZXB0X2RpbV8xKGRzdCkAZ2dtbF9hcmVfc2FtZV9zaGFwZShzcmMxLCBkc3QpAGdnbWxfY2FuX3JlcGVhdChzcmMwLCBkc3QpAGdnbWxfYXJlX3NhbWVfc2hhcGUoc3JjMCwgc3JjMSkgJiYgZ2dtbF9hcmVfc2FtZV9zaGFwZShzcmMwLCBkc3QpAGdnbWxfY2FuX3JlcGVhdChzcmMxLCBzcmMwKSAmJiBnZ21sX2FyZV9zYW1lX3NoYXBlKHNyYzAsIGRzdCkAJXMgKGNvbnQpAGRzdC0+bmJbMF0gPT0gc2l6ZW9mKGZsb2F0KQBzcmMwLT5uYlswXSA9PSBzaXplb2YoZmxvYXQpAG5idjAgPT0gc2l6ZW9mKGZsb2F0KQBuYnEwID09IHNpemVvZihmbG9hdCkAbmJrMCA9PSBzaXplb2YoZmxvYXQpAG5iMCA9PSBzaXplb2YoZmxvYXQpAG5iYzEwID09IHNpemVvZihmbG9hdCkAbmIxMCA9PSBzaXplb2YoZmxvYXQpAG5iYjEwID09IHNpemVvZihmbG9hdCkAbmIwMCA9PSBzaXplb2YoZmxvYXQpAHNyYzAtPm5iWzBdID09IHNpemVvZihnZ21sX2ZwMTZfdCkAbmJ2MCA9PSBzaXplb2YoZ2dtbF9mcDE2X3QpAG5icTAgPT0gc2l6ZW9mKGdnbWxfZnAxNl90KQBuYmswID09IHNpemVvZihnZ21sX2ZwMTZfdCkAbmIwID09IHNpemVvZihnZ21sX2ZwMTZfdCkAbmJhMCA9PSBzaXplb2YoZ2dtbF9mcDE2X3QpAG5iYzAwID09IHNpemVvZihnZ21sX2ZwMTZfdCkAbmIwMCA9PSBzaXplb2YoZ2dtbF9mcDE2X3QpAG5iYjAwID09IHNpemVvZihnZ21sX2ZwMTZfdCkAJXMgKGNvcHkgb2YgJXMpACFnZ21sX2lzX3ZpZXcodGVuc29yKQAobnVsbCkAZ2dtbF9pc19jb250aWd1b3VzKG1hc2spAG5iMTAgPT0gZ2dtbF90eXBlX3NpemUoc3JjMS0+dHlwZSkAZ2dtbF9pc19xdWFudGl6ZWQoc3JjMC0+dHlwZSkAbmIwMCA9PSBnZ21sX3R5cGVfc2l6ZSh0eXBlKQAlcyAocGVybXV0ZWQpACVzICh0cmFuc3Bvc2VkKQAlcyAocmVzaGFwZWQpAGdnbWxfaXNfY29udGlndW91c19leGNlcHRfZGltXzEoZ3JhZCkAZ2dtbF9hcmVfc2FtZV9zaGFwZShzcmMwLCBncmFkKQB2aWV3X3NyYyA9PSBOVUxMIHx8IGRhdGFfc2l6ZSArIHZpZXdfb2ZmcyA8PSBnZ21sX25ieXRlcyh2aWV3X3NyYykAcGFyYW1zLT53c2l6ZSA+PSBzaXplb2YoZmxvYXQpICogKG50aCArIG50aCAqIG5jKQBnZ21sX25lbGVtZW50cyhhKSA9PSBnZ21sX25lbGVtZW50cyhiKQBnZ21sX2lzX3NjYWxhcihiKQBnZ21sX2Nhbl9tdWxfbWF0KGEsIGIpAGdnbWxfYXJlX3NhbWVfc2hhcGUoYSwgYikAZ2dtbF9pc19jb250aWd1b3VzKGEpACFnZ21sX2lzX3RyYW5zcG9zZWQoYSkAZ2dtbF9pc19wYWRkZWRfMWQoYSkAZ2dtbF9jYW5fcmVwZWF0X3Jvd3MobWFzaywgYSkAZ2dtbF9jYW5fcmVwZWF0KGIsIGEpAGdnbWxfaXNfY29udGlndW91cyhzcmMxKQBnZ21sX2lzX3NjYWxhcihzcmMxKQBnZ21sX2FyZV9zYW1lX3NoYXBlKHNyYzAsIGRzdCkgJiYgZ2dtbF9hcmVfc2FtZV9zaGFwZShzcmMwLCBzcmMxKQBnZ21sX2lzX2NvbnRpZ3VvdXMob3B0MCkAZ2dtbF9pc19jb250aWd1b3VzKGRzdCkgJiYgZ2dtbF9pc19jb250aWd1b3VzKHNyYzApAGdnbWxfbmVsZW1lbnRzKGRzdCkgPT0gZ2dtbF9uZWxlbWVudHMoc3JjMCkAb2Zmc2V0ICsgKG5lMTAgPT0gMCA/IDAgOiBuZTEwLTEpKm5iMDAgKyAobmUxMSA9PSAwID8gMCA6IG5lMTEtMSkqbmIwMSArIChuZTEyID09IDAgPyAwIDogbmUxMi0xKSpuYjAyICsgKG5lMTMgPT0gMCA/IDAgOiBuZTEzLTEpKm5iMDMgPCBnZ21sX25ieXRlcyhzcmMwKQBnZ21sX2lzX2NvbnRpZ3VvdXNfZXhjZXB0X2RpbV8xKHNyYzApAGdnbWxfY2FuX3JlcGVhdChkc3QsIHNyYzApACkpKQBvcGVyYXRvcigpACgoKABzcmMxLT50eXBlID09IEdHTUxfVFlQRV9GMzIgJiYgIm9ubHkgZjMyIHNyYzEgc3VwcG9ydGVkIGZvciBub3ciAHRlbnNvci0+YnVmZmVyICE9IE5VTEwgJiYgInRlbnNvciBidWZmZXIgbm90IHNldCIAYWxsb2MtPm5fZnJlZV9ibG9ja3MgPCBNQVhfRlJFRV9CTE9DS1MgJiYgIm91dCBvZiBmcmVlIGJsb2NrcyIAb2Zmc2V0ICsgc2l6ZSA8PSBnZ21sX25ieXRlcyh0ZW5zb3IpICYmICJ0ZW5zb3Igd3JpdGUgb3V0IG9mIGJvdW5kcyIAb2Zmc2V0ICsgc2l6ZSA8PSBnZ21sX25ieXRlcyh0ZW5zb3IpICYmICJ0ZW5zb3IgcmVhZCBvdXQgb2YgYm91bmRzIgBkYXRhICE9IE5VTEwgJiYgImZhaWxlZCB0byBhbGxvY2F0ZSBidWZmZXIiACEibm90IGVub3VnaCBzcGFjZSBpbiB0aGUgYnVmZmVyIgB0ZW5zb3ItPmRhdGEgIT0gTlVMTCAmJiAidGVuc29yIG5vdCBhbGxvY2F0ZWQiAGJhc2UgIT0gTlVMTCAmJiAiYmFja2VuZCBidWZmZXIgYmFzZSBjYW5ub3QgYmUgTlVMTCIAUHVyZSB2aXJ0dWFsIGZ1bmN0aW9uIGNhbGxlZCEAV0FSTklORzogQmVoYXZpb3IgbWF5IGJlIHVuZXhwZWN0ZWQgd2hlbiBhbGxvY2F0aW5nIDAgYnl0ZXMgZm9yIGdnbWxfYWxpZ25lZF9tYWxsb2MhACB8IABBVlggPSAAVlNYID0gAEJMQVMgPSAAT1BFTlZJTk8gPSAATkVPTiA9IABDT1JFTUwgPSAATUVUQUwgPSAAV0FTTV9TSU1EID0gAEYxNkMgPSAARlAxNl9WQSA9IABBUk1fRk1BID0gAENVREEgPSAAU1NTRTMgPSAAQVZYMiA9IABBVlg1MTIgPSAAJXM6IG9wIG5vdCBpbXBsZW1lbnRlZDogACVzOiB0ZW5zb3IgJyVzJyBoYXMgd3Jvbmcgc2l6ZSBpbiBtb2RlbCBmaWxlOiBnb3QgJXp1LCBleHBlY3RlZCAlenUKACVzOiB1c2luZyBkaXN0aWxsZWQgbW9kZWwgLSBmb3JjaW5nIG5vX3RpbWVzdGFtcHMKACVzOiBhZGRpbmcgJWQgZXh0cmEgdG9rZW5zCgAlczogICAgICBtZWwgdGltZSA9ICU4LjJmIG1zCgAlczogICAgdG90YWwgdGltZSA9ICU4LjJmIG1zCgAlczogICAgIGxvYWQgdGltZSA9ICU4LjJmIG1zCgBzeXN0ZW1faW5mbzogbl90aHJlYWRzID0gJWQgLyAlZCB8ICVzCgBXSElTUEVSX0FTU0VSVDogJXM6JWQ6ICVzCgBHR01MX0FTU0VSVDogJXM6JWQ6ICVzCgBbJXMgLS0+ICVzXSAgJXMKACVzOiBvZmZzZXQgJWRtcyBpcyBiZWZvcmUgdGhlIHN0YXJ0IG9mIHRoZSBhdWRpbwoAdW5rbm93biB0b2tlbgoAJXM6IGZhaWxlZCB0byBjb21wdXRlIGxvZyBtZWwgc3BlY3Ryb2dyYW0KACVzOiBsb2FkaW5nIG1vZGVsCgAlczogZmFpbGVkIHRvIGxvYWQgbW9kZWwKACVzOiBmYWlsZWQgdG8gZXZhbAoAJXM6ICAgICBmYWxsYmFja3MgPSAlM2QgcCAvICUzZCBoCgAlczogV0FSTiBubyB0ZW5zb3JzIGxvYWRlZCBmcm9tIG1vZGVsIGZpbGUgLSBhc3N1bWluZyBlbXB0eSBtb2RlbCBmb3IgdGVzdGluZwoAJXM6IGVuY29kZXJfYmVnaW5fY2FsbGJhY2sgcmV0dXJuZWQgZmFsc2UgLSBhYm9ydGluZwoAJXM6IHRlbnNvciAnJXMnIGhhcyB3cm9uZyBzaXplIGluIG1vZGVsIGZpbGUKACVzOiB1bmtub3duIHRlbnNvciAnJXMnIGluIG1vZGVsIGZpbGUKACVzOiBubyBzaWduYWwgZGF0YSBhdmFpbGFibGUKACVzOiBmYWlsZWQgdG8gYWxsb2NhdGUgbWVtb3J5IGZvciBrdiBjYWNoZQoAJXM6IGt2X2NhY2hlX2luaXQoKSBmYWlsZWQgZm9yIGNyb3NzLWF0dGVudGlvbiBjYWNoZQoAJXM6IGt2X2NhY2hlX2luaXQoKSBmYWlsZWQgZm9yIHNlbGYtYXR0ZW50aW9uIGNhY2hlCgAlczogZmFpbGVkIHRvIGF1dG8tZGV0ZWN0IGxhbmd1YWdlCgAlczogZmFpbGVkIHRvIGVuY29kZQoAJXM6IGZhaWxlZCB0byBkZWNvZGUKACVzOiBnZ21sX2luaXQoKSBmYWlsZWQKACVzOiBuX3Rva2Vucz0lZCA+IG5fY3R4PSVkCgAlczogRVJST1Igbm90IGFsbCB0ZW5zb3JzIGxvYWRlZCBmcm9tIG1vZGVsIGZpbGUgLSBleHBlY3RlZCAlenUsIGdvdCAlZAoAJXM6IHVua25vd24gbGFuZ3VhZ2UgaWQgJWQKACVzOiB0b28gbWFueSBkZWNvZGVycyByZXF1ZXN0ZWQgKCVkKSwgbWF4ID0gJWQKACVzOiBuX2F1ZGlvX2xheWVyID0gJWQKACVzOiBuX2F1ZGlvX3N0YXRlID0gJWQKACVzOiBuX3RleHRfbGF5ZXIgID0gJWQKACVzOiBuX3RleHRfc3RhdGUgID0gJWQKACVzOiBuX2F1ZGlvX2hlYWQgID0gJWQKACVzOiBuX2F1ZGlvX2N0eCAgID0gJWQKACVzOiBuX3RleHRfaGVhZCAgID0gJWQKACVzOiBuX3RleHRfY3R4ICAg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EBAQEBAAEBAQEBAAEAAQEBAQEBAAABAQEBAQAAAAEBAQEBAQEBAAEBAQEAAQEAAQEBAQEAAQABAQEBAAABAAEBAQEBAQAAAQEBAQABAAABAQEBAQAAAAEBAQEAAAAAAQEBAQEBAQEAAQEBAAEBAQABAQEBAAEBAAEBAQAAAQEAAQEBAQEAAQABAQEAAQABAAEBAQEAAAEAAQEBAAAAAQABAQEBAQEAAAEBAQABAQAAAQEBAQABAAABAQEAAAEAAAEBAQEBAAAAAQEBAAEAAAABAQEBAAAAAAEBAQAAAAAAAQEBAQEBAQEAAQEAAQEBAQABAQEAAQEBAAEBAAABAQEAAQEBAQABAQABAQABAAEBAAEBAQAAAQEAAQEAAAABAQABAQEBAQABAAEBAAEBAAEAAQEBAAEAAQABAQAAAQABAAEBAQEAAAEAAQEAAQAAAQABAQEAAAABAAEBAAAAAAEAAQEBAQEBAAABAQABAQEAAAEBAQABAQAAAQEAAAEBAAABAQEBAAEAAAEBAAEAAQAAAQEBAAABAAABAQAAAAEAAAEBAQEBAAAAAQEAAQEAAAABAQEAAQAAAAEBAAABAAAAAQEBAQAAAAABAQABAAAAAAEBAQAAAAAAAQEAAAAAAAABAQEBAQEBAQABAAEBAQEBAAEBAAEBAQEAAQAAAQEBAQABAQEAAQEBAAEAAQABAQEAAQEAAAEBAQABAAAAAQEBAAEBAQEAAQEAAQABAQABAQABAQABAAEBAAEAAAEAAQEAAQEBAAABAQABAAEAAAEBAAEBAAAAAQEAAQAAAAABAQABAQEBAQABAAEAAQEBAAEAAQEAAQEAAQABAAABAQABAAEBAQABAAEAAQABAAEAAQABAQAAAQABAAEAAAABAAEAAQEBAQAAAQABAAEBAAABAAEBAAEAAAEAAQAAAQAAAQABAQEAAAABAAEAAQAAAAEAAQEAAAAAAQABAAAAAAABAAEBAQEBAQAAAQABAQEBAAABAQABAQEAAAEAAAEBAQAAAQEBAAEBAAABAAEAAQEAAAEBAAABAQAAAQAAAAEBAAABAQEBAAEAAAEAAQEAAQAAAQEAAQABAAABAAABAAEAAAEBAQAAAQAAAQABAAABAAABAQAAAAEAAAEAAAAAAQAAAQEBAQEAAAABAAEBAQAAAAEBAAEBAAAAAQAAAQEAAAABAQEAAQAAAAEAAQABAAAAAQEAAAEAAAABAAAAAQAAAAEBAQEAAAAAAQABAQAAAAABAQABAAAAAAEAAAEAAAAAAQEBAAAAAAABAAEAAAAAAAEBAAAAAAAAAQAAAAAAAAABAQEBAQEBAQAAAQEBAQEBAAEAAQEBAQEAAAABAQEBAQABAQABAQEBAAABAAEBAQEAAQAAAQEBAQAAAAABAQEBAAEBAQABAQEAAAEBAAEBAQABAAEAAQEBAAAAAQABAQEAAQEAAAEBAQAAAQAAAQEBAAEAAAABAQEAAAAAAAEBAQABAQEBAAEBAAABAQEAAQEAAQABAQABAQAAAAEBAAEBAAEBAAEAAQEAAAEAAQABAQABAAABAAEBAAAAAAEAAQEAAQEBAAABAQAAAQEAAAEBAAEAAQAAAQEAAAABAAABAQABAQAAAAEBAAABAAAAAQEAAQAAAAABAQAAAAAAAAEBAAEBAQEBAAEAAAEBAQEAAQABAAEBAQABAAAAAQEBAAEAAQEAAQEAAQAAAQABAQABAAEAAAEBAAEAAAAAAQEAAQABAQEAAQABAAABAQABAAEAAQABAAEAAQAAAAEAAQABAAEBAAABAAEAAAEAAAEAAQABAAAAAQABAAAAAAABAAEAAQEBAQAAAQAAAQEBAAABAAEAAQEAAAEAAAABAQAAAQABAQABAAABAAABAAEAAAEAAQAAAQAAAQAAAAABAAABAAEBAQAAAAEAAAEBAAAAAQABAAEAAAABAAAAAQAAAAEAAQEAAAAAAQAAAQAAAAABAAEAAAAAAAEAAAAAAAAAAQABAQEBAQEAAAABAQEBAQAAAQABAQEBAAAAAAEBAQEAAAEBAAEBAQAAAAEAAQEBAAABAAABAQEAAAAAAAEBAQAAAQEBAAEBAAAAAQEAAQEAAAEAAQABAQAAAAABAAEBAAABAQAAAQEAAAABAAABAQAAAQAAAAEBAAAAAAAAAQEAAAEBAQEAAQAAAAEBAQABAAABAAEBAAEAAAAAAQEAAQAAAQEAAQABAAAAAQABAAEAAAEAAAEAAQAAAAAAAQABAAABAQEAAAEAAAABAQAAAQAAAQABAAABAAAAAAEAAAEAAAEBAAAAAQAAAAEAAAABAAABAAAAAAEAAAAAAAAAAQAAAQEBAQEAAAAAAQEBAQAAAAEAAQEBAAAAAAABAQEAAAABAQABAQAAAAABAAEBAAAAAQAAAQEAAAAAAAABAQAAAAEBAQABAAAAAAEBAAEAAAABAAEAAQAAAAAAAQABAAAAAQEAAAEAAAAAAQAAAQAAAAEAAAABAAAAAAAAAAEAAAABAQEBAAAAAAABAQEAAAAAAQABAQAAAAAAAAEBAAAAAAEBAAEAAAAAAAEAAQAAAAABAAABAAAAAAAAAAEAAAAAAQEBAAAAAAAAAQEAAAAAAAEAAQAAAAAAAAABAAAAAAABAQAAAAAAAAABAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAQAAAAAAAAEBAAAAAAAAAAABAAAAAAABAAEAAAAAAAABAQAAAAAAAQEBAAAAAAAAAAABAAAAAAEAAAEAAAAAAAEAAQAAAAABAQABAAAAAAAAAQEAAAAAAQABAQAAAAAAAQEBAAAAAAEBAQEAAAAAAAAAAAEAAAABAAAAAQAAAAABAAABAAAAAQEAAAEAAAAAAAEAAQAAAAEAAQABAAAAAAEBAAEAAAABAQEAAQAAAAAAAAEBAAAAAQAAAQEAAAAAAQABAQAAAAEBAAEBAAAAAAABAQEAAAABAAEBAQAAAAABAQEBAAAAAQEBAQEAAAAAAAAAAAEAAAEAAAAAAQAAAAEAAAABAAABAQAAAAEAAAAAAQAAAQAAAQABAAABAAAAAQEAAAEAAAEBAQAAAQAAAAAAAQABAAABAAABAAEAAAABAAEAAQAAAQEAAQABAAAAAAEBAAEAAAEAAQEAAQAAAAEBAQABAAABAQEBAAEAAAAAAAABAQAAAQAAAAEBAAAAAQAAAQEAAAEBAAABAQAAAAABAAEBAAABAAEAAQEAAAABAQABAQAAAQEBAAEBAAAAAAABAQEAAAEAAAEBAQAAAAEAAQEBAAABAQABAQEAAAAAAQEBAQAAAQABAQEBAAAAAQEBAQEAAAEBAQEBAQAAAAAAAAAAAQABAAAAAAABAAABAAAAAAEAAQEAAAAAAQAAAAEAAAABAAEAAQAAAAEAAAEBAAAAAQABAQEAAAABAAAAAAEAAAEAAQAAAQAAAQAAAQABAAABAAEBAAEAAAEAAAABAQAAAQABAAEBAAABAAABAQEAAAEAAQEBAQAAAQAAAAAAAQABAAEAAAABAAEAAAEAAAEAAQABAQAAAQABAAAAAQABAAEAAQABAAEAAQAAAQEAAQABAAEBAQABAAEAAAAAAQEAAQABAAABAQABAAABAAEBAAEAAQEAAQEAAQAAAAEBAQABAAEAAQEBAAEAAAEBAQEAAQABAQEBAQABAAAAAAAAAQEAAQAAAAABAQAAAQAAAAEBAAEBAAAAAQEAAAABAAABAQABAAEAAAEBAAABAQAAAQEAAQEBAAABAQAAAAABAAEBAAEAAAEAAQEAAAEAAQABAQABAQABAAEBAAAAAQEAAQEAAQABAQABAQAAAQEBAAEBAAEBAQEAAQEAAAAAAAEBAQABAAAAAQEBAAABAAABAQEAAQEAAAEBAQAAAAEAAQEBAAEAAQABAQEAAAEBAAEBAQABAQEAAQEBAAAAAAEBAQEAAQAAAQEBAQAAAQABAQEBAAEBAAEBAQEAAAABAQEBAQABAAEBAQEBAAABAQEBAQEAAQEBAQEBAQAAAAAAAAAAAQEAAAAAAAABAAEAAAAAAAEBAQAAAAAAAQAAAQAAAAABAQABAAAAAAEAAQEAAAAAAQEBAQAAAAABAAAAAQAAAAEBAAABAAAAAQABAAEAAAABAQEAAQAAAAEAAAEBAAAAAQEAAQEAAAABAAEBAQAAAAEBAQEBAAAAAQAAAAABAAABAQAAAAEAAAEAAQAAAQAAAQEBAAABAAABAAABAAEAAAEBAAEAAQAAAQABAQABAAABAQEBAAEAAAEAAAABAQAAAQEAAAEBAAABAAEAAQEAAAEBAQABAQAAAQAAAQEBAAABAQABAQEAAAEAAQEBAQAAAQEBAQEBAAABAAAAAAABAAEBAAAAAAEAAQABAAAAAQABAQEAAAABAAEAAAEAAAEAAQEAAQAAAQABAAEBAAABAAEBAQEAAAEAAQAAAAEAAQABAQAAAQABAAEAAQABAAEAAQEBAAEAAQABAAABAQABAAEBAAEBAAEAAQABAQEAAQABAQEBAQABAAEAAAAAAQEAAQEAAAABAQABAAEAAAEBAAEBAQAAAQEAAQAAAQABAQABAQABAAEBAAEAAQEAAQEAAQEBAQABAQABAAAAAQEBAAEBAAABAQEAAQABAAEBAQABAQEAAQEBAAEAAAEBAQEAAQEAAQEBAQABAAEBAQEBAAEBAQEBAQEAAQAAAAAAAAEBAQAAAAAAAQEAAQAAAAABAQEBAAAAAAEBAAABAAAAAQEBAAEAAA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AAAAXwAAAGAAAABhAAAATlN0M19fMjIwX19zaGFyZWRfcHRyX3BvaW50ZXJJUE5TXzEzX19lbXB0eV9zdGF0ZUljRUVOU18xMHNoYXJlZF9wdHJJUzJfRTI3X19zaGFyZWRfcHRyX2RlZmF1bHRfZGVsZXRlSVMyX1MyX0VFTlNfOWFsbG9jYXRvcklTMl9FRUVFAAAAAAjaAABYUwAAiNAAAE5TdDNfXzIxMHNoYXJlZF9wdHJJTlNfMTNfX2VtcHR5X3N0YXRlSWNFRUUyN19fc2hhcmVkX3B0cl9kZWZhdWx0X2RlbGV0ZUlTMl9TMl9FRQAAAAAAAADIVAAAYgAAAGMAAABkAAAAXAAAAE5TdDNfXzIxM19fZW1wdHlfc3RhdGVJY0VFAE5TdDNfXzIxNl9fb3duc19vbmVfc3RhdGVJY0VFAE5TdDNfXzIxNV9faGFzX29uZV9zdGF0ZUljRUUAAAAI2gAAkVQAAChTAAAI2gAAc1QAALBUAAAI2gAAWFQAALxUAAAAAAAAvFQAAGIAAABlAAAAZgAAAFwAAAAAAAAAKFUAAGIAAABnAAAAaAAAAFwAAABOU3QzX18yMjBfX2xfYW5jaG9yX211bHRpbGluZUljRUUAAAAI2gAABFUAALxUAAAAAAAAcFUAAGIAAABpAAAAagAAAFwAAABOU3QzX18yMjBfX3JfYW5jaG9yX211bHRpbGluZUljRUUAAAAI2gAATFUAALxUAAAAAAAAyFUAAGsAAABsAAAAbQAAAFwAAABOU3QzX18yMTVfX3dvcmRfYm91bmRhcnlJY05TXzEycmVnZXhfdHJhaXRzSWNFRUVFAAAACNoAAJRVAAC8VAAAAAAAABxWAABuAAAAbwAAAHAAAABcAAAATlN0M19fMjExX19sb29rYWhlYWRJY05TXzEycmVnZXhfdHJhaXRzSWNFRUVFAAAACNoAAOxVAAC8VAAAAAAAAGhWAABiAAAAcQAAAHIAAABcAAAATlN0M19fMjIzX19tYXRjaF9hbnlfYnV0X25ld2xpbmVJY0VFAAAAAAjaAABAVgAAvFQAAAAAAADEVgAAcwAAAHQAAAB1AAAAXAAAAE5TdDNfXzIxOF9fbWF0Y2hfY2hhcl9pY2FzZUljTlNfMTJyZWdleF90cmFpdHNJY0VFRUUAAAAACNoAAIxWAAC8VAAAAAAAACBXAAB2AAAAdwAAAHgAAABcAAAATlN0M19fMjIwX19tYXRjaF9jaGFyX2NvbGxhdGVJY05TXzEycmVnZXhfdHJhaXRzSWNFRUVFAAAI2gAA6FYAALxUAAAAAAAAYFcAAGIAAAB5AAAAegAAAFwAAABOU3QzX18yMTJfX21hdGNoX2NoYXJJY0VFAAAACNoAAERXAAC8VAAAAAAAALhXAAB7AAAAfAAAAH0AAABcAAAATlN0M19fMjE2X19iYWNrX3JlZl9pY2FzZUljTlNfMTJyZWdleF90cmFpdHNJY0VFRUUAAAjaAACEVwAAvFQAAAAAAAAUWAAAfgAAAH8AAACAAAAAXAAAAE5TdDNfXzIxOF9fYmFja19yZWZfY29sbGF0ZUljTlNfMTJyZWdleF90cmFpdHNJY0VFRUUAAAAACNoAANxXAAC8VAAAAAAAAFBYAABiAAAAgQAAAIIAAABcAAAATlN0M19fMjEwX19iYWNrX3JlZkljRUUACNoAADhYAAC8VAAAAAAAAKxYAACDAAAAhAAAAIUAAABcAAAATlN0M19fMjIwX19icmFja2V0X2V4cHJlc3Npb25JY05TXzEycmVnZXhfdHJhaXRzSWNFRUVFAAAI2gAAdFgAALxUAAAAAAAA/FgAAGIAAACGAAAAhwAAAFwAAABOU3QzX18yMjhfX2JlZ2luX21hcmtlZF9zdWJleHByZXNzaW9uSWNFRQAAAAjaAADQWAAAvFQAAAAAAABIWQAAYgAAAIgAAACJAAAAXAAAAE5TdDNfXzIyNl9fZW5kX21hcmtlZF9zdWJleHByZXNzaW9uSWNFRQAI2gAAIFkAALxUAAAAAAAArFkAAIoAAACLAAAAjAAAAI0AAABOU3QzX18yNl9fbG9vcEljRUUATlN0M19fMjE3X19vd25zX3R3b19zdGF0ZXNJY0VFAAAACNoAAH9ZAAC8VAAACNoAAGxZAACgWQAAAAAAAKBZAACKAAAAjgAAAGYAAABcAAAAAAAAAAhaAABZAAAAjwAAAJAAAABcAAAATlN0M19fMjE3X19yZXBlYXRfb25lX2xvb3BJY0VFAAAI2gAA6FkAALBUAAAAAAAASFoAAIoAAACRAAAAkgAAAJMAAABOU3QzX18yMTFfX2FsdGVybmF0ZUljRUUAAAAACNoAACxaAACgWQAAAAAAAJBaAABZAAAAlAAAAJUAAABcAAAATlN0M19fMjIxX19lbXB0eV9ub25fb3duX3N0YXRlSWNFRQAACNoAAGxaAACwVAAAAAAAANBaAABiAAAAlgAAAJcAAABcAAAATlN0M19fMjExX19tYXRjaF9hbnlJY0VFAAAAAAjaAAC0WgAAvFQAAAAAAACcWwAAmAAAAJkAAACaAAAAmwAAAJwAAACdAAAAngAAAJ8AAACgAAAATlN0M19fMjEwX19mdW5jdGlvbjZfX2Z1bmNJWjE4d2hpc3Blcl9pbml0X3N0YXRlRTMkXzBOU185YWxsb2NhdG9ySVMyX0VFRlAxMWdnbWxfY2dyYXBodkVFRQBOU3QzX18yMTBfX2Z1bmN0aW9uNl9fYmFzZUlGUDExZ2dtbF9jZ3JhcGh2RUVFAADg2QAAZFsAAAjaAAAIWwAAlFsAAFoxOHdoaXNwZXJfaW5pdF9zdGF0ZUUzJF8wAADg2QAAqFsAAAAAAABUXAAAmAAAAKEAAACiAAAAowAAAKQAAAClAAAApgAAAKcAAACoAAAATlN0M19fMjEwX19mdW5jdGlvbjZfX2Z1bmNJWjE4d2hpc3Blcl9pbml0X3N0YXRlRTMkXzFOU185YWxsb2NhdG9ySVMyX0VFRlAxMWdnbWxfY2dyYXBodkVFRQAI2gAA+FsAAJRbAABaMTh3aGlzcGVyX2luaXRfc3RhdGVFMyRfMQAA4NkAAGBcAAAAAAAADF0AAJgAAACpAAAAqgAAAKsAAACsAAAArQAAAK4AAACvAAAAsAAAAE5TdDNfXzIxMF9fZnVuY3Rpb242X19mdW5jSVoxOHdoaXNwZXJfaW5pdF9zdGF0ZUUzJF8yTlNfOWFsbG9jYXRvcklTMl9FRUZQMTFnZ21sX2NncmFwaHZFRUUACNoAALBcAACUWwAAWjE4d2hpc3Blcl9pbml0X3N0YXRlRTMkXzIAAODZAAAYXQAAAAAAAMRdAACYAAAAsQAAALIAAACzAAAAtAAAALUAAAC2AAAAtwAAALgAAABOU3QzX18yMTBfX2Z1bmN0aW9uNl9fZnVuY0laMTh3aGlzcGVyX2luaXRfc3RhdGVFMyRfM05TXzlhbGxvY2F0b3JJUzJfRUVGUDExZ2dtbF9jZ3JhcGh2RUVFAAjaAABoXQAAlFsAAFoxOHdoaXNwZXJfaW5pdF9zdGF0ZUUzJF8zAADg2QAA0F0AAE5TdDNfXzIxMmJhc2ljX3N0cmluZ0loTlNfMTFjaGFyX3RyYWl0c0loRUVOU185YWxsb2NhdG9ySWhFRUVFAADg2QAA9F0AAE5TdDNfXzIxMmJhc2ljX3N0cmluZ0l3TlNfMTFjaGFyX3RyYWl0c0l3RUVOU185YWxsb2NhdG9ySXdFRUVFAADg2QAAPF4AAE5TdDNfXzIxMmJhc2ljX3N0cmluZ0lEc05TXzExY2hhcl90cmFpdHNJRHNFRU5TXzlhbGxvY2F0b3JJRHNFRUVFAAAA4NkAAIReAABOU3QzX18yMTJiYXNpY19zdHJpbmdJRGlOU18xMWNoYXJfdHJhaXRzSURpRUVOU185YWxsb2NhdG9ySURpRUVFRQAAAODZAADQXgAATjEwZW1zY3JpcHRlbjExbWVtb3J5X3ZpZXdJY0VFAADg2QAAHF8AAE4xMGVtc2NyaXB0ZW4xMW1lbW9yeV92aWV3SWFFRQAA4NkAAERfAABOMTBlbXNjcmlwdGVuMTFtZW1vcnlfdmlld0loRUUAAODZAABsXwAATjEwZW1zY3JpcHRlbjExbWVtb3J5X3ZpZXdJc0VFAADg2QAAlF8AAE4xMGVtc2NyaXB0ZW4xMW1lbW9yeV92aWV3SXRFRQAA4NkAALxfAABOMTBlbXNjcmlwdGVuMTFtZW1vcnlfdmlld0lpRUUAAODZAADkXwAATjEwZW1zY3JpcHRlbjExbWVtb3J5X3ZpZXdJakVFAADg2QAADGAAAE4xMGVtc2NyaXB0ZW4xMW1lbW9yeV92aWV3SWxFRQAA4NkAADRgAABOMTBlbXNjcmlwdGVuMTFtZW1vcnlfdmlld0ltRUUAAODZAABcYAAATjEwZW1zY3JpcHRlbjExbWVtb3J5X3ZpZXdJeEVFAADg2QAAhGAAAE4xMGVtc2NyaXB0ZW4xMW1lbW9yeV92aWV3SXlFRQAA4NkAAKxgAABOMTBlbXNjcmlwdGVuMTFtZW1vcnlfdmlld0lmRUUAAODZAADUYAAATjEwZW1zY3JpcHRlbjExbWVtb3J5X3ZpZXdJZEVFAADg2QAA/GAAAAAAAAAAAAAAAAAAAAMAAAAEAAAABAAAAAYAAACD+aIARE5uAPwpFQDRVycA3TT1AGLbwAA8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SWNFRUVFAAAAAODZAADEpAAATlN0M19fMjEzYmFzaWNfaXN0cmVhbUljTlNfMTFjaGFyX3RyYWl0c0ljRUVFRQAAZNoAAAClAAAAAAAAAQAAALikAAAD9P//bAAAAAAAAADYpQAA7wAAAPAAAACU////lP///9ilAADxAAAA8gAAAFSlAACMpQAAoKUAAGilAABsAAAAAAAAADClAADhAAAA4gAAAJT///+U////MKUAAOMAAADkAAAATlN0M19fMjE0YmFzaWNfaWZzdHJlYW1JY05TXzExY2hhcl90cmFpdHNJY0VFRUUACNoAAKilAAAwpQAATlN0M19fMjEzYmFzaWNfZmlsZWJ1ZkljTlNfMTFjaGFyX3RyYWl0c0ljRUVFRQAACNoAAOSlAAD4pAAAAAAAAESmAADzAAAA9AAAAE5TdDNfXzI4aW9zX2Jhc2VFAAAA4NkAADCmAAAAAAAA0XSeAFedvSqAcFIP//8+JwoAAABkAAAA6AMAABAnAACghgEAQEIPAICWmAAA4fUFGAAAADUAAABxAAAAa////877//+Sv///AAAAAAAAAAD/////////////////////////////////////////////////////////////////AAECAwQFBgcICf////////8KCwwNDg8QERITFBUWFxgZGhscHR4fICEiI////////woLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIj/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wABAgQHAwYFAAAAAAAAAAIAAMADAADABAAAwAUAAMAGAADABwAAwAgAAMAJAADACgAAwAsAAMAMAADADQAAwA4AAMAPAADAEAAAwBEAAMASAADAEwAAwBQAAMAVAADAFgAAwBcAAMAYAADAGQAAwBoAAMAbAADAHAAAwB0AAMAeAADAHwAAwAAAALMBAADDAgAAwwMAAMMEAADDBQAAwwYAAMMHAADDCAAAwwkAAMMKAADDCwAAwwwAAMMNAADTDgAAww8AAMMAAAy7AQAMwwIA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ODY4Nzg4ODk5MDkxOTI5Mzk0OTU5Njk3OTg5OQAAAAAAAAAAAv8ABGQAIAAABP//BgABAAEAAQD//wH/Af//////Af8B/wH/Af8B/wH/Af8B//////8K/yAA//8D/wH/BP8eAAABBf//////YwAACGMA6AMCAAAA//////8AAAAB/wH//////////////wAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAB/wH//////wABIAAEAIAAAAj//wH/Af////////8B/wb/B/8I/wn//////7wCvAIBAP//AQABAP//AAD//////////wAAAAAAAAAAAAAAAAAAAAAUAXj//wEACv///////////wH/Af8AAAAAAAAB/wH/Af8AAAAAAAAAAAAAAAAAAAAAAAAB/wAAAAAAAAH/Af8BAAAAAQAAAAH//////wAAAAAB////AAAAAP////////////8oAAr//////wEACv////8A//////////8BvggB/wH///8BAP//////////////////Cv//////DP8N/04xMF9fY3h4YWJpdjExNl9fc2hpbV90eXBlX2luZm9FAAAI2gAAFtgAACzcAABOMTBfX2N4eGFiaXYxMTdfX2NsYXNzX3R5cGVfaW5mb0UAAAAI2gAARNgAADjYAABOMTBfX2N4eGFiaXYxMTdfX3BiYXNlX3R5cGVfaW5mb0UAAAAI2gAAdNgAADjYAABOMTBfX2N4eGFiaXYxMTlfX3BvaW50ZXJfdHlwZV9pbmZvRQAI2gAApNgAAJjYAAAAAAAAGNkAAP8BAAAAAgAAAQIAAAICAAADAgAATjEwX19jeHhhYml2MTIzX19mdW5kYW1lbnRhbF90eXBlX2luZm9FAAjaAADw2AAAONgAAHYAAADc2AAAJNkAAGIAAADc2AAAMNkAAGMAAADc2AAAPNkAAGgAAADc2AAASNkAAGEAAADc2AAAVNkAAHMAAADc2AAAYNkAAHQAAADc2AAAbNkAAGkAAADc2AAAeNkAAGoAAADc2AAAhNkAAGwAAADc2AAAkNkAAG0AAADc2AAAnNkAAHgAAADc2AAAqNkAAHkAAADc2AAAtNkAAGYAAADc2AAAwNkAAGQAAADc2AAAzNkAAAAAAABo2AAA/wEAAAQCAAABAgAAAgIAAAUCAAAGAgAABwIAAAgCAAAAAAAAUNoAAP8BAAAJAgAAAQIAAAICAAAFAgAACgIAAAsCAAAMAgAATjEwX19jeHhhYml2MTIwX19zaV9jbGFzc190eXBlX2luZm9FAAAAAAjaAAAo2gAAaNgAAAAAAACs2gAA/wEAAA0CAAABAgAAAgIAAAUCAAAOAgAADwIAABACAABOMTBfX2N4eGFiaXYxMjFfX3ZtaV9jbGFzc190eXBlX2luZm9FAAAACNoAAITaAABo2AAAAAAAABzbAAAIAAAAEQIAABICAAAAAAAARNsAAAgAAAATAgAAFAIAAAAAAAAE2wAACAAAABUCAAAWAgAAU3Q5ZXhjZXB0aW9uAAAAAODZAAD02gAAU3Q5YmFkX2FsbG9jAAAAAAjaAAAM2wAABNsAAFN0MjBiYWRfYXJyYXlfbmV3X2xlbmd0aAAAAAAI2gAAKNsAABzbAAAAAAAAiNsAAAcAAAAXAgAAGAIAAAAAAAAQ3AAAGQIAABoCAAD8AQAAU3QxMWxvZ2ljX2Vycm9yAAjaAAB42wAABNsAAAAAAAC82wAABwAAABsCAAAYAgAAU3QxMmxlbmd0aF9lcnJvcgAAAAAI2gAAqNsAAIjbAAAAAAAA8NsAAAcAAAAcAgAAGAIAAFN0MTJvdXRfb2ZfcmFuZ2UAAAAACNoAANzbAACI2wAAU3QxM3J1bnRpbWVfZXJyb3IAAAAI2gAA/NsAAATbAABTdDl0eXBlX2luZm8AAAAA4NkAABzcAAABFT0AAAA+AAAAAAAAAD8AAAAAAAAAWAFoUNwAAFDcAAAAAAEAAAIAAAAAAAAFAAAAAAAAAAAAAAC9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7AAAAugAAAOA9DQAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAA//////////8BWZjcAAAAAAAABQAAAAAAAAAAAAAAywAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuwAAAMwAAADoPQ0AAAQAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAP////8KAQww3QAAwEwOAP4BAAA=";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile)}function getBinarySync(file){if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}var binary=tryParseAsDataURI(file);if(binary){return binary}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}function getBinaryPromise(binaryFile){return Promise.resolve().then(()=>getBinarySync(binaryFile))}function instantiateArrayBuffer(binaryFile,imports,receiver){return getBinaryPromise(binaryFile).then(binary=>WebAssembly.instantiate(binary,imports)).then(instance=>instance).then(receiver,reason=>{err(`failed to asynchronously prepare wasm: ${reason}`);abort(reason)})}function instantiateAsync(binary,binaryFile,imports,callback){return instantiateArrayBuffer(binaryFile,imports,callback)}function createWasm(){var info={"a":wasmImports};function receiveInstance(instance,module){var exports=instance.exports;wasmExports=exports;registerTLSInit(wasmExports["_"]);wasmTable=wasmExports["X"];addOnInit(wasmExports["W"]);wasmModule=module;removeRunDependency("wasm-instantiate");return exports}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)}}instantiateAsync(wasmBinary,wasmBinaryFile,info,receiveInstantiationResult).catch(readyPromiseReject);return{}}var tempDouble;var tempI64;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];assert(worker);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};if(ENVIRONMENT_IS_NODE){worker.unref()}worker.postMessage(msg,threadParams.transferList);return 0};var PATH={isAbs:path=>path.charAt(0)==="/",splitPath:filename=>{var splitPathRe=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;return splitPathRe.exec(filename).slice(1)},normalizeArray:(parts,allowAboveRoot)=>{var up=0;for(var i=parts.length-1;i>=0;i--){var last=parts[i];if(last==="."){parts.splice(i,1)}else if(last===".."){parts.splice(i,1);up++}else if(up){parts.splice(i,1);up--}}if(allowAboveRoot){for(;up;up--){parts.unshift("..")}}return parts},normalize:path=>{var isAbsolute=PATH.isAbs(path),trailingSlash=path.substr(-1)==="/";path=PATH.normalizeArray(path.split("/").filter(p=>!!p),!isAbsolute).join("/");if(!path&&!isAbsolute){path="."}if(path&&trailingSlash){path+="/"}return(isAbsolute?"/":"")+path},dirname:path=>{var result=PATH.splitPath(path),root=result[0],dir=result[1];if(!root&&!dir){return"."}if(dir){dir=dir.substr(0,dir.length-1)}return root+dir},basename:path=>{if(path==="/")return"/";path=PATH.normalize(path);path=path.replace(/\/$/,"");var lastSlash=path.lastIndexOf("/");if(lastSlash===-1)return path;return path.substr(lastSlash+1)},join:function(){var paths=Array.prototype.slice.call(arguments);return PATH.normalize(paths.join("/"))},join2:(l,r)=>PATH.normalize(l+"/"+r)};var initRandomFill=()=>{if(typeof crypto=="object"&&typeof crypto["getRandomValues"]=="function"){return view=>(view.set(crypto.getRandomValues(new Uint8Array(view.byteLength))),view)}else if(ENVIRONMENT_IS_NODE){try{var crypto_module=require("crypto");var randomFillSync=crypto_module["randomFillSync"];if(randomFillSync){return view=>crypto_module["randomFillSync"](view)}var randomBytes=crypto_module["randomBytes"];return view=>(view.set(randomBytes(view.byteLength)),view)}catch(e){}}abort("initRandomDevice")};var randomFill=view=>(randomFill=initRandomFill())(view);var PATH_FS={resolve:function(){var resolvedPath="",resolvedAbsolute=false;for(var i=arguments.length-1;i>=-1&&!resolvedAbsolute;i--){var path=i>=0?arguments[i]:FS.cwd();if(typeof path!="string"){throw new TypeError("Arguments to path.resolve must be strings")}else if(!path){return""}resolvedPath=path+"/"+resolvedPath;resolvedAbsolute=PATH.isAbs(path)}resolvedPath=PATH.normalizeArray(resolvedPath.split("/").filter(p=>!!p),!resolvedAbsolute).join("/");return(resolvedAbsolute?"/":"")+resolvedPath||"."},relative:(from,to)=>{from=PATH_FS.resolve(from).substr(1);to=PATH_FS.resolve(to).substr(1);function trim(arr){var start=0;for(;start<arr.length;start++){if(arr[start]!=="")break}var end=arr.length-1;for(;end>=0;end--){if(arr[end]!=="")break}if(start>end)return[];return arr.slice(start,end-start+1)}var fromParts=trim(from.split("/"));var toParts=trim(to.split("/"));var length=Math.min(fromParts.length,toParts.length);var samePartsLength=length;for(var i=0;i<length;i++){if(fromParts[i]!==toParts[i]){samePartsLength=i;break}}var outputParts=[];for(var i=samePartsLength;i<fromParts.length;i++){outputParts.push("..")}outputParts=outputParts.concat(toParts.slice(samePartsLength));return outputParts.join("/")}};var UTF8Decoder=typeof TextDecoder!="undefined"?new TextDecoder("utf8"):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.buffer instanceof SharedArrayBuffer?heapOrArray.slice(idx,endPtr):heapOrArray.subarray(idx,endPtr))}var str="";while(idx<endPtr){var u0=heapOrArray[idx++];if(!(u0&128)){str+=String.fromCharCode(u0);continue}var u1=heapOrArray[idx++]&63;if((u0&224)==192){str+=String.fromCharCode((u0&31)<<6|u1);continue}var u2=heapOrArray[idx++]&63;if((u0&240)==224){u0=(u0&15)<<12|u1<<6|u2}else{u0=(u0&7)<<18|u1<<12|u2<<6|heapOrArray[idx++]&63}if(u0<65536){str+=String.fromCharCode(u0)}else{var ch=u0-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}}return str};var FS_stdin_getChar_buffer=[];var lengthBytesUTF8=str=>{var len=0;for(var i=0;i<str.length;++i){var c=str.charCodeAt(i);if(c<=127){len++}else if(c<=2047){len+=2}else if(c>=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<str.length;++i){var u=str.charCodeAt(i);if(u>=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};function intArrayFromString(stringy,dontAddNull,length){var len=length>0?length:lengthBytesUTF8(stringy)+1;var u8array=new Array(len);var numBytesWritten=stringToUTF8Array(stringy,u8array,0,u8array.length);if(dontAddNull)u8array.length=numBytesWritten;return u8array}var FS_stdin_getChar=()=>{if(!FS_stdin_getChar_buffer.length){var result=null;if(ENVIRONMENT_IS_NODE){var BUFSIZE=256;var buf=Buffer.alloc(BUFSIZE);var bytesRead=0;var fd=process.stdin.fd;try{bytesRead=fs.readSync(fd,buf)}catch(e){if(e.toString().includes("EOF"))bytesRead=0;else throw e}if(bytesRead>0){result=buf.slice(0,bytesRead).toString("utf-8")}else{result=null}}else if(typeof window!="undefined"&&typeof window.prompt=="function"){result=window.prompt("Input: ");if(result!==null){result+="\n"}}else if(typeof readline=="function"){result=readline();if(result!==null){result+="\n"}}if(!result){return null}FS_stdin_getChar_buffer=intArrayFromString(result,true)}return FS_stdin_getChar_buffer.shift()};var TTY={ttys:[],init(){},shutdown(){},register(dev,ops){TTY.ttys[dev]={input:[],output:[],ops:ops};FS.registerDevice(dev,TTY.stream_ops)},stream_ops:{open(stream){var tty=TTY.ttys[stream.node.rdev];if(!tty){throw new FS.ErrnoError(43)}stream.tty=tty;stream.seekable=false},close(stream){stream.tty.ops.fsync(stream.tty)},fsync(stream){stream.tty.ops.fsync(stream.tty)},read(stream,buffer,offset,length,pos){if(!stream.tty||!stream.tty.ops.get_char){throw new FS.ErrnoError(60)}var bytesRead=0;for(var i=0;i<length;i++){var result;try{result=stream.tty.ops.get_char(stream.tty)}catch(e){throw new FS.ErrnoError(29)}if(result===undefined&&bytesRead===0){throw new FS.ErrnoError(6)}if(result===null||result===undefined)break;bytesRead++;buffer[offset+i]=result}if(bytesRead){stream.node.timestamp=Date.now()}return bytesRead},write(stream,buffer,offset,length,pos){if(!stream.tty||!stream.tty.ops.put_char){throw new FS.ErrnoError(60)}try{for(var i=0;i<length;i++){stream.tty.ops.put_char(stream.tty,buffer[offset+i])}}catch(e){throw new FS.ErrnoError(29)}if(length){stream.node.timestamp=Date.now()}return i}},default_tty_ops:{get_char(tty){return FS_stdin_getChar()},put_char(tty,val){if(val===null||val===10){out(UTF8ArrayToString(tty.output,0));tty.output=[]}else{if(val!=0)tty.output.push(val)}},fsync(tty){if(tty.output&&tty.output.length>0){out(UTF8ArrayToString(tty.output,0));tty.output=[]}},ioctl_tcgets(tty){return{c_iflag:25856,c_oflag:5,c_cflag:191,c_lflag:35387,c_cc:[3,28,127,21,4,0,1,0,17,19,26,0,18,15,23,22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}},ioctl_tcsets(tty,optional_actions,data){return 0},ioctl_tiocgwinsz(tty){return[24,80]}},default_tty1_ops:{put_char(tty,val){if(val===null||val===10){err(UTF8ArrayToString(tty.output,0));tty.output=[]}else{if(val!=0)tty.output.push(val)}},fsync(tty){if(tty.output&&tty.output.length>0){err(UTF8ArrayToString(tty.output,0));tty.output=[]}}}};var mmapAlloc=size=>{abort()};var MEMFS={ops_table:null,mount(mount){return MEMFS.createNode(null,"/",16384|511,0)},createNode(parent,name,mode,dev){if(FS.isBlkdev(mode)||FS.isFIFO(mode)){throw new FS.ErrnoError(63)}if(!MEMFS.ops_table){MEMFS.ops_table={dir:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,lookup:MEMFS.node_ops.lookup,mknod:MEMFS.node_ops.mknod,rename:MEMFS.node_ops.rename,unlink:MEMFS.node_ops.unlink,rmdir:MEMFS.node_ops.rmdir,readdir:MEMFS.node_ops.readdir,symlink:MEMFS.node_ops.symlink},stream:{llseek:MEMFS.stream_ops.llseek}},file:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:{llseek:MEMFS.stream_ops.llseek,read:MEMFS.stream_ops.read,write:MEMFS.stream_ops.write,allocate:MEMFS.stream_ops.allocate,mmap:MEMFS.stream_ops.mmap,msync:MEMFS.stream_ops.msync}},link:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,readlink:MEMFS.node_ops.readlink},stream:{}},chrdev:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:FS.chrdev_stream_ops}}}var node=FS.createNode(parent,name,mode,dev);if(FS.isDir(node.mode)){node.node_ops=MEMFS.ops_table.dir.node;node.stream_ops=MEMFS.ops_table.dir.stream;node.contents={}}else if(FS.isFile(node.mode)){node.node_ops=MEMFS.ops_table.file.node;node.stream_ops=MEMFS.ops_table.file.stream;node.usedBytes=0;node.contents=null}else if(FS.isLink(node.mode)){node.node_ops=MEMFS.ops_table.link.node;node.stream_ops=MEMFS.ops_table.link.stream}else if(FS.isChrdev(node.mode)){node.node_ops=MEMFS.ops_table.chrdev.node;node.stream_ops=MEMFS.ops_table.chrdev.stream}node.timestamp=Date.now();if(parent){parent.contents[name]=node;parent.timestamp=node.timestamp}return node},getFileDataAsTypedArray(node){if(!node.contents)return new Uint8Array(0);if(node.contents.subarray)return node.contents.subarray(0,node.usedBytes);return new Uint8Array(node.contents)},expandFileStorage(node,newCapacity){var prevCapacity=node.contents?node.contents.length:0;if(prevCapacity>=newCapacity)return;var CAPACITY_DOUBLING_MAX=1024*1024;newCapacity=Math.max(newCapacity,prevCapacity*(prevCapacity<CAPACITY_DOUBLING_MAX?2:1.125)>>>0);if(prevCapacity!=0)newCapacity=Math.max(newCapacity,256);var oldContents=node.contents;node.contents=new Uint8Array(newCapacity);if(node.usedBytes>0)node.contents.set(oldContents.subarray(0,node.usedBytes),0)},resizeFileStorage(node,newSize){if(node.usedBytes==newSize)return;if(newSize==0){node.contents=null;node.usedBytes=0}else{var oldContents=node.contents;node.contents=new Uint8Array(newSize);if(oldContents){node.contents.set(oldContents.subarray(0,Math.min(newSize,node.usedBytes)))}node.usedBytes=newSize}},node_ops:{getattr(node){var attr={};attr.dev=FS.isChrdev(node.mode)?node.id:1;attr.ino=node.id;attr.mode=node.mode;attr.nlink=1;attr.uid=0;attr.gid=0;attr.rdev=node.rdev;if(FS.isDir(node.mode)){attr.size=4096}else if(FS.isFile(node.mode)){attr.size=node.usedBytes}else if(FS.isLink(node.mode)){attr.size=node.link.length}else{attr.size=0}attr.atime=new Date(node.timestamp);attr.mtime=new Date(node.timestamp);attr.ctime=new Date(node.timestamp);attr.blksize=4096;attr.blocks=Math.ceil(attr.size/attr.blksize);return attr},setattr(node,attr){if(attr.mode!==undefined){node.mode=attr.mode}if(attr.timestamp!==undefined){node.timestamp=attr.timestamp}if(attr.size!==undefined){MEMFS.resizeFileStorage(node,attr.size)}},lookup(parent,name){throw FS.genericErrors[44]},mknod(parent,name,mode,dev){return MEMFS.createNode(parent,name,mode,dev)},rename(old_node,new_dir,new_name){if(FS.isDir(old_node.mode)){var new_node;try{new_node=FS.lookupNode(new_dir,new_name)}catch(e){}if(new_node){for(var i in new_node.contents){throw new FS.ErrnoError(55)}}}delete old_node.parent.contents[old_node.name];old_node.parent.timestamp=Date.now();old_node.name=new_name;new_dir.contents[new_name]=old_node;new_dir.timestamp=old_node.parent.timestamp;old_node.parent=new_dir},unlink(parent,name){delete parent.contents[name];parent.timestamp=Date.now()},rmdir(parent,name){var node=FS.lookupNode(parent,name);for(var i in node.contents){throw new FS.ErrnoError(55)}delete parent.contents[name];parent.timestamp=Date.now()},readdir(node){var entries=[".",".."];for(var key in node.contents){if(!node.contents.hasOwnProperty(key)){continue}entries.push(key)}return entries},symlink(parent,newname,oldpath){var node=MEMFS.createNode(parent,newname,511|40960,0);node.link=oldpath;return node},readlink(node){if(!FS.isLink(node.mode)){throw new FS.ErrnoError(28)}return node.link}},stream_ops:{read(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=stream.node.usedBytes)return 0;var size=Math.min(stream.node.usedBytes-position,length);if(size>8&&contents.subarray){buffer.set(contents.subarray(position,position+size),offset)}else{for(var i=0;i<size;i++)buffer[offset+i]=contents[position+i]}return size},write(stream,buffer,offset,length,position,canOwn){if(buffer.buffer===GROWABLE_HEAP_I8().buffer){canOwn=false}if(!length)return 0;var node=stream.node;node.timestamp=Date.now();if(buffer.subarray&&(!node.contents||node.contents.subarray)){if(canOwn){node.contents=buffer.subarray(offset,offset+length);node.usedBytes=length;return length}else if(node.usedBytes===0&&position===0){node.contents=buffer.slice(offset,offset+length);node.usedBytes=length;return length}else if(position+length<=node.usedBytes){node.contents.set(buffer.subarray(offset,offset+length),position);return length}}MEMFS.expandFileStorage(node,position+length);if(node.contents.subarray&&buffer.subarray){node.contents.set(buffer.subarray(offset,offset+length),position)}else{for(var i=0;i<length;i++){node.contents[position+i]=buffer[offset+i]}}node.usedBytes=Math.max(node.usedBytes,position+length);return length},llseek(stream,offset,whence){var position=offset;if(whence===1){position+=stream.position}else if(whence===2){if(FS.isFile(stream.node.mode)){position+=stream.node.usedBytes}}if(position<0){throw new FS.ErrnoError(28)}return position},allocate(stream,offset,length){MEMFS.expandFileStorage(stream.node,offset+length);stream.node.usedBytes=Math.max(stream.node.usedBytes,offset+length)},mmap(stream,length,position,prot,flags){if(!FS.isFile(stream.node.mode)){throw new FS.ErrnoError(43)}var ptr;var allocated;var contents=stream.node.contents;if(!(flags&2)&&contents.buffer===GROWABLE_HEAP_I8().buffer){allocated=false;ptr=contents.byteOffset}else{if(position>0||position+length<contents.length){if(contents.subarray){contents=contents.subarray(position,position+length)}else{contents=Array.prototype.slice.call(contents,position,position+length)}}allocated=true;ptr=mmapAlloc(length);if(!ptr){throw new FS.ErrnoError(48)}GROWABLE_HEAP_I8().set(contents,ptr)}return{ptr:ptr,allocated:allocated}},msync(stream,buffer,offset,length,mmapFlags){MEMFS.stream_ops.write(stream,buffer,0,length,offset,false);return 0}}};var asyncLoad=(url,onload,onerror,noRunDep)=>{var dep=!noRunDep?getUniqueRunDependency(`al ${url}`):"";readAsync(url,arrayBuffer=>{assert(arrayBuffer,`Loading data file "${url}" failed (no arrayBuffer).`);onload(new Uint8Array(arrayBuffer));if(dep)removeRunDependency(dep)},event=>{if(onerror){onerror()}else{throw`Loading data file "${url}" failed.`}});if(dep)addRunDependency(dep)};var preloadPlugins=Module["preloadPlugins"]||[];var FS_handledByPreloadPlugin=(byteArray,fullname,finish,onerror)=>{if(typeof Browser!="undefined")Browser.init();var handled=false;preloadPlugins.forEach(plugin=>{if(handled)return;if(plugin["canHandle"](fullname)){plugin["handle"](byteArray,fullname,finish,onerror);handled=true}});return handled};var FS_createPreloadedFile=(parent,name,url,canRead,canWrite,onload,onerror,dontCreateFile,canOwn,preFinish)=>{var fullname=name?PATH_FS.resolve(PATH.join2(parent,name)):parent;var dep=getUniqueRunDependency(`cp ${fullname}`);function processData(byteArray){function finish(byteArray){if(preFinish)preFinish();if(!dontCreateFile){FS.createDataFile(parent,name,byteArray,canRead,canWrite,canOwn)}if(onload)onload();removeRunDependency(dep)}if(FS_handledByPreloadPlugin(byteArray,fullname,finish,()=>{if(onerror)onerror();removeRunDependency(dep)})){return}finish(byteArray)}addRunDependency(dep);if(typeof url=="string"){asyncLoad(url,byteArray=>processData(byteArray),onerror)}else{processData(url)}};var FS_modeStringToFlags=str=>{var flagModes={"r":0,"r+":2,"w":512|64|1,"w+":512|64|2,"a":1024|64|1,"a+":1024|64|2};var flags=flagModes[str];if(typeof flags=="undefined"){throw new Error(`Unknown file open mode: ${str}`)}return flags};var FS_getMode=(canRead,canWrite)=>{var mode=0;if(canRead)mode|=292|73;if(canWrite)mode|=146;return mode};var FS={root:null,mounts:[],devices:{},streams:[],nextInode:1,nameTable:null,currentPath:"/",initialized:false,ignorePermissions:true,ErrnoError:null,genericErrors:{},filesystems:null,syncFSRequests:0,lookupPath(path,opts={}){path=PATH_FS.resolve(path);if(!path)return{path:"",node:null};var defaults={follow_mount:true,recurse_count:0};opts=Object.assign(defaults,opts);if(opts.recurse_count>8){throw new FS.ErrnoError(32)}var parts=path.split("/").filter(p=>!!p);var current=FS.root;var current_path="/";for(var i=0;i<parts.length;i++){var islast=i===parts.length-1;if(islast&&opts.parent){break}current=FS.lookupNode(current,parts[i]);current_path=PATH.join2(current_path,parts[i]);if(FS.isMountpoint(current)){if(!islast||islast&&opts.follow_mount){current=current.mounted.root}}if(!islast||opts.follow){var count=0;while(FS.isLink(current.mode)){var link=FS.readlink(current_path);current_path=PATH_FS.resolve(PATH.dirname(current_path),link);var lookup=FS.lookupPath(current_path,{recurse_count:opts.recurse_count+1});current=lookup.node;if(count++>40){throw new FS.ErrnoError(32)}}}}return{path:current_path,node:current}},getPath(node){var path;while(true){if(FS.isRoot(node)){var mount=node.mount.mountpoint;if(!path)return mount;return mount[mount.length-1]!=="/"?`${mount}/${path}`:mount+path}path=path?`${node.name}/${path}`:node.name;node=node.parent}},hashName(parentid,name){var hash=0;for(var i=0;i<name.length;i++){hash=(hash<<5)-hash+name.charCodeAt(i)|0}return(parentid+hash>>>0)%FS.nameTable.length},hashAddNode(node){var hash=FS.hashName(node.parent.id,node.name);node.name_next=FS.nameTable[hash];FS.nameTable[hash]=node},hashRemoveNode(node){var hash=FS.hashName(node.parent.id,node.name);if(FS.nameTable[hash]===node){FS.nameTable[hash]=node.name_next}else{var current=FS.nameTable[hash];while(current){if(current.name_next===node){current.name_next=node.name_next;break}current=current.name_next}}},lookupNode(parent,name){var errCode=FS.mayLookup(parent);if(errCode){throw new FS.ErrnoError(errCode,parent)}var hash=FS.hashName(parent.id,name);for(var node=FS.nameTable[hash];node;node=node.name_next){var nodeName=node.name;if(node.parent.id===parent.id&&nodeName===name){return node}}return FS.lookup(parent,name)},createNode(parent,name,mode,rdev){var node=new FS.FSNode(parent,name,mode,rdev);FS.hashAddNode(node);return node},destroyNode(node){FS.hashRemoveNode(node)},isRoot(node){return node===node.parent},isMountpoint(node){return!!node.mounted},isFile(mode){return(mode&61440)===32768},isDir(mode){return(mode&61440)===16384},isLink(mode){return(mode&61440)===40960},isChrdev(mode){return(mode&61440)===8192},isBlkdev(mode){return(mode&61440)===24576},isFIFO(mode){return(mode&61440)===4096},isSocket(mode){return(mode&49152)===49152},flagsToPermissionString(flag){var perms=["r","w","rw"][flag&3];if(flag&512){perms+="w"}return perms},nodePermissions(node,perms){if(FS.ignorePermissions){return 0}if(perms.includes("r")&&!(node.mode&292)){return 2}else if(perms.includes("w")&&!(node.mode&146)){return 2}else if(perms.includes("x")&&!(node.mode&73)){return 2}return 0},mayLookup(dir){var errCode=FS.nodePermissions(dir,"x");if(errCode)return errCode;if(!dir.node_ops.lookup)return 2;return 0},mayCreate(dir,name){try{var node=FS.lookupNode(dir,name);return 20}catch(e){}return FS.nodePermissions(dir,"wx")},mayDelete(dir,name,isdir){var node;try{node=FS.lookupNode(dir,name)}catch(e){return e.errno}var errCode=FS.nodePermissions(dir,"wx");if(errCode){return errCode}if(isdir){if(!FS.isDir(node.mode)){return 54}if(FS.isRoot(node)||FS.getPath(node)===FS.cwd()){return 10}}else{if(FS.isDir(node.mode)){return 31}}return 0},mayOpen(node,flags){if(!node){return 44}if(FS.isLink(node.mode)){return 32}else if(FS.isDir(node.mode)){if(FS.flagsToPermissionString(flags)!=="r"||flags&512){return 31}}return FS.nodePermissions(node,FS.flagsToPermissionString(flags))},MAX_OPEN_FDS:4096,nextfd(){for(var fd=0;fd<=FS.MAX_OPEN_FDS;fd++){if(!FS.streams[fd]){return fd}}throw new FS.ErrnoError(33)},getStreamChecked(fd){var stream=FS.getStream(fd);if(!stream){throw new FS.ErrnoError(8)}return stream},getStream:fd=>FS.streams[fd],createStream(stream,fd=-1){if(!FS.FSStream){FS.FSStream=function(){this.shared={}};FS.FSStream.prototype={};Object.defineProperties(FS.FSStream.prototype,{object:{get(){return this.node},set(val){this.node=val}},isRead:{get(){return(this.flags&2097155)!==1}},isWrite:{get(){return(this.flags&2097155)!==0}},isAppend:{get(){return this.flags&1024}},flags:{get(){return this.shared.flags},set(val){this.shared.flags=val}},position:{get(){return this.shared.position},set(val){this.shared.position=val}}})}stream=Object.assign(new FS.FSStream,stream);if(fd==-1){fd=FS.nextfd()}stream.fd=fd;FS.streams[fd]=stream;return stream},closeStream(fd){FS.streams[fd]=null},chrdev_stream_ops:{open(stream){var device=FS.getDevice(stream.node.rdev);stream.stream_ops=device.stream_ops;if(stream.stream_ops.open){stream.stream_ops.open(stream)}},llseek(){throw new FS.ErrnoError(70)}},major:dev=>dev>>8,minor:dev=>dev&255,makedev:(ma,mi)=>ma<<8|mi,registerDevice(dev,ops){FS.devices[dev]={stream_ops:ops}},getDevice:dev=>FS.devices[dev],getMounts(mount){var mounts=[];var check=[mount];while(check.length){var m=check.pop();mounts.push(m);check.push.apply(check,m.mounts)}return mounts},syncfs(populate,callback){if(typeof populate=="function"){callback=populate;populate=false}FS.syncFSRequests++;if(FS.syncFSRequests>1){err(`warning: ${FS.syncFSRequests} FS.syncfs operations in flight at once, probably just doing extra work`)}var mounts=FS.getMounts(FS.root.mount);var completed=0;function doCallback(errCode){FS.syncFSRequests--;return callback(errCode)}function done(errCode){if(errCode){if(!done.errored){done.errored=true;return doCallback(errCode)}return}if(++completed>=mounts.length){doCallback(null)}}mounts.forEach(mount=>{if(!mount.type.syncfs){return done(null)}mount.type.syncfs(mount,populate,done)})},mount(type,opts,mountpoint){var root=mountpoint==="/";var pseudo=!mountpoint;var node;if(root&&FS.root){throw new FS.ErrnoError(10)}else if(!root&&!pseudo){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});mountpoint=lookup.path;node=lookup.node;if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}if(!FS.isDir(node.mode)){throw new FS.ErrnoError(54)}}var mount={type:type,opts:opts,mountpoint:mountpoint,mounts:[]};var mountRoot=type.mount(mount);mountRoot.mount=mount;mount.root=mountRoot;if(root){FS.root=mountRoot}else if(node){node.mounted=mount;if(node.mount){node.mount.mounts.push(mount)}}return mountRoot},unmount(mountpoint){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});if(!FS.isMountpoint(lookup.node)){throw new FS.ErrnoError(28)}var node=lookup.node;var mount=node.mounted;var mounts=FS.getMounts(mount);Object.keys(FS.nameTable).forEach(hash=>{var current=FS.nameTable[hash];while(current){var next=current.name_next;if(mounts.includes(current.mount)){FS.destroyNode(current)}current=next}});node.mounted=null;var idx=node.mount.mounts.indexOf(mount);node.mount.mounts.splice(idx,1)},lookup(parent,name){return parent.node_ops.lookup(parent,name)},mknod(path,mode,dev){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);if(!name||name==="."||name===".."){throw new FS.ErrnoError(28)}var errCode=FS.mayCreate(parent,name);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.mknod){throw new FS.ErrnoError(63)}return parent.node_ops.mknod(parent,name,mode,dev)},create(path,mode){mode=mode!==undefined?mode:438;mode&=4095;mode|=32768;return FS.mknod(path,mode,0)},mkdir(path,mode){mode=mode!==undefined?mode:511;mode&=511|512;mode|=16384;return FS.mknod(path,mode,0)},mkdirTree(path,mode){var dirs=path.split("/");var d="";for(var i=0;i<dirs.length;++i){if(!dirs[i])continue;d+="/"+dirs[i];try{FS.mkdir(d,mode)}catch(e){if(e.errno!=20)throw e}}},mkdev(path,mode,dev){if(typeof dev=="undefined"){dev=mode;mode=438}mode|=8192;return FS.mknod(path,mode,dev)},symlink(oldpath,newpath){if(!PATH_FS.resolve(oldpath)){throw new FS.ErrnoError(44)}var lookup=FS.lookupPath(newpath,{parent:true});var parent=lookup.node;if(!parent){throw new FS.ErrnoError(44)}var newname=PATH.basename(newpath);var errCode=FS.mayCreate(parent,newname);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.symlink){throw new FS.ErrnoError(63)}return parent.node_ops.symlink(parent,newname,oldpath)},rename(old_path,new_path){var old_dirname=PATH.dirname(old_path);var new_dirname=PATH.dirname(new_path);var old_name=PATH.basename(old_path);var new_name=PATH.basename(new_path);var lookup,old_dir,new_dir;lookup=FS.lookupPath(old_path,{parent:true});old_dir=lookup.node;lookup=FS.lookupPath(new_path,{parent:true});new_dir=lookup.node;if(!old_dir||!new_dir)throw new FS.ErrnoError(44);if(old_dir.mount!==new_dir.mount){throw new FS.ErrnoError(75)}var old_node=FS.lookupNode(old_dir,old_name);var relative=PATH_FS.relative(old_path,new_dirname);if(relative.charAt(0)!=="."){throw new FS.ErrnoError(28)}relative=PATH_FS.relative(new_path,old_dirname);if(relative.charAt(0)!=="."){throw new FS.ErrnoError(55)}var new_node;try{new_node=FS.lookupNode(new_dir,new_name)}catch(e){}if(old_node===new_node){return}var isdir=FS.isDir(old_node.mode);var errCode=FS.mayDelete(old_dir,old_name,isdir);if(errCode){throw new FS.ErrnoError(errCode)}errCode=new_node?FS.mayDelete(new_dir,new_name,isdir):FS.mayCreate(new_dir,new_name);if(errCode){throw new FS.ErrnoError(errCode)}if(!old_dir.node_ops.rename){throw new FS.ErrnoError(63)}if(FS.isMountpoint(old_node)||new_node&&FS.isMountpoint(new_node)){throw new FS.ErrnoError(10)}if(new_dir!==old_dir){errCode=FS.nodePermissions(old_dir,"w");if(errCode){throw new FS.ErrnoError(errCode)}}FS.hashRemoveNode(old_node);try{old_dir.node_ops.rename(old_node,new_dir,new_name)}catch(e){throw e}finally{FS.hashAddNode(old_node)}},rmdir(path){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);var node=FS.lookupNode(parent,name);var errCode=FS.mayDelete(parent,name,true);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.rmdir){throw new FS.ErrnoError(63)}if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}parent.node_ops.rmdir(parent,name);FS.destroyNode(node)},readdir(path){var lookup=FS.lookupPath(path,{follow:true});var node=lookup.node;if(!node.node_ops.readdir){throw new FS.ErrnoError(54)}return node.node_ops.readdir(node)},unlink(path){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;if(!parent){throw new FS.ErrnoError(44)}var name=PATH.basename(path);var node=FS.lookupNode(parent,name);var errCode=FS.mayDelete(parent,name,false);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.unlink){throw new FS.ErrnoError(63)}if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}parent.node_ops.unlink(parent,name);FS.destroyNode(node)},readlink(path){var lookup=FS.lookupPath(path);var link=lookup.node;if(!link){throw new FS.ErrnoError(44)}if(!link.node_ops.readlink){throw new FS.ErrnoError(28)}return PATH_FS.resolve(FS.getPath(link.parent),link.node_ops.readlink(link))},stat(path,dontFollow){var lookup=FS.lookupPath(path,{follow:!dontFollow});var node=lookup.node;if(!node){throw new FS.ErrnoError(44)}if(!node.node_ops.getattr){throw new FS.ErrnoError(63)}return node.node_ops.getattr(node)},lstat(path){return FS.stat(path,true)},chmod(path,mode,dontFollow){var node;if(typeof path=="string"){var lookup=FS.lookupPath(path,{follow:!dontFollow});node=lookup.node}else{node=path}if(!node.node_ops.setattr){throw new FS.ErrnoError(63)}node.node_ops.setattr(node,{mode:mode&4095|node.mode&~4095,timestamp:Date.now()})},lchmod(path,mode){FS.chmod(path,mode,true)},fchmod(fd,mode){var stream=FS.getStreamChecked(fd);FS.chmod(stream.node,mode)},chown(path,uid,gid,dontFollow){var node;if(typeof path=="string"){var lookup=FS.lookupPath(path,{follow:!dontFollow});node=lookup.node}else{node=path}if(!node.node_ops.setattr){throw new FS.ErrnoError(63)}node.node_ops.setattr(node,{timestamp:Date.now()})},lchown(path,uid,gid){FS.chown(path,uid,gid,true)},fchown(fd,uid,gid){var stream=FS.getStreamChecked(fd);FS.chown(stream.node,uid,gid)},truncate(path,len){if(len<0){throw new FS.ErrnoError(28)}var node;if(typeof path=="string"){var lookup=FS.lookupPath(path,{follow:true});node=lookup.node}else{node=path}if(!node.node_ops.setattr){throw new FS.ErrnoError(63)}if(FS.isDir(node.mode)){throw new FS.ErrnoError(31)}if(!FS.isFile(node.mode)){throw new FS.ErrnoError(28)}var errCode=FS.nodePermissions(node,"w");if(errCode){throw new FS.ErrnoError(errCode)}node.node_ops.setattr(node,{size:len,timestamp:Date.now()})},ftruncate(fd,len){var stream=FS.getStreamChecked(fd);if((stream.flags&2097155)===0){throw new FS.ErrnoError(28)}FS.truncate(stream.node,len)},utime(path,atime,mtime){var lookup=FS.lookupPath(path,{follow:true});var node=lookup.node;node.node_ops.setattr(node,{timestamp:Math.max(atime,mtime)})},open(path,flags,mode){if(path===""){throw new FS.ErrnoError(44)}flags=typeof flags=="string"?FS_modeStringToFlags(flags):flags;mode=typeof mode=="undefined"?438:mode;if(flags&64){mode=mode&4095|32768}else{mode=0}var node;if(typeof path=="object"){node=path}else{path=PATH.normalize(path);try{var lookup=FS.lookupPath(path,{follow:!(flags&131072)});node=lookup.node}catch(e){}}var created=false;if(flags&64){if(node){if(flags&128){throw new FS.ErrnoError(20)}}else{node=FS.mknod(path,mode,0);created=true}}if(!node){throw new FS.ErrnoError(44)}if(FS.isChrdev(node.mode)){flags&=~512}if(flags&65536&&!FS.isDir(node.mode)){throw new FS.ErrnoError(54)}if(!created){var errCode=FS.mayOpen(node,flags);if(errCode){throw new FS.ErrnoError(errCode)}}if(flags&512&&!created){FS.truncate(node,0)}flags&=~(128|512|131072);var stream=FS.createStream({node:node,path:FS.getPath(node),flags:flags,seekable:true,position:0,stream_ops:node.stream_ops,ungotten:[],error:false});if(stream.stream_ops.open){stream.stream_ops.open(stream)}if(Module["logReadFiles"]&&!(flags&1)){if(!FS.readFiles)FS.readFiles={};if(!(path in FS.readFiles)){FS.readFiles[path]=1}}return stream},close(stream){if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if(stream.getdents)stream.getdents=null;try{if(stream.stream_ops.close){stream.stream_ops.close(stream)}}catch(e){throw e}finally{FS.closeStream(stream.fd)}stream.fd=null},isClosed(stream){return stream.fd===null},llseek(stream,offset,whence){if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if(!stream.seekable||!stream.stream_ops.llseek){throw new FS.ErrnoError(70)}if(whence!=0&&whence!=1&&whence!=2){throw new FS.ErrnoError(28)}stream.position=stream.stream_ops.llseek(stream,offset,whence);stream.ungotten=[];return stream.position},read(stream,buffer,offset,length,position){if(length<0||position<0){throw new FS.ErrnoError(28)}if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if((stream.flags&2097155)===1){throw new FS.ErrnoError(8)}if(FS.isDir(stream.node.mode)){throw new FS.ErrnoError(31)}if(!stream.stream_ops.read){throw new FS.ErrnoError(28)}var seeking=typeof position!="undefined";if(!seeking){position=stream.position}else if(!stream.seekable){throw new FS.ErrnoError(70)}var bytesRead=stream.stream_ops.read(stream,buffer,offset,length,position);if(!seeking)stream.position+=bytesRead;return bytesRead},write(stream,buffer,offset,length,position,canOwn){if(length<0||position<0){throw new FS.ErrnoError(28)}if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if((stream.flags&2097155)===0){throw new FS.ErrnoError(8)}if(FS.isDir(stream.node.mode)){throw new FS.ErrnoError(31)}if(!stream.stream_ops.write){throw new FS.ErrnoError(28)}if(stream.seekable&&stream.flags&1024){FS.llseek(stream,0,2)}var seeking=typeof position!="undefined";if(!seeking){position=stream.position}else if(!stream.seekable){throw new FS.ErrnoError(70)}var bytesWritten=stream.stream_ops.write(stream,buffer,offset,length,position,canOwn);if(!seeking)stream.position+=bytesWritten;return bytesWritten},allocate(stream,offset,length){if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if(offset<0||length<=0){throw new FS.ErrnoError(28)}if((stream.flags&2097155)===0){throw new FS.ErrnoError(8)}if(!FS.isFile(stream.node.mode)&&!FS.isDir(stream.node.mode)){throw new FS.ErrnoError(43)}if(!stream.stream_ops.allocate){throw new FS.ErrnoError(138)}stream.stream_ops.allocate(stream,offset,length)},mmap(stream,length,position,prot,flags){if((prot&2)!==0&&(flags&2)===0&&(stream.flags&2097155)!==2){throw new FS.ErrnoError(2)}if((stream.flags&2097155)===1){throw new FS.ErrnoError(2)}if(!stream.stream_ops.mmap){throw new FS.ErrnoError(43)}return stream.stream_ops.mmap(stream,length,position,prot,flags)},msync(stream,buffer,offset,length,mmapFlags){if(!stream.stream_ops.msync){return 0}return stream.stream_ops.msync(stream,buffer,offset,length,mmapFlags)},munmap:stream=>0,ioctl(stream,cmd,arg){if(!stream.stream_ops.ioctl){throw new FS.ErrnoError(59)}return stream.stream_ops.ioctl(stream,cmd,arg)},readFile(path,opts={}){opts.flags=opts.flags||0;opts.encoding=opts.encoding||"binary";if(opts.encoding!=="utf8"&&opts.encoding!=="binary"){throw new Error(`Invalid encoding type "${opts.encoding}"`)}var ret;var stream=FS.open(path,opts.flags);var stat=FS.stat(path);var length=stat.size;var buf=new Uint8Array(length);FS.read(stream,buf,0,length,0);if(opts.encoding==="utf8"){ret=UTF8ArrayToString(buf,0)}else if(opts.encoding==="binary"){ret=buf}FS.close(stream);return ret},writeFile(path,data,opts={}){opts.flags=opts.flags||577;var stream=FS.open(path,opts.flags,opts.mode);if(typeof data=="string"){var buf=new Uint8Array(lengthBytesUTF8(data)+1);var actualNumBytes=stringToUTF8Array(data,buf,0,buf.length);FS.write(stream,buf,0,actualNumBytes,undefined,opts.canOwn)}else if(ArrayBuffer.isView(data)){FS.write(stream,data,0,data.byteLength,undefined,opts.canOwn)}else{throw new Error("Unsupported data type")}FS.close(stream)},cwd:()=>FS.currentPath,chdir(path){var lookup=FS.lookupPath(path,{follow:true});if(lookup.node===null){throw new FS.ErrnoError(44)}if(!FS.isDir(lookup.node.mode)){throw new FS.ErrnoError(54)}var errCode=FS.nodePermissions(lookup.node,"x");if(errCode){throw new FS.ErrnoError(errCode)}FS.currentPath=lookup.path},createDefaultDirectories(){FS.mkdir("/tmp");FS.mkdir("/home");FS.mkdir("/home/web_user")},createDefaultDevices(){FS.mkdir("/dev");FS.registerDevice(FS.makedev(1,3),{read:()=>0,write:(stream,buffer,offset,length,pos)=>length});FS.mkdev("/dev/null",FS.makedev(1,3));TTY.register(FS.makedev(5,0),TTY.default_tty_ops);TTY.register(FS.makedev(6,0),TTY.default_tty1_ops);FS.mkdev("/dev/tty",FS.makedev(5,0));FS.mkdev("/dev/tty1",FS.makedev(6,0));var randomBuffer=new Uint8Array(1024),randomLeft=0;var randomByte=()=>{if(randomLeft===0){randomLeft=randomFill(randomBuffer).byteLength}return randomBuffer[--randomLeft]};FS.createDevice("/dev","random",randomByte);FS.createDevice("/dev","urandom",randomByte);FS.mkdir("/dev/shm");FS.mkdir("/dev/shm/tmp")},createSpecialDirectories(){FS.mkdir("/proc");var proc_self=FS.mkdir("/proc/self");FS.mkdir("/proc/self/fd");FS.mount({mount(){var node=FS.createNode(proc_self,"fd",16384|511,73);node.node_ops={lookup(parent,name){var fd=+name;var stream=FS.getStreamChecked(fd);var ret={parent:null,mount:{mountpoint:"fake"},node_ops:{readlink:()=>stream.path}};ret.parent=ret;return ret}};return node}},{},"/proc/self/fd")},createStandardStreams(){if(Module["stdin"]){FS.createDevice("/dev","stdin",Module["stdin"])}else{FS.symlink("/dev/tty","/dev/stdin")}if(Module["stdout"]){FS.createDevice("/dev","stdout",null,Module["stdout"])}else{FS.symlink("/dev/tty","/dev/stdout")}if(Module["stderr"]){FS.createDevice("/dev","stderr",null,Module["stderr"])}else{FS.symlink("/dev/tty1","/dev/stderr")}var stdin=FS.open("/dev/stdin",0);var stdout=FS.open("/dev/stdout",1);var stderr=FS.open("/dev/stderr",1)},ensureErrnoError(){if(FS.ErrnoError)return;FS.ErrnoError=function ErrnoError(errno,node){this.name="ErrnoError";this.node=node;this.setErrno=function(errno){this.errno=errno};this.setErrno(errno);this.message="FS error"};FS.ErrnoError.prototype=new Error;FS.ErrnoError.prototype.constructor=FS.ErrnoError;[44].forEach(code=>{FS.genericErrors[code]=new FS.ErrnoError(code);FS.genericErrors[code].stack="<generic error, no stack>"})},staticInit(){FS.ensureErrnoError();FS.nameTable=new Array(4096);FS.mount(MEMFS,{},"/");FS.createDefaultDirectories();FS.createDefaultDevices();FS.createSpecialDirectories();FS.filesystems={"MEMFS":MEMFS}},init(input,output,error){FS.init.initialized=true;FS.ensureErrnoError();Module["stdin"]=input||Module["stdin"];Module["stdout"]=output||Module["stdout"];Module["stderr"]=error||Module["stderr"];FS.createStandardStreams()},quit(){FS.init.initialized=false;for(var i=0;i<FS.streams.length;i++){var stream=FS.streams[i];if(!stream){continue}FS.close(stream)}},findObject(path,dontResolveLastLink){var ret=FS.analyzePath(path,dontResolveLastLink);if(!ret.exists){return null}return ret.object},analyzePath(path,dontResolveLastLink){try{var lookup=FS.lookupPath(path,{follow:!dontResolveLastLink});path=lookup.path}catch(e){}var ret={isRoot:false,exists:false,error:0,name:null,path:null,object:null,parentExists:false,parentPath:null,parentObject:null};try{var lookup=FS.lookupPath(path,{parent:true});ret.parentExists=true;ret.parentPath=lookup.path;ret.parentObject=lookup.node;ret.name=PATH.basename(path);lookup=FS.lookupPath(path,{follow:!dontResolveLastLink});ret.exists=true;ret.path=lookup.path;ret.object=lookup.node;ret.name=lookup.node.name;ret.isRoot=lookup.path==="/"}catch(e){ret.error=e.errno}return ret},createPath(parent,path,canRead,canWrite){parent=typeof parent=="string"?parent:FS.getPath(parent);var parts=path.split("/").reverse();while(parts.length){var part=parts.pop();if(!part)continue;var current=PATH.join2(parent,part);try{FS.mkdir(current)}catch(e){}parent=current}return current},createFile(parent,name,properties,canRead,canWrite){var path=PATH.join2(typeof parent=="string"?parent:FS.getPath(parent),name);var mode=FS_getMode(canRead,canWrite);return FS.create(path,mode)},createDataFile(parent,name,data,canRead,canWrite,canOwn){var path=name;if(parent){parent=typeof parent=="string"?parent:FS.getPath(parent);path=name?PATH.join2(parent,name):parent}var mode=FS_getMode(canRead,canWrite);var node=FS.create(path,mode);if(data){if(typeof data=="string"){var arr=new Array(data.length);for(var i=0,len=data.length;i<len;++i)arr[i]=data.charCodeAt(i);data=arr}FS.chmod(node,mode|146);var stream=FS.open(node,577);FS.write(stream,data,0,data.length,0,canOwn);FS.close(stream);FS.chmod(node,mode)}return node},createDevice(parent,name,input,output){var path=PATH.join2(typeof parent=="string"?parent:FS.getPath(parent),name);var mode=FS_getMode(!!input,!!output);if(!FS.createDevice.major)FS.createDevice.major=64;var dev=FS.makedev(FS.createDevice.major++,0);FS.registerDevice(dev,{open(stream){stream.seekable=false},close(stream){if(output&&output.buffer&&output.buffer.length){output(10)}},read(stream,buffer,offset,length,pos){var bytesRead=0;for(var i=0;i<length;i++){var result;try{result=input()}catch(e){throw new FS.ErrnoError(29)}if(result===undefined&&bytesRead===0){throw new FS.ErrnoError(6)}if(result===null||result===undefined)break;bytesRead++;buffer[offset+i]=result}if(bytesRead){stream.node.timestamp=Date.now()}return bytesRead},write(stream,buffer,offset,length,pos){for(var i=0;i<length;i++){try{output(buffer[offset+i])}catch(e){throw new FS.ErrnoError(29)}}if(length){stream.node.timestamp=Date.now()}return i}});return FS.mkdev(path,mode,dev)},forceLoadFile(obj){if(obj.isDevice||obj.isFolder||obj.link||obj.contents)return true;if(typeof XMLHttpRequest!="undefined"){throw new Error("Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread.")}else if(read_){try{obj.contents=intArrayFromString(read_(obj.url),true);obj.usedBytes=obj.contents.length}catch(e){throw new FS.ErrnoError(29)}}else{throw new Error("Cannot load without read() or XMLHttpRequest.")}},createLazyFile(parent,name,url,canRead,canWrite){function LazyUint8Array(){this.lengthKnown=false;this.chunks=[]}LazyUint8Array.prototype.get=function LazyUint8Array_get(idx){if(idx>this.length-1||idx<0){return undefined}var chunkOffset=idx%this.chunkSize;var chunkNum=idx/this.chunkSize|0;return this.getter(chunkNum)[chunkOffset]};LazyUint8Array.prototype.setDataGetter=function LazyUint8Array_setDataGetter(getter){this.getter=getter};LazyUint8Array.prototype.cacheLength=function LazyUint8Array_cacheLength(){var xhr=new XMLHttpRequest;xhr.open("HEAD",url,false);xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error("Couldn't load "+url+". Status: "+xhr.status);var datalength=Number(xhr.getResponseHeader("Content-length"));var header;var hasByteServing=(header=xhr.getResponseHeader("Accept-Ranges"))&&header==="bytes";var usesGzip=(header=xhr.getResponseHeader("Content-Encoding"))&&header==="gzip";var chunkSize=1024*1024;if(!hasByteServing)chunkSize=datalength;var doXHR=(from,to)=>{if(from>to)throw new Error("invalid range ("+from+", "+to+") or no bytes requested!");if(to>datalength-1)throw new Error("only "+datalength+" bytes available! programmer error!");var xhr=new XMLHttpRequest;xhr.open("GET",url,false);if(datalength!==chunkSize)xhr.setRequestHeader("Range","bytes="+from+"-"+to);xhr.responseType="arraybuffer";if(xhr.overrideMimeType){xhr.overrideMimeType("text/plain; charset=x-user-defined")}xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error("Couldn't load "+url+". Status: "+xhr.status);if(xhr.response!==undefined){return new Uint8Array(xhr.response||[])}return intArrayFromString(xhr.responseText||"",true)};var lazyArray=this;lazyArray.setDataGetter(chunkNum=>{var start=chunkNum*chunkSize;var end=(chunkNum+1)*chunkSize-1;end=Math.min(end,datalength-1);if(typeof lazyArray.chunks[chunkNum]=="undefined"){lazyArray.chunks[chunkNum]=doXHR(start,end)}if(typeof lazyArray.chunks[chunkNum]=="undefined")throw new Error("doXHR failed!");return lazyArray.chunks[chunkNum]});if(usesGzip||!datalength){chunkSize=datalength=1;datalength=this.getter(0).length;chunkSize=datalength;out("LazyFiles on gzip forces download of the whole file when length is accessed")}this._length=datalength;this._chunkSize=chunkSize;this.lengthKnown=true};if(typeof XMLHttpRequest!="undefined"){if(!ENVIRONMENT_IS_WORKER)throw"Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc";var lazyArray=new LazyUint8Array;Object.defineProperties(lazyArray,{length:{get:function(){if(!this.lengthKnown){this.cacheLength()}return this._length}},chunkSize:{get:function(){if(!this.lengthKnown){this.cacheLength()}return this._chunkSize}}});var properties={isDevice:false,contents:lazyArray}}else{var properties={isDevice:false,url:url}}var node=FS.createFile(parent,name,properties,canRead,canWrite);if(properties.contents){node.contents=properties.contents}else if(properties.url){node.contents=null;node.url=properties.url}Object.defineProperties(node,{usedBytes:{get:function(){return this.contents.length}}});var stream_ops={};var keys=Object.keys(node.stream_ops);keys.forEach(key=>{var fn=node.stream_ops[key];stream_ops[key]=function forceLoadLazyFile(){FS.forceLoadFile(node);return fn.apply(null,arguments)}});function writeChunks(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=contents.length)return 0;var size=Math.min(contents.length-position,length);if(contents.slice){for(var i=0;i<size;i++){buffer[offset+i]=contents[position+i]}}else{for(var i=0;i<size;i++){buffer[offset+i]=contents.get(position+i)}}return size}stream_ops.read=(stream,buffer,offset,length,position)=>{FS.forceLoadFile(node);return writeChunks(stream,buffer,offset,length,position)};stream_ops.mmap=(stream,length,position,prot,flags)=>{FS.forceLoadFile(node);var ptr=mmapAlloc(length);if(!ptr){throw new FS.ErrnoError(48)}writeChunks(stream,GROWABLE_HEAP_I8(),ptr,length,position);return{ptr:ptr,allocated:true}};node.stream_ops=stream_ops;return node}};var UTF8ToString=(ptr,maxBytesToRead)=>ptr?UTF8ArrayToString(GROWABLE_HEAP_U8(),ptr,maxBytesToRead):"";var SYSCALLS={DEFAULT_POLLMASK:5,calculateAt(dirfd,path,allowEmpty){if(PATH.isAbs(path)){return path}var dir;if(dirfd===-100){dir=FS.cwd()}else{var dirstream=SYSCALLS.getStreamFromFD(dirfd);dir=dirstream.path}if(path.length==0){if(!allowEmpty){throw new FS.ErrnoError(44)}return dir}return PATH.join2(dir,path)},doStat(func,path,buf){try{var stat=func(path)}catch(e){if(e&&e.node&&PATH.normalize(path)!==PATH.normalize(FS.getPath(e.node))){return-54}throw e}GROWABLE_HEAP_I32()[buf>>2]=stat.dev;GROWABLE_HEAP_I32()[buf+4>>2]=stat.mode;GROWABLE_HEAP_U32()[buf+8>>2]=stat.nlink;GROWABLE_HEAP_I32()[buf+12>>2]=stat.uid;GROWABLE_HEAP_I32()[buf+16>>2]=stat.gid;GROWABLE_HEAP_I32()[buf+20>>2]=stat.rdev;tempI64=[stat.size>>>0,(tempDouble=stat.size,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],GROWABLE_HEAP_I32()[buf+24>>2]=tempI64[0],GROWABLE_HEAP_I32()[buf+28>>2]=tempI64[1];GROWABLE_HEAP_I32()[buf+32>>2]=4096;GROWABLE_HEAP_I32()[buf+36>>2]=stat.blocks;var atime=stat.atime.getTime();var mtime=stat.mtime.getTime();var ctime=stat.ctime.getTime();tempI64=[Math.floor(atime/1e3)>>>0,(tempDouble=Math.floor(atime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],GROWABLE_HEAP_I32()[buf+40>>2]=tempI64[0],GROWABLE_HEAP_I32()[buf+44>>2]=tempI64[1];GROWABLE_HEAP_U32()[buf+48>>2]=atime%1e3*1e3;tempI64=[Math.floor(mtime/1e3)>>>0,(tempDouble=Math.floor(mtime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],GROWABLE_HEAP_I32()[buf+56>>2]=tempI64[0],GROWABLE_HEAP_I32()[buf+60>>2]=tempI64[1];GROWABLE_HEAP_U32()[buf+64>>2]=mtime%1e3*1e3;tempI64=[Math.floor(ctime/1e3)>>>0,(tempDouble=Math.floor(ctime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],GROWABLE_HEAP_I32()[buf+72>>2]=tempI64[0],GROWABLE_HEAP_I32()[buf+76>>2]=tempI64[1];GROWABLE_HEAP_U32()[buf+80>>2]=ctime%1e3*1e3;tempI64=[stat.ino>>>0,(tempDouble=stat.ino,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],GROWABLE_HEAP_I32()[buf+88>>2]=tempI64[0],GROWABLE_HEAP_I32()[buf+92>>2]=tempI64[1];return 0},doMsync(addr,stream,len,flags,offset){if(!FS.isFile(stream.node.mode)){throw new FS.ErrnoError(43)}if(flags&2){return 0}var buffer=GROWABLE_HEAP_U8().slice(addr,addr+len);FS.msync(stream,buffer,offset,len,flags)},varargs:undefined,get(){var ret=GROWABLE_HEAP_I32()[SYSCALLS.varargs>>2];SYSCALLS.varargs+=4;return ret},getp(){return SYSCALLS.get()},getStr(ptr){var ret=UTF8ToString(ptr);return ret},getStreamFromFD(fd){var stream=FS.getStreamChecked(fd);return stream}};function _proc_exit(code){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(0,1,code);EXITSTATUS=code;if(!keepRuntimeAlive()){PThread.terminateAllThreads();if(Module["onExit"])Module["onExit"](code);ABORT=true}quit_(code,new ExitStatus(code))}var exitJS=(status,implicit)=>{EXITSTATUS=status;if(ENVIRONMENT_IS_PTHREAD){exitOnMainThread(status);throw"unwind"}_proc_exit(status)};var _exit=exitJS;var handleException=e=>{if(e instanceof ExitStatus||e=="unwind"){return EXITSTATUS}quit_(1,e)};var PThread={unusedWorkers:[],runningWorkers:[],tlsInitFunctions:[],pthreads:{},init(){if(ENVIRONMENT_IS_PTHREAD){PThread.initWorker()}else{PThread.initMainThread()}},initMainThread(){var pthreadPoolSize=8;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;if(ENVIRONMENT_IS_NODE&&!worker.pthread_ptr){worker.unref()}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};if(ENVIRONMENT_IS_NODE){worker.on("message",data=>worker.onmessage({data:data}));worker.on("error",e=>worker.onerror(e))}var handlers=[];var knownHandlers=["onExit","onAbort","print","printErr"];for(var handler of knownHandlers){if(Module.hasOwnProperty(handler)){handlers.push(handler)}}worker.postMessage({"cmd":"load","handlers":handlers,"urlOrBlob":Module["mainScriptUrlOrBlob"]||_scriptDir,"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 pthreadMainJs=locateFile("libwhisper.worker.js");worker=new Worker(pthreadMainJs);PThread.unusedWorkers.push(worker)},getNewWorker(){if(PThread.unusedWorkers.length==0){PThread.allocateUnusedWorker();PThread.loadWasmModuleToWorker(PThread.unusedWorkers[0])}return PThread.unusedWorkers.pop()}};Module["PThread"]=PThread;var callRuntimeCallbacks=callbacks=>{while(callbacks.length>0){callbacks.shift()(Module)}};var establishStackSpace=()=>{var pthread_ptr=_pthread_self();var stackHigh=GROWABLE_HEAP_I32()[pthread_ptr+52>>2];var stackSize=GROWABLE_HEAP_I32()[pthread_ptr+56>>2];var stackLow=stackHigh-stackSize;_emscripten_stack_set_limits(stackHigh,stackLow);stackRestore(stackHigh)};Module["establishStackSpace"]=establishStackSpace;function exitOnMainThread(returnCode){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(1,0,returnCode);_exit(returnCode)}var wasmTableMirror=[];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 invokeEntryPoint=(ptr,arg)=>{var result=getWasmTableEntry(ptr)(arg);function finish(result){if(keepRuntimeAlive()){PThread.setExitStatus(result)}else{__emscripten_thread_exit(result)}}finish(result)};Module["invokeEntryPoint"]=invokeEntryPoint;var registerTLSInit=tlsInitFunc=>{PThread.tlsInitFunctions.push(tlsInitFunc)};function ExceptionInfo(excPtr){this.excPtr=excPtr;this.ptr=excPtr-24;this.set_type=function(type){GROWABLE_HEAP_U32()[this.ptr+4>>2]=type};this.get_type=function(){return GROWABLE_HEAP_U32()[this.ptr+4>>2]};this.set_destructor=function(destructor){GROWABLE_HEAP_U32()[this.ptr+8>>2]=destructor};this.get_destructor=function(){return GROWABLE_HEAP_U32()[this.ptr+8>>2]};this.set_caught=function(caught){caught=caught?1:0;GROWABLE_HEAP_I8()[this.ptr+12>>0]=caught};this.get_caught=function(){return GROWABLE_HEAP_I8()[this.ptr+12>>0]!=0};this.set_rethrown=function(rethrown){rethrown=rethrown?1:0;GROWABLE_HEAP_I8()[this.ptr+13>>0]=rethrown};this.get_rethrown=function(){return GROWABLE_HEAP_I8()[this.ptr+13>>0]!=0};this.init=function(type,destructor){this.set_adjusted_ptr(0);this.set_type(type);this.set_destructor(destructor)};this.set_adjusted_ptr=function(adjustedPtr){GROWABLE_HEAP_U32()[this.ptr+16>>2]=adjustedPtr};this.get_adjusted_ptr=function(){return GROWABLE_HEAP_U32()[this.ptr+16>>2]};this.get_exception_ptr=function(){var isPointer=___cxa_is_pointer_type(this.get_type());if(isPointer){return GROWABLE_HEAP_U32()[this.excPtr>>2]}var adjusted=this.get_adjusted_ptr();if(adjusted!==0)return adjusted;return this.excPtr}}var exceptionLast=0;var uncaughtExceptionCount=0;var ___cxa_throw=(ptr,type,destructor)=>{var info=new ExceptionInfo(ptr);info.init(type,destructor);exceptionLast=ptr;uncaughtExceptionCount++;throw exceptionLast};var ___emscripten_init_main_thread_js=tb=>{__emscripten_thread_init(tb,!ENVIRONMENT_IS_WORKER,1,!ENVIRONMENT_IS_WEB,65536,false);PThread.threadInitTLS()};var ___emscripten_thread_cleanup=thread=>{if(!ENVIRONMENT_IS_PTHREAD)cleanupThread(thread);else postMessage({"cmd":"cleanupThread","thread":thread})};function pthreadCreateProxied(pthread_ptr,attr,startRoutine,arg){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(2,1,pthread_ptr,attr,startRoutine,arg);return ___pthread_create_js(pthread_ptr,attr,startRoutine,arg)}var ___pthread_create_js=(pthread_ptr,attr,startRoutine,arg)=>{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)};var setErrNo=value=>{GROWABLE_HEAP_I32()[___errno_location()>>2]=value;return value};function ___syscall_fcntl64(fd,cmd,varargs){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(3,1,fd,cmd,varargs);SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(cmd){case 0:{var arg=SYSCALLS.get();if(arg<0){return-28}while(FS.streams[arg]){arg++}var newStream;newStream=FS.createStream(stream,arg);return newStream.fd}case 1:case 2:return 0;case 3:return stream.flags;case 4:{var arg=SYSCALLS.get();stream.flags|=arg;return 0}case 5:{var arg=SYSCALLS.getp();var offset=0;GROWABLE_HEAP_I16()[arg+offset>>1]=2;return 0}case 6:case 7:return 0;case 16:case 8:return-28;case 9:setErrNo(28);return-1;default:{return-28}}}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_ioctl(fd,op,varargs){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(4,1,fd,op,varargs);SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(op){case 21509:{if(!stream.tty)return-59;return 0}case 21505:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tcgets){var termios=stream.tty.ops.ioctl_tcgets(stream);var argp=SYSCALLS.getp();GROWABLE_HEAP_I32()[argp>>2]=termios.c_iflag||0;GROWABLE_HEAP_I32()[argp+4>>2]=termios.c_oflag||0;GROWABLE_HEAP_I32()[argp+8>>2]=termios.c_cflag||0;GROWABLE_HEAP_I32()[argp+12>>2]=termios.c_lflag||0;for(var i=0;i<32;i++){GROWABLE_HEAP_I8()[argp+i+17>>0]=termios.c_cc[i]||0}return 0}return 0}case 21510:case 21511:case 21512:{if(!stream.tty)return-59;return 0}case 21506:case 21507:case 21508:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tcsets){var argp=SYSCALLS.getp();var c_iflag=GROWABLE_HEAP_I32()[argp>>2];var c_oflag=GROWABLE_HEAP_I32()[argp+4>>2];var c_cflag=GROWABLE_HEAP_I32()[argp+8>>2];var c_lflag=GROWABLE_HEAP_I32()[argp+12>>2];var c_cc=[];for(var i=0;i<32;i++){c_cc.push(GROWABLE_HEAP_I8()[argp+i+17>>0])}return stream.tty.ops.ioctl_tcsets(stream.tty,op,{c_iflag:c_iflag,c_oflag:c_oflag,c_cflag:c_cflag,c_lflag:c_lflag,c_cc:c_cc})}return 0}case 21519:{if(!stream.tty)return-59;var argp=SYSCALLS.getp();GROWABLE_HEAP_I32()[argp>>2]=0;return 0}case 21520:{if(!stream.tty)return-59;return-28}case 21531:{var argp=SYSCALLS.getp();return FS.ioctl(stream,op,argp)}case 21523:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tiocgwinsz){var winsize=stream.tty.ops.ioctl_tiocgwinsz(stream.tty);var argp=SYSCALLS.getp();GROWABLE_HEAP_I16()[argp>>1]=winsize[0];GROWABLE_HEAP_I16()[argp+2>>1]=winsize[1]}return 0}case 21524:{if(!stream.tty)return-59;return 0}case 21515:{if(!stream.tty)return-59;return 0}default:return-28}}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_openat(dirfd,path,flags,varargs){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(5,1,dirfd,path,flags,varargs);SYSCALLS.varargs=varargs;try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);var mode=varargs?SYSCALLS.get():0;return FS.open(path,flags,mode).fd}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var __embind_register_bigint=(primitiveType,name,size,minRange,maxRange)=>{};var embind_init_charCodes=()=>{var codes=new Array(256);for(var i=0;i<256;++i){codes[i]=String.fromCharCode(i)}embind_charCodes=codes};var embind_charCodes=undefined;var readLatin1String=ptr=>{var ret="";var c=ptr;while(GROWABLE_HEAP_U8()[c]){ret+=embind_charCodes[GROWABLE_HEAP_U8()[c++]]}return ret};var awaitingDependencies={};var registeredTypes={};var typeDependencies={};var BindingError=undefined;var throwBindingError=message=>{throw new BindingError(message)};var InternalError=undefined;var throwInternalError=message=>{throw new InternalError(message)};var whenDependentTypesAreResolved=(myTypes,dependentTypes,getTypeConverters)=>{myTypes.forEach(function(type){typeDependencies[type]=dependentTypes});function onComplete(typeConverters){var myTypeConverters=getTypeConverters(typeConverters);if(myTypeConverters.length!==myTypes.length){throwInternalError("Mismatched type converter count")}for(var i=0;i<myTypes.length;++i){registerType(myTypes[i],myTypeConverters[i])}}var typeConverters=new Array(dependentTypes.length);var unregisteredTypes=[];var registered=0;dependentTypes.forEach((dt,i)=>{if(registeredTypes.hasOwnProperty(dt)){typeConverters[i]=registeredTypes[dt]}else{unregisteredTypes.push(dt);if(!awaitingDependencies.hasOwnProperty(dt)){awaitingDependencies[dt]=[]}awaitingDependencies[dt].push(()=>{typeConverters[i]=registeredTypes[dt];++registered;if(registered===unregisteredTypes.length){onComplete(typeConverters)}})}});if(0===unregisteredTypes.length){onComplete(typeConverters)}};function sharedRegisterType(rawType,registeredInstance,options={}){var name=registeredInstance.name;if(!rawType){throwBindingError(`type "${name}" must have a positive integer typeid pointer`)}if(registeredTypes.hasOwnProperty(rawType)){if(options.ignoreDuplicateRegistrations){return}else{throwBindingError(`Cannot register type '${name}' twice`)}}registeredTypes[rawType]=registeredInstance;delete typeDependencies[rawType];if(awaitingDependencies.hasOwnProperty(rawType)){var callbacks=awaitingDependencies[rawType];delete awaitingDependencies[rawType];callbacks.forEach(cb=>cb())}}function registerType(rawType,registeredInstance,options={}){if(!("argPackAdvance"in registeredInstance)){throw new TypeError("registerType registeredInstance requires argPackAdvance")}return sharedRegisterType(rawType,registeredInstance,options)}var GenericWireTypeSize=8;var __embind_register_bool=(rawType,name,trueValue,falseValue)=>{name=readLatin1String(name);registerType(rawType,{name:name,"fromWireType":function(wt){return!!wt},"toWireType":function(destructors,o){return o?trueValue:falseValue},"argPackAdvance":GenericWireTypeSize,"readValueFromPointer":function(pointer){return this["fromWireType"](GROWABLE_HEAP_U8()[pointer])},destructorFunction:null})};function handleAllocatorInit(){Object.assign(HandleAllocator.prototype,{get(id){return this.allocated[id]},has(id){return this.allocated[id]!==undefined},allocate(handle){var id=this.freelist.pop()||this.allocated.length;this.allocated[id]=handle;return id},free(id){this.allocated[id]=undefined;this.freelist.push(id)}})}function HandleAllocator(){this.allocated=[undefined];this.freelist=[]}var emval_handles=new HandleAllocator;var __emval_decref=handle=>{if(handle>=emval_handles.reserved&&0===--emval_handles.get(handle).refcount){emval_handles.free(handle)}};var count_emval_handles=()=>{var count=0;for(var i=emval_handles.reserved;i<emval_handles.allocated.length;++i){if(emval_handles.allocated[i]!==undefined){++count}}return count};var init_emval=()=>{emval_handles.allocated.push({value:undefined},{value:null},{value:true},{value:false});emval_handles.reserved=emval_handles.allocated.length;Module["count_emval_handles"]=count_emval_handles};var Emval={toValue:handle=>{if(!handle){throwBindingError("Cannot use deleted val. handle = "+handle)}return emval_handles.get(handle).value},toHandle:value=>{switch(value){case undefined:return 1;case null:return 2;case true:return 3;case false:return 4;default:{return emval_handles.allocate({refcount:1,value:value})}}}};function simpleReadValueFromPointer(pointer){return this["fromWireType"](GROWABLE_HEAP_I32()[pointer>>2])}var __embind_register_emval=(rawType,name)=>{name=readLatin1String(name);registerType(rawType,{name:name,"fromWireType":handle=>{var rv=Emval.toValue(handle);__emval_decref(handle);return rv},"toWireType":(destructors,value)=>Emval.toHandle(value),"argPackAdvance":GenericWireTypeSize,"readValueFromPointer":simpleReadValueFromPointer,destructorFunction:null})};var floatReadValueFromPointer=(name,width)=>{switch(width){case 4:return function(pointer){return this["fromWireType"](GROWABLE_HEAP_F32()[pointer>>2])};case 8:return function(pointer){return this["fromWireType"](GROWABLE_HEAP_F64()[pointer>>3])};default:throw new TypeError(`invalid float width (${width}): ${name}`)}};var __embind_register_float=(rawType,name,size)=>{name=readLatin1String(name);registerType(rawType,{name:name,"fromWireType":value=>value,"toWireType":(destructors,value)=>value,"argPackAdvance":GenericWireTypeSize,"readValueFromPointer":floatReadValueFromPointer(name,size),destructorFunction:null})};var char_0=48;var char_9=57;var makeLegalFunctionName=name=>{if(undefined===name){return"_unknown"}name=name.replace(/[^a-zA-Z0-9_]/g,"$");var f=name.charCodeAt(0);if(f>=char_0&&f<=char_9){return`_${name}`}return name};var runDestructors=destructors=>{while(destructors.length){var ptr=destructors.pop();var del=destructors.pop();del(ptr)}};function createNamedFunction(name,body){name=makeLegalFunctionName(name);return{[name]:function(){return body.apply(this,arguments)}}[name]}function newFunc(constructor,argumentList){if(!(constructor instanceof Function)){throw new TypeError(`new_ called with constructor type ${typeof constructor} which is not a function`)}var dummy=createNamedFunction(constructor.name||"unknownFunctionName",function(){});dummy.prototype=constructor.prototype;var obj=new dummy;var r=constructor.apply(obj,argumentList);return r instanceof Object?r:obj}function craftInvokerFunction(humanName,argTypes,classType,cppInvokerFunc,cppTargetFunc,isAsync){var argCount=argTypes.length;if(argCount<2){throwBindingError("argTypes array size mismatch! Must at least get return value and 'this' types!")}var isClassMethodFunc=argTypes[1]!==null&&classType!==null;var needsDestructorStack=false;for(var i=1;i<argTypes.length;++i){if(argTypes[i]!==null&&argTypes[i].destructorFunction===undefined){needsDestructorStack=true;break}}var returns=argTypes[0].name!=="void";var argsList="";var argsListWired="";for(var i=0;i<argCount-2;++i){argsList+=(i!==0?", ":"")+"arg"+i;argsListWired+=(i!==0?", ":"")+"arg"+i+"Wired"}var invokerFnBody=`\n return function ${makeLegalFunctionName(humanName)}(${argsList}) {\n if (arguments.length !== ${argCount-2}) {\n throwBindingError('function ${humanName} called with ' + arguments.length + ' arguments, expected ${argCount-2}');\n }`;if(needsDestructorStack){invokerFnBody+="var destructors = [];\n"}var dtorStack=needsDestructorStack?"destructors":"null";var args1=["throwBindingError","invoker","fn","runDestructors","retType","classParam"];var args2=[throwBindingError,cppInvokerFunc,cppTargetFunc,runDestructors,argTypes[0],argTypes[1]];if(isClassMethodFunc){invokerFnBody+="var thisWired = classParam.toWireType("+dtorStack+", this);\n"}for(var i=0;i<argCount-2;++i){invokerFnBody+="var arg"+i+"Wired = argType"+i+".toWireType("+dtorStack+", arg"+i+"); // "+argTypes[i+2].name+"\n";args1.push("argType"+i);args2.push(argTypes[i+2])}if(isClassMethodFunc){argsListWired="thisWired"+(argsListWired.length>0?", ":"")+argsListWired}invokerFnBody+=(returns||isAsync?"var rv = ":"")+"invoker(fn"+(argsListWired.length>0?", ":"")+argsListWired+");\n";if(needsDestructorStack){invokerFnBody+="runDestructors(destructors);\n"}else{for(var i=isClassMethodFunc?1:2;i<argTypes.length;++i){var paramName=i===1?"thisWired":"arg"+(i-2)+"Wired";if(argTypes[i].destructorFunction!==null){invokerFnBody+=paramName+"_dtor("+paramName+"); // "+argTypes[i].name+"\n";args1.push(paramName+"_dtor");args2.push(argTypes[i].destructorFunction)}}}if(returns){invokerFnBody+="var ret = retType.fromWireType(rv);\n"+"return ret;\n"}else{}invokerFnBody+="}\n";args1.push(invokerFnBody);return newFunc(Function,args1).apply(null,args2)}var ensureOverloadTable=(proto,methodName,humanName)=>{if(undefined===proto[methodName].overloadTable){var prevFunc=proto[methodName];proto[methodName]=function(){if(!proto[methodName].overloadTable.hasOwnProperty(arguments.length)){throwBindingError(`Function '${humanName}' called with an invalid number of arguments (${arguments.length}) - expects one of (${proto[methodName].overloadTable})!`)}return proto[methodName].overloadTable[arguments.length].apply(this,arguments)};proto[methodName].overloadTable=[];proto[methodName].overloadTable[prevFunc.argCount]=prevFunc}};var exposePublicSymbol=(name,value,numArguments)=>{if(Module.hasOwnProperty(name)){if(undefined===numArguments||undefined!==Module[name].overloadTable&&undefined!==Module[name].overloadTable[numArguments]){throwBindingError(`Cannot register public name '${name}' twice`)}ensureOverloadTable(Module,name,name);if(Module.hasOwnProperty(numArguments)){throwBindingError(`Cannot register multiple overloads of a function with the same number of arguments (${numArguments})!`)}Module[name].overloadTable[numArguments]=value}else{Module[name]=value;if(undefined!==numArguments){Module[name].numArguments=numArguments}}};var heap32VectorToArray=(count,firstElement)=>{var array=[];for(var i=0;i<count;i++){array.push(GROWABLE_HEAP_U32()[firstElement+i*4>>2])}return array};var replacePublicSymbol=(name,value,numArguments)=>{if(!Module.hasOwnProperty(name)){throwInternalError("Replacing nonexistant public symbol")}if(undefined!==Module[name].overloadTable&&undefined!==numArguments){Module[name].overloadTable[numArguments]=value}else{Module[name]=value;Module[name].argCount=numArguments}};var dynCallLegacy=(sig,ptr,args)=>{var f=Module["dynCall_"+sig];return args&&args.length?f.apply(null,[ptr].concat(args)):f.call(null,ptr)};var dynCall=(sig,ptr,args)=>{if(sig.includes("j")){return dynCallLegacy(sig,ptr,args)}var rtn=getWasmTableEntry(ptr).apply(null,args);return rtn};var getDynCaller=(sig,ptr)=>{var argCache=[];return function(){argCache.length=0;Object.assign(argCache,arguments);return dynCall(sig,ptr,argCache)}};var embind__requireFunction=(signature,rawFunction)=>{signature=readLatin1String(signature);function makeDynCaller(){if(signature.includes("j")){return getDynCaller(signature,rawFunction)}return getWasmTableEntry(rawFunction)}var fp=makeDynCaller();if(typeof fp!="function"){throwBindingError(`unknown function pointer with signature ${signature}: ${rawFunction}`)}return fp};var extendError=(baseErrorType,errorName)=>{var errorClass=createNamedFunction(errorName,function(message){this.name=errorName;this.message=message;var stack=new Error(message).stack;if(stack!==undefined){this.stack=this.toString()+"\n"+stack.replace(/^Error(:[^\n]*)?\n/,"")}});errorClass.prototype=Object.create(baseErrorType.prototype);errorClass.prototype.constructor=errorClass;errorClass.prototype.toString=function(){if(this.message===undefined){return this.name}else{return`${this.name}: ${this.message}`}};return errorClass};var UnboundTypeError=undefined;var getTypeName=type=>{var ptr=___getTypeName(type);var rv=readLatin1String(ptr);_free(ptr);return rv};var throwUnboundTypeError=(message,types)=>{var unboundTypes=[];var seen={};function visit(type){if(seen[type]){return}if(registeredTypes[type]){return}if(typeDependencies[type]){typeDependencies[type].forEach(visit);return}unboundTypes.push(type);seen[type]=true}types.forEach(visit);throw new UnboundTypeError(`${message}: `+unboundTypes.map(getTypeName).join([", "]))};var __embind_register_function=(name,argCount,rawArgTypesAddr,signature,rawInvoker,fn,isAsync)=>{var argTypes=heap32VectorToArray(argCount,rawArgTypesAddr);name=readLatin1String(name);rawInvoker=embind__requireFunction(signature,rawInvoker);exposePublicSymbol(name,function(){throwUnboundTypeError(`Cannot call ${name} due to unbound types`,argTypes)},argCount-1);whenDependentTypesAreResolved([],argTypes,function(argTypes){var invokerArgsArray=[argTypes[0],null].concat(argTypes.slice(1));replacePublicSymbol(name,craftInvokerFunction(name,invokerArgsArray,null,rawInvoker,fn,isAsync),argCount-1);return[]})};var integerReadValueFromPointer=(name,width,signed)=>{switch(width){case 1:return signed?pointer=>GROWABLE_HEAP_I8()[pointer>>0]:pointer=>GROWABLE_HEAP_U8()[pointer>>0];case 2:return signed?pointer=>GROWABLE_HEAP_I16()[pointer>>1]:pointer=>GROWABLE_HEAP_U16()[pointer>>1];case 4:return signed?pointer=>GROWABLE_HEAP_I32()[pointer>>2]:pointer=>GROWABLE_HEAP_U32()[pointer>>2];default:throw new TypeError(`invalid integer width (${width}): ${name}`)}};var __embind_register_integer=(primitiveType,name,size,minRange,maxRange)=>{name=readLatin1String(name);if(maxRange===-1){maxRange=4294967295}var fromWireType=value=>value;if(minRange===0){var bitshift=32-8*size;fromWireType=value=>value<<bitshift>>>bitshift}var isUnsignedType=name.includes("unsigned");var checkAssertions=(value,toTypeName)=>{};var toWireType;if(isUnsignedType){toWireType=function(destructors,value){checkAssertions(value,this.name);return value>>>0}}else{toWireType=function(destructors,value){checkAssertions(value,this.name);return value}}registerType(primitiveType,{name:name,"fromWireType":fromWireType,"toWireType":toWireType,"argPackAdvance":GenericWireTypeSize,"readValueFromPointer":integerReadValueFromPointer(name,size,minRange!==0),destructorFunction:null})};var __embind_register_memory_view=(rawType,dataTypeIndex,name)=>{var typeMapping=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array];var TA=typeMapping[dataTypeIndex];function decodeMemoryView(handle){var size=GROWABLE_HEAP_U32()[handle>>2];var data=GROWABLE_HEAP_U32()[handle+4>>2];return new TA(GROWABLE_HEAP_I8().buffer,data,size)}name=readLatin1String(name);registerType(rawType,{name:name,"fromWireType":decodeMemoryView,"argPackAdvance":GenericWireTypeSize,"readValueFromPointer":decodeMemoryView},{ignoreDuplicateRegistrations:true})};function readPointer(pointer){return this["fromWireType"](GROWABLE_HEAP_U32()[pointer>>2])}var stringToUTF8=(str,outPtr,maxBytesToWrite)=>stringToUTF8Array(str,GROWABLE_HEAP_U8(),outPtr,maxBytesToWrite);var __embind_register_std_string=(rawType,name)=>{name=readLatin1String(name);var stdStringIsUTF8=name==="std::string";registerType(rawType,{name:name,"fromWireType":value=>{var length=GROWABLE_HEAP_U32()[value>>2];var payload=value+4;var str;if(stdStringIsUTF8){var decodeStartPtr=payload;for(var i=0;i<=length;++i){var currentBytePtr=payload+i;if(i==length||GROWABLE_HEAP_U8()[currentBytePtr]==0){var maxRead=currentBytePtr-decodeStartPtr;var stringSegment=UTF8ToString(decodeStartPtr,maxRead);if(str===undefined){str=stringSegment}else{str+=String.fromCharCode(0);str+=stringSegment}decodeStartPtr=currentBytePtr+1}}}else{var a=new Array(length);for(var i=0;i<length;++i){a[i]=String.fromCharCode(GROWABLE_HEAP_U8()[payload+i])}str=a.join("")}_free(value);return str},"toWireType":(destructors,value)=>{if(value instanceof ArrayBuffer){value=new Uint8Array(value)}var length;var valueIsOfTypeString=typeof value=="string";if(!(valueIsOfTypeString||value instanceof Uint8Array||value instanceof Uint8ClampedArray||value instanceof Int8Array)){throwBindingError("Cannot pass non-string to std::string")}if(stdStringIsUTF8&&valueIsOfTypeString){length=lengthBytesUTF8(value)}else{length=value.length}var base=_malloc(4+length+1);var ptr=base+4;GROWABLE_HEAP_U32()[base>>2]=length;if(stdStringIsUTF8&&valueIsOfTypeString){stringToUTF8(value,ptr,length+1)}else{if(valueIsOfTypeString){for(var i=0;i<length;++i){var charCode=value.charCodeAt(i);if(charCode>255){_free(ptr);throwBindingError("String has UTF-16 code units that do not fit in 8 bits")}GROWABLE_HEAP_U8()[ptr+i]=charCode}}else{for(var i=0;i<length;++i){GROWABLE_HEAP_U8()[ptr+i]=value[i]}}}if(destructors!==null){destructors.push(_free,base)}return base},"argPackAdvance":GenericWireTypeSize,"readValueFromPointer":readPointer,destructorFunction:ptr=>_free(ptr)})};var UTF16Decoder=typeof TextDecoder!="undefined"?new TextDecoder("utf-16le"):undefined;var UTF16ToString=(ptr,maxBytesToRead)=>{var endPtr=ptr;var idx=endPtr>>1;var maxIdx=idx+maxBytesToRead/2;while(!(idx>=maxIdx)&&GROWABLE_HEAP_U16()[idx])++idx;endPtr=idx<<1;if(endPtr-ptr>32&&UTF16Decoder)return UTF16Decoder.decode(GROWABLE_HEAP_U8().slice(ptr,endPtr));var str="";for(var i=0;!(i>=maxBytesToRead/2);++i){var codeUnit=GROWABLE_HEAP_I16()[ptr+i*2>>1];if(codeUnit==0)break;str+=String.fromCharCode(codeUnit)}return str};var stringToUTF16=(str,outPtr,maxBytesToWrite)=>{if(maxBytesToWrite===undefined){maxBytesToWrite=2147483647}if(maxBytesToWrite<2)return 0;maxBytesToWrite-=2;var startPtr=outPtr;var numCharsToWrite=maxBytesToWrite<str.length*2?maxBytesToWrite/2:str.length;for(var i=0;i<numCharsToWrite;++i){var codeUnit=str.charCodeAt(i);GROWABLE_HEAP_I16()[outPtr>>1]=codeUnit;outPtr+=2}GROWABLE_HEAP_I16()[outPtr>>1]=0;return outPtr-startPtr};var lengthBytesUTF16=str=>str.length*2;var UTF32ToString=(ptr,maxBytesToRead)=>{var i=0;var str="";while(!(i>=maxBytesToRead/4)){var utf32=GROWABLE_HEAP_I32()[ptr+i*4>>2];if(utf32==0)break;++i;if(utf32>=65536){var ch=utf32-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}else{str+=String.fromCharCode(utf32)}}return str};var stringToUTF32=(str,outPtr,maxBytesToWrite)=>{if(maxBytesToWrite===undefined){maxBytesToWrite=2147483647}if(maxBytesToWrite<4)return 0;var startPtr=outPtr;var endPtr=startPtr+maxBytesToWrite-4;for(var i=0;i<str.length;++i){var codeUnit=str.charCodeAt(i);if(codeUnit>=55296&&codeUnit<=57343){var trailSurrogate=str.charCodeAt(++i);codeUnit=65536+((codeUnit&1023)<<10)|trailSurrogate&1023}GROWABLE_HEAP_I32()[outPtr>>2]=codeUnit;outPtr+=4;if(outPtr+4>endPtr)break}GROWABLE_HEAP_I32()[outPtr>>2]=0;return outPtr-startPtr};var lengthBytesUTF32=str=>{var len=0;for(var i=0;i<str.length;++i){var codeUnit=str.charCodeAt(i);if(codeUnit>=55296&&codeUnit<=57343)++i;len+=4}return len};var __embind_register_std_wstring=(rawType,charSize,name)=>{name=readLatin1String(name);var decodeString,encodeString,getHeap,lengthBytesUTF,shift;if(charSize===2){decodeString=UTF16ToString;encodeString=stringToUTF16;lengthBytesUTF=lengthBytesUTF16;getHeap=()=>GROWABLE_HEAP_U16();shift=1}else if(charSize===4){decodeString=UTF32ToString;encodeString=stringToUTF32;lengthBytesUTF=lengthBytesUTF32;getHeap=()=>GROWABLE_HEAP_U32();shift=2}registerType(rawType,{name:name,"fromWireType":value=>{var length=GROWABLE_HEAP_U32()[value>>2];var HEAP=getHeap();var str;var decodeStartPtr=value+4;for(var i=0;i<=length;++i){var currentBytePtr=value+4+i*charSize;if(i==length||HEAP[currentBytePtr>>shift]==0){var maxReadBytes=currentBytePtr-decodeStartPtr;var stringSegment=decodeString(decodeStartPtr,maxReadBytes);if(str===undefined){str=stringSegment}else{str+=String.fromCharCode(0);str+=stringSegment}decodeStartPtr=currentBytePtr+charSize}}_free(value);return str},"toWireType":(destructors,value)=>{if(!(typeof value=="string")){throwBindingError(`Cannot pass non-string to C++ string type ${name}`)}var length=lengthBytesUTF(value);var ptr=_malloc(4+length+charSize);GROWABLE_HEAP_U32()[ptr>>2]=length>>shift;encodeString(value,ptr+4,length+charSize);if(destructors!==null){destructors.push(_free,ptr)}return ptr},"argPackAdvance":GenericWireTypeSize,"readValueFromPointer":simpleReadValueFromPointer,destructorFunction:ptr=>_free(ptr)})};var __embind_register_void=(rawType,name)=>{name=readLatin1String(name);registerType(rawType,{isVoid:true,name:name,"argPackAdvance":0,"fromWireType":()=>undefined,"toWireType":(destructors,o)=>undefined})};var nowIsMonotonic=true;var __emscripten_get_now_is_monotonic=()=>nowIsMonotonic;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)}};var __emscripten_thread_mailbox_await=pthread_ptr=>{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)}};Module["__emscripten_thread_mailbox_await"]=__emscripten_thread_mailbox_await;var checkMailbox=()=>{var pthread_ptr=_pthread_self();if(pthread_ptr){__emscripten_thread_mailbox_await(pthread_ptr);callUserCallback(()=>__emscripten_check_mailbox())}};Module["checkMailbox"]=checkMailbox;var __emscripten_notify_mailbox_postmessage=(targetThreadId,currThreadId,mainThreadId)=>{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 withStackSave=f=>{var stack=stackSave();var ret=f();stackRestore(stack);return ret};var proxyToMainThread=function(index,sync){var numCallArgs=arguments.length-2;var outerArgs=arguments;return withStackSave(()=>{var serializedNumCallArgs=numCallArgs;var args=stackAlloc(serializedNumCallArgs*8);var b=args>>3;for(var i=0;i<numCallArgs;i++){var arg=outerArgs[2+i];GROWABLE_HEAP_F64()[b+i]=arg}return __emscripten_run_on_main_thread_js(index,serializedNumCallArgs,args,sync)})};var proxiedJSCallArgs=[];var __emscripten_receive_on_main_thread_js=(index,callingThread,numCallArgs,args)=>{proxiedJSCallArgs.length=numCallArgs;var b=args>>3;for(var i=0;i<numCallArgs;i++){proxiedJSCallArgs[i]=GROWABLE_HEAP_F64()[b+i]}var func=proxiedFunctionTable[index];PThread.currentProxiedOperationCallerThread=callingThread;var rtn=func.apply(null,proxiedJSCallArgs);PThread.currentProxiedOperationCallerThread=0;return rtn};var __emscripten_thread_set_strongref=thread=>{if(ENVIRONMENT_IS_NODE){PThread.pthreads[thread].ref()}};var requireRegisteredType=(rawType,humanName)=>{var impl=registeredTypes[rawType];if(undefined===impl){throwBindingError(humanName+" has unknown type "+getTypeName(rawType))}return impl};var __emval_as=(handle,returnType,destructorsRef)=>{handle=Emval.toValue(handle);returnType=requireRegisteredType(returnType,"emval::as");var destructors=[];var rd=Emval.toHandle(destructors);GROWABLE_HEAP_U32()[destructorsRef>>2]=rd;return returnType["toWireType"](destructors,handle)};var emval_symbols={};var getStringOrSymbol=address=>{var symbol=emval_symbols[address];if(symbol===undefined){return readLatin1String(address)}return symbol};var emval_methodCallers=[];var __emval_call_void_method=(caller,handle,methodName,args)=>{caller=emval_methodCallers[caller];handle=Emval.toValue(handle);methodName=getStringOrSymbol(methodName);caller(handle,methodName,null,args)};var emval_addMethodCaller=caller=>{var id=emval_methodCallers.length;emval_methodCallers.push(caller);return id};var emval_lookupTypes=(argCount,argTypes)=>{var a=new Array(argCount);for(var i=0;i<argCount;++i){a[i]=requireRegisteredType(GROWABLE_HEAP_U32()[argTypes+i*4>>2],"parameter "+i)}return a};var emval_registeredMethods=[];var __emval_get_method_caller=(argCount,argTypes)=>{var types=emval_lookupTypes(argCount,argTypes);var retType=types[0];var signatureName=retType.name+"_$"+types.slice(1).map(function(t){return t.name}).join("_")+"$";var returnId=emval_registeredMethods[signatureName];if(returnId!==undefined){return returnId}var params=["retType"];var args=[retType];var argsList="";for(var i=0;i<argCount-1;++i){argsList+=(i!==0?", ":"")+"arg"+i;params.push("argType"+i);args.push(types[1+i])}var functionName=makeLegalFunctionName("methodCaller_"+signatureName);var functionBody="return function "+functionName+"(handle, name, destructors, args) {\n";var offset=0;for(var i=0;i<argCount-1;++i){functionBody+=" var arg"+i+" = argType"+i+".readValueFromPointer(args"+(offset?"+"+offset:"")+");\n";offset+=types[i+1]["argPackAdvance"]}functionBody+=" var rv = handle[name]("+argsList+");\n";for(var i=0;i<argCount-1;++i){if(types[i+1]["deleteObject"]){functionBody+=" argType"+i+".deleteObject(arg"+i+");\n"}}if(!retType.isVoid){functionBody+=" return retType.toWireType(destructors, rv);\n"}functionBody+="};\n";params.push(functionBody);var invokerFunction=newFunc(Function,params).apply(null,args);returnId=emval_addMethodCaller(invokerFunction);emval_registeredMethods[signatureName]=returnId;return returnId};var __emval_get_module_property=name=>{name=getStringOrSymbol(name);return Emval.toHandle(Module[name])};var __emval_get_property=(handle,key)=>{handle=Emval.toValue(handle);key=Emval.toValue(key);return Emval.toHandle(handle[key])};var __emval_incref=handle=>{if(handle>4){emval_handles.get(handle).refcount+=1}};var craftEmvalAllocator=argCount=>{var argsList="";for(var i=0;i<argCount;++i){argsList+=(i!==0?", ":"")+"arg"+i}var getMemory=()=>GROWABLE_HEAP_U32();var functionBody="return function emval_allocator_"+argCount+"(constructor, argTypes, args) {\n"+" var HEAPU32 = getMemory();\n";for(var i=0;i<argCount;++i){functionBody+="var argType"+i+" = requireRegisteredType(HEAPU32[((argTypes)>>2)], 'parameter "+i+"');\n"+"var arg"+i+" = argType"+i+".readValueFromPointer(args);\n"+"args += argType"+i+"['argPackAdvance'];\n"+"argTypes += 4;\n"}functionBody+="var obj = new constructor("+argsList+");\n"+"return valueToHandle(obj);\n"+"}\n";return new Function("requireRegisteredType","Module","valueToHandle","getMemory",functionBody)(requireRegisteredType,Module,Emval.toHandle,getMemory)};var emval_newers={};var __emval_new=(handle,argCount,argTypes,args)=>{handle=Emval.toValue(handle);var newer=emval_newers[argCount];if(!newer){newer=craftEmvalAllocator(argCount);emval_newers[argCount]=newer}return newer(handle,argTypes,args)};var __emval_new_cstring=v=>Emval.toHandle(getStringOrSymbol(v));var __emval_run_destructors=handle=>{var destructors=Emval.toValue(handle);runDestructors(destructors);__emval_decref(handle)};var _abort=()=>{abort("")};var warnOnce=text=>{if(!warnOnce.shown)warnOnce.shown={};if(!warnOnce.shown[text]){warnOnce.shown[text]=1;if(ENVIRONMENT_IS_NODE)text="warning: "+text;err(text)}};var _emscripten_check_blocking_allowed=()=>{};var runtimeKeepalivePush=()=>{runtimeKeepaliveCounter+=1};var _emscripten_exit_with_live_runtime=()=>{runtimeKeepalivePush();throw"unwind"};var getHeapMax=()=>2147483648;var _emscripten_get_heap_max=()=>getHeapMax();var _emscripten_get_now;_emscripten_get_now=()=>performance.timeOrigin+performance.now();var _emscripten_num_logical_cores=()=>{if(ENVIRONMENT_IS_NODE)return require("os").cpus().length;return 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){}};var _emscripten_resize_heap=requestedSize=>{var oldSize=GROWABLE_HEAP_U8().length;requestedSize>>>=0;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 ENV={};var getExecutableName=()=>thisProgram||"./this.program";var getEnvStrings=()=>{if(!getEnvStrings.strings){var lang=(typeof navigator=="object"&&navigator.languages&&navigator.languages[0]||"C").replace("-","_")+".UTF-8";var env={"USER":"web_user","LOGNAME":"web_user","PATH":"/","PWD":"/","HOME":"/home/web_user","LANG":lang,"_":getExecutableName()};for(var x in ENV){if(ENV[x]===undefined)delete env[x];else env[x]=ENV[x]}var strings=[];for(var x in env){strings.push(`${x}=${env[x]}`)}getEnvStrings.strings=strings}return getEnvStrings.strings};var stringToAscii=(str,buffer)=>{for(var i=0;i<str.length;++i){GROWABLE_HEAP_I8()[buffer++>>0]=str.charCodeAt(i)}GROWABLE_HEAP_I8()[buffer>>0]=0};var _environ_get=function(__environ,environ_buf){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(6,1,__environ,environ_buf);var bufSize=0;getEnvStrings().forEach((string,i)=>{var ptr=environ_buf+bufSize;GROWABLE_HEAP_U32()[__environ+i*4>>2]=ptr;stringToAscii(string,ptr);bufSize+=string.length+1});return 0};var _environ_sizes_get=function(penviron_count,penviron_buf_size){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(7,1,penviron_count,penviron_buf_size);var strings=getEnvStrings();GROWABLE_HEAP_U32()[penviron_count>>2]=strings.length;var bufSize=0;strings.forEach(string=>bufSize+=string.length+1);GROWABLE_HEAP_U32()[penviron_buf_size>>2]=bufSize;return 0};function _fd_close(fd){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(8,1,fd);try{var stream=SYSCALLS.getStreamFromFD(fd);FS.close(stream);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var doReadv=(stream,iov,iovcnt,offset)=>{var ret=0;for(var i=0;i<iovcnt;i++){var ptr=GROWABLE_HEAP_U32()[iov>>2];var len=GROWABLE_HEAP_U32()[iov+4>>2];iov+=8;var curr=FS.read(stream,GROWABLE_HEAP_I8(),ptr,len,offset);if(curr<0)return-1;ret+=curr;if(curr<len)break;if(typeof offset!=="undefined"){offset+=curr}}return ret};function _fd_read(fd,iov,iovcnt,pnum){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(9,1,fd,iov,iovcnt,pnum);try{var stream=SYSCALLS.getStreamFromFD(fd);var num=doReadv(stream,iov,iovcnt);GROWABLE_HEAP_U32()[pnum>>2]=num;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var convertI32PairToI53Checked=(lo,hi)=>hi+2097152>>>0<4194305-!!lo?(lo>>>0)+hi*4294967296:NaN;function _fd_seek(fd,offset_low,offset_high,whence,newOffset){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(10,1,fd,offset_low,offset_high,whence,newOffset);var offset=convertI32PairToI53Checked(offset_low,offset_high);try{if(isNaN(offset))return 61;var stream=SYSCALLS.getStreamFromFD(fd);FS.llseek(stream,offset,whence);tempI64=[stream.position>>>0,(tempDouble=stream.position,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],GROWABLE_HEAP_I32()[newOffset>>2]=tempI64[0],GROWABLE_HEAP_I32()[newOffset+4>>2]=tempI64[1];if(stream.getdents&&offset===0&&whence===0)stream.getdents=null;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var doWritev=(stream,iov,iovcnt,offset)=>{var ret=0;for(var i=0;i<iovcnt;i++){var ptr=GROWABLE_HEAP_U32()[iov>>2];var len=GROWABLE_HEAP_U32()[iov+4>>2];iov+=8;var curr=FS.write(stream,GROWABLE_HEAP_I8(),ptr,len,offset);if(curr<0)return-1;ret+=curr;if(typeof offset!=="undefined"){offset+=curr}}return ret};function _fd_write(fd,iov,iovcnt,pnum){if(ENVIRONMENT_IS_PTHREAD)return proxyToMainThread(11,1,fd,iov,iovcnt,pnum);try{var stream=SYSCALLS.getStreamFromFD(fd);var num=doWritev(stream,iov,iovcnt);GROWABLE_HEAP_U32()[pnum>>2]=num;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var isLeapYear=year=>year%4===0&&(year%100!==0||year%400===0);var arraySum=(array,index)=>{var sum=0;for(var i=0;i<=index;sum+=array[i++]){}return sum};var MONTH_DAYS_LEAP=[31,29,31,30,31,30,31,31,30,31,30,31];var MONTH_DAYS_REGULAR=[31,28,31,30,31,30,31,31,30,31,30,31];var addDays=(date,days)=>{var newDate=new Date(date.getTime());while(days>0){var leap=isLeapYear(newDate.getFullYear());var currentMonth=newDate.getMonth();var daysInCurrentMonth=(leap?MONTH_DAYS_LEAP:MONTH_DAYS_REGULAR)[currentMonth];if(days>daysInCurrentMonth-newDate.getDate()){days-=daysInCurrentMonth-newDate.getDate()+1;newDate.setDate(1);if(currentMonth<11){newDate.setMonth(currentMonth+1)}else{newDate.setMonth(0);newDate.setFullYear(newDate.getFullYear()+1)}}else{newDate.setDate(newDate.getDate()+days);return newDate}}return newDate};var writeArrayToMemory=(array,buffer)=>{GROWABLE_HEAP_I8().set(array,buffer)};var _strftime=(s,maxsize,format,tm)=>{var tm_zone=GROWABLE_HEAP_U32()[tm+40>>2];var date={tm_sec:GROWABLE_HEAP_I32()[tm>>2],tm_min:GROWABLE_HEAP_I32()[tm+4>>2],tm_hour:GROWABLE_HEAP_I32()[tm+8>>2],tm_mday:GROWABLE_HEAP_I32()[tm+12>>2],tm_mon:GROWABLE_HEAP_I32()[tm+16>>2],tm_year:GROWABLE_HEAP_I32()[tm+20>>2],tm_wday:GROWABLE_HEAP_I32()[tm+24>>2],tm_yday:GROWABLE_HEAP_I32()[tm+28>>2],tm_isdst:GROWABLE_HEAP_I32()[tm+32>>2],tm_gmtoff:GROWABLE_HEAP_I32()[tm+36>>2],tm_zone:tm_zone?UTF8ToString(tm_zone):""};var pattern=UTF8ToString(format);var EXPANSION_RULES_1={"%c":"%a %b %d %H:%M:%S %Y","%D":"%m/%d/%y","%F":"%Y-%m-%d","%h":"%b","%r":"%I:%M:%S %p","%R":"%H:%M","%T":"%H:%M:%S","%x":"%m/%d/%y","%X":"%H:%M:%S","%Ec":"%c","%EC":"%C","%Ex":"%m/%d/%y","%EX":"%H:%M:%S","%Ey":"%y","%EY":"%Y","%Od":"%d","%Oe":"%e","%OH":"%H","%OI":"%I","%Om":"%m","%OM":"%M","%OS":"%S","%Ou":"%u","%OU":"%U","%OV":"%V","%Ow":"%w","%OW":"%W","%Oy":"%y"};for(var rule in EXPANSION_RULES_1){pattern=pattern.replace(new RegExp(rule,"g"),EXPANSION_RULES_1[rule])}var WEEKDAYS=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];var MONTHS=["January","February","March","April","May","June","July","August","September","October","November","December"];function leadingSomething(value,digits,character){var str=typeof value=="number"?value.toString():value||"";while(str.length<digits){str=character[0]+str}return str}function leadingNulls(value,digits){return leadingSomething(value,digits,"0")}function compareByDay(date1,date2){function sgn(value){return value<0?-1:value>0?1:0}var compare;if((compare=sgn(date1.getFullYear()-date2.getFullYear()))===0){if((compare=sgn(date1.getMonth()-date2.getMonth()))===0){compare=sgn(date1.getDate()-date2.getDate())}}return compare}function getFirstWeekStartDate(janFourth){switch(janFourth.getDay()){case 0:return new Date(janFourth.getFullYear()-1,11,29);case 1:return janFourth;case 2:return new Date(janFourth.getFullYear(),0,3);case 3:return new Date(janFourth.getFullYear(),0,2);case 4:return new Date(janFourth.getFullYear(),0,1);case 5:return new Date(janFourth.getFullYear()-1,11,31);case 6:return new Date(janFourth.getFullYear()-1,11,30)}}function getWeekBasedYear(date){var thisDate=addDays(new Date(date.tm_year+1900,0,1),date.tm_yday);var janFourthThisYear=new Date(thisDate.getFullYear(),0,4);var janFourthNextYear=new Date(thisDate.getFullYear()+1,0,4);var firstWeekStartThisYear=getFirstWeekStartDate(janFourthThisYear);var firstWeekStartNextYear=getFirstWeekStartDate(janFourthNextYear);if(compareByDay(firstWeekStartThisYear,thisDate)<=0){if(compareByDay(firstWeekStartNextYear,thisDate)<=0){return thisDate.getFullYear()+1}return thisDate.getFullYear()}return thisDate.getFullYear()-1}var EXPANSION_RULES_2={"%a":date=>WEEKDAYS[date.tm_wday].substring(0,3),"%A":date=>WEEKDAYS[date.tm_wday],"%b":date=>MONTHS[date.tm_mon].substring(0,3),"%B":date=>MONTHS[date.tm_mon],"%C":date=>{var year=date.tm_year+1900;return leadingNulls(year/100|0,2)},"%d":date=>leadingNulls(date.tm_mday,2),"%e":date=>leadingSomething(date.tm_mday,2," "),"%g":date=>getWeekBasedYear(date).toString().substring(2),"%G":date=>getWeekBasedYear(date),"%H":date=>leadingNulls(date.tm_hour,2),"%I":date=>{var twelveHour=date.tm_hour;if(twelveHour==0)twelveHour=12;else if(twelveHour>12)twelveHour-=12;return leadingNulls(twelveHour,2)},"%j":date=>leadingNulls(date.tm_mday+arraySum(isLeapYear(date.tm_year+1900)?MONTH_DAYS_LEAP:MONTH_DAYS_REGULAR,date.tm_mon-1),3),"%m":date=>leadingNulls(date.tm_mon+1,2),"%M":date=>leadingNulls(date.tm_min,2),"%n":()=>"\n","%p":date=>{if(date.tm_hour>=0&&date.tm_hour<12){return"AM"}return"PM"},"%S":date=>leadingNulls(date.tm_sec,2),"%t":()=>"\t","%u":date=>date.tm_wday||7,"%U":date=>{var days=date.tm_yday+7-date.tm_wday;return leadingNulls(Math.floor(days/7),2)},"%V":date=>{var val=Math.floor((date.tm_yday+7-(date.tm_wday+6)%7)/7);if((date.tm_wday+371-date.tm_yday-2)%7<=2){val++}if(!val){val=52;var dec31=(date.tm_wday+7-date.tm_yday-1)%7;if(dec31==4||dec31==5&&isLeapYear(date.tm_year%400-1)){val++}}else if(val==53){var jan1=(date.tm_wday+371-date.tm_yday)%7;if(jan1!=4&&(jan1!=3||!isLeapYear(date.tm_year)))val=1}return leadingNulls(val,2)},"%w":date=>date.tm_wday,"%W":date=>{var days=date.tm_yday+7-(date.tm_wday+6)%7;return leadingNulls(Math.floor(days/7),2)},"%y":date=>(date.tm_year+1900).toString().substring(2),"%Y":date=>date.tm_year+1900,"%z":date=>{var off=date.tm_gmtoff;var ahead=off>=0;off=Math.abs(off)/60;off=off/60*100+off%60;return(ahead?"+":"-")+String("0000"+off).slice(-4)},"%Z":date=>date.tm_zone,"%%":()=>"%"};pattern=pattern.replace(/%%/g,"\0\0");for(var rule in EXPANSION_RULES_2){if(pattern.includes(rule)){pattern=pattern.replace(new RegExp(rule,"g"),EXPANSION_RULES_2[rule](date))}}pattern=pattern.replace(/\0\0/g,"%");var bytes=intArrayFromString(pattern,false);if(bytes.length>maxsize){return 0}writeArrayToMemory(bytes,s);return bytes.length-1};var _strftime_l=(s,maxsize,format,tm,loc)=>_strftime(s,maxsize,format,tm);PThread.init();var FSNode=function(parent,name,mode,rdev){if(!parent){parent=this}this.parent=parent;this.mount=parent.mount;this.mounted=null;this.id=FS.nextInode++;this.name=name;this.mode=mode;this.node_ops={};this.stream_ops={};this.rdev=rdev};var readMode=292|73;var writeMode=146;Object.defineProperties(FSNode.prototype,{read:{get:function(){return(this.mode&readMode)===readMode},set:function(val){val?this.mode|=readMode:this.mode&=~readMode}},write:{get:function(){return(this.mode&writeMode)===writeMode},set:function(val){val?this.mode|=writeMode:this.mode&=~writeMode}},isFolder:{get:function(){return FS.isDir(this.mode)}},isDevice:{get:function(){return FS.isChrdev(this.mode)}}});FS.FSNode=FSNode;FS.createPreloadedFile=FS_createPreloadedFile;FS.staticInit();Module["FS_createPath"]=FS.createPath;Module["FS_createDataFile"]=FS.createDataFile;Module["FS_createPreloadedFile"]=FS.createPreloadedFile;Module["FS_unlink"]=FS.unlink;Module["FS_createLazyFile"]=FS.createLazyFile;Module["FS_createDevice"]=FS.createDevice;embind_init_charCodes();BindingError=Module["BindingError"]=class BindingError extends Error{constructor(message){super(message);this.name="BindingError"}};InternalError=Module["InternalError"]=class InternalError extends Error{constructor(message){super(message);this.name="InternalError"}};handleAllocatorInit();init_emval();UnboundTypeError=Module["UnboundTypeError"]=extendError(Error,"UnboundTypeError");var proxiedFunctionTable=[_proc_exit,exitOnMainThread,pthreadCreateProxied,___syscall_fcntl64,___syscall_ioctl,___syscall_openat,_environ_get,_environ_sizes_get,_fd_close,_fd_read,_fd_seek,_fd_write];var wasmImports={d:___cxa_throw,J:___emscripten_init_main_thread_js,m:___emscripten_thread_cleanup,G:___pthread_create_js,q:___syscall_fcntl64,L:___syscall_ioctl,M:___syscall_openat,y:__embind_register_bigint,R:__embind_register_bool,Q:__embind_register_emval,s:__embind_register_float,h:__embind_register_function,g:__embind_register_integer,c:__embind_register_memory_view,r:__embind_register_std_string,k:__embind_register_std_wstring,S:__embind_register_void,P:__emscripten_get_now_is_monotonic,F:__emscripten_notify_mailbox_postmessage,H:__emscripten_receive_on_main_thread_js,I:__emscripten_thread_mailbox_await,O:__emscripten_thread_set_strongref,w:__emval_as,U:__emval_call_void_method,f:__emval_decref,V:__emval_get_method_caller,u:__emval_get_module_property,i:__emval_get_property,l:__emval_incref,t:__emval_new,j:__emval_new_cstring,v:__emval_run_destructors,b:_abort,n:_emscripten_check_blocking_allowed,N:_emscripten_exit_with_live_runtime,z:_emscripten_get_heap_max,e:_emscripten_get_now,A:_emscripten_num_logical_cores,E:_emscripten_resize_heap,C:_environ_get,D:_environ_sizes_get,T:_exit,o:_fd_close,K:_fd_read,x:_fd_seek,p:_fd_write,a:wasmMemory||Module["wasmMemory"],B:_strftime_l};var wasmExports=createWasm();var ___wasm_call_ctors=()=>(___wasm_call_ctors=wasmExports["W"])();var _free=a0=>(_free=wasmExports["Y"])(a0);var _malloc=a0=>(_malloc=wasmExports["Z"])(a0);var __emscripten_tls_init=Module["__emscripten_tls_init"]=()=>(__emscripten_tls_init=Module["__emscripten_tls_init"]=wasmExports["_"])();var _pthread_self=Module["_pthread_self"]=()=>(_pthread_self=Module["_pthread_self"]=wasmExports["$"])();var ___getTypeName=a0=>(___getTypeName=wasmExports["aa"])(a0);var __embind_initialize_bindings=Module["__embind_initialize_bindings"]=()=>(__embind_initialize_bindings=Module["__embind_initialize_bindings"]=wasmExports["ba"])();var ___errno_location=()=>(___errno_location=wasmExports["ca"])();var __emscripten_thread_init=Module["__emscripten_thread_init"]=(a0,a1,a2,a3,a4,a5)=>(__emscripten_thread_init=Module["__emscripten_thread_init"]=wasmExports["da"])(a0,a1,a2,a3,a4,a5);var __emscripten_thread_crashed=Module["__emscripten_thread_crashed"]=()=>(__emscripten_thread_crashed=Module["__emscripten_thread_crashed"]=wasmExports["ea"])();var _emscripten_main_thread_process_queued_calls=()=>(_emscripten_main_thread_process_queued_calls=wasmExports["emscripten_main_thread_process_queued_calls"])();var _emscripten_main_runtime_thread_id=()=>(_emscripten_main_runtime_thread_id=wasmExports["emscripten_main_runtime_thread_id"])();var __emscripten_run_on_main_thread_js=(a0,a1,a2,a3)=>(__emscripten_run_on_main_thread_js=wasmExports["fa"])(a0,a1,a2,a3);var __emscripten_thread_free_data=a0=>(__emscripten_thread_free_data=wasmExports["ga"])(a0);var __emscripten_thread_exit=Module["__emscripten_thread_exit"]=a0=>(__emscripten_thread_exit=Module["__emscripten_thread_exit"]=wasmExports["ha"])(a0);var __emscripten_check_mailbox=Module["__emscripten_check_mailbox"]=()=>(__emscripten_check_mailbox=Module["__emscripten_check_mailbox"]=wasmExports["ia"])();var _emscripten_stack_set_limits=(a0,a1)=>(_emscripten_stack_set_limits=wasmExports["ja"])(a0,a1);var stackSave=()=>(stackSave=wasmExports["ka"])();var stackRestore=a0=>(stackRestore=wasmExports["la"])(a0);var stackAlloc=a0=>(stackAlloc=wasmExports["ma"])(a0);var ___cxa_is_pointer_type=a0=>(___cxa_is_pointer_type=wasmExports["na"])(a0);var dynCall_jiji=Module["dynCall_jiji"]=(a0,a1,a2,a3,a4)=>(dynCall_jiji=Module["dynCall_jiji"]=wasmExports["oa"])(a0,a1,a2,a3,a4);var dynCall_viijii=Module["dynCall_viijii"]=(a0,a1,a2,a3,a4,a5,a6)=>(dynCall_viijii=Module["dynCall_viijii"]=wasmExports["pa"])(a0,a1,a2,a3,a4,a5,a6);var dynCall_iiiiij=Module["dynCall_iiiiij"]=(a0,a1,a2,a3,a4,a5,a6)=>(dynCall_iiiiij=Module["dynCall_iiiiij"]=wasmExports["qa"])(a0,a1,a2,a3,a4,a5,a6);var dynCall_iiiiijj=Module["dynCall_iiiiijj"]=(a0,a1,a2,a3,a4,a5,a6,a7,a8)=>(dynCall_iiiiijj=Module["dynCall_iiiiijj"]=wasmExports["ra"])(a0,a1,a2,a3,a4,a5,a6,a7,a8);var dynCall_iiiiiijj=Module["dynCall_iiiiiijj"]=(a0,a1,a2,a3,a4,a5,a6,a7,a8,a9)=>(dynCall_iiiiiijj=Module["dynCall_iiiiiijj"]=wasmExports["sa"])(a0,a1,a2,a3,a4,a5,a6,a7,a8,a9);function intArrayFromBase64(s){if(typeof ENVIRONMENT_IS_NODE!="undefined"&&ENVIRONMENT_IS_NODE){var buf=Buffer.from(s,"base64");return new Uint8Array(buf.buffer,buf.byteOffset,buf.length)}try{var decoded=atob(s);var bytes=new Uint8Array(decoded.length);for(var i=0;i<decoded.length;++i){bytes[i]=decoded.charCodeAt(i)}return bytes}catch(_){throw new Error("Converting base64 string to bytes failed.")}}function tryParseAsDataURI(filename){if(!isDataURI(filename)){return}return intArrayFromBase64(filename.slice(dataURIPrefix.length))}Module["addRunDependency"]=addRunDependency;Module["removeRunDependency"]=removeRunDependency;Module["FS_createPath"]=FS.createPath;Module["FS_createDataFile"]=FS.createDataFile;Module["FS_createLazyFile"]=FS.createLazyFile;Module["FS_createDevice"]=FS.createDevice;Module["FS_unlink"]=FS.unlink;Module["keepRuntimeAlive"]=keepRuntimeAlive;Module["wasmMemory"]=wasmMemory;Module["ExitStatus"]=ExitStatus;Module["FS_createPreloadedFile"]=FS.createPreloadedFile;Module["PThread"]=PThread;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);if(Module["onRuntimeInitialized"])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(); + + + return moduleArg.ready +} + +); +})(); +if (typeof exports === 'object' && typeof module === 'object') + module.exports = whisper_factory; +else if (typeof define === 'function' && define['amd']) + define([], () => whisper_factory); diff --git a/bindings/ruby/.document b/bindings/ruby/.document new file mode 100644 index 0000000..a8e9788 --- /dev/null +++ b/bindings/ruby/.document @@ -0,0 +1,3 @@ +README.md +LICENSE +sig diff --git a/bindings/ruby/.gitignore b/bindings/ruby/.gitignore new file mode 100644 index 0000000..54e3a2a --- /dev/null +++ b/bindings/ruby/.gitignore @@ -0,0 +1,9 @@ +LICENSE +pkg/ +lib/whisper.* +ext/examples/ +ext/ggml/ +ext/include/ +ext/scripts/ +ext/src/ +test/fixtures/ diff --git a/bindings/ruby/.rdoc_options b/bindings/ruby/.rdoc_options new file mode 100644 index 0000000..cf14aa5 --- /dev/null +++ b/bindings/ruby/.rdoc_options @@ -0,0 +1,2 @@ +title: whispercpp +main_page: README.md diff --git a/bindings/ruby/CHANGELOG.md b/bindings/ruby/CHANGELOG.md new file mode 100644 index 0000000..8f7d239 --- /dev/null +++ b/bindings/ruby/CHANGELOG.md @@ -0,0 +1,169 @@ +# Changelog + +## [1.3.9] - Unreleased + +Bundled whisper.cpp: `1.9.3` + +- Fixed test fixture JFKReader's format string. +- Add #free method to `Whisper::Context`, `Whisper::VAD::Context` and `Whisper::Parakeet::Context`. +- Checked MemoryView format more strictly. + +## [1.3.8] - 2026-07-28 + +Bundled whisper.cpp: `1.9.1` + +- Added `Whisper::Context#full_n_vad_segments`, + `#full_get_vad_segment_t0`, and `#full_get_vad_segment_t1` for reading the + speech segments produced by VAD-enabled transcription. +- Changed standalone VAD processing to release Ruby's Global VM Lock. +- Fixed VAD parameter ownership and type handling, compatibility with older + CMake option syntax, and model cache lookup behavior. + ([#3931](https://github.com/ggml-org/whisper.cpp/pull/3931)) + +## [1.3.7] - 2026-06-17 + +Bundled whisper.cpp: `1.9.0` + +- Added Ruby bindings for NVIDIA Parakeet, including models, contexts, + parameters, segments, tokens, callbacks, and shared output helpers. + ([#3885](https://github.com/ggml-org/whisper.cpp/pull/3885)) +- Added Windows build support and support for additional Ruby MemoryView + inputs, and changed transcription to release Ruby's Global VM Lock. + ([#3775](https://github.com/ggml-org/whisper.cpp/pull/3775)) +- Fixed dangling pointers, a memory leak, and a segmentation fault during + parallel transcription. + ([#3715](https://github.com/ggml-org/whisper.cpp/pull/3715)) +- Raised the minimum supported Ruby version from 3.1 to 3.3. + +## [1.3.6] - 2026-03-19 + +Bundled whisper.cpp: `1.8.4` + +- Added the low-level `Whisper::VAD::Context#segments_from_samples` API and + accepted `Pathname`-compatible model and audio paths. + ([#3633](https://github.com/ggml-org/whisper.cpp/pull/3633)) +- Added `Whisper::Context::Params` for configuring context initialization and + fixed token memory ownership. + ([#3647](https://github.com/ggml-org/whisper.cpp/pull/3647)) +- Added a missing context null check. + ([#3689](https://github.com/ggml-org/whisper.cpp/pull/3689)) + +## [1.3.5] - 2026-01-16 + +Bundled whisper.cpp: `1.8.3` + +- Added standalone voice activity detection through + `Whisper::VAD::Context`, `Whisper::VAD::Segments`, and + `Whisper::VAD::Segment`. + ([#3518](https://github.com/ggml-org/whisper.cpp/pull/3518)) +- Updated the packaged Silero VAD model support to v6.2.0. + ([#3524](https://github.com/ggml-org/whisper.cpp/pull/3524)) +- Added `Whisper::Token` and corrected model URI handling. + ([#3575](https://github.com/ggml-org/whisper.cpp/pull/3575)) +- Fixed segmentation faults in token and segment access. + ([#3591](https://github.com/ggml-org/whisper.cpp/pull/3591)) + +## [1.3.4] - 2025-10-08 + +Bundled whisper.cpp: `1.8.0` + +- Added `Whisper::Params#max_len`. + ([#3365](https://github.com/ggml-org/whisper.cpp/pull/3365)) +- Fixed negative model-download padding values and made installation tests less + sensitive to output formatting. + ([#3389](https://github.com/ggml-org/whisper.cpp/pull/3389), + [#3448](https://github.com/ggml-org/whisper.cpp/pull/3448)) + +## [1.3.3] - 2025-07-12 + +Bundled whisper.cpp: `1.7.6` + +- Added Core ML build support. + ([#3214](https://github.com/ggml-org/whisper.cpp/pull/3214)) +- Added parallel transcription through `Whisper::Context#full_parallel`. + ([#3222](https://github.com/ggml-org/whisper.cpp/pull/3222)) +- Added higher-level segment iteration and text, SRT, VTT, CSV, and JSON output + helpers. + ([#3237](https://github.com/ggml-org/whisper.cpp/pull/3237)) +- Added `Whisper::VERSION`. + ([#3292](https://github.com/ggml-org/whisper.cpp/pull/3292)) +- Improved install-time build option handling and Apple framework linkage. + ([#3206](https://github.com/ggml-org/whisper.cpp/pull/3206), + [#3270](https://github.com/ggml-org/whisper.cpp/pull/3270)) + +## [1.3.2] - 2025-05-28 + +Bundled whisper.cpp: `1.7.5` + +- Added VAD-enabled transcription and `Whisper::VAD::Params`. + ([#3197](https://github.com/ggml-org/whisper.cpp/pull/3197)) +- Moved native extension builds to CMake and added install-time CMake build + options. + ([#3043](https://github.com/ggml-org/whisper.cpp/pull/3043), + [#3056](https://github.com/ggml-org/whisper.cpp/pull/3056)) +- Added encoder-begin callback APIs and refined model download caching. + ([#3076](https://github.com/ggml-org/whisper.cpp/pull/3076), + [#3109](https://github.com/ggml-org/whisper.cpp/pull/3109)) +- Expanded context initialization and segment retrieval APIs. + ([#2749](https://github.com/ggml-org/whisper.cpp/pull/2749)) + +## [1.3.1] - 2024-12-20 + +Bundled whisper.cpp: `1.7.3` + +- Added Metal build support and new-segment callbacks. + ([#2516](https://github.com/ggml-org/whisper.cpp/pull/2516), + [#2506](https://github.com/ggml-org/whisper.cpp/pull/2506)) +- Expanded context, model, parameter, and segment APIs, including low-level + transcription methods. + ([#2518](https://github.com/ggml-org/whisper.cpp/pull/2518), + [#2551](https://github.com/ggml-org/whisper.cpp/pull/2551), + [#2585](https://github.com/ggml-org/whisper.cpp/pull/2585)) +- Added model download support and `no_speech_thold`. + ([#2617](https://github.com/ggml-org/whisper.cpp/pull/2617), + [#2641](https://github.com/ggml-org/whisper.cpp/pull/2641)) + +## [1.3.0] - 2024-05-16 + +Bundled whisper.cpp: `1.5.5`-era source snapshot + +- Refreshed the packaged whisper.cpp and ggml sources for the newer backend + architecture. +- Updated the native extension for upstream context initialization changes and + fixed builds against the newer source layout. +- Expanded the Rake packaging and test tasks used to produce the gem. + +## [1.2.0.2] - 2023-02-27 + +Bundled whisper.cpp: `1.2.0`-era source snapshot + +- Added Rake build, clean, package, and test tasks. +- Changed long-running transcription to run without Ruby's Global VM Lock and + added interruption handling. + +## [1.2.0.1] - 2023-02-25 + +Bundled whisper.cpp: `1.2.0`-era source snapshot + +- Fixed gem packaging so `LICENSE` and `README.md` were included at valid + in-package paths. + +## [1.2.0] - 2023-02-25 + +Bundled whisper.cpp: `1.2.0`-era source snapshot + +- First published `whispercpp` Ruby gem, based on the initial Ruby binding. + ([#500](https://github.com/ggml-org/whisper.cpp/pull/500)) + +[1.3.8]: https://rubygems.org/gems/whispercpp/versions/1.3.8 +[1.3.7]: https://rubygems.org/gems/whispercpp/versions/1.3.7 +[1.3.6]: https://rubygems.org/gems/whispercpp/versions/1.3.6 +[1.3.5]: https://rubygems.org/gems/whispercpp/versions/1.3.5 +[1.3.4]: https://rubygems.org/gems/whispercpp/versions/1.3.4 +[1.3.3]: https://rubygems.org/gems/whispercpp/versions/1.3.3 +[1.3.2]: https://rubygems.org/gems/whispercpp/versions/1.3.2 +[1.3.1]: https://rubygems.org/gems/whispercpp/versions/1.3.1 +[1.3.0]: https://rubygems.org/gems/whispercpp/versions/1.3.0 +[1.2.0.2]: https://rubygems.org/gems/whispercpp/versions/1.2.0.2 +[1.2.0.1]: https://rubygems.org/gems/whispercpp/versions/1.2.0.1 +[1.2.0]: https://rubygems.org/gems/whispercpp/versions/1.2.0 diff --git a/bindings/ruby/README.md b/bindings/ruby/README.md new file mode 100644 index 0000000..67a9ec3 --- /dev/null +++ b/bindings/ruby/README.md @@ -0,0 +1,497 @@ +whispercpp +========== + +![whisper.cpp](https://user-images.githubusercontent.com/1991296/235238348-05d0f6a4-da44-4900-a1de-d0707e75b763.jpeg) + +Ruby bindings for [whisper.cpp][], an interface of automatic speech recognition model. + +Usage +----- + +```ruby +require "whisper" + +whisper = Whisper::Context.new("base") + +params = Whisper::Params.new( + language: "en", + offset: 10_000, + duration: 60_000, + max_text_tokens: 300, + translate: true, + print_timestamps: false, + initial_prompt: "Initial prompt here.", + carry_initial_prompt: true +) + +whisper.transcribe("path/to/audio.wav", params) do |whole_text| + puts whole_text +end + +``` + +### Preparing model ### + +Some models are prepared up-front: + +You also can use shorthand for pre-converted models: + +```ruby +whisper = Whisper::Context.new("base.en") +``` + +You can see the list of prepared model names by `Whisper::Model.pre_converted_models.keys`: + +```ruby +puts Whisper::Model.pre_converted_models.keys +# tiny +# tiny.en +# tiny-q5_1 +# tiny.en-q5_1 +# tiny-q8_0 +# base +# base.en +# base-q5_1 +# base.en-q5_1 +# base-q8_0 +# : +# : +``` + +You can also retrieve each model: + +```ruby +base_en = Whisper::Model.pre_converted_models["base.en"] +whisper = Whisper::Context.new(base_en) +``` + +At first time you use a model, it is downloaded automatically. After that, downloaded cached file is used. To clear cache, call `#clear_cache`: + +```ruby +Whisper::Model.pre_converted_models["base"].clear_cache +``` + +You can also use local model files you prepared: + +```ruby +whisper = Whisper::Context.new("path/to/your/model.bin") +``` + +Or, you can download model files: + +```ruby +whisper = Whisper::Context.new("https://example.net/uri/of/your/model.bin") +# Or +uri = URI("https://example.net/uri/of/your/model.bin") +whisper = Whisper::Context.new(uri) +``` + +See [models][] page for details. + +### Preparing audio file ### + +Currently, whisper.cpp accepts only 16-bit WAV files. + +### Voice Activity Detection (VAD) ### + +Support for Voice Activity Detection (VAD) can be enabled by setting `Whisper::Params`'s `vad` argument to `true` and specifying VAD model: + +```ruby +Whisper::Params.new( + vad: true, + vad_model_path: "silero-v6.2.0", + # other arguments... +) +``` + +When you pass the model name (`"silero-v6.2.0"`) or URI (`https://huggingface.co/ggml-org/whisper-vad/resolve/main/ggml-silero-v6.2.0.bin`), it will be downloaded automatically. +Currently, "silero-v6.2.0" is registered as pre-converted model like ASR models. You also specify file path or URI of model. + +If you need configure VAD behavior, pass params for that: + +```ruby +Whisper::Params.new( + vad: true, + vad_model_path: "silero-v6.2.0", + vad_params: Whisper::VAD::Params.new( + threshold: 1.0, # defaults to 0.5 + min_speech_duration_ms: 500, # defaults to 250 + min_silence_duration_ms: 200, # defaults to 100 + max_speech_duration_s: 30000.0, # default is FLT_MAX, + speech_pad_ms: 50, # defaults to 30 + samples_overlap: 0.5 # defaults to 0.1 + ), + # other arguments... +) +``` + +For details on VAD, see [whisper.cpp's README](https://github.com/ggml-org/whisper.cpp?tab=readme-ov-file#voice-activity-detection-vad). + +### Output ### + +whispercpp supports SRT and WebVTT output: + +```ruby +puts whisper.transcribe("path/to/audio.wav", Whisper::Params.new).to_webvtt +# => +WEBVTT + +1 +00:00:00.000 --> 00:00:03.860 + My thought I have nobody by a beauty and will as you poured. + +2 +00:00:03.860 --> 00:00:09.840 + Mr. Rochester is sub in that so-don't find simplest, and devoted about, to let might in + +3 +00:00:09.840 --> 00:00:09.940 + a + +``` + +You may call `#to_srt`, too + +Installation +------------ + +Install the gem and add to the application's Gemfile by executing: + + $ bundle add whispercpp + +If bundler is not being used to manage dependencies, install the gem by executing: + + $ gem install whispercpp + +You can pass build options for whisper.cpp, for instance: + + $ bundle config build.whispercpp --enable-ggml-cuda + +or, + + $ gem install whispercpp -- --enable-ggml-cuda + +See whisper.cpp's [README](https://github.com/ggml-org/whisper.cpp/blob/master/README.md) for available options. You need convert options present in the README to Ruby-style options, for example: + +Boolean options: + +* `-DGGML_BLAS=1` -> `--enable-ggml-blas` +* `-DWHISPER_COREML=OFF` -> `--disable-whisper-coreml` + +Argument options: + +* `-DGGML_CUDA_COMPRESSION_MODE=size` -> `--ggml-cuda-compression-mode=size` + +Combination: + +* `-DGGML_CUDA=1 -DCMAKE_CUDA_ARCHITECTURES="86"` -> `--enable-ggml-cuda --cmake-cuda-architectures="86"` + +For boolean options like `GGML_CUDA`, the README says `-DGGML_CUDA=1`. You need strip `-D`, prepend `--enable-` for `1` or `ON` (`--disable-` for `0` or `OFF`) and make it kebab-case: `--enable-ggml-cuda`. +For options which require arguments like `CMAKE_CUDA_ARCHITECTURES`, the README says `-DCMAKE_CUDA_ARCHITECTURES="86"`. You need strip `-D`, prepend `--`, make it kebab-case, append `=` and append argument: `--cmake-cuda-architectures="86"`. + +API +--- + +### Transcription ### + +By default, `Whisper::Context#transcribe` works in a single thread. You can make it work in parallel by passing `n_processors` option: + +```ruby +whisper.transcribe("path/to/audio.wav", params, n_processors: Etc.nprocessors) +``` + +Note that transcription occasionally might be low accuracy when it works in parallel. + +If n_processors is greater than 1, you cannot set some callbacks including encoder_begin_callback, abort_callback. Also, progress_callback is ignored even if it's set. + +### Segments ### + +Once `Whisper::Context#transcribe` called, you can retrieve segments by `#each_segment`: + +```ruby +def format_time(time_ms) + sec, decimal_part = time_ms.divmod(1000) + min, sec = sec.divmod(60) + hour, min = min.divmod(60) + "%02d:%02d:%02d.%03d" % [hour, min, sec, decimal_part] +end + +whisper + .transcribe("path/to/audio.wav", params) + .each_segment.with_index do |segment, index| + line = "[%{nth}: %{st} --> %{ed}] %{text}" % { + nth: index + 1, + st: format_time(segment.start_time), + ed: format_time(segment.end_time), + text: segment.text + } + line << " (speaker turned)" if segment.speaker_turn_next? + puts line + end + +``` + +You can also add hook to params called on new segment: + +```ruby +# Add hook before calling #transcribe +params.on_new_segment do |segment| + line = "[%{st} --> %{ed}] %{text}" % { + st: format_time(segment.start_time), + ed: format_time(segment.end_time), + text: segment.text + } + line << " (speaker turned)" if segment.speaker_turn_next? + puts line +end + +whisper.transcribe("path/to/audio.wav", params) + +``` + +### Tokens ### + +Each segment has tokens. + +To enable token timestamps, you need to set `Whisper::Params#token_timestamps = true`. Then, retrieve tokens from segments using `Whisper::Segment#each_token`. + +```ruby +whisper = Whisper::Context.new("base.en") +params = Whisper::Params.new(token_timestamps: true) +whisper + .transcribe("path/to/audio.wav", params) + .each_segment do |segment| + segment.each_token do |token| + token => {start_time:, end_time:, text:, probability:} + st = "%05.2fs" % (start_time / 1000.0) + et = "%05.2fs" % (end_time / 1000.0) + prob = "%.1f%%" % (probability * 100) + puts "[#{st} --> #{et}] #{text} (#{prob})" + end + end +``` + +``` +[00.00s --> 00.00s] [_BEG_] (84.2%) +[00.32s --> 00.37s] And (71.2%) +[00.37s --> 00.53s] so (98.5%) +[00.69s --> 00.85s] my (70.7%) +[00.85s --> 01.59s] fellow (99.5%) +[01.59s --> 02.10s] Americans (90.1%) +[02.85s --> 03.30s] , (28.4%) +[03.30s --> 04.14s] ask (79.8%) +[04.14s --> 04.28s] not (78.9%) +[05.03s --> 05.35s] what (93.3%) +[05.41s --> 05.74s] your (98.8%) +[05.74s --> 06.41s] country (99.6%) +[06.41s --> 06.74s] can (97.7%) +[06.74s --> 06.92s] do (99.0%) +[07.00s --> 07.00s] for (95.8%) +[07.01s --> 07.52s] you (98.5%) +[07.81s --> 08.05s] , (49.3%) +[08.19s --> 08.37s] ask (65.6%) +[08.37s --> 08.75s] what (98.8%) +[08.91s --> 09.04s] you (98.2%) +[09.04s --> 09.32s] can (96.9%) +[09.32s --> 09.38s] do (90.3%) +[09.44s --> 09.76s] for (91.8%) +[09.76s --> 09.99s] your (98.2%) +[10.02s --> 10.36s] country (99.6%) +[10.51s --> 10.99s] . (87.0%) +[11.00s --> 11.00s] [_TT_550] (7.6%) +``` + +### Models ### + +You can see model information: + +```ruby +whisper = Whisper::Context.new("base") +model = whisper.model + +model.n_vocab # => 51864 +model.n_audio_ctx # => 1500 +model.n_audio_state # => 512 +model.n_audio_head # => 8 +model.n_audio_layer # => 6 +model.n_text_ctx # => 448 +model.n_text_state # => 512 +model.n_text_head # => 8 +model.n_text_layer # => 6 +model.n_mels # => 80 +model.ftype # => 1 +model.type # => "base" + +``` + +### Logging ### + +You can set log callback: + +```ruby +prefix = "[MyApp] " +log_callback = ->(level, buffer, user_data) { + case level + when Whisper::LOG_LEVEL_NONE + puts "#{user_data}none: #{buffer}" + when Whisper::LOG_LEVEL_INFO + puts "#{user_data}info: #{buffer}" + when Whisper::LOG_LEVEL_WARN + puts "#{user_data}warn: #{buffer}" + when Whisper::LOG_LEVEL_ERROR + puts "#{user_data}error: #{buffer}" + when Whisper::LOG_LEVEL_DEBUG + puts "#{user_data}debug: #{buffer}" + when Whisper::LOG_LEVEL_CONT + puts "#{user_data}same to previous: #{buffer}" + end +} +Whisper.log_set log_callback, prefix +``` + +Using this feature, you are also able to suppress log: + +```ruby +Whisper.log_set ->(level, buffer, user_data) { + # do nothing +}, nil +Whisper::Context.new("base") +``` + +### Low-level API to transcribe ### + +You can also call `Whisper::Context#full` and `#full_parallel` with a Ruby array as samples. Although `#transcribe` with audio file path is recommended because it extracts PCM samples in C++ and is fast, `#full` and `#full_parallel` give you flexibility. Unlike `#transcribe`, these methods requires 16,000 Hz, 32-bit float audio. + +```ruby +require "whisper" +require "wavefile" + +reader = WaveFile::Reader.new("path/to/audio.wav", WaveFile::Format.new(:mono, :float, 16000)) +samples = reader.enum_for(:each_buffer).map(&:samples).flatten + +whisper = Whisper::Context.new("base") +whisper + .full(Whisper::Params.new, samples) + .each_segment do |segment| + puts segment.text + end +``` + +The second argument `samples` may be an array, an object with `length` and `each` method, or a MemoryView. + +If you can prepare audio data as C array and export it as a MemoryView, whispercpp accepts and works with it with zero copy. + +```ruby +require "torchaudio" +require "ndav/torch/tensor" +require "whisper" + +waveform, sample_rate = TorchAudio.load("test/fixtures/jfk.wav") +# Convert Torch::Tensor to NDAV +samples = waveform.squeeze.to_ndav + +whisper = Whisper::Context.new("base") +whisper + # NDAV exports MemoryView + .full(Whisper::Params.new, samples) +``` + +### Parakeet ### + +whispercpp gem now supports NVIDIA's ASR model Parakeet. + +If you want to use Parakeet instead of Whisper, the API should feel familiar. +In most cases, replace `Whisper::Context` and `Whisper::Params` with `Whisper::Parakeet::Context` and `Whisper::Parakeet::Params`, then use `#transcribe`, `#full`, `#each_segment`, and `#each_token` in the same way. + +```ruby +require "whisper" + +# It's useful to assign Whisper::Parakeet to top-level Parakeet constant unless you use Parakeet gem. +Parakeet = Whisper::Parakeet + +parakeet = Parakeet::Context.new("path/to/model") + +params = Parakeet::Params.new( + no_context: true +) + +parakeet + .transcribe("path/to/audio.wav", params) + .each_segment do |segment| + puts "[#{segment.start_time} --> #{segment.end_time}] #{segment.text}" + end +``` + +The main differences are: + +* Namespace is `Whisper::Parakeet`. +* Parakeet also supports `on_new_token` / `new_token_callback` in addition to segment and progress callbacks. + +Custom context params +--------------------- + +You can use customize `Whisper::Context`'s behavior using `Whisper::Context::Params`. + +```ruby +context_params = Whisper::Context::Params.new( + use_gpu: false, + flash_attn: false, + # etc +) +whisper = Whisper::Context.new("base", context_params) +``` + +Using VAD separately from ASR +----------------------------- + +VAD feature itself is useful. You can use it separately from ASR: + +```ruby +vad = Whisper::VAD::Context.new("silero-v6.2.0") +vad + .detect("path/to/audio.wav", Whisper::VAD::Params.new) + .each.with_index do |segment, index| + segment => {start_time: st, end_time: ed} # `Segment` responds to `#deconstruct_keys` + + puts "[%{nth}: %{st} --> %{ed}]" % {nth: index + 1, st:, ed:} + end +``` + +You may also low level API `Whisper::VAD::Context#segments_from_samples` as such `Whisper::Context#full`: + +```ruby +# Ruby Array +reader = WaveFile::Reader.new("path/to/audio.wav", WaveFile::Format.new(:mono, :float, 16000)) +samples = reader.enum_for(:each_buffer).map(&:samples).flatten + +# Or, object which exports MemoryView +waveform, sample_rate = TorchAudio.load("test/fixtures/jfk.wav") +samples = waveform.squeeze.numo.to_arrow.to_arrow_array + +segments = vad.segments_from_samples(Whisper::VAD::Params.new, samples) +``` + +Development +----------- + + % git clone https://github.com/ggml-org/whisper.cpp.git + % cd whisper.cpp/bindings/ruby + % rake test + +First call of `rake test` builds an extension and downloads a model for testing. After that, you add tests in `test` directory and modify `ext/*.{h,c,cpp}`. + +If something seems wrong on build, running `rake clean` solves some cases. + +### Need help ### + +* Windows support +* Check of compilation with various hardware +* Refinement of C/C++ code, especially memory management + +License +------- + +The same to [whisper.cpp][]. + +[whisper.cpp]: https://github.com/ggml-org/whisper.cpp +[models]: https://github.com/ggml-org/whisper.cpp/tree/master/models diff --git a/bindings/ruby/Rakefile b/bindings/ruby/Rakefile new file mode 100644 index 0000000..2327651 --- /dev/null +++ b/bindings/ruby/Rakefile @@ -0,0 +1,111 @@ +require 'rake/clean' +require "bundler/gem_tasks" +require "rake/testtask" +require_relative "extsources" + +SOURCES_DIR = "ext/sources" + +SOURCES = FileList[] + +EXTSOURCES.each do |src| + basename = src.pathmap("%f") + dest = basename == "LICENSE" ? basename + : src.pathmap("%{\\.\\./\\.\\.,#{SOURCES_DIR}}p") + .pathmap("%{\\.\\./javascript,#{SOURCES_DIR}/bindings/javascript}p") + dir = dest.pathmap("%d") + file src + directory dir + file dest => [src, dir] do |t| + copy t.source, t.name + end + SOURCES.include dest +end + +CLEAN.include SOURCES + +SRC = FileList["ext/*.{c,cpp,h}"] + +task build: SOURCES + +directory "pkg" +CLOBBER.include "pkg" + +LIB_NAME = "whisper".ext(RbConfig::CONFIG["DLEXT"]) +SO_FILE = File.join("ext", LIB_NAME) +LIB_FILE = File.join("lib", LIB_NAME) + +file "ext/Makefile" => SRC + SOURCES + FileList["ext/*.rb"] do |t| + chdir "ext" do + ruby "extconf.rb" + end +end +if File.exist? "ext/Makefile" + task :make_clean do + cd "ext" do + sh "make", "clean" + end + end + task clean: :make_clean + task :make_distclean do + cd "ext" do + sh "make", "distclean" + end + end + task clobber: :make_distclean +end + +file SO_FILE => "ext/Makefile" do |t| + chdir "ext" do + sh "make" + end +end +CLEAN.include SO_FILE + +directory "lib" +file LIB_FILE => [SO_FILE, "lib"] do |t| + copy t.source, t.name +end +CLEAN.include LIB_FILE + +Rake::TestTask.new + +TEST_FIXTURE_AUDIO = "test/fixtures/jfk.wav" +TEST_FIXTURE_AUDIO_SRC = File.expand_path(File.join(__dir__, "..", "..", "samples", "jfk.wav")) +TEST_FIXTURE_AUDIO_DIR = TEST_FIXTURE_AUDIO.pathmap("%d") +directory TEST_FIXTURE_AUDIO_DIR +if File.exist? TEST_FIXTURE_AUDIO_SRC + file TEST_FIXTURE_AUDIO => [TEST_FIXTURE_AUDIO_SRC, TEST_FIXTURE_AUDIO_DIR] do |t| + symlink t.source, t.name + end +else + require "open-uri" + file TEST_FIXTURE_AUDIO => TEST_FIXTURE_AUDIO_DIR do |t| + File.write t.name, URI("https://github.com/ggml-org/whisper.cpp/raw/refs/heads/master/samples/jfk.wav").read + end +end + +TEST_PARAKEET_MODEL = "test/fixtures/for-tests-ggml-parakeet-tdt.bin" +TEST_PARAKEET_MODEL_SRC = File.expand_path(File.join(__dir__, "..", "..", "models", "for-tests-ggml-parakeet-tdt.bin")) +TEST_PARAKEET_MODEL_DIR = TEST_PARAKEET_MODEL.pathmap("%d") +directory TEST_PARAKEET_MODEL_DIR +if File.exist? TEST_PARAKEET_MODEL_SRC + file TEST_PARAKEET_MODEL => [TEST_PARAKEET_MODEL_SRC, TEST_PARAKEET_MODEL_DIR] do |t| + symlink t.source, t.name + end +else + require "open-uri" + file TEST_PARAKEET_MODEL => TEST_PARAKEET_MODEL_DIR do |t| + File.write t.name, URI("https://github.com/ggml-org/whisper.cpp/raw/refs/heads/master/models/for-tests-ggml-parakeet-tdt.bin").read + end +end + +TEST_MEMORY_VIEW = "test/jfk_reader/jfk_reader.#{RbConfig::CONFIG['DLEXT']}" +file TEST_MEMORY_VIEW => "test/jfk_reader/jfk_reader.c" do |t| + chdir "test/jfk_reader" do + ruby "extconf.rb" + sh "make" + end +end +CLEAN.include TEST_MEMORY_VIEW + +task test: [LIB_FILE, TEST_MEMORY_VIEW, TEST_FIXTURE_AUDIO, TEST_PARAKEET_MODEL] diff --git a/bindings/ruby/ext/.gitignore b/bindings/ruby/ext/.gitignore new file mode 100644 index 0000000..6fd36e4 --- /dev/null +++ b/bindings/ruby/ext/.gitignore @@ -0,0 +1,9 @@ +Makefile +whisper.so +whisper.bundle +whisper.dll +*.o +*.a +sources/* +!sources/CMakeGraphVizOptions.cmake +mkmf.log diff --git a/bindings/ruby/ext/dependencies.rb b/bindings/ruby/ext/dependencies.rb new file mode 100644 index 0000000..b2eb9be --- /dev/null +++ b/bindings/ruby/ext/dependencies.rb @@ -0,0 +1,79 @@ +require "tsort" + +class Dependencies + include TSort + + def initialize(cmake, options) + @cmake = cmake + @options = options + @static_lib_shape = nil + @nodes = {} + @graph = Hash.new {|h, k| h[k] = []} + + generate_dot + parse_dot + end + + def libs + tsort.filter_map {|node| + label, shape = @nodes[node] + if shape == @static_lib_shape + label.gsub(/\\n\([^)]+\)/, '') + else + nil + end + }.reverse.collect {|lib| "#{prefix(lib)}#{lib}.#{RbConfig::CONFIG['LIBEXT']}"} + end + + def to_s + libs.join(" ") + end + + def local_libs + to_s + end + + private + + def dot_path + File.join(__dir__, "build", "whisper.cpp.dot") + end + + def generate_dot + system @cmake, "-S", "sources", "-B", "build", *@options.graphviz_cmake_args, "--graphviz", dot_path, *@options, exception: true + end + + def parse_dot + File.open(dot_path).each_line do |line| + case line + when /\[\s*label\s*=\s*"Static Library"\s*,\s*shape\s*=\s*(?<shape>\w+)\s*\]/ + @static_lib_shape = $~[:shape] + when /\A\s*"(?<node>\w+)"\s*\[\s*label\s*=\s*"(?<label>\S+)"\s*,\s*shape\s*=\s*(?<shape>\w+)\s*\]\s*;\s*\z/ + node = $~[:node] + label = $~[:label] + shape = $~[:shape] + @nodes[node] = [label, shape] + when /\A\s*"(?<depender>\w+)"\s*->\s*"(?<dependee>\w+)"/ + depender = $~[:depender] + dependee = $~[:dependee] + @graph[depender] << dependee + end + end + end + + def prefix(lib) + "lib" + end + + def tsort_each_node + @nodes.each_key do |node| + yield node + end + end + + def tsort_each_child(node) + @graph[node].each do |child| + yield child + end + end +end diff --git a/bindings/ruby/ext/dependencies_for_windows.rb b/bindings/ruby/ext/dependencies_for_windows.rb new file mode 100644 index 0000000..5574107 --- /dev/null +++ b/bindings/ruby/ext/dependencies_for_windows.rb @@ -0,0 +1,17 @@ +require_relative "dependencies" + +class DependenciesForWindows < Dependencies + def local_libs + libs.collect {|lib| %|"#{lib_path(lib)}"|}.join(" ") + end + + private + + def prefix(lib) + lib.start_with?("ggml") ? "" : "lib" + end + + def lib_path(lib) + File.join(__dir__, lib).tr("\\", "/") + end +end diff --git a/bindings/ruby/ext/extconf.rb b/bindings/ruby/ext/extconf.rb new file mode 100644 index 0000000..99894f1 --- /dev/null +++ b/bindings/ruby/ext/extconf.rb @@ -0,0 +1,35 @@ +require "mkmf" + +if RUBY_PLATFORM.match? /mswin|mingw|ucrt/ + require_relative "options_for_windows" + require_relative "dependencies_for_windows" + + Opts = OptionsForWindows + Deps = DependenciesForWindows +else + require_relative "options" + require_relative "dependencies" + + Opts = Options + Deps = Dependencies +end + +cmake = find_executable("cmake") || abort +options = Opts.new(cmake) +have_library("gomp") rescue nil +libs = Deps.new(cmake, options) + +append_cflags ["-O3", "-march=native"] +$INCFLAGS << " -Isources/include -Isources/ggml/include -Isources/examples" +$LOCAL_LIBS << " #{libs.local_libs}" +$cleanfiles << " build #{libs}" + +create_makefile "whisper" do |conf| + conf << <<~EOF + $(TARGET_SO): #{libs} + #{libs}: cmake-targets + cmake-targets: + #{"\t"}"#{cmake}" -S sources -B build #{options} + #{"\t"}"#{cmake}" --build build --config Release --target common whisper parakeet + EOF +end diff --git a/bindings/ruby/ext/options.rb b/bindings/ruby/ext/options.rb new file mode 100644 index 0000000..c097ccb --- /dev/null +++ b/bindings/ruby/ext/options.rb @@ -0,0 +1,125 @@ +require "fileutils" + +class Options + def initialize(cmake="cmake") + @cmake = cmake + @options = {} + + configure + write_cache_file + end + + def to_a + [ + "-D", "BUILD_SHARED_LIBS=OFF", + "-D", "WHISPER_BUILD_TESTS=OFF", + "-D", "CMAKE_ARCHIVE_OUTPUT_DIRECTORY=#{__dir__}", + "-D", "CMAKE_POSITION_INDEPENDENT_CODE=ON", + "-C", cache_path + ] + end + + def to_s + command_line(*to_a) + end + + def graphviz_cmake_args + [] + end + + private + + def cmake_options + @cmake_options ||= cmake_options_output.lines.drop_while {|line| line.chomp != "-- Cache values"}.drop(1) + .filter_map {|line| + option, value = line.chomp.split("=", 2) + name, type = option.split(":", 2) + [ + name, + [ + type, + type == "BOOL" ? value == "ON" : value + ] + ] + }.to_h + end + + def cmake_options_output + Dir.chdir(__dir__) do + IO.popen([@cmake, "-S", "sources", "-B", "build", "-L"]) {|io| io.read} + end + end + + def configure + cmake_options.each_pair do |name, (type, default_value)| + option = option_name(name) + value = type == "BOOL" ? enable_config(option) : arg_config("--#{option}") + @options[name] = [type, value] + end + + configure_accelerate + configure_metal + configure_coreml + end + + # See ggml/src/ggml-cpu/CMakeLists.txt + def configure_accelerate + if RUBY_PLATFORM.match?(/darwin/) && enabled?("GGML_ACCELERATE") + $LDFLAGS << " -framework Accelerate" + end + end + + # See ggml/src/ggml-metal/CMakeLists.txt + def configure_metal + $LDFLAGS << " -framework Foundation -framework Metal -framework MetalKit" if enabled?("GGML_METAL") + end + + # See src/CmakeLists.txt + def configure_coreml + if enabled?("WHISPER_COREML") + $LDFLAGS << " -framework Foundation -framework CoreML" + $defs << "-DRUBY_WHISPER_USE_COREML" + end + end + + def option_name(name) + name.downcase.gsub("_", "-") + end + + def enabled?(option) + op = @options[option] + return false unless op + return false unless op[0] == "BOOL" + if op[1].nil? + cmake_options[option][1] + else + op[1] + end + end + + def cache_path + File.join(__dir__, "sources", "Options.cmake") + end + + def write_cache_file + FileUtils.mkpath File.dirname(cache_path) + File.open cache_path, "w" do |file| + @options.reject {|name, (type, value)| value.nil?}.each do |name, (type, value)| + line = 'set(%<name>s %<value>s CACHE %<type>s "" FORCE)' %{ + name:, + type:, + value: value == true ? "ON" : value == false ? "OFF" : escape_cmake(value) + } + file.puts line + end + end + end + + def escape_cmake(str) + str.gsub(/[\\"]/, '\\\\\&') + end + + def command_line(*args) + args.collect {|arg| %|"#{arg.to_s.gsub(/[\\"]/, '\\\\\&')}"|}.join(" ") + end +end diff --git a/bindings/ruby/ext/options_for_windows.rb b/bindings/ruby/ext/options_for_windows.rb new file mode 100644 index 0000000..7db785d --- /dev/null +++ b/bindings/ruby/ext/options_for_windows.rb @@ -0,0 +1,51 @@ +require_relative "options" + +class OptionsForWindows < Options + def to_s + command_line(*generator_args, *to_a) + end + + def graphviz_cmake_args + generator_args + end + + private + + def arm? + RbConfig::CONFIG["host_cpu"].to_s.downcase.match?(/\A(?:arm64|aarch64)\z/) + end + + def cmake_options_output + Dir.chdir(__dir__) do + IO.popen([@cmake, "-S", "sources", "-B", "build", *generator_args, "-L"]) {|io| io.read} + end + end + + def generator_args + generator = cmake_generator + ["-G", generator] if generator && !generator.empty? + end + + def cmake_generator + return @cmake_generator if defined?(@cmake_generator) + + generator = ENV["CMAKE_GENERATOR"] + abort "CMAKE_GENERATOR=#{generator} is unsupported for mingw/ucrt Ruby" if visual_studio_generator_name?(generator) + return @cmake_generator = generator unless generator.nil? || generator.empty? + + ninja = find_executable("ninja") + return @cmake_generator = "Ninja" if ninja + + make = find_executable("make") + return @cmake_generator = "MSYS Makefiles" if make + + mingw32_make = find_executable("mingw32-make") + return @cmake_generator = "MinGW Makefiles" if mingw32_make + + @cmake_generator = nil + end + + def visual_studio_generator_name?(generator) + generator && generator.start_with?("Visual Studio") + end +end diff --git a/bindings/ruby/ext/ruby_whisper.c b/bindings/ruby/ext/ruby_whisper.c new file mode 100644 index 0000000..bd852a8 --- /dev/null +++ b/bindings/ruby/ext/ruby_whisper.c @@ -0,0 +1,198 @@ +#include "ruby_whisper.h" + +VALUE mWhisper; +VALUE mLogSettable; +VALUE mVAD; +VALUE mParakeet; +VALUE cContext; +VALUE cParams; +VALUE cVADContext; +VALUE cVADParams; +VALUE cVADSegments; +VALUE cVADSegment; +VALUE cParakeetContext; +VALUE cParakeetContextParams; +VALUE cParakeetParams; +VALUE cParakeetSegment; +VALUE cParakeetModel; +VALUE eError; + +VALUE cSegment; +VALUE cToken; +VALUE cModel; + +VALUE mOutputContext; +VALUE mOutputSegment; + +ID id_to_s; +ID id_call; +ID id___method__; +ID id_to_enum; +ID id_length; +ID id_next; +ID id_new; +ID id_to_path; +ID id_URI; +ID id_pre_converted_models; +ID id_coreml_compiled_models; +ID id_cache; +ID id_n_processors; +ID id_extended; +ID id_start_log_callback_thread; +ID id_log_callback_thread; +ID id_alive_p; +ID id_join; + +// High level API +extern VALUE ruby_whisper_segment_allocate(VALUE klass); + +extern VALUE init_ruby_whisper_context(VALUE *mWhisper); +extern void init_ruby_whisper_context_params(VALUE *cContext); +extern void init_ruby_whisper_params(VALUE *mWhisper); +extern void init_ruby_whisper_error(VALUE *mWhisper); +extern void init_ruby_whisper_segment(VALUE *mWhisper); +extern void init_ruby_whisper_token(VALUE *mWhisper); +extern void init_ruby_whisper_model(VALUE *mWhisper); +extern void init_ruby_whisper_vad_params(VALUE *mVAD); +extern void init_ruby_whisper_vad_context(VALUE *mVAD); +extern void init_ruby_whisper_vad_segment(VALUE *mVAD); +extern void init_ruby_whisper_vad_segments(VALUE *mVAD); +extern void init_ruby_whisper_parakeet(VALUE *mWhisper); +extern void register_callbacks(ruby_whisper_params *rwp, VALUE *context); + +static ruby_whisper_log_queue whisper_log_queue; + +LOG_SETTABLE_SETUP(whisper_log_queue, mWhisper, whisper_log_set) + +/* + * call-seq: + * lang_max_id -> Integer + */ +static VALUE ruby_whisper_s_lang_max_id(VALUE self) { + return INT2NUM(whisper_lang_max_id()); +} + +/* + * call-seq: + * lang_id(lang_name) -> Integer + */ +static VALUE ruby_whisper_s_lang_id(VALUE self, VALUE lang) { + const char * lang_str = StringValueCStr(lang); + const int id = whisper_lang_id(lang_str); + if (-1 == id) { + rb_raise(rb_eArgError, "language not found: %s", lang_str); + } + return INT2NUM(id); +} + +/* + * call-seq: + * lang_str(lang_id) -> String + */ +static VALUE ruby_whisper_s_lang_str(VALUE self, VALUE id) { + const int lang_id = NUM2INT(id); + const char * str = whisper_lang_str(lang_id); + if (NULL == str) { + rb_raise(rb_eIndexError, "id %d outside of language id", lang_id); + } + return rb_str_new2(str); +} + +/* + * call-seq: + * lang_str(lang_id) -> String + */ +static VALUE ruby_whisper_s_lang_str_full(VALUE self, VALUE id) { + const int lang_id = NUM2INT(id); + const char * str_full = whisper_lang_str_full(lang_id); + if (NULL == str_full) { + rb_raise(rb_eIndexError, "id %d outside of language id", lang_id); + } + return rb_str_new2(str_full); +} + +/* + * call-seq: + * system_info_str -> String + */ +static VALUE ruby_whisper_s_system_info_str(VALUE self) { + return rb_str_new2(whisper_print_system_info()); +} + +void Init_whisper() { + id_to_s = rb_intern("to_s"); + id_call = rb_intern("call"); + id___method__ = rb_intern("__method__"); + id_to_enum = rb_intern("to_enum"); + id_length = rb_intern("length"); + id_next = rb_intern("next"); + id_new = rb_intern("new"); + id_to_path = rb_intern("to_path"); + id_URI = rb_intern("URI"); + id_pre_converted_models = rb_intern("pre_converted_models"); + id_coreml_compiled_models = rb_intern("coreml_compiled_models"); + id_cache = rb_intern("cache"); + id_n_processors = rb_intern("n_processors"); + id_start_log_callback_thread = rb_intern("start_log_callback_thread"); + id_log_callback_thread = rb_intern("@log_callback_thread"); + id_alive_p = rb_intern("alive?"); + id_join = rb_intern("join"); + + mWhisper = rb_define_module("Whisper"); + rb_require("whisper/log_settable"); + mLogSettable = rb_path2class("Whisper::LogSettable"); + mVAD = rb_define_module_under(mWhisper, "VAD"); + rb_require("whisper/output"); + mOutputContext = rb_path2class("Whisper::Output::Context"); + mOutputSegment = rb_path2class("Whisper::Output::Segment"); + + rb_define_const(mWhisper, "VERSION", rb_str_new2(whisper_version())); + rb_define_const(mWhisper, "LOG_LEVEL_NONE", INT2NUM(GGML_LOG_LEVEL_NONE)); + rb_define_const(mWhisper, "LOG_LEVEL_INFO", INT2NUM(GGML_LOG_LEVEL_INFO)); + rb_define_const(mWhisper, "LOG_LEVEL_WARN", INT2NUM(GGML_LOG_LEVEL_WARN)); + rb_define_const(mWhisper, "LOG_LEVEL_ERROR", INT2NUM(GGML_LOG_LEVEL_ERROR)); + rb_define_const(mWhisper, "LOG_LEVEL_DEBUG", INT2NUM(GGML_LOG_LEVEL_DEBUG)); + rb_define_const(mWhisper, "LOG_LEVEL_CONT", INT2NUM(GGML_LOG_LEVEL_CONT)); + + rb_define_const(mWhisper, "AHEADS_NONE", INT2NUM(WHISPER_AHEADS_NONE)); + rb_define_const(mWhisper, "AHEADS_N_TOP_MOST", INT2NUM(WHISPER_AHEADS_N_TOP_MOST)); + rb_define_const(mWhisper, "AHEADS_CUSTOM", INT2NUM(WHISPER_AHEADS_CUSTOM)); + rb_define_const(mWhisper, "AHEADS_TINY_EN", INT2NUM(WHISPER_AHEADS_TINY_EN)); + rb_define_const(mWhisper, "AHEADS_TINY", INT2NUM(WHISPER_AHEADS_TINY)); + rb_define_const(mWhisper, "AHEADS_BASE_EN", INT2NUM(WHISPER_AHEADS_BASE_EN)); + rb_define_const(mWhisper, "AHEADS_BASE", INT2NUM(WHISPER_AHEADS_BASE)); + rb_define_const(mWhisper, "AHEADS_SMALL_EN", INT2NUM(WHISPER_AHEADS_SMALL_EN)); + rb_define_const(mWhisper, "AHEADS_SMALL", INT2NUM(WHISPER_AHEADS_SMALL)); + rb_define_const(mWhisper, "AHEADS_MEDIUM_EN", INT2NUM(WHISPER_AHEADS_MEDIUM_EN)); + rb_define_const(mWhisper, "AHEADS_MEDIUM", INT2NUM(WHISPER_AHEADS_MEDIUM)); + rb_define_const(mWhisper, "AHEADS_LARGE_V1", INT2NUM(WHISPER_AHEADS_LARGE_V1)); + rb_define_const(mWhisper, "AHEADS_LARGE_V2", INT2NUM(WHISPER_AHEADS_LARGE_V2)); + rb_define_const(mWhisper, "AHEADS_LARGE_V3", INT2NUM(WHISPER_AHEADS_LARGE_V3)); + rb_define_const(mWhisper, "AHEADS_LARGE_V3_TURBO", INT2NUM(WHISPER_AHEADS_LARGE_V3_TURBO)); + + rb_define_singleton_method(mWhisper, "lang_max_id", ruby_whisper_s_lang_max_id, 0); + rb_define_singleton_method(mWhisper, "lang_id", ruby_whisper_s_lang_id, 1); + rb_define_singleton_method(mWhisper, "lang_str", ruby_whisper_s_lang_str, 1); + rb_define_singleton_method(mWhisper, "lang_str_full", ruby_whisper_s_lang_str_full, 1); + rb_define_singleton_method(mWhisper, "system_info_str", ruby_whisper_s_system_info_str, 0); + + LOG_SETTABLE_INIT(whisper_log_queue, mWhisper) + + cContext = init_ruby_whisper_context(&mWhisper); + init_ruby_whisper_context_params(&cContext); + init_ruby_whisper_params(&mWhisper); + init_ruby_whisper_error(&mWhisper); + init_ruby_whisper_segment(&mWhisper); + init_ruby_whisper_token(&mWhisper); + init_ruby_whisper_model(&mWhisper); + init_ruby_whisper_vad_params(&mVAD); + init_ruby_whisper_vad_segment(&mVAD); + init_ruby_whisper_vad_segments(&mVAD); + init_ruby_whisper_vad_context(&mVAD); + init_ruby_whisper_parakeet(&mWhisper); + + rb_require("whisper/model/uri"); + + rb_include_module(cContext, mOutputContext); + rb_include_module(cSegment, mOutputSegment); +} diff --git a/bindings/ruby/ext/ruby_whisper.h b/bindings/ruby/ext/ruby_whisper.h new file mode 100644 index 0000000..85ac63e --- /dev/null +++ b/bindings/ruby/ext/ruby_whisper.h @@ -0,0 +1,248 @@ +#ifndef RUBY_WHISPER_H +#define RUBY_WHISPER_H + +#include <ruby.h> +#include <ruby/version.h> +#include <ruby/util.h> +#include <ruby/thread.h> +#include <ruby/thread_native.h> +#include <ruby/atomic.h> +#include <ruby/memory_view.h> +#include "whisper.h" +#include "parakeet.h" +#include "ruby_whisper_log_settable.h" + +#if RUBY_API_VERSION_MAJOR < 4 +// Exists but not declared as public API +int ruby_thread_has_gvl_p(void); +#endif + +typedef struct { + VALUE *context; + VALUE user_data; + VALUE callback; + VALUE callbacks; +} ruby_whisper_callback_container; + +typedef struct ruby_whisper_abort_callback_user_data { + volatile rb_atomic_t is_interrupted; + ruby_whisper_callback_container *callback_container; +} ruby_whisper_abort_callback_user_data; + +typedef struct ruby_whisper_log { + enum ggml_log_level level; + char *text; + size_t length; + size_t capacity; +} ruby_whisper_log; + +typedef struct ruby_whisper_log_queue { + rb_nativethread_lock_t lock; + rb_nativethread_cond_t cond; + bool is_open; + + size_t head; + size_t tail; + size_t size; + ruby_whisper_log *logs; +} ruby_whisper_log_queue; + +typedef struct { + struct whisper_context *context; +} ruby_whisper; + +typedef struct ruby_whisper_context_params { + struct whisper_context_params params; +} ruby_whisper_context_params; + +typedef struct { + struct whisper_full_params params; + bool diarize; + ruby_whisper_callback_container *new_segment_callback_container; + ruby_whisper_callback_container *progress_callback_container; + ruby_whisper_callback_container *encoder_begin_callback_container; + ruby_whisper_callback_container *abort_callback_container; + VALUE vad_params; +} ruby_whisper_params; + +typedef struct { + struct whisper_vad_params params; +} ruby_whisper_vad_params; + +typedef struct { + VALUE context; + int index; +} ruby_whisper_segment; + +typedef struct { + whisper_token_data *token_data; + VALUE text; +} ruby_whisper_token; + +typedef struct { + VALUE context; +} ruby_whisper_model; + +typedef struct { + struct whisper_vad_segments *segments; +} ruby_whisper_vad_segments; + +typedef struct { + VALUE segments; + int index; +} ruby_whisper_vad_segment; + +typedef struct { + struct whisper_vad_context *context; +} ruby_whisper_vad_context; + +typedef struct parsed_samples_t { + float *samples; + int n_samples; + rb_memory_view_t memview; + bool memview_exported; +} parsed_samples_t; + +typedef struct { + VALUE *context; + VALUE *params; + float *samples; + int n_samples; +} ruby_whisper_full_args; + +typedef struct segments_from_samples_args { + VALUE *context; + VALUE *params; + float *samples; + int n_samples; +} segments_from_samples_args; + +typedef struct ruby_whisper_full_parallel_args { + VALUE *context; + VALUE *params; + float *samples; + int n_samples; + int n_processors; +} ruby_whisper_full_parallel_args; + +typedef struct { + struct parakeet_full_params params; + ruby_whisper_callback_container *new_segment_callback_container; + ruby_whisper_callback_container *new_token_callback_container; + ruby_whisper_callback_container *progress_callback_container; + ruby_whisper_callback_container *encoder_begin_callback_container; + ruby_whisper_callback_container *abort_callback_container; +} ruby_whisper_parakeet_params; + +typedef struct { + struct parakeet_context_params params; +} ruby_whisper_parakeet_context_params; + +typedef struct { + struct parakeet_context *context; +} ruby_whisper_parakeet_context; + +typedef struct { + VALUE context; + int index; +} ruby_whisper_parakeet_segment; + +typedef struct { + parakeet_token_data *token_data; + VALUE text; +} ruby_whisper_parakeet_token; + +typedef struct { + VALUE context; +} ruby_whisper_parakeet_model; + +extern ID id_log_callback_thread; +extern ID id_start_log_callback_thread; +extern ID id_alive_p; +extern ID id_join; +extern void ruby_whisper_log_queue_initialize(ruby_whisper_log_queue *log_queue); +extern void ruby_whisper_log_queue_open(ruby_whisper_log_queue *log_queue); +extern void ruby_whisper_log_queue_close(ruby_whisper_log_queue *log_queue); +extern void ruby_whisper_log_queue_enqueue(ruby_whisper_log_queue *log_queue, enum ggml_log_level level, const char *text); +extern VALUE ruby_whisper_log_queue_drain(ruby_whisper_log_queue *log_queue); + +#define GetContext(obj, rw) do { \ + TypedData_Get_Struct((obj), ruby_whisper, &ruby_whisper_type, (rw)); \ + if ((rw)->context == NULL) { \ + rb_raise(rb_eRuntimeError, "Already freed or not initialized"); \ + } \ +} while (0) + +#define GetContextParams(obj, rwcp) do { \ + TypedData_Get_Struct((obj), ruby_whisper_context_params, &ruby_whisper_context_params_type, (rwcp)); \ +} while (0) + +#define GetToken(obj, rwt) do { \ + TypedData_Get_Struct((obj), ruby_whisper_token, &ruby_whisper_token_type, (rwt)); \ + if ((rwt)->token_data == NULL) { \ + rb_raise(rb_eRuntimeError, "Not initialized"); \ + } \ +} while (0) + +#define GetVADContext(obj, rwvc) do { \ + TypedData_Get_Struct((obj), ruby_whisper_vad_context, &ruby_whisper_vad_context_type, (rwvc)); \ + if ((rwvc)->context == NULL) { \ + rb_raise(rb_eRuntimeError, "Already freed or not initialized"); \ + } \ +} while (0) + +#define GetVADParams(obj, rwvp) do { \ + TypedData_Get_Struct((obj), ruby_whisper_vad_params, &ruby_whisper_vad_params_type, (rwvp)); \ +} while (0) + +#define GetVADSegments(obj, rwvss) do { \ + TypedData_Get_Struct((obj), ruby_whisper_vad_segments, &ruby_whisper_vad_segments_type, (rwvss)); \ + if ((rwvss)->segments == NULL) { \ + rb_raise(rb_eRuntimeError, "Not initialized"); \ + } \ +} while (0) + +#define GetParakeetContextParams(obj, rwpcp) do { \ + TypedData_Get_Struct((obj), ruby_whisper_parakeet_context_params, &ruby_whisper_parakeet_context_params_type, (rwpcp)); \ +} while (0) + +#define GetParakeetContext(obj, rwpc) do { \ + TypedData_Get_Struct((obj), ruby_whisper_parakeet_context, &ruby_whisper_parakeet_context_type, (rwpc)); \ + if ((rwpc)->context == NULL) { \ + rb_raise(rb_eRuntimeError, "Already freed or not initialized"); \ + } \ +} while (0) + +#define GetParakeetParams(obj, rwpp) do { \ + TypedData_Get_Struct((obj), ruby_whisper_parakeet_params, &ruby_whisper_parakeet_params_type, (rwpp)); \ + if (!(rwpp)->new_segment_callback_container || \ + !(rwpp)->new_token_callback_container || \ + !(rwpp)->progress_callback_container || \ + !(rwpp)->encoder_begin_callback_container || \ + !(rwpp)->abort_callback_container) { \ + rb_raise(rb_eRuntimeError, "Not initialized"); \ + } \ +} while (0) + +#define GetParakeetSegment(obj, rwps) do { \ + TypedData_Get_Struct((obj), ruby_whisper_parakeet_segment, &ruby_whisper_parakeet_segment_type, (rwps)); \ + if (!(rwps)->context) { \ + rb_raise(rb_eRuntimeError, "Not initialized"); \ + } \ +} while (0) + +#define GetParakeetToken(obj, rwpt) do { \ + TypedData_Get_Struct((obj), ruby_whisper_parakeet_token, &ruby_whisper_parakeet_token_type, (rwpt)); \ + if (!(rwpt)->token_data) { \ + rb_raise(rb_eRuntimeError, "Not initialized"); \ + } \ +} while (0) + +#define GetParakeetModel(obj, rwpm) do { \ + TypedData_Get_Struct((obj), ruby_whisper_parakeet_model, &ruby_whisper_parakeet_model_type, (rwpm)); \ + if (NIL_P((rwpm)->context)) { \ + rb_raise(rb_eRuntimeError, "Not initialized"); \ + } \ +} while (0) + +#endif diff --git a/bindings/ruby/ext/ruby_whisper_context.c b/bindings/ruby/ext/ruby_whisper_context.c new file mode 100644 index 0000000..0787902 --- /dev/null +++ b/bindings/ruby/ext/ruby_whisper_context.c @@ -0,0 +1,941 @@ +#include "ruby_whisper.h" + +#ifdef WORDS_BIGENDIAN + #define IS_BIGENDIAN true +#else + #define IS_BIGENDIAN false +#endif + +extern ID id_to_s; +extern ID id___method__; +extern ID id_to_enum; +extern ID id_length; +extern ID id_next; +extern ID id_new; +extern ID id_to_path; +extern ID id_URI; +extern ID id_pre_converted_models; +extern ID id_coreml_compiled_models; +extern ID id_cache; +extern ID id_n_processors; + +extern VALUE cContext; +extern VALUE eError; +extern VALUE cModel; + +extern const rb_data_type_t ruby_whisper_params_type; +extern const rb_data_type_t ruby_whisper_context_params_type; +extern VALUE ruby_whisper_transcribe(int argc, VALUE *argv, VALUE self); +extern VALUE rb_whisper_model_s_new(VALUE context); +extern VALUE rb_whisper_segment_s_new(VALUE context, int index); +extern void prepare_transcription(ruby_whisper_params *rwp, VALUE *context, int n_processors, ruby_whisper_abort_callback_user_data *abort_callback_user_data); + +ID transcribe_option_names[1]; + +typedef struct fill_samples_args { + float *dest; + VALUE *src; + int n_samples; +} fill_samples_args; + +typedef struct full_without_gvl_args { + struct whisper_context *context; + struct whisper_full_params *params; + float *samples; + int n_samples; + int result; +} full_without_gvl_args; + +typedef struct full_parallel_without_gvl_args { + struct whisper_context *context; + struct whisper_full_params *params; + float *samples; + int n_samples; + int n_processors; + int result; +} full_parallel_without_gvl_args; + +typedef struct full_ubf_args { + ruby_whisper_abort_callback_user_data *abort_callback_user_data; +} full_ubf_args; + +static void +ruby_whisper_free(ruby_whisper *rw) +{ + if (rw->context) { + whisper_free(rw->context); + rw->context = NULL; + } +} + +void +rb_whisper_mark(ruby_whisper *rw) +{ + // call rb_gc_mark on any ruby references in rw +} + +void +rb_whisper_free(void *p) +{ + ruby_whisper *rw = (ruby_whisper *)p; + ruby_whisper_free(rw); + free(rw); +} + +static size_t +ruby_whisper_memsize(const void *p) +{ + const ruby_whisper *rw = (const ruby_whisper *)p; + size_t size = sizeof(*rw); + if (!rw) { + return 0; + } + if (rw->context) { + size += sizeof(rw->context); + } + return size; +} + +const rb_data_type_t ruby_whisper_type = { + "ruby_whisper", + {0, rb_whisper_free, ruby_whisper_memsize,}, + 0, 0, + 0 +}; + +static VALUE +ruby_whisper_allocate(VALUE klass) +{ + ruby_whisper *rw; + VALUE obj = TypedData_Make_Struct(klass, ruby_whisper, &ruby_whisper_type, rw); + rw->context = NULL; + return obj; +} + +VALUE +ruby_whisper_normalize_model_path(VALUE model_path) +{ + VALUE pre_converted_models = rb_funcall(cModel, id_pre_converted_models, 0); + VALUE pre_converted_model = rb_hash_aref(pre_converted_models, model_path); + if (!NIL_P(pre_converted_model)) { + model_path = pre_converted_model; +#ifdef RUBY_WHISPER_USE_COREML + VALUE coreml_converted_models = rb_funcall(cModel, id_coreml_compiled_models, 0); + VALUE coreml_converted_model = rb_hash_aref(coreml_converted_models, pre_converted_model); + if (!NIL_P(coreml_converted_model)) { + rb_funcall(coreml_converted_model, id_cache, 0); + } +#endif + } + else if (TYPE(model_path) == T_STRING) { + const char * model_path_str = StringValueCStr(model_path); + if (strncmp("http://", model_path_str, 7) == 0 || strncmp("https://", model_path_str, 8) == 0) { + VALUE uri_class = rb_const_get(cModel, id_URI); + model_path = rb_class_new_instance(1, &model_path, uri_class); + } + } + else if (rb_obj_is_kind_of(model_path, rb_path2class("URI::HTTP"))) { + VALUE uri_class = rb_const_get(cModel, id_URI); + model_path = rb_class_new_instance(1, &model_path, uri_class); + } + if (rb_respond_to(model_path, id_to_path)) { + model_path = rb_funcall(model_path, id_to_path, 0); + } + + return model_path; +} + +/* + * call-seq: + * new("base.en") -> Whisper::Context + * new("path/to/model.bin") -> Whisper::Context + * new(Whisper::Model::URI.new("https://example.net/uri/of/model.bin")) -> Whisper::Context + */ +static VALUE +ruby_whisper_initialize(int argc, VALUE *argv, VALUE self) +{ + ruby_whisper *rw; + VALUE whisper_model_file_path; + VALUE context_params; + struct whisper_context_params params; + + // TODO: we can support init from buffer here too maybe another ruby object to expose + rb_scan_args(argc, argv, "11", &whisper_model_file_path, &context_params); + TypedData_Get_Struct(self, ruby_whisper, &ruby_whisper_type, rw); + + whisper_model_file_path = ruby_whisper_normalize_model_path(whisper_model_file_path); + if (!rb_respond_to(whisper_model_file_path, id_to_s)) { + rb_raise(rb_eRuntimeError, "Expected file path to model to initialize Whisper::Context"); + } + if (NIL_P(context_params)) { + params = whisper_context_default_params(); + } else { + ruby_whisper_context_params *rwcp; + GetContextParams(context_params, rwcp); + params = rwcp->params; + } + rw->context = whisper_init_from_file_with_params(StringValueCStr(whisper_model_file_path), params); + if (rw->context == NULL) { + rb_raise(rb_eRuntimeError, "error: failed to initialize whisper context"); + } + return self; +} + +/* + * call-seq: + * model_n_vocab -> Integer + */ +VALUE ruby_whisper_model_n_vocab(VALUE self) +{ + ruby_whisper *rw; + GetContext(self, rw); + return INT2NUM(whisper_model_n_vocab(rw->context)); +} + +/* + * call-seq: + * model_n_audio_ctx -> Integer + */ +VALUE ruby_whisper_model_n_audio_ctx(VALUE self) +{ + ruby_whisper *rw; + GetContext(self, rw); + return INT2NUM(whisper_model_n_audio_ctx(rw->context)); +} + +/* + * call-seq: + * model_n_audio_state -> Integer + */ +VALUE ruby_whisper_model_n_audio_state(VALUE self) +{ + ruby_whisper *rw; + GetContext(self, rw); + return INT2NUM(whisper_model_n_audio_state(rw->context)); +} + +/* + * call-seq: + * model_n_audio_head -> Integer + */ +VALUE ruby_whisper_model_n_audio_head(VALUE self) +{ + ruby_whisper *rw; + GetContext(self, rw); + return INT2NUM(whisper_model_n_audio_head(rw->context)); +} + +/* + * call-seq: + * model_n_audio_layer -> Integer + */ +VALUE ruby_whisper_model_n_audio_layer(VALUE self) +{ + ruby_whisper *rw; + GetContext(self, rw); + return INT2NUM(whisper_model_n_audio_layer(rw->context)); +} + +/* + * call-seq: + * model_n_text_ctx -> Integer + */ +VALUE ruby_whisper_model_n_text_ctx(VALUE self) +{ + ruby_whisper *rw; + GetContext(self, rw); + return INT2NUM(whisper_model_n_text_ctx(rw->context)); +} + +/* + * call-seq: + * model_n_text_state -> Integer + */ +VALUE ruby_whisper_model_n_text_state(VALUE self) +{ + ruby_whisper *rw; + GetContext(self, rw); + return INT2NUM(whisper_model_n_text_state(rw->context)); +} + +/* + * call-seq: + * model_n_text_head -> Integer + */ +VALUE ruby_whisper_model_n_text_head(VALUE self) +{ + ruby_whisper *rw; + GetContext(self, rw); + return INT2NUM(whisper_model_n_text_head(rw->context)); +} + +/* + * call-seq: + * model_n_text_layer -> Integer + */ +VALUE ruby_whisper_model_n_text_layer(VALUE self) +{ + ruby_whisper *rw; + GetContext(self, rw); + return INT2NUM(whisper_model_n_text_layer(rw->context)); +} + +/* + * call-seq: + * model_n_mels -> Integer + */ +VALUE ruby_whisper_model_n_mels(VALUE self) +{ + ruby_whisper *rw; + GetContext(self, rw); + return INT2NUM(whisper_model_n_mels(rw->context)); +} + +/* + * call-seq: + * model_ftype -> Integer + */ +VALUE ruby_whisper_model_ftype(VALUE self) +{ + ruby_whisper *rw; + GetContext(self, rw); + return INT2NUM(whisper_model_ftype(rw->context)); +} + +/* + * call-seq: + * model_type -> String + */ +VALUE ruby_whisper_model_type(VALUE self) +{ + ruby_whisper *rw; + GetContext(self, rw); + return rb_str_new2(whisper_model_type_readable(rw->context)); +} + +static bool +check_memory_view(rb_memory_view_t *memview) +{ + rb_memory_view_prepare_item_desc(memview); + + if (!memview->format) { + rb_warn("format is required"); + return false; + } + + if (memview->item_desc.length != 1) { + rb_warn("format must be exact one character"); + return false; + } + + rb_memory_view_item_component_t component = memview->item_desc.components[0]; + + if (component.offset) { + rb_warn("format has offset"); + return false; + } + if (component.repeat != 1) { + rb_warn("format repeated"); + return false; + } + switch (component.format) { + case 'f': + // accept + break; + case 'e': + if (IS_BIGENDIAN) { + rb_warn("currently format \"e\" is only supported on little-endian environment"); + return false; + } + break; + case 'g': + if (!IS_BIGENDIAN) { + rb_warn("currently format \"g\" is only supported on big-endian environment"); + return false; + } + break; + default: + rb_warn("currently only format \"f\", \"e\" on little-endian environment and \"g\" on big-endian environment are supported for MemoryView, but given: %c", component.format); + return false; + } + + if (memview->ndim != 1 && !(memview->ndim == 2 && memview->shape[1] == 1)) { + // TODO: Accept ndim == 2 with shape [n_samples, channels] and channels > 1 by averaging the samples in different channels or just taking the first channel + rb_warn("currently only 1 dimensional MemoryView is supported, but given: %zd", memview->ndim); + return false; + } + + return true; +} + +static VALUE +fill_samples(VALUE rb_args) +{ + fill_samples_args *args = (fill_samples_args *)rb_args; + + if (RB_TYPE_P(*args->src, T_ARRAY)) { + for (int i = 0; i < args->n_samples; i++) { + VALUE sample = rb_ary_entry(*args->src, i); + if (!RB_FLOAT_TYPE_P(sample)) { + sample = rb_to_float(sample); + } + args->dest[i] = RFLOAT_VALUE(sample); + } + } else { + // TODO: use rb_block_call + VALUE iter = rb_funcall(*args->src, id_to_enum, 1, rb_str_new2("each")); + for (int i = 0; i < args->n_samples; i++) { + // TODO: check if iter is exhausted and raise ArgumentError appropriately + VALUE sample = rb_funcall(iter, id_next, 0); + if (!RB_FLOAT_TYPE_P(sample)) { + sample = rb_to_float(sample); + } + args->dest[i] = RFLOAT_VALUE(sample); + } + } + + return Qnil; +} + +parsed_samples_t +parse_samples(VALUE *samples, VALUE *n_samples) +{ + bool memview_available = rb_memory_view_available_p(*samples); + struct parsed_samples_t parsed = {0}; + parsed.memview_exported = false; + const bool is_array = RB_TYPE_P(*samples, T_ARRAY); + + if (!NIL_P(*n_samples)) { + parsed.n_samples = NUM2INT(*n_samples); + if (is_array) { + if (RARRAY_LEN(*samples) < parsed.n_samples) { + rb_raise(rb_eArgError, "samples length %ld is less than n_samples %d", RARRAY_LEN(*samples), parsed.n_samples); + } + } + // Should check when samples.respond_to?(:length)? + } else { + if (is_array) { + if (RARRAY_LEN(*samples) > INT_MAX) { + rb_raise(rb_eArgError, "samples are too long"); + } + parsed.n_samples = (int)RARRAY_LEN(*samples); + } else if (memview_available) { + bool memview_got = rb_memory_view_get(*samples, &parsed.memview, RUBY_MEMORY_VIEW_FORMAT | RUBY_MEMORY_VIEW_ROW_MAJOR); + if (memview_got) { + parsed.memview_exported = check_memory_view(&parsed.memview); + if (!parsed.memview_exported) { + rb_memory_view_release(&parsed.memview); + parsed.memview = (rb_memory_view_t){0}; + } + } else { + // Sometimes MemoryView producers accept only SIMPLE flag even when they provide suitable MemoryView + parsed.memview = (rb_memory_view_t){0}; + bool simple_memview_got = rb_memory_view_get(*samples, &parsed.memview, RUBY_MEMORY_VIEW_SIMPLE); + if (simple_memview_got) { + parsed.memview_exported = check_memory_view(&parsed.memview); + if (!parsed.memview_exported) { + rb_memory_view_release(&parsed.memview); + parsed.memview = (rb_memory_view_t){0}; + } + } + } + if (parsed.memview_exported) { + ssize_t n_samples_size = parsed.memview.byte_size / parsed.memview.item_size; + if (n_samples_size > INT_MAX) { + rb_memory_view_release(&parsed.memview); + rb_raise(rb_eArgError, "samples are too long: %zd", n_samples_size); + } + parsed.n_samples = (int)n_samples_size; + } else { + rb_warn("unable to get a memory view. falls back to Ruby object"); + if (rb_respond_to(*samples, id_length)) { + parsed.n_samples = NUM2INT(rb_funcall(*samples, id_length, 0)); + } else { + rb_raise(rb_eArgError, "samples must respond to :length"); + } + } + } else if (rb_respond_to(*samples, id_length)) { + parsed.n_samples = NUM2INT(rb_funcall(*samples, id_length, 0)); + } else { + rb_raise(rb_eArgError, "samples must respond to :length or be a MemoryView of an array of float when n_samples is not given"); + } + } + + if (parsed.memview_exported) { + parsed.samples = (float *)parsed.memview.data; + } else { + parsed.samples = ALLOC_N(float, parsed.n_samples); + fill_samples_args args = { + parsed.samples, + samples, + parsed.n_samples, + }; + int state; + rb_protect(fill_samples, (VALUE)&args, &state); + if (state) { + xfree(parsed.samples); + rb_jump_tag(state); + } + } + + return parsed; +} + +VALUE +release_samples(VALUE rb_parsed_args) +{ + parsed_samples_t *parsed_args = (parsed_samples_t *)rb_parsed_args; + + if (parsed_args->memview_exported) { + rb_memory_view_release(&parsed_args->memview); + } else { + xfree(parsed_args->samples); + } + *parsed_args = (parsed_samples_t){0}; + + return Qnil; +} + +static void* +full_without_gvl(void *rb_args) +{ + full_without_gvl_args *args = (full_without_gvl_args *)rb_args; + args->result = whisper_full(args->context, *args->params, args->samples, args->n_samples); + return NULL; +} + +static void +full_ubf(void *rb_args) +{ + full_ubf_args *args = (full_ubf_args *)rb_args; + + RUBY_ATOMIC_SET(args->abort_callback_user_data->is_interrupted, 1); +} + +VALUE +full_body(VALUE rb_args) +{ + ruby_whisper_full_args *args = (ruby_whisper_full_args *)rb_args; + + ruby_whisper *rw; + ruby_whisper_params *rwp; + GetContext(*args->context, rw); + TypedData_Get_Struct(*args->params, ruby_whisper_params, &ruby_whisper_params_type, rwp); + + ruby_whisper_abort_callback_user_data abort_callback_user_data = { + 0, + NULL, + }; + prepare_transcription(rwp, args->context, 1, &abort_callback_user_data); + + struct full_without_gvl_args full_without_gvl_args = { + rw->context, + &rwp->params, + args->samples, + args->n_samples, + 0, + }; + full_ubf_args full_ubf_args = { + &abort_callback_user_data, + }; + rb_thread_call_without_gvl(full_without_gvl, (void *)&full_without_gvl_args, full_ubf, (void *)&full_ubf_args); + return INT2NUM(full_without_gvl_args.result); +} + +/* + * Run the entire model: PCM -> log mel spectrogram -> encoder -> decoder -> text + * Not thread safe for same context + * Uses the specified decoding strategy to obtain the text. + * + * call-seq: + * full(params, samples, n_samples) -> nil + * full(params, samples) -> nil + * + * The second argument +samples+ must be an array of samples, respond to :length, or be a MemoryView of an array of float. It must be 32 bit float PCM audio data. + */ +VALUE ruby_whisper_full(int argc, VALUE *argv, VALUE self) +{ + if (argc < 2 || argc > 3) { + rb_raise(rb_eArgError, "wrong number of arguments (given %d, expected 2..3)", argc); + } + + VALUE n_samples = argc == 2 ? Qnil : argv[2]; + + struct parsed_samples_t parsed = parse_samples(&argv[1], &n_samples); + ruby_whisper_full_args args = { + &self, + &argv[0], + parsed.samples, + parsed.n_samples, + }; + VALUE rb_result = rb_ensure(full_body, (VALUE)&args, release_samples, (VALUE)&parsed); + const int result = NUM2INT(rb_result); + if (0 == result) { + return self; + } else { + rb_exc_raise(rb_funcall(eError, id_new, 1, result)); + } +} + +static void* +full_parallel_without_gvl(void *rb_args) +{ + full_parallel_without_gvl_args *args = (full_parallel_without_gvl_args *)rb_args; + args->result = whisper_full_parallel(args->context, *args->params, args->samples, args->n_samples, args->n_processors); + return NULL; +} + +VALUE +full_parallel_body(VALUE rb_args) +{ + ruby_whisper_full_parallel_args *args = (ruby_whisper_full_parallel_args *)rb_args; + + ruby_whisper *rw; + ruby_whisper_params *rwp; + GetContext(*args->context, rw); + TypedData_Get_Struct(*args->params, ruby_whisper_params, &ruby_whisper_params_type, rwp); + + ruby_whisper_abort_callback_user_data abort_callback_user_data = { + 0, + NULL, + }; + prepare_transcription(rwp, args->context, args->n_processors, &abort_callback_user_data); + + struct full_parallel_without_gvl_args full_parallel_without_gvl_args = { + rw->context, + &rwp->params, + args->samples, + args->n_samples, + args->n_processors, + 0, + }; + full_ubf_args full_ubf_args = { + &abort_callback_user_data, + }; + rb_thread_call_without_gvl(full_parallel_without_gvl, (void *)&full_parallel_without_gvl_args, full_ubf, (void *)&full_ubf_args); + return INT2NUM(full_parallel_without_gvl_args.result); +} + +/* + * Split the input audio in chunks and process each chunk separately using whisper_full_with_state() + * Result is stored in the default state of the context + * Not thread safe if executed in parallel on the same context. + * It seems this approach can offer some speedup in some cases. + * However, the transcription accuracy can be worse at the beginning and end of each chunk. + * + * call-seq: + * full_parallel(params, samples) -> nil + * full_parallel(params, samples, n_samples) -> nil + * full_parallel(params, samples, n_samples, n_processors) -> nil + * full_parallel(params, samples, nil, n_processors) -> nil + */ +static VALUE +ruby_whisper_full_parallel(int argc, VALUE *argv,VALUE self) +{ + if (argc < 2 || argc > 4) { + rb_raise(rb_eArgError, "wrong number of arguments (given %d, expected 2..4)", argc); + } + + VALUE n_samples = argc == 2 ? Qnil : argv[2]; + int n_processors; + switch (argc) { + case 2: + n_processors = 1; + break; + case 3: + n_processors = 1; + break; + case 4: + n_processors = NUM2INT(argv[3]); + break; + } + struct parsed_samples_t parsed = parse_samples(&argv[1], &n_samples); + const ruby_whisper_full_parallel_args args = { + &self, + &argv[0], + parsed.samples, + parsed.n_samples, + n_processors, + }; + const VALUE rb_result = rb_ensure(full_parallel_body, (VALUE)&args, release_samples, (VALUE)&parsed); + const int result = NUM2INT(rb_result); + if (0 == result) { + return self; + } else { + rb_exc_raise(rb_funcall(eError, id_new, 1, result)); + } +} + +/* + * Number of segments. + * + * call-seq: + * full_n_segments -> Integer + */ +static VALUE +ruby_whisper_full_n_segments(VALUE self) +{ + ruby_whisper *rw; + GetContext(self, rw); + return INT2NUM(whisper_full_n_segments(rw->context)); +} + +/* + * Language ID, which can be converted to string by Whisper.lang_str and Whisper.lang_str_full. + * + * call-seq: + * full_lang_id -> Integer + */ +static VALUE +ruby_whisper_full_lang_id(VALUE self) +{ + ruby_whisper *rw; + GetContext(self, rw); + return INT2NUM(whisper_full_lang_id(rw->context)); +} + +static int ruby_whisper_full_check_segment_index(const ruby_whisper * rw, const VALUE i_segment) +{ + const int c_i_segment = NUM2INT(i_segment); + if (c_i_segment < 0 || c_i_segment >= whisper_full_n_segments(rw->context)) { + rb_raise(rb_eIndexError, "segment index %d out of range", c_i_segment); + } + return c_i_segment; +} + +/* + * Start time of a segment indexed by +segment_index+ in centiseconds (10 times milliseconds). + * + * full_get_segment_t0(3) # => 1668 (16680 ms) + * + * call-seq: + * full_get_segment_t0(segment_index) -> Integer + */ +static VALUE +ruby_whisper_full_get_segment_t0(VALUE self, VALUE i_segment) +{ + ruby_whisper *rw; + GetContext(self, rw); + const int c_i_segment = ruby_whisper_full_check_segment_index(rw, i_segment); + const int64_t t0 = whisper_full_get_segment_t0(rw->context, c_i_segment); + return LONG2NUM(t0); +} + +/* + * End time of a segment indexed by +segment_index+ in centiseconds (10 times milliseconds). + * + * full_get_segment_t1(3) # => 1668 (16680 ms) + * + * call-seq: + * full_get_segment_t1(segment_index) -> Integer + */ +static VALUE +ruby_whisper_full_get_segment_t1(VALUE self, VALUE i_segment) +{ + ruby_whisper *rw; + GetContext(self, rw); + const int c_i_segment = ruby_whisper_full_check_segment_index(rw, i_segment); + const int64_t t1 = whisper_full_get_segment_t1(rw->context, c_i_segment); + return LONG2NUM(t1); +} + +/* + * Whether the next segment indexed by +segment_index+ is predicated as a speaker turn. + * + * full_get_segment_speacker_turn_next(3) # => true + * + * call-seq: + * full_get_segment_speacker_turn_next(segment_index) -> bool + */ +static VALUE +ruby_whisper_full_get_segment_speaker_turn_next(VALUE self, VALUE i_segment) +{ + ruby_whisper *rw; + GetContext(self, rw); + const int c_i_segment = ruby_whisper_full_check_segment_index(rw, i_segment); + const bool speaker_turn_next = whisper_full_get_segment_speaker_turn_next(rw->context, c_i_segment); + return speaker_turn_next ? Qtrue : Qfalse; +} + +/* + * Text of a segment indexed by +segment_index+. + * + * full_get_segment_text(3) # => "ask not what your country can do for you, ..." + * + * call-seq: + * full_get_segment_text(segment_index) -> String + */ +static VALUE +ruby_whisper_full_get_segment_text(VALUE self, VALUE i_segment) +{ + ruby_whisper *rw; + GetContext(self, rw); + const int c_i_segment = ruby_whisper_full_check_segment_index(rw, i_segment); + const char * text = whisper_full_get_segment_text(rw->context, c_i_segment); + return rb_str_new2(text); +} + +/* + * call-seq: + * full_get_segment_no_speech_prob(segment_index) -> Float + */ +static VALUE +ruby_whisper_full_get_segment_no_speech_prob(VALUE self, VALUE i_segment) +{ + ruby_whisper *rw; + GetContext(self, rw); + const int c_i_segment = ruby_whisper_full_check_segment_index(rw, i_segment); + const float no_speech_prob = whisper_full_get_segment_no_speech_prob(rw->context, c_i_segment); + return DBL2NUM(no_speech_prob); +} + +static VALUE +ruby_whisper_full_n_vad_segments(VALUE self) +{ + ruby_whisper *rw; + GetContext(self, rw); + + return INT2NUM(whisper_full_n_vad_segments(rw->context)); +} + +static int +ruby_whisper_full_check_vad_segment_index(const ruby_whisper *rw, const VALUE i_segment) +{ + const int c_i_segment = NUM2INT(i_segment); + if (c_i_segment < 0 || c_i_segment >= whisper_full_n_vad_segments(rw->context)) { + rb_raise(rb_eIndexError, "segment index %d out of range", c_i_segment); + } + return c_i_segment; +} + +static VALUE +ruby_whisper_full_get_vad_segment_t0(VALUE self, VALUE i_segment) +{ + ruby_whisper *rw; + GetContext(self, rw); + const int c_i_segment = ruby_whisper_full_check_vad_segment_index(rw, i_segment); + + return LONG2NUM(whisper_full_get_vad_segment_t0(rw->context, c_i_segment)); +} + +static VALUE +ruby_whisper_full_get_vad_segment_t1(VALUE self, VALUE i_segment) +{ + ruby_whisper *rw; + GetContext(self, rw); + const int c_i_segment = ruby_whisper_full_check_vad_segment_index(rw, i_segment); + + return LONG2NUM(whisper_full_get_vad_segment_t1(rw->context, c_i_segment)); +} + +static VALUE +ruby_whisper_context_free(VALUE self) +{ + ruby_whisper *rw; + GetContext(self, rw); + whisper_free(rw->context); + rw->context = NULL; + + return Qnil; +} + +// High level API + +static VALUE +ruby_whisper_full_get_segment(VALUE self, VALUE i_segment) +{ + return rb_whisper_segment_s_new(self, NUM2INT(i_segment)); +} + +/* + * Yields each Whisper::Segment: + * + * whisper.transcribe("path/to/audio.wav", params) + * whisper.each_segment do |segment| + * puts segment.text + * end + * + * Returns an Enumerator if no block given: + * + * whisper.transcribe("path/to/audio.wav", params) + * enum = whisper.each_segment + * enum.to_a # => [#<Whisper::Segment>, ...] + * + * call-seq: + * each_segment {|segment| ... } + * each_segment -> Enumerator + */ +static VALUE +ruby_whisper_each_segment(VALUE self) +{ + if (!rb_block_given_p()) { + const VALUE method_name = rb_funcall(self, id___method__, 0); + return rb_funcall(self, id_to_enum, 1, method_name); + } + + ruby_whisper *rw; + GetContext(self, rw); + + const int n_segments = whisper_full_n_segments(rw->context); + for (int i = 0; i < n_segments; ++i) { + rb_yield(rb_whisper_segment_s_new(self, i)); + } + + return self; +} + +/* + * call-seq: + * model -> Whisper::Model + */ +static VALUE +ruby_whisper_get_model(VALUE self) +{ + return rb_whisper_model_s_new(self); +} + +VALUE +init_ruby_whisper_context(VALUE *mWhisper) +{ + cContext = rb_define_class_under(*mWhisper, "Context", rb_cObject); + + transcribe_option_names[0] = id_n_processors; + + rb_define_alloc_func(cContext, ruby_whisper_allocate); + rb_define_method(cContext, "initialize", ruby_whisper_initialize, -1); + + rb_define_method(cContext, "transcribe", ruby_whisper_transcribe, -1); + rb_define_method(cContext, "model_n_vocab", ruby_whisper_model_n_vocab, 0); + rb_define_method(cContext, "model_n_audio_ctx", ruby_whisper_model_n_audio_ctx, 0); + rb_define_method(cContext, "model_n_audio_state", ruby_whisper_model_n_audio_state, 0); + rb_define_method(cContext, "model_n_audio_head", ruby_whisper_model_n_audio_head, 0); + rb_define_method(cContext, "model_n_audio_layer", ruby_whisper_model_n_audio_layer, 0); + rb_define_method(cContext, "model_n_text_ctx", ruby_whisper_model_n_text_ctx, 0); + rb_define_method(cContext, "model_n_text_state", ruby_whisper_model_n_text_state, 0); + rb_define_method(cContext, "model_n_text_head", ruby_whisper_model_n_text_head, 0); + rb_define_method(cContext, "model_n_text_layer", ruby_whisper_model_n_text_layer, 0); + rb_define_method(cContext, "model_n_mels", ruby_whisper_model_n_mels, 0); + rb_define_method(cContext, "model_ftype", ruby_whisper_model_ftype, 0); + rb_define_method(cContext, "model_type", ruby_whisper_model_type, 0); + rb_define_method(cContext, "full_n_segments", ruby_whisper_full_n_segments, 0); + rb_define_method(cContext, "full_lang_id", ruby_whisper_full_lang_id, 0); + rb_define_method(cContext, "full_get_segment_t0", ruby_whisper_full_get_segment_t0, 1); + rb_define_method(cContext, "full_get_segment_t1", ruby_whisper_full_get_segment_t1, 1); + rb_define_method(cContext, "full_get_segment_speaker_turn_next", ruby_whisper_full_get_segment_speaker_turn_next, 1); + rb_define_method(cContext, "full_get_segment_text", ruby_whisper_full_get_segment_text, 1); + rb_define_method(cContext, "full_get_segment_no_speech_prob", ruby_whisper_full_get_segment_no_speech_prob, 1); + rb_define_method(cContext, "full_n_vad_segments", ruby_whisper_full_n_vad_segments, 0); + rb_define_method(cContext, "full_get_vad_segment_t0", ruby_whisper_full_get_vad_segment_t0, 1); + rb_define_method(cContext, "full_get_vad_segment_t1", ruby_whisper_full_get_vad_segment_t1, 1); + rb_define_method(cContext, "full", ruby_whisper_full, -1); + rb_define_method(cContext, "full_parallel", ruby_whisper_full_parallel, -1); + rb_define_method(cContext, "free", ruby_whisper_context_free, 0); + + // High level + rb_define_method(cContext, "full_get_segment", ruby_whisper_full_get_segment, 1); + rb_define_method(cContext, "each_segment", ruby_whisper_each_segment, 0); + + rb_define_method(cContext, "model", ruby_whisper_get_model, 0); + + return cContext; +} diff --git a/bindings/ruby/ext/ruby_whisper_context_params.c b/bindings/ruby/ext/ruby_whisper_context_params.c new file mode 100644 index 0000000..87df21d --- /dev/null +++ b/bindings/ruby/ext/ruby_whisper_context_params.c @@ -0,0 +1,163 @@ +#include "ruby_whisper.h" + +#define NUM_PARAMS 6 + +#define DEF_BOOLEAN_ATTR_METHOD(name) \ +static VALUE \ +ruby_whisper_context_params_get_ ## name(VALUE self) { \ + ruby_whisper_context_params *rwcp; \ + GetContextParams(self, rwcp); \ + return rwcp->params.name ? Qtrue : Qfalse; \ +} \ +static VALUE \ +ruby_whisper_context_params_set_ ## name(VALUE self, VALUE value) { \ + ruby_whisper_context_params *rwcp; \ + GetContextParams(self, rwcp); \ + rwcp->params.name = RTEST(value); \ + return value; \ +} + +#define DEF_INT_ATTR_METHOD(name) \ +static VALUE \ +ruby_whisper_context_params_get_ ## name(VALUE self) { \ + ruby_whisper_context_params *rwcp; \ + GetContextParams(self, rwcp); \ + return INT2NUM(rwcp->params.name); \ +} \ +static VALUE \ +ruby_whisper_context_params_set_ ## name(VALUE self, VALUE value) { \ + ruby_whisper_context_params *rwcp; \ + GetContextParams(self, rwcp); \ + rwcp->params.name = NUM2INT(value); \ + return value; \ +} + +#define DEFINE_PARAM(param_name, nth) \ + id_ ## param_name = rb_intern(#param_name); \ + param_names[nth] = id_ ## param_name; \ + rb_define_method(cContextParams, #param_name, ruby_whisper_context_params_get_ ## param_name, 0); \ + rb_define_method(cContextParams, #param_name "=", ruby_whisper_context_params_set_ ## param_name, 1); + +VALUE cContextParams; + +static ID param_names[NUM_PARAMS]; +static ID id_use_gpu; +static ID id_flash_attn; +static ID id_gpu_device; +static ID id_dtw_token_timestamps; +static ID id_dtw_aheads_preset; +static ID id_dtw_n_top; + +static size_t +ruby_whisper_context_params_memsize(const void *p) +{ + const ruby_whisper_context_params *rwcp = (ruby_whisper_context_params *)p; + if (!rwcp) { + return 0; + } + return sizeof(ruby_whisper_context_params); +} + +const rb_data_type_t ruby_whisper_context_params_type = { + "ruby_whisper_context_params", + {0, RUBY_DEFAULT_FREE, ruby_whisper_context_params_memsize,}, + 0, 0, + 0 +}; + +static VALUE +ruby_whisper_context_params_s_allocate(VALUE klass) +{ + ruby_whisper_context_params *rwcp; + return TypedData_Make_Struct(klass, ruby_whisper_context_params, &ruby_whisper_context_params_type, rwcp); +} + +DEF_BOOLEAN_ATTR_METHOD(use_gpu); +DEF_BOOLEAN_ATTR_METHOD(flash_attn); +DEF_INT_ATTR_METHOD(gpu_device); +DEF_BOOLEAN_ATTR_METHOD(dtw_token_timestamps); +DEF_INT_ATTR_METHOD(dtw_aheads_preset); + +static VALUE +ruby_whisper_context_params_get_dtw_n_top(VALUE self) { + ruby_whisper_context_params *rwcp; + GetContextParams(self, rwcp); + + int dtw_n_top = rwcp->params.dtw_n_top; + + return dtw_n_top == -1 ? Qnil : INT2NUM(dtw_n_top); +} + +static VALUE +ruby_whisper_context_params_set_dtw_n_top(VALUE self, VALUE value) { + ruby_whisper_context_params *rwcp; + GetContextParams(self, rwcp); + + rwcp->params.dtw_n_top = NIL_P(value) ? -1 : NUM2INT(value); + + return value; +} + +#define SET_PARAM_IF_SAME(param_name) \ + if (id == id_ ## param_name) { \ + ruby_whisper_context_params_set_ ## param_name(self, value); \ + continue; \ + } + +static VALUE +ruby_whisper_context_params_initialize(int argc, VALUE *argv, VALUE self) +{ + ruby_whisper_context_params *rwcp; + TypedData_Get_Struct(self, ruby_whisper_context_params, &ruby_whisper_context_params_type, rwcp); + rwcp->params = whisper_context_default_params(); + + VALUE kw_hash; + rb_scan_args_kw(RB_SCAN_ARGS_KEYWORDS, argc, argv, ":", &kw_hash); + if (NIL_P(kw_hash)) { + return Qnil; + } + + VALUE values[NUM_PARAMS] = {Qundef}; + rb_get_kwargs(kw_hash, param_names, 0, NUM_PARAMS, values); + + ID id; + VALUE value; + for (int i = 0; i < NUM_PARAMS; i++) { + id = param_names[i]; + value = values[i]; + if (value == Qundef) { + continue; + } + SET_PARAM_IF_SAME(use_gpu) + SET_PARAM_IF_SAME(flash_attn) + SET_PARAM_IF_SAME(gpu_device) + SET_PARAM_IF_SAME(dtw_token_timestamps) + SET_PARAM_IF_SAME(dtw_aheads_preset) + SET_PARAM_IF_SAME(dtw_n_top) + } + + return Qnil; +} + +#undef SET_PARAM_IF_SAME + +void +init_ruby_whisper_context_params(VALUE *cContext) +{ + cContextParams = rb_define_class_under(*cContext, "Params", rb_cObject); + + rb_define_alloc_func(cContextParams, ruby_whisper_context_params_s_allocate); + rb_define_method(cContextParams, "initialize", ruby_whisper_context_params_initialize, -1); + + DEFINE_PARAM(use_gpu, 0) + DEFINE_PARAM(flash_attn, 1) + DEFINE_PARAM(gpu_device, 2) + DEFINE_PARAM(dtw_token_timestamps, 3) + DEFINE_PARAM(dtw_aheads_preset, 4) + DEFINE_PARAM(dtw_n_top, 5) +} + +#undef DEFINE_PARAM +#undef DEF_INT_ATTR_METHOD +#undef DEF_BOOLEAN_ATTR_METHOD +#undef NUM_PARAMS diff --git a/bindings/ruby/ext/ruby_whisper_error.c b/bindings/ruby/ext/ruby_whisper_error.c new file mode 100644 index 0000000..b4dbec0 --- /dev/null +++ b/bindings/ruby/ext/ruby_whisper_error.c @@ -0,0 +1,52 @@ +#include <ruby.h> + +extern VALUE eError; + +VALUE ruby_whisper_error_initialize(VALUE self, VALUE code) +{ + const int c_code = NUM2INT(code); + const char *raw_message; + switch (c_code) { + case -2: + raw_message = "failed to compute log mel spectrogram"; + break; + case -3: + raw_message = "failed to auto-detect language"; + break; + case -4: + raw_message = "too many decoders requested"; + break; + case -5: + raw_message = "audio_ctx is larger than the maximum allowed"; + break; + case -6: + raw_message = "failed to encode"; + break; + case -7: + raw_message = "whisper_kv_cache_init() failed for self-attention cache"; + break; + case -8: + raw_message = "failed to decode"; + break; + case -9: + raw_message = "failed to decode"; + break; + default: + raw_message = "unknown error"; + break; + } + const VALUE message = rb_str_new2(raw_message); + rb_call_super(1, &message); + rb_iv_set(self, "@code", code); + + return self; +} + +void +init_ruby_whisper_error(VALUE *mWhisper) +{ + eError = rb_define_class_under(*mWhisper, "Error", rb_eStandardError); + + rb_define_attr(eError, "code", true, false); + rb_define_method(eError, "initialize", ruby_whisper_error_initialize, 1); +} diff --git a/bindings/ruby/ext/ruby_whisper_log_queue.c b/bindings/ruby/ext/ruby_whisper_log_queue.c new file mode 100644 index 0000000..6558a33 --- /dev/null +++ b/bindings/ruby/ext/ruby_whisper_log_queue.c @@ -0,0 +1,180 @@ +#include "ruby_whisper.h" + +#define LOG_QUEUE_CAPACITY 256 +#define LOG_DEFAULT_CAPACITY 1024 + +void +ruby_whisper_log_queue_initialize(ruby_whisper_log_queue *log_queue) +{ + rb_nativethread_lock_initialize(&log_queue->lock); + rb_native_cond_initialize(&log_queue->cond); + log_queue->head = 0; + log_queue->tail = 0; + log_queue->size = 0; + log_queue->is_open = true; + log_queue->logs = ALLOC_N(ruby_whisper_log, LOG_QUEUE_CAPACITY); + for (size_t i = 0; i < LOG_QUEUE_CAPACITY; i++) { + // we cannot call Ruby API like ALLOC_N because this slot may be realloced without GVL + // this doesn't be freed because log queue lives until the end of process + char *slot = malloc(sizeof(char) * LOG_QUEUE_CAPACITY); + if (!slot) { + rb_raise(rb_eRuntimeError, "Could not allocate memory for log text"); + } + ruby_whisper_log log = { + 0, + slot, + 0, + LOG_QUEUE_CAPACITY, + }; + log_queue->logs[i] = log; + } +} + +void +ruby_whisper_log_queue_open(ruby_whisper_log_queue *log_queue) +{ + rb_nativethread_lock_lock(&log_queue->lock); + + log_queue->is_open = true; + + rb_native_cond_signal(&log_queue->cond); + + rb_nativethread_lock_unlock(&log_queue->lock); +} + +void +ruby_whisper_log_queue_close(ruby_whisper_log_queue *log_queue) +{ + rb_nativethread_lock_lock(&log_queue->lock); + + log_queue->is_open = false; + rb_native_cond_broadcast(&log_queue->cond); + + rb_nativethread_lock_unlock(&log_queue->lock); +} + +static size_t +calc_enough_cap(size_t len) +{ + size_t quot = len / LOG_DEFAULT_CAPACITY; + size_t rem = len % LOG_DEFAULT_CAPACITY; + + return sizeof(char) * (rem == 0 ? quot : quot + 1) * LOG_DEFAULT_CAPACITY; +} + +void +ruby_whisper_log_queue_enqueue(ruby_whisper_log_queue *log_queue, enum ggml_log_level level, const char *text) +{ + rb_nativethread_lock_lock(&log_queue->lock); + + if (!log_queue->is_open) { + rb_nativethread_lock_unlock(&log_queue->lock); + return; + } + + size_t len = strlen(text); + ruby_whisper_log *log = &log_queue->logs[log_queue->head]; + if (len > log->capacity) { + size_t new_cap = calc_enough_cap(len); + // we cannot call Ruby API like REALLOC_N because this function is called without GVL + char *slot = realloc(log->text, new_cap); + if (!slot) { + rb_nativethread_lock_unlock(&log_queue->lock); + return; + } + log->text = slot; + log->capacity = new_cap; + } + // we cannot call Ruby API like MEMCPY because this function is called without GVL + memcpy(log->text, text, sizeof(char) * len); + log->length = len; + log->level = level; + log_queue->head = (log_queue->head + 1) % LOG_QUEUE_CAPACITY; + bool is_full = log_queue->size >= LOG_QUEUE_CAPACITY; + log_queue->size = is_full ? LOG_QUEUE_CAPACITY : log_queue->size + 1; + if (is_full) { + log_queue->tail = log_queue->head; + } + + rb_native_cond_signal(&log_queue->cond); + rb_nativethread_lock_unlock(&log_queue->lock); +} + +static void* +ruby_whisper_log_queue_wait(void *args) +{ + ruby_whisper_log_queue *log_queue = (ruby_whisper_log_queue *)args; + + rb_native_cond_wait(&log_queue->cond, &log_queue->lock); + rb_nativethread_lock_unlock(&log_queue->lock); + + return NULL; +} + +static void +ruby_whisper_log_queue_wait_ubf(void *args) +{ + ruby_whisper_log_queue *log_queue = (ruby_whisper_log_queue *)args; + + rb_native_cond_broadcast(&log_queue->cond); +} + +typedef struct { + enum ggml_log_level level; + size_t length; + char *text; +} log_snapshot; + +VALUE +ruby_whisper_log_queue_drain(ruby_whisper_log_queue *log_queue) +{ + log_snapshot logs[LOG_QUEUE_CAPACITY]; + + rb_nativethread_lock_lock(&log_queue->lock); + + while (log_queue->size == 0 && log_queue->is_open) { + rb_thread_call_without_gvl(ruby_whisper_log_queue_wait, (void *)log_queue, ruby_whisper_log_queue_wait_ubf, (void *)log_queue); + rb_nativethread_lock_lock(&log_queue->lock); + } + + if (log_queue->size == 0 && !log_queue->is_open) { + rb_native_cond_broadcast(&log_queue->cond); + rb_nativethread_lock_unlock(&log_queue->lock); + return Qnil; + } + + size_t size = log_queue->size; + ruby_whisper_log *log; + size_t i; + for (i = 0; i < size; i++) { + log = &log_queue->logs[(log_queue->tail + i) % LOG_QUEUE_CAPACITY]; + logs[i].level = log->level; + logs[i].length = log->length; + char *text = malloc(log->length); + if (!text) { + logs[i].text = NULL; + continue; + } + logs[i].text = text; + memcpy(logs[i].text, log->text, log->length); + } + log_queue->size = 0; + log_queue->tail = log_queue->head; + + rb_native_cond_signal(&log_queue->cond); + + rb_nativethread_lock_unlock(&log_queue->lock); + + VALUE rb_logs = rb_ary_new2(size); + VALUE rb_text; + for (i = 0; i < size; i++) { + if (!logs[i].text) { + continue; + } + rb_text = rb_str_new(logs[i].text, logs[i].length); + free(logs[i].text); + rb_ary_push(rb_logs, rb_ary_new3(2, INT2NUM(logs[i].level), rb_text)); + } + + return rb_logs; +} diff --git a/bindings/ruby/ext/ruby_whisper_log_settable.h b/bindings/ruby/ext/ruby_whisper_log_settable.h new file mode 100644 index 0000000..04f9877 --- /dev/null +++ b/bindings/ruby/ext/ruby_whisper_log_settable.h @@ -0,0 +1,46 @@ +#ifndef RUBY_WHISPER_LOG_SETTABLE_H +#define RUBY_WHISPER_LOG_SETTABLE_H + +#define LOG_SETTABLE_SETUP(log_queue, mod, log_set) \ + static VALUE \ + ruby_whisper_##log_queue##_s_drain_logs(VALUE self) \ + { \ + return ruby_whisper_log_queue_drain(&log_queue); \ + } \ + static void \ + ruby_whisper_##log_queue##_log_callback(enum ggml_log_level level, const char *text, void *user_data) \ + { \ + ruby_whisper_log_queue_enqueue(&log_queue, level, text); \ + } \ + static VALUE \ + ruby_whisper_##log_queue##_s_log_set(VALUE self, VALUE log_callback, VALUE user_data) \ + { \ + rb_iv_set(self, "@log_callback", log_callback); \ + rb_iv_set(self, "@log_callback_user_data", user_data); \ + if (NIL_P(log_callback)) { \ + log_set(NULL, NULL); \ + } else { \ + ruby_whisper_log_queue_open(&log_queue); \ + rb_funcall((mod), id_start_log_callback_thread, 0); \ + log_set(ruby_whisper_##log_queue##_log_callback, NULL); \ + } \ + return Qnil; \ + } \ + static void \ + ruby_whisper_##log_queue##_end_proc(VALUE args) \ + { \ + ruby_whisper_log_queue_close(&log_queue); \ + VALUE log_callback_thread = rb_ivar_get(mod, id_log_callback_thread); \ + if (!NIL_P(log_callback_thread) && RTEST(rb_funcall(log_callback_thread, id_alive_p, 0))) { \ + rb_funcall(log_callback_thread, id_join, 0); \ + } \ + } + +#define LOG_SETTABLE_INIT(log_queue, mod) \ + ruby_whisper_log_queue_initialize(&log_queue); \ + rb_define_singleton_method(mod, "drain_logs", ruby_whisper_##log_queue##_s_drain_logs, 0); \ + rb_define_singleton_method(mod, "log_set", ruby_whisper_##log_queue##_s_log_set, 2); \ + rb_set_end_proc(ruby_whisper_##log_queue##_end_proc, Qnil); \ + rb_extend_object(mod, mLogSettable); + +#endif diff --git a/bindings/ruby/ext/ruby_whisper_model.c b/bindings/ruby/ext/ruby_whisper_model.c new file mode 100644 index 0000000..0e91fb3 --- /dev/null +++ b/bindings/ruby/ext/ruby_whisper_model.c @@ -0,0 +1,231 @@ +#include "ruby_whisper.h" + +extern const rb_data_type_t ruby_whisper_type; + +extern VALUE cModel; + +static void rb_whisper_model_mark(void *p) { + ruby_whisper_model *rwm = (ruby_whisper_model *)p; + if (rwm->context) { + rb_gc_mark(rwm->context); + } +} + +static size_t +ruby_whisper_model_memsize(const void *p) +{ + const ruby_whisper_model *rwm = (const ruby_whisper_model *)p; + size_t size = sizeof(rwm); + if (!rwm) { + return 0; + } + return size; +} + +static const rb_data_type_t rb_whisper_model_type = { + "ruby_whisper_model", + {rb_whisper_model_mark, RUBY_DEFAULT_FREE, ruby_whisper_model_memsize,}, + 0, 0, + 0 +}; + +static VALUE ruby_whisper_model_allocate(VALUE klass) { + ruby_whisper_model *rwm; + return TypedData_Make_Struct(klass, ruby_whisper_model, &rb_whisper_model_type, rwm); +} + +VALUE rb_whisper_model_s_new(VALUE context) { + ruby_whisper_model *rwm; + const VALUE model = ruby_whisper_model_allocate(cModel); + TypedData_Get_Struct(model, ruby_whisper_model, &rb_whisper_model_type, rwm); + rwm->context = context; + return model; +}; + +/* + * call-seq: + * n_vocab -> Integer + */ +static VALUE +ruby_whisper_model_n_vocab(VALUE self) +{ + ruby_whisper_model *rwm; + TypedData_Get_Struct(self, ruby_whisper_model, &rb_whisper_model_type, rwm); + ruby_whisper *rw; + GetContext(rwm->context, rw); + return INT2NUM(whisper_model_n_vocab(rw->context)); +} + +/* + * call-seq: + * n_audio_ctx -> Integer + */ +static VALUE +ruby_whisper_model_n_audio_ctx(VALUE self) +{ + ruby_whisper_model *rwm; + TypedData_Get_Struct(self, ruby_whisper_model, &rb_whisper_model_type, rwm); + ruby_whisper *rw; + GetContext(rwm->context, rw); + return INT2NUM(whisper_model_n_audio_ctx(rw->context)); +} + +/* + * call-seq: + * n_audio_state -> Integer + */ +static VALUE +ruby_whisper_model_n_audio_state(VALUE self) +{ + ruby_whisper_model *rwm; + TypedData_Get_Struct(self, ruby_whisper_model, &rb_whisper_model_type, rwm); + ruby_whisper *rw; + GetContext(rwm->context, rw); + return INT2NUM(whisper_model_n_audio_state(rw->context)); +} + +/* + * call-seq: + * n_audio_head -> Integer + */ +static VALUE +ruby_whisper_model_n_audio_head(VALUE self) +{ + ruby_whisper_model *rwm; + TypedData_Get_Struct(self, ruby_whisper_model, &rb_whisper_model_type, rwm); + ruby_whisper *rw; + GetContext(rwm->context, rw); + return INT2NUM(whisper_model_n_audio_head(rw->context)); +} + +/* + * call-seq: + * n_audio_layer -> Integer + */ +static VALUE +ruby_whisper_model_n_audio_layer(VALUE self) +{ + ruby_whisper_model *rwm; + TypedData_Get_Struct(self, ruby_whisper_model, &rb_whisper_model_type, rwm); + ruby_whisper *rw; + GetContext(rwm->context, rw); + return INT2NUM(whisper_model_n_audio_layer(rw->context)); +} + +/* + * call-seq: + * n_text_ctx -> Integer + */ +static VALUE +ruby_whisper_model_n_text_ctx(VALUE self) +{ + ruby_whisper_model *rwm; + TypedData_Get_Struct(self, ruby_whisper_model, &rb_whisper_model_type, rwm); + ruby_whisper *rw; + GetContext(rwm->context, rw); + return INT2NUM(whisper_model_n_text_ctx(rw->context)); +} + +/* + * call-seq: + * n_text_state -> Integer + */ +static VALUE +ruby_whisper_model_n_text_state(VALUE self) +{ + ruby_whisper_model *rwm; + TypedData_Get_Struct(self, ruby_whisper_model, &rb_whisper_model_type, rwm); + ruby_whisper *rw; + GetContext(rwm->context, rw); + return INT2NUM(whisper_model_n_text_state(rw->context)); +} + +/* + * call-seq: + * n_text_head -> Integer + */ +static VALUE +ruby_whisper_model_n_text_head(VALUE self) +{ + ruby_whisper_model *rwm; + TypedData_Get_Struct(self, ruby_whisper_model, &rb_whisper_model_type, rwm); + ruby_whisper *rw; + GetContext(rwm->context, rw); + return INT2NUM(whisper_model_n_text_head(rw->context)); +} + +/* + * call-seq: + * n_text_layer -> Integer + */ +static VALUE +ruby_whisper_model_n_text_layer(VALUE self) +{ + ruby_whisper_model *rwm; + TypedData_Get_Struct(self, ruby_whisper_model, &rb_whisper_model_type, rwm); + ruby_whisper *rw; + GetContext(rwm->context, rw); + return INT2NUM(whisper_model_n_text_layer(rw->context)); +} + +/* + * call-seq: + * n_mels -> Integer + */ +static VALUE +ruby_whisper_model_n_mels(VALUE self) +{ + ruby_whisper_model *rwm; + TypedData_Get_Struct(self, ruby_whisper_model, &rb_whisper_model_type, rwm); + ruby_whisper *rw; + GetContext(rwm->context, rw); + return INT2NUM(whisper_model_n_mels(rw->context)); +} + +/* + * call-seq: + * ftype -> Integer + */ +static VALUE +ruby_whisper_model_ftype(VALUE self) +{ + ruby_whisper_model *rwm; + TypedData_Get_Struct(self, ruby_whisper_model, &rb_whisper_model_type, rwm); + ruby_whisper *rw; + GetContext(rwm->context, rw); + return INT2NUM(whisper_model_ftype(rw->context)); +} + +/* + * call-seq: + * type -> String + */ +static VALUE +ruby_whisper_model_type(VALUE self) +{ + ruby_whisper_model *rwm; + TypedData_Get_Struct(self, ruby_whisper_model, &rb_whisper_model_type, rwm); + ruby_whisper *rw; + GetContext(rwm->context, rw); + return rb_str_new2(whisper_model_type_readable(rw->context)); +} + +void +init_ruby_whisper_model(VALUE *mWhisper) +{ + cModel = rb_define_class_under(*mWhisper, "Model", rb_cObject); + + rb_define_alloc_func(cModel, ruby_whisper_model_allocate); + rb_define_method(cModel, "n_vocab", ruby_whisper_model_n_vocab, 0); + rb_define_method(cModel, "n_audio_ctx", ruby_whisper_model_n_audio_ctx, 0); + rb_define_method(cModel, "n_audio_state", ruby_whisper_model_n_audio_state, 0); + rb_define_method(cModel, "n_audio_head", ruby_whisper_model_n_audio_head, 0); + rb_define_method(cModel, "n_audio_layer", ruby_whisper_model_n_audio_layer, 0); + rb_define_method(cModel, "n_text_ctx", ruby_whisper_model_n_text_ctx, 0); + rb_define_method(cModel, "n_text_state", ruby_whisper_model_n_text_state, 0); + rb_define_method(cModel, "n_text_head", ruby_whisper_model_n_text_head, 0); + rb_define_method(cModel, "n_text_layer", ruby_whisper_model_n_text_layer, 0); + rb_define_method(cModel, "n_mels", ruby_whisper_model_n_mels, 0); + rb_define_method(cModel, "ftype", ruby_whisper_model_ftype, 0); + rb_define_method(cModel, "type", ruby_whisper_model_type, 0); +} diff --git a/bindings/ruby/ext/ruby_whisper_parakeet.c b/bindings/ruby/ext/ruby_whisper_parakeet.c new file mode 100644 index 0000000..d693694 --- /dev/null +++ b/bindings/ruby/ext/ruby_whisper_parakeet.c @@ -0,0 +1,49 @@ +#include "ruby_whisper.h" +#include <stdio.h> +#include <unistd.h> + +extern VALUE mParakeet; +extern VALUE mLogSettable; +extern VALUE cParakeetContext; +extern VALUE cParakeetSegment; +extern VALUE mOutputContext; +extern VALUE mOutputSegment; + +extern void init_ruby_whisper_parakeet_params(VALUE *mParakeet); +extern void init_ruby_whisper_parakeet_token(VALUE *mParakeet); +extern void init_ruby_whisper_parakeet_segment(VALUE *mParakeet); +extern VALUE init_ruby_whisper_parakeet_context(VALUE *mParakeet); +extern void init_ruby_whisper_parakeet_context_params(VALUE *cParakeetContext); +extern void init_ruby_whisper_parakeet_model(VALUE *mParakeet); + +static ruby_whisper_log_queue parakeet_log_queue; + +LOG_SETTABLE_SETUP(parakeet_log_queue, mParakeet, parakeet_log_set) + +static VALUE +ruby_whisper_parakeet_s_system_info_str(VALUE self) +{ + return rb_str_new2(parakeet_print_system_info()); +} + +void +init_ruby_whisper_parakeet(VALUE *mWhisper) +{ + mParakeet = rb_define_module_under(*mWhisper, "Parakeet"); + + rb_define_const(mParakeet, "VERSION", rb_str_new2(parakeet_version())); + + LOG_SETTABLE_INIT(parakeet_log_queue, mParakeet) + + rb_define_singleton_method(mParakeet, "system_info_str", ruby_whisper_parakeet_s_system_info_str, 0); + + init_ruby_whisper_parakeet_params(&mParakeet); + init_ruby_whisper_parakeet_token(&mParakeet); + init_ruby_whisper_parakeet_segment(&mParakeet); + cParakeetContext = init_ruby_whisper_parakeet_context(&mParakeet); + init_ruby_whisper_parakeet_context_params(&cParakeetContext); + init_ruby_whisper_parakeet_model(&mParakeet); + + rb_include_module(cParakeetContext, mOutputContext); + rb_include_module(cParakeetSegment, mOutputSegment); +} diff --git a/bindings/ruby/ext/ruby_whisper_parakeet_context.c b/bindings/ruby/ext/ruby_whisper_parakeet_context.c new file mode 100644 index 0000000..8ac551d --- /dev/null +++ b/bindings/ruby/ext/ruby_whisper_parakeet_context.c @@ -0,0 +1,316 @@ +#include "ruby_whisper.h" + +#define ITERATE_SEGMENT_ATTRS(ITERATOR) \ + ITERATOR(get_segment_t0, LONG) \ + ITERATOR(get_segment_t1, LONG) \ + ITERATOR(get_segment_text, STRING) \ + ITERATOR(n_tokens, INT) + +#define ITERATE_TOKEN_ATTRS(ITERATOR) \ + ITERATOR(get_token_text, STRING) \ + ITERATOR(get_token_id, INT) \ + ITERATOR(get_token_p, FLOAT) + +#define VAL_FROM_LONG(v) LONG2NUM(v) +#define VAL_FROM_STRING(v) rb_utf8_str_new_cstr(v) +#define VAL_FROM_INT(v) INT2NUM(v) +#define VAL_FROM_FLOAT(v) DBL2NUM(v) +#define READER(type) VAL_FROM_##type + +extern ID id_to_s; +extern ID id___method__; +extern ID id_to_enum; +extern ID id_new; + +extern VALUE cParakeetContext; +extern VALUE eError; + +extern VALUE ruby_whisper_normalize_model_path(VALUE model_path); +extern VALUE ruby_whisper_parakeet_transcribe(VALUE self, VALUE audio_path, VALUE params); +extern VALUE ruby_whisper_parakeet_segment_init(VALUE context, int index); +extern parsed_samples_t parse_samples(VALUE *samples, VALUE *n_samples); +extern VALUE release_samples(VALUE rb_parsed_args); +extern void ruby_whisper_parakeet_prepare_transcription(ruby_whisper_parakeet_params *rwpp, VALUE *context, ruby_whisper_abort_callback_user_data *abort_callback_user_data); +extern rb_data_type_t ruby_whisper_parakeet_params_type; +extern rb_data_type_t ruby_whisper_parakeet_context_params_type; +extern VALUE ruby_whisper_parakeet_token_s_from_token_data(struct parakeet_context *context, const parakeet_token_data *token_data); +extern VALUE ruby_whisper_parakeet_model_s_new(VALUE context); + +static void +ruby_whisper_parakeet_context_free(void *p) +{ + ruby_whisper_parakeet_context *rwpc = (ruby_whisper_parakeet_context *)p; + if (rwpc->context) { + parakeet_free(rwpc->context); + rwpc->context = NULL; + } + xfree(rwpc); +} + +static size_t +ruby_whisper_parakeet_context_memsize(const void *p) +{ + ruby_whisper_parakeet_context *rwpc = (ruby_whisper_parakeet_context *)p; + if (!rwpc) { + return 0; + } + size_t size = sizeof(*rwpc); + return size; +} + +const rb_data_type_t ruby_whisper_parakeet_context_type = { + "ruby_whisper_parakeet_context", + {0, ruby_whisper_parakeet_context_free, ruby_whisper_parakeet_context_memsize,}, + 0, 0, + 0 +}; + +static VALUE +ruby_whisper_parakeet_context_allocate(VALUE klass) +{ + ruby_whisper_parakeet_context *rwpc; + + VALUE obj = TypedData_Make_Struct(klass, ruby_whisper_parakeet_context, &ruby_whisper_parakeet_context_type, rwpc); + rwpc->context = NULL; + + return obj; +} + +typedef struct { + struct parakeet_context **context; + char *model_path; + struct parakeet_context_params params; +} ruby_whisper_parakeet_context_init_args; + +static void* +ruby_whisper_parakeet_context_init_without_gvl(void *args) +{ + ruby_whisper_parakeet_context_init_args *init_args = (ruby_whisper_parakeet_context_init_args *)args; + *init_args->context = parakeet_init_from_file_with_params(init_args->model_path, init_args->params); + return NULL; +} + +static VALUE +ruby_whisper_parakeet_context_initialize(int argc, VALUE *argv, VALUE self) +{ + ruby_whisper_parakeet_context *rwpc; + VALUE model_path; + VALUE context_params; + struct parakeet_context_params params; + + rb_scan_args(argc, argv, "11", &model_path, &context_params); + TypedData_Get_Struct(self, ruby_whisper_parakeet_context, &ruby_whisper_parakeet_context_type, rwpc); + + model_path = ruby_whisper_normalize_model_path(model_path); + if (!rb_respond_to(model_path, id_to_s)) { + rb_raise(rb_eRuntimeError, "Expected file path to model to initialize Parakeet::Context"); + } + if (NIL_P(context_params)) { + params = parakeet_context_default_params(); + } else { + ruby_whisper_parakeet_context_params *rwpcp; + GetParakeetContextParams(context_params, rwpcp); + params = rwpcp->params; + } + ruby_whisper_parakeet_context_init_args init_args = { + &rwpc->context, + StringValueCStr(model_path), + params, + }; + rb_thread_call_without_gvl(ruby_whisper_parakeet_context_init_without_gvl, (void *)&init_args, NULL, NULL); + if (rwpc->context == NULL) { + rb_raise(rb_eRuntimeError, "Failed to load model"); + } + + return Qnil; +} + +static VALUE +ruby_whisper_parakeet_context_full_n_segments(VALUE self) +{ + ruby_whisper_parakeet_context *rwpc; + GetParakeetContext(self, rwpc); + + return INT2NUM(parakeet_full_n_segments(rwpc->context)); +} + +#define DEF_SEGMENT_ATTR(name, type) \ + static VALUE \ + ruby_whisper_parakeet_context_full_##name(VALUE self, VALUE i_segment) \ + { \ + ruby_whisper_parakeet_context *rwpc; \ + GetParakeetContext(self, rwpc); \ + return READER(type)(parakeet_full_##name(rwpc->context, NUM2INT(i_segment))); \ + } + +ITERATE_SEGMENT_ATTRS(DEF_SEGMENT_ATTR) + +#define DEF_TOKEN_ATTR(name, type) \ + static VALUE \ + ruby_whisper_parakeet_context_full_##name(VALUE self, VALUE i_segment, VALUE i_token) \ + { \ + ruby_whisper_parakeet_context *rwpc; \ + GetParakeetContext(self, rwpc); \ + return READER(type)(parakeet_full_##name(rwpc->context, NUM2INT(i_segment), NUM2INT(i_token))); \ + } + +ITERATE_TOKEN_ATTRS(DEF_TOKEN_ATTR) + +static VALUE +ruby_whisper_parakeet_context_full_get_token_data(VALUE self, VALUE i_segment, VALUE i_token) +{ + ruby_whisper_parakeet_context *rwpc; + GetParakeetContext(self, rwpc); + parakeet_token_data token_data = parakeet_full_get_token_data(rwpc->context, NUM2INT(i_segment), NUM2INT(i_token)); + + return ruby_whisper_parakeet_token_s_from_token_data(rwpc->context, &token_data); +} + +static VALUE +ruby_whisper_parakeet_context_each_segment(VALUE self) +{ + if (!rb_block_given_p()) { + const VALUE method_name = rb_funcall(self, id___method__, 0); + return rb_funcall(self, id_to_enum, 1, method_name); + } + + ruby_whisper_parakeet_context *rwpc; + GetParakeetContext(self, rwpc); + + const int n_segments = parakeet_full_n_segments(rwpc->context); + for (int i = 0; i < n_segments; ++i) { + rb_yield(ruby_whisper_parakeet_segment_init(self, i)); + } + + return self; +} + +typedef struct { + struct parakeet_context *context; + struct parakeet_full_params *params; + float *samples; + int n_samples; + int result; +} parakeet_full_without_gvl_args; + +static void* +parakeet_full_without_gvl(void *rb_args) +{ + parakeet_full_without_gvl_args *args = (parakeet_full_without_gvl_args *)rb_args; + args->result = parakeet_full(args->context, *args->params, args->samples, args->n_samples); + + return NULL; +} + +typedef struct { + ruby_whisper_abort_callback_user_data *abort_callback_user_data; +} parakeet_full_ubf_args; + +static void +parakeet_full_ubf(void *rb_args) +{ + parakeet_full_ubf_args *args = (parakeet_full_ubf_args *)rb_args; + + RUBY_ATOMIC_SET(args->abort_callback_user_data->is_interrupted, 1); +} + +VALUE +ruby_whisper_parakeet_context_full_body(VALUE rb_args) +{ + ruby_whisper_full_args *args = (ruby_whisper_full_args *)rb_args; + ruby_whisper_parakeet_context *rwpc; + GetParakeetContext(*args->context, rwpc); + ruby_whisper_parakeet_params *rwpp; + GetParakeetParams(*args->params, rwpp); + + ruby_whisper_abort_callback_user_data abort_callback_user_data = { + 0, + NULL, + }; + ruby_whisper_parakeet_prepare_transcription(rwpp, args->context, &abort_callback_user_data); + + parakeet_full_without_gvl_args full_without_gvl_args = { + rwpc->context, + &rwpp->params, + args->samples, + args->n_samples, + 0 + }; + parakeet_full_ubf_args full_ubf_args = { + &abort_callback_user_data, + }; + rb_thread_call_without_gvl(parakeet_full_without_gvl, (void *)&full_without_gvl_args, parakeet_full_ubf, (void *)&full_ubf_args); + + return INT2NUM(full_without_gvl_args.result); +} + +static VALUE +ruby_whisper_parakeet_context_full(int argc, VALUE *argv, VALUE self) +{ + if (argc < 2 || argc > 3) { + rb_raise(rb_eArgError, "wrong number of arguments (given %d, expected 2..3)", argc); + } + + VALUE n_samples = argc == 2 ? Qnil : argv[2]; + + struct parsed_samples_t parsed = parse_samples(&argv[1], &n_samples); + ruby_whisper_full_args args = { + &self, + &argv[0], + parsed.samples, + parsed.n_samples, + }; + VALUE rb_result = rb_ensure(ruby_whisper_parakeet_context_full_body, (VALUE)&args, release_samples, (VALUE)&parsed); + const int result = NUM2INT(rb_result); + if (result == 0) { + return self; + } else { + rb_exc_raise(rb_funcall(eError, id_new, 1, rb_result)); + } +} + +static VALUE +ruby_whisper_parakeet_free(VALUE self) +{ + ruby_whisper_parakeet_context *rwpc; + GetParakeetContext(self, rwpc); + parakeet_free(rwpc->context); + rwpc->context = NULL; + + return Qnil; +} + +static VALUE +ruby_whisper_parakeet_context_get_model(VALUE self) +{ + return ruby_whisper_parakeet_model_s_new(self); +} + +VALUE +init_ruby_whisper_parakeet_context(VALUE *mParakeet) +{ + cParakeetContext = rb_define_class_under(*mParakeet, "Context", rb_cObject); + + rb_define_alloc_func(cParakeetContext, ruby_whisper_parakeet_context_allocate); + + rb_define_method(cParakeetContext, "initialize", ruby_whisper_parakeet_context_initialize, -1); + rb_define_method(cParakeetContext, "transcribe", ruby_whisper_parakeet_transcribe, 2); + rb_define_method(cParakeetContext, "full_n_segments", ruby_whisper_parakeet_context_full_n_segments, 0); + rb_define_method(cParakeetContext, "full_get_token_data", ruby_whisper_parakeet_context_full_get_token_data, 2); + rb_define_method(cParakeetContext, "model", ruby_whisper_parakeet_context_get_model, 0); + rb_define_method(cParakeetContext, "each_segment", ruby_whisper_parakeet_context_each_segment, 0); + rb_define_method(cParakeetContext, "full", ruby_whisper_parakeet_context_full, -1); + rb_define_method(cParakeetContext, "free", ruby_whisper_parakeet_free, 0); + +#define REGISTER_SEGMENT_ATTR(name, type) \ + rb_define_method(cParakeetContext, "full_" #name, ruby_whisper_parakeet_context_full_##name, 1); + + ITERATE_SEGMENT_ATTRS(REGISTER_SEGMENT_ATTR) + +#define REGISTER_TOKEN_ATTR(name, type) \ + rb_define_method(cParakeetContext, "full_" #name, ruby_whisper_parakeet_context_full_##name, 2); + + ITERATE_TOKEN_ATTRS(REGISTER_TOKEN_ATTR) + + return cParakeetContext; +} diff --git a/bindings/ruby/ext/ruby_whisper_parakeet_context_params.c b/bindings/ruby/ext/ruby_whisper_parakeet_context_params.c new file mode 100644 index 0000000..38bd6d5 --- /dev/null +++ b/bindings/ruby/ext/ruby_whisper_parakeet_context_params.c @@ -0,0 +1,117 @@ +#include "ruby_whisper.h" + +#define ITERATE_ATTRS(ITERATOR) \ + ITERATOR(use_gpu, BOOL) \ + ITERATOR(gpu_device, INT) + +#define VAL_FROM_BOOL(v) ((v) ? Qtrue : Qfalse) +#define VAL_TO_BOOL(v) (RTEST(v)) +#define VAL_FROM_INT(v) (INT2NUM(v)) +#define VAL_TO_INT(v) (NUM2INT(v)) +#define READER(type) VAL_FROM_##type +#define WRITER(type) VAL_TO_##type + +#define DEF_ATTR(name, type) \ + static VALUE \ + ruby_whisper_parakeet_context_params_get_##name(VALUE self) \ + { \ + ruby_whisper_parakeet_context_params *rwpcp; \ + GetParakeetContextParams(self, rwpcp); \ + return READER(type)(rwpcp->params.name); \ + } \ + static VALUE \ + ruby_whisper_parakeet_context_params_set_##name(VALUE self, VALUE val) \ + { \ + ruby_whisper_parakeet_context_params *rwpcp; \ + GetParakeetContextParams(self, rwpcp); \ + rwpcp->params.name = WRITER(type)(val); \ + return val; \ + } + +enum { +#define DEF_IDX(name, type) RUBY_WHISPER_PARAKEET_CONTEXT_PARAMS_##name, + + ITERATE_ATTRS(DEF_IDX) + RUBY_WHISPER_PARAKEET_NUM_CONTEXT_PARAMS +}; + +extern VALUE cParakeetContextParams; + +typedef VALUE (*param_writer_t)(VALUE, VALUE); + +static ID param_names[RUBY_WHISPER_PARAKEET_NUM_CONTEXT_PARAMS]; +static param_writer_t param_writers[RUBY_WHISPER_PARAKEET_NUM_CONTEXT_PARAMS]; + +static size_t +ruby_whisper_parakeet_context_params_memsize(const void *p) +{ + if (!p) { + return 0; + } + return sizeof(ruby_whisper_parakeet_context_params); +} + +const rb_data_type_t ruby_whisper_parakeet_context_params_type = { + "ruby_whisper_parakeet_context_params", + {0, RUBY_DEFAULT_FREE, ruby_whisper_parakeet_context_params_memsize,}, + 0, 0, + 0, +}; + +static VALUE +ruby_whisper_parakeet_context_params_s_allocate(VALUE klass) +{ + ruby_whisper_parakeet_context_params *rwpcp; + return TypedData_Make_Struct(klass, ruby_whisper_parakeet_context_params, &ruby_whisper_parakeet_context_params_type, rwpcp); +} + +static VALUE +ruby_whisper_parakeet_context_params_initialize(int argc, VALUE *argv, VALUE self) +{ + VALUE kw_hash; + VALUE values[RUBY_WHISPER_PARAKEET_NUM_CONTEXT_PARAMS] = {Qundef}; + VALUE value; + ruby_whisper_parakeet_context_params *rwpcp; + int i; + + TypedData_Get_Struct(self, ruby_whisper_parakeet_context_params, &ruby_whisper_parakeet_context_params_type, rwpcp); + rwpcp->params = parakeet_context_default_params(); + + rb_scan_args_kw(RB_SCAN_ARGS_KEYWORDS, argc, argv, ":", &kw_hash); + if (NIL_P(kw_hash)) { + return Qnil; + } + + rb_get_kwargs(kw_hash, param_names, 0, RUBY_WHISPER_PARAKEET_NUM_CONTEXT_PARAMS, values); + for (i = 0; i < RUBY_WHISPER_PARAKEET_NUM_CONTEXT_PARAMS; i++) { + value = values[i]; + if (value == Qundef) { + continue; + } + param_writers[i](self, value); + } + + return Qnil; +} + +ITERATE_ATTRS(DEF_ATTR) + +void +init_ruby_whisper_parakeet_context_params(VALUE *cParakeetContext) +{ + cParakeetContextParams = rb_define_class_under(*cParakeetContext, "Params", rb_cObject); + + rb_define_alloc_func(cParakeetContextParams, ruby_whisper_parakeet_context_params_s_allocate); + + rb_define_method(cParakeetContextParams, "initialize", ruby_whisper_parakeet_context_params_initialize, -1); + + int i = 0; +#define REGISTER_ATTR(name, type) \ + param_names[i] = rb_intern(#name); \ + param_writers[i] = ruby_whisper_parakeet_context_params_set_##name; \ + rb_define_method(cParakeetContextParams, #name, ruby_whisper_parakeet_context_params_get_##name, 0); \ + rb_define_method(cParakeetContextParams, #name "=", ruby_whisper_parakeet_context_params_set_##name, 1); \ + i++; + + ITERATE_ATTRS(REGISTER_ATTR) +} diff --git a/bindings/ruby/ext/ruby_whisper_parakeet_model.c b/bindings/ruby/ext/ruby_whisper_parakeet_model.c new file mode 100644 index 0000000..dce43c6 --- /dev/null +++ b/bindings/ruby/ext/ruby_whisper_parakeet_model.c @@ -0,0 +1,84 @@ +#include "ruby_whisper.h" + +#define ITERATE_ATTRS(ITERATOR) \ + ITERATOR(n_vocab) \ + ITERATOR(n_audio_ctx) \ + ITERATOR(n_audio_state) \ + ITERATOR(n_audio_head) \ + ITERATOR(n_audio_layer) \ + ITERATOR(n_mels) \ + ITERATOR(ftype) + +extern rb_data_type_t ruby_whisper_parakeet_context_type; +extern VALUE cParakeetModel; + +static void +ruby_whisper_parakeet_model_mark(void *p) +{ + ruby_whisper_parakeet_model *rwpm = (ruby_whisper_parakeet_model *)p; + if (!NIL_P(rwpm->context)) { + rb_gc_mark(rwpm->context); + } +} + +static size_t +ruby_whisper_parakeet_model_memsize(const void *p) +{ + if (!p) { + return 0; + } + return sizeof(ruby_whisper_parakeet_model); +} + +static const rb_data_type_t ruby_whisper_parakeet_model_type = { + "ruby_whisper_parakeet_model", + {ruby_whisper_parakeet_model_mark, RUBY_DEFAULT_FREE, ruby_whisper_parakeet_model_memsize}, + 0, 0, + 0 +}; + +static VALUE +ruby_whisper_parakeet_model_s_allocate(VALUE klass) +{ + ruby_whisper_parakeet_model *rwpm; + VALUE model = TypedData_Make_Struct(klass, ruby_whisper_parakeet_model, &ruby_whisper_parakeet_model_type, rwpm); + rwpm->context = Qnil; + + return model; +} + +VALUE +ruby_whisper_parakeet_model_s_new(VALUE context) +{ + const VALUE model = ruby_whisper_parakeet_model_s_allocate(cParakeetModel); + ruby_whisper_parakeet_model *rwpm; + TypedData_Get_Struct(model, ruby_whisper_parakeet_model, &ruby_whisper_parakeet_model_type, rwpm); + rwpm->context = context; + return model; +} + +#define DEF_ATTR(name) \ + static VALUE \ + ruby_whisper_parakeet_model_get_##name(VALUE self) \ + { \ + ruby_whisper_parakeet_model *rwpm; \ + ruby_whisper_parakeet_context *rwpc; \ + GetParakeetModel(self, rwpm); \ + GetParakeetContext(rwpm->context, rwpc); \ + return INT2NUM(parakeet_model_##name(rwpc->context)); \ + } + +ITERATE_ATTRS(DEF_ATTR) + +void +init_ruby_whisper_parakeet_model(VALUE *mParakeet) +{ + cParakeetModel = rb_define_class_under(*mParakeet, "Model", rb_cObject); + + rb_define_alloc_func(cParakeetModel, ruby_whisper_parakeet_model_s_allocate); + +#define REGISTER_ATTR(name) \ + rb_define_method(cParakeetModel, #name, ruby_whisper_parakeet_model_get_##name, 0); + + ITERATE_ATTRS(REGISTER_ATTR) +} diff --git a/bindings/ruby/ext/ruby_whisper_parakeet_params.c b/bindings/ruby/ext/ruby_whisper_parakeet_params.c new file mode 100644 index 0000000..076e2a0 --- /dev/null +++ b/bindings/ruby/ext/ruby_whisper_parakeet_params.c @@ -0,0 +1,548 @@ +#include "ruby_whisper.h" + +#define ITERATE_PARAMS(ITERATOR) \ + ITERATOR(n_threads, INT) \ + ITERATOR(offset_ms, INT) \ + ITERATOR(duration_ms, INT) \ + ITERATOR(no_context, BOOL) \ + ITERATOR(audio_ctx, INT) + +#define ITERATE_NORMAL_CALLBACK_NAMES(ITERATOR, DATA) \ + ITERATOR(new_segment, DATA) \ + ITERATOR(new_token, DATA) \ + ITERATOR(progress, DATA) \ + ITERATOR(encoder_begin, DATA) + +#define ITERATE_NORMAL_CALLBACK_PARAM(name, ITERATOR) ITERATOR(name##_callback) +#define ITERATE_NORMAL_CALLBACK_PARAMS(ITERATOR) \ + ITERATE_NORMAL_CALLBACK_NAMES(ITERATE_NORMAL_CALLBACK_PARAM, ITERATOR) + +#define ITERATE_CALLBACK_PARAMS(ITERATOR) \ + ITERATE_NORMAL_CALLBACK_PARAMS(ITERATOR) \ + ITERATOR(abort_callback) + +enum { +#define DEF_IDX(name, type) RUBY_WHISPER_PARAKEET_PARAM_##name, +#define DEF_IDX_CALLBACK(name) RUBY_WHISPER_PARAKEET_PARAM_##name, +#define DEF_IDX_USER_DATA(name) RUBY_WHISPER_PARAKEET_PARAM_##name##_user_data, + ITERATE_PARAMS(DEF_IDX) + ITERATE_CALLBACK_PARAMS(DEF_IDX_CALLBACK) + ITERATE_CALLBACK_PARAMS(DEF_IDX_USER_DATA) + + RUBY_WHISPER_PARAKEET_NUM_PARAMS +}; + +#define VAL_TO_INT(v) (NUM2INT(v)) +#define VAL_FROM_INT(v) (INT2NUM(v)) +#define VAL_TO_BOOL(v) (RTEST(v)) +#define VAL_FROM_BOOL(v) (v ? Qtrue : Qfalse) + +extern VALUE cParakeetParams; +extern ID id_call; + +extern void ruby_whisper_callback_container_mark(ruby_whisper_callback_container *rwc); +extern ruby_whisper_callback_container* ruby_whisper_callback_container_allocate(void); +extern bool ruby_whisper_callback_container_is_present(const ruby_whisper_callback_container *container); +extern VALUE ruby_whisper_parakeet_segment_init(VALUE context, int index); +extern VALUE ruby_whisper_parakeet_token_s_from_token_data(struct parakeet_context *context, const parakeet_token_data *token_data); + +static ID param_names[RUBY_WHISPER_PARAKEET_NUM_PARAMS]; +typedef VALUE (*param_writer_t)(VALUE, VALUE); +static param_writer_t param_writers[RUBY_WHISPER_PARAKEET_NUM_PARAMS]; + +typedef struct { + const ruby_whisper_callback_container *container; + struct parakeet_state *state; + int n_new; +} call_parakeet_new_segment_callbacks_args; + +static void* +call_parakeet_new_segment_callbacks(void *v_args) +{ + call_parakeet_new_segment_callbacks_args *args = (call_parakeet_new_segment_callbacks_args *)v_args; + const ruby_whisper_callback_container *container = args->container; + + if (!NIL_P(container->callback)) { + rb_funcall(container->callback, id_call, 4, *container->context, Qnil, INT2NUM(args->n_new), container->user_data); + } + if (NIL_P(container->callbacks)) { + return NULL; + } + const long n_callbacks = RARRAY_LEN(container->callbacks); + if (n_callbacks == 0) { + return NULL; + } + const int n_segments = parakeet_full_n_segments_from_state(args->state); + for (int i = args->n_new; i > 0; i--) { + int i_segment = n_segments - i; + VALUE segment = ruby_whisper_parakeet_segment_init(*container->context, i_segment); + for (int j = 0; j < n_callbacks; j++) { + VALUE cb = rb_ary_entry(container->callbacks, j); + rb_funcall(cb, id_call, 1, segment); + } + } + + return NULL; +} + +static void +ruby_whisper_parakeet_new_segment_callback(struct parakeet_context *context, struct parakeet_state *state, int n_new, void *user_data) +{ + const ruby_whisper_callback_container *container = (ruby_whisper_callback_container *)user_data; + if (!ruby_whisper_callback_container_is_present(container)) { + return; + } + + call_parakeet_new_segment_callbacks_args args = { + container, + state, + n_new, + }; + rb_thread_call_with_gvl(call_parakeet_new_segment_callbacks, (void *)&args); +} + +typedef struct { + const ruby_whisper_callback_container *container; + struct parakeet_context *context; + struct parakeet_state *state; + const parakeet_token_data *token_data; +} call_parakeet_new_token_callbacks_args; + +static void* +call_parakeet_new_token_callbacks(void *v_args) +{ + call_parakeet_new_token_callbacks_args *args = (call_parakeet_new_token_callbacks_args *)v_args; + VALUE token = Qnil; + const ruby_whisper_callback_container *container = args->container; + + if (!NIL_P(container->callback)) { + token = ruby_whisper_parakeet_token_s_from_token_data(args->context, args->token_data); + rb_funcall(container->callback, id_call, 4, *container->context, Qnil, token, container->user_data); + } + if (NIL_P(container->callbacks)) { + return NULL; + } + const long n_callbacks = RARRAY_LEN(container->callbacks); + if (n_callbacks == 0) { + return NULL; + } + if (NIL_P(token)) { + token = ruby_whisper_parakeet_token_s_from_token_data(args->context, args->token_data); + } + for (int i = 0; i < n_callbacks; i++) { + VALUE cb = rb_ary_entry(container->callbacks, i); + rb_funcall(cb, id_call, 1, token); + } + + return NULL; +} + +static void +ruby_whisper_parakeet_new_token_callback(struct parakeet_context *context, struct parakeet_state *state, const parakeet_token_data *token_data, void *user_data) +{ + const ruby_whisper_callback_container *container = (ruby_whisper_callback_container *)user_data; + if (!ruby_whisper_callback_container_is_present(container)) { + return; + } + + call_parakeet_new_token_callbacks_args args = { + container, + context, + state, + token_data, + }; + rb_thread_call_with_gvl(call_parakeet_new_token_callbacks, (void *)&args); +} + +typedef struct { + const ruby_whisper_callback_container *container; + struct parakeet_state *state; + int progress; +} call_parakeet_progress_callbacks_args; + +static void* +call_parakeet_progress_callback(void *v_args) +{ + call_parakeet_progress_callbacks_args *args = (call_parakeet_progress_callbacks_args *)v_args; + const ruby_whisper_callback_container *container = args->container; + + if (!NIL_P(container->callback)) { + rb_funcall(container->callback, id_call, 4, *container->context, Qnil, INT2NUM(args->progress), container->user_data); + } + if (NIL_P(container->callbacks)) { + return NULL; + } + const long n_callbacks = RARRAY_LEN(container->callbacks); + if (n_callbacks == 0) { + return NULL; + } + for (long i = 0; i < n_callbacks; i++) { + VALUE cb = rb_ary_entry(container->callbacks, i); + rb_funcall(cb, id_call, 1, INT2NUM(args->progress)); + } + + return NULL; +} + +static void +ruby_whisper_parakeet_progress_callback(struct parakeet_context *context, struct parakeet_state *state, int progress, void *user_data) +{ + const ruby_whisper_callback_container *container = (ruby_whisper_callback_container *)user_data; + if (!ruby_whisper_callback_container_is_present(container)) { + return; + } + + call_parakeet_progress_callbacks_args args = { + container, + state, + progress, + }; + rb_thread_call_with_gvl(call_parakeet_progress_callback, (void *)&args); +} + +typedef struct { + const ruby_whisper_callback_container *container; + struct parakeet_state *state; + bool is_continued; +} call_parakeet_encoder_begin_callbacks_args; + +static void* +call_parakeet_encoder_begin_callbacks(void *v_args) +{ + call_parakeet_encoder_begin_callbacks_args *args = (call_parakeet_encoder_begin_callbacks_args *)v_args; + const ruby_whisper_callback_container *container = args->container; + VALUE result = Qnil; + + if (!NIL_P(container->callback)) { + result = rb_funcall(container->callback, id_call, 3, *container->context, Qnil, container->user_data); + if (result == Qfalse) { + args->is_continued = false; + return NULL; + } + } + if (NIL_P(container->callbacks)) { + return NULL; + } + const long n_callbacks = RARRAY_LEN(container->callbacks); + if (n_callbacks == 0) { + return NULL; + } + for (long i = 0; i < n_callbacks; i++) { + VALUE cb = rb_ary_entry(container->callbacks, i); + result = rb_funcall(cb, id_call, 0); + if (result == Qfalse) { + args->is_continued = false; + return NULL; + } + } + + return NULL; +} + +static bool +ruby_whisper_parakeet_encoder_begin_callback(struct parakeet_context *context, struct parakeet_state *state, void *user_data) +{ + const ruby_whisper_callback_container *container = (ruby_whisper_callback_container *)user_data; + if (!ruby_whisper_callback_container_is_present(container)) { + return true; + } + + call_parakeet_encoder_begin_callbacks_args args = { + container, + state, + true, + }; + rb_thread_call_with_gvl(call_parakeet_encoder_begin_callbacks, (void *)&args); + + return args.is_continued; +} + +typedef struct { + const ruby_whisper_callback_container *container; + bool is_interrupted; +} call_parakeet_abort_callbacks_args; + +static void* +call_parakeet_abort_callbacks(void *v_args) +{ + call_parakeet_abort_callbacks_args *args = (call_parakeet_abort_callbacks_args *)v_args; + const ruby_whisper_callback_container *container = args->container; + VALUE result = Qnil; + + if (!NIL_P(container->callback)) { + result = rb_funcall(container->callback, id_call, 1, container->user_data); + if (RTEST(result)) { + args->is_interrupted = true; + return NULL; + } + } + if (NIL_P(container->callbacks)) { + return NULL; + } + const long n_callbacks = RARRAY_LEN(container->callbacks); + if (n_callbacks == 0) { + return NULL; + } + VALUE cb; + for (long i = 0; i < n_callbacks; i++) { + cb = rb_ary_entry(container->callbacks, i); + result = rb_funcall(cb, id_call, 0); + if (RTEST(result)) { + args->is_interrupted = true; + return NULL; + } + } + + return NULL; +} + +static bool +ruby_whisper_parakeet_abort_callback(void *user_data) +{ + ruby_whisper_abort_callback_user_data *data = (ruby_whisper_abort_callback_user_data *)user_data; + + int is_interrupted = RUBY_ATOMIC_LOAD(data->is_interrupted); + if (is_interrupted) { + return true; + } + + if (!(data->callback_container) || !ruby_whisper_callback_container_is_present(data->callback_container)) { + return false; + } + + call_parakeet_abort_callbacks_args args = { + data->callback_container, + false, + }; + rb_thread_call_with_gvl(call_parakeet_abort_callbacks, (void *)&args); + + return args.is_interrupted; +} + +#define CALLBACK_CONTAINER_NAME(name) name ## _container + +void +ruby_whisper_parakeet_prepare_transcription(ruby_whisper_parakeet_params *rwpp, VALUE *context, ruby_whisper_abort_callback_user_data *abort_callback_user_data) +{ +#define PARAM_NAME(name) name +#define USER_DATA_NAME(name) name##_user_data +#define REGISTER_CALLBACK(name) \ + if (ruby_whisper_callback_container_is_present(rwpp->CALLBACK_CONTAINER_NAME(name))) { \ + rwpp->CALLBACK_CONTAINER_NAME(name)->context = context; \ + rwpp->params.PARAM_NAME(name) = ruby_whisper_parakeet_##name; \ + rwpp->params.USER_DATA_NAME(name) = rwpp->CALLBACK_CONTAINER_NAME(name); \ + } + + ITERATE_NORMAL_CALLBACK_PARAMS(REGISTER_CALLBACK) + + if (ruby_whisper_callback_container_is_present(rwpp->abort_callback_container)) { + abort_callback_user_data->callback_container = rwpp->abort_callback_container; + } + rwpp->params.abort_callback = ruby_whisper_parakeet_abort_callback; + rwpp->params.abort_callback_user_data = (void *)abort_callback_user_data; +} + +static void +ruby_whisper_parakeet_params_mark(void *p) +{ + ruby_whisper_parakeet_params *rwpp = (ruby_whisper_parakeet_params *)p; + +#define MARK_CONTAINER(name) \ + if (rwpp->name##_container) { \ + ruby_whisper_callback_container_mark(rwpp->name##_container); \ + } + + ITERATE_CALLBACK_PARAMS(MARK_CONTAINER) +} + +static void +ruby_whisper_parakeet_params_free(void *p) +{ + ruby_whisper_parakeet_params *rwpp = (ruby_whisper_parakeet_params *)p; + +#define FREE_CONTAINER(name) \ + if (rwpp->name##_container) { \ + xfree(rwpp->name##_container); \ + } + + ITERATE_CALLBACK_PARAMS(FREE_CONTAINER) + + xfree(rwpp); +} + +static size_t +ruby_whisper_parakeet_params_memsize(const void *p) +{ + const struct ruby_whisper_parakeet_params *params = p; + if (!params) { + return 0; + } + return sizeof(ruby_whisper_parakeet_params); +} + +const rb_data_type_t ruby_whisper_parakeet_params_type = { + "ruby_whisper_parakeet_params", + {ruby_whisper_parakeet_params_mark, ruby_whisper_parakeet_params_free, ruby_whisper_parakeet_params_memsize,}, + 0, 0, + 0 +}; + +#define READER(type) VAL_FROM_##type +#define WRITER(type) VAL_TO_##type +#define DEF_PARAM_ATTR(name, type) \ + static VALUE \ + ruby_whisper_parakeet_params_get_##name(VALUE self) \ + { \ + ruby_whisper_parakeet_params *rwpp; \ + GetParakeetParams(self, rwpp); \ + return READER(type)(rwpp->params.name); \ + } \ + static VALUE \ + ruby_whisper_parakeet_params_set_##name(VALUE self, VALUE val) \ + { \ + ruby_whisper_parakeet_params *rwpp; \ + GetParakeetParams(self, rwpp); \ + rwpp->params.name = WRITER(type)(val); \ + return val; \ + } + +#define DEF_CALLBACK_PARAM_ATTR(name) \ + static VALUE \ + ruby_whisper_parakeet_params_get_##name(VALUE self) \ + { \ + ruby_whisper_parakeet_params *rwpp; \ + GetParakeetParams(self, rwpp); \ + return rwpp->CALLBACK_CONTAINER_NAME(name)->callback; \ + } \ + static VALUE \ + ruby_whisper_parakeet_params_set_##name(VALUE self, VALUE val) \ + { \ + ruby_whisper_parakeet_params *rwpp; \ + GetParakeetParams(self, rwpp); \ + rwpp->CALLBACK_CONTAINER_NAME(name)->callback = (val); \ + return val; \ + } + +#define DEF_USER_DATA_PARAM_ATTR(name) \ + static VALUE \ + ruby_whisper_parakeet_params_get_##name##_user_data(VALUE self) \ + { \ + ruby_whisper_parakeet_params *rwpp; \ + GetParakeetParams(self, rwpp); \ + return rwpp->CALLBACK_CONTAINER_NAME(name)->user_data; \ + } \ + static VALUE \ + ruby_whisper_parakeet_params_set_##name##_user_data(VALUE self, VALUE val) \ + { \ + ruby_whisper_parakeet_params *rwpp; \ + GetParakeetParams(self, rwpp); \ + rwpp->CALLBACK_CONTAINER_NAME(name)->user_data = val; \ + return val; \ + } + +#define DEF_HOOK(name, data) \ + static VALUE \ + ruby_whisper_parakeet_params_on_##name(VALUE self) \ + { \ + ruby_whisper_parakeet_params *rwpp; \ + GetParakeetParams(self, rwpp); \ + const VALUE blk = rb_block_proc(); \ + if (NIL_P(rwpp->name##_callback_container->callbacks)) { \ + rwpp->name##_callback_container->callbacks = rb_ary_new(); \ + } \ + rb_ary_push(rwpp->name##_callback_container->callbacks, blk); \ + return Qnil; \ + } + +ITERATE_PARAMS(DEF_PARAM_ATTR) +ITERATE_CALLBACK_PARAMS(DEF_CALLBACK_PARAM_ATTR) +ITERATE_CALLBACK_PARAMS(DEF_USER_DATA_PARAM_ATTR) +ITERATE_NORMAL_CALLBACK_NAMES(DEF_HOOK, _) + +static VALUE +ruby_whisper_parakeet_params_abort_on(VALUE self) +{ + ruby_whisper_parakeet_params *rwpp; + GetParakeetParams(self, rwpp); + const VALUE blk = rb_block_proc(); + if (NIL_P(rwpp->abort_callback_container->callbacks)) { + rwpp->abort_callback_container->callbacks = rb_ary_new(); + } + rb_ary_push(rwpp->abort_callback_container->callbacks, blk); + + return Qnil; +} + +static VALUE +ruby_whisper_parakeet_params_s_allocate(VALUE klass) +{ + ruby_whisper_parakeet_params *rwpp; + VALUE obj = TypedData_Make_Struct(klass, ruby_whisper_parakeet_params, &ruby_whisper_parakeet_params_type, rwpp); + rwpp->params = parakeet_full_default_params(PARAKEET_SAMPLING_GREEDY); + return obj; +} + +static VALUE +ruby_whisper_parakeet_params_initialize(int argc, VALUE *argv, VALUE self) +{ + VALUE kw_hash; + VALUE values[RUBY_WHISPER_PARAKEET_NUM_PARAMS] = {Qundef}; + VALUE value; + ruby_whisper_parakeet_params *rwpp; + int i; + + TypedData_Get_Struct(self, ruby_whisper_parakeet_params, &ruby_whisper_parakeet_params_type, rwpp); + +#define INIT_CONTAINER(name) rwpp->name##_container = ruby_whisper_callback_container_allocate(); + + ITERATE_CALLBACK_PARAMS(INIT_CONTAINER) + + rb_scan_args_kw(RB_SCAN_ARGS_KEYWORDS, argc, argv, ":", &kw_hash); + if (NIL_P(kw_hash)) { + return Qnil; + } + + rb_get_kwargs(kw_hash, param_names, 0, RUBY_WHISPER_PARAKEET_NUM_PARAMS, values); + + for (i = 0; i < RUBY_WHISPER_PARAKEET_NUM_PARAMS; i++) { + value = values[i]; + if (value == Qundef) { + continue; + } + param_writers[i](self, value); + } + + return Qnil; +} + +void +init_ruby_whisper_parakeet_params(VALUE *mParakeet) +{ + cParakeetParams = rb_define_class_under(*mParakeet, "Params", rb_cObject); + rb_define_alloc_func(cParakeetParams, ruby_whisper_parakeet_params_s_allocate); + + rb_define_method(cParakeetParams, "initialize", ruby_whisper_parakeet_params_initialize, -1); + + int i = 0; +#define REGISTER_PARAM(name) \ + param_names[i] = rb_intern(#name); \ + param_writers[i] = ruby_whisper_parakeet_params_set_##name; \ + rb_define_method(cParakeetParams, #name, ruby_whisper_parakeet_params_get_##name, 0); \ + rb_define_method(cParakeetParams, #name "=", ruby_whisper_parakeet_params_set_##name, 1); \ + i++; + +#define REGISTER_PARAM_ATTR(name, type) REGISTER_PARAM(name) +#define REGISTER_CALLBACK_PARAM_ATTR(name) REGISTER_PARAM(name) +#define REGISTER_USER_DATA_PARAM_ATTR(name) REGISTER_PARAM(name##_user_data) + + ITERATE_PARAMS(REGISTER_PARAM_ATTR) + ITERATE_CALLBACK_PARAMS(REGISTER_CALLBACK_PARAM_ATTR) + ITERATE_CALLBACK_PARAMS(REGISTER_USER_DATA_PARAM_ATTR) + +#define REGISTER_HOOK(name, data) \ + rb_define_method(cParakeetParams, "on_" #name, ruby_whisper_parakeet_params_on_##name, 0); + + ITERATE_NORMAL_CALLBACK_NAMES(REGISTER_HOOK, _) + + rb_define_method(cParakeetParams, "abort_on", ruby_whisper_parakeet_params_abort_on, 0); +} diff --git a/bindings/ruby/ext/ruby_whisper_parakeet_segment.c b/bindings/ruby/ext/ruby_whisper_parakeet_segment.c new file mode 100644 index 0000000..b1e81ba --- /dev/null +++ b/bindings/ruby/ext/ruby_whisper_parakeet_segment.c @@ -0,0 +1,157 @@ +#include "ruby_whisper.h" + +#define ITERATE_ATTRS(ITERATOR) \ + ITERATOR(start_time, t0, TIME) \ + ITERATOR(end_time, t1, TIME) \ + ITERATOR(text, text, STRING) + +enum { +#define DEF_IDX(name, c_name, type) RUBY_WHISPER_PARAKEET_SEGMENT_##name, + + ITERATE_ATTRS(DEF_IDX) + RUBY_WHISPER_PARAKEET_SEGMENT_NUM_ATTRS, +}; + +#define VAL_FROM_TIME(v) (LONG2NUM((v) * 10)) +#define VAL_FROM_STRING(v) (rb_str_new2(v)) +#define READER(type) VAL_FROM_##type +#define DEF_ATTR(rb_name, c_name, type) \ + static VALUE \ + ruby_whisper_parakeet_get_##rb_name(VALUE self) \ + { \ + ruby_whisper_parakeet_segment *rwps; \ + GetParakeetSegment(self, rwps); \ + ruby_whisper_parakeet_context *rwpc; \ + GetParakeetContext(rwps->context, rwpc); \ + return READER(type)(parakeet_full_get_segment_##c_name(rwpc->context, rwps->index)); \ + } + +extern ID id___method__; +extern ID id_to_enum; +extern VALUE cParakeetSegment; +extern VALUE sym_start_time; +extern VALUE sym_end_time; +extern VALUE sym_text; +extern const rb_data_type_t ruby_whisper_parakeet_context_type; +extern VALUE ruby_whisper_parakeet_token_s_from_index(struct parakeet_context *context, int i_segment, int i_token); + +static void +rb_whisper_parakeet_segment_mark(void *p) +{ + ruby_whisper_parakeet_segment *rwps = (ruby_whisper_parakeet_segment *)p; + rb_gc_mark(rwps->context); +} + +static size_t +ruby_whisper_parakeet_segment_memsize(const void *p) +{ + const ruby_whisper_parakeet_segment *rwps = (const ruby_whisper_parakeet_segment *)p; + if (!rwps) { + return 0; + } + return sizeof(*rwps); +} + +static const rb_data_type_t ruby_whisper_parakeet_segment_type = { + "ruby_whisper_parakeet_segment", + {rb_whisper_parakeet_segment_mark, RUBY_DEFAULT_FREE, ruby_whisper_parakeet_segment_memsize,}, + 0, 0, + 0 +}; + +static VALUE +ruby_whisper_parakeet_segment_s_allocate(VALUE klass) +{ + ruby_whisper_parakeet_segment *rwps; + return TypedData_Make_Struct(klass, ruby_whisper_parakeet_segment, &ruby_whisper_parakeet_segment_type, rwps); +} + +VALUE +ruby_whisper_parakeet_segment_init(VALUE context, int index) +{ + ruby_whisper_parakeet_segment *rwps; + + const VALUE segment = ruby_whisper_parakeet_segment_s_allocate(cParakeetSegment); + TypedData_Get_Struct(segment, ruby_whisper_parakeet_segment, &ruby_whisper_parakeet_segment_type, rwps); + rwps->context = context; + rwps->index = index; + + return segment; +} + +ITERATE_ATTRS(DEF_ATTR) + +static VALUE +ruby_whisper_parakeet_segment_each_token(VALUE self) +{ + if (!rb_block_given_p()) { + const VALUE method_name = rb_funcall(self, id___method__, 0); + return rb_funcall(self, id_to_enum, 1, method_name); + } + + ruby_whisper_parakeet_segment *rwps; + GetParakeetSegment(self, rwps); + ruby_whisper_parakeet_context *rwpc; + GetParakeetContext(rwps->context, rwpc); + + const int n_tokens = parakeet_full_n_tokens(rwpc->context, rwps->index); + for (int i = 0; i < n_tokens; i++) { + rb_yield(ruby_whisper_parakeet_token_s_from_index(rwpc->context, rwps->index, i)); + } + + return self; +} + +static VALUE +ruby_whisper_parakeet_segment_deconstruct_keys(VALUE self, VALUE keys) +{ + ruby_whisper_parakeet_segment *rwps; + GetParakeetSegment(self, rwps); + ruby_whisper_parakeet_context *rwpc; + GetParakeetContext(rwps->context, rwpc); + + VALUE hash = rb_hash_new(); + long n_keys; + if (NIL_P(keys)) { + keys = rb_ary_new3( + RUBY_WHISPER_PARAKEET_SEGMENT_NUM_ATTRS, + sym_start_time, + sym_end_time, + sym_text + ); + n_keys = RUBY_WHISPER_PARAKEET_SEGMENT_NUM_ATTRS; + } else { + n_keys = RARRAY_LEN(keys); + if (n_keys > RUBY_WHISPER_PARAKEET_SEGMENT_NUM_ATTRS) { + return hash; + } + } + for (int i = 0; i < n_keys; i++) { + VALUE key = rb_ary_entry(keys, i); + +#define CHECK_AND_SET_KEY(rb_name, c_name, type) \ + if (key == sym_##rb_name) { \ + rb_hash_aset(hash, key, ruby_whisper_parakeet_get_##rb_name(self)); \ + } + + ITERATE_ATTRS(CHECK_AND_SET_KEY) + } + + return hash; +} + +void +init_ruby_whisper_parakeet_segment(VALUE *mParakeet) +{ + cParakeetSegment = rb_define_class_under(*mParakeet, "Segment", rb_cObject); + + rb_define_alloc_func(cParakeetSegment, ruby_whisper_parakeet_segment_s_allocate); + +#define REGISTER_ATTR(rb_name, c_name, type) \ + rb_define_method(cParakeetSegment, #rb_name, ruby_whisper_parakeet_get_##rb_name, 0); + + ITERATE_ATTRS(REGISTER_ATTR) + + rb_define_method(cParakeetSegment, "each_token", ruby_whisper_parakeet_segment_each_token, 0); + rb_define_method(cParakeetSegment, "deconstruct_keys", ruby_whisper_parakeet_segment_deconstruct_keys, 1); +} diff --git a/bindings/ruby/ext/ruby_whisper_parakeet_token.c b/bindings/ruby/ext/ruby_whisper_parakeet_token.c new file mode 100644 index 0000000..a00b7ae --- /dev/null +++ b/bindings/ruby/ext/ruby_whisper_parakeet_token.c @@ -0,0 +1,188 @@ +#include "ruby_whisper.h" + +#define ITERATE_MEMBERS(ITERATOR) \ + ITERATOR(id, id, id, id, INT) \ + ITERATOR(duration_idx, duration_idx, duration_idx, duration_idx, INT) \ + ITERATOR(duration_value, duration_value, duration_value, duration_value, INT) \ + ITERATOR(frame_index, frame_index, frame_index, frame_index, INT) \ + ITERATOR(probability, probability, p, p, FLOAT) \ + ITERATOR(log_probability, log_probability, plog, plog, FLOAT) \ + ITERATOR(start_time, start_time, start_time, t0, TIME) \ + ITERATOR(end_time, end_time, end_time, t1, TIME) \ + ITERATOR(word_start?, word_start, word_start_p, is_word_start, BOOL) + +#define ITERATE_ATTRS(ITERATOR) \ + ITERATOR(text, text, text, text, STRING) + +enum { +#define DEF_IDX(rb_name, s_key, c_name, p_name, type) RUBY_WHISPER_PARAKEET_TOKEN_##c_name, + + ITERATE_MEMBERS(DEF_IDX) + ITERATE_ATTRS(DEF_IDX) + RUBY_WHISPER_PARAKEET_TOKEN_NUM_ATTRS, +}; + +#define VAL_FROM_INT(v) (INT2NUM(v)) +#define VAL_FROM_FLOAT(v) (DBL2NUM(v)) +#define VAL_FROM_TIME(v) (LONG2NUM(v * 10)) +#define VAL_FROM_BOOL(v) ((v) ? Qtrue : Qfalse) +#define VAL_FROM_STRING(v) (rb_str_new2(v)) + +#define READER(type) VAL_FROM_##type +#define MEMBER_NAME(name) name +#define DEF_MEMBER_ATTR(rb_name, s_key, c_name, p_name, type) \ + static VALUE \ + ruby_whisper_parakeet_token_get_##c_name(VALUE self) \ + { \ + ruby_whisper_parakeet_token *rwpt; \ + GetParakeetToken(self, rwpt); \ + return READER(type)(rwpt->token_data->MEMBER_NAME(p_name)); \ + } + +#define DEF_ATTR(rb_name, s_key, c_name, p_name, type) \ + static VALUE \ + ruby_whisper_parakeet_token_get_##c_name(VALUE self) \ + { \ + ruby_whisper_parakeet_token *rwpt; \ + GetParakeetToken(self, rwpt); \ + return rwpt->p_name; \ + } + +VALUE cParakeetToken; + +#define DEC_ATTR_SYMS(rb_name, s_key, c_name, p_name, type) static VALUE sym_##s_key; + +ITERATE_MEMBERS(DEC_ATTR_SYMS) +ITERATE_ATTRS(DEC_ATTR_SYMS) + +static void +ruby_whisper_parakeet_token_mark(void *p) +{ + ruby_whisper_parakeet_token *rwpt = (ruby_whisper_parakeet_token *)p; + rb_gc_mark(rwpt->text); +} + +static void +ruby_whisper_parakeet_token_free(void *p) +{ + ruby_whisper_parakeet_token *rwpt = (ruby_whisper_parakeet_token *)p; + if (rwpt->token_data) { + xfree(rwpt->token_data); + rwpt->token_data = NULL; + } + xfree(rwpt); +} + +static size_t +ruby_whisper_parakeet_token_memsize(const void *p) +{ + ruby_whisper_parakeet_token *rwpt = (ruby_whisper_parakeet_token *)p; + if (!rwpt) { + return 0; + } + size_t size = sizeof(*rwpt); + if (rwpt->token_data) { + size += sizeof(*rwpt->token_data); + } + + return size; +} + +static const rb_data_type_t ruby_whisper_parakeet_token_type = { + "ruby_whisper_parakeet_token", + {ruby_whisper_parakeet_token_mark, ruby_whisper_parakeet_token_free, ruby_whisper_parakeet_token_memsize}, + 0, 0, + 0, +}; + +static VALUE +ruby_whisper_parakeet_token_s_allocate(VALUE klass) +{ + ruby_whisper_parakeet_token *rwpt; + VALUE token = TypedData_Make_Struct(klass, ruby_whisper_parakeet_token, &ruby_whisper_parakeet_token_type, rwpt); + + rwpt->token_data = NULL; + rwpt->text = Qnil; + + return token; +} + +VALUE +ruby_whisper_parakeet_token_s_from_token_data(struct parakeet_context *context, const parakeet_token_data *token_data) +{ + const VALUE token = ruby_whisper_parakeet_token_s_allocate(cParakeetToken); + ruby_whisper_parakeet_token *rwpt; + TypedData_Get_Struct(token, ruby_whisper_parakeet_token, &ruby_whisper_parakeet_token_type, rwpt); + + rwpt->token_data = ALLOC(parakeet_token_data); + *rwpt->token_data = *token_data; + rwpt->text = rb_utf8_str_new_cstr(parakeet_token_to_str(context, token_data->id)); + + return token; +} + +VALUE +ruby_whisper_parakeet_token_s_from_index(struct parakeet_context *context, int i_segment, int i_token) +{ + parakeet_token_data token_data = parakeet_full_get_token_data(context, i_segment, i_token); + return ruby_whisper_parakeet_token_s_from_token_data(context, &token_data); +} + +ITERATE_MEMBERS(DEF_MEMBER_ATTR) +// Define #text using parakeet_token_to_str or parakeet_token_to_text +ITERATE_ATTRS(DEF_ATTR) + +static VALUE +ruby_whisper_parakeet_token_deconstruct_keys(VALUE self, VALUE keys) +{ + ruby_whisper_parakeet_token *rwpt; + GetParakeetToken(self, rwpt); + + VALUE hash = rb_hash_new(); + long n_keys = 0; + + if (NIL_P(keys)) { + VALUE attrs[] = { +#define LIST_SYMS(rb_name, s_key, c_name, p_name, type) sym_##s_key, + + ITERATE_MEMBERS(LIST_SYMS) + ITERATE_ATTRS(LIST_SYMS) + }; + keys = rb_ary_new_from_values(RUBY_WHISPER_PARAKEET_TOKEN_NUM_ATTRS, attrs); + n_keys = RUBY_WHISPER_PARAKEET_TOKEN_NUM_ATTRS; + } else { + n_keys = RARRAY_LEN(keys); + if (n_keys > RUBY_WHISPER_PARAKEET_TOKEN_NUM_ATTRS) { + return hash; + } + } + for (long i = 0; i < n_keys; i++) { + VALUE key = rb_ary_entry(keys, i); + +#define CHECK_AND_SET_KEY(rb_name, s_key, c_name, p_name, type) \ + if (key == sym_##s_key) { \ + rb_hash_aset(hash, key, ruby_whisper_parakeet_token_get_##c_name(self)); \ + } + + ITERATE_MEMBERS(CHECK_AND_SET_KEY) + ITERATE_ATTRS(CHECK_AND_SET_KEY) + } + + return hash; +} + +void +init_ruby_whisper_parakeet_token(VALUE *mParakeet) +{ + cParakeetToken = rb_define_class_under(*mParakeet, "Token", rb_cObject); + rb_define_alloc_func(cParakeetToken, ruby_whisper_parakeet_token_s_allocate); + +#define REGISTER_ATTR(rb_name, s_key, c_name, p_name, type) \ + sym_##s_key = ID2SYM(rb_intern(#s_key)); \ + rb_define_method(cParakeetToken, #rb_name, ruby_whisper_parakeet_token_get_##c_name, 0); + + ITERATE_MEMBERS(REGISTER_ATTR) + ITERATE_ATTRS(REGISTER_ATTR) + + rb_define_method(cParakeetToken, "deconstruct_keys", ruby_whisper_parakeet_token_deconstruct_keys, 1); +} diff --git a/bindings/ruby/ext/ruby_whisper_parakeet_transcribe.cpp b/bindings/ruby/ext/ruby_whisper_parakeet_transcribe.cpp new file mode 100644 index 0000000..c4deccc --- /dev/null +++ b/bindings/ruby/ext/ruby_whisper_parakeet_transcribe.cpp @@ -0,0 +1,58 @@ +#include "ruby_whisper.h" +#include "common-whisper.h" +#include <string> +#include <vector> + +#ifdef __cplusplus +extern "C" { +#endif + +extern const rb_data_type_t ruby_whisper_parakeet_context_type; +extern const rb_data_type_t ruby_whisper_parakeet_params_type; + +extern VALUE ruby_whisper_parakeet_context_full_body(VALUE rb_args); + +extern ID id_to_path; +extern ID id_new; + +extern VALUE eError; + +VALUE +ruby_whisper_parakeet_transcribe(VALUE self, VALUE audio_path, VALUE params) +{ + if (rb_respond_to(audio_path, id_to_path)) { + audio_path = rb_funcall(audio_path, id_to_path, 0); + } + + std::string fname = StringValueCStr(audio_path); + std::vector<float> pcmf32; + std::vector<std::vector<float>> pcmf32s; + + if (!read_audio_data(fname, pcmf32, pcmf32s, false)) { + rb_raise(rb_eRuntimeError, "Failed to open %s", fname.c_str()); + return Qnil; + } + + ruby_whisper_parakeet_context *rwpc; + ruby_whisper_parakeet_params *rwpp; + GetParakeetContext(self, rwpc); + GetParakeetParams(params, rwpp); + + ruby_whisper_full_args args = { + &self, + ¶ms, + pcmf32.data(), + (int)pcmf32.size(), + }; + VALUE rb_result = ruby_whisper_parakeet_context_full_body((VALUE)&args); + const int result = NUM2INT(rb_result); + if (result == 0) { + return self; + } else { + rb_exc_raise(rb_funcall(eError, id_new, 1, rb_result)); + } +} + +#ifdef __cplusplus +} +#endif diff --git a/bindings/ruby/ext/ruby_whisper_params.c b/bindings/ruby/ext/ruby_whisper_params.c new file mode 100644 index 0000000..be874d5 --- /dev/null +++ b/bindings/ruby/ext/ruby_whisper_params.c @@ -0,0 +1,1548 @@ +#include "ruby_whisper.h" + +#define BOOL_PARAMS_SETTER(self, prop, value) \ + ruby_whisper_params *rwp; \ + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); \ + if (value == Qfalse || value == Qnil) { \ + rwp->params.prop = false; \ + } else { \ + rwp->params.prop = true; \ + } \ + return value; \ + +#define BOOL_PARAMS_GETTER(self, prop) \ + ruby_whisper_params *rwp; \ + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); \ + if (rwp->params.prop) { \ + return Qtrue; \ + } else { \ + return Qfalse; \ + } + +#define DEFINE_PARAM(param_name, nth) \ + id_ ## param_name = rb_intern(#param_name); \ + param_names[nth] = id_ ## param_name; \ + rb_define_method(cParams, #param_name, ruby_whisper_params_get_ ## param_name, 0); \ + rb_define_method(cParams, #param_name "=", ruby_whisper_params_set_ ## param_name, 1); + +#define RUBY_WHISPER_PARAMS_PARAM_NAMES_COUNT 37 + +extern VALUE cParams; +extern VALUE cVADParams; +extern VALUE mWhisper; + +extern ID id_call; + +extern VALUE ruby_whisper_normalize_model_path(VALUE model_path); +extern VALUE rb_whisper_segment_s_new(VALUE context, int index); +extern const rb_data_type_t ruby_whisper_vad_params_type; + +static ID param_names[RUBY_WHISPER_PARAMS_PARAM_NAMES_COUNT]; +static ID id_language; +static ID id_translate; +static ID id_no_context; +static ID id_single_segment; +static ID id_print_special; +static ID id_print_progress; +static ID id_print_realtime; +static ID id_print_timestamps; +static ID id_carry_initial_prompt; +static ID id_suppress_blank; +static ID id_suppress_nst; +static ID id_token_timestamps; +static ID id_max_len; +static ID id_split_on_word; +static ID id_initial_prompt; +static ID id_diarize; +static ID id_offset; +static ID id_duration; +static ID id_max_text_tokens; +static ID id_temperature; +static ID id_max_initial_ts; +static ID id_length_penalty; +static ID id_temperature_inc; +static ID id_entropy_thold; +static ID id_logprob_thold; +static ID id_no_speech_thold; +static ID id_new_segment_callback; +static ID id_new_segment_callback_user_data; +static ID id_progress_callback; +static ID id_progress_callback_user_data; +static ID id_encoder_begin_callback; +static ID id_encoder_begin_callback_user_data; +static ID id_abort_callback; +static ID id_abort_callback_user_data; +static ID id_vad; +static ID id_vad_model_path; +static ID id_vad_params; + +void +ruby_whisper_callback_container_mark(ruby_whisper_callback_container *rwc) +{ + if (rwc == NULL) return; + + rb_gc_mark(rwc->user_data); + rb_gc_mark(rwc->callback); + rb_gc_mark(rwc->callbacks); +} + +ruby_whisper_callback_container* +ruby_whisper_callback_container_allocate() { + ruby_whisper_callback_container *container; + container = ALLOC(ruby_whisper_callback_container); + container->context = NULL; + container->user_data = Qnil; + container->callback = Qnil; + container->callbacks = Qnil; + return container; +} + +bool +ruby_whisper_callback_container_is_present(const ruby_whisper_callback_container *container) { + return !NIL_P(container->callback) || !NIL_P(container->callbacks); +} + +typedef struct { + const ruby_whisper_callback_container *container; + struct whisper_state *state; + int n_new; +} call_new_segment_callbacks_args; + +static void* +call_new_segment_callbacks(void *v_args) { + call_new_segment_callbacks_args *args = (call_new_segment_callbacks_args *)v_args; + const ruby_whisper_callback_container *container = args->container; + struct whisper_state *state = args->state; + int n_new = args->n_new; + + // Currently, doesn't support state because + // those require to resolve GC-related problems. + if (!NIL_P(container->callback)) { + rb_funcall(container->callback, id_call, 4, *container->context, Qnil, INT2NUM(n_new), container->user_data); + } + if (NIL_P(container->callbacks)) { + return NULL; + } + const long callbacks_len = RARRAY_LEN(container->callbacks); + if (0 == callbacks_len) { + return NULL; + } + const int n_segments = whisper_full_n_segments_from_state(state); + for (int i = n_new; i > 0; i--) { + int i_segment = n_segments - i; + VALUE segment = rb_whisper_segment_s_new(*container->context, i_segment); + for (int j = 0; j < callbacks_len; j++) { + VALUE cb = rb_ary_entry(container->callbacks, j); + rb_funcall(cb, id_call, 1, segment); + } + } + + return NULL; +} + +static void new_segment_callback(struct whisper_context *ctx, struct whisper_state *state, int n_new, void *user_data) { + const ruby_whisper_callback_container *container = (ruby_whisper_callback_container *)user_data; + if (!ruby_whisper_callback_container_is_present(container)) { + return; + } + + call_new_segment_callbacks_args args = { + container, + state, + n_new + }; + rb_thread_call_with_gvl(call_new_segment_callbacks, (void *)&args); +} + +typedef struct { + const ruby_whisper_callback_container *container; + struct whisper_state *state; + int progress_cur; +} call_progress_callbacks_args; + +static void* +call_progress_callbacks(void *v_args) { + call_progress_callbacks_args *args = (call_progress_callbacks_args *)v_args; + const ruby_whisper_callback_container *container = args->container; + int progress_cur = args->progress_cur; + + // Currently, doesn't support state because + // those require to resolve GC-related problems. + if (!NIL_P(args->container->callback)) { + rb_funcall(container->callback, id_call, 4, *container->context, Qnil, INT2NUM(progress_cur), container->user_data); + } + if (NIL_P(container->callbacks)) { + return NULL; + } + const long callbacks_len = RARRAY_LEN(container->callbacks); + if (0 == callbacks_len) { + return NULL; + } + for (int j = 0; j < callbacks_len; j++) { + VALUE cb = rb_ary_entry(container->callbacks, j); + rb_funcall(cb, id_call, 1, INT2NUM(progress_cur)); + } + + return NULL; +} + +static void progress_callback(struct whisper_context *ctx, struct whisper_state *state, int progress_cur, void *user_data) { + const ruby_whisper_callback_container *container = (ruby_whisper_callback_container *)user_data; + if (!ruby_whisper_callback_container_is_present(container)) { + return; + } + + call_progress_callbacks_args args = { + container, + state, + progress_cur + }; + rb_thread_call_with_gvl(call_progress_callbacks, (void *)&args); +} + +typedef struct { + const ruby_whisper_callback_container *container; + struct whisper_state *state; + bool is_continued; +} call_encoder_begin_callbacks_args; + +static void* +call_encoder_begin_callbacks(void *v_args) { + call_encoder_begin_callbacks_args *args = (call_encoder_begin_callbacks_args *)v_args; + const ruby_whisper_callback_container *container = args->container; + VALUE result = Qnil; + + // Currently, doesn't support state because + // those require to resolve GC-related problems. + if (!NIL_P(container->callback)) { + result = rb_funcall(container->callback, id_call, 3, *container->context, Qnil, container->user_data); + if (result == Qfalse) { + args->is_continued = false; + return NULL; + } + } + if (!NIL_P(container->callbacks)) { + const long callbacks_len = RARRAY_LEN(container->callbacks); + if (0 == callbacks_len) { + return NULL; + } + for (int j = 0; j < callbacks_len; j++) { + VALUE cb = rb_ary_entry(container->callbacks, j); + result = rb_funcall(cb, id_call, 0); + if (result == Qfalse) { + args->is_continued = false; + return NULL; + } + } + } + + return NULL; +} + +static bool encoder_begin_callback(struct whisper_context *ctx, struct whisper_state *state, void *user_data) { + const ruby_whisper_callback_container *container = (ruby_whisper_callback_container *)user_data; + if (!ruby_whisper_callback_container_is_present(container)) { + return true; + } + + call_encoder_begin_callbacks_args args = { + container, + state, + true + }; + rb_thread_call_with_gvl(call_encoder_begin_callbacks, (void *)&args); + + return args.is_continued; +} + +typedef struct { + const ruby_whisper_callback_container *container; + bool is_interrupted; +} call_abort_callbacks_args; + +static void* +call_abort_callbacks(void *v_args) { + call_abort_callbacks_args *args = (call_abort_callbacks_args *)v_args; + const ruby_whisper_callback_container *container = args->container; + VALUE result = Qnil; + + if (!NIL_P(container->callback)) { + result = rb_funcall(container->callback, id_call, 1, container->user_data); + if (RTEST(result)) { + args->is_interrupted = true; + return NULL; + } + } + if (NIL_P(container->callbacks)) { + return NULL; + } + const long n_callbacks = RARRAY_LEN(container->callbacks); + if (0 == n_callbacks) { + return NULL; + } + for (int j = 0; j < n_callbacks; j++) { + VALUE cb = rb_ary_entry(container->callbacks, j); + VALUE result = rb_funcall(cb, id_call, 0); + if (RTEST(result)) { + args->is_interrupted = true; + return NULL; + } + } + + return NULL; +} + +static bool abort_callback(void * user_data) { + ruby_whisper_abort_callback_user_data *data = (ruby_whisper_abort_callback_user_data *)user_data; + + int is_interrupted = RUBY_ATOMIC_LOAD(data->is_interrupted); + if (is_interrupted) { + return true; + } + + if (!(data->callback_container) || !ruby_whisper_callback_container_is_present(data->callback_container)) { + return false; + } + + call_abort_callbacks_args args = { + data->callback_container, + false + }; + rb_thread_call_with_gvl(call_abort_callbacks, (void *)&args); + + return args.is_interrupted; +} + +static void +check_thread_safety(ruby_whisper_params *rwp, int n_processors) +{ + if (n_processors == 1) { + return; + } + + // new_segment_callback is called only after multiple threads are joined + // progress_callback is not called when parallel + + if (ruby_whisper_callback_container_is_present(rwp->encoder_begin_callback_container)) { + rb_raise(rb_eRuntimeError, "encoder begin callback not supported on parallel transcription"); + } + + if (ruby_whisper_callback_container_is_present(rwp->abort_callback_container)) { + rb_raise(rb_eRuntimeError, "abort callback not supported on parallel transcription"); + } +} + +static void register_callbacks(ruby_whisper_params * rwp, VALUE * context, ruby_whisper_abort_callback_user_data *abort_callback_user_data) { + if (ruby_whisper_callback_container_is_present(rwp->new_segment_callback_container)) { + rwp->new_segment_callback_container->context = context; + rwp->params.new_segment_callback = new_segment_callback; + rwp->params.new_segment_callback_user_data = rwp->new_segment_callback_container; + } + + if (ruby_whisper_callback_container_is_present(rwp->progress_callback_container)) { + rwp->progress_callback_container->context = context; + rwp->params.progress_callback = progress_callback; + rwp->params.progress_callback_user_data = rwp->progress_callback_container; + } + + if (ruby_whisper_callback_container_is_present(rwp->encoder_begin_callback_container)) { + rwp->encoder_begin_callback_container->context = context; + rwp->params.encoder_begin_callback = encoder_begin_callback; + rwp->params.encoder_begin_callback_user_data = rwp->encoder_begin_callback_container; + } + + abort_callback_user_data->callback_container = rwp->abort_callback_container; + rwp->abort_callback_container->context = context; + rwp->params.abort_callback = abort_callback; + rwp->params.abort_callback_user_data = (void *)abort_callback_user_data; +} + +static void set_vad_params(ruby_whisper_params *rwp) +{ + ruby_whisper_vad_params * rwvp; + TypedData_Get_Struct(rwp->vad_params, ruby_whisper_vad_params, &ruby_whisper_vad_params_type, rwvp); + rwp->params.vad_params = rwvp->params; +} + +void +prepare_transcription(ruby_whisper_params *rwp, VALUE *context, int n_processors, ruby_whisper_abort_callback_user_data *abort_callback_user_data) +{ + check_thread_safety(rwp, n_processors); + register_callbacks(rwp, context, abort_callback_user_data); + set_vad_params(rwp); +} + +void +rb_whisper_params_mark(void *p) +{ + ruby_whisper_params *rwp = (ruby_whisper_params *)p; + ruby_whisper_callback_container_mark(rwp->new_segment_callback_container); + ruby_whisper_callback_container_mark(rwp->progress_callback_container); + ruby_whisper_callback_container_mark(rwp->encoder_begin_callback_container); + ruby_whisper_callback_container_mark(rwp->abort_callback_container); + rb_gc_mark(rwp->vad_params); +} + +void +ruby_whisper_params_free(ruby_whisper_params *rwp) +{ + if (rwp->params.language) { + ruby_xfree((void *)rwp->params.language); + } + if (rwp->params.initial_prompt) { + ruby_xfree((void *)rwp->params.initial_prompt); + } + if (rwp->params.vad_model_path) { + ruby_xfree((void *)rwp->params.vad_model_path); + } + + xfree(rwp->new_segment_callback_container); + xfree(rwp->progress_callback_container); + xfree(rwp->encoder_begin_callback_container); + xfree(rwp->abort_callback_container); +} + +void +rb_whisper_params_free(void *p) +{ + ruby_whisper_params *rwp = (ruby_whisper_params *)p; + // How to free user_data and callback only when not referred to by others? + ruby_whisper_params_free(rwp); + xfree(rwp); +} + +static size_t +ruby_whisper_params_memsize(const void *p) +{ + const ruby_whisper_params *rwp = (const ruby_whisper_params *)p; + + return sizeof(ruby_whisper_params) + sizeof(rwp->params) + sizeof(rwp->vad_params); +} + +const rb_data_type_t ruby_whisper_params_type = { + "ruby_whisper_params", + { + rb_whisper_params_mark, + rb_whisper_params_free, + ruby_whisper_params_memsize, + }, + 0, 0, + 0 +}; + +static VALUE +ruby_whisper_params_allocate(VALUE klass) +{ + ruby_whisper_params *rwp; + VALUE obj = TypedData_Make_Struct(klass, ruby_whisper_params, &ruby_whisper_params_type, rwp); + rwp->params = whisper_full_default_params(WHISPER_SAMPLING_GREEDY); + if (rwp->params.language != NULL) { + rwp->params.language = ruby_strdup(rwp->params.language); + } + if (rwp->params.initial_prompt != NULL) { + rwp->params.initial_prompt = ruby_strdup(rwp->params.initial_prompt); + } + if (rwp->params.vad_model_path != NULL) { + rwp->params.vad_model_path = ruby_strdup(rwp->params.vad_model_path); + } + rwp->diarize = false; + rwp->vad_params = rb_class_new_instance(0, NULL, cVADParams); + rwp->new_segment_callback_container = ruby_whisper_callback_container_allocate(); + rwp->progress_callback_container = ruby_whisper_callback_container_allocate(); + rwp->encoder_begin_callback_container = ruby_whisper_callback_container_allocate(); + rwp->abort_callback_container = ruby_whisper_callback_container_allocate(); + return obj; +} + +/* + * params.language = "auto" | "en", etc... + * + * call-seq: + * language = lang_name -> lang_name + */ +static VALUE +ruby_whisper_params_set_language(VALUE self, VALUE value) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + ruby_xfree((void *)rwp->params.language); + rwp->params.language = NULL; + if (value == Qfalse || value == Qnil) { + rwp->params.language = ruby_strdup("auto"); + } else { + rwp->params.language = ruby_strdup(StringValueCStr(value)); + } + return value; +} +/* + * call-seq: + * language -> String + */ +static VALUE +ruby_whisper_params_get_language(VALUE self) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + if (rwp->params.language) { + return rb_str_new2(rwp->params.language); + } else { + return rb_str_new2("auto"); + } +} +/* + * call-seq: + * translate = do_translate -> do_translate + */ +static VALUE +ruby_whisper_params_set_translate(VALUE self, VALUE value) +{ + BOOL_PARAMS_SETTER(self, translate, value) +} +/* + * call-seq: + * translate -> bool + */ +static VALUE +ruby_whisper_params_get_translate(VALUE self) +{ + BOOL_PARAMS_GETTER(self, translate) +} +/* + * call-seq: + * no_context = dont_use_context -> dont_use_context + */ +static VALUE +ruby_whisper_params_set_no_context(VALUE self, VALUE value) +{ + BOOL_PARAMS_SETTER(self, no_context, value) +} +/* + * If true, does not use past transcription (if any) as initial prompt for the decoder. + * + * call-seq: + * no_context -> bool + */ +static VALUE +ruby_whisper_params_get_no_context(VALUE self) +{ + BOOL_PARAMS_GETTER(self, no_context) +} +/* + * call-seq: + * single_segment = force_single -> force_single + */ +static VALUE +ruby_whisper_params_set_single_segment(VALUE self, VALUE value) +{ + BOOL_PARAMS_SETTER(self, single_segment, value) +} +/* + * If true, forces single segment output (useful for streaming). + * + * call-seq: + * single_segment -> bool + */ +static VALUE +ruby_whisper_params_get_single_segment(VALUE self) +{ + BOOL_PARAMS_GETTER(self, single_segment) +} +/* + * call-seq: + * print_special = force_print -> force_print + */ +static VALUE +ruby_whisper_params_set_print_special(VALUE self, VALUE value) +{ + BOOL_PARAMS_SETTER(self, print_special, value) +} +/* + * If true, prints special tokens (e.g. <SOT>, <EOT>, <BEG>, etc.). + * + * call-seq: + * print_special -> bool + */ +static VALUE +ruby_whisper_params_get_print_special(VALUE self) +{ + BOOL_PARAMS_GETTER(self, print_special) +} +/* + * call-seq: + * print_progress = force_print -> force_print + */ +static VALUE +ruby_whisper_params_set_print_progress(VALUE self, VALUE value) +{ + BOOL_PARAMS_SETTER(self, print_progress, value) +} +/* + * If true, prints progress information. + * + * call-seq: + * print_progress -> bool + */ +static VALUE +ruby_whisper_params_get_print_progress(VALUE self) +{ + BOOL_PARAMS_GETTER(self, print_progress) +} +/* + * call-seq: + * print_realtime = force_print -> force_print + */ +static VALUE +ruby_whisper_params_set_print_realtime(VALUE self, VALUE value) +{ + BOOL_PARAMS_SETTER(self, print_realtime, value) +} +/* + * If true, prints results from within whisper.cpp. (avoid it, use callback instead) + * + * call-seq: + * print_realtime -> bool + */ +static VALUE +ruby_whisper_params_get_print_realtime(VALUE self) +{ + BOOL_PARAMS_GETTER(self, print_realtime) +} +/* + * call-seq: + * print_timestamps = force_print -> force_print + */ +static VALUE +ruby_whisper_params_set_print_timestamps(VALUE self, VALUE value) +{ + BOOL_PARAMS_SETTER(self, print_timestamps, value) +} +/* + * If true, prints timestamps for each text segment when printing realtime. + * + * call-seq: + * print_timestamps -> bool + */ +static VALUE +ruby_whisper_params_get_print_timestamps(VALUE self) +{ + BOOL_PARAMS_GETTER(self, print_timestamps) +} + +/* + * call-seq: + * carry_initial_prompt -> true or false + */ +static VALUE +ruby_whisper_params_get_carry_initial_prompt(VALUE self) +{ + BOOL_PARAMS_GETTER(self, carry_initial_prompt) +} + +/* + * call-seq: + * carry_initial_prompt = bool -> bool + */ +static VALUE +ruby_whisper_params_set_carry_initial_prompt(VALUE self, VALUE value) +{ + BOOL_PARAMS_SETTER(self, carry_initial_prompt, value) +} +/* + * call-seq: + * suppress_blank = force_suppress -> force_suppress + */ +static VALUE +ruby_whisper_params_set_suppress_blank(VALUE self, VALUE value) +{ + BOOL_PARAMS_SETTER(self, suppress_blank, value) +} +/* + * If true, suppresses blank outputs. + * + * call-seq: + * suppress_blank -> bool + */ +static VALUE +ruby_whisper_params_get_suppress_blank(VALUE self) +{ + BOOL_PARAMS_GETTER(self, suppress_blank) +} +/* + * call-seq: + * suppress_nst = force_suppress -> force_suppress + */ +static VALUE +ruby_whisper_params_set_suppress_nst(VALUE self, VALUE value) +{ + BOOL_PARAMS_SETTER(self, suppress_nst, value) +} +/* + * If true, suppresses non-speech-tokens. + * + * call-seq: + * suppress_nst -> bool + */ +static VALUE +ruby_whisper_params_get_suppress_nst(VALUE self) +{ + BOOL_PARAMS_GETTER(self, suppress_nst) +} +/* + * If true, enables token-level timestamps. + * + * call-seq: + * token_timestamps -> bool + */ +static VALUE +ruby_whisper_params_get_token_timestamps(VALUE self) +{ + BOOL_PARAMS_GETTER(self, token_timestamps) +} +/* + * call-seq: + * token_timestamps = force_timestamps -> force_timestamps + */ +static VALUE +ruby_whisper_params_set_token_timestamps(VALUE self, VALUE value) +{ + BOOL_PARAMS_SETTER(self, token_timestamps, value) +} + +/* + * max segment length in characters. + * + * call-seq: + * max_len -> Integer + */ +static VALUE +ruby_whisper_params_get_max_len(VALUE self) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + return INT2NUM(rwp->params.max_len); +} +/* + * call-seq: + * max_len = length -> length + */ +static VALUE +ruby_whisper_params_set_max_len(VALUE self, VALUE value) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + rwp->params.max_len = NUM2INT(value); + return value; +} + +/* + * If true, split on word rather than on token (when used with max_len). + * + * call-seq: + * translate -> bool + */ +static VALUE +ruby_whisper_params_get_split_on_word(VALUE self) +{ + BOOL_PARAMS_GETTER(self, split_on_word) +} +/* + * call-seq: + * split_on_word = force_split -> force_split + */ +static VALUE +ruby_whisper_params_set_split_on_word(VALUE self, VALUE value) +{ + BOOL_PARAMS_SETTER(self, split_on_word, value) +} +/* + * Tokens to provide to the whisper decoder as initial prompt + * these are prepended to any existing text context from a previous call + * use whisper_tokenize() to convert text to tokens. + * Maximum of whisper_n_text_ctx()/2 tokens are used (typically 224). + * + * call-seq: + * initial_prompt -> String + */ +static VALUE +ruby_whisper_params_get_initial_prompt(VALUE self) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + return rwp->params.initial_prompt == NULL ? Qnil : rb_str_new2(rwp->params.initial_prompt); +} +/* + * call-seq: + * initial_prompt = prompt -> prompt + */ +static VALUE +ruby_whisper_params_set_initial_prompt(VALUE self, VALUE value) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + ruby_xfree((void *)rwp->params.initial_prompt); + rwp->params.initial_prompt = NULL; + if (NIL_P(value)) { + rwp->params.initial_prompt = NULL; + } else { + rwp->params.initial_prompt = ruby_strdup(StringValueCStr(value)); + } + return value; +} +/* + * If true, enables diarization. + * + * call-seq: + * diarize -> bool + */ +static VALUE +ruby_whisper_params_get_diarize(VALUE self) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + if (rwp->diarize) { + return Qtrue; + } else { + return Qfalse; + } +} +/* + * call-seq: + * diarize = force_diarize -> force_diarize + */ +static VALUE +ruby_whisper_params_set_diarize(VALUE self, VALUE value) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + if (value == Qfalse || value == Qnil) { + rwp->diarize = false; + } else { + rwp->diarize = true; + } \ + return value; +} + +/* + * Start offset in ms. + * + * call-seq: + * offset -> Integer + */ +static VALUE +ruby_whisper_params_get_offset(VALUE self) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + return INT2NUM(rwp->params.offset_ms); +} +/* + * call-seq: + * offset = offset_ms -> offset_ms + */ +static VALUE +ruby_whisper_params_set_offset(VALUE self, VALUE value) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + rwp->params.offset_ms = NUM2INT(value); + return value; +} +/* + * Audio duration to process in ms. + * + * call-seq: + * duration -> Integer + */ +static VALUE +ruby_whisper_params_get_duration(VALUE self) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + return INT2NUM(rwp->params.duration_ms); +} +/* + * call-seq: + * duration = duration_ms -> duration_ms + */ +static VALUE +ruby_whisper_params_set_duration(VALUE self, VALUE value) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + rwp->params.duration_ms = NUM2INT(value); + return value; +} + +/* + * Max tokens to use from past text as prompt for the decoder. + * + * call-seq: + * max_text_tokens -> Integer + */ +static VALUE +ruby_whisper_params_get_max_text_tokens(VALUE self) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + return INT2NUM(rwp->params.n_max_text_ctx); +} +/* + * call-seq: + * max_text_tokens = n_tokens -> n_tokens + */ +static VALUE +ruby_whisper_params_set_max_text_tokens(VALUE self, VALUE value) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + rwp->params.n_max_text_ctx = NUM2INT(value); + return value; +} +/* + * call-seq: + * temperature -> Float + */ +static VALUE +ruby_whisper_params_get_temperature(VALUE self) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + return DBL2NUM(rwp->params.temperature); +} +/* + * call-seq: + * temperature = temp -> temp + */ +static VALUE +ruby_whisper_params_set_temperature(VALUE self, VALUE value) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + rwp->params.temperature = NUM2DBL(value); + return value; +} +/* + * See https://github.com/openai/whisper/blob/f82bc59f5ea234d4b97fb2860842ed38519f7e65/whisper/decoding.py#L97 + * + * call-seq: + * max_initial_ts -> Flaot + */ +static VALUE +ruby_whisper_params_get_max_initial_ts(VALUE self) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + return DBL2NUM(rwp->params.max_initial_ts); +} +/* + * call-seq: + * max_initial_ts = timestamp -> timestamp + */ +static VALUE +ruby_whisper_params_set_max_initial_ts(VALUE self, VALUE value) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + rwp->params.max_initial_ts = NUM2DBL(value); + return value; +} +/* + * call-seq: + * length_penalty -> Float + */ +static VALUE +ruby_whisper_params_get_length_penalty(VALUE self) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + return DBL2NUM(rwp->params.length_penalty); +} +/* + * call-seq: + * length_penalty = penalty -> penalty + */ +static VALUE +ruby_whisper_params_set_length_penalty(VALUE self, VALUE value) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + rwp->params.length_penalty = NUM2DBL(value); + return value; +} +/* + * call-seq: + * temperature_inc -> Float + */ +static VALUE +ruby_whisper_params_get_temperature_inc(VALUE self) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + return DBL2NUM(rwp->params.temperature_inc); +} +/* + * call-seq: + * temperature_inc = inc -> inc + */ +static VALUE +ruby_whisper_params_set_temperature_inc(VALUE self, VALUE value) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + rwp->params.temperature_inc = NUM2DBL(value); + return value; +} +/* + * Similar to OpenAI's "compression_ratio_threshold" + * + * call-seq: + * entropy_thold -> Float + */ +static VALUE +ruby_whisper_params_get_entropy_thold(VALUE self) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + return DBL2NUM(rwp->params.entropy_thold); +} +/* + * call-seq: + * entropy_thold = threshold -> threshold + */ +static VALUE +ruby_whisper_params_set_entropy_thold(VALUE self, VALUE value) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + rwp->params.entropy_thold = NUM2DBL(value); + return value; +} +/* + * call-seq: + * logprob_thold -> Float + */ +static VALUE +ruby_whisper_params_get_logprob_thold(VALUE self) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + return DBL2NUM(rwp->params.logprob_thold); +} +/* + * call-seq: + * logprob_thold = threshold -> threshold + */ +static VALUE +ruby_whisper_params_set_logprob_thold(VALUE self, VALUE value) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + rwp->params.logprob_thold = NUM2DBL(value); + return value; +} +/* + * call-seq: + * no_speech_thold -> Float + */ +static VALUE +ruby_whisper_params_get_no_speech_thold(VALUE self) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + return DBL2NUM(rwp->params.no_speech_thold); +} +/* + * call-seq: + * no_speech_thold = threshold -> threshold + */ +static VALUE +ruby_whisper_params_set_no_speech_thold(VALUE self, VALUE value) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + rwp->params.no_speech_thold = NUM2DBL(value); + return value; +} +static VALUE +ruby_whisper_params_get_new_segment_callback(VALUE self) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + return rwp->new_segment_callback_container->callback; +} +/* + * Sets new segment callback, called for every newly generated text segment. + * + * params.new_segment_callback = ->(context, _, n_new, user_data) { + * # ... + * } + * + * call-seq: + * new_segment_callback = callback -> callback + */ +static VALUE +ruby_whisper_params_set_new_segment_callback(VALUE self, VALUE value) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + rwp->new_segment_callback_container->callback = value; + return value; +} +static VALUE +ruby_whisper_params_get_new_segment_callback_user_data(VALUE self) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + return rwp->new_segment_callback_container->user_data; +} +/* + * Sets user data passed to the last argument of new segment callback. + * + * call-seq: + * new_segment_callback_user_data = user_data -> use_data + */ +static VALUE +ruby_whisper_params_set_new_segment_callback_user_data(VALUE self, VALUE value) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + rwp->new_segment_callback_container->user_data = value; + return value; +} +static VALUE +ruby_whisper_params_get_progress_callback(VALUE self) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + return rwp->progress_callback_container->callback; +} +/* + * Sets progress callback, called on each progress update. + * + * params.new_segment_callback = ->(context, _, progress, user_data) { + * # ... + * } + * + * +progress+ is an Integer between 0 and 100. + * + * call-seq: + * progress_callback = callback -> callback + */ +static VALUE +ruby_whisper_params_set_progress_callback(VALUE self, VALUE value) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + rwp->progress_callback_container->callback = value; + return value; +} +static VALUE +ruby_whisper_params_get_progress_callback_user_data(VALUE self) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + return rwp->progress_callback_container->user_data; +} +/* + * Sets user data passed to the last argument of progress callback. + * + * call-seq: + * progress_callback_user_data = user_data -> use_data + */ +static VALUE +ruby_whisper_params_set_progress_callback_user_data(VALUE self, VALUE value) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + rwp->progress_callback_container->user_data = value; + return value; +} + +static VALUE +ruby_whisper_params_get_encoder_begin_callback(VALUE self) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + return rwp->encoder_begin_callback_container->callback; +} + +/* + * Sets encoder begin callback, called when the encoder starts. + * + * params.encoder_begin_callback = ->(context, _, user_data) { + * # ... + * } + * + * call-seq: + * encoder_begin_callback = callback -> callback + */ +static VALUE +ruby_whisper_params_set_encoder_begin_callback(VALUE self, VALUE value) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + rwp->encoder_begin_callback_container->callback = value; + return value; +} + +static VALUE +ruby_whisper_params_get_encoder_begin_callback_user_data(VALUE self) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + return rwp->encoder_begin_callback_container->user_data; +} + +/* + * Sets user data passed to the last argument of encoder begin callback. + * + * call-seq: + * encoder_begin_callback_user_data = user_data -> use_data + */ +static VALUE +ruby_whisper_params_set_encoder_begin_callback_user_data(VALUE self, VALUE value) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + rwp->encoder_begin_callback_container->user_data = value; + return value; +} + +static VALUE +ruby_whisper_params_get_abort_callback(VALUE self) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + return rwp->abort_callback_container->callback; +} +/* + * Sets abort callback, called to check if the process should be aborted. + * + * params.abort_callback = ->(user_data) { + * # ... + * } + * + * call-seq: + * abort_callback = callback -> callback + */ +static VALUE +ruby_whisper_params_set_abort_callback(VALUE self, VALUE value) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + rwp->abort_callback_container->callback = value; + return value; +} +static VALUE +ruby_whisper_params_get_abort_callback_user_data(VALUE self) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + return rwp->abort_callback_container->user_data; +} +/* + * Sets user data passed to the last argument of abort callback. + * + * call-seq: + * abort_callback_user_data = user_data -> use_data + */ +static VALUE +ruby_whisper_params_set_abort_callback_user_data(VALUE self, VALUE value) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + rwp->abort_callback_container->user_data = value; + return value; +} + +/* + * call-seq: + * vad = use_vad -> use_vad + */ +static VALUE +ruby_whisper_params_get_vad(VALUE self) +{ + BOOL_PARAMS_GETTER(self, vad) +} + +static VALUE +ruby_whisper_params_set_vad(VALUE self, VALUE value) +{ + BOOL_PARAMS_SETTER(self, vad, value) +} + +/* + * call-seq: + * vad_model_path = model_path -> model_path + */ +static VALUE +ruby_whisper_params_set_vad_model_path(VALUE self, VALUE value) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + ruby_xfree((void *)rwp->params.vad_model_path); + rwp->params.vad_model_path = NULL; + if (NIL_P(value)) { + rwp->params.vad_model_path = NULL; + return value; + } + VALUE path = ruby_whisper_normalize_model_path(value); + rwp->params.vad_model_path = ruby_strdup(StringValueCStr(path)); + return value; +} + +static VALUE +ruby_whisper_params_get_vad_model_path(VALUE self) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + return rwp->params.vad_model_path == NULL ? Qnil : rb_str_new2(rwp->params.vad_model_path); +} + +/* + * call-seq: + * vad_params = params -> params + */ +static VALUE +ruby_whisper_params_set_vad_params(VALUE self, VALUE value) +{ + ruby_whisper_params *rwp; + rb_check_typeddata(value, &ruby_whisper_vad_params_type); + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + rwp->vad_params = value; + return value; +} + +static VALUE +ruby_whisper_params_get_vad_params(VALUE self) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + return rwp->vad_params; +} + +#define SET_PARAM_IF_SAME(param_name) \ + if (id == id_ ## param_name) { \ + ruby_whisper_params_set_ ## param_name(self, value); \ + continue; \ + } + +static VALUE +ruby_whisper_params_initialize(int argc, VALUE *argv, VALUE self) +{ + VALUE kw_hash; + VALUE values[RUBY_WHISPER_PARAMS_PARAM_NAMES_COUNT] = {Qundef}; + VALUE value; + ruby_whisper_params *rwp; + ID id; + int i; + + rb_scan_args_kw(RB_SCAN_ARGS_KEYWORDS, argc, argv, ":", &kw_hash); + if (NIL_P(kw_hash)) { + return self; + } + + rb_get_kwargs(kw_hash, param_names, 0, RUBY_WHISPER_PARAMS_PARAM_NAMES_COUNT, values); + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + + for (i = 0; i < RUBY_WHISPER_PARAMS_PARAM_NAMES_COUNT; i++) { + id = param_names[i]; + value = values[i]; + if (value == Qundef) { + continue; + } + if (id == id_diarize) { + rwp->diarize = value; + continue; + } else { + SET_PARAM_IF_SAME(language) + SET_PARAM_IF_SAME(translate) + SET_PARAM_IF_SAME(no_context) + SET_PARAM_IF_SAME(single_segment) + SET_PARAM_IF_SAME(print_special) + SET_PARAM_IF_SAME(print_progress) + SET_PARAM_IF_SAME(print_realtime) + SET_PARAM_IF_SAME(print_timestamps) + SET_PARAM_IF_SAME(suppress_blank) + SET_PARAM_IF_SAME(suppress_nst) + SET_PARAM_IF_SAME(token_timestamps) + SET_PARAM_IF_SAME(max_len) + SET_PARAM_IF_SAME(split_on_word) + SET_PARAM_IF_SAME(initial_prompt) + SET_PARAM_IF_SAME(carry_initial_prompt) + SET_PARAM_IF_SAME(offset) + SET_PARAM_IF_SAME(duration) + SET_PARAM_IF_SAME(max_text_tokens) + SET_PARAM_IF_SAME(temperature) + SET_PARAM_IF_SAME(max_initial_ts) + SET_PARAM_IF_SAME(length_penalty) + SET_PARAM_IF_SAME(temperature_inc) + SET_PARAM_IF_SAME(entropy_thold) + SET_PARAM_IF_SAME(logprob_thold) + SET_PARAM_IF_SAME(no_speech_thold) + SET_PARAM_IF_SAME(new_segment_callback) + SET_PARAM_IF_SAME(new_segment_callback_user_data) + SET_PARAM_IF_SAME(progress_callback) + SET_PARAM_IF_SAME(progress_callback_user_data) + SET_PARAM_IF_SAME(encoder_begin_callback) + SET_PARAM_IF_SAME(encoder_begin_callback_user_data) + SET_PARAM_IF_SAME(abort_callback) + SET_PARAM_IF_SAME(abort_callback_user_data) + SET_PARAM_IF_SAME(vad) + SET_PARAM_IF_SAME(vad_model_path) + SET_PARAM_IF_SAME(vad_params) + } + } + + return self; +} + +#undef SET_PARAM_IF_SAME + +/* + * Hook called on new segment. Yields each Whisper::Segment. + * + * whisper.on_new_segment do |segment| + * # ... + * end + * + * call-seq: + * on_new_segment {|segment| ... } + */ +static VALUE +ruby_whisper_params_on_new_segment(VALUE self) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + const VALUE blk = rb_block_proc(); + if (NIL_P(rwp->new_segment_callback_container->callbacks)) { + rwp->new_segment_callback_container->callbacks = rb_ary_new(); + } + rb_ary_push(rwp->new_segment_callback_container->callbacks, blk); + return Qnil; +} + +/* + * Hook called on progress update. Yields each progress Integer between 0 and 100. + * + * whisper.on_progress do |progress| + * # ... + * end + * + * call-seq: + * on_progress {|progress| ... } + */ +static VALUE +ruby_whisper_params_on_progress(VALUE self) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + const VALUE blk = rb_block_proc(); + if (NIL_P(rwp->progress_callback_container->callbacks)) { + rwp->progress_callback_container->callbacks = rb_ary_new(); + } + rb_ary_push(rwp->progress_callback_container->callbacks, blk); + return Qnil; +} + +/* + * Hook called when the encoder starts. + * + * whisper.on_encoder_begin do + * # ... + * end + * + * call-seq: + * on_encoder_begin { ... } + */ +static VALUE +ruby_whisper_params_on_encoder_begin(VALUE self) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + const VALUE blk = rb_block_proc(); + if (NIL_P(rwp->encoder_begin_callback_container->callbacks)) { + rwp->encoder_begin_callback_container->callbacks = rb_ary_new(); + } + rb_ary_push(rwp->encoder_begin_callback_container->callbacks, blk); + return Qnil; +} + +/* + * Call block to determine whether abort or not. Return +true+ when you want to abort. + * + * params.abort_on do + * if some_condition + * true # abort + * else + * false # continue + * end + * end + * + * call-seq: + * abort_on { ... } + */ +static VALUE +ruby_whisper_params_abort_on(VALUE self) +{ + ruby_whisper_params *rwp; + TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); + const VALUE blk = rb_block_proc(); + if (NIL_P(rwp->abort_callback_container->callbacks)) { + rwp->abort_callback_container->callbacks = rb_ary_new(); + } + rb_ary_push(rwp->abort_callback_container->callbacks, blk); + return Qnil; +} + +void +init_ruby_whisper_params(VALUE *mWhisper) +{ + cParams = rb_define_class_under(*mWhisper, "Params", rb_cObject); + + rb_define_alloc_func(cParams, ruby_whisper_params_allocate); + rb_define_method(cParams, "initialize", ruby_whisper_params_initialize, -1); + + DEFINE_PARAM(language, 0) + DEFINE_PARAM(translate, 1) + DEFINE_PARAM(no_context, 2) + DEFINE_PARAM(single_segment, 3) + DEFINE_PARAM(print_special, 4) + DEFINE_PARAM(print_progress, 5) + DEFINE_PARAM(print_realtime, 6) + DEFINE_PARAM(print_timestamps, 7) + DEFINE_PARAM(suppress_blank, 8) + DEFINE_PARAM(suppress_nst, 9) + DEFINE_PARAM(token_timestamps, 10) + DEFINE_PARAM(max_len, 11) + DEFINE_PARAM(split_on_word, 12) + DEFINE_PARAM(initial_prompt, 13) + DEFINE_PARAM(carry_initial_prompt, 14) + DEFINE_PARAM(diarize, 15) + DEFINE_PARAM(offset, 16) + DEFINE_PARAM(duration, 17) + DEFINE_PARAM(max_text_tokens, 18) + DEFINE_PARAM(temperature, 19) + DEFINE_PARAM(max_initial_ts, 20) + DEFINE_PARAM(length_penalty, 21) + DEFINE_PARAM(temperature_inc, 22) + DEFINE_PARAM(entropy_thold, 23) + DEFINE_PARAM(logprob_thold, 24) + DEFINE_PARAM(no_speech_thold, 25) + DEFINE_PARAM(new_segment_callback, 26) + DEFINE_PARAM(new_segment_callback_user_data, 27) + DEFINE_PARAM(progress_callback, 28) + DEFINE_PARAM(progress_callback_user_data, 29) + DEFINE_PARAM(encoder_begin_callback, 30) + DEFINE_PARAM(encoder_begin_callback_user_data, 31) + DEFINE_PARAM(abort_callback, 32) + DEFINE_PARAM(abort_callback_user_data, 33) + DEFINE_PARAM(vad, 34) + DEFINE_PARAM(vad_model_path, 35) + DEFINE_PARAM(vad_params, 36) + + rb_define_method(cParams, "on_new_segment", ruby_whisper_params_on_new_segment, 0); + rb_define_method(cParams, "on_progress", ruby_whisper_params_on_progress, 0); + rb_define_method(cParams, "on_encoder_begin", ruby_whisper_params_on_encoder_begin, 0); + rb_define_method(cParams, "abort_on", ruby_whisper_params_abort_on, 0); +} diff --git a/bindings/ruby/ext/ruby_whisper_segment.c b/bindings/ruby/ext/ruby_whisper_segment.c new file mode 100644 index 0000000..cf03727 --- /dev/null +++ b/bindings/ruby/ext/ruby_whisper_segment.c @@ -0,0 +1,284 @@ +#include "ruby_whisper.h" + +#define N_KEY_NAMES 6 + +extern ID id___method__; +extern ID id_to_enum; +VALUE sym_start_time; +VALUE sym_end_time; +VALUE sym_text; +VALUE sym_no_speech_prob; +VALUE sym_speaker_turn_next; +VALUE sym_n_tokens; + +extern const rb_data_type_t ruby_whisper_type; + +extern VALUE cSegment; + +extern VALUE ruby_whisper_token_s_init(struct whisper_context *context, int i_segment, int index); + +static void +rb_whisper_segment_mark(void *p) +{ + ruby_whisper_segment *rws = (ruby_whisper_segment *)p; + rb_gc_mark(rws->context); +} + +static size_t +ruby_whisper_segment_memsize(const void *p) +{ + const ruby_whisper_segment *rws = (const ruby_whisper_segment *)p; + size_t size = sizeof(rws); + if (!rws) { + return 0; + } + if (rws->index) { + size += sizeof(rws->index); + } + return size; +} + +static const rb_data_type_t ruby_whisper_segment_type = { + "ruby_whisper_segment", + {rb_whisper_segment_mark, RUBY_DEFAULT_FREE, ruby_whisper_segment_memsize,}, + 0, 0, + 0 +}; + +VALUE +ruby_whisper_segment_allocate(VALUE klass) +{ + ruby_whisper_segment *rws; + return TypedData_Make_Struct(klass, ruby_whisper_segment, &ruby_whisper_segment_type, rws); +} + +VALUE +rb_whisper_segment_s_new(VALUE context, int index) +{ + ruby_whisper_segment *rws; + const VALUE segment = ruby_whisper_segment_allocate(cSegment); + TypedData_Get_Struct(segment, ruby_whisper_segment, &ruby_whisper_segment_type, rws); + rws->context = context; + rws->index = index; + return segment; +}; + +/* + * Start time in milliseconds. + * + * call-seq: + * start_time -> Integer + */ +static VALUE +ruby_whisper_segment_get_start_time(VALUE self) +{ + ruby_whisper_segment *rws; + TypedData_Get_Struct(self, ruby_whisper_segment, &ruby_whisper_segment_type, rws); + ruby_whisper *rw; + GetContext(rws->context, rw); + const int64_t t0 = whisper_full_get_segment_t0(rw->context, rws->index); + // able to multiply 10 without overflow because to_timestamp() in whisper.cpp does it + return LONG2NUM(t0 * 10); +} + +/* + * End time in milliseconds. + * + * call-seq: + * end_time -> Integer + */ +static VALUE +ruby_whisper_segment_get_end_time(VALUE self) +{ + ruby_whisper_segment *rws; + TypedData_Get_Struct(self, ruby_whisper_segment, &ruby_whisper_segment_type, rws); + ruby_whisper *rw; + GetContext(rws->context, rw); + const int64_t t1 = whisper_full_get_segment_t1(rw->context, rws->index); + // able to multiply 10 without overflow because to_timestamp() in whisper.cpp does it + return LONG2NUM(t1 * 10); +} + +/* + * Whether the next segment is predicted as a speaker turn. + * + * call-seq: + * speaker_turn_next? -> bool + */ +static VALUE +ruby_whisper_segment_get_speaker_turn_next(VALUE self) +{ + ruby_whisper_segment *rws; + TypedData_Get_Struct(self, ruby_whisper_segment, &ruby_whisper_segment_type, rws); + ruby_whisper *rw; + GetContext(rws->context, rw); + return whisper_full_get_segment_speaker_turn_next(rw->context, rws->index) ? Qtrue : Qfalse; +} + +/* + * call-seq: + * text -> String + */ +static VALUE +ruby_whisper_segment_get_text(VALUE self) +{ + ruby_whisper_segment *rws; + TypedData_Get_Struct(self, ruby_whisper_segment, &ruby_whisper_segment_type, rws); + ruby_whisper *rw; + GetContext(rws->context, rw); + const char * text = whisper_full_get_segment_text(rw->context, rws->index); + return rb_str_new2(text); +} + +/* + * call-seq: + * no_speech_prob -> Float + */ +static VALUE +ruby_whisper_segment_get_no_speech_prob(VALUE self) +{ + ruby_whisper_segment *rws; + TypedData_Get_Struct(self, ruby_whisper_segment, &ruby_whisper_segment_type, rws); + ruby_whisper *rw; + GetContext(rws->context, rw); + return DBL2NUM(whisper_full_get_segment_no_speech_prob(rw->context, rws->index)); +} + +/* + * Get number of tokens in the segment + * + * call-seq: + * n_tokens -> Integer + */ +static VALUE +ruby_whisper_segment_get_n_tokens(VALUE self) +{ + ruby_whisper_segment *rws; + TypedData_Get_Struct(self, ruby_whisper_segment, &ruby_whisper_segment_type, rws); + ruby_whisper *rw; + GetContext(rws->context, rw); + return INT2NUM(whisper_full_n_tokens(rw->context, rws->index)); +} + +/* + * Yields each Whisper::Token: + * + * whisper.each_segment.first.each_token do |token| + * p token + * end + * + * Returns an Enumerator if no block is given: + * + * whisper.each_segment.first.each_token.to_a # => [#<Whisper::Token>, ...] + * + * call-seq: + * each_token {|token| ... } + * each_token -> Enumerator + */ +static VALUE +ruby_whisper_segment_each_token(VALUE self) +{ + if (!rb_block_given_p()) { + const VALUE method_name = rb_funcall(self, id___method__, 0); + return rb_funcall(self, id_to_enum, 1, method_name); + } + + ruby_whisper_segment *rws; + TypedData_Get_Struct(self, ruby_whisper_segment, &ruby_whisper_segment_type, rws); + ruby_whisper *rw; + GetContext(rws->context, rw); + + const int n_tokens = whisper_full_n_tokens(rw->context, rws->index); + for (int i = 0; i < n_tokens; ++i) { + rb_yield(ruby_whisper_token_s_init(rw->context, rws->index, i)); + } + + return self; +} + +/* + * call-seq: + * deconstruct_keys(keys) -> hash + * + * Possible keys: :start_time, :end_time, :text, :no_speech_prob, :speaker_turn_next, :n_tokens + * + * whisper.each_segment do |segment| + * segment => {start_time:, end_time:, text:, no_speech_prob:, speaker_turn_next:} + * + * puts "[#{start_time} --> #{end_time}] #{text} (no speech prob: #{no_speech_prob}#{speaker_turn_next ? ', speaker turns next' : ''})" + * end + */ +static VALUE +ruby_whisper_segment_deconstruct_keys(VALUE self, VALUE keys) +{ + ruby_whisper_segment *rws; + TypedData_Get_Struct(self, ruby_whisper_segment, &ruby_whisper_segment_type, rws); + ruby_whisper *rw; + GetContext(rws->context, rw); + + VALUE hash = rb_hash_new(); + long n_keys; + if (NIL_P(keys)) { + keys = rb_ary_new3( + N_KEY_NAMES, + sym_start_time, + sym_end_time, + sym_text, + sym_no_speech_prob, + sym_speaker_turn_next + ); + n_keys = N_KEY_NAMES; + } else { + n_keys = RARRAY_LEN(keys); + if (n_keys > N_KEY_NAMES) { + return hash; + } + } + for (int i = 0; i < n_keys; i++) { + VALUE key = rb_ary_entry(keys, i); + if (key == sym_start_time) { + rb_hash_aset(hash, key, ruby_whisper_segment_get_start_time(self)); + } + if (key == sym_end_time) { + rb_hash_aset(hash, key, ruby_whisper_segment_get_end_time(self)); + } + if (key == sym_text) { + rb_hash_aset(hash, key, ruby_whisper_segment_get_text(self)); + } + if (key == sym_no_speech_prob) { + rb_hash_aset(hash, key, ruby_whisper_segment_get_no_speech_prob(self)); + } + if (key == sym_speaker_turn_next) { + rb_hash_aset(hash, key, ruby_whisper_segment_get_speaker_turn_next(self)); + } + if (key == sym_n_tokens) { + rb_hash_aset(hash, key, ruby_whisper_segment_get_n_tokens(self)); + } + } + + return hash; +} + +void +init_ruby_whisper_segment(VALUE *mWhisper) +{ + cSegment = rb_define_class_under(*mWhisper, "Segment", rb_cObject); + + sym_start_time = ID2SYM(rb_intern("start_time")); + sym_end_time = ID2SYM(rb_intern("end_time")); + sym_text = ID2SYM(rb_intern("text")); + sym_no_speech_prob = ID2SYM(rb_intern("no_speech_prob")); + sym_speaker_turn_next = ID2SYM(rb_intern("speaker_turn_next")); + sym_n_tokens = ID2SYM(rb_intern("n_tokens")); + + rb_define_alloc_func(cSegment, ruby_whisper_segment_allocate); + rb_define_method(cSegment, "start_time", ruby_whisper_segment_get_start_time, 0); + rb_define_method(cSegment, "end_time", ruby_whisper_segment_get_end_time, 0); + rb_define_method(cSegment, "speaker_turn_next?", ruby_whisper_segment_get_speaker_turn_next, 0); + rb_define_method(cSegment, "text", ruby_whisper_segment_get_text, 0); + rb_define_method(cSegment, "no_speech_prob", ruby_whisper_segment_get_no_speech_prob, 0); + rb_define_method(cSegment, "n_tokens", ruby_whisper_segment_get_n_tokens, 0); + rb_define_method(cSegment, "each_token", ruby_whisper_segment_each_token, 0); + rb_define_method(cSegment, "deconstruct_keys", ruby_whisper_segment_deconstruct_keys, 1); +} +#undef N_KEY_NAMES diff --git a/bindings/ruby/ext/ruby_whisper_token.c b/bindings/ruby/ext/ruby_whisper_token.c new file mode 100644 index 0000000..73f5a54 --- /dev/null +++ b/bindings/ruby/ext/ruby_whisper_token.c @@ -0,0 +1,371 @@ +#include "ruby_whisper.h" + +#define N_KEY_NAMES 11 + +extern VALUE cToken; +extern const rb_data_type_t ruby_whisper_type; + +static VALUE sym_id; +static VALUE sym_tid; +static VALUE sym_probability; +static VALUE sym_log_probability; +static VALUE sym_pt; +static VALUE sym_ptsum; +static VALUE sym_t_dtw; +static VALUE sym_voice_length; +static VALUE sym_start_time; +static VALUE sym_end_time; +static VALUE sym_text; + +static size_t +ruby_whisper_token_memsize(const void *p) +{ + const ruby_whisper_token *rwt = (const ruby_whisper_token *)p; + if (!rwt) { + return 0; + } + size_t size = sizeof(*rwt); + if (rwt->token_data) { + size += sizeof(*rwt->token_data); + } + return size; +} + +static void +ruby_whisper_token_mark(void *p) +{ + ruby_whisper_token *rwt = (ruby_whisper_token *)p; + rb_gc_mark(rwt->text); +} + +static void +ruby_whisper_token_free(void *p) +{ + ruby_whisper_token *rwt = (ruby_whisper_token *)p; + if (rwt->token_data) { + xfree(rwt->token_data); + rwt->token_data = NULL; + } + xfree(rwt); +} + +static const rb_data_type_t ruby_whisper_token_type = { + "ruby_whisper_token", + {ruby_whisper_token_mark, ruby_whisper_token_free, ruby_whisper_token_memsize,}, + 0, 0, + 0 +}; + +static VALUE +ruby_whisper_token_allocate(VALUE klass) +{ + ruby_whisper_token *rwt; + VALUE token = TypedData_Make_Struct(klass, ruby_whisper_token, &ruby_whisper_token_type, rwt); + rwt->token_data = NULL; + rwt->text = Qnil; + return token; +} + +VALUE +ruby_whisper_token_s_init(struct whisper_context *context, int i_segment, int i_token) +{ + const VALUE token = ruby_whisper_token_allocate(cToken); + ruby_whisper_token *rwt; + TypedData_Get_Struct(token, ruby_whisper_token, &ruby_whisper_token_type, rwt); + rwt->token_data = ALLOC(whisper_token_data); + *(rwt->token_data) = whisper_full_get_token_data(context, i_segment, i_token); + rwt->text = rb_str_new2(whisper_full_get_token_text(context, i_segment, i_token)); + return token; +} + +/* + * Token ID. + * + * call-seq: + * id -> Integer + */ +static VALUE +ruby_whisper_token_get_id(VALUE self) +{ + ruby_whisper_token *rwt; + GetToken(self, rwt); + return INT2NUM(rwt->token_data->id); +} + +/* + * Forced timestamp token ID. + * + * call-seq: + * tid -> Integer + */ +static VALUE +ruby_whisper_token_get_tid(VALUE self) +{ + ruby_whisper_token *rwt; + GetToken(self, rwt); + return INT2NUM(rwt->token_data->tid); +} + +/* + * Probability of the token. + * + * call-seq: + * probability -> Float + */ +static VALUE +ruby_whisper_token_get_p(VALUE self) +{ + ruby_whisper_token *rwt; + GetToken(self, rwt); + return DBL2NUM(rwt->token_data->p); +} + +/* + * Log probability of the token. + * + * call-seq: + * log_probability -> Float + */ +static VALUE +ruby_whisper_token_get_plog(VALUE self) +{ + ruby_whisper_token *rwt; + GetToken(self, rwt); + return DBL2NUM(rwt->token_data->plog); +} + +/* + * Probability of the timestamp token. + * + * call-seq: + * pt -> Float + */ +static VALUE +ruby_whisper_token_get_pt(VALUE self) +{ + ruby_whisper_token *rwt; + GetToken(self, rwt); + return DBL2NUM(rwt->token_data->pt); +} + +/* + * Sum of probability of all timestamp tokens. + * + * call-seq: + * ptsum -> Float + */ +static VALUE +ruby_whisper_token_get_ptsum(VALUE self) +{ + ruby_whisper_token *rwt; + GetToken(self, rwt); + return DBL2NUM(rwt->token_data->ptsum); +} + +/* + * [EXPERIMENTAL] Token-level timestamps with DTW + * + * Do not use if you haven't computed token-level timestamps with dtw. + * Roughly corresponds to the moment in audio in which the token was output. + * + * call-seq: + * t_dtw -> Integer + */ +static VALUE +ruby_whisper_token_get_t_dtw(VALUE self) +{ + ruby_whisper_token *rwt; + GetToken(self, rwt); + return LONG2NUM(rwt->token_data->t_dtw); +} + +/* + * Voice length of the token. + * + * call-seq: + * voice_length -> Float + */ +static VALUE +ruby_whisper_token_get_vlen(VALUE self) +{ + ruby_whisper_token *rwt; + GetToken(self, rwt); + return DBL2NUM(rwt->token_data->vlen); +} + +/* + * Get the token text of the token. + * + * call-seq: + * text -> String + */ +static VALUE +ruby_whisper_token_get_text(VALUE self) +{ + ruby_whisper_token *rwt; + GetToken(self, rwt); + return rwt->text; +} + +/* + * Start time of the token. + * + * Token-level timestamp data. + * Do not use if you haven't computed token-level timestamps. + * + * call-seq: + * start_time -> Integer + */ +static VALUE +ruby_whisper_token_get_start_time(VALUE self) +{ + ruby_whisper_token *rwt; + GetToken(self, rwt); + return LONG2NUM(rwt->token_data->t0 * 10); +} + +/* + * End time of the token. + * + * Token-level timestamp data. + * Do not use if you haven't computed token-level timestamps. + * + * call-seq: + * end_time -> Integer + */ +static VALUE +ruby_whisper_token_get_end_time(VALUE self) +{ + ruby_whisper_token *rwt; + GetToken(self, rwt); + return LONG2NUM(rwt->token_data->t1 * 10); +} + +/* + * call-seq: + * deconstruct_keys(keys) -> hash + * + * Possible keys: :id, :tid, :probability, :log_probability, :pt, :ptsum, + * :t_dtw, :voice_length, :start_time, :end_time, :text + * segment.each_token do |token| + * token => {text:, probability:} + puts "#{text} (#{probability})" + * end + */ +static VALUE ruby_whisper_token_deconstruct_keys(VALUE self, VALUE keys) +{ + ruby_whisper_token *rwt; + GetToken(self, rwt); + VALUE hash = rb_hash_new(); + long n_keys = 0; + + if (NIL_P(keys)) { + keys = rb_ary_new3( + N_KEY_NAMES, + sym_id, + sym_tid, + sym_probability, + sym_log_probability, + sym_pt, + sym_ptsum, + sym_t_dtw, + sym_voice_length, + sym_start_time, + sym_end_time, + sym_text + ); + n_keys = N_KEY_NAMES; + } else { + n_keys = RARRAY_LEN(keys); + if (n_keys > N_KEY_NAMES) { + return hash; + } + } + + for (int i = 0; i < n_keys; i++) { + VALUE key = rb_ary_entry(keys, i); + if (key == sym_start_time) { + rb_hash_aset(hash, key, ruby_whisper_token_get_start_time(self)); + continue; + } + if (key == sym_end_time) { + rb_hash_aset(hash, key, ruby_whisper_token_get_end_time(self)); + continue; + } + if (key == sym_text) { + rb_hash_aset(hash, key, ruby_whisper_token_get_text(self)); + continue; + } + if (key == sym_probability) { + rb_hash_aset(hash, key, ruby_whisper_token_get_p(self)); + continue; + } + if (key == sym_id) { + rb_hash_aset(hash, key, ruby_whisper_token_get_id(self)); + continue; + } + if (key == sym_tid) { + rb_hash_aset(hash, key, ruby_whisper_token_get_tid(self)); + continue; + } + if (key == sym_log_probability) { + rb_hash_aset(hash, key, ruby_whisper_token_get_plog(self)); + continue; + } + if (key == sym_pt) { + rb_hash_aset(hash, key, ruby_whisper_token_get_pt(self)); + continue; + } + if (key == sym_ptsum) { + rb_hash_aset(hash, key, ruby_whisper_token_get_ptsum(self)); + continue; + } + if (key == sym_t_dtw) { + rb_hash_aset(hash, key, ruby_whisper_token_get_t_dtw(self)); + continue; + } + if (key == sym_voice_length) { + rb_hash_aset(hash, key, ruby_whisper_token_get_vlen(self)); + continue; + } + } + + return hash; +} + + +void +init_ruby_whisper_token(VALUE *mWhisper) +{ + cToken = rb_define_class_under(*mWhisper, "Token", rb_cObject); + + rb_define_alloc_func(cToken, ruby_whisper_token_allocate); + + sym_id = ID2SYM(rb_intern("id")); + sym_tid = ID2SYM(rb_intern("tid")); + sym_probability = ID2SYM(rb_intern("probability")); + sym_log_probability = ID2SYM(rb_intern("log_probability")); + sym_pt = ID2SYM(rb_intern("pt")); + sym_ptsum = ID2SYM(rb_intern("ptsum")); + sym_t_dtw = ID2SYM(rb_intern("t_dtw")); + sym_voice_length = ID2SYM(rb_intern("voice_length")); + sym_start_time = ID2SYM(rb_intern("start_time")); + sym_end_time = ID2SYM(rb_intern("end_time")); + sym_text = ID2SYM(rb_intern("text")); + + rb_define_method(cToken, "id", ruby_whisper_token_get_id, 0); + rb_define_method(cToken, "tid", ruby_whisper_token_get_tid, 0); + rb_define_method(cToken, "probability", ruby_whisper_token_get_p, 0); + rb_define_method(cToken, "log_probability", ruby_whisper_token_get_plog, 0); + rb_define_method(cToken, "pt", ruby_whisper_token_get_pt, 0); + rb_define_method(cToken, "ptsum", ruby_whisper_token_get_ptsum, 0); + rb_define_method(cToken, "t_dtw", ruby_whisper_token_get_t_dtw, 0); + rb_define_method(cToken, "voice_length", ruby_whisper_token_get_vlen, 0); + rb_define_method(cToken, "start_time", ruby_whisper_token_get_start_time, 0); + rb_define_method(cToken, "end_time", ruby_whisper_token_get_end_time, 0); + rb_define_method(cToken, "text", ruby_whisper_token_get_text, 0); + + rb_define_method(cToken, "deconstruct_keys", ruby_whisper_token_deconstruct_keys, 1); +} + +#undef N_KEY_NAMES diff --git a/bindings/ruby/ext/ruby_whisper_transcribe.cpp b/bindings/ruby/ext/ruby_whisper_transcribe.cpp new file mode 100644 index 0000000..699f9c6 --- /dev/null +++ b/bindings/ruby/ext/ruby_whisper_transcribe.cpp @@ -0,0 +1,104 @@ +#include "ruby_whisper.h" +#include "common-whisper.h" +#include <string> +#include <vector> + +#ifdef __cplusplus +extern "C" { +#endif + +extern const rb_data_type_t ruby_whisper_type; +extern const rb_data_type_t ruby_whisper_params_type; + +extern ID id_to_s; +extern ID id_call; +extern ID id_to_path; +extern ID transcribe_option_names[1]; + +extern VALUE full_body(VALUE rb_args); +extern VALUE full_parallel_body(VALUE rb_args); + +/* + * transcribe a single file + * can emit to a block results + * + * params = Whisper::Params.new + * params.duration = 60_000 + * whisper.transcribe "path/to/audio.wav", params do |text| + * puts text + * end + * + * call-seq: + * transcribe(path_to_audio, params) {|text| ...} + **/ +VALUE +ruby_whisper_transcribe(int argc, VALUE *argv, VALUE self) { + ruby_whisper *rw; + ruby_whisper_params *rwp; + VALUE wave_file_path, blk, params, kws; + VALUE opts[1]; + + rb_scan_args_kw(RB_SCAN_ARGS_LAST_HASH_KEYWORDS, argc, argv, "2:&", &wave_file_path, ¶ms, &kws, &blk); + rb_get_kwargs(kws, transcribe_option_names, 0, 1, opts); + + int n_processors = opts[0] == Qundef ? 1 : NUM2INT(opts[0]); + + GetContext(self, rw); + TypedData_Get_Struct(params, ruby_whisper_params, &ruby_whisper_params_type, rwp); + + if (!rb_respond_to(wave_file_path, id_to_s)) { + rb_raise(rb_eRuntimeError, "Expected file path to wave file"); + } + + if (rb_respond_to(wave_file_path, id_to_path)) { + wave_file_path = rb_funcall(wave_file_path, id_to_path, 0); + } + std::string fname_inp = StringValueCStr(wave_file_path); + + std::vector<float> pcmf32; // mono-channel F32 PCM + std::vector<std::vector<float>> pcmf32s; // stereo-channel F32 PCM + + if (!read_audio_data(fname_inp, pcmf32, pcmf32s, rwp->diarize)) { + fprintf(stderr, "error: failed to open '%s' as WAV file\n", fname_inp.c_str()); + return self; + } + + VALUE rb_result; + if (n_processors == 1) { + ruby_whisper_full_args args = { + &self, + ¶ms, + pcmf32.data(), + (int)pcmf32.size(), + }; + rb_result = full_body((VALUE)&args); + } else { + ruby_whisper_full_parallel_args parallel_args = { + &self, + ¶ms, + pcmf32.data(), + (int)pcmf32.size(), + n_processors, + }; + rb_result = full_parallel_body((VALUE)¶llel_args); + } + const int result = NUM2INT(rb_result); + if (result != 0) { + fprintf(stderr, "failed to process audio\n"); + return self; + } + if (NIL_P(blk)) { + return self; + } + const int n_segments = whisper_full_n_segments(rw->context); + VALUE output = rb_str_new2(""); + for (int i = 0; i < n_segments; ++i) { + const char * text = whisper_full_get_segment_text(rw->context, i); + output = rb_str_concat(output, rb_str_new2(text)); + } + rb_funcall(blk, id_call, 1, output); + return self; +} +#ifdef __cplusplus +} +#endif diff --git a/bindings/ruby/ext/ruby_whisper_vad_context.c b/bindings/ruby/ext/ruby_whisper_vad_context.c new file mode 100644 index 0000000..b98ed93 --- /dev/null +++ b/bindings/ruby/ext/ruby_whisper_vad_context.c @@ -0,0 +1,154 @@ +#include "ruby_whisper.h" + +extern ID id_to_s; + +extern VALUE cVADContext; + +extern const rb_data_type_t ruby_whisper_vad_params_type; +extern VALUE ruby_whisper_vad_detect(VALUE self, VALUE file_path, VALUE params); +extern VALUE ruby_whisper_normalize_model_path(VALUE model_path); +extern parsed_samples_t parse_samples(VALUE *samples, VALUE *n_samples); +extern VALUE release_samples(VALUE parsed); + +extern VALUE ruby_whisper_vad_segments_s_init(struct whisper_vad_segments *segments); + +static size_t +ruby_whisper_vad_context_memsize(const void *p) +{ + const ruby_whisper_vad_context *rwvc = p; + size_t size = sizeof(rwvc); + if (!rwvc) { + return 0; + } + if (rwvc->context) { + size += sizeof(rwvc->context); + } + return size; +} + +static void +ruby_whisper_vad_context_free(void *p) +{ + ruby_whisper_vad_context *rwvc = (ruby_whisper_vad_context *)p; + if (rwvc->context) { + whisper_vad_free(rwvc->context); + rwvc->context = NULL; + } + xfree(rwvc); +} + +const rb_data_type_t ruby_whisper_vad_context_type = { + "ruby_whisper_vad_context", + {0, ruby_whisper_vad_context_free, ruby_whisper_vad_context_memsize,}, + 0, 0, + 0 +}; + +static VALUE +ruby_whisper_vad_context_s_allocate(VALUE klass) +{ + ruby_whisper_vad_context *rwvc; + VALUE obj = TypedData_Make_Struct(klass, ruby_whisper_vad_context, &ruby_whisper_vad_context_type, rwvc); + rwvc->context = NULL; + return obj; +} + +static VALUE +ruby_whisper_vad_context_initialize(VALUE self, VALUE model_path) +{ + ruby_whisper_vad_context *rwvc; + struct whisper_vad_context *context; + + model_path = ruby_whisper_normalize_model_path(model_path); + context = whisper_vad_init_from_file_with_params(StringValueCStr(model_path), whisper_vad_default_context_params()); + if (context == NULL) { + rb_raise(rb_eRuntimeError, "Failed to initialize whisper VAD context"); + } + TypedData_Get_Struct(self, ruby_whisper_vad_context, &ruby_whisper_vad_context_type, rwvc); + rwvc->context = context; + + return Qnil; +} + +typedef struct { + struct whisper_vad_context *context; + struct whisper_vad_params *params; + float *samples; + int n_samples; + struct whisper_vad_segments *result; +} segments_from_samples_without_gvl_args; + +static void* +segments_from_samples_without_gvl(void *rb_args) +{ + segments_from_samples_without_gvl_args *args = (segments_from_samples_without_gvl_args *)rb_args; + args->result = whisper_vad_segments_from_samples(args->context, *args->params, args->samples, args->n_samples); + + return NULL; +} + +VALUE +segments_from_samples_body(VALUE rb_args) +{ + segments_from_samples_args *args = (segments_from_samples_args *)rb_args; + + ruby_whisper_vad_context *rwvc; + ruby_whisper_vad_params *rwvp; + GetVADContext(*args->context, rwvc); + GetVADParams(*args->params, rwvp); + + segments_from_samples_without_gvl_args segments_from_samples_without_gvl_args = { + rwvc->context, + &rwvp->params, + args->samples, + args->n_samples, + NULL + }; + rb_thread_call_without_gvl(segments_from_samples_without_gvl, (void *)&segments_from_samples_without_gvl_args, NULL, NULL); + if (!segments_from_samples_without_gvl_args.result) { + rb_raise(rb_eRuntimeError, "Failed to process audio"); + } + + return ruby_whisper_vad_segments_s_init(segments_from_samples_without_gvl_args.result); +} + +static VALUE +ruby_whisper_vad_segments_from_samples(int argc, VALUE *argv, VALUE self) +{ + if (argc < 2 || argc > 3) { + rb_raise(rb_eArgError, "wrong number of arguments (given %d, expected 2..3)", argc); + } + + VALUE n_samples = argc == 2 ? Qnil : argv[2]; + struct parsed_samples_t parsed = parse_samples(&argv[1], &n_samples); + segments_from_samples_args args = { + &self, + &argv[0], + parsed.samples, + parsed.n_samples, + }; + VALUE segments = rb_ensure(segments_from_samples_body, (VALUE)&args, release_samples, (VALUE)&parsed); + + return segments; +} + +static VALUE +ruby_whisper_vad_free(VALUE self) +{ + ruby_whisper_vad_context *rwvc; + GetVADContext(self, rwvc); + whisper_vad_free(rwvc->context); + rwvc->context = NULL; + + return Qnil; +} + +void init_ruby_whisper_vad_context(VALUE *mVAD) +{ + cVADContext = rb_define_class_under(*mVAD, "Context", rb_cObject); + rb_define_alloc_func(cVADContext, ruby_whisper_vad_context_s_allocate); + rb_define_method(cVADContext, "initialize", ruby_whisper_vad_context_initialize, 1); + rb_define_method(cVADContext, "segments_from_samples", ruby_whisper_vad_segments_from_samples, -1); + rb_define_method(cVADContext, "detect", ruby_whisper_vad_detect, 2); + rb_define_method(cVADContext, "free", ruby_whisper_vad_free, 0); +} diff --git a/bindings/ruby/ext/ruby_whisper_vad_context_detect.cpp b/bindings/ruby/ext/ruby_whisper_vad_context_detect.cpp new file mode 100644 index 0000000..862da81 --- /dev/null +++ b/bindings/ruby/ext/ruby_whisper_vad_context_detect.cpp @@ -0,0 +1,50 @@ +#include "ruby_whisper.h" +#include "common-whisper.h" +#include <string> +#include <vector> + +#ifdef __cplusplus +extern "C" { +#endif + +extern ID id_to_path; + +extern VALUE cVADSegments; + +extern const rb_data_type_t ruby_whisper_vad_context_type; +extern const rb_data_type_t ruby_whisper_vad_params_type; +extern const rb_data_type_t ruby_whisper_vad_segments_type; + +extern VALUE ruby_whisper_vad_segments_s_init(struct whisper_vad_segments *segments); +extern VALUE segments_from_samples_body(VALUE rb_args); + +VALUE +ruby_whisper_vad_detect(VALUE self, VALUE file_path, VALUE params) { + ruby_whisper_vad_context *rwvc; + std::string cpp_file_path; + std::vector<float> pcmf32; + std::vector<std::vector<float>> pcmf32s; + + GetVADContext(self, rwvc); + + if (rb_respond_to(file_path, id_to_path)) { + file_path = rb_funcall(file_path, id_to_path, 0); + } + cpp_file_path = StringValueCStr(file_path); + + if (!read_audio_data(cpp_file_path, pcmf32, pcmf32s, false)) { + rb_raise(rb_eRuntimeError, "Failed to open '%s' as WAV file\n", cpp_file_path.c_str()); + } + + segments_from_samples_args args = { + &self, + ¶ms, + pcmf32.data(), + (int)pcmf32.size(), + }; + return segments_from_samples_body((VALUE)&args); +} + +#ifdef __cplusplus +} +#endif diff --git a/bindings/ruby/ext/ruby_whisper_vad_params.c b/bindings/ruby/ext/ruby_whisper_vad_params.c new file mode 100644 index 0000000..edcc25d --- /dev/null +++ b/bindings/ruby/ext/ruby_whisper_vad_params.c @@ -0,0 +1,287 @@ +#include "ruby_whisper.h" + +#define DEFINE_PARAM(param_name, nth) \ + id_ ## param_name = rb_intern(#param_name); \ + param_names[nth] = id_ ## param_name; \ + rb_define_method(cVADParams, #param_name, ruby_whisper_vad_params_get_ ## param_name, 0); \ + rb_define_method(cVADParams, #param_name "=", ruby_whisper_vad_params_set_ ## param_name, 1); + +#define NUM_PARAMS 6 + +extern VALUE cVADParams; + +static size_t +ruby_whisper_vad_params_memsize(const void *p) +{ + const struct ruby_whisper_vad_params *params = p; + size_t size = sizeof(params); + if (!params) { + return 0; + } + return size; +} + +static ID param_names[NUM_PARAMS]; +static ID id_threshold; +static ID id_min_speech_duration_ms; +static ID id_min_silence_duration_ms; +static ID id_max_speech_duration_s; +static ID id_speech_pad_ms; +static ID id_samples_overlap; + +const rb_data_type_t ruby_whisper_vad_params_type = { + "ruby_whisper_vad_params", + {0, RUBY_DEFAULT_FREE, ruby_whisper_vad_params_memsize,}, + 0, 0, + 0 +}; + +static VALUE +ruby_whisper_vad_params_s_allocate(VALUE klass) +{ + ruby_whisper_vad_params *rwvp; + VALUE obj = TypedData_Make_Struct(klass, ruby_whisper_vad_params, &ruby_whisper_vad_params_type, rwvp); + rwvp->params = whisper_vad_default_params(); + return obj; +} + +/* + * Probability threshold to consider as speech. + * + * call-seq: + * threshold = th -> th + */ +static VALUE +ruby_whisper_vad_params_set_threshold(VALUE self, VALUE value) +{ + ruby_whisper_vad_params *rwvp; + TypedData_Get_Struct(self, ruby_whisper_vad_params, &ruby_whisper_vad_params_type, rwvp); + rwvp->params.threshold = NUM2DBL(value); + return value; +} + +static VALUE +ruby_whisper_vad_params_get_threshold(VALUE self) +{ + ruby_whisper_vad_params *rwvp; + TypedData_Get_Struct(self, ruby_whisper_vad_params, &ruby_whisper_vad_params_type, rwvp); + return DBL2NUM(rwvp->params.threshold); +} + +/* + * Min duration for a valid speech segment. + * + * call-seq: + * min_speech_duration_ms = duration_ms -> duration_ms + */ +static VALUE +ruby_whisper_vad_params_set_min_speech_duration_ms(VALUE self, VALUE value) +{ + ruby_whisper_vad_params *rwvp; + TypedData_Get_Struct(self, ruby_whisper_vad_params, &ruby_whisper_vad_params_type, rwvp); + rwvp->params.min_speech_duration_ms = NUM2INT(value); + return value; +} + +static VALUE +ruby_whisper_vad_params_get_min_speech_duration_ms(VALUE self) +{ + ruby_whisper_vad_params *rwvp; + TypedData_Get_Struct(self, ruby_whisper_vad_params, &ruby_whisper_vad_params_type, rwvp); + return INT2NUM(rwvp->params.min_speech_duration_ms); +} + +/* + * Min silence duration to consider speech as ended. + * + * call-seq: + * min_silence_duration_ms = duration_ms -> duration_ms + */ +static VALUE +ruby_whisper_vad_params_set_min_silence_duration_ms(VALUE self, VALUE value) +{ + ruby_whisper_vad_params *rwvp; + TypedData_Get_Struct(self, ruby_whisper_vad_params, &ruby_whisper_vad_params_type, rwvp); + rwvp->params.min_silence_duration_ms = NUM2INT(value); + return value; +} + +static VALUE +ruby_whisper_vad_params_get_min_silence_duration_ms(VALUE self) +{ + ruby_whisper_vad_params *rwvp; + TypedData_Get_Struct(self, ruby_whisper_vad_params, &ruby_whisper_vad_params_type, rwvp); + return INT2NUM(rwvp->params.min_silence_duration_ms); +} + +/* + * Max duration of a speech segment before forcing a new segment. + * + * call-seq: + * max_speech_duration_s = duration_s -> duration_s + */ +static VALUE +ruby_whisper_vad_params_set_max_speech_duration_s(VALUE self, VALUE value) +{ + ruby_whisper_vad_params *rwvp; + TypedData_Get_Struct(self, ruby_whisper_vad_params, &ruby_whisper_vad_params_type, rwvp); + rwvp->params.max_speech_duration_s = NUM2DBL(value); + return value; +} + +static VALUE +ruby_whisper_vad_params_get_max_speech_duration_s(VALUE self) +{ + ruby_whisper_vad_params *rwvp; + TypedData_Get_Struct(self, ruby_whisper_vad_params, &ruby_whisper_vad_params_type, rwvp); + return DBL2NUM(rwvp->params.max_speech_duration_s); +} + +/* + * Padding added before and after speech segments. + * + * call-seq: + * speech_pad_ms = pad_ms -> pad_ms + */ +static VALUE +ruby_whisper_vad_params_set_speech_pad_ms(VALUE self, VALUE value) +{ + ruby_whisper_vad_params *rwvp; + TypedData_Get_Struct(self, ruby_whisper_vad_params, &ruby_whisper_vad_params_type, rwvp); + rwvp->params.speech_pad_ms = NUM2INT(value); + return value; +} + +static VALUE +ruby_whisper_vad_params_get_speech_pad_ms(VALUE self) +{ + ruby_whisper_vad_params *rwvp; + TypedData_Get_Struct(self, ruby_whisper_vad_params, &ruby_whisper_vad_params_type, rwvp); + return INT2NUM(rwvp->params.speech_pad_ms); +} + +/* + * Overlap in seconds when copying audio samples from speech segment. + * + * call-seq: + * samples_overlap = overlap -> overlap + */ +static VALUE +ruby_whisper_vad_params_set_samples_overlap(VALUE self, VALUE value) +{ + ruby_whisper_vad_params *rwvp; + TypedData_Get_Struct(self, ruby_whisper_vad_params, &ruby_whisper_vad_params_type, rwvp); + rwvp->params.samples_overlap = NUM2DBL(value); + return value; +} + +static VALUE +ruby_whisper_vad_params_get_samples_overlap(VALUE self) +{ + ruby_whisper_vad_params *rwvp; + TypedData_Get_Struct(self, ruby_whisper_vad_params, &ruby_whisper_vad_params_type, rwvp); + return DBL2NUM(rwvp->params.samples_overlap); +} + +static VALUE +ruby_whisper_vad_params_equal(VALUE self, VALUE other) +{ + ruby_whisper_vad_params *rwvp1; + ruby_whisper_vad_params *rwvp2; + + if (self == other) { + return Qtrue; + } + + if (!rb_obj_is_kind_of(other, cVADParams)) { + return Qfalse; + } + + TypedData_Get_Struct(self, ruby_whisper_vad_params, &ruby_whisper_vad_params_type, rwvp1); + TypedData_Get_Struct(other, ruby_whisper_vad_params, &ruby_whisper_vad_params_type, rwvp2); + + if (rwvp1->params.threshold != rwvp2->params.threshold) { + return Qfalse; + } + if (rwvp1->params.min_speech_duration_ms != rwvp2->params.min_speech_duration_ms) { + return Qfalse; + } + if (rwvp1->params.min_silence_duration_ms != rwvp2->params.min_silence_duration_ms) { + return Qfalse; + } + if (rwvp1->params.max_speech_duration_s != rwvp2->params.max_speech_duration_s) { + return Qfalse; + } + if (rwvp1->params.speech_pad_ms != rwvp2->params.speech_pad_ms) { + return Qfalse; + } + if (rwvp1->params.samples_overlap != rwvp2->params.samples_overlap) { + return Qfalse; + } + + return Qtrue; +} + +#define SET_PARAM_IF_SAME(param_name) \ + if (id == id_ ## param_name) { \ + ruby_whisper_vad_params_set_ ## param_name(self, value); \ + continue; \ + } + +VALUE +ruby_whisper_vad_params_initialize(int argc, VALUE *argv, VALUE self) +{ + VALUE kw_hash; + VALUE values[NUM_PARAMS] = {Qundef}; + VALUE value; + ruby_whisper_vad_params *rwvp; + ID id; + int i; + + TypedData_Get_Struct(self, ruby_whisper_vad_params, &ruby_whisper_vad_params_type, rwvp); + + rb_scan_args_kw(RB_SCAN_ARGS_KEYWORDS, argc, argv, ":", &kw_hash); + if (NIL_P(kw_hash)) { + return self; + } + + rb_get_kwargs(kw_hash, param_names, 0, NUM_PARAMS, values); + + for (i = 0; i < NUM_PARAMS; i++) { + id = param_names[i]; + value = values[i]; + if (value == Qundef) { + continue; + } + SET_PARAM_IF_SAME(threshold) + SET_PARAM_IF_SAME(min_speech_duration_ms) + SET_PARAM_IF_SAME(min_silence_duration_ms) + SET_PARAM_IF_SAME(max_speech_duration_s) + SET_PARAM_IF_SAME(speech_pad_ms) + SET_PARAM_IF_SAME(samples_overlap) + } + + return self; +} + +#undef SET_PARAM_IF_SAME + +void +init_ruby_whisper_vad_params(VALUE *mVAD) +{ + cVADParams = rb_define_class_under(*mVAD, "Params", rb_cObject); + rb_define_alloc_func(cVADParams, ruby_whisper_vad_params_s_allocate); + rb_define_method(cVADParams, "initialize", ruby_whisper_vad_params_initialize, -1); + + DEFINE_PARAM(threshold, 0) + DEFINE_PARAM(min_speech_duration_ms, 1) + DEFINE_PARAM(min_silence_duration_ms, 2) + DEFINE_PARAM(max_speech_duration_s, 3) + DEFINE_PARAM(speech_pad_ms, 4) + DEFINE_PARAM(samples_overlap, 5) + + rb_define_method(cVADParams, "==", ruby_whisper_vad_params_equal, 1); +} + +#undef DEFINE_PARAM +#undef NUM_PARAMS diff --git a/bindings/ruby/ext/ruby_whisper_vad_segment.c b/bindings/ruby/ext/ruby_whisper_vad_segment.c new file mode 100644 index 0000000..0db6db6 --- /dev/null +++ b/bindings/ruby/ext/ruby_whisper_vad_segment.c @@ -0,0 +1,138 @@ +#include "ruby_whisper.h" + +#define N_KEY_NAMES 2 + +extern VALUE cVADSegment; + +extern const rb_data_type_t ruby_whisper_vad_segments_type; + +static VALUE sym_start_time; +static VALUE sym_end_time; + +static void +rb_whisper_vad_segment_mark(void *p) +{ + ruby_whisper_vad_segment *rwvs = (ruby_whisper_vad_segment *)p; + rb_gc_mark(rwvs->segments); +} + +static size_t +ruby_whisper_vad_segment_memsize(const void *p) +{ + const ruby_whisper_vad_segment *rwvs = p; + size_t size = sizeof(rwvs); + if (!rwvs) { + return 0; + } + if (rwvs->index) { + size += sizeof(rwvs->index); + } + return size; +} + +static const rb_data_type_t ruby_whisper_vad_segment_type = { + "ruby_whisper_vad_segment", + {rb_whisper_vad_segment_mark, RUBY_DEFAULT_FREE, ruby_whisper_vad_segment_memsize,}, + 0, 0, + 0 +}; + +static VALUE +ruby_whisper_vad_segment_s_allocate(VALUE klass) +{ + ruby_whisper_vad_segment *rwvs; + VALUE obj = TypedData_Make_Struct(klass, ruby_whisper_vad_segment, &ruby_whisper_vad_segment_type, rwvs); + rwvs->segments = Qnil; + rwvs->index = -1; + return obj; +} + +VALUE +rb_whisper_vad_segment_s_new(VALUE segments, int index) +{ + ruby_whisper_vad_segment *rwvs; + const VALUE segment = ruby_whisper_vad_segment_s_allocate(cVADSegment); + TypedData_Get_Struct(segment, ruby_whisper_vad_segment, &ruby_whisper_vad_segment_type, rwvs); + rwvs->segments = segments; + rwvs->index = index; + return segment; +} + +static VALUE +ruby_whisper_vad_segment_get_start_time(VALUE self) +{ + ruby_whisper_vad_segment *rwvs; + ruby_whisper_vad_segments *rwvss; + float t0; + + TypedData_Get_Struct(self, ruby_whisper_vad_segment, &ruby_whisper_vad_segment_type, rwvs); + TypedData_Get_Struct(rwvs->segments, ruby_whisper_vad_segments, &ruby_whisper_vad_segments_type, rwvss); + t0 = whisper_vad_segments_get_segment_t0(rwvss->segments, rwvs->index); + return LONG2NUM(t0 * 10); +} + +static VALUE +ruby_whisper_vad_segment_get_end_time(VALUE self) +{ + ruby_whisper_vad_segment *rwvs; + ruby_whisper_vad_segments *rwvss; + float t1; + + TypedData_Get_Struct(self, ruby_whisper_vad_segment, &ruby_whisper_vad_segment_type, rwvs); + TypedData_Get_Struct(rwvs->segments, ruby_whisper_vad_segments, &ruby_whisper_vad_segments_type, rwvss); + t1 = whisper_vad_segments_get_segment_t1(rwvss->segments, rwvs->index); + return LONG2NUM(t1 * 10); +} + +static VALUE +ruby_whisper_vad_segment_deconstruct_keys(VALUE self, VALUE keys) +{ + ruby_whisper_vad_segment *rwvs; + ruby_whisper_vad_segments *rwvss; + VALUE hash, key; + long n_keys; + int i; + + TypedData_Get_Struct(self, ruby_whisper_vad_segment, &ruby_whisper_vad_segment_type, rwvs); + TypedData_Get_Struct(rwvs->segments, ruby_whisper_vad_segments, &ruby_whisper_vad_segments_type, rwvss); + + hash = rb_hash_new(); + if (NIL_P(keys)) { + keys = rb_ary_new3( + N_KEY_NAMES, + sym_start_time, + sym_end_time + ); + n_keys = N_KEY_NAMES; + } else { + n_keys = RARRAY_LEN(keys); + if (n_keys > N_KEY_NAMES) { + return hash; + } + } + for (i = 0; i < n_keys; i++) { + key = rb_ary_entry(keys, i); + if (key == sym_start_time) { + rb_hash_aset(hash, key, ruby_whisper_vad_segment_get_start_time(self)); + } + if (key == sym_end_time) { + rb_hash_aset(hash, key, ruby_whisper_vad_segment_get_end_time(self)); + } + } + + return hash; +} + +void +init_ruby_whisper_vad_segment(VALUE *mVAD) +{ + cVADSegment = rb_define_class_under(*mVAD, "Segment", rb_cObject); + + sym_start_time = ID2SYM(rb_intern("start_time")); + sym_end_time = ID2SYM(rb_intern("end_time")); + + rb_define_alloc_func(cVADSegment, ruby_whisper_vad_segment_s_allocate); + rb_define_method(cVADSegment, "start_time", ruby_whisper_vad_segment_get_start_time, 0); + rb_define_method(cVADSegment, "end_time", ruby_whisper_vad_segment_get_end_time, 0); + rb_define_method(cVADSegment, "deconstruct_keys", ruby_whisper_vad_segment_deconstruct_keys, 1); +} diff --git a/bindings/ruby/ext/ruby_whisper_vad_segments.c b/bindings/ruby/ext/ruby_whisper_vad_segments.c new file mode 100644 index 0000000..db62fdb --- /dev/null +++ b/bindings/ruby/ext/ruby_whisper_vad_segments.c @@ -0,0 +1,105 @@ +#include "ruby_whisper.h" + +extern ID id___method__; +extern ID id_to_enum; + +extern VALUE cVADSegments; + +extern VALUE rb_whisper_vad_segment_s_new(VALUE segments, int index); + +static size_t +ruby_whisper_vad_segments_memsize(const void *p) +{ + const ruby_whisper_vad_segments *rwvss = p; + size_t size = sizeof(rwvss); + if (!rwvss) { + return 0; + } + if (rwvss->segments) { + size += sizeof(rwvss->segments); + } + return size; +} + +static void +ruby_whisper_vad_segments_free(void *p) +{ + ruby_whisper_vad_segments *rwvss = (ruby_whisper_vad_segments *)p; + if (rwvss->segments) { + whisper_vad_free_segments(rwvss->segments); + rwvss->segments = NULL; + } + xfree(rwvss); +} + +const rb_data_type_t ruby_whisper_vad_segments_type = { + "ruby_whisper_vad_segments", + {0, ruby_whisper_vad_segments_free, ruby_whisper_vad_segments_memsize,}, + 0, 0, + 0 +}; + +static VALUE +ruby_whisper_vad_segments_s_allocate(VALUE klass) +{ + ruby_whisper_vad_segments *rwvss; + VALUE obj = TypedData_Make_Struct(klass, ruby_whisper_vad_segments, &ruby_whisper_vad_segments_type, rwvss); + rwvss->segments = NULL; + return obj; +} + +VALUE +ruby_whisper_vad_segments_s_init(struct whisper_vad_segments *segments) +{ + VALUE rb_segments; + ruby_whisper_vad_segments *rwvss; + + rb_segments = ruby_whisper_vad_segments_s_allocate(cVADSegments); + TypedData_Get_Struct(rb_segments, ruby_whisper_vad_segments, &ruby_whisper_vad_segments_type, rwvss); + rwvss->segments = segments; + + return rb_segments; +} + +static VALUE +ruby_whisper_vad_segments_each(VALUE self) +{ + ruby_whisper_vad_segments *rwvss; + VALUE method_name; + int n_segments, i; + + if (!rb_block_given_p()) { + method_name = rb_funcall(self, id___method__, 0); + return rb_funcall(self, id_to_enum, 1, method_name); + } + + GetVADSegments(self, rwvss); + n_segments = whisper_vad_segments_n_segments(rwvss->segments); + for (i = 0; i < n_segments; ++i) { + rb_yield(rb_whisper_vad_segment_s_new(self, i)); + } + + return self; +} + +static VALUE +ruby_whisper_vad_segments_get_length(VALUE self) +{ + ruby_whisper_vad_segments *rwvss; + int n_segments; + + GetVADSegments(self, rwvss); + n_segments = whisper_vad_segments_n_segments(rwvss->segments); + + return INT2NUM(n_segments); +} + +void +init_ruby_whisper_vad_segments(VALUE *mVAD) +{ + cVADSegments = rb_define_class_under(*mVAD, "Segments", rb_cObject); + rb_define_alloc_func(cVADSegments, ruby_whisper_vad_segments_s_allocate); + rb_define_method(cVADSegments, "each", ruby_whisper_vad_segments_each, 0); + rb_define_method(cVADSegments, "length", ruby_whisper_vad_segments_get_length, 0); + rb_include_module(cVADSegments, rb_path2class("Enumerable")); +} diff --git a/bindings/ruby/ext/sources/CMakeGraphVizOptions.cmake b/bindings/ruby/ext/sources/CMakeGraphVizOptions.cmake new file mode 100644 index 0000000..746c14b --- /dev/null +++ b/bindings/ruby/ext/sources/CMakeGraphVizOptions.cmake @@ -0,0 +1,8 @@ +set(GRAPHVIZ_EXECUTABLES FALSE) +set(GRAPHVIZ_STATIC_LIBS TRUE) +set(GRAPHVIZ_SHARED_LIBS FALSE) +set(GRAPHVIZ_MODULE_LIBS FALSE) +set(GRAPHVIZ_INTERFACE_LIBS FALSE) +set(GRAPHVIZ_OBJECT_LIBS FALSE) +set(GRAPHVIZ_UNKNOWN_LIBS FALSE) +set(GRAPHVIZ_GENERATE_DEPENDERS FALSE) diff --git a/bindings/ruby/extsources.rb b/bindings/ruby/extsources.rb new file mode 100644 index 0000000..850ac98 --- /dev/null +++ b/bindings/ruby/extsources.rb @@ -0,0 +1,57 @@ +require "pathname" + +root = Pathname("..")/".." +ignored_dirs = %w[ + .devops + .github + ci + examples/addon.node + examples/bench.wasm + examples/command + examples/command.wasm + examples/lsp + examples/main + examples/python + examples/stream + examples/stream.wasm + examples/sycl + examples/talk-llama + examples/wchess + examples/whisper.android + examples/whisper.android.java + examples/whisper.nvim + examples/whisper.objc + examples/whisper.swiftui + examples/whisper.wasm + grammars + models + samples + scripts + tests +].collect {|dir| root/dir} +ignored_files = %w[ + AUTHORS + Makefile + .gitignore + .gitmodules + .dockerignore +] +ignored_exts = %w[ + .yml + .sh + .md + .py + .js + .nvim +] + +EXTSOURCES = + `git ls-files -z #{root}`.split("\x0") + .collect {|file| Pathname(file)} + .reject {|file| + ignored_exts.include?(file.extname) || + ignored_files.include?(file.basename.to_path) || + ignored_dirs.any? {|dir| file.descend.any? {|desc| desc == dir}} || + (file.descend.to_a[1] != root && file != Pathname("..")/"javascript"/"package-tmpl.json") + } + .collect(&:to_path) diff --git a/bindings/ruby/lib/whisper/log_settable.rb b/bindings/ruby/lib/whisper/log_settable.rb new file mode 100644 index 0000000..477aa1f --- /dev/null +++ b/bindings/ruby/lib/whisper/log_settable.rb @@ -0,0 +1,33 @@ +module Whisper + module LogSettable + private + + def start_log_callback_thread + return if @log_callback_thread&.alive? + + @log_callback_thread = Thread.new { + begin + while logs = drain_logs + begin + callback, user_data = synchronize {[@log_callback, @log_callback_user_data]} + next if callback.nil? + + logs.each do |(level, text)| + callback.call level, text, user_data + end + rescue => err + $stderr.puts err + end + end + rescue => err + $stderr.puts err + end + } + end + + def synchronize(&block) + @mutex ||= Thread::Mutex.new + @mutex.synchronize &block + end + end +end diff --git a/bindings/ruby/lib/whisper/model/uri.rb b/bindings/ruby/lib/whisper/model/uri.rb new file mode 100644 index 0000000..58db376 --- /dev/null +++ b/bindings/ruby/lib/whisper/model/uri.rb @@ -0,0 +1,237 @@ +require "uri" +require "net/http" +require "time" +require "pathname" +require "io/console/size" + +module Whisper + class Model + class URI + def initialize(uri) + @uri = URI(uri) + end + + def to_path + cache + cache_path.to_path + end + + def clear_cache + path = cache_path + path.delete if path.exist? + end + + private + + def cache_path + base_cache_dir/@uri.host/@uri.path[1..] + end + + def base_cache_dir + base = case RUBY_PLATFORM + when /mswin|mingw/ + ENV.key?("LOCALAPPDATA") ? Pathname(ENV["LOCALAPPDATA"]) : Pathname(Dir.home)/"AppData/Local" + when /darwin/ + Pathname(Dir.home)/"Library/Caches" + else + ENV.key?("XDG_CACHE_HOME") ? Pathname(ENV["XDG_CACHE_HOME"]) : Pathname(Dir.home)/".cache" + end + base/"whisper.cpp" + end + + def cache + path = cache_path + return path if cache_path.exist? + + headers = {} + request @uri, headers + path + end + + def request(uri, headers) + Net::HTTP.start uri.host, uri.port, use_ssl: uri.scheme == "https" do |http| + request = Net::HTTP::Get.new(uri, headers) + http.request request do |response| + case response + when Net::HTTPOK + download response + when Net::HTTPRedirection + request URI(response["location"]), headers + else + raise "#{response.code} #{response.message}\n#{response.body}" + end + end + end + rescue => err + if cache_path.exist? + warn err + # Use cache file + else + raise + end + end + + def download(response) + path = cache_path + path.dirname.mkpath unless path.dirname.exist? + downloading_path = Pathname("#{path}.downloading") + size = response.content_length + downloading_path.open "wb" do |file| + downloaded = 0 + response.read_body do |chunk| + file << chunk + downloaded += chunk.bytesize + show_progress downloaded, size + end + $stderr.puts + end + downloading_path.rename path + end + + def show_progress(current, size) + line_size = 47 + progress_rate_available = size && $stderr.tty? && $stderr.winsize[1] >= line_size + + unless @prev + @prev = Time.now + $stderr.puts "Downloading #{@uri} to #{cache_path}" + end + + now = Time.now + + if progress_rate_available + return if now - @prev < 1 && current < size + + progress_width = 20 + progress = current.to_f / size + arrow_length = progress * progress_width + arrow = "=" * (arrow_length - 1) + ">" + " " * (progress_width - arrow_length) + line = "[#{arrow}] (#{format_bytesize(current)} / #{format_bytesize(size)})" + padding = ' ' * ($stderr.winsize[1] - line.size) + $stderr.print "\r#{line}#{padding}" + else + return if now - @prev < 1 + + $stderr.print "." + end + @prev = now + end + + def format_bytesize(bytesize) + return "0.0 B" if bytesize.zero? + + units = %w[B KiB MiB GiB TiB] + exp = (Math.log(bytesize) / Math.log(1024)).to_i + format("%.1f %s", bytesize.to_f / 1024 ** exp, units[exp]) + end + end + + class ZipURI < URI + def cache + zip_path = super + dest = unzipped_path + return if dest.exist? && dest.mtime >= zip_path.mtime + escaping dest do + system "unzip", "-q", "-d", zip_path.dirname.to_path, zip_path.to_path, exception: true + end + zip_path + end + + def clear_cache + super + unzipped_path.rmtree if unzipped_path.exist? + end + + private + + def unzipped_path + cache_path.sub_ext("") + end + + def escaping(path) + escaped = Pathname("#{path}.removing") + if path.exist? + escaped.rmtree if escaped.exist? + path.rename escaped + end + yield + ensure + if path.exist? + escaped.rmtree if escaped.exist? + else + escaped.rename path if escaped.exist? + end + end + end + + @pre_converted_models = %w[ + tiny + tiny.en + tiny-q5_1 + tiny.en-q5_1 + tiny-q8_0 + base + base.en + base-q5_1 + base.en-q5_1 + base-q8_0 + small + small.en + small-q5_1 + small.en-q5_1 + small-q8_0 + medium + medium.en + medium-q5_0 + medium.en-q5_0 + medium-q8_0 + large-v1 + large-v2 + large-v2-q5_0 + large-v2-q8_0 + large-v3 + large-v3-q5_0 + large-v3-turbo + large-v3-turbo-q5_0 + large-v3-turbo-q8_0 + ].each_with_object({}) {|name, models| + models[name] = URI.new("https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-#{name}.bin") + } + + %w[ + small.en-tdrz + ].each do |name| + @pre_converted_models[name] = URI.new("https://huggingface.co/akashmjn/tinydiarize-whisper.cpp/resolve/main/ggml-#{name}.bin") + end + + %w[ + silero-v5.1.2 + silero-v6.2.0 + ].each do |name| + @pre_converted_models[name] = URI.new("https://huggingface.co/ggml-org/whisper-vad/resolve/main/ggml-#{name}.bin") + end + + %w[ + parakeet-tdt-0.6b-v3-f16 + parakeet-tdt-0.6b-v3-f32 + parakeet-tdt-0.6b-v3-q4_0 + parakeet-tdt-0.6b-v3-q4_k + parakeet-tdt-0.6b-v3-q8_0 + ].each do |name| + @pre_converted_models[name] = URI.new("https://huggingface.co/ggml-org/parakeet-GGUF/resolve/main/ggml-#{name}.bin") + end + + @coreml_compiled_models = @pre_converted_models.each_with_object({}) {|(name, uri), models| + next if name.end_with?("-tdrz") || name.start_with?("silero-") || name.start_with?("parakeet-") + + if matched = name.match(/\A(?<name>.*)-q\d_\d\z/) + name = matched[:name] + end + models[uri] = ZipURI.new("https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-#{name}-encoder.mlmodelc.zip") + } + + class << self + attr_reader :pre_converted_models, :coreml_compiled_models + end + end +end diff --git a/bindings/ruby/lib/whisper/output.rb b/bindings/ruby/lib/whisper/output.rb new file mode 100644 index 0000000..1781af1 --- /dev/null +++ b/bindings/ruby/lib/whisper/output.rb @@ -0,0 +1,74 @@ +module Whisper + module Output + module Context + def to_srt + each_segment.with_index.reduce("") {|srt, (segment, index)| + srt << "#{index + 1}\n#{segment.to_srt_cue}\n" + } + end + + def to_webvtt + each_segment.with_index.reduce("WEBVTT\n\n") {|webvtt, (segment, index)| + webvtt << "#{index + 1}\n#{segment.to_webvtt_cue}\n" + } + end + end + + module Segment + SRT_ESCAPES = { + "&" => "&", + "<" => "<", + ">" => ">", + } + SRT_ESCAPES_RE = Regexp.union(SRT_ESCAPES.keys) + private_constant :SRT_ESCAPES, :SRT_ESCAPES_RE + + def to_srt_cue + "#{srt_start_time} --> #{srt_end_time}\n#{srt_text}\n" + end + + def to_webvtt_cue + "#{webvtt_start_time} --> #{webvtt_end_time}\n#{webvtt_text}\n" + end + + private + + def time_to_a(time) + sec, decimal_part = time.divmod(1000) + min, sec = sec.divmod(60) + hour, min = min.divmod(60) + [hour, min, sec, decimal_part] + end + + def srt_time(time) + "%02d:%02d:%02d,%03d" % time_to_a(time) + end + + def srt_start_time + srt_time(start_time) + end + + def srt_end_time + srt_time(end_time) + end + + def srt_text + text.gsub(SRT_ESCAPES_RE, SRT_ESCAPES) + end + + def webvtt_time(time) + "%02d:%02d:%02d.%03d" % time_to_a(time) + end + + def webvtt_start_time + webvtt_time(start_time) + end + + def webvtt_end_time + webvtt_time(end_time) + end + + alias webvtt_text srt_text + end + end +end diff --git a/bindings/ruby/sig/whisper.rbs b/bindings/ruby/sig/whisper.rbs new file mode 100644 index 0000000..6000641 --- /dev/null +++ b/bindings/ruby/sig/whisper.rbs @@ -0,0 +1,1036 @@ +module Whisper + interface _Samples + def length: () -> Integer + def each: { (Float) -> void } -> void + end + + type log_callback = ^(Integer level, String message, Object user_data) -> void + type new_segment_callback = ^(Whisper::Context, untyped, Integer n_new, Object user_data) -> void + type progress_callback = ^(Whisper::Context, untyped, Integer progress, Object user_data) -> void + type encoder_begin_callback = ^(Whisper::Context, untyped, Object user_data) -> void + type abort_callback = ^(Whisper::Context, untyped, Object user_data) -> boolish + + VERSION: String + LOG_LEVEL_NONE: Integer + LOG_LEVEL_INFO: Integer + LOG_LEVEL_WARN: Integer + LOG_LEVEL_ERROR: Integer + LOG_LEVEL_DEBUG: Integer + LOG_LEVEL_CONT: Integer + AHEADS_NONE: Integer + AHEADS_N_TOP_MOST: Integer + AHEADS_CUSTOM: Integer + AHEADS_TINY_EN: Integer + AHEADS_TINY: Integer + AHEADS_BASE_EN: Integer + AHEADS_BASE: Integer + AHEADS_SMALL_EN: Integer + AHEADS_SMALL: Integer + AHEADS_MEDIUM_EN: Integer + AHEADS_MEDIUM: Integer + AHEADS_LARGE_V1: Integer + AHEADS_LARGE_V2: Integer + AHEADS_LARGE_V3: Integer + AHEADS_LARGE_V3_TURBO: Integer + + def self.lang_max_id: () -> Integer + def self.lang_id: (string name) -> Integer + def self.lang_str: (Integer id) -> String + def self.lang_str_full: (Integer id) -> String + def self.log_set: (log_callback?, Object? user_data) -> log_callback + def self.system_info_str: () -> String + + module Output + module Context + def to_srt: () -> String + def to_webvtt: () -> String + end + + module Segment + def to_srt_cue: () -> String + def to_webvtt_cue: () -> String + end + end + + class Context + include Output::Context + + def self.new: (String | path | ::URI::HTTP) -> instance + + # transcribe a single file + # can emit to a block results + # + # params = Whisper::Params.new + # params.duration = 60_000 + # whisper.transcribe "path/to/audio.wav", params do |text| + # puts text + # end + # + # If `n_processors` is greater than 1, you cannot set any callbacks including + # new_segment_callback, progress_callback, encoder_begin_callback, abort_callback, + # and log_callback set by Whisper.log_set + def transcribe: (path, Whisper::Params, ?n_processors: Integer) -> self + | (path, Whisper::Params, ?n_processors: Integer) { (String) -> void } -> self + + def model_n_vocab: () -> Integer + def model_n_audio_ctx: () -> Integer + def model_n_audio_state: () -> Integer + def model_n_text_head: () -> Integer + def model_n_text_layer: () -> Integer + def model_n_mels: () -> Integer + def model_ftype: () -> Integer + def model_type: () -> String + + # Yields each Whisper::Segment: + # + # whisper.transcribe("path/to/audio.wav", params) + # whisper.each_segment do |segment| + # puts segment.text + # end + # + # Returns an `Enumerator` if no block given: + # + # whisper.transcribe("path/to/audio.wav", params) + # enum = whisper.each_segment + # enum.to_a # => [#<Whisper::Segment>, ...] + # + def each_segment: { (Segment) -> void } -> void + | () -> Enumerator[Segment] + + def model: () -> Model + def full_get_segment: (Integer nth) -> Segment + def full_n_segments: () -> Integer + + # Language ID, which can be converted to string by Whisper.lang_str and Whisper.lang_str_full. + # + def full_lang_id: () -> Integer + + # Start time of a segment indexed by `segment_index` in centiseconds (10 times milliseconds). + # + # full_get_segment_t0(3) # => 1668 (16680 ms) + # + def full_get_segment_t0: (Integer) -> Integer + + # End time of a segment indexed by `segment_index` in centiseconds (10 times milliseconds). + # + # full_get_segment_t1(3) # => 1668 (16680 ms) + # + def full_get_segment_t1: (Integer) -> Integer + + # Whether the next segment indexed by `segment_index` is predicated as a speaker turn. + # + # full_get_segment_speacker_turn_next(3) # => true + # + def full_get_segment_speaker_turn_next: (Integer) -> (true | false) + + # Text of a segment indexed by `segment_index`. + # + # full_get_segment_text(3) # => "ask not what your country can do for you, ..." + # + def full_get_segment_text: (Integer) -> String + + def full_get_segment_no_speech_prob: (Integer) -> Float + + def full_n_vad_segments: () -> Integer + + def full_get_vad_segment_t0: (Integer) -> Integer + + def full_get_vad_segment_t1: (Integer) -> Integer + + # Run the entire model: PCM -> log mel spectrogram -> encoder -> decoder -> text + # Not thread safe for same context + # Uses the specified decoding strategy to obtain the text. + # + # The second argument `samples` must be an array of samples, respond to `:length`, or be a MemoryView of an array of float. It must be 32 bit float PCM audio data. + # + def full: (Whisper::Params, Array[Float] samples, ?Integer n_samples) -> self + | (Whisper::Params, _Samples, ?Integer n_samples) -> self + + # Split the input audio in chunks and process each chunk separately using `whisper_full_with_state()` + # Result is stored in the default state of the context + # Not thread safe if executed in parallel on the same context. + # It seems this approach can offer some speedup in some cases. + # However, the transcription accuracy can be worse at the beginning and end of each chunk. + # + # If `n_processors` is greater than 1, you cannot set any callbacks including + # new_segment_callback, progress_callback, encoder_begin_callback, abort_callback, + # and log_callback set by Whisper.log_set + def full_parallel: (Whisper::Params, Array[Float], ?Integer n_samples) -> self + | (Whisper::Params, _Samples, ?Integer n_samples) -> self + | (Whisper::Params, _Samples, ?Integer? n_samples, Integer n_processors) -> self + + # Free context and unload the model. + def free: () -> void + + class Params + def self.new: ( + ?use_gpu: boolish, + ?flash_attn: boolish, + ?gpu_device: Integer, + ?dtw_token_timestamps: boolish, + ?dtw_aheads_preset: Integer, + ?dtw_n_top: Integer | nil, + ) -> instance + + def use_gpu=: (boolish) -> boolish + def use_gpu: () -> (true | false) + def flash_attn=: (boolish) -> boolish + def flash_attn: () -> (true | false) + def gpu_device=: (Integer) -> Integer + def gpu_device: () -> Integer + def dtw_token_timestamps=: (boolish) -> boolish + def dtw_token_timestamps: () -> (true | false) + def dtw_aheads_preset=: (Integer) -> Integer + def dtw_aheads_preset: () -> Integer + def dtw_n_top=: (Integer | nil) -> (Integer | nil) + def dtw_n_top: () -> (Integer | nil) + end + end + + class Params + def self.new: ( + ?language: string, + ?translate: boolish, + ?no_context: boolish, + ?single_segment: boolish, + ?print_special: boolish, + ?print_progress: boolish, + ?print_realtime: boolish, + ?print_timestamps: boolish, + ?suppress_blank: boolish, + ?suppress_nst: boolish, + ?token_timestamps: boolish, + ?max_len: Integer, + ?split_on_word: boolish, + ?initial_prompt: string | nil, + ?carry_initial_prompt: boolish, + ?diarize: boolish, + ?offset: Integer, + ?duration: Integer, + ?max_text_tokens: Integer, + ?temperature: Float, + ?max_initial_ts: Float, + ?length_penalty: Float, + ?temperature_inc: Float, + ?entropy_thold: Float, + ?logprob_thold: Float, + ?no_speech_thold: Float, + ?new_segment_callback: new_segment_callback, + ?new_segment_callback_user_data: Object, + ?progress_callback: progress_callback, + ?progress_callback_user_data: Object, + ?encoder_begin_callback: encoder_begin_callback, + ?encoder_begin_callback_user_data: Object, + ?abort_callback: abort_callback, + ?abort_callback_user_data: Object, + ?vad: boolish, + ?vad_model_path: path | URI, + ?vad_params: Whisper::VAD::Params + ) -> instance + + # params.language = "auto" | "en", etc... + # + def language=: (String) -> String # TODO: Enumerate lang names + + def language: () -> String + def translate=: (boolish) -> boolish + def translate: () -> (true | false) + def no_context=: (boolish) -> boolish + + # If `true`, does not use past transcription (if any) as initial prompt for the decoder. + # + def no_context: () -> (true | false) + + def single_segment=: (boolish) -> boolish + + # If `true`, forces single segment output (useful for streaming). + # + def single_segment: () -> (true | false) + + def print_special=: (boolish) -> boolish + + # If `true`, prints special tokens (e.g. <SOT>, <EOT>, <BEG>, etc.). + # + def print_special: () -> (true | false) + + def print_progress=: (boolish) -> boolish + + # If `true`, prints progress information. + # + def print_progress: () -> (true | false) + + def print_realtime=: (boolish) -> boolish + + # If `true`, prints results from within whisper.cpp. (avoid it, use callback instead) + # + def print_realtime: () -> (true | false) + + # If `true`, prints timestamps for each text segment when printing realtime. + # + def print_timestamps=: (boolish) -> boolish + + def print_timestamps: () -> (true | false) + + def suppress_blank=: (boolish) -> boolish + + # If `true`, suppresses blank outputs. + # + def suppress_blank: () -> (true | false) + + def suppress_nst=: (boolish) -> boolish + + # If `true`, suppresses non-speech-tokens. + # + def suppress_nst: () -> (true | false) + + def token_timestamps=: (boolish) -> boolish + + # If `true`, enables token-level timestamps. + # + def token_timestamps: () -> (true | false) + + def max_len=: (Integer) -> Integer + + # max segment length in characters. + # + def max_len: () -> Integer + + def split_on_word=: (boolish) -> boolish + + # If `true`, split on word rather than on token (when used with max_len). + # + def split_on_word: () -> (true | false) + + def initial_prompt=: (_ToS) -> _ToS + def carry_initial_prompt=: (boolish) -> boolish + + # Tokens to provide to the whisper decoder as initial prompt + # these are prepended to any existing text context from a previous call + # use whisper_tokenize() to convert text to tokens. + # Maximum of whisper_n_text_ctx()/2 tokens are used (typically 224). + # + def initial_prompt: () -> (String | nil) + def carry_initial_prompt: () -> (true | false) + + def diarize=: (boolish) -> boolish + + # If `true`, enables diarization. + # + def diarize: () -> (true | false) + + def offset=: (Integer) -> Integer + + # Start offset in ms. + # + def offset: () -> Integer + + def duration=: (Integer) -> Integer + + # Audio duration to process in ms. + # + def duration: () -> Integer + + def max_text_tokens=: (Integer) -> Integer + + # Max tokens to use from past text as prompt for the decoder. + # + def max_text_tokens: () -> Integer + + def temperature=: (Float) -> Float + def temperature: () -> Float + def max_initial_ts=: (Float) -> Float + + # See https://github.com/openai/whisper/blob/f82bc59f5ea234d4b97fb2860842ed38519f7e65/whisper/decoding.py#L97 + # + def max_initial_ts: () -> Float + + def length_penalty=: (Float) -> Float + def length_penalty: () -> Float + def temperature_inc=: (Float) -> Float + def temperature_inc: () -> Float + def entropy_thold=: (Float) -> Float + + # Similar to OpenAI's "compression_ratio_threshold" + # + def entropy_thold: () -> Float + + def logprob_thold=: (Float) -> Float + def logprob_thold: () -> Float + def no_speech_thold=: (Float) -> Float + def no_speech_thold: () -> Float + + # Sets new segment callback, called for every newly generated text segment. + # + # params.new_segment_callback = ->(context, _, n_new, user_data) { + # # ... + # } + # + def new_segment_callback=: (new_segment_callback) -> new_segment_callback + def new_segment_callback: () -> (new_segment_callback | nil) + + # Sets user data passed to the last argument of new segment callback. + # + def new_segment_callback_user_data=: (Object) -> Object + + def new_segment_callback_user_data: () -> Object + + # Sets progress callback, called on each progress update. + # + # params.new_segment_callback = ->(context, _, progress, user_data) { + # # ... + # } + # + # +progress+ is an Integer between 0 and 100. + # + def progress_callback=: (progress_callback) -> progress_callback + + def progress_callback: () -> (progress_callback | nil) + + # Sets user data passed to the last argument of progress callback. + # + def progress_callback_user_data=: (Object) -> Object + + def progress_callback_user_data: () -> Object + + # Sets encoder begin callback, called when the encoder starts. + # + def encoder_begin_callback=: (encoder_begin_callback) -> encoder_begin_callback + + def encoder_begin_callback: () -> (encoder_begin_callback | nil) + + # Sets user data passed to the last argument of encoder begin callback. + # + def encoder_begin_callback_user_data=: (Object) -> Object + + def encoder_begin_callback_user_data: () -> Object + + # Sets abort callback, called to check if the process should be aborted. + # + # params.abort_callback = ->(user_data) { + # # ... + # } + # + # + def abort_callback=: (abort_callback) -> abort_callback + + def abort_callback: () -> (abort_callback | nil) + + # Sets user data passed to the last argument of abort callback. + # + def abort_callback_user_data=: (Object) -> Object + + def abort_callback_user_data: () -> Object + + # Enable VAD + # + def vad=: (boolish) -> boolish + + def vad: () -> (true | false) + + # Path to the VAD model + def vad_model_path=: (path | URI | nil) -> (path | URI | nil) + + def vad_model_path: () -> (String | nil) + + def vad_params=: (Whisper::VAD::Params) -> Whisper::VAD::Params + def vad_params: () -> (Whisper::VAD::Params) + + # Hook called on new segment. Yields each Whisper::Segment. + # + # whisper.on_new_segment do |segment| + # # ... + # end + # + def on_new_segment: { (Segment) -> void } -> void + + # Hook called on progress update. Yields each progress `Integer` between 0 and 100. + # + def on_progress: { (Integer progress) -> void } -> void + + # Hook called on encoder starts. + # + def on_encoder_begin: { () -> void } -> void + + # Call block to determine whether abort or not. Return `true` when you want to abort. + # + # params.abort_on do + # if some_condition + # true # abort + # else + # false # continue + # end + # end + # + def abort_on: { (Object user_data) -> boolish } -> void + end + + module LogSettable + end + + class Model + def self.pre_converted_models: () -> Hash[String, Model::URI] + def self.coreml_compiled_models: () -> Hash[Model::URI, Model::ZipURI] + def self.new: () -> instance + def n_vocab: () -> Integer + def n_audio_ctx: () -> Integer + def n_audio_state: () -> Integer + def n_audio_head: () -> Integer + def n_audio_layer: () -> Integer + def n_text_ctx: () -> Integer + def n_text_state: () -> Integer + def n_text_head: () -> Integer + def n_text_layer: () -> Integer + def n_mels: () -> Integer + def ftype: () -> Integer + def type: () -> String + + class URI + def self.new: (string | ::URI::HTTP) -> instance + def to_path: -> String + def clear_cache: -> void + end + + class ZipURI < URI + def cache: () -> Pathname + def clear_cache: () -> void + end + end + + class Segment + include Output::Segment + + type deconstructed_keys = { + start_time: (Integer | nil), + end_time: (Integer | nil), + text: (String | nil), + no_speech_prob: (Float | nil), + speaker_turn_next: (true | false | nil), + n_tokens: (Integer | nil) + } + + # Start time in milliseconds. + # + def start_time: () -> Integer + + # End time in milliseconds. + # + def end_time: () -> Integer + + # Whether the next segment is predicted as a speaker turn. + # + def speaker_turn_next?: () -> (true | false) + + def text: () -> String + def no_speech_prob: () -> Float + + # Get number of tokens in the segment + # + def n_tokens: () -> Integer + + # Yields each Whisper::Token: + # + # whisper.each_segment.first.each_token do |token| + # p token + # end + # + # Returns an `Enumerator` if no block is given: + # + # whisper.each_segment.first.each_token.to_a # => [#<Whisper::Token>, ...] + # + def each_token: { (Token) -> void } -> void + | () -> Enumerator[Token] + + # Possible keys: `:start_time`, `:end_time`, `:text`, `:no_speech_prob`, `:speaker_turn_next` + # + # whisper.each_segment do |segment| + # segment => {start_time:, end_time:, text:, no_speech_prob:, speaker_turn_next:} + # + # puts "[#{start_time} --> #{end_time}] #{text} (no speech prob: #{no_speech_prob}#{speaker_turn_next ? ', speaker turns next' : ''})" + # end + def deconstruct_keys: (Array[:start_time | :end_time | :text | :no_speech_prob | :speaker_turn_next | :n_tokens] | nil) -> deconstructed_keys + end + + class Token + type deconstructed_keys = { + id: (Integer | nil), + tid: (Integer | nil), + probability: (Float | nil), + log_probability: (Float | nil), + pt: (Float | nil), + ptsum: (Float | nil), + t_dtw: (Integer | nil), + voice_length: (Float | nil), + text: (String | nil), + start_time: (Integer | nil), + end_time: (Integer | nil), + } + + # Token ID. + # + def id: () -> Integer + + # Forced timestamp token ID. + # + def tid: () -> Integer + + # Probability of the token. + # + def probability: () -> Float + + # Log probability of the token. + # + def log_probability: () -> Float + + # Probability of the timestamp token. + # + def pt: () -> Float + + # Sum of probability of all timestamp tokens. + # + def ptsum: () -> Float + + # [EXPERIMENTAL] Token-level timestamps with DTW + # + # Do not use if you haven't computed token-level timestamps with dtw. + # Roughly corresponds to the moment in audio in which the token was output. + # + def t_dtw: () -> Integer + + # Voice length of the token. + # + def voice_length: () -> Float + + # Start time of the token. + # + # Token-level timestamp data. + # Do not use if you haven't computed token-level timestamps. + # + def start_time: () -> Integer + + # End time of the token. + # + # Token-level timestamp data. + # Do not use if you haven't computed token-level timestamps. + # + def end_time: () -> Integer + + # Get the token text of the token. + # + def text: () -> String + def deconstruct_keys: (Array[:id | :tid | :probability | :log_probability | :pt | :ptsum | :t_dtw | :voice_length | :start_time | :end_time | :text] | nil) -> deconstructed_keys + end + + module Parakeet + extend LogSettable + + VERSION: String + + # Control logging output. The default behavior is to print to stderr. + # + def self.log_set: (nil, Object? user_data) -> nil + | (^(Integer level, String message, Object user_data) -> void, Object? user_data) -> nil + def self.system_info_str: () -> String + + class Context + include Output::Context + + # Load a Parakeet model from the given file path. + # + def self.new: (String | path | ::URI::HTTP, ?Params) -> instance + + # Transcribe a single audio file. + # + def transcribe: (path audio_file_path, Whisper::Parakeet::Params) -> self + + # Run the entire model: PCM -> log mel spectrogram -> encoder -> decoder -> text. + # Not thread safe for the same context. + # + # The second argument `samples` must be an array of samples, respond to `:length`, + # or be a MemoryView of an array of float. It must be 32 bit float PCM audio data. + # + def full: (Whisper::Parakeet::Params, Array[Float] samples, ?Integer n_samples) -> self + | (Whisper::Parakeet::Params, _Samples, ?Integer n_samples) -> self + + # Number of generated text segments. + # + def full_n_segments: () -> Integer + + # Start time of a segment indexed by `segment_index` in centiseconds (10 times milliseconds). + # + # full_get_segment_t0(3) # => 1668 (16680 ms) + # + def full_get_segment_t0: (Integer segment_index) -> Integer + + # End time of a segment indexed by `segment_index` in centiseconds (10 times milliseconds). + # + # full_get_segment_t1(3) # => 1668 (16680 ms) + # + def full_get_segment_t1: (Integer segment_index) -> Integer + + # Text of a segment indexed by `segment_index`. + # + # full_get_segment_text(3) # => "ask not what your country can do for you, ..." + # + def full_get_segment_text: (Integer segment_index) -> String + + # Number of tokens in the segment indexed by `segment_index`. + # + def full_n_tokens: (Integer segment_index) -> Integer + + # Text of the token indexed by `token_index` in the segment indexed by `segment_index`. + # + def full_get_token_text: (Integer segment_index, Integer token_index) -> String + + # Token id of the token indexed by `token_index` in the segment indexed by `segment_index`. + # + def full_get_token_id: (Integer segment_index, Integer token_index) -> Integer + + # Probability of the token indexed by `token_index` in the segment indexed by `segment_index`. + # + def full_get_token_p: (Integer segment_index, Integer token_index) -> Float + + # Token data of the token indexed by `token_index` in the segment indexed by `segment_index`. + # + def full_get_token_data: (Integer segment_index, Integer token_index) -> Token + + def model: () -> Model + + # Yields each Whisper::Parakeet::Segment: + # + # parakeet.transcribe("path/to/audio.wav", params) + # parakeet.each_segment do |segment| + # puts segment.text + # end + # + # Returns an `Enumerator` if no block given: + # + # parakeet.transcribe("path/to/audio.wav", params) + # enum = parakeet.each_segment + # enum.to_a # => [#<Whisper::Parakeet::Segment>, ...] + # + def each_segment: { (Segment) -> void } -> void + | () -> Enumerator[Segment] + + def free: () -> void + + class Params + def self.new: (?use_gpu: boolish, ?gpu_device: Integer) -> instance + def use_gpu: () -> boolish + def use_gpu=: (boolish) -> boolish + def gpu_device: () -> Integer + def gpu_device=: (Integer) -> Integer + end + end + + class Params + def self.new: ( + ?n_threads: Integer, + ?offset_ms: Integer, + ?duration_ms: Integer, + ?no_context: boolish, + ?audio_ctx: Integer, + ?new_segment_callback: ^(Whisper::Parakeet::Context, untyped, Integer n_new, Object user_data) -> void, + ?new_segment_callback_user_data: Object, + ?new_token_callback: ^(Whisper::Parakeet::Context, untyped, Whisper::Parakeet::Token, Object user_data) -> void, + ?new_token_callback_user_data: Object, + ?progress_callback: ^(Whisper::Parakeet::Context, untyped, Integer progress, Object user_data) -> void, + ?progress_callback_user_data: Object, + ?encoder_begin_callback: ^(Whisper::Parakeet::Context, untyped, Object user_data) -> boolish, + ?encoder_begin_callback_user_data: Object, + ?abort_callback: ^(Object user_data) -> boolish, + ?abort_callback_user_data: Object + ) -> instance + + # Number of threads to use. + # + def n_threads=: (Integer) -> Integer + def n_threads: () -> Integer + + # Start offset in ms. + # + def offset_ms=: (Integer) -> Integer + def offset_ms: () -> Integer + + # Audio duration to process in ms. + # + def duration_ms=: (Integer) -> Integer + def duration_ms: () -> Integer + + # If `true`, does not use past transcription (if any) as context. + # + def no_context=: (boolish) -> boolish + def no_context: () -> (true | false) + + # Overwrite the audio context size. `0` uses the default value. + # + def audio_ctx=: (Integer) -> Integer + def audio_ctx: () -> Integer + + # Sets new segment callback, called for every newly generated text segment. + # + # params.new_segment_callback = ->(context, _, n_new, user_data) { + # # ... + # } + # + def new_segment_callback=: (^(Whisper::Parakeet::Context, untyped, Integer n_new, Object user_data) -> void) -> (^(Whisper::Parakeet::Context, untyped, Integer n_new, Object user_data) -> void) + def new_segment_callback: () -> ((^(Whisper::Parakeet::Context, untyped, Integer n_new, Object user_data) -> void) | nil) + + # Sets user data passed to the last argument of new segment callback. + # + def new_segment_callback_user_data=: (Object?) -> Object? + def new_segment_callback_user_data: () -> Object? + + # Sets token callback, called for every newly predicted token. + # + def new_token_callback=: (^(Whisper::Parakeet::Context, untyped, Whisper::Parakeet::Token, Object user_data) -> void) -> (^(Whisper::Parakeet::Context, untyped, Whisper::Parakeet::Token, Object user_data) -> void) + def new_token_callback: () -> ((^(Whisper::Parakeet::Context, untyped, Whisper::Parakeet::Token, Object user_data) -> void) | nil) + + # Sets user data passed to the last argument of token callback. + # + def new_token_callback_user_data=: (Object?) -> Object? + def new_token_callback_user_data: () -> Object? + + # Sets progress callback, called on each progress update. + # + # +progress+ is an Integer between 0 and 100. + # + def progress_callback=: (^(Whisper::Parakeet::Context, untyped, Integer progress, Object user_data) -> void) -> (^(Whisper::Parakeet::Context, untyped, Integer progress, Object user_data) -> void) + def progress_callback: () -> ((^(Whisper::Parakeet::Context, untyped, Integer progress, Object user_data) -> void) | nil) + + # Sets user data passed to the last argument of progress callback. + # + def progress_callback_user_data=: (Object?) -> Object? + def progress_callback_user_data: () -> Object? + + # Sets encoder begin callback, called each time before the encoder starts. + # + # If it returns `false`, the computation is aborted. + # + def encoder_begin_callback=: (^(Whisper::Parakeet::Context, untyped, Object user_data) -> boolish) -> (^(Whisper::Parakeet::Context, untyped, Object user_data) -> boolish) + def encoder_begin_callback: () -> ((^(Whisper::Parakeet::Context, untyped, Object user_data) -> boolish) | nil) + + # Sets user data passed to the last argument of encoder begin callback. + # + def encoder_begin_callback_user_data=: (Object?) -> Object? + def encoder_begin_callback_user_data: () -> Object? + + # Sets abort callback, called each time before ggml computation starts. + # + def abort_callback=: (^(Object user_data) -> boolish) -> (^(Object user_data) -> boolish) + def abort_callback: () -> ((^(Object user_data) -> boolish) | nil) + + # Sets user data passed to the last argument of abort callback. + # + def abort_callback_user_data=: (Object?) -> Object? + def abort_callback_user_data: () -> Object? + + # Hook called on new segment. Yields each Whisper::Parakeet::Segment. + # + def on_new_segment: { (Segment) -> void } -> void + + # Hook called on new token. Yields each Whisper::Parakeet::Token. + # + def on_new_token: { (Token) -> void } -> void + + # Hook called on progress update. Yields each progress `Integer` between 0 and 100. + # + def on_progress: { (Integer progress) -> void } -> void + + # Hook called each time before the encoder starts. + # + def on_encoder_begin: { () -> boolish } -> void + + # Call block to determine whether abort or not. Return `true` when you want to abort. + # + def abort_on: { () -> boolish } -> void + end + + class Segment + include Output::Segment + + type deconstructed_keys = { + start_time: (Integer | nil), + end_time: (Integer | nil), + text: (String | nil) + } + + # Start time in milliseconds. + # + def start_time: () -> Integer + + # End time in milliseconds. + # + def end_time: () -> Integer + + # Text of the segment. + # + def text: () -> String + + # Yields each Whisper::Parakeet::Token: + # + # parakeet.each_segment.first.each_token do |token| + # p token + # end + # + # Returns an `Enumerator` if no block is given: + # + # parakeet.each_segment.first.each_token.to_a # => [#<Whisper::Parakeet::Token>, ...] + # + def each_token: { (Token) -> void } -> void + | () -> Enumerator[Token] + + # Possible keys: `:start_time`, `:end_time`, `:text` + # + def deconstruct_keys: (Array[:start_time | :end_time | :text] | nil) -> deconstructed_keys + end + + class Token + type deconstructed_keys = { + id: (Integer | nil), + duration_idx: (Integer | nil), + duration_value: (Integer | nil), + frame_index: (Integer | nil), + probability: (Float | nil), + log_probability: (Float | nil), + start_time: (Integer | nil), + end_time: (Integer | nil), + word_start: ((true | false) | nil), + text: (String | nil), + } + + # Token ID. + # + def id: () -> Integer + + # Index into the model's durations array. + # + def duration_idx: () -> Integer + + # Actual duration value. + # + def duration_value: () -> Integer + + # Frame index of the token. + # + def frame_index: () -> Integer + + # Probability of the token. + # + def probability: () -> Float + + # Log probability of the token. + # + def log_probability: () -> Float + + # Start time of the token in milliseconds. + # + def start_time: () -> Integer + + # End time of the token in milliseconds. + # + def end_time: () -> Integer + + # Whether this token is the start of a word. + # + def word_start?: () -> (true | false) + + # Get the token text of the token. + # + def text: () -> String + + def deconstruct_keys: (Array[:id | :duration_idx | :duration_value | :frame_index | :probability | :log_probability | :start_time | :end_time | :word_start | :text] | nil) -> deconstructed_keys + end + + class Model + def n_vocab: () -> Integer + def n_audio_ctx: () -> Integer + def n_audio_state: () -> Integer + def n_audio_head: () -> Integer + def n_audio_layer: () -> Integer + def n_mels: () -> Integer + def ftype: () -> Integer + end + end + + module VAD + class Params + def self.new: ( + ?threshold: Float, + ?min_speech_duration_ms: Integer, + ?min_silence_duration_ms: Integer, + ?max_speech_duration_s: Float, + ?speech_pad_ms: Integer, + ?samples_overlap: Float + ) -> instance + + # Probability threshold to consider as speech. + # + def threshold=: (Float) -> Float + + def threshold: () -> Float + + # Min duration for a valid speech segment. + # + def min_speech_duration_ms=: (Integer) -> Integer + + def min_speech_duration_ms: () -> Integer + + # Min silence duration to consider speech as ended. + # + def min_silence_duration_ms=: (Integer) -> Integer + + def min_silence_duration_ms: () -> Integer + + # Max duration of a speech segment before forcing a new segment. + def max_speech_duration_s=: (Float) -> Float + + def max_speech_duration_s: () -> Float + + # Padding added before and after speech segments. + # + def speech_pad_ms=: (Integer) -> Integer + + def speech_pad_ms: () -> Integer + + # Overlap in seconds when copying audio samples from speech segment. + # + def samples_overlap=: (Float) -> Float + + def samples_overlap: () -> Float + def ==: (Params) -> (true | false) + end + + class Context + def self.new: (String | path | ::URI::HTTP model_name_or_path) -> instance + def segments_from_samples: (Params, Array[Float] samples, ?Integer n_samples) -> Segments + | (Params, _Samples, ?Integer n_samples) -> Segments + def detect: (path wav_file_path, Params) -> Segments + def free: () -> void + end + + class Segments + include Enumerable[Segment] + + def each: { (Segment) -> void } -> void + | () -> Enumerator[Segment] + def length: -> Integer + end + + class Segment + type deconstructed_keys = { + start_time: (Integer | nil), + end_time: (Integer | nil), + } + + def start_time: () -> Integer + def end_time: () -> Integer + def deconstruct_keys: (Array[:start_time | :end_time] | nil) -> deconstructed_keys + end + end + + class Error < StandardError + attr_reader code: Integer + + def self.new: (Integer code) -> instance + end +end diff --git a/bindings/ruby/test/helper.rb b/bindings/ruby/test/helper.rb new file mode 100644 index 0000000..5e37ad9 --- /dev/null +++ b/bindings/ruby/test/helper.rb @@ -0,0 +1,26 @@ +require "test/unit" +require "whisper" +require_relative "jfk_reader/jfk_reader" + +class TestBase < Test::Unit::TestCase + AUDIO = File.join(__dir__, "fixtures", "jfk.wav") + + Parakeet = Whisper::Parakeet + + class << self + def whisper + return @whisper if @whisper + + @whisper = Whisper::Context.new("base.en") + params = Whisper::Params.new + params.print_timestamps = false + @whisper.transcribe(TestBase::AUDIO, params) + end + end + + private + + def whisper + self.class.whisper + end +end diff --git a/bindings/ruby/test/jfk_reader/.gitignore b/bindings/ruby/test/jfk_reader/.gitignore new file mode 100644 index 0000000..656da8d --- /dev/null +++ b/bindings/ruby/test/jfk_reader/.gitignore @@ -0,0 +1,5 @@ +Makefile +jfk_reader.o +jfk_reader.so +jfk_reader.bundle +jfk_reader.dll diff --git a/bindings/ruby/test/jfk_reader/extconf.rb b/bindings/ruby/test/jfk_reader/extconf.rb new file mode 100644 index 0000000..0d842d0 --- /dev/null +++ b/bindings/ruby/test/jfk_reader/extconf.rb @@ -0,0 +1,3 @@ +require "mkmf" + +create_makefile("jfk_reader") diff --git a/bindings/ruby/test/jfk_reader/jfk_reader.c b/bindings/ruby/test/jfk_reader/jfk_reader.c new file mode 100644 index 0000000..7c95f72 --- /dev/null +++ b/bindings/ruby/test/jfk_reader/jfk_reader.c @@ -0,0 +1,111 @@ +#include <ruby.h> +#include <ruby/memory_view.h> +#include <ruby/encoding.h> + +typedef struct { + VALUE audio_path; + int n_samples; + const char *audio_path_str; + float *data; + short *samples; +} jfk_alloc_args; + +static VALUE +jfk_reader_alloc_resources(VALUE arg) +{ + jfk_alloc_args *a = (jfk_alloc_args *)arg; + a->audio_path_str = StringValueCStr(a->audio_path); + a->data = ALLOC_N(float, a->n_samples); + a->samples = ALLOC_N(short, a->n_samples); + return Qnil; +} + +static VALUE +jfk_reader_initialize(VALUE self, VALUE audio_path) +{ + rb_iv_set(self, "audio_path", audio_path); + return Qnil; +} + +static bool +jfk_reader_get_memory_view(const VALUE obj, rb_memory_view_t *view, int flags) +{ + VALUE audio_path = rb_iv_get(obj, "audio_path"); + // n_samples is a fixed constant (not derived from user input). + const int n_samples = 176000; + + jfk_alloc_args args = { + .audio_path = audio_path, + .n_samples = n_samples, + .audio_path_str = NULL, + .data = NULL, + .samples = NULL, + }; + + int state; + rb_protect(jfk_reader_alloc_resources, (VALUE)&args, &state); + if (state) { + if (args.samples) xfree(args.samples); + if (args.data) xfree(args.data); + return false; + } + + FILE *file = fopen(args.audio_path_str, "rb"); + if (file == NULL) { + xfree(args.samples); + xfree(args.data); + return false; + } + + fseek(file, 78, SEEK_SET); + fread(args.samples, sizeof(short), n_samples, file); + fclose(file); + for (int i = 0; i < n_samples; i++) { + args.data[i] = args.samples[i] / 32768.0; + } + xfree(args.samples); + + view->obj = obj; + view->data = (void *)args.data; + view->byte_size = sizeof(float) * n_samples; + view->readonly = true; + view->format = "e"; + view->item_size = sizeof(float); + view->item_desc.components = NULL; + view->item_desc.length = 0; + view->ndim = 1; + view->shape = NULL; + view->sub_offsets = NULL; + view->private_data = NULL; + + return true; +} + +static bool +jfk_reader_release_memory_view(const VALUE obj, rb_memory_view_t *view) +{ + if (view->data) { + xfree(view->data); + view->data = NULL; + } + return true; +} + +static bool +jfk_reader_memory_view_available_p(const VALUE obj) +{ + return true; +} + +static const rb_memory_view_entry_t jfk_reader_view_entry = { + jfk_reader_get_memory_view, + jfk_reader_release_memory_view, + jfk_reader_memory_view_available_p +}; + +void Init_jfk_reader(void) +{ + VALUE cJFKReader = rb_define_class("JFKReader", rb_cObject); + rb_memory_view_register(cJFKReader, &jfk_reader_view_entry); + rb_define_method(cJFKReader, "initialize", jfk_reader_initialize, 1); +} diff --git a/bindings/ruby/test/test_callback.rb b/bindings/ruby/test/test_callback.rb new file mode 100644 index 0000000..6490c8a --- /dev/null +++ b/bindings/ruby/test/test_callback.rb @@ -0,0 +1,203 @@ +require_relative "helper" + +class TestCallback < TestBase + def setup + GC.start + @params = Whisper::Params.new + @whisper = Whisper::Context.new("base.en") + @audio = File.join(AUDIO) + end + + def test_new_segment_callback + @params.new_segment_callback = ->(context, state, n_new, user_data) { + assert_kind_of Integer, n_new + assert n_new > 0 + assert_same @whisper, context + + n_segments = context.full_n_segments + n_new.times do |i| + i_segment = n_segments - 1 + i + start_time = context.full_get_segment_t0(i_segment) * 10 + end_time = context.full_get_segment_t1(i_segment) * 10 + text = context.full_get_segment_text(i_segment) + + assert_kind_of Integer, start_time + assert start_time >= 0 + assert_kind_of Integer, end_time + assert end_time > 0 + assert_match(/ask not what your country can do for you, ask what you can do for your country/, text) if i_segment == 0 + end + } + + @whisper.transcribe(@audio, @params) + end + + def test_new_segment_callback_closure + search_word = "what" + @params.new_segment_callback = ->(context, state, n_new, user_data) { + n_segments = context.full_n_segments + n_new.times do |i| + i_segment = n_segments - 1 + i + text = context.full_get_segment_text(i_segment) + if text.include?(search_word) + t0 = context.full_get_segment_t0(i_segment) + t1 = context.full_get_segment_t1(i_segment) + raise "search word '#{search_word}' found at between #{t0} and #{t1}" + end + end + } + + assert_raise RuntimeError do + @whisper.transcribe(@audio, @params) + end + end + + def test_new_segment_callback_user_data + udata = Object.new + @params.new_segment_callback_user_data = udata + @params.new_segment_callback = ->(context, state, n_new, user_data) { + assert_same udata, user_data + } + + @whisper.transcribe(@audio, @params) + end + + def test_new_segment_callback_user_data_gc + @params.new_segment_callback_user_data = "My user data" + @params.new_segment_callback = ->(context, state, n_new, user_data) { + assert_equal "My user data", user_data + } + GC.start + + assert_same @whisper, @whisper.transcribe(@audio, @params) + end + + def test_progress_callback + first = nil + last = nil + @params.progress_callback = ->(context, state, progress, user_data) { + assert_kind_of Integer, progress + assert 0 <= progress && progress <= 100 + assert_same @whisper, context + first = progress if first.nil? + last = progress + } + @whisper.transcribe(@audio, @params) + assert_equal 0, first + assert_equal 100, last + end + + def test_progress_callback_user_data + udata = Object.new + @params.progress_callback_user_data = udata + @params.progress_callback = ->(context, state, n_new, user_data) { + assert_same udata, user_data + } + + @whisper.transcribe(@audio, @params) + end + + def test_on_progress + first = nil + last = nil + @params.on_progress do |progress| + assert_kind_of Integer, progress + assert 0 <= progress && progress <= 100 + first = progress if first.nil? + last = progress + end + @whisper.transcribe(@audio, @params) + assert_equal 0, first + assert_equal 100, last + end + + def test_encoder_begin_callback + i = 0 + @params.encoder_begin_callback = ->(context, state, user_data) { + i += 1 + } + @whisper.transcribe(@audio, @params) + assert i > 0 + end + + def test_encoder_begin_callback_abort + logs = [] + Whisper.log_set -> (level, buffer, user_data) { + logs << buffer if level == Whisper::LOG_LEVEL_ERROR + }, logs + @params.encoder_begin_callback = ->(context, state, user_data) { + return false + } + @whisper.transcribe(@audio, @params) + sleep 0.5 # wait for logs dequeued + assert_match(/encoder_begin_callback returned false - aborting/, logs.join) + Whisper.log_set ->(level, buffer, user_data) {}, nil + end + + def test_encoder_begin_callback_user_data + udata = Object.new + @params.encoder_begin_callback_user_data = udata + yielded = nil + @params.encoder_begin_callback = ->(context, state, user_data) { + yielded = user_data + } + @whisper.transcribe(@audio, @params) + assert_same udata, yielded + end + + def test_on_encoder_begin + i = 0 + @params.on_encoder_begin do + i += 1 + end + @whisper.transcribe(@audio, @params) + assert i > 0 + end + + def test_abort_callback + i = 0 + @params.abort_callback = ->(user_data) { + assert_nil user_data + i += 1 + return false + } + @whisper.transcribe(@audio, @params) + assert i > 0 + end + + def test_abort_callback_abort + i = 0 + @params.abort_callback = ->(user_data) { + i += 1 + return i == 3 + } + @whisper.transcribe(@audio, @params) + assert_equal 3, i + end + + def test_abort_callback_user_data + udata = Object.new + @params.abort_callback_user_data = udata + yielded = nil + @params.abort_callback = ->(user_data) { + yielded = user_data + } + @whisper.transcribe(@audio, @params) + assert_same udata, yielded + end + + def test_abort_on + do_abort = false + _aborted_from_callback = false + @params.on_new_segment do |segment| + do_abort = true if segment.text.match?(/ask/) + end + i = 0 + @params.abort_on do + i += 1 + do_abort + end + @whisper.transcribe(@audio, @params) + assert i > 0 + end +end diff --git a/bindings/ruby/test/test_context_params.rb b/bindings/ruby/test/test_context_params.rb new file mode 100644 index 0000000..8d19fdc --- /dev/null +++ b/bindings/ruby/test/test_context_params.rb @@ -0,0 +1,82 @@ +require_relative "helper" + +class TestContextParams < TestBase + PARAM_NAMES = [ + :use_gpu, + :flash_attn, + :gpu_device, + :dtw_token_timestamps, + :dtw_aheads_preset, + :dtw_n_top + ] + + def test_new + params = Whisper::Context::Params.new + assert_instance_of Whisper::Context::Params, params + end + + def test_attributes + params = Whisper::Context::Params.new + + assert_true params.use_gpu + params.use_gpu = false + assert_false params.use_gpu + + assert_true params.flash_attn + params.flash_attn = false + assert_false params.flash_attn + + assert_equal 0, params.gpu_device + params.gpu_device = 1 + assert_equal 1, params.gpu_device + + assert_false params.dtw_token_timestamps + params.dtw_token_timestamps = true + assert_true params.dtw_token_timestamps + + assert_equal Whisper::AHEADS_NONE, params.dtw_aheads_preset + params.dtw_aheads_preset =Whisper::AHEADS_BASE + assert_equal Whisper::AHEADS_BASE, params.dtw_aheads_preset + + assert_nil params.dtw_n_top + params.dtw_n_top = 6 + assert_equal 6, params.dtw_n_top + params.dtw_n_top = nil + assert_nil params.dtw_n_top + end + + def test_new_with_kw_args + params = Whisper::Context::Params.new(use_gpu: false) + assert_false params.use_gpu + end + + def test_new_with_kw_wargs_non_existent + assert_raise ArgumentError do + Whisper::Context::Params.new(non_existent: "value") + end + end + + data(PARAM_NAMES.collect {|param| [param, param]}.to_h) + def test_new_with_kw_args_default_values(param) + default_params = Whisper::Context::Params.new + default_value = default_params.send(param) + value = if param == :dtw_n_top + 6 + else + case default_value + in true | false + !default_value + in Integer + default_value + 1 + end + end + params = Whisper::Context::Params.new(param => value) + assert_equal value, params.send(param) + + PARAM_NAMES.reject {|name| name == param}.each do |name| + expected = default_params.send(name) + actual = params.send(name) + assert_equal expected, actual + end + end +end diff --git a/bindings/ruby/test/test_error.rb b/bindings/ruby/test/test_error.rb new file mode 100644 index 0000000..2f28849 --- /dev/null +++ b/bindings/ruby/test/test_error.rb @@ -0,0 +1,20 @@ +require_relative "helper" + +class TestError < TestBase + def test_error + error = Whisper::Error.new(-2) + assert_equal "failed to compute log mel spectrogram", error.message + assert_equal(-2, error.code) + end + + def test_unknown_error + error = Whisper::Error.new(-20) + assert_equal "unknown error", error.message + end + + def test_non_int_code + assert_raise TypeError do + _error = Whisper::Error.new("non int") + end + end +end diff --git a/bindings/ruby/test/test_model.rb b/bindings/ruby/test/test_model.rb new file mode 100644 index 0000000..5648fc3 --- /dev/null +++ b/bindings/ruby/test/test_model.rb @@ -0,0 +1,118 @@ +require_relative "helper" +require "pathname" + +class TestModel < TestBase + def test_model + whisper = Whisper::Context.new("base.en") + assert_instance_of Whisper::Model, whisper.model + end + + def test_attributes + whisper = Whisper::Context.new("base.en") + model = whisper.model + + assert_equal 51864, model.n_vocab + assert_equal 1500, model.n_audio_ctx + assert_equal 512, model.n_audio_state + assert_equal 8, model.n_audio_head + assert_equal 6, model.n_audio_layer + assert_equal 448, model.n_text_ctx + assert_equal 512, model.n_text_state + assert_equal 8, model.n_text_head + assert_equal 6, model.n_text_layer + assert_equal 80, model.n_mels + assert_equal 1, model.ftype + assert_equal "base", model.type + end + + def test_gc + model = Whisper::Context.new("base.en").model + GC.start + + assert_equal 51864, model.n_vocab + assert_equal 1500, model.n_audio_ctx + assert_equal 512, model.n_audio_state + assert_equal 8, model.n_audio_head + assert_equal 6, model.n_audio_layer + assert_equal 448, model.n_text_ctx + assert_equal 512, model.n_text_state + assert_equal 8, model.n_text_head + assert_equal 6, model.n_text_layer + assert_equal 80, model.n_mels + assert_equal 1, model.ftype + assert_equal "base", model.type + end + + def test_pathname + path = Pathname(Whisper::Model.pre_converted_models["base.en"].to_path) + whisper = Whisper::Context.new(path) + model = whisper.model + + assert_equal 51864, model.n_vocab + assert_equal 1500, model.n_audio_ctx + assert_equal 512, model.n_audio_state + assert_equal 8, model.n_audio_head + assert_equal 6, model.n_audio_layer + assert_equal 448, model.n_text_ctx + assert_equal 512, model.n_text_state + assert_equal 8, model.n_text_head + assert_equal 6, model.n_text_layer + assert_equal 80, model.n_mels + assert_equal 1, model.ftype + assert_equal "base", model.type + end + + def test_auto_download + path = Whisper::Model.pre_converted_models["base.en"].to_path + + assert_path_exist path + assert_equal 147964211, File.size(path) + end + + def test_uri_string + path = "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-base.en.bin" + whisper = Whisper::Context.new(path) + model = whisper.model + + assert_equal 51864, model.n_vocab + assert_equal 1500, model.n_audio_ctx + assert_equal 512, model.n_audio_state + assert_equal 8, model.n_audio_head + assert_equal 6, model.n_audio_layer + assert_equal 448, model.n_text_ctx + assert_equal 512, model.n_text_state + assert_equal 8, model.n_text_head + assert_equal 6, model.n_text_layer + assert_equal 80, model.n_mels + assert_equal 1, model.ftype + assert_equal "base", model.type + end + + def test_uri + path = URI("https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-base.en.bin") + whisper = Whisper::Context.new(path) + model = whisper.model + + assert_equal 51864, model.n_vocab + assert_equal 1500, model.n_audio_ctx + assert_equal 512, model.n_audio_state + assert_equal 8, model.n_audio_head + assert_equal 6, model.n_audio_layer + assert_equal 448, model.n_text_ctx + assert_equal 512, model.n_text_state + assert_equal 8, model.n_text_head + assert_equal 6, model.n_text_layer + assert_equal 80, model.n_mels + assert_equal 1, model.ftype + assert_equal "base", model.type + end + + def test_coreml_model_auto_download + uri = Whisper::Model.coreml_compiled_models[Whisper::Model.pre_converted_models["tiny"]] + model_path = Pathname(uri.to_path).sub_ext("") + model_path.rmtree if model_path.exist? + + uri.cache + assert_path_exist model_path + end +end diff --git a/bindings/ruby/test/test_package.rb b/bindings/ruby/test/test_package.rb new file mode 100644 index 0000000..f99012c --- /dev/null +++ b/bindings/ruby/test/test_package.rb @@ -0,0 +1,52 @@ +require_relative "helper" +require 'tempfile' +require 'tmpdir' +require 'open3' + +class TestPackage < TestBase + def test_build + Tempfile.create do |file| + assert system("gem", "build", "whispercpp.gemspec", "--output", file.to_path, exception: true) + assert file.size > 0 + assert_path_exist file.to_path + end + end + + sub_test_case "Building binary on installation" do + def setup + system "rake", "build", exception: true + end + + def test_install + gemspec = Gem::Specification.load("whispercpp.gemspec") + Dir.mktmpdir do |dir| + system "gem", "install", "--install-dir", dir, "--no-document", File.join("pkg", gemspec.file_name), exception: true + assert_installed dir, gemspec.version + end + end + + def test_install_with_coreml + omit_unless RUBY_PLATFORM.match?(/darwin/) do + gemspec = Gem::Specification.load("whispercpp.gemspec") + Dir.mktmpdir do |dir| + system "gem", "install", "--install-dir", dir, "--no-document", File.join("pkg", gemspec.file_name), "--", "--enable-whisper-coreml", exception: true + assert_installed dir, gemspec.version + libdir = File.join(dir, "gems", "#{gemspec.name}-#{gemspec.version}", "lib") + assert_nothing_raised do + system "ruby", "-I", libdir, "-r", "whisper", "-e", "Whisper::Context.new('tiny')", exception: true + end + output, status = Open3.capture2("ruby", "-I", libdir, "-r", "whisper", "-e", "puts Whisper.system_info_str") + assert_match /COREML = 1/, output + end + end + end + + private + + def assert_installed(dir, version) + assert_path_exist File.join(dir, "gems/whispercpp-#{version}/lib", "whisper.#{RbConfig::CONFIG["DLEXT"]}") + assert_path_exist File.join(dir, "gems/whispercpp-#{version}/LICENSE") + assert_path_not_exist File.join(dir, "gems/whispercpp-#{version}/ext/build") + end + end +end diff --git a/bindings/ruby/test/test_parakeet.rb b/bindings/ruby/test/test_parakeet.rb new file mode 100644 index 0000000..bfd5707 --- /dev/null +++ b/bindings/ruby/test/test_parakeet.rb @@ -0,0 +1,28 @@ +require_relative "helper" +require "stringio" + +class TestParakeet < TestBase + def test_log_set + log_callback = Parakeet.instance_variable_get("@log_callback") + user_data = Parakeet.instance_variable_get("@log_callback_user_data") + + $stdout = StringIO.new + Parakeet.log_set proc {|level, message, _| puts [level, message].join(": ")}, nil + Parakeet::Context.new("test/fixtures/for-tests-ggml-parakeet-tdt.bin") + sleep 0.1 + $stdout.rewind + logs = $stdout.string + assert_match /loading model from/, logs + ensure + $stdout = STDOUT + Parakeet.log_set log_callback, user_data + end + + def test_system_info_str + assert_match /\APARAKEET : /, Parakeet.system_info_str + end + + def test_version + assert_instance_of String, Parakeet::VERSION + end +end diff --git a/bindings/ruby/test/test_parakeet_callback.rb b/bindings/ruby/test/test_parakeet_callback.rb new file mode 100644 index 0000000..1209e96 --- /dev/null +++ b/bindings/ruby/test/test_parakeet_callback.rb @@ -0,0 +1,107 @@ +require_relative "helper" + +class TestParakeetCallback < TestBase + def setup + omit "Skip not to download large model" if ENV["CI"] + + Whisper.instance_variable_set "@whisper", nil + GC.start + @params = Parakeet::Params.new + @parakeet = Parakeet::Context.new("parakeet-tdt-0.6b-v3-q4_0") + end + + def test_new_segment_callback + @params.new_segment_callback = ->(context, state, n_new, user_data) { + assert_kind_of Integer, n_new + assert n_new > 0 + assert_same @parakeet, context + + n_segments = context.full_n_segments + n_new.times do |i| + i_segment = n_segments - 1 + i + start_time = context.full_get_segment_t0(i_segment) * 10 + end_time = context.full_get_segment_t1(i_segment) * 10 + text = context.full_get_segment_text(i_segment) + + assert_kind_of Integer, start_time + assert start_time >= 0 + assert_kind_of Integer, end_time + assert end_time > 0 + assert_match(/ask not what your country can do for you, ask what you can do for your/, text) if i_segment == 0 + end + } + + @parakeet.transcribe AUDIO, @params + end + + def test_on_new_segment + seg = nil + index = 0 + @params.on_new_segment do |segment| + assert_instance_of Parakeet::Segment, segment + if index == 0 + seg = segment + assert_equal 0, segment.start_time + assert_match(/ask not what your country can do for you, ask what you can do for your/, segment.text) + end + index += 1 + end + @parakeet.transcribe AUDIO, @params + assert_equal 0, seg.start_time + assert_match /ask not what your country can do for you, ask what you can do for your/, seg.text + end + + def test_on_new_token + index = 0 + @params.on_new_token do |token| + assert_instance_of Parakeet::Token, token + if index == 0 + assert_instance_of Integer, token.start_time + assert_match "▁And", token.text + end + index += 1 + end + + @parakeet.transcribe AUDIO, @params + end + + def test_on_progress + first = nil + @params.on_progress do |progress| + assert_kind_of Integer, progress + assert 0 <= progress && progress <= 100 + first = progress if first.nil? + end + + @parakeet.transcribe AUDIO, @params + + assert_equal 0, first + end + + def test_on_encoder_begin + i = 0 + @params.on_encoder_begin do + i += 1 + end + + @parakeet.transcribe AUDIO, @params + + assert i > 0 + end + + def test_abort_on + do_abort = false + @params.on_new_segment do |segment| + do_abort = true if segment.text.match?(/ask/) + end + i = 0 + @params.abort_on do + i += 1 + do_abort + end + + @parakeet.transcribe(AUDIO, @params) rescue nil + + assert i > 0 + end +end diff --git a/bindings/ruby/test/test_parakeet_context.rb b/bindings/ruby/test/test_parakeet_context.rb new file mode 100644 index 0000000..cef6b14 --- /dev/null +++ b/bindings/ruby/test/test_parakeet_context.rb @@ -0,0 +1,123 @@ +require_relative "helper" +require "stringio" + +class TestParakeetContext < TestBase + def setup + omit "Skip not to download large model" if ENV["CI"] + + Whisper.instance_variable_set "@whisper", nil + GC.start + + @parakeet = Parakeet::Context.new("parakeet-tdt-0.6b-v3-q4_0") + @params = Parakeet::Params.new + end + + def test_new + assert_instance_of Parakeet::Context, @parakeet + end + + def test_new_with_params + log_callback = Parakeet.instance_variable_get(:@log_callback) + user_data = Parakeet.instance_variable_get(:@log_callback_user_data) + begin + logs = "" + Parakeet.log_set proc {|level, message| logs << message}, nil + params = Parakeet::Context::Params.new(use_gpu: false) + parakeet = Parakeet::Context.new("parakeet-tdt-0.6b-v3-q4_0", params) + assert_instance_of Parakeet::Context, parakeet + assert_match /use gpu\s+=\s+0/, logs + ensure + Parakeet.log_set log_callback, user_data + end + end + + sub_test_case "full" do + def setup + super + @samples = File.read(AUDIO, nil, 78).unpack("s<*").collect {|i| i.to_f / 2**15} + end + + def test_full + @parakeet.full @params, @samples, @samples.length + + segments = @parakeet.each_segment.to_a + assert_equal 1, segments.length + assert_match /ask not what your country can do for you, ask what you can do for your/, segments.first.text + end + + def test_full_without_length + @parakeet.full(@params, @samples) + + segments = @parakeet.each_segment.to_a + assert_equal 1, segments.length + assert_match /ask not what your country can do for you, ask what you can do for your/, @parakeet.each_segment.first.text + end + + def test_full_enumerator + samples = @samples.each + @parakeet.full @params, samples, @samples.length + + segments = @parakeet.each_segment.to_a + assert_equal 1, segments.length + assert_match /ask not what your country can do for you, ask what you can do for your/, @parakeet.each_segment.first.text + end + + def test_full_enumerator_without_length + samples = @samples.each + assert_raise ArgumentError do + @parakeet.full @params, samples + end + end + + def test_full_enumerator_with_too_large_length + samples = @samples.each.take(10).to_enum + assert_raise StopIteration do + @parakeet.full @params, samples, 11 + end + end + + def test_full_with_memory_view + samples = JFKReader.new(AUDIO) + @parakeet.full @params, samples + + segments = @parakeet.each_segment.to_a + assert_equal 1, segments.length + assert_match /ask not what your country can do for you, ask what you can do for your/, @parakeet.each_segment.first.text + end + + def test_full_with_memroy_view_gc + samples = JFKReader.new(AUDIO) + @parakeet.full(@params, samples) + GC.start + require "fiddle" + Fiddle::MemoryView.export samples do |view| + assert_equal 176000, view.to_s.unpack("#{view.format}*").length + end + end + end + + def test_transcribe + assert_nothing_raised do + @parakeet.transcribe AUDIO, @params + end + end + + def test_transcribe_with_pathname + assert_nothing_raised do + @parakeet.transcribe Pathname(AUDIO), @params + end + end + + def test_transcribe_with_nothing + assert_raise_message(/open/) do + @parakeet.transcribe "nothing", @params + end + end + + def test_free + @parakeet.free + assert_raise RuntimeError do + @parakeet.transcribe AUDIO, @params + end + end +end diff --git a/bindings/ruby/test/test_parakeet_context_params.rb b/bindings/ruby/test/test_parakeet_context_params.rb new file mode 100644 index 0000000..fcd0f24 --- /dev/null +++ b/bindings/ruby/test/test_parakeet_context_params.rb @@ -0,0 +1,24 @@ +require_relative "helper" + +class TestParakeetContextParams < TestBase + def setup + @params = Parakeet::Context::Params.new + end + + def test_new + assert_instance_of Parakeet::Context::Params, @params + end + + def test_attributes + assert_true @params.use_gpu + assert_instance_of Integer, @params.gpu_device + end + + def test_attribute_writer + @params.use_gpu = false + assert_false @params.use_gpu + + @params.gpu_device = 2 + assert_equal 2, @params.gpu_device + end +end diff --git a/bindings/ruby/test/test_parakeet_model.rb b/bindings/ruby/test/test_parakeet_model.rb new file mode 100644 index 0000000..5343b35 --- /dev/null +++ b/bindings/ruby/test/test_parakeet_model.rb @@ -0,0 +1,21 @@ +require_relative "helper" + +class TestParakeetModel < TestBase + def test_model + parakeet = Parakeet::Context.new("test/fixtures/for-tests-ggml-parakeet-tdt.bin") + assert_instance_of Parakeet::Model, parakeet.model + end + + def test_attributes + parakeet = Parakeet::Context.new("test/fixtures/for-tests-ggml-parakeet-tdt.bin") + model = parakeet.model + + assert_equal 10, model.n_vocab + assert_equal 3200, model.n_audio_ctx + assert_equal 8, model.n_audio_state + assert_equal 2, model.n_audio_head + assert_equal 1, model.n_audio_layer + assert_equal 16, model.n_mels + assert_equal 0, model.ftype + end +end diff --git a/bindings/ruby/test/test_parakeet_params.rb b/bindings/ruby/test/test_parakeet_params.rb new file mode 100644 index 0000000..dc651f7 --- /dev/null +++ b/bindings/ruby/test/test_parakeet_params.rb @@ -0,0 +1,78 @@ +require_relative "helper" +require "etc" + +class TestParakeetParams < TestBase + PARAM_NAMES = [ + :n_threads, + :offset_ms, + :duration_ms, + :no_context, + :audio_ctx + ] + + def setup + @params = Parakeet::Params.new + end + + def test_new + assert_instance_of Parakeet::Params, @params + end + + def test_n_threads + assert_equal [4, Etc.nprocessors].min, @params.n_threads + + @params.n_threads = 1 + assert_equal 1, @params.n_threads + end + + def test_offset_ms + assert_equal 0, @params.offset_ms + + @params.offset_ms = 10_000 + assert_equal 10_000, @params.offset_ms + end + + def test_duration_ms + assert_equal 0, @params.duration_ms + + @params.duration_ms = 60_000 + assert_equal 60_000, @params.duration_ms + end + + def test_no_context + assert_equal true, @params.no_context + + @params.no_context = false + assert_equal false, @params.no_context + end + + def test_audio_ctx + assert_equal 0, @params.audio_ctx + + @params.audio_ctx = 1 + assert_equal 1, @params.audio_ctx + end + + def test_new_with_kw_args + params = Parakeet::Params.new(n_threads: 1) + assert_equal 1, params.n_threads + assert_equal 0, params.offset_ms + end + + data(PARAM_NAMES.collect {|param| [param, param]}.to_h) + def test_new_with_kw_args_default_values(param) + default_value = @params.send(param) + value = case [param, default_value] + in [*, true | false] + !default_value + in [*, Integer] + default_value + 1 + end + params = Parakeet::Params.new(param => value) + assert_equal value, params.send(param) + + PARAM_NAMES.reject {|name| name == param}.each do |name| + assert_equal @params.send(name), params.send(name) + end + end +end diff --git a/bindings/ruby/test/test_parakeet_segment.rb b/bindings/ruby/test/test_parakeet_segment.rb new file mode 100644 index 0000000..d5b99bd --- /dev/null +++ b/bindings/ruby/test/test_parakeet_segment.rb @@ -0,0 +1,42 @@ +require_relative "helper" + +class TestParakeetSegment < TestBase + def setup + omit "Skip not to download large model" if ENV["CI"] + + @parakeet = Parakeet::Context.new("parakeet-tdt-0.6b-v3-q4_0") + @parakeet.transcribe AUDIO, Parakeet::Params.new + end + + def test_segment + whole_text = "" + @parakeet.each_segment do |segment| + assert_instance_of Parakeet::Segment, segment + assert_kind_of Integer, segment.start_time + assert segment.end_time >= segment.start_time + assert_kind_of String, segment.text + whole_text << segment.text + end + assert_match(/ask not what your country can do for you, ask what you can do for your country/, whole_text) + end + + def test_deconstruct_keys + segment = @parakeet.each_segment.first + expected = { + start_time: segment.start_time, + end_time: segment.end_time, + text: segment.text + } + assert_equal expected, segment.deconstruct_keys([:start_time, :end_time, :text]) + end + + def test_deconstruct_keys_with_nil + segment = @parakeet.each_segment.first + expected = { + start_time: segment.start_time, + end_time: segment.end_time, + text: segment.text + } + assert_equal expected, segment.deconstruct_keys(nil) + end +end diff --git a/bindings/ruby/test/test_parakeet_token.rb b/bindings/ruby/test/test_parakeet_token.rb new file mode 100644 index 0000000..6f0b8b5 --- /dev/null +++ b/bindings/ruby/test/test_parakeet_token.rb @@ -0,0 +1,73 @@ +require_relative "helper" + +class TestParakeetToken < TestBase + ATTRS = %i[ + id + duration_idx + duration_value + frame_index + probability + log_probability + start_time + end_time + word_start? + text + ] + + def setup + omit "Skip not to download large model" if ENV["CI"] + + Whisper.instance_variable_set "@whisper", nil + GC.start + + parakeet = Parakeet::Context.new("parakeet-tdt-0.6b-v3-q4_0") + params = Parakeet::Params.new + parakeet.transcribe AUDIO, params + @segment = parakeet.each_segment.first + end + + def test_each_token + i = 0 + @segment.each_token do |token| + i += 1 + assert_instance_of Parakeet::Token, token + end + assert_equal 38, i + end + + def test_each_token_without_block + assert_instance_of Enumerator, @segment.each_token + end + + def test_token + token = @segment.each_token.first + + assert_instance_of Parakeet::Token, token + assert_instance_of Integer, token.id + assert_instance_of Integer, token.duration_idx + assert_instance_of Integer, token.duration_value + assert_instance_of Integer, token.frame_index + assert_instance_of Float, token.probability + assert_instance_of Float, token.log_probability + assert_instance_of Integer, token.start_time + assert_instance_of Integer, token.end_time + assert_instance_of String, token.text + end + + def test_text + assert_equal ["▁And", "▁so", ",", "▁my", "▁f", "ell", "ow", "▁Amer", "ic", "ans", ",", "▁a", "sk", "▁not", "▁what", "▁your", "▁co", "un", "tr", "y", "▁can", "▁do", "▁for", "▁you", ",", "▁a", "sk", "▁what", "▁you", "▁can", "▁do", "▁for", "▁your", "▁co", "un", "tr", "y", "."], + @segment.each_token.collect(&:text) + end + + def test_deconstruct_keys_with_nil + token = @segment.each_token.first + expected = ATTRS.collect {|attr| [attr.to_s.sub(/\?\z/, "").intern, token.send(attr)]}.to_h + assert_equal expected, token.deconstruct_keys(nil) + end + + def test_deconstruct_keys_with_keys + token = @segment.each_token.first + expected = ATTRS.collect {|attr| [attr.to_s.sub(/\?\z/, "").intern, token.send(attr)]}.to_h + assert_equal expected, token.deconstruct_keys(expected.keys) + end +end diff --git a/bindings/ruby/test/test_params.rb b/bindings/ruby/test/test_params.rb new file mode 100644 index 0000000..ff5c28e --- /dev/null +++ b/bindings/ruby/test/test_params.rb @@ -0,0 +1,315 @@ +require_relative "helper" + +class TestParams < TestBase + PARAM_NAMES = [ + :language, + :translate, + :no_context, + :single_segment, + :print_special, + :print_progress, + :print_realtime, + :print_timestamps, + :suppress_blank, + :suppress_nst, + :token_timestamps, + :max_len, + :split_on_word, + :initial_prompt, + :carry_initial_prompt, + :diarize, + :offset, + :duration, + :max_text_tokens, + :temperature, + :max_initial_ts, + :length_penalty, + :temperature_inc, + :entropy_thold, + :logprob_thold, + :no_speech_thold, + :new_segment_callback, + :new_segment_callback_user_data, + :progress_callback, + :progress_callback_user_data, + :abort_callback, + :abort_callback_user_data, + :vad, + :vad_model_path, + :vad_params, + ] + + def setup + @params = Whisper::Params.new + end + + def test_language + @params.language = "en" + assert_equal @params.language, "en" + GC.compact + assert_equal @params.language, "en" + @params.language = "auto" + assert_equal @params.language, "auto" + end + + def test_offset + @params.offset = 10_000 + assert_equal @params.offset, 10_000 + @params.offset = 0 + assert_equal @params.offset, 0 + end + + def test_duration + @params.duration = 60_000 + assert_equal @params.duration, 60_000 + @params.duration = 0 + assert_equal @params.duration, 0 + end + + def test_max_text_tokens + @params.max_text_tokens = 300 + assert_equal @params.max_text_tokens, 300 + @params.max_text_tokens = 0 + assert_equal @params.max_text_tokens, 0 + end + + def test_translate + @params.translate = true + assert @params.translate + @params.translate = false + assert !@params.translate + end + + def test_no_context + @params.no_context = true + assert @params.no_context + @params.no_context = false + assert !@params.no_context + end + + def test_single_segment + @params.single_segment = true + assert @params.single_segment + @params.single_segment = false + assert !@params.single_segment + end + + def test_print_special + @params.print_special = true + assert @params.print_special + @params.print_special = false + assert !@params.print_special + end + + def test_print_progress + @params.print_progress = true + assert @params.print_progress + @params.print_progress = false + assert !@params.print_progress + end + + def test_print_realtime + @params.print_realtime = true + assert @params.print_realtime + @params.print_realtime = false + assert !@params.print_realtime + end + + def test_print_timestamps + @params.print_timestamps = true + assert @params.print_timestamps + @params.print_timestamps = false + assert !@params.print_timestamps + end + + def test_carry_initial_prompt + @params.carry_initial_prompt = true + assert @params.carry_initial_prompt + @params.carry_initial_prompt = false + assert !@params.carry_initial_prompt + end + + def test_suppress_blank + @params.suppress_blank = true + assert @params.suppress_blank + @params.suppress_blank = false + assert !@params.suppress_blank + end + + def test_suppress_nst + @params.suppress_nst = true + assert @params.suppress_nst + @params.suppress_nst = false + assert !@params.suppress_nst + end + + def test_token_timestamps + @params.token_timestamps = true + assert @params.token_timestamps + @params.token_timestamps = false + assert !@params.token_timestamps + end + + def test_max_len + @params.max_len = 42 + assert_equal @params.max_len, 42 + @params.max_len = 0 + assert_equal @params.max_len, 0 + end + + def test_split_on_word + @params.split_on_word = true + assert @params.split_on_word + @params.split_on_word = false + assert !@params.split_on_word + end + + def test_initial_prompt + assert_nil @params.initial_prompt + @params.initial_prompt = "You are a polite person." + assert_equal "You are a polite person.", @params.initial_prompt + end + + def test_temperature + assert_equal 0.0, @params.temperature + @params.temperature = 0.5 + assert_equal 0.5, @params.temperature + end + + def test_max_initial_ts + assert_equal 1.0, @params.max_initial_ts + @params.max_initial_ts = 600.0 + assert_equal 600.0, @params.max_initial_ts + end + + def test_length_penalty + assert_equal(-1.0, @params.length_penalty) + @params.length_penalty = 0.5 + assert_equal 0.5, @params.length_penalty + end + + def test_temperature_inc + assert_in_delta 0.2, @params.temperature_inc + @params.temperature_inc = 0.5 + assert_in_delta 0.5, @params.temperature_inc + end + + def test_entropy_thold + assert_in_delta 2.4, @params.entropy_thold + @params.entropy_thold = 3.0 + assert_in_delta 3.0, @params.entropy_thold + end + + def test_logprob_thold + assert_in_delta(-1.0, @params.logprob_thold) + @params.logprob_thold = -0.5 + assert_in_delta(-0.5, @params.logprob_thold) + end + + def test_no_speech_thold + assert_in_delta 0.6, @params.no_speech_thold + @params.no_speech_thold = 0.2 + assert_in_delta 0.2, @params.no_speech_thold + end + + def test_vad + assert_false @params.vad + @params.vad = true + assert_true @params.vad + end + + def test_vad_model_path + assert_nil @params.vad_model_path + @params.vad_model_path = "silero-v6.2.0" + assert_equal Whisper::Model.pre_converted_models["silero-v6.2.0"].to_path, @params.vad_model_path + end + + def test_vad_model_path_with_nil + @params.vad_model_path = "silero-v6.2.0" + @params.vad_model_path = nil + assert_nil @params.vad_model_path + end + + def test_vad_model_path_with_invalid + assert_raise TypeError do + @params.vad_model_path = Object.new + end + end + + def test_vad_model_path_with_URI_string + @params.vad_model_path = "https://huggingface.co/ggml-org/whisper-vad/resolve/main/ggml-silero-v6.2.0.bin" + assert_equal @params.vad_model_path, Whisper::Model.pre_converted_models["silero-v6.2.0"].to_path + end + + def test_vad_model_path_with_URI + @params.vad_model_path = URI("https://huggingface.co/ggml-org/whisper-vad/resolve/main/ggml-silero-v6.2.0.bin") + assert_equal @params.vad_model_path, Whisper::Model.pre_converted_models["silero-v6.2.0"].to_path + end + + def test_vad_params + assert_kind_of Whisper::VAD::Params, @params.vad_params + default_params = @params.vad_params + assert_same default_params, @params.vad_params + assert_equal 0.5, default_params.threshold + new_params = Whisper::VAD::Params.new + @params.vad_params = new_params + assert_same new_params, @params.vad_params + end + + def test_new_with_kw_args + params = Whisper::Params.new(language: "es") + assert_equal "es", params.language + assert_equal 1.0, params.max_initial_ts + end + + def test_new_with_kw_args_non_existent + assert_raise ArgumentError do + Whisper::Params.new(non_existent: "value") + end + end + + def test_new_with_kw_args_wrong_type + assert_raise TypeError do + Whisper::Params.new(language: 3) + end + end + + data(PARAM_NAMES.collect {|param| [param, param]}.to_h) + def test_new_with_kw_args_default_values(param) + default_value = @params.send(param) + value = case [param, default_value] + in [*, true | false] + !default_value + in [*, Integer | Float] + default_value + 1 + in [:language, *] + "es" + in [:initial_prompt, *] + "Initial prompt" + in [/_callback\Z/, *] + proc {} + in [/_user_data\Z/, *] + Object.new + in [:vad_model_path, *] + Whisper::Model.pre_converted_models["silero-v6.2.0"].to_path + in [:vad_params, *] + Whisper::VAD::Params.new + end + params = Whisper::Params.new(param => value) + if Float === value + assert_in_delta value, params.send(param) + else + assert_equal value, params.send(param) + end + + PARAM_NAMES.reject {|name| name == param}.each do |name| + expected = @params.send(name) + actual = params.send(name) + if Float === expected + assert_in_delta expected, actual + else + assert_equal expected, actual + end + end + end +end diff --git a/bindings/ruby/test/test_segment.rb b/bindings/ruby/test/test_segment.rb new file mode 100644 index 0000000..08a037c --- /dev/null +++ b/bindings/ruby/test/test_segment.rb @@ -0,0 +1,145 @@ +require_relative "helper" + +class TestSegment < TestBase + def test_iteration + whisper.each_segment do |segment| + assert_instance_of Whisper::Segment, segment + end + end + + def test_enumerator + enum = whisper.each_segment + assert_instance_of Enumerator, enum + enum.to_a.each_with_index do |segment, index| + assert_instance_of Whisper::Segment, segment + assert_kind_of Integer, index + end + end + + def test_start_time + i = 0 + whisper.each_segment do |segment| + assert_equal 0, segment.start_time if i == 0 + i += 1 + end + end + + def test_end_time + i = 0 + whisper.each_segment do |segment| + assert_equal whisper.full_get_segment_t1(i) * 10, segment.end_time + i += 1 + end + end + + def test_no_speech_prob + no_speech_prob = nil + whisper.each_segment do |segment| + no_speech_prob = segment.no_speech_prob + end + assert no_speech_prob > 0.0 + end + + def test_on_new_segment + params = Whisper::Params.new + seg = nil + index = 0 + params.on_new_segment do |segment| + assert_instance_of Whisper::Segment, segment + if index == 0 + seg = segment + assert_equal 0, segment.start_time + assert_match(/ask not what your country can do for you, ask what you can do for your country/, segment.text) + end + index += 1 + end + whisper.transcribe(AUDIO, params) + assert_equal 0, seg.start_time + assert_match(/ask not what your country can do for you, ask what you can do for your country/, seg.text) + end + + def test_on_new_segment_twice + params = Whisper::Params.new + seg = nil + params.on_new_segment do |segment| + seg = segment + return + end + params.on_new_segment do |segment| + assert_same seg, segment + return + end + whisper.transcribe(AUDIO, params) + end + + def test_transcription_after_segment_retrieved + segment = whisper.each_segment.first + assert_match(/ask not what your country can do for you, ask what you can do for your country/, segment.text) + + whisper.transcribe(AUDIO, Whisper::Params.new(offset: 5000)) + assert_not_match(/ask not what your country can do for you, ask what you can do for your country/, segment.text) + assert_match(/what you can do for your country/i, segment.text) + end + + def test_pattern_matching + segment = whisper.each_segment.first + segment => {start_time:, end_time:, text:, no_speech_prob:, speaker_turn_next:} + + assert_equal segment.start_time, start_time + assert_equal segment.end_time, end_time + assert_equal segment.text, text + assert_equal segment.no_speech_prob, no_speech_prob + assert_equal segment.speaker_turn_next?, speaker_turn_next + end + + def test_pattern_matching_partial + segment = whisper.each_segment.first + segment => {start_time:, end_time:, text:} + + assert_equal segment.start_time, start_time + assert_equal segment.end_time, end_time + assert_equal segment.text, text + end + + def test_deconstruct_keys + segment = whisper.each_segment.first + expected = { + start_time: segment.start_time, + end_time: segment.end_time, + text: segment.text, + no_speech_prob: segment.no_speech_prob, + speaker_turn_next: segment.speaker_turn_next? + } + assert_equal expected, segment.deconstruct_keys([:start_time, :end_time, :text, :no_speech_prob, :speaker_turn_next]) + end + + def test_deconstruct_keys_non_existent + omit "Undefined behavior" + + segment = whisper.each_segment.first + + assert_equal({}, segment.deconstruct_keys([:non_existent])) + end + + def test_deconstruct_keys_too_many_keys + omit "Undefined behavior" + + segment = whisper.each_segment.first + + assert_equal({}, segment.deconstruct_keys([:start_time, :end_time, :text, :no_speech_prob, :speaker_turn_next, :extra_key])) + end + + def test_deconstruct_keys_includes_non_existent_keys_not_too_many + omit "Undefined behavior" + + segment = whisper.each_segment.first + + expected = { + start_time: segment.start_time, + end_time: segment.end_time, + text: segment.text, + no_speech_prob: segment.no_speech_prob + } + assert_equal(expected, segment.deconstruct_keys([:start_time, :end_time, :text, :no_speech_prob, :non_existent])) + end +end diff --git a/bindings/ruby/test/test_token.rb b/bindings/ruby/test/test_token.rb new file mode 100644 index 0000000..a23f681 --- /dev/null +++ b/bindings/ruby/test/test_token.rb @@ -0,0 +1,81 @@ +require_relative "helper" + +class TestToken < TestBase + def setup + @segment = whisper.each_segment.first + @token = @segment.each_token.first + end + + def test_n_tokens + assert_equal 27, @segment.n_tokens + end + + def test_allocate + token = Whisper::Token.allocate + assert_raise do + token.id + end + end + + def test_each_token + i = 0 + @segment.each_token do |token| + i += 1 + assert_instance_of Whisper::Token, token + end + assert_equal 27, i + end + + def test_each_token_without_block + assert_instance_of Enumerator, @segment.each_token + end + + def test_token + assert_instance_of Whisper::Token, @token + + assert_instance_of Integer, @token.id + assert_instance_of Float, @token.probability + assert_instance_of Float, @token.log_probability + + assert_instance_of Integer, @token.tid + assert_instance_of Float, @token.pt + assert_instance_of Float, @token.ptsum + + assert_instance_of Integer, @token.start_time + assert_instance_of Integer, @token.end_time + + assert_instance_of Integer, @token.t_dtw + + assert_instance_of Float, @token.voice_length + + assert_instance_of String, @token.text + end + + def test_text + assert_equal ["[_BEG_]", " And", " so", " my", " fellow", " Americans", ",", " ask", " not", " what", " your", " country", " can", " do", " for", " you", ",", " ask", " what", " you", " can", " do", " for", " your", " country", ".", "[_TT_550]"], + @segment.each_token.collect(&:text) + end + + def test_token_timestamps + params = Whisper::Params.new(token_timestamps: true) + whisper.transcribe(TestBase::AUDIO, params) + prev = -1 + whisper.each_segment.first.each_token do |token| + assert token.start_time >= prev + assert token.end_time >= token.start_time + prev = token.end_time + end + end + + def test_deconstruct_keys_with_nil + keys = %i[id tid probability log_probability pt ptsum t_dtw voice_length start_time end_time text] + expected = keys.collect {|key| [key, @token.send(key)] }.to_h + assert_equal(expected, @token.deconstruct_keys(nil)) + end + + def test_deconstruct_keys_with_keys + keys = %i[id tid probability log_probability pt ptsum t_dtw voice_length start_time end_time text] + expected = keys.collect {|key| [key, @token.send(key)] }.to_h + assert_equal expected, @token.deconstruct_keys(keys) + end +end diff --git a/bindings/ruby/test/test_vad.rb b/bindings/ruby/test/test_vad.rb new file mode 100644 index 0000000..8d3d94d --- /dev/null +++ b/bindings/ruby/test/test_vad.rb @@ -0,0 +1,28 @@ +require_relative "helper" + +class TestVAD < TestBase + def setup + @whisper = Whisper::Context.new("base.en") + vad_params = Whisper::VAD::Params.new + @params = Whisper::Params.new( + vad: true, + vad_model_path: "silero-v6.2.0", + vad_params: + ) + end + + def test_transcribe + @whisper.transcribe(TestBase::AUDIO, @params) do |text| + assert_match(/ask not what your country can do for you[,.] ask what you can do for your country/i, text) + end + end + + def test_vad_segments_api + @whisper.transcribe TestBase::AUDIO, @params + + assert_equal 4, @whisper.full_n_vad_segments + @whisper.full_n_vad_segments.times do |i| + assert @whisper.full_get_vad_segment_t0(i) < @whisper.full_get_vad_segment_t1(i) + end + end +end diff --git a/bindings/ruby/test/test_vad_context.rb b/bindings/ruby/test/test_vad_context.rb new file mode 100644 index 0000000..9cc5016 --- /dev/null +++ b/bindings/ruby/test/test_vad_context.rb @@ -0,0 +1,108 @@ +require_relative "helper" + +class TestVADContext < TestBase + def test_initialize + context = Whisper::VAD::Context.new("silero-v6.2.0") + assert_instance_of Whisper::VAD::Context, context + end + + def test_detect + context = Whisper::VAD::Context.new("silero-v6.2.0") + segments = context.detect(AUDIO, Whisper::VAD::Params.new) + assert_segments segments + end + + def test_invalid_model_type + assert_raise TypeError do + Whisper::VAD::Context.new(Object.new) + end + end + + def test_allocate + vad = Whisper::VAD::Context.allocate + assert_raise do + vad.detect(AUDIO, Whisper::VAD::Params.new) + end + end + + def test_free + vad = Whisper::VAD::Context.new("silero-v6.2.0") + vad.free + assert_raise RuntimeError do + vad.detect(AUDIO, Whisper::VAD::Params.new) + end + end + + private + + def assert_segments(segments) + assert_instance_of Whisper::VAD::Segments, segments + + i = 0 + segments.each do |segment| + i += 1 + assert_instance_of Whisper::VAD::Segment, segment + end + assert i > 0 + + segments.each_with_index do |segment, index| + assert_instance_of Integer, index + end + + assert_instance_of Enumerator, segments.each + + segment = segments.each.first + assert_instance_of Integer, segment.start_time + assert_instance_of Integer, segment.end_time + + segment => {start_time:, end_time:} + assert_equal segment.start_time, start_time + assert_equal segment.end_time, end_time + + assert_equal 4, segments.length + end + + sub_test_case "from samples" do + def setup + super + @vad = Whisper::VAD::Context.new("silero-v6.2.0") + @samples = File.read(AUDIO, nil, 78).unpack("s<*").collect {|i| i.to_f / 2**15} + end + + def test_segments_from_samples + segments = @vad.segments_from_samples(Whisper::VAD::Params.new, @samples, @samples.length) + assert_segments segments + end + + def test_segments_from_samples_without_length + segments = @vad.segments_from_samples(Whisper::VAD::Params.new, @samples) + assert_segments segments + end + + def test_segments_from_samples_enumerator + samples = @samples.each + segments = @vad.segments_from_samples(Whisper::VAD::Params.new, samples, @samples.length) + assert_segments segments + end + + def test_segments_from_samples_enumerator_without_length + samples = @samples.each + assert_raise ArgumentError do + @vad.segments_from_samples(Whisper::VAD::Params.new, samples) + end + end + + def test_segments_from_samples_enumerator_with_too_large_length + samples = @samples.each.take(10).to_enum + assert_raise StopIteration do + @vad.segments_from_samples(Whisper::VAD::Params.new, samples, 11) + end + end + + def test_segments_from_samples_with_memory_view + samples = JFKReader.new(AUDIO) + segments = @vad.segments_from_samples(Whisper::VAD::Params.new, samples) + assert_segments segments + end + end +end diff --git a/bindings/ruby/test/test_vad_params.rb b/bindings/ruby/test/test_vad_params.rb new file mode 100644 index 0000000..add4899 --- /dev/null +++ b/bindings/ruby/test/test_vad_params.rb @@ -0,0 +1,103 @@ +require_relative "helper" + +class TestVADParams < TestBase + PARAM_NAMES = [ + :threshold, + :min_speech_duration_ms, + :min_silence_duration_ms, + :max_speech_duration_s, + :speech_pad_ms, + :samples_overlap + ] + + def setup + @params = Whisper::VAD::Params.new + end + + def test_new + params = Whisper::VAD::Params.new + assert_kind_of Whisper::VAD::Params, params + end + + def test_threshold + assert_in_delta @params.threshold, 0.5 + @params.threshold = 0.7 + assert_in_delta @params.threshold, 0.7 + end + + def test_min_speech_duration + pend + end + + def test_min_speech_duration_ms + assert_equal 250, @params.min_speech_duration_ms + @params.min_speech_duration_ms = 500 + assert_equal 500, @params.min_speech_duration_ms + end + + def test_min_silence_duration_ms + assert_equal 100, @params.min_silence_duration_ms + @params.min_silence_duration_ms = 200 + assert_equal 200, @params.min_silence_duration_ms + end + + def test_max_speech_duration + pend + end + + def test_max_speech_duration_s + assert @params.max_speech_duration_s >= 10e37 # Defaults to FLT_MAX + @params.max_speech_duration_s = 60.0 + assert_equal 60.0, @params.max_speech_duration_s + end + + def test_speech_pad_ms + assert_equal 30, @params.speech_pad_ms + @params.speech_pad_ms = 50 + assert_equal 50, @params.speech_pad_ms + end + + def test_samples_overlap + assert_in_delta @params.samples_overlap, 0.1 + @params.samples_overlap = 0.5 + assert_in_delta @params.samples_overlap, 0.5 + end + + def test_equal + assert_equal @params, Whisper::VAD::Params.new + end + + def test_new_with_kw_args + params = Whisper::VAD::Params.new(threshold: 0.7) + assert_in_delta params.threshold, 0.7 + assert_equal 250, params.min_speech_duration_ms + end + + def test_new_with_kw_args_non_existent + assert_raise ArgumentError do + Whisper::VAD::Params.new(non_existent: "value") + end + end + + data(PARAM_NAMES.collect {|param| [param, param]}.to_h) + def test_new_with_kw_args_default_values(param) + default_value = @params.send(param) + value = default_value + 1 + params = Whisper::VAD::Params.new(param => value) + if Float === value + assert_in_delta value, params.send(param) + else + assert_equal value, params.send(param) + end + + PARAM_NAMES.reject {|name| name == param}.each do |name| + expected = @params.send(name) + actual = params.send(name) + if Float === expected + assert_in_delta expected, actual + else + assert_equal expected, actual + end + end + end +end diff --git a/bindings/ruby/test/test_vad_segment.rb b/bindings/ruby/test/test_vad_segment.rb new file mode 100644 index 0000000..6d66c27 --- /dev/null +++ b/bindings/ruby/test/test_vad_segment.rb @@ -0,0 +1,19 @@ +require_relative "helper" + +class TestVADSegment < TestBase + def test_initialize + segment = Whisper::VAD::Segment.new + + assert_raise do + segment.start_time + end + + assert_raise do + segment.end_time + end + + assert_raise do + segment => {start_time:, end_time:} + end + end +end diff --git a/bindings/ruby/test/test_vad_segments.rb b/bindings/ruby/test/test_vad_segments.rb new file mode 100644 index 0000000..855dc48 --- /dev/null +++ b/bindings/ruby/test/test_vad_segments.rb @@ -0,0 +1,16 @@ +require_relative "helper" + +class TestVADSegments < TestBase + def test_initialize + segments = Whisper::VAD::Segments.new + + assert_raise do + segments.each do |segment| + end + end + + assert_raise do + segments.length + end + end +end diff --git a/bindings/ruby/test/test_whisper.rb b/bindings/ruby/test/test_whisper.rb new file mode 100644 index 0000000..ba5dbe7 --- /dev/null +++ b/bindings/ruby/test/test_whisper.rb @@ -0,0 +1,350 @@ +require_relative "helper" +require "stringio" +require "etc" +require "pathname" + +# Exists to detect memory-related bug +Whisper.log_set ->(level, buffer, user_data) {}, nil + +class TestWhisper < TestBase + def setup + @params = Whisper::Params.new + end + + def test_whisper + @whisper = Whisper::Context.new("base.en") + params = Whisper::Params.new + params.print_timestamps = false + + @whisper.transcribe(AUDIO, params) {|text| + assert_match(/ask not what your country can do for you, ask what you can do for your country/, text) + } + end + + def test_whisper_pathname + @whisper = Whisper::Context.new("base.en") + params = Whisper::Params.new + + @whisper.transcribe(Pathname(AUDIO), params) {|text| + assert_match(/ask not what your country can do for you, ask what you can do for your country/, text) + } + end + + def test_transcribe_non_parallel + @whisper = Whisper::Context.new("base.en") + params = Whisper::Params.new + + @whisper.transcribe(AUDIO, params, n_processors: 1) {|text| + assert_match(/ask not what your country can do for you, ask what you can do for your country/, text) + } + end + + def test_transcribe_n_processors + @whisper = Whisper::Context.new("base.en") + params = Whisper::Params.new + + without_log_callback do + @whisper.transcribe(AUDIO, params, n_processors: 4) {|text| + assert_match(/what you can do for your country/i, text) + } + end + end + + def test_free + whisper = Whisper::Context.new("base.en") + whisper.free + + assert_raise RuntimeError do + whisper.model_type + end + end + + private + + def without_log_callback + Whisper.log_set nil, nil + yield + ensure + Whisper.log_set ->(level, buffer, user_data) {}, nil + end + + sub_test_case "After transcription" do + def test_full_n_segments + assert_equal 1, whisper.full_n_segments + end + + def test_full_lang_id + assert_equal 0, whisper.full_lang_id + end + + def test_full_get_segment + segment = whisper.full_get_segment(0) + assert_equal 0, segment.start_time + assert_match(/ask not what your country can do for you, ask what you can do for your country/, segment.text) + end + + def test_full_get_segment_t0 + assert_equal 0, whisper.full_get_segment_t0(0) + assert_raise IndexError do + whisper.full_get_segment_t0(whisper.full_n_segments) + end + assert_raise IndexError do + whisper.full_get_segment_t0(-1) + end + end + + def test_full_get_segment_t1 + t1 = whisper.full_get_segment_t1(0) + assert_kind_of Integer, t1 + assert t1 > 0 + assert_raise IndexError do + whisper.full_get_segment_t1(whisper.full_n_segments) + end + end + + def test_full_get_segment_speaker_turn_next + assert_false whisper.full_get_segment_speaker_turn_next(0) + end + + def test_full_get_segment_text + assert_match(/ask not what your country can do for you, ask what you can do for your country/, whisper.full_get_segment_text(0)) + end + + def test_full_get_segment_no_speech_prob + prob = whisper.full_get_segment_no_speech_prob(0) + assert prob > 0.0 + assert prob < 1.0 + end + end + + def test_lang_max_id + assert_kind_of Integer, Whisper.lang_max_id + end + + def test_lang_id + assert_equal 0, Whisper.lang_id("en") + assert_raise ArgumentError do + Whisper.lang_id("non existing language") + end + end + + def test_lang_str + assert_equal "en", Whisper.lang_str(0) + assert_raise IndexError do + Whisper.lang_str(Whisper.lang_max_id + 1) + end + end + + def test_lang_str_full + assert_equal "english", Whisper.lang_str_full(0) + assert_raise IndexError do + Whisper.lang_str_full(Whisper.lang_max_id + 1) + end + end + + def test_system_info_str + assert_match(/\AWHISPER : COREML = \d | OPENVINO = \d |/, Whisper.system_info_str) + end + + def test_version + assert_kind_of String, Whisper::VERSION + end + + def test_log_set + user_data = Object.new + logs = [] + log_callback = ->(level, buffer, udata) { + logs << [level, buffer, udata] + } + Whisper.log_set log_callback, user_data + Whisper::Context.new("base.en") + sleep 0.1 # wait for logs dequeued + + assert logs.length > 30 + logs.each do |log| + assert_include [Whisper::LOG_LEVEL_DEBUG, Whisper::LOG_LEVEL_INFO, Whisper::LOG_LEVEL_WARN], log[0] + assert_same user_data, log[2] + end + end + + def test_log_suppress + stderr = $stderr + Whisper.log_set ->(level, buffer, user_data) { + # do nothing + }, nil + dev = StringIO.new("") + $stderr = dev + Whisper::Context.new("base.en") + assert_empty dev.string + ensure + $stderr = stderr + end + + def test_access_attribute_without_initialization + whisper = Whisper::Context.allocate + assert_raise do + whisper.model_type + end + end + + sub_test_case "full" do + def setup + super + @whisper = Whisper::Context.new("base.en") + @samples = File.read(AUDIO, nil, 78).unpack("s<*").collect {|i| i.to_f / 2**15} + end + + def test_full + @whisper.full(@params, @samples, @samples.length) + + assert_equal 1, @whisper.full_n_segments + assert_match(/ask not what your country can do for you, ask what you can do for your country/, @whisper.each_segment.first.text) + end + + def test_full_without_length + @whisper.full(@params, @samples) + + assert_equal 1, @whisper.full_n_segments + assert_match(/ask not what your country can do for you, ask what you can do for your country/, @whisper.each_segment.first.text) + end + + def test_full_enumerator + samples = @samples.each + @whisper.full(@params, samples, @samples.length) + + assert_equal 1, @whisper.full_n_segments + assert_match(/ask not what your country can do for you, ask what you can do for your country/, @whisper.each_segment.first.text) + end + + def test_full_enumerator_without_length + samples = @samples.each + assert_raise ArgumentError do + @whisper.full(@params, samples) + end + end + + def test_full_enumerator_with_too_large_length + samples = @samples.each.take(10).to_enum + assert_raise StopIteration do + @whisper.full(@params, samples, 11) + end + end + + def test_full_with_memory_view + samples = JFKReader.new(AUDIO) + @whisper.full(@params, samples) + + assert_equal 1, @whisper.full_n_segments + assert_match(/ask not what your country can do for you, ask what you can do for your country/, @whisper.each_segment.first.text) + end + + def test_full_with_memroy_view_gc + samples = JFKReader.new(AUDIO) + @whisper.full(@params, samples) + GC.start + require "fiddle" + Fiddle::MemoryView.export samples do |view| + assert_equal 176000, view.to_s.unpack("#{view.format}*").length + end + end + + def test_full_parallel + nprocessors = 2 + without_log_callback do + @whisper.full_parallel(@params, @samples, @samples.length, nprocessors) + end + + assert_equal nprocessors, @whisper.full_n_segments + text = @whisper.each_segment.collect(&:text).join + assert_match(/ask what you can do/i, text) + assert_match(/for your country/i, text) + end + + def test_full_parallel_with_memory_view + nprocessors = 2 + samples = JFKReader.new(AUDIO) + without_log_callback do + @whisper.full_parallel(@params, samples, nil, nprocessors) + end + + assert_equal nprocessors, @whisper.full_n_segments + text = @whisper.each_segment.collect(&:text).join + assert_match(/ask what you can do/i, text) + assert_match(/for your country/i, text) + end + + def test_full_parallel_without_length_and_n_processors + @whisper.full_parallel(@params, @samples) + + assert_equal 1, @whisper.full_n_segments + text = @whisper.each_segment.collect(&:text).join + assert_match(/ask what you can do/i, text) + assert_match(/for your country/i, text) + end + + def test_full_parallel_without_length + nprocessors = 2 + without_log_callback do + @whisper.full_parallel(@params, @samples, nil, nprocessors) + end + + assert_equal nprocessors, @whisper.full_n_segments + text = @whisper.each_segment.collect(&:text).join + assert_match(/ask what you can do/i, text) + assert_match(/for your country/i, text) + end + + def test_full_parallel_without_n_processors + @whisper.full_parallel(@params, @samples, @samples.length) + + assert_equal 1, @whisper.full_n_segments + text = @whisper.each_segment.collect(&:text).join + assert_match(/ask what you can do/i, text) + assert_match(/for your country/i, text) + end + end + + def test_to_srt + whisper = Whisper::Context.new("base.en") + whisper.transcribe AUDIO, @params + + lines = whisper.to_srt.lines + assert_match(/\A\d+\n/, lines[0]) + assert_match(/\d{2}:\d{2}:\d{2},\d{3} --> \d{2}:\d{2}:\d{2},\d{3}\n/, lines[1]) + assert_match(/ask not what your country can do for you, ask what you can do for your country/, lines[2]) + end + + def test_to_webvtt + whisper = Whisper::Context.new("base.en") + whisper.transcribe AUDIO, @params + + lines = whisper.to_webvtt.lines + assert_equal "WEBVTT\n", lines[0] + assert_equal "\n", lines[1] + assert_match(/\A\d+\n/, lines[2]) + assert_match(/\d{2}:\d{2}:\d{2}\.\d{3} --> \d{2}:\d{2}:\d{2}\.\d{3}\n/, lines[3]) + assert_match(/ask not what your country can do for you, ask what you can do for your country/, lines[4]) + end + + sub_test_case "Format needs escape" do + def setup + @whisper = Whisper::Context.new("base.en") + @whisper.transcribe AUDIO, Whisper::Params.new + segment = @whisper.each_segment.first + segment.define_singleton_method :text do + "& so my fellow Americans --> ask not what your country can do for you <-- ask what you can do for your country." + end + @whisper.define_singleton_method :each_segment do + Enumerator.new(3) {|yielder| 3.times {yielder << segment}} + end + end + + def test_to_srt_escape + assert_equal "& so my fellow Americans --> ask not what your country can do for you <-- ask what you can do for your country.\n", @whisper.to_srt.lines[2] + end + + def test_to_webvtt_escape + assert_equal "& so my fellow Americans --> ask not what your country can do for you <-- ask what you can do for your country.\n", @whisper.to_webvtt.lines[4] + end + end +end diff --git a/bindings/ruby/whispercpp.gemspec b/bindings/ruby/whispercpp.gemspec new file mode 100644 index 0000000..e10521c --- /dev/null +++ b/bindings/ruby/whispercpp.gemspec @@ -0,0 +1,36 @@ +require_relative "extsources" + +Gem::Specification.new do |s| + s.name = "whispercpp" + s.authors = ["Georgi Gerganov", "Todd A. Fisher"] + s.version = '1.3.9' + s.description = %q{High-performance inference of OpenAI's Whisper automatic speech recognition (ASR) model via Ruby} + s.email = 'todd.fisher@gmail.com' + s.extra_rdoc_files = ['LICENSE', 'README.md'] + + s.files = `git ls-files . -z`.split("\x0") + + EXTSOURCES.collect {|file| + basename = File.basename(file) + if s.extra_rdoc_files.include?(basename) + basename + else + file.sub("../..", "ext/sources") + .sub("../javascript", "ext/sources/bindings/javascript") + end + } + + s.summary = %q{Ruby whisper.cpp bindings} + s.test_files = s.files.select {|file| file.start_with? "test/"} + + s.extensions << 'ext/extconf.rb' + s.required_ruby_version = '>= 3.3.0' + + #### Documentation and testing. + s.homepage = 'https://github.com/ggml-org/whisper.cpp' + s.rdoc_options = ['--main', 'README.md'] + + + s.platform = Gem::Platform::RUBY + + s.licenses = ['MIT'] +end diff --git a/build-xcframework.sh b/build-xcframework.sh new file mode 100755 index 0000000..e49de71 --- /dev/null +++ b/build-xcframework.sh @@ -0,0 +1,574 @@ +#!/bin/bash +# +# Options +IOS_MIN_OS_VERSION=16.4 +MACOS_MIN_OS_VERSION=13.3 +VISIONOS_MIN_OS_VERSION=1.0 +TVOS_MIN_OS_VERSION=16.4 + +BUILD_SHARED_LIBS=OFF +WHISPER_BUILD_EXAMPLES=OFF +WHISPER_BUILD_TESTS=OFF +WHISPER_BUILD_SERVER=OFF +GGML_METAL=ON +GGML_METAL_EMBED_LIBRARY=ON +GGML_BLAS_DEFAULT=ON +GGML_METAL_USE_BF16=ON +GGML_OPENMP=OFF +BUILD_STATIC_XCFRAMEWORK=${BUILD_STATIC_XCFRAMEWORK:-OFF} + +COMMON_C_FLAGS="-Wno-macro-redefined -Wno-shorten-64-to-32 -Wno-unused-command-line-argument -g" +COMMON_CXX_FLAGS="-Wno-macro-redefined -Wno-shorten-64-to-32 -Wno-unused-command-line-argument -g" + +# Common options for all builds +COMMON_CMAKE_ARGS=( + -DCMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED=NO + -DCMAKE_XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY="" + -DCMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED=NO + -DCMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT="dwarf-with-dsym" + -DCMAKE_XCODE_ATTRIBUTE_GCC_GENERATE_DEBUGGING_SYMBOLS=YES + -DCMAKE_XCODE_ATTRIBUTE_COPY_PHASE_STRIP=NO + -DCMAKE_XCODE_ATTRIBUTE_STRIP_INSTALLED_PRODUCT=NO + -DCMAKE_XCODE_ATTRIBUTE_DEVELOPMENT_TEAM=ggml + -DBUILD_SHARED_LIBS=${BUILD_SHARED_LIBS} + -DWHISPER_BUILD_EXAMPLES=${WHISPER_BUILD_EXAMPLES} + -DWHISPER_BUILD_TESTS=${WHISPER_BUILD_TESTS} + -DWHISPER_BUILD_SERVER=${WHISPER_BUILD_SERVER} + -DGGML_METAL_EMBED_LIBRARY=${GGML_METAL_EMBED_LIBRARY} + -DGGML_BLAS_DEFAULT=${GGML_BLAS_DEFAULT} + -DGGML_METAL=${GGML_METAL} + -DGGML_METAL_USE_BF16=${GGML_METAL_USE_BF16} + -DGGML_NATIVE=OFF + -DGGML_OPENMP=${GGML_OPENMP} +) + +XCODE_VERSION=$(xcodebuild -version 2>/dev/null | head -n1 | awk '{ print $2 }') +MAJOR_VERSION=$(echo $XCODE_VERSION | cut -d. -f1) +MINOR_VERSION=$(echo $XCODE_VERSION | cut -d. -f2) +echo "Detected Xcode version: $XCODE_VERSION" + +check_required_tool() { + local tool=$1 + local install_message=$2 + + if ! command -v $tool &> /dev/null; then + echo "Error: $tool is required but not found." + echo "$install_message" + exit 1 + fi +} +echo "Checking for required tools..." +check_required_tool "cmake" "Please install CMake 3.28.0 or later (brew install cmake)" +check_required_tool "xcodebuild" "Please install Xcode and Xcode Command Line Tools (xcode-select --install)" +check_required_tool "libtool" "Please install libtool which should be available with Xcode Command Line Tools (CLT). Make sure Xcode CLT is installed (xcode-select --install)" +check_required_tool "dsymutil" "Please install Xcode and Xcode Command Line Tools (xcode-select --install)" + +set -e + +## Clean up previous builds +rm -rf build-apple +rm -rf build-ios-sim +rm -rf build-ios-device +rm -rf build-macos +rm -rf build-visionos +rm -rf build-visionos-sim +rm -rf build-tvos-sim +rm -rf build-tvos-device + +# Setup the xcframework build directory structure +setup_framework_structure() { + local build_dir=$1 + local min_os_version=$2 + local platform=$3 # "ios", "macos", "visionos", or "tvos" + local framework_name="whisper" + + echo "Creating ${platform}-style framework structure for ${build_dir}" + + if [[ "$platform" == "macos" ]]; then + # macOS versioned structure uses versioned directories + mkdir -p ${build_dir}/framework/${framework_name}.framework/Versions/A/Headers + mkdir -p ${build_dir}/framework/${framework_name}.framework/Versions/A/Modules + mkdir -p ${build_dir}/framework/${framework_name}.framework/Versions/A/Resources + + # Create symbolic links + ln -sf A ${build_dir}/framework/${framework_name}.framework/Versions/Current + ln -sf Versions/Current/Headers ${build_dir}/framework/${framework_name}.framework/Headers + ln -sf Versions/Current/Modules ${build_dir}/framework/${framework_name}.framework/Modules + ln -sf Versions/Current/Resources ${build_dir}/framework/${framework_name}.framework/Resources + ln -sf Versions/Current/${framework_name} ${build_dir}/framework/${framework_name}.framework/${framework_name} + + # Set header and module paths + local header_path=${build_dir}/framework/${framework_name}.framework/Versions/A/Headers/ + local module_path=${build_dir}/framework/${framework_name}.framework/Versions/A/Modules/ + else + # iOS/VisionOS/tvOS use a flat structure + mkdir -p ${build_dir}/framework/${framework_name}.framework/Headers + mkdir -p ${build_dir}/framework/${framework_name}.framework/Modules + + # Remove any existing structure to ensure clean build + rm -rf ${build_dir}/framework/${framework_name}.framework/Versions + + # Set header and module paths + local header_path=${build_dir}/framework/${framework_name}.framework/Headers/ + local module_path=${build_dir}/framework/${framework_name}.framework/Modules/ + fi + + # Copy all required headers (common for all platforms) + cp include/whisper.h ${header_path} + cp include/parakeet.h ${header_path} + cp ggml/include/ggml.h ${header_path} + cp ggml/include/ggml-alloc.h ${header_path} + cp ggml/include/ggml-backend.h ${header_path} + cp ggml/include/ggml-metal.h ${header_path} + cp ggml/include/ggml-cpu.h ${header_path} + cp ggml/include/ggml-blas.h ${header_path} + cp ggml/include/gguf.h ${header_path} + + # Create module map (common for all platforms) + cat > ${module_path}module.modulemap << EOF +framework module whisper { + header "whisper.h" + header "parakeet.h" + header "ggml.h" + header "ggml-alloc.h" + header "ggml-backend.h" + header "ggml-metal.h" + header "ggml-cpu.h" + header "ggml-blas.h" + header "gguf.h" + + link "c++" + link framework "Accelerate" + link framework "Metal" + link framework "Foundation" + + export * +} +EOF + + # Platform-specific settings for Info.plist + local platform_name="" + local sdk_name="" + local supported_platform="" + + case "$platform" in + "ios") + platform_name="iphoneos" + sdk_name="iphoneos${min_os_version}" + supported_platform="iPhoneOS" + local plist_path="${build_dir}/framework/${framework_name}.framework/Info.plist" + local device_family=' <key>UIDeviceFamily</key> + <array> + <integer>1</integer> + <integer>2</integer> + </array>' + ;; + "macos") + platform_name="macosx" + sdk_name="macosx${min_os_version}" + supported_platform="MacOSX" + local plist_path="${build_dir}/framework/${framework_name}.framework/Versions/A/Resources/Info.plist" + local device_family="" + ;; + "visionos") + platform_name="xros" + sdk_name="xros${min_os_version}" + supported_platform="XRPlatform" + local plist_path="${build_dir}/framework/${framework_name}.framework/Info.plist" + local device_family="" + ;; + "tvos") + platform_name="appletvos" + sdk_name="appletvos${min_os_version}" + supported_platform="AppleTVOS" + local plist_path="${build_dir}/framework/${framework_name}.framework/Info.plist" + local device_family=' <key>UIDeviceFamily</key> + <array> + <integer>3</integer> + </array>' + ;; + esac + + # Create Info.plist + cat > ${plist_path} << EOF +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>en</string> + <key>CFBundleExecutable</key> + <string>whisper</string> + <key>CFBundleIdentifier</key> + <string>org.ggml.whisper</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>whisper</string> + <key>CFBundlePackageType</key> + <string>FMWK</string> + <key>CFBundleShortVersionString</key> + <string>1.0</string> + <key>CFBundleVersion</key> + <string>1</string> + <key>MinimumOSVersion</key> + <string>${min_os_version}</string> + <key>CFBundleSupportedPlatforms</key> + <array> + <string>${supported_platform}</string> + </array>${device_family} + <key>DTPlatformName</key> + <string>${platform_name}</string> + <key>DTSDKName</key> + <string>${sdk_name}</string> +</dict> +</plist> +EOF +} + +# Create dynamic libraries from static libraries. +combine_static_libraries() { + local build_dir="$1" + local release_dir="$2" + local platform="$3" # "ios", "macos", "visionos", or "tvos" + local is_simulator="$4" + local base_dir="$(pwd)" + local framework_name="whisper" + + # Determine output path based on platform + local output_lib="" + if [[ "$platform" == "macos" ]]; then + # macOS uses versioned structure + output_lib="${build_dir}/framework/${framework_name}.framework/Versions/A/${framework_name}" + else + # iOS, visionOS, and tvOS use a directory flat structure + output_lib="${build_dir}/framework/${framework_name}.framework/${framework_name}" + fi + + local libs=( + "${base_dir}/${build_dir}/src/${release_dir}/libwhisper.a" + "${base_dir}/${build_dir}/src/${release_dir}/libparakeet.a" + "${base_dir}/${build_dir}/ggml/src/${release_dir}/libggml.a" + "${base_dir}/${build_dir}/ggml/src/${release_dir}/libggml-base.a" + "${base_dir}/${build_dir}/ggml/src/${release_dir}/libggml-cpu.a" + "${base_dir}/${build_dir}/ggml/src/ggml-metal/${release_dir}/libggml-metal.a" + "${base_dir}/${build_dir}/ggml/src/ggml-blas/${release_dir}/libggml-blas.a" + ) + if [[ "$platform" == "macos" || "$platform" == "ios" ]]; then + echo "Adding libwhisper.coreml library to the build." + libs+=( + "${base_dir}/${build_dir}/src/${release_dir}/libwhisper.coreml.a" + ) + fi + + # Create temporary directory for processing + local temp_dir="${base_dir}/${build_dir}/temp" + echo "Creating temporary directory: ${temp_dir}" + mkdir -p "${temp_dir}" + + # Since we have multiple architectures libtool will find object files that do not + # match the target architecture. We suppress these warnings. + libtool -static -o "${temp_dir}/combined.a" "${libs[@]}" 2> /dev/null + + # Determine SDK, architectures, and install_name based on platform and simulator flag. + local sdk="" + local archs="" + local min_version_flag="" + local install_name="" + local frameworks="-framework Foundation -framework Metal -framework Accelerate" + + case "$platform" in + "ios") + if [[ "$is_simulator" == "true" ]]; then + sdk="iphonesimulator" + archs="arm64 x86_64" + min_version_flag="-mios-simulator-version-min=${IOS_MIN_OS_VERSION}" + else + sdk="iphoneos" + archs="arm64" + min_version_flag="-mios-version-min=${IOS_MIN_OS_VERSION}" + fi + install_name="@rpath/whisper.framework/whisper" + frameworks+=" -framework CoreML" + ;; + "macos") + sdk="macosx" + archs="arm64 x86_64" + min_version_flag="-mmacosx-version-min=${MACOS_MIN_OS_VERSION}" + install_name="@rpath/whisper.framework/Versions/Current/whisper" + frameworks+=" -framework CoreML" + ;; + "visionos") + if [[ "$is_simulator" == "true" ]]; then + sdk="xrsimulator" + archs="arm64 x86_64" + min_version_flag="-mtargetos=xros${VISIONOS_MIN_OS_VERSION}-simulator" + else + sdk="xros" + archs="arm64" + min_version_flag="-mtargetos=xros${VISIONOS_MIN_OS_VERSION}" + fi + # Use flat structure for visionOS, same as iOS + install_name="@rpath/whisper.framework/whisper" + ;; + "tvos") + if [[ "$is_simulator" == "true" ]]; then + sdk="appletvsimulator" + archs="arm64 x86_64" + min_version_flag="-mtvos-simulator-version-min=${TVOS_MIN_OS_VERSION}" + else + sdk="appletvos" + archs="arm64" + min_version_flag="-mtvos-version-min=${TVOS_MIN_OS_VERSION}" + fi + install_name="@rpath/whisper.framework/whisper" + ;; + esac + + # Build architecture flags + local arch_flags="" + for arch in $archs; do + arch_flags+=" -arch $arch" + done + + + if [[ "${BUILD_STATIC_XCFRAMEWORK}" == "ON" ]]; then + echo "Packaging static framework for ${platform}." + mkdir -p "$(dirname "${base_dir}/${output_lib}")" + cp "${temp_dir}/combined.a" "${base_dir}/${output_lib}" + rm -rf "${temp_dir}" + return + fi + + # Create dynamic library + echo "Creating dynamic library for ${platform}." + xcrun -sdk $sdk clang++ -dynamiclib \ + -isysroot $(xcrun --sdk $sdk --show-sdk-path) \ + $arch_flags \ + $min_version_flag \ + -Wl,-force_load,"${temp_dir}/combined.a" \ + $frameworks \ + -install_name "$install_name" \ + -o "${base_dir}/${output_lib}" + + # Platform-specific post-processing for device builds + if [[ "$is_simulator" == "false" ]]; then + if command -v xcrun vtool &>/dev/null; then + case "$platform" in + "ios") + echo "Marking binary as a framework binary for iOS..." + xcrun vtool -set-build-version ios ${IOS_MIN_OS_VERSION} ${IOS_MIN_OS_VERSION} -replace \ + -output "${base_dir}/${output_lib}" "${base_dir}/${output_lib}" + ;; + "visionos") + echo "Marking binary as a framework binary for visionOS..." + if [[ "$MAJOR_VERSION" -gt 16 ]] || [[ "$MAJOR_VERSION" -eq 16 && "$MINOR_VERSION" -gt 2 ]]; then + echo "Xcode version greater than 16.2, using visionOS." + VISION_OS_BUILD_VERSION="visionos" + else + echo "Xcode version less than or equal to 16.2, using xros." + VISION_OS_BUILD_VERSION="xros" + fi + xcrun vtool -set-build-version ${VISION_OS_BUILD_VERSION} ${VISIONOS_MIN_OS_VERSION} ${VISIONOS_MIN_OS_VERSION} -replace \ + -output "${base_dir}/${output_lib}" "${base_dir}/${output_lib}" + ;; + "tvos") + echo "Marking binary as a framework binary for tvOS..." + xcrun vtool -set-build-version tvos ${TVOS_MIN_OS_VERSION} ${TVOS_MIN_OS_VERSION} -replace \ + -output "${base_dir}/${output_lib}" "${base_dir}/${output_lib}" + ;; + esac + else + echo "Warning: vtool not found. Binary may not pass App Store validation." + fi + fi + + echo "Creating properly formatted dSYM..." + # Create a separate directory for dSYMs for all platforms + mkdir -p "${base_dir}/${build_dir}/dSYMs" + + # iOS and visionOS style dSYM (flat structure) + if [[ "$platform" == "ios" || "$platform" == "visionos" || "$platform" == "tvos" ]]; then + # Generate dSYM in the dSYMs directory + xcrun dsymutil "${base_dir}/${output_lib}" -o "${base_dir}/${build_dir}/dSYMs/whisper.dSYM" + + # Create a copy of the binary that will be stripped + cp "${base_dir}/${output_lib}" "${temp_dir}/binary_to_strip" + + # Strip debug symbols from the copy + xcrun strip -S "${temp_dir}/binary_to_strip" -o "${temp_dir}/stripped_lib" + + # Replace the original with the stripped version + mv "${temp_dir}/stripped_lib" "${base_dir}/${output_lib}" + else + # macOS style dSYM + # First strip debug info to a separate file + xcrun strip -S "${base_dir}/${output_lib}" -o "${temp_dir}/stripped_lib" + + # Generate dSYM in the dSYMs directory + xcrun dsymutil "${base_dir}/${output_lib}" -o "${base_dir}/${build_dir}/dSYMs/whisper.dSYM" + + # Replace original binary with stripped version + mv "${temp_dir}/stripped_lib" "${base_dir}/${output_lib}" + fi + + # Remove any automatically generated dSYM files in the framework structure as they will + # otherwise case Invalid Bundle Structure validation errors. + if [ -d "${base_dir}/${output_lib}.dSYM" ]; then + echo "Removing generated dSYM file in framework structure: ${base_dir}/${output_lib}.dSYM" + rm -rf "${base_dir}/${output_lib}.dSYM" + fi + + # Clean up + rm -rf "${temp_dir}" +} + +echo "Building for iOS simulator..." +cmake -B build-ios-sim -G Xcode \ + "${COMMON_CMAKE_ARGS[@]}" \ + -DCMAKE_OSX_DEPLOYMENT_TARGET=${IOS_MIN_OS_VERSION} \ + -DIOS=ON \ + -DCMAKE_SYSTEM_NAME=iOS \ + -DCMAKE_OSX_SYSROOT=iphonesimulator \ + -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" \ + -DCMAKE_XCODE_ATTRIBUTE_SUPPORTED_PLATFORMS=iphonesimulator \ + -DCMAKE_C_FLAGS="${COMMON_C_FLAGS}" \ + -DCMAKE_CXX_FLAGS="${COMMON_CXX_FLAGS}" \ + -DWHISPER_COREML="ON" \ + -DWHISPER_COREML_ALLOW_FALLBACK="ON" \ + -S . +cmake --build build-ios-sim --config Release -- -quiet + +echo "Building for iOS devices..." +cmake -B build-ios-device -G Xcode \ + "${COMMON_CMAKE_ARGS[@]}" \ + -DCMAKE_OSX_DEPLOYMENT_TARGET=${IOS_MIN_OS_VERSION} \ + -DCMAKE_OSX_SYSROOT=iphoneos \ + -DCMAKE_OSX_ARCHITECTURES="arm64" \ + -DCMAKE_XCODE_ATTRIBUTE_SUPPORTED_PLATFORMS=iphoneos \ + -DCMAKE_C_FLAGS="${COMMON_C_FLAGS}" \ + -DCMAKE_CXX_FLAGS="${COMMON_CXX_FLAGS}" \ + -DWHISPER_COREML="ON" \ + -DWHISPER_COREML_ALLOW_FALLBACK="ON" \ + -S . +cmake --build build-ios-device --config Release -- -quiet + +echo "Building for macOS..." +cmake -B build-macos -G Xcode \ + "${COMMON_CMAKE_ARGS[@]}" \ + -DCMAKE_OSX_DEPLOYMENT_TARGET=${MACOS_MIN_OS_VERSION} \ + -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" \ + -DCMAKE_C_FLAGS="${COMMON_C_FLAGS}" \ + -DCMAKE_CXX_FLAGS="${COMMON_CXX_FLAGS}" \ + -DWHISPER_COREML="ON" \ + -DWHISPER_COREML_ALLOW_FALLBACK="ON" \ + -S . +cmake --build build-macos --config Release -- -quiet + +echo "Building for visionOS..." +cmake -B build-visionos -G Xcode \ + "${COMMON_CMAKE_ARGS[@]}" \ + -DCMAKE_OSX_DEPLOYMENT_TARGET=${VISIONOS_MIN_OS_VERSION} \ + -DCMAKE_OSX_ARCHITECTURES="arm64" \ + -DCMAKE_SYSTEM_NAME=visionOS \ + -DCMAKE_OSX_SYSROOT=xros \ + -DCMAKE_XCODE_ATTRIBUTE_SUPPORTED_PLATFORMS=xros \ + -DCMAKE_C_FLAGS="-D_XOPEN_SOURCE=700 ${COMMON_C_FLAGS}" \ + -DCMAKE_CXX_FLAGS="-D_XOPEN_SOURCE=700 ${COMMON_CXX_FLAGS}" \ + -S . +cmake --build build-visionos --config Release -- -quiet + +echo "Building for visionOS simulator..." +cmake -B build-visionos-sim -G Xcode \ + "${COMMON_CMAKE_ARGS[@]}" \ + -DCMAKE_OSX_DEPLOYMENT_TARGET=${VISIONOS_MIN_OS_VERSION} \ + -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" \ + -DCMAKE_SYSTEM_NAME=visionOS \ + -DCMAKE_OSX_SYSROOT=xrsimulator \ + -DCMAKE_XCODE_ATTRIBUTE_SUPPORTED_PLATFORMS=xrsimulator \ + -DCMAKE_C_FLAGS="-D_XOPEN_SOURCE=700 ${COMMON_C_FLAGS}" \ + -DCMAKE_CXX_FLAGS="-D_XOPEN_SOURCE=700 ${COMMON_CXX_FLAGS}" \ + -S . +cmake --build build-visionos-sim --config Release -- -quiet + +# Add tvOS builds (might need the same u_int definitions as watchOS and visionOS) +echo "Building for tvOS simulator..." +cmake -B build-tvos-sim -G Xcode \ + "${COMMON_CMAKE_ARGS[@]}" \ + -DCMAKE_OSX_DEPLOYMENT_TARGET=${TVOS_MIN_OS_VERSION} \ + -DCMAKE_SYSTEM_NAME=tvOS \ + -DCMAKE_OSX_SYSROOT=appletvsimulator \ + -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" \ + -DGGML_METAL=ON \ + -DCMAKE_XCODE_ATTRIBUTE_SUPPORTED_PLATFORMS=appletvsimulator \ + -DCMAKE_C_FLAGS="${COMMON_C_FLAGS}" \ + -DCMAKE_CXX_FLAGS="${COMMON_CXX_FLAGS}" \ + -S . +cmake --build build-tvos-sim --config Release -- -quiet + +echo "Building for tvOS devices..." +cmake -B build-tvos-device -G Xcode \ + "${COMMON_CMAKE_ARGS[@]}" \ + -DCMAKE_OSX_DEPLOYMENT_TARGET=${TVOS_MIN_OS_VERSION} \ + -DCMAKE_SYSTEM_NAME=tvOS \ + -DCMAKE_OSX_SYSROOT=appletvos \ + -DCMAKE_OSX_ARCHITECTURES="arm64" \ + -DGGML_METAL=ON \ + -DCMAKE_XCODE_ATTRIBUTE_SUPPORTED_PLATFORMS=appletvos \ + -DCMAKE_C_FLAGS="${COMMON_C_FLAGS}" \ + -DCMAKE_CXX_FLAGS="${COMMON_CXX_FLAGS}" \ + -S . +cmake --build build-tvos-device --config Release -- -quiet + +# Setup frameworks and copy binaries and headers +echo "Setting up framework structures..." +setup_framework_structure "build-ios-sim" ${IOS_MIN_OS_VERSION} "ios" +setup_framework_structure "build-ios-device" ${IOS_MIN_OS_VERSION} "ios" +setup_framework_structure "build-macos" ${MACOS_MIN_OS_VERSION} "macos" +setup_framework_structure "build-visionos" ${VISIONOS_MIN_OS_VERSION} "visionos" +setup_framework_structure "build-visionos-sim" ${VISIONOS_MIN_OS_VERSION} "visionos" +setup_framework_structure "build-tvos-sim" ${TVOS_MIN_OS_VERSION} "tvos" +setup_framework_structure "build-tvos-device" ${TVOS_MIN_OS_VERSION} "tvos" + +# Create dynamic libraries from static libraries +echo "Creating dynamic libraries from static libraries..." +combine_static_libraries "build-ios-sim" "Release-iphonesimulator" "ios" "true" +combine_static_libraries "build-ios-device" "Release-iphoneos" "ios" "false" +combine_static_libraries "build-macos" "Release" "macos" "false" +combine_static_libraries "build-visionos" "Release-xros" "visionos" "false" +combine_static_libraries "build-visionos-sim" "Release-xrsimulator" "visionos" "true" +combine_static_libraries "build-tvos-sim" "Release-appletvsimulator" "tvos" "true" +combine_static_libraries "build-tvos-device" "Release-appletvos" "tvos" "false" + +# Create XCFramework with correct debug symbols paths +echo "Creating XCFramework..." + +if [[ "${BUILD_STATIC_XCFRAMEWORK}" == "ON" ]]; then + xcodebuild -create-xcframework \ + -framework $(pwd)/build-ios-sim/framework/whisper.framework \ + -framework $(pwd)/build-ios-device/framework/whisper.framework \ + -framework $(pwd)/build-macos/framework/whisper.framework \ + -framework $(pwd)/build-visionos/framework/whisper.framework \ + -framework $(pwd)/build-visionos-sim/framework/whisper.framework \ + -framework $(pwd)/build-tvos-device/framework/whisper.framework \ + -framework $(pwd)/build-tvos-sim/framework/whisper.framework \ + -output $(pwd)/build-apple/whisper.xcframework + exit 0 +fi + +xcodebuild -create-xcframework \ + -framework $(pwd)/build-ios-sim/framework/whisper.framework \ + -debug-symbols $(pwd)/build-ios-sim/dSYMs/whisper.dSYM \ + -framework $(pwd)/build-ios-device/framework/whisper.framework \ + -debug-symbols $(pwd)/build-ios-device/dSYMs/whisper.dSYM \ + -framework $(pwd)/build-macos/framework/whisper.framework \ + -debug-symbols $(pwd)/build-macos/dSYMs/whisper.dSYM \ + -framework $(pwd)/build-visionos/framework/whisper.framework \ + -debug-symbols $(pwd)/build-visionos/dSYMs/whisper.dSYM \ + -framework $(pwd)/build-visionos-sim/framework/whisper.framework \ + -debug-symbols $(pwd)/build-visionos-sim/dSYMs/whisper.dSYM \ + -framework $(pwd)/build-tvos-device/framework/whisper.framework \ + -debug-symbols $(pwd)/build-tvos-device/dSYMs/whisper.dSYM \ + -framework $(pwd)/build-tvos-sim/framework/whisper.framework \ + -debug-symbols $(pwd)/build-tvos-sim/dSYMs/whisper.dSYM \ + -output $(pwd)/build-apple/whisper.xcframework diff --git a/ci/README.md b/ci/README.md new file mode 100644 index 0000000..63df4aa --- /dev/null +++ b/ci/README.md @@ -0,0 +1,41 @@ +# CI + +In addition to [Github Actions](https://github.com/ggerganov/whisper.cpp/actions) `whisper.cpp` uses a custom CI framework: + +https://github.com/ggml-org/ci + +It monitors the `master` branch for new commits and runs the +[ci/run.sh](https://github.com/ggerganov/whisper.cpp/blob/master/ci/run.sh) script on dedicated cloud instances. This allows us +to execute heavier workloads compared to just using Github Actions. Also with time, the cloud instances will be scaled +to cover various hardware architectures, including GPU and Apple Silicon instances. + +Collaborators can optionally trigger the CI run by adding the `ggml-ci` keyword to their commit message. +Only the branches of this repo are monitored for this keyword. + +It is a good practice, before publishing changes to execute the full CI locally on your machine: + +```bash +mkdir tmp + +# CPU-only build +bash ./ci/run.sh ./tmp/results ./tmp/mnt + +# with CUDA support +GG_BUILD_CUDA=1 bash ./ci/run.sh ./tmp/results ./tmp/mnt +``` + +## Environment Variables + +The CI script supports several environment variables to control the build: + +| Variable | Description | +|----------|-------------| +| `GG_BUILD_CUDA` | Enable NVIDIA CUDA GPU acceleration | +| `GG_BUILD_SYCL` | Enable Intel SYCL acceleration | +| `GG_BUILD_VULKAN` | Enable Vulkan GPU acceleration | +| `GG_BUILD_METAL` | Enable Metal acceleration on Apple Silicon | +| `GG_BUILD_BLAS` | Enable BLAS CPU acceleration | +| `GG_BUILD_OPENVINO` | Enable OpenVINO support | +| `GG_BUILD_COREML` | Enable Core ML support for Apple Neural Engine | +| `GG_BUILD_LOW_PERF` | Limit tests for low-performance hardware | +| `GG_BUILD_TEST_MODELS` | Comma-separated list of models to test (e.g. "tiny.en,tiny,base,medium", defaults to all models unless `GG_BUILD_LOW_PERF` is set) | diff --git a/ci/ruleset-nightly.json b/ci/ruleset-nightly.json new file mode 100644 index 0000000..87e68b0 --- /dev/null +++ b/ci/ruleset-nightly.json @@ -0,0 +1,26 @@ +{ + "name": "releases-nightly", + "target": "tag", + "enforcement": "active", + "bypass_actors": [ + { + "actor_id": null, + "actor_type": "DeployKey", + "bypass_mode": "always" + } + ], + "conditions": { + "ref_name": { + "include": [ + "refs/tags/b*" + ], + "exclude": [] + } + }, + "rules": [ + { "type": "deletion" }, + { "type": "non_fast_forward" }, + { "type": "update" }, + { "type": "creation" } + ] +} diff --git a/ci/ruleset-official.json b/ci/ruleset-official.json new file mode 100644 index 0000000..b94280a --- /dev/null +++ b/ci/ruleset-official.json @@ -0,0 +1,39 @@ +{ + "name": "releases-official", + "target": "tag", + "enforcement": "active", + "bypass_actors": [ + { + "actor_id": null, + "actor_type": "DeployKey", + "bypass_mode": "always" + } + ], + "conditions": { + "ref_name": { + "include": [ + "refs/tags/v*" + ], + "exclude": [] + } + }, + "rules": [ + { "type": "deletion" }, + { "type": "non_fast_forward" }, + { + "type": "required_status_checks", + "parameters": { + "strict_required_status_checks_policy": false, + "do_not_enforce_on_create": false, + "required_status_checks": [ + { + "context": "release", + "integration_id": 15368 + } + ] + } + }, + { "type": "update" }, + { "type": "creation" } + ] +} diff --git a/ci/run.sh b/ci/run.sh new file mode 100644 index 0000000..dca4476 --- /dev/null +++ b/ci/run.sh @@ -0,0 +1,390 @@ +#!/bin/bash +# +# sample usage: +# +# mkdir tmp +# +# # CPU-only build +# bash ./ci/run.sh ./tmp/results ./tmp/mnt +# +# # with CUDA support +# GG_BUILD_CUDA=1 bash ./ci/run.sh ./tmp/results ./tmp/mnt +# +# # with SYCL support +# GG_BUILD_SYCL=1 bash ./ci/run.sh ./tmp/results ./tmp/mnt + +if [ -z "$2" ]; then + echo "usage: $0 <output-dir> <mnt-dir>" + exit 1 +fi + +mkdir -p "$1" +mkdir -p "$2" + +OUT=$(realpath "$1") +MNT=$(realpath "$2") + +rm -vf $OUT/*.log +rm -vf $OUT/*.exit +rm -vf $OUT/*.md + +sd=`dirname $0` +cd $sd/../ +SRC=`pwd` + +ALL_MODELS=( "tiny.en" "tiny" "base.en" "base" "small.en" "small" "medium.en" "medium" "large-v1" "large-v2" "large-v3" "large-v3-turbo" ) +BENCH_N_THREADS=4 +BENCH_ENCODER_ONLY=0 +BENCH_FLASH_ATTN=0 + +# check for user-specified models first. if not specified, use fast models +if [ ! -z ${GG_BUILD_TEST_MODELS} ]; then + IFS=',' read -r -a MODELS <<< "${GG_BUILD_TEST_MODELS}" +else + if [ ! -z ${GG_BUILD_LOW_PERF} ]; then + MODELS=( "tiny" "base" "small" ) + else + MODELS=("${ALL_MODELS[@]}") + fi +fi + +CMAKE_EXTRA="-DWHISPER_FATAL_WARNINGS=ON" + +if [[ "$(uname -m)" == "x86_64" ]]; then + CMAKE_EXTRA="${CMAKE_EXTRA} -DGGML_NATIVE=OFF" +fi + +if [ ! -z ${GG_BUILD_METAL} ]; then + CMAKE_EXTRA="${CMAKE_EXTRA} -DGGML_METAL=ON" +fi + +if [ ! -z ${GG_BUILD_CUDA} ]; then + CMAKE_EXTRA="${CMAKE_EXTRA} -DGGML_CUDA=ON" + + if command -v nvidia-smi >/dev/null 2>&1; then + CUDA_ARCH=$(nvidia-smi --query-gpu=compute_cap --format=csv,noheader,nounits 2>/dev/null | head -1 | tr -d '.') + if [[ -n "$CUDA_ARCH" && "$CUDA_ARCH" =~ ^[0-9]+$ ]]; then + CMAKE_EXTRA="${CMAKE_EXTRA} -DCMAKE_CUDA_ARCHITECTURES=${CUDA_ARCH}" + else + echo "Warning: Using fallback CUDA architectures" + CMAKE_EXTRA="${CMAKE_EXTRA} -DCMAKE_CUDA_ARCHITECTURES=61;70;75;80;86;89" + fi + else + echo "Error: nvidia-smi not found, cannot build with CUDA" + exit 1 + fi +fi + +if [ ! -z ${GG_BUILD_ROCM} ]; then + CMAKE_EXTRA="${CMAKE_EXTRA} -DGGML_HIP=ON" + if [ -z ${GG_BUILD_AMDGPU_TARGETS} ]; then + echo "Missing GG_BUILD_AMDGPU_TARGETS, please set it to your GPU architecture (e.g. gfx90a, gfx1100, etc.)" + exit 1 + fi + + CMAKE_EXTRA="${CMAKE_EXTRA} -DAMDGPU_TARGETS=${GG_BUILD_AMDGPU_TARGETS}" +fi + +if [ ! -z ${GG_BUILD_SYCL} ]; then + if [ -z ${ONEAPI_ROOT} ]; then + echo "Not detected ONEAPI_ROOT, please install oneAPI base toolkit and enable it by:" + echo "source /opt/intel/oneapi/setvars.sh" + exit 1 + fi + # Use only main GPU + export ONEAPI_DEVICE_SELECTOR="level_zero:0" + # Enable sysman for correct memory reporting + export ZES_ENABLE_SYSMAN=1 + # to circumvent precision issues on CPY operations + export SYCL_PROGRAM_COMPILE_OPTIONS="-cl-fp32-correctly-rounded-divide-sqrt" + CMAKE_EXTRA="${CMAKE_EXTRA} -DGGML_SYCL=1 -DCMAKE_C_COMPILER=icx -DCMAKE_CXX_COMPILER=icpx -DGGML_SYCL_F16=ON" +fi + +if [ ! -z ${GG_BUILD_VULKAN} ]; then + CMAKE_EXTRA="${CMAKE_EXTRA} -DGGML_VULKAN=1" + + # if on Mac, disable METAL + if [[ "$OSTYPE" == "darwin"* ]]; then + CMAKE_EXTRA="${CMAKE_EXTRA} -DGGML_METAL=OFF -DGGML_BLAS=OFF" + fi + +fi + +if [ ! -z ${GG_BUILD_WEBGPU} ]; then + CMAKE_EXTRA="${CMAKE_EXTRA} -DGGML_WEBGPU=1" +fi + +if [ ! -z ${GG_BUILD_MUSA} ]; then + # Use qy1 by default (MTT S80) + MUSA_ARCH=${MUSA_ARCH:-21} + CMAKE_EXTRA="${CMAKE_EXTRA} -DGGML_MUSA=ON -DMUSA_ARCHITECTURES=${MUSA_ARCH}" +fi + +if [ ! -z ${GG_BUILD_NO_SVE} ]; then + # arm 9 and newer enables sve by default, adjust these flags depending on the cpu used + CMAKE_EXTRA="${CMAKE_EXTRA} -DGGML_NATIVE=OFF -DGGML_CPU_ARM_ARCH=armv8.5-a+fp16+i8mm" +fi + +## helpers + +# download a file if it does not exist or if it is outdated +function gg_wget { + local out=$1 + local url=$2 + + local cwd=`pwd` + + mkdir -p $out + cd $out + + # should not re-download if file is the same + wget -nv -N $url + + cd $cwd +} + +function gg_download_model { + local model_name=$1 + local model_file="$MNT/models/ggml-${model_name}.bin" + + if [ ! -f ${model_file} ]; then + local cwd=`pwd` + mkdir -p "$MNT/models" + cd "$MNT/models" + set -x + bash "$cwd/models/download-ggml-model.sh" ${model_name} . + local download_status=$? + set +x + cd "$cwd" + if [ $download_status -ne 0 ]; then + echo "Error: failed to download model ${model_name}" + ret=1 + fi + fi +} + +function gg_printf { + printf -- "$@" >> $OUT/README.md +} + +# Helper function to check command exit status +function gg_check_last_command_status { + local exit_file=$1 + local command_name=$2 + + local exit_status=$? + echo "$exit_status" > "$exit_file" + + if [ $exit_status -ne 0 ]; then + echo "Error: Command $command_name failed with exit status $exit_status" + return 1 + fi + + return 0 +} + +# Usage: gg_run <test_name> [additional_args...] +# +# Parameters: +# test_name - Name of the test to run (calls gg_run_<test_name>) +# additional_args - Any additional arguments to pass to the test function (first argument is appended to the log filename) +function gg_run { + ci=$1 + + if [ $# -gt 1 ]; then + ci="${ci}_${2}" + fi + + set -o pipefail + set -x + + gg_run_$1 "$@" | tee $OUT/$ci.log + cur=$? + echo "$cur" > $OUT/$ci.exit + + set +x + set +o pipefail + + gg_sum_$1 "$@" + + ret=$((ret | cur)) +} + +function gg_check_build_requirements { + if ! command -v cmake &> /dev/null; then + gg_printf 'cmake not found, please install' + fi + + if ! command -v make &> /dev/null; then + gg_printf 'make not found, please install' + fi +} + +## ci + +function gg_run_ctest { + mode=$2 + + cd ${SRC} + + rm -rf build-ci-${mode} && mkdir build-ci-${mode} && cd build-ci-${mode} + + set -e + + gg_check_build_requirements + + (time cmake -DCMAKE_BUILD_TYPE=${mode} ${CMAKE_EXTRA} .. ) 2>&1 | tee -a $OUT/${ci}-cmake.log + (time make -j$(nproc) ) 2>&1 | tee -a $OUT/${ci}-make.log + + (time ctest --output-on-failure -L main -E test-opt ) 2>&1 | tee -a $OUT/${ci}-ctest.log + + set +e +} + +function gg_sum_ctest { + mode=$2 + + gg_printf '### %s\n\n' "${ci}" + + gg_printf 'Runs ctest in '${mode}' mode\n' + gg_printf '- status: %s\n' "$(cat $OUT/${ci}.exit)" + gg_printf '```\n' + gg_printf '%s\n' "$(cat $OUT/${ci}-ctest.log)" + gg_printf '```\n' +} + +function gg_run_bench { + cd ${SRC} + + # set flash attention flag if enabled + fattn="-nfa" + if [ "$BENCH_FLASH_ATTN" -eq 1 ]; then + fattn="-fa" + fi + + # run memcpy benchmark if not encoder-only mode + if [ "$BENCH_ENCODER_ONLY" -eq 0 ]; then + echo "Running memcpy benchmark" + (time ./build-ci-release/bin/whisper-bench -w 1 -t $BENCH_N_THREADS 2>&1) | tee -a $OUT/${ci}-memcpy.log + gg_check_last_command_status "$OUT/${ci}-memcpy.exit" "memcpy benchmark" + + echo "Running ggml_mul_mat benchmark with $BENCH_N_THREADS threads" + (time ./build-ci-release/bin/whisper-bench -w 2 -t $BENCH_N_THREADS 2>&1) | tee -a $OUT/${ci}-mul_mat.log + gg_check_last_command_status "$OUT/${ci}-mul_mat.exit" "ggml_mul_mat benchmark" + fi + + echo "Running benchmark for all models" + + # generate header for the benchmark table + { + printf "| %16s | %13s | %3s | %3s | %7s | %7s | %7s | %7s | %7s |\n" "Config" "Model" "Th" "FA" "Enc." "Dec." "Bch5" "PP" "Commit" + printf "| %16s | %13s | %3s | %3s | %7s | %7s | %7s | %7s | %7s |\n" "---" "---" "---" "---" "---" "---" "---" "---" "---" + } | tee -a $OUT/${ci}-models-table.log + + res=0 + + # run benchmark for each model + for model in "${MODELS[@]}"; do + echo "Benchmarking model: $model" + + # run the benchmark and capture output + output=$(./build-ci-release/bin/whisper-bench -m $MNT/models/ggml-$model.bin -t $BENCH_N_THREADS $fattn 2>&1) + ret=$? + + # save the raw output + echo "$output" > $OUT/${ci}-bench-$model.log + + if [ $ret -eq 0 ]; then + # parse the benchmark results + encode_time=$(echo "$output" | grep "encode time" | awk '{print $11}') + decode_time=$(echo "$output" | grep "decode time" | awk '{print $11}') + batchd_time=$(echo "$output" | grep "batchd time" | awk '{print $11}') + prompt_time=$(echo "$output" | grep "prompt time" | awk '{print $11}') + system_info=$(echo "$output" | grep "system_info") + actual_threads=$(echo "$output" | grep "system_info" | awk '{print $4}') + + # determine configuration + config="" + if [[ $system_info == *"AVX2 = 1"* ]]; then + config="$config AVX2" + fi + if [[ $system_info == *"NEON = 1"* ]]; then + config="$config NEON" + fi + if [[ $system_info == *"BLAS = 1"* ]]; then + config="$config BLAS" + fi + if [[ $system_info == *"COREML = 1"* ]]; then + config="$config COREML" + fi + if [[ $system_info == *"CUDA = 1"* ]]; then + config="$config CUDA" + fi + if [[ $system_info == *"METAL = 1"* ]]; then + config="$config METAL" + fi + + # get commit hash + commit=$(git rev-parse --short HEAD) + + # add row to benchmark table + printf "| %16s | %13s | %3s | %3s | %7s | %7s | %7s | %7s | %7s |\n" \ + "$config" "$model" "$actual_threads" "$BENCH_FLASH_ATTN" "$encode_time" "$decode_time" "$batchd_time" "$prompt_time" "$commit" \ + | tee -a $OUT/${ci}-models-table.log + else + echo "Benchmark failed for model: $model" | tee -a $OUT/${ci}-bench-errors.log + res=1 + fi + done + + return $res +} + +function gg_sum_bench { + gg_printf '### %s\n\n' "${ci}" + + gg_printf 'Whisper Benchmark Results\n' + gg_printf '- status: %s\n' "$(cat $OUT/${ci}.exit)" + + # show memcpy and ggml_mul_mat benchmark results if available + if [ "$BENCH_ENCODER_ONLY" -eq 0 ]; then + if [ -f "$OUT/${ci}-memcpy.log" ]; then + gg_printf '#### memcpy Benchmark\n\n' + gg_printf '```\n%s\n```\n\n' "$(cat $OUT/${ci}-memcpy.log)" + fi + + if [ -f "$OUT/${ci}-mul_mat.log" ]; then + gg_printf '#### ggml_mul_mat Benchmark\n\n' + gg_printf '```\n%s\n```\n\n' "$(cat $OUT/${ci}-mul_mat.log)" + fi + fi + + # show model benchmark results + gg_printf '#### Model Benchmarks\n\n' + if [ -f "$OUT/${ci}-models-table.log" ]; then + gg_printf '%s\n\n' "$(cat $OUT/${ci}-models-table.log)" + else + gg_printf 'No model benchmark results available.\n\n' + fi + + # show any errors that occurred + if [ -f "$OUT/${ci}-bench-errors.log" ]; then + gg_printf '#### Benchmark Errors\n\n' + gg_printf '```\n%s\n```\n\n' "$(cat $OUT/${ci}-bench-errors.log)" + fi +} + +ret=0 + +for model in "${MODELS[@]}"; do + test $ret -eq 0 && gg_download_model ${model} +done + +test $ret -eq 0 && gg_run ctest debug +test $ret -eq 0 && gg_run ctest release + +test $ret -eq 0 && gg_run bench + +cat $OUT/README.md + +exit $ret diff --git a/cmake/DefaultTargetOptions.cmake b/cmake/DefaultTargetOptions.cmake new file mode 100644 index 0000000..0cfbb34 --- /dev/null +++ b/cmake/DefaultTargetOptions.cmake @@ -0,0 +1,16 @@ +# Set the default compile features and properties for a target. + +if (NOT TARGET) + message(FATAL_ERROR "TARGET not set before including DefaultTargetOptions") +endif() + +target_compile_features(${TARGET} + PRIVATE + cxx_std_11 + ) + +set_target_properties(${TARGET} + PROPERTIES + EXPORT_COMPILE_COMMANDS ON + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" +) diff --git a/cmake/FindFFmpeg.cmake b/cmake/FindFFmpeg.cmake new file mode 100644 index 0000000..bb6aff6 --- /dev/null +++ b/cmake/FindFFmpeg.cmake @@ -0,0 +1,163 @@ +# From +# https://github.com/snikulov/cmake-modules/blob/master/FindFFmpeg.cmake +# +# vim: ts=2 sw=2 +# - Try to find the required ffmpeg components(default: AVFORMAT, AVUTIL, AVCODEC) +# +# Once done this will define +# FFMPEG_FOUND - System has the all required components. +# FFMPEG_INCLUDE_DIRS - Include directory necessary for using the required components headers. +# FFMPEG_LIBRARIES - Link these to use the required ffmpeg components. +# FFMPEG_DEFINITIONS - Compiler switches required for using the required ffmpeg components. +# +# For each of the components it will additionally set. +# - AVCODEC +# - AVDEVICE +# - AVFORMAT +# - AVFILTER +# - AVUTIL +# - POSTPROC +# - SWSCALE +# the following variables will be defined +# <component>_FOUND - System has <component> +# <component>_INCLUDE_DIRS - Include directory necessary for using the <component> headers +# <component>_LIBRARIES - Link these to use <component> +# <component>_DEFINITIONS - Compiler switches required for using <component> +# <component>_VERSION - The components version +# +# Copyright (c) 2006, Matthias Kretz, <kretz@kde.org> +# Copyright (c) 2008, Alexander Neundorf, <neundorf@kde.org> +# Copyright (c) 2011, Michael Jansen, <kde@michael-jansen.biz> +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +include(FindPackageHandleStandardArgs) + +# The default components were taken from a survey over other FindFFMPEG.cmake files +if (NOT FFmpeg_FIND_COMPONENTS) + set(FFmpeg_FIND_COMPONENTS AVFORMAT AVCODEC AVUTIL SWRESAMPLE) +endif() + +# +### Macro: set_component_found +# +# Marks the given component as found if both *_LIBRARIES AND *_INCLUDE_DIRS is present. +# +macro(set_component_found _component ) + if (${_component}_LIBRARIES AND ${_component}_INCLUDE_DIRS) + message(DEBUG " - ${_component} found.") + set(${_component}_FOUND TRUE) + else () + message(DEBUG " - ${_component} not found.") + endif () +endmacro() + +# +### Macro: find_component +# +# Checks for the given component by invoking pkgconfig and then looking up the libraries and +# include directories. +# +macro(find_component _component _pkgconfig _library _header) + + if (NOT WIN32) + # use pkg-config to get the directories and then use these values + # in the FIND_PATH() and FIND_LIBRARY() calls + find_package(PkgConfig) + if (PKG_CONFIG_FOUND) + pkg_check_modules(PC_${_component} ${_pkgconfig}) + message(STATUS "Pkgconfig found: ${PC_${_component}_INCLUDEDIR}") + message(STATUS "Pkgconfig found: ${PC_${_component}_INCLUDE_DIRS}") + message(STATUS "${PC_${_component}_CFLAGS}") + endif () + endif (NOT WIN32) + + + find_path(${_component}_INCLUDE_DIRS ${_header} + HINTS + ${PC_${_component}_INCLUDEDIR} + ${PC_${_component}_INCLUDE_DIRS} + PATH_SUFFIXES + ffmpeg + ) + + # CMake's default is to search first for shared libraries and then for static libraries. + # Todo later: add option to prefer static libs over dynamic: + find_library(${_component}_LIBRARIES NAMES ${_library} lib${_library}.a + HINTS + ${PC_${_component}_LIBDIR} + ${PC_${_component}_LIBRARY_DIRS} + ) + + set(${_component}_DEFINITIONS ${PC_${_component}_CFLAGS_OTHER} CACHE STRING "The ${_component} CFLAGS.") + set(${_component}_VERSION ${PC_${_component}_VERSION} CACHE STRING "The ${_component} version number.") + + set_component_found(${_component}) + + mark_as_advanced( + ${_component}_INCLUDE_DIRS + ${_component}_LIBRARIES + ${_component}_DEFINITIONS + ${_component}_VERSION) + +endmacro() + + +# Check for cached results. If there are skip the costly part. +if (NOT FFMPEG_LIBRARIES) + + # Check for all possible component. + find_component(AVCODEC libavcodec avcodec libavcodec/avcodec.h) + find_component(AVFORMAT libavformat avformat libavformat/avformat.h) + find_component(AVDEVICE libavdevice avdevice libavdevice/avdevice.h) + #find_component(AVRESAMPLE libavresample avresample libavresample/avresample.h) # old name for swresample + find_component(AVUTIL libavutil avutil libavutil/avutil.h) + find_component(AVFILTER libavfilter avfilter libavfilter/avfilter.h) + find_component(SWSCALE libswscale swscale libswscale/swscale.h) + find_component(POSTPROC libpostproc postproc libpostproc/postprocess.h) + find_component(SWRESAMPLE libswresample swresample libswresample/swresample.h) + + # Check if the required components were found and add their stuff to the FFMPEG_* vars. + foreach (_component ${FFmpeg_FIND_COMPONENTS}) + if (${_component}_FOUND) + # message(STATUS "Required component ${_component} present.") + set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${${_component}_LIBRARIES}) + set(FFMPEG_DEFINITIONS ${FFMPEG_DEFINITIONS} ${${_component}_DEFINITIONS}) + list(APPEND FFMPEG_INCLUDE_DIRS ${${_component}_INCLUDE_DIRS}) + else () + # message(STATUS "Required component ${_component} missing.") + endif () + endforeach () + + # Build the include path with duplicates removed. + if (FFMPEG_INCLUDE_DIRS) + list(REMOVE_DUPLICATES FFMPEG_INCLUDE_DIRS) + endif () + + # cache the vars. + set(FFMPEG_INCLUDE_DIRS ${FFMPEG_INCLUDE_DIRS} CACHE STRING "The FFmpeg include directories." FORCE) + set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} CACHE STRING "The FFmpeg libraries." FORCE) + set(FFMPEG_DEFINITIONS ${FFMPEG_DEFINITIONS} CACHE STRING "The FFmpeg cflags." FORCE) + + mark_as_advanced(FFMPEG_INCLUDE_DIRS + FFMPEG_LIBRARIES + FFMPEG_DEFINITIONS) + +endif () + +# Now set the noncached _FOUND vars for the components. +# whisper.cpp does not need SWSCALE +foreach (_component AVCODEC AVDEVICE AVFORMAT AVRESAMPLE AVUTIL POSTPROCESS) + set_component_found(${_component}) +endforeach () + +# Compile the list of required vars +set(_FFmpeg_REQUIRED_VARS FFMPEG_LIBRARIES FFMPEG_INCLUDE_DIRS) +foreach (_component ${FFmpeg_FIND_COMPONENTS}) + list(APPEND _FFmpeg_REQUIRED_VARS ${_component}_LIBRARIES ${_component}_INCLUDE_DIRS) +endforeach () + +# Give a nice error message if some of the required vars are missing. +find_package_handle_standard_args(FFmpeg DEFAULT_MSG ${_FFmpeg_REQUIRED_VARS}) + diff --git a/cmake/arm64-apple-clang.cmake b/cmake/arm64-apple-clang.cmake new file mode 100644 index 0000000..5fcd288 --- /dev/null +++ b/cmake/arm64-apple-clang.cmake @@ -0,0 +1,16 @@ +set( CMAKE_SYSTEM_NAME Darwin ) +set( CMAKE_SYSTEM_PROCESSOR arm64 ) + +set( target arm64-apple-darwin-macho ) + +set( CMAKE_C_COMPILER clang ) +set( CMAKE_CXX_COMPILER clang++ ) + +set( CMAKE_C_COMPILER_TARGET ${target} ) +set( CMAKE_CXX_COMPILER_TARGET ${target} ) + +set( arch_c_flags "-march=armv8.4-a -fvectorize -ffp-model=fast -fno-finite-math-only" ) +set( warn_c_flags "-Wno-format -Wno-unused-variable -Wno-unused-function" ) + +set( CMAKE_C_FLAGS_INIT "${arch_c_flags} ${warn_c_flags}" ) +set( CMAKE_CXX_FLAGS_INIT "${arch_c_flags} ${warn_c_flags}" ) diff --git a/cmake/arm64-windows-llvm-cuda.cmake b/cmake/arm64-windows-llvm-cuda.cmake new file mode 100644 index 0000000..526a5a2 --- /dev/null +++ b/cmake/arm64-windows-llvm-cuda.cmake @@ -0,0 +1,24 @@ +include( ${CMAKE_CURRENT_LIST_DIR}/arm64-windows-llvm.cmake ) + +if ( DEFINED CUDAToolkit_ROOT ) + file( TO_CMAKE_PATH "${CUDAToolkit_ROOT}" CUDA_ROOT ) +elseif ( DEFINED ENV{CUDA_PATH} ) + file( TO_CMAKE_PATH "$ENV{CUDA_PATH}" CUDA_ROOT ) +else() + message( FATAL_ERROR "Set CUDAToolkit_ROOT or CUDA_PATH to a Windows CUDA Toolkit with ARM64 target libraries" ) +endif() + +if ( DEFINED ENV{VCToolsInstallDir} ) + file( TO_CMAKE_PATH "$ENV{VCToolsInstallDir}" MSVC_TOOLS_ROOT ) + set( CMAKE_CUDA_HOST_COMPILER "${MSVC_TOOLS_ROOT}/bin/Hostx64/arm64/cl.exe" CACHE FILEPATH "" ) +endif() + +set( CMAKE_CUDA_COMPILER "${CUDA_ROOT}/bin/nvcc.exe" CACHE FILEPATH "" ) +set( CMAKE_CUDA_FLAGS_INIT "-target-dir=arm64" ) + +# FindCUDAToolkit selects lib/x64 from the host architecture on Windows. +set( CUDA_CUDART "${CUDA_ROOT}/lib/arm64/cudart.lib" CACHE FILEPATH "" ) +set( CUDA_cudart_LIBRARY "${CUDA_ROOT}/lib/arm64/cudart.lib" CACHE FILEPATH "" ) +set( CUDA_cublas_LIBRARY "${CUDA_ROOT}/lib/arm64/cublas.lib" CACHE FILEPATH "" ) +set( CUDA_cublasLt_LIBRARY "${CUDA_ROOT}/lib/arm64/cublasLt.lib" CACHE FILEPATH "" ) +set( CUDA_cuda_driver_LIBRARY "${CUDA_ROOT}/lib/arm64/cuda.lib" CACHE FILEPATH "" ) diff --git a/cmake/arm64-windows-llvm.cmake b/cmake/arm64-windows-llvm.cmake new file mode 100644 index 0000000..8023796 --- /dev/null +++ b/cmake/arm64-windows-llvm.cmake @@ -0,0 +1,16 @@ +set( CMAKE_SYSTEM_NAME Windows ) +set( CMAKE_SYSTEM_PROCESSOR arm64 ) + +set( target arm64-pc-windows-msvc ) + +set( CMAKE_C_COMPILER clang ) +set( CMAKE_CXX_COMPILER clang++ ) + +set( CMAKE_C_COMPILER_TARGET ${target} ) +set( CMAKE_CXX_COMPILER_TARGET ${target} ) + +set( arch_c_flags "-march=armv8.7-a -fvectorize -ffp-model=fast -fno-finite-math-only" ) +set( warn_c_flags "-Wno-format -Wno-unused-variable -Wno-unused-function -Wno-gnu-zero-variadic-macro-arguments" ) + +set( CMAKE_C_FLAGS_INIT "${arch_c_flags} ${warn_c_flags}" ) +set( CMAKE_CXX_FLAGS_INIT "${arch_c_flags} ${warn_c_flags}" ) diff --git a/cmake/build-info.cmake b/cmake/build-info.cmake new file mode 100644 index 0000000..b293c9b --- /dev/null +++ b/cmake/build-info.cmake @@ -0,0 +1,60 @@ +set(BUILD_NUMBER 0) +set(BUILD_COMMIT "unknown") +set(BUILD_COMPILER "unknown") +set(BUILD_TARGET "unknown") + +# Look for git +find_package(Git) +if(NOT Git_FOUND) + find_program(GIT_EXECUTABLE NAMES git git.exe) + if(GIT_EXECUTABLE) + set(Git_FOUND TRUE) + message(STATUS "Found Git: ${GIT_EXECUTABLE}") + else() + message(WARNING "Git not found. Build info will not be accurate.") + endif() +endif() + +# Get the commit count and hash +if(Git_FOUND) + execute_process( + COMMAND ${GIT_EXECUTABLE} rev-parse --short HEAD + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + OUTPUT_VARIABLE HEAD + OUTPUT_STRIP_TRAILING_WHITESPACE + RESULT_VARIABLE RES + ) + if (RES EQUAL 0) + set(BUILD_COMMIT ${HEAD}) + endif() + execute_process( + COMMAND ${GIT_EXECUTABLE} rev-list --count HEAD + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + OUTPUT_VARIABLE COUNT + OUTPUT_STRIP_TRAILING_WHITESPACE + RESULT_VARIABLE RES + ) + if (RES EQUAL 0) + set(BUILD_NUMBER ${COUNT}) + endif() +endif() + +if(MSVC) + set(BUILD_COMPILER "${CMAKE_C_COMPILER_ID} ${CMAKE_C_COMPILER_VERSION}") + set(BUILD_TARGET ${CMAKE_VS_PLATFORM_NAME}) + add_compile_options("$<$<COMPILE_LANGUAGE:C>:/utf-8>") + add_compile_options("$<$<COMPILE_LANGUAGE:CXX>:/utf-8>") +else() + execute_process( + COMMAND sh -c "$@ --version | head -1" _ ${CMAKE_C_COMPILER} + OUTPUT_VARIABLE OUT + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + set(BUILD_COMPILER ${OUT}) + execute_process( + COMMAND ${CMAKE_C_COMPILER} -dumpmachine + OUTPUT_VARIABLE OUT + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + set(BUILD_TARGET ${OUT}) +endif() diff --git a/cmake/git-vars.cmake b/cmake/git-vars.cmake new file mode 100644 index 0000000..1a4c24e --- /dev/null +++ b/cmake/git-vars.cmake @@ -0,0 +1,22 @@ +find_package(Git) + +# the commit's SHA1 +execute_process(COMMAND + "${GIT_EXECUTABLE}" describe --match=NeVeRmAtCh --always --abbrev=8 + WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" + OUTPUT_VARIABLE GIT_SHA1 + ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) + +# the date of the commit +execute_process(COMMAND + "${GIT_EXECUTABLE}" log -1 --format=%ad --date=local + WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" + OUTPUT_VARIABLE GIT_DATE + ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) + +# the subject of the commit +execute_process(COMMAND + "${GIT_EXECUTABLE}" log -1 --format=%s + WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" + OUTPUT_VARIABLE GIT_COMMIT_SUBJECT + ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) diff --git a/cmake/parakeet-config.cmake.in b/cmake/parakeet-config.cmake.in new file mode 100644 index 0000000..4895d7d --- /dev/null +++ b/cmake/parakeet-config.cmake.in @@ -0,0 +1,30 @@ +set(PARAKEET_VERSION @WHISPER_VERSION@) +set(PARAKEET_BUILD_COMMIT @WHISPER_BUILD_COMMIT@) +set(PARAKEET_BUILD_NUMBER @WHISPER_BUILD_NUMBER@) +set(PARAKEET_SHARED_LIB @BUILD_SHARED_LIBS@) + +@PACKAGE_INIT@ + +set_and_check(PARAKEET_INCLUDE_DIR "@PACKAGE_PARAKEET_INCLUDE_INSTALL_DIR@") +set_and_check(PARAKEET_LIB_DIR "@PACKAGE_PARAKEET_LIB_INSTALL_DIR@") +set(PARAKEET_BIN_DIR "@PACKAGE_PARAKEET_BIN_INSTALL_DIR@") + +find_package(ggml REQUIRED HINTS ${PARAKEET_LIB_DIR}/cmake) + +find_library(parakeet_LIBRARY parakeet + REQUIRED + HINTS ${PARAKEET_LIB_DIR} + NO_CMAKE_FIND_ROOT_PATH +) + +add_library(parakeet UNKNOWN IMPORTED) +set_target_properties(parakeet + PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${PARAKEET_INCLUDE_DIR}" + INTERFACE_LINK_LIBRARIES "ggml::ggml;ggml::ggml-base;" + IMPORTED_LINK_INTERFACE_LANGUAGES "CXX" + IMPORTED_LOCATION "${parakeet_LIBRARY}" + INTERFACE_COMPILE_FEATURES cxx_std_11 + POSITION_INDEPENDENT_CODE ON) + +check_required_components(parakeet) diff --git a/cmake/parakeet.pc.in b/cmake/parakeet.pc.in new file mode 100644 index 0000000..de1acb7 --- /dev/null +++ b/cmake/parakeet.pc.in @@ -0,0 +1,10 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=${prefix} +libdir=@CMAKE_INSTALL_FULL_LIBDIR@ +includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@ + +Name: parakeet +Description: Port of NVIDIA's Parakeet model in C/C++ +Version: @WHISPER_VERSION@ +Libs: -L${libdir} -lggml -lggml-base -lparakeet +Cflags: -I${includedir} diff --git a/cmake/riscv64-spacemit-linux-gnu-gcc.cmake b/cmake/riscv64-spacemit-linux-gnu-gcc.cmake new file mode 100644 index 0000000..08fdbf5 --- /dev/null +++ b/cmake/riscv64-spacemit-linux-gnu-gcc.cmake @@ -0,0 +1,29 @@ +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_SYSTEM_PROCESSOR riscv64) +set(CMAKE_SYSTEM_VERSION 1) + +if (CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "^(riscv)") + message(STATUS "HOST SYSTEM ${CMAKE_HOST_SYSTEM_PROCESSOR}") +else() + set(GNU_MACHINE riscv64-unknown-linux-gnu CACHE STRING "GNU compiler triple") + if (DEFINED ENV{RISCV_ROOT_PATH}) + file(TO_CMAKE_PATH $ENV{RISCV_ROOT_PATH} RISCV_ROOT_PATH) + else() + message(FATAL_ERROR "RISCV_ROOT_PATH env must be defined") + endif() + + set(RISCV_ROOT_PATH ${RISCV_ROOT_PATH} CACHE STRING "root path to riscv toolchain") + set(CMAKE_C_COMPILER ${RISCV_ROOT_PATH}/bin/riscv64-unknown-linux-gnu-gcc) + set(CMAKE_CXX_COMPILER ${RISCV_ROOT_PATH}/bin/riscv64-unknown-linux-gnu-g++) + set(CMAKE_STRIP ${RISCV_ROOT_PATH}/bin/riscv64-unknown-linux-gnu-strip) + set(CMAKE_FIND_ROOT_PATH "${RISCV_ROOT_PATH}/riscv64-unknown-linux-gnu") + set(CMAKE_SYSROOT "${RISCV_ROOT_PATH}/sysroot") +endif() + +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) +set(CMAKE_C_FLAGS "-march=rv64gcv_zfh_zba_zicbop -mabi=lp64d ${CMAKE_C_FLAGS}") +set(CMAKE_CXX_FLAGS "-march=rv64gcv_zfh_zba_zicbop -mabi=lp64d ${CXX_FLAGS}") +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -latomic") diff --git a/cmake/whisper-config.cmake.in b/cmake/whisper-config.cmake.in new file mode 100644 index 0000000..551abe1 --- /dev/null +++ b/cmake/whisper-config.cmake.in @@ -0,0 +1,30 @@ +set(WHISPER_VERSION @WHISPER_VERSION@) +set(WHISPER_BUILD_COMMIT @WHISPER_BUILD_COMMIT@) +set(WHISPER_BUILD_NUMBER @WHISPER_BUILD_NUMBER@) +set(WHISPER_SHARED_LIB @BUILD_SHARED_LIBS@) + +@PACKAGE_INIT@ + +set_and_check(WHISPER_INCLUDE_DIR "@PACKAGE_WHISPER_INCLUDE_INSTALL_DIR@") +set_and_check(WHISPER_LIB_DIR "@PACKAGE_WHISPER_LIB_INSTALL_DIR@") +set(WHISPER_BIN_DIR "@PACKAGE_WHISPER_BIN_INSTALL_DIR@") + +find_package(ggml REQUIRED HINTS ${WHISPER_LIB_DIR}/cmake) + +find_library(whisper_LIBRARY whisper + REQUIRED + HINTS ${WHISPER_LIB_DIR} + NO_CMAKE_FIND_ROOT_PATH +) + +add_library(whisper UNKNOWN IMPORTED) +set_target_properties(whisper + PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${WHISPER_INCLUDE_DIR}" + INTERFACE_LINK_LIBRARIES "ggml::ggml;ggml::ggml-base;" + IMPORTED_LINK_INTERFACE_LANGUAGES "CXX" + IMPORTED_LOCATION "${whisper_LIBRARY}" + INTERFACE_COMPILE_FEATURES cxx_std_11 + POSITION_INDEPENDENT_CODE ON ) + +check_required_components(whisper) diff --git a/cmake/whisper.pc.in b/cmake/whisper.pc.in new file mode 100644 index 0000000..270fc2e --- /dev/null +++ b/cmake/whisper.pc.in @@ -0,0 +1,10 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=${prefix} +libdir=@CMAKE_INSTALL_FULL_LIBDIR@ +includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@ + +Name: whisper +Description: Port of OpenAI's Whisper model in C/C++ +Version: @WHISPER_VERSION@ +Libs: -L${libdir} -lggml -lggml-base -lwhisper +Cflags: -I${includedir} diff --git a/cmake/x64-windows-llvm.cmake b/cmake/x64-windows-llvm.cmake new file mode 100644 index 0000000..77e7914 --- /dev/null +++ b/cmake/x64-windows-llvm.cmake @@ -0,0 +1,5 @@ +set( CMAKE_SYSTEM_NAME Windows ) +set( CMAKE_SYSTEM_PROCESSOR x86_64 ) + +set( CMAKE_C_COMPILER clang ) +set( CMAKE_CXX_COMPILER clang++ ) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt new file mode 100644 index 0000000..7aedb9d --- /dev/null +++ b/examples/CMakeLists.txt @@ -0,0 +1,127 @@ +# dependencies + +find_package(Threads REQUIRED) + +# third-party + +if (WHISPER_SDL2) + # SDL2 + find_package(SDL2 REQUIRED) + + string(STRIP "${SDL2_LIBRARIES}" SDL2_LIBRARIES) + + message(STATUS "SDL2_INCLUDE_DIRS = ${SDL2_INCLUDE_DIRS}") + message(STATUS "SDL2_LIBRARIES = ${SDL2_LIBRARIES}") +endif() + +# common + +set(TARGET common) + +unset(COMMON_EXTRA_LIBS) + +if (WHISPER_COMMON_FFMPEG) + # As of cmake 3.27, there is no official cmake support for FindFFmpeg. + # Consequnelty we added a FindFFmpeg.cmake script the cmake subfolder: + # whisper.cpp does not need the full ffmpeg libs, just AVFORMAT AVCODEC AVUTIL SWRESAMPLE + # libswresample performs highly optimized audio resampling, rematrixing and sample format conversion operations + # libavcodec provides a generic encoding/decoding framework and contains multiple decoders and encoders for audio, video and subtitle streams, and several bitstream filters. + # libavformat provides a generic framework for multiplexing and demultiplexing (muxing and demuxing) audio, video and subtitle streams. + find_package(FFmpeg REQUIRED) + + if (NOT ${FFMPEG_FOUND}) + message(FATAL_ERROR "Cannot find ffmpeg libs/headers") + endif() + + message(STATUS "Found ffmpeg libs: ${FFMPEG_LIBRARIES}") + message(STATUS "Found ffmpeg headers in: ${FFMPEG_INCLUDE_DIRS}") + message(STATUS "ffmpeg definitions: ${FFMPEG_DEFINITIONS}") + message(STATUS "Found avformat ${AVFORMAT_VERSION}") + + include_directories(${FFMPEG_INCLUDE_DIRS}) + add_compile_definitions(WHISPER_COMMON_FFMPEG) + + list(APPEND COMMON_EXTRA_LIBS ${FFMPEG_LIBRARIES}) + + set(COMMON_SOURCES_FFMPEG ffmpeg-transcode.cpp) +endif() + + +add_library(${TARGET} STATIC + common.h + common.cpp + common-ggml.h + common-ggml.cpp + common-whisper.h + common-whisper.cpp + grammar-parser.h + grammar-parser.cpp + ${COMMON_SOURCES_FFMPEG} + ) + +include(DefaultTargetOptions) + +target_link_libraries(${TARGET} PRIVATE whisper ${COMMON_EXTRA_LIBS} ${CMAKE_DL_LIBS}) + +set_target_properties(${TARGET} PROPERTIES POSITION_INDEPENDENT_CODE ON) +set_target_properties(${TARGET} PROPERTIES FOLDER "libs") + +if (WHISPER_SDL2) + # common-sdl + + set(TARGET common-sdl) + + add_library(${TARGET} STATIC + common-sdl.h + common-sdl.cpp + ) + + include(DefaultTargetOptions) + + target_include_directories(${TARGET} PUBLIC ${SDL2_INCLUDE_DIRS}) + target_link_libraries (${TARGET} PRIVATE ${SDL2_LIBRARIES}) + + set_target_properties(${TARGET} PROPERTIES POSITION_INDEPENDENT_CODE ON) + set_target_properties(${TARGET} PROPERTIES FOLDER "libs") +endif() + +# add json lib +add_library(json_cpp INTERFACE) +target_include_directories(json_cpp INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) + +# examples + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + +if (EMSCRIPTEN) + add_subdirectory(whisper.wasm) + add_subdirectory(stream.wasm) + add_subdirectory(command.wasm) + add_subdirectory(bench.wasm) + add_subdirectory(wchess) +elseif(CMAKE_JS_VERSION) + add_subdirectory(addon.node) +else() + add_subdirectory(cli) + add_subdirectory(bench) + add_subdirectory(server) + add_subdirectory(quantize) + add_subdirectory(vad-speech-segments) + add_subdirectory(parakeet-cli) + add_subdirectory(parakeet-quantize) + if (WHISPER_SDL2) + add_subdirectory(stream) + add_subdirectory(command) + add_subdirectory(talk-llama) + add_subdirectory(lsp) + if (GGML_SYCL) + add_subdirectory(sycl) + endif() + endif (WHISPER_SDL2) + + add_subdirectory(deprecation-warning) +endif() + +if (WHISPER_SDL2) + add_subdirectory(wchess) +endif (WHISPER_SDL2) diff --git a/examples/addon.node/.gitignore b/examples/addon.node/.gitignore new file mode 100644 index 0000000..b456cad --- /dev/null +++ b/examples/addon.node/.gitignore @@ -0,0 +1,3 @@ +.idea +node_modules +build diff --git a/examples/addon.node/CMakeLists.txt b/examples/addon.node/CMakeLists.txt new file mode 100644 index 0000000..75c68d1 --- /dev/null +++ b/examples/addon.node/CMakeLists.txt @@ -0,0 +1,34 @@ +set(TARGET addon.node) + +# Base settings +#================================================================== +# env var supported by cmake-js +add_definitions(-DNAPI_VERSION=4) +include_directories(${CMAKE_JS_INC}) +#================================================================== + +add_library(${TARGET} SHARED ${CMAKE_JS_SRC} addon.cpp) +set_target_properties(${TARGET} PROPERTIES + PREFIX "" + OUTPUT_NAME "addon" + SUFFIX ".node" + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/Release" +) + +# Include N-API wrappers +#================================================================== +execute_process(COMMAND node -p "require('node-addon-api').include" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + OUTPUT_VARIABLE NODE_ADDON_API_DIR + ) +string(REPLACE "\n" "" NODE_ADDON_API_DIR ${NODE_ADDON_API_DIR}) +string(REPLACE "\"" "" NODE_ADDON_API_DIR ${NODE_ADDON_API_DIR}) +target_include_directories(${TARGET} PRIVATE ${NODE_ADDON_API_DIR}) +#================================================================== + +target_link_libraries(${TARGET} ${CMAKE_JS_LIB} common whisper ${CMAKE_THREAD_LIBS_INIT}) + +if(MSVC AND CMAKE_JS_NODELIB_DEF AND CMAKE_JS_NODELIB_TARGET) + # Generate node.lib + execute_process(COMMAND ${CMAKE_AR} /def:${CMAKE_JS_NODELIB_DEF} /out:${CMAKE_JS_NODELIB_TARGET} ${CMAKE_STATIC_LINKER_FLAGS}) +endif() diff --git a/examples/addon.node/README.md b/examples/addon.node/README.md new file mode 100644 index 0000000..bb09ba1 --- /dev/null +++ b/examples/addon.node/README.md @@ -0,0 +1,115 @@ +# whisper.cpp Node.js addon + +This is an addon demo that can **perform whisper model reasoning in `node` and `electron` environments**, based on [cmake-js](https://github.com/cmake-js/cmake-js). +It can be used as a reference for using the whisper.cpp project in other node projects. + +This addon now supports **Voice Activity Detection (VAD)** for improved transcription performance. + +## Install + +```shell +npm install +``` + +## Compile + +Make sure it is in the project root directory and compiled with make-js. + +```shell +npx cmake-js compile -T addon.node -B Release +``` + +For Electron addon and cmake-js options, you can see [cmake-js](https://github.com/cmake-js/cmake-js) and make very few configuration changes. + +> Such as appointing special cmake path: +> ```shell +> npx cmake-js compile -c 'xxx/cmake' -T addon.node -B Release +> ``` + +## Run + +### Basic Usage + +```shell +cd examples/addon.node + +node index.js --language='language' --model='model-path' --fname_inp='file-path' +``` + +### VAD (Voice Activity Detection) Usage + +Run the VAD example with performance comparison: + +```shell +node vad-example.js +``` + +## Voice Activity Detection (VAD) Support + +VAD can significantly improve transcription performance by only processing speech segments, which is especially beneficial for audio files with long periods of silence. + +### VAD Model Setup + +Before using VAD, download a VAD model: + +```shell +# From the whisper.cpp root directory +./models/download-vad-model.sh silero-v6.2.0 +``` + +### VAD Parameters + +All VAD parameters are optional and have sensible defaults: + +- `vad`: Enable VAD (default: false) +- `vad_model`: Path to VAD model file (required when VAD enabled) +- `vad_threshold`: Speech detection threshold 0.0-1.0 (default: 0.5) +- `vad_min_speech_duration_ms`: Min speech duration in ms (default: 250) +- `vad_min_silence_duration_ms`: Min silence duration in ms (default: 100) +- `vad_max_speech_duration_s`: Max speech duration in seconds (default: FLT_MAX) +- `vad_speech_pad_ms`: Speech padding in ms (default: 30) +- `vad_samples_overlap`: Sample overlap 0.0-1.0 (default: 0.1) + +### JavaScript API Example + +```javascript +const path = require("path"); +const { whisper } = require(path.join(__dirname, "../../build/Release/addon.node")); +const { promisify } = require("util"); + +const whisperAsync = promisify(whisper); + +// With VAD enabled +const vadParams = { + language: "en", + model: path.join(__dirname, "../../models/ggml-base.en.bin"), + fname_inp: path.join(__dirname, "../../samples/jfk.wav"), + vad: true, + vad_model: path.join(__dirname, "../../models/ggml-silero-v6.2.0.bin"), + vad_threshold: 0.5, + progress_callback: (progress) => console.log(`Progress: ${progress}%`) +}; + +whisperAsync(vadParams).then(result => console.log(result)); +``` + +## Supported Parameters + +Both traditional whisper.cpp parameters and new VAD parameters are supported: + +- `language`: Language code (e.g., "en", "es", "fr") +- `model`: Path to whisper model file +- `fname_inp`: Path to input audio file +- `use_gpu`: Enable GPU acceleration (default: true) +- `flash_attn`: Enable flash attention (default: false) +- `no_prints`: Disable console output (default: false) +- `no_timestamps`: Disable timestamps (default: false) +- `detect_language`: Auto-detect language (default: false) +- `audio_ctx`: Audio context size (default: 0) +- `max_len`: Maximum segment length (default: 0) +- `max_context`: Maximum context size (default: -1) +- `prompt`: Initial prompt for decoder +- `comma_in_time`: Use comma in timestamps (default: true) +- `print_progress`: Print progress info (default: false) +- `progress_callback`: Progress callback function +- VAD parameters (see above section) diff --git a/examples/addon.node/__test__/whisper.spec.js b/examples/addon.node/__test__/whisper.spec.js new file mode 100644 index 0000000..b07430a --- /dev/null +++ b/examples/addon.node/__test__/whisper.spec.js @@ -0,0 +1,133 @@ +const { join } = require('path'); +const { whisper } = require('../../../build/Release/addon.node'); +const { promisify } = require('util'); + +const whisperAsync = promisify(whisper); + +const commonParams = { + language: 'en', + model: join(__dirname, '../../../models/ggml-base.en.bin'), + fname_inp: join(__dirname, '../../../samples/jfk.wav'), + use_gpu: true, + flash_attn: false, + no_prints: true, + no_timestamps: false, + detect_language: false, + audio_ctx: 0, + max_len: 0 +}; + +describe('Whisper.cpp Node.js addon with VAD support', () => { + test('Basic whisper transcription without VAD', async () => { + const params = { + ...commonParams, + vad: false + }; + + const result = await whisperAsync(params); + + expect(typeof result).toBe('object'); + expect(Array.isArray(result.transcription)).toBe(true); + expect(result.transcription.length).toBeGreaterThan(0); + + // Check that we got some transcription text + const text = result.transcription.map(segment => segment[2]).join(' '); + expect(text.length).toBeGreaterThan(0); + expect(text.toLowerCase()).toContain('ask not'); + }, 30000); + + test('VAD parameters validation', async () => { + // Test with invalid VAD model - should return empty transcription + const invalidParams = { + ...commonParams, + vad: true, + vad_model: 'non-existent-model.bin', + vad_threshold: 0.5 + }; + + // This should handle the error gracefully and return empty transcription + const result = await whisperAsync(invalidParams); + expect(typeof result).toBe('object'); + expect(Array.isArray(result.transcription)).toBe(true); + // When VAD model doesn't exist, it should return empty transcription + expect(result.transcription.length).toBe(0); + }, 10000); + + test('VAD parameter parsing', async () => { + // Test that VAD parameters are properly parsed (even if VAD model doesn't exist) + const vadParams = { + ...commonParams, + vad: false, // Disabled so no model required + vad_threshold: 0.7, + vad_min_speech_duration_ms: 300, + vad_min_silence_duration_ms: 150, + vad_max_speech_duration_s: 45.0, + vad_speech_pad_ms: 50, + vad_samples_overlap: 0.15 + }; + + const result = await whisperAsync(vadParams); + + expect(typeof result).toBe('object'); + expect(Array.isArray(result.transcription)).toBe(true); + }, 30000); + + test('Progress callback with VAD disabled', async () => { + let progressCalled = false; + let lastProgress = 0; + + const params = { + ...commonParams, + vad: false, + progress_callback: (progress) => { + progressCalled = true; + lastProgress = progress; + expect(progress).toBeGreaterThanOrEqual(0); + expect(progress).toBeLessThanOrEqual(100); + } + }; + + const result = await whisperAsync(params); + + expect(progressCalled).toBe(true); + expect(lastProgress).toBe(100); + expect(typeof result).toBe('object'); + }, 30000); + + test('Language detection without VAD', async () => { + const params = { + ...commonParams, + vad: false, + detect_language: true, + language: 'auto' + }; + + const result = await whisperAsync(params); + + expect(typeof result).toBe('object'); + expect(typeof result.language).toBe('string'); + expect(result.language.length).toBeGreaterThan(0); + }, 30000); + + test('Basic transcription with all VAD parameters set', async () => { + // Test with VAD disabled but all parameters set to ensure no crashes + const params = { + ...commonParams, + vad: false, // Disabled so it works without VAD model + vad_model: '', // Empty model path + vad_threshold: 0.6, + vad_min_speech_duration_ms: 200, + vad_min_silence_duration_ms: 80, + vad_max_speech_duration_s: 25.0, + vad_speech_pad_ms: 40, + vad_samples_overlap: 0.08 + }; + + const result = await whisperAsync(params); + + expect(typeof result).toBe('object'); + expect(Array.isArray(result.transcription)).toBe(true); + expect(result.transcription.length).toBeGreaterThan(0); + }, 30000); +}); + diff --git a/examples/addon.node/addon.cpp b/examples/addon.node/addon.cpp new file mode 100644 index 0000000..71f65b0 --- /dev/null +++ b/examples/addon.node/addon.cpp @@ -0,0 +1,557 @@ +#include "napi.h" +#include "common.h" +#include "common-whisper.h" + +#include "whisper.h" + +#include <string> +#include <thread> +#include <vector> +#include <cmath> +#include <cstdint> +#include <cfloat> + +struct whisper_params { + int32_t n_threads = std::min(4, (int32_t) std::thread::hardware_concurrency()); + int32_t n_processors = 1; + int32_t offset_t_ms = 0; + int32_t offset_n = 0; + int32_t duration_ms = 0; + int32_t max_context = -1; + int32_t max_len = 0; + int32_t best_of = 5; + int32_t beam_size = -1; + int32_t audio_ctx = 0; + + float word_thold = 0.01f; + float entropy_thold = 2.4f; + float logprob_thold = -1.0f; + + bool translate = false; + bool diarize = false; + bool output_txt = false; + bool output_vtt = false; + bool output_srt = false; + bool output_wts = false; + bool output_csv = false; + bool print_special = false; + bool print_colors = false; + bool print_progress = false; + bool no_timestamps = false; + bool no_prints = false; + bool detect_language= false; + bool use_gpu = true; + bool flash_attn = false; + bool comma_in_time = true; + + std::string language = "en"; + std::string prompt; + std::string model = "../../ggml-large.bin"; + + std::vector<std::string> fname_inp = {}; + std::vector<std::string> fname_out = {}; + + std::vector<float> pcmf32 = {}; // mono-channel F32 PCM + + // Voice Activity Detection (VAD) parameters + bool vad = false; + std::string vad_model = ""; + float vad_threshold = 0.5f; + int vad_min_speech_duration_ms = 250; + int vad_min_silence_duration_ms = 100; + float vad_max_speech_duration_s = FLT_MAX; + int vad_speech_pad_ms = 30; + float vad_samples_overlap = 0.1f; +}; + +struct whisper_print_user_data { + const whisper_params * params; + + const std::vector<std::vector<float>> * pcmf32s; +}; + +void whisper_print_segment_callback(struct whisper_context * ctx, struct whisper_state * state, int n_new, void * user_data) { + const auto & params = *((whisper_print_user_data *) user_data)->params; + const auto & pcmf32s = *((whisper_print_user_data *) user_data)->pcmf32s; + + const int n_segments = whisper_full_n_segments(ctx); + + std::string speaker = ""; + + int64_t t0; + int64_t t1; + + // print the last n_new segments + const int s0 = n_segments - n_new; + + if (s0 == 0) { + printf("\n"); + } + + for (int i = s0; i < n_segments; i++) { + if (!params.no_timestamps || params.diarize) { + t0 = whisper_full_get_segment_t0(ctx, i); + t1 = whisper_full_get_segment_t1(ctx, i); + } + + if (!params.no_timestamps && !params.no_prints) { + printf("[%s --> %s] ", to_timestamp(t0).c_str(), to_timestamp(t1).c_str()); + } + + if (params.diarize && pcmf32s.size() == 2) { + const int64_t n_samples = pcmf32s[0].size(); + + const int64_t is0 = timestamp_to_sample(t0, n_samples, WHISPER_SAMPLE_RATE); + const int64_t is1 = timestamp_to_sample(t1, n_samples, WHISPER_SAMPLE_RATE); + + double energy0 = 0.0f; + double energy1 = 0.0f; + + for (int64_t j = is0; j < is1; j++) { + energy0 += fabs(pcmf32s[0][j]); + energy1 += fabs(pcmf32s[1][j]); + } + + if (energy0 > 1.1*energy1) { + speaker = "(speaker 0)"; + } else if (energy1 > 1.1*energy0) { + speaker = "(speaker 1)"; + } else { + speaker = "(speaker ?)"; + } + + //printf("is0 = %lld, is1 = %lld, energy0 = %f, energy1 = %f, %s\n", is0, is1, energy0, energy1, speaker.c_str()); + } + + // colorful print bug + // + if (!params.no_prints) { + const char * text = whisper_full_get_segment_text(ctx, i); + printf("%s%s", speaker.c_str(), text); + } + + + // with timestamps or speakers: each segment on new line + if ((!params.no_timestamps || params.diarize) && !params.no_prints) { + printf("\n"); + } + + fflush(stdout); + } +} + +void cb_log_disable(enum ggml_log_level, const char *, void *) {} + +struct whisper_result { + std::vector<std::vector<std::string>> segments; + std::string language; +}; + +class ProgressWorker : public Napi::AsyncWorker { + public: + ProgressWorker(Napi::Function& callback, whisper_params params, Napi::Function progress_callback, Napi::Env env) + : Napi::AsyncWorker(callback), params(params), env(env) { + // Create thread-safe function + if (!progress_callback.IsEmpty()) { + tsfn = Napi::ThreadSafeFunction::New( + env, + progress_callback, + "Progress Callback", + 0, + 1 + ); + } + } + + ~ProgressWorker() { + if (tsfn) { + // Make sure to release the thread-safe function on destruction + tsfn.Release(); + } + } + + void Execute() override { + // Use custom run function with progress callback support + run_with_progress(params, result); + } + + void OnOK() override { + Napi::HandleScope scope(Env()); + + if (params.detect_language) { + Napi::Object resultObj = Napi::Object::New(Env()); + resultObj.Set("language", Napi::String::New(Env(), result.language)); + Callback().Call({Env().Null(), resultObj}); + } + + Napi::Object returnObj = Napi::Object::New(Env()); + if (!result.language.empty()) { + returnObj.Set("language", Napi::String::New(Env(), result.language)); + } + Napi::Array transcriptionArray = Napi::Array::New(Env(), result.segments.size()); + for (uint64_t i = 0; i < result.segments.size(); ++i) { + Napi::Object tmp = Napi::Array::New(Env(), 3); + for (uint64_t j = 0; j < 3; ++j) { + tmp[j] = Napi::String::New(Env(), result.segments[i][j]); + } + transcriptionArray[i] = tmp; + } + returnObj.Set("transcription", transcriptionArray); + Callback().Call({Env().Null(), returnObj}); + } + + // Progress callback function - using thread-safe function + void OnProgress(int progress) { + if (tsfn) { + // Use thread-safe function to call JavaScript callback + auto callback = [progress](Napi::Env env, Napi::Function jsCallback) { + jsCallback.Call({Napi::Number::New(env, progress)}); + }; + + tsfn.BlockingCall(callback); + } + } + + private: + whisper_params params; + whisper_result result; + Napi::Env env; + Napi::ThreadSafeFunction tsfn; + + // Custom run function with progress callback support + int run_with_progress(whisper_params ¶ms, whisper_result & result) { + if (params.no_prints) { + whisper_log_set(cb_log_disable, NULL); + } + + if (params.fname_inp.empty() && params.pcmf32.empty()) { + fprintf(stderr, "error: no input files or audio buffer specified\n"); + return 2; + } + + if (params.language != "auto" && whisper_lang_id(params.language.c_str()) == -1) { + fprintf(stderr, "error: unknown language '%s'\n", params.language.c_str()); + exit(0); + } + + // whisper init + struct whisper_context_params cparams = whisper_context_default_params(); + cparams.use_gpu = params.use_gpu; + cparams.flash_attn = params.flash_attn; + struct whisper_context * ctx = whisper_init_from_file_with_params(params.model.c_str(), cparams); + + if (ctx == nullptr) { + fprintf(stderr, "error: failed to initialize whisper context\n"); + return 3; + } + + // If params.pcmf32 provides, set params.fname_inp as "buffer" + if (!params.pcmf32.empty()) { + fprintf(stderr, "info: using audio buffer as input\n"); + params.fname_inp.clear(); + params.fname_inp.emplace_back("buffer"); + } + + for (int f = 0; f < (int) params.fname_inp.size(); ++f) { + const auto fname_inp = params.fname_inp[f]; + const auto fname_out = f < (int)params.fname_out.size() && !params.fname_out[f].empty() ? params.fname_out[f] : params.fname_inp[f]; + + std::vector<float> pcmf32; // mono-channel F32 PCM + std::vector<std::vector<float>> pcmf32s; // stereo-channel F32 PCM + + // If params.pcmf32 is empty, read input audio file + if (params.pcmf32.empty()) { + if (!::read_audio_data(fname_inp, pcmf32, pcmf32s, params.diarize)) { + fprintf(stderr, "error: failed to read audio file '%s'\n", fname_inp.c_str()); + continue; + } + } else { + pcmf32 = params.pcmf32; + } + + // Print system info + if (!params.no_prints) { + fprintf(stderr, "\n"); + fprintf(stderr, "system_info: n_threads = %d / %d | %s\n", + params.n_threads*params.n_processors, std::thread::hardware_concurrency(), whisper_print_system_info()); + } + + // Print processing info + if (!params.no_prints) { + fprintf(stderr, "\n"); + if (!whisper_is_multilingual(ctx)) { + if (params.language != "en" || params.translate) { + params.language = "en"; + params.translate = false; + fprintf(stderr, "%s: WARNING: model is not multilingual, ignoring language and translation options\n", __func__); + } + } + fprintf(stderr, "%s: processing '%s' (%d samples, %.1f sec), %d threads, %d processors, lang = %s, task = %s, timestamps = %d, audio_ctx = %d ...\n", + __func__, fname_inp.c_str(), int(pcmf32.size()), float(pcmf32.size())/WHISPER_SAMPLE_RATE, + params.n_threads, params.n_processors, + params.language.c_str(), + params.translate ? "translate" : "transcribe", + params.no_timestamps ? 0 : 1, + params.audio_ctx); + + fprintf(stderr, "\n"); + } + + // Run inference + { + whisper_full_params wparams = whisper_full_default_params(WHISPER_SAMPLING_GREEDY); + + wparams.strategy = params.beam_size > 1 ? WHISPER_SAMPLING_BEAM_SEARCH : WHISPER_SAMPLING_GREEDY; + + wparams.print_realtime = false; + wparams.print_progress = params.print_progress; + wparams.print_timestamps = !params.no_timestamps; + wparams.print_special = params.print_special; + wparams.translate = params.translate; + wparams.language = params.detect_language ? "auto" : params.language.c_str(); + wparams.detect_language = params.detect_language; + wparams.n_threads = params.n_threads; + wparams.n_max_text_ctx = params.max_context >= 0 ? params.max_context : wparams.n_max_text_ctx; + wparams.offset_ms = params.offset_t_ms; + wparams.duration_ms = params.duration_ms; + + wparams.token_timestamps = params.output_wts || params.max_len > 0; + wparams.thold_pt = params.word_thold; + wparams.entropy_thold = params.entropy_thold; + wparams.logprob_thold = params.logprob_thold; + wparams.max_len = params.output_wts && params.max_len == 0 ? 60 : params.max_len; + wparams.audio_ctx = params.audio_ctx; + + wparams.greedy.best_of = params.best_of; + wparams.beam_search.beam_size = params.beam_size; + + wparams.initial_prompt = params.prompt.c_str(); + + wparams.no_timestamps = params.no_timestamps; + + whisper_print_user_data user_data = { ¶ms, &pcmf32s }; + + // This callback is called for each new segment + if (!wparams.print_realtime) { + wparams.new_segment_callback = whisper_print_segment_callback; + wparams.new_segment_callback_user_data = &user_data; + } + + // Set progress callback + wparams.progress_callback = [](struct whisper_context * /*ctx*/, struct whisper_state * /*state*/, int progress, void * user_data) { + ProgressWorker* worker = static_cast<ProgressWorker*>(user_data); + worker->OnProgress(progress); + }; + wparams.progress_callback_user_data = this; + + // Set VAD parameters + wparams.vad = params.vad; + wparams.vad_model_path = params.vad_model.c_str(); + + wparams.vad_params.threshold = params.vad_threshold; + wparams.vad_params.min_speech_duration_ms = params.vad_min_speech_duration_ms; + wparams.vad_params.min_silence_duration_ms = params.vad_min_silence_duration_ms; + wparams.vad_params.max_speech_duration_s = params.vad_max_speech_duration_s; + wparams.vad_params.speech_pad_ms = params.vad_speech_pad_ms; + wparams.vad_params.samples_overlap = params.vad_samples_overlap; + + if (whisper_full_parallel(ctx, wparams, pcmf32.data(), pcmf32.size(), params.n_processors) != 0) { + fprintf(stderr, "failed to process audio\n"); + return 10; + } + } + } + + if (params.detect_language || params.language == "auto") { + result.language = whisper_lang_str(whisper_full_lang_id(ctx)); + } + const int n_segments = whisper_full_n_segments(ctx); + result.segments.resize(n_segments); + + for (int i = 0; i < n_segments; ++i) { + const char * text = whisper_full_get_segment_text(ctx, i); + const int64_t t0 = whisper_full_get_segment_t0(ctx, i); + const int64_t t1 = whisper_full_get_segment_t1(ctx, i); + + result.segments[i].emplace_back(to_timestamp(t0, params.comma_in_time)); + result.segments[i].emplace_back(to_timestamp(t1, params.comma_in_time)); + result.segments[i].emplace_back(text); + } + + whisper_print_timings(ctx); + whisper_free(ctx); + + return 0; + } +}; + +Napi::Value whisper(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + if (info.Length() <= 0 || !info[0].IsObject()) { + Napi::TypeError::New(env, "object expected").ThrowAsJavaScriptException(); + } + whisper_params params; + + Napi::Object whisper_params = info[0].As<Napi::Object>(); + std::string language = whisper_params.Get("language").As<Napi::String>(); + std::string model = whisper_params.Get("model").As<Napi::String>(); + std::string input = whisper_params.Get("fname_inp").As<Napi::String>(); + + bool use_gpu = true; + if (whisper_params.Has("use_gpu") && whisper_params.Get("use_gpu").IsBoolean()) { + use_gpu = whisper_params.Get("use_gpu").As<Napi::Boolean>(); + } + + bool flash_attn = false; + if (whisper_params.Has("flash_attn") && whisper_params.Get("flash_attn").IsBoolean()) { + flash_attn = whisper_params.Get("flash_attn").As<Napi::Boolean>(); + } + + bool no_prints = false; + if (whisper_params.Has("no_prints") && whisper_params.Get("no_prints").IsBoolean()) { + no_prints = whisper_params.Get("no_prints").As<Napi::Boolean>(); + } + + bool no_timestamps = false; + if (whisper_params.Has("no_timestamps") && whisper_params.Get("no_timestamps").IsBoolean()) { + no_timestamps = whisper_params.Get("no_timestamps").As<Napi::Boolean>(); + } + + bool detect_language = false; + if (whisper_params.Has("detect_language") && whisper_params.Get("detect_language").IsBoolean()) { + detect_language = whisper_params.Get("detect_language").As<Napi::Boolean>(); + } + + int32_t audio_ctx = 0; + if (whisper_params.Has("audio_ctx") && whisper_params.Get("audio_ctx").IsNumber()) { + audio_ctx = whisper_params.Get("audio_ctx").As<Napi::Number>(); + } + + bool comma_in_time = true; + if (whisper_params.Has("comma_in_time") && whisper_params.Get("comma_in_time").IsBoolean()) { + comma_in_time = whisper_params.Get("comma_in_time").As<Napi::Boolean>(); + } + + int32_t max_len = 0; + if (whisper_params.Has("max_len") && whisper_params.Get("max_len").IsNumber()) { + max_len = whisper_params.Get("max_len").As<Napi::Number>(); + } + + // Add support for max_context + int32_t max_context = -1; + if (whisper_params.Has("max_context") && whisper_params.Get("max_context").IsNumber()) { + max_context = whisper_params.Get("max_context").As<Napi::Number>(); + } + + // support prompt + std::string prompt = ""; + if (whisper_params.Has("prompt") && whisper_params.Get("prompt").IsString()) { + prompt = whisper_params.Get("prompt").As<Napi::String>(); + } + + // Add support for print_progress + bool print_progress = false; + if (whisper_params.Has("print_progress") && whisper_params.Get("print_progress").IsBoolean()) { + print_progress = whisper_params.Get("print_progress").As<Napi::Boolean>(); + } + // Add support for progress_callback + Napi::Function progress_callback; + if (whisper_params.Has("progress_callback") && whisper_params.Get("progress_callback").IsFunction()) { + progress_callback = whisper_params.Get("progress_callback").As<Napi::Function>(); + } + + // Add support for VAD parameters + bool vad = false; + if (whisper_params.Has("vad") && whisper_params.Get("vad").IsBoolean()) { + vad = whisper_params.Get("vad").As<Napi::Boolean>(); + } + + std::string vad_model = ""; + if (whisper_params.Has("vad_model") && whisper_params.Get("vad_model").IsString()) { + vad_model = whisper_params.Get("vad_model").As<Napi::String>(); + } + + float vad_threshold = 0.5f; + if (whisper_params.Has("vad_threshold") && whisper_params.Get("vad_threshold").IsNumber()) { + vad_threshold = whisper_params.Get("vad_threshold").As<Napi::Number>(); + } + + int vad_min_speech_duration_ms = 250; + if (whisper_params.Has("vad_min_speech_duration_ms") && whisper_params.Get("vad_min_speech_duration_ms").IsNumber()) { + vad_min_speech_duration_ms = whisper_params.Get("vad_min_speech_duration_ms").As<Napi::Number>(); + } + + int vad_min_silence_duration_ms = 100; + if (whisper_params.Has("vad_min_silence_duration_ms") && whisper_params.Get("vad_min_silence_duration_ms").IsNumber()) { + vad_min_silence_duration_ms = whisper_params.Get("vad_min_silence_duration_ms").As<Napi::Number>(); + } + + float vad_max_speech_duration_s = FLT_MAX; + if (whisper_params.Has("vad_max_speech_duration_s") && whisper_params.Get("vad_max_speech_duration_s").IsNumber()) { + vad_max_speech_duration_s = whisper_params.Get("vad_max_speech_duration_s").As<Napi::Number>(); + } + + int vad_speech_pad_ms = 30; + if (whisper_params.Has("vad_speech_pad_ms") && whisper_params.Get("vad_speech_pad_ms").IsNumber()) { + vad_speech_pad_ms = whisper_params.Get("vad_speech_pad_ms").As<Napi::Number>(); + } + + float vad_samples_overlap = 0.1f; + if (whisper_params.Has("vad_samples_overlap") && whisper_params.Get("vad_samples_overlap").IsNumber()) { + vad_samples_overlap = whisper_params.Get("vad_samples_overlap").As<Napi::Number>(); + } + + Napi::Value pcmf32Value = whisper_params.Get("pcmf32"); + std::vector<float> pcmf32_vec; + if (pcmf32Value.IsTypedArray()) { + Napi::Float32Array pcmf32 = pcmf32Value.As<Napi::Float32Array>(); + size_t length = pcmf32.ElementLength(); + pcmf32_vec.reserve(length); + for (size_t i = 0; i < length; i++) { + pcmf32_vec.push_back(pcmf32[i]); + } + } + + params.language = language; + params.model = model; + params.fname_inp.emplace_back(input); + params.use_gpu = use_gpu; + params.flash_attn = flash_attn; + params.no_prints = no_prints; + params.no_timestamps = no_timestamps; + params.audio_ctx = audio_ctx; + params.pcmf32 = pcmf32_vec; + params.comma_in_time = comma_in_time; + params.max_len = max_len; + params.max_context = max_context; + params.print_progress = print_progress; + params.prompt = prompt; + params.detect_language = detect_language; + + // Set VAD parameters + params.vad = vad; + params.vad_model = vad_model; + params.vad_threshold = vad_threshold; + params.vad_min_speech_duration_ms = vad_min_speech_duration_ms; + params.vad_min_silence_duration_ms = vad_min_silence_duration_ms; + params.vad_max_speech_duration_s = vad_max_speech_duration_s; + params.vad_speech_pad_ms = vad_speech_pad_ms; + params.vad_samples_overlap = vad_samples_overlap; + + Napi::Function callback = info[1].As<Napi::Function>(); + // Create a new Worker class with progress callback support + ProgressWorker* worker = new ProgressWorker(callback, params, progress_callback, env); + worker->Queue(); + return env.Undefined(); +} + + +Napi::Object Init(Napi::Env env, Napi::Object exports) { + exports.Set( + Napi::String::New(env, "whisper"), + Napi::Function::New(env, whisper) + ); + return exports; +} + +NODE_API_MODULE(whisper, Init); diff --git a/examples/addon.node/index.js b/examples/addon.node/index.js new file mode 100644 index 0000000..2e4ed61 --- /dev/null +++ b/examples/addon.node/index.js @@ -0,0 +1,59 @@ +const path = require('path'); +const os = require('os'); + +const isWindows = os.platform() === 'win32'; +const buildPath = isWindows ? "../../build/bin/Release/addon.node" : "../../build/Release/addon.node"; + +const { whisper } = require(path.join(__dirname, buildPath)); +const { promisify } = require("util"); + +const whisperAsync = promisify(whisper); + +const whisperParams = { + language: "en", + model: path.join(__dirname, "../../models/ggml-base.en.bin"), + fname_inp: path.join(__dirname, "../../samples/jfk.wav"), + use_gpu: true, + flash_attn: false, + no_prints: true, + comma_in_time: false, + translate: true, + no_timestamps: false, + detect_language: false, + audio_ctx: 0, + max_len: 0, + progress_callback: (progress) => { + console.log(`progress: ${progress}%`); + } +}; + +const arguments = process.argv.slice(2); +const params = Object.fromEntries( + arguments.reduce((pre, item) => { + if (item.startsWith("--")) { + const [key, value] = item.slice(2).split("="); + if (key === "audio_ctx") { + whisperParams[key] = parseInt(value); + } else if (key === "detect_language") { + whisperParams[key] = value === "true"; + } else { + whisperParams[key] = value; + } + return pre; + } + return pre; + }, []) +); + +for (const key in params) { + if (whisperParams.hasOwnProperty(key)) { + whisperParams[key] = params[key]; + } +} + +console.log("whisperParams =", whisperParams); + +whisperAsync(whisperParams).then((result) => { + console.log(); + console.log(result); +}); diff --git a/examples/addon.node/package-lock.json b/examples/addon.node/package-lock.json new file mode 100644 index 0000000..1d1a8cd --- /dev/null +++ b/examples/addon.node/package-lock.json @@ -0,0 +1,4359 @@ +{ + "name": "addon.node", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "addon.node", + "version": "0.0.0", + "license": "MIT", + "devDependencies": { + "cmake-js": "^7.1.1", + "jest": "^29.4.0", + "node-addon-api": "^5.0.0" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.26.8", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz", + "integrity": "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz", + "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.10", + "@babel/helper-compilation-targets": "^7.26.5", + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helpers": "^7.26.10", + "@babel/parser": "^7.26.10", + "@babel/template": "^7.26.9", + "@babel/traverse": "^7.26.10", + "@babel/types": "^7.26.10", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.0.tgz", + "integrity": "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.27.0", + "@babel/types": "^7.27.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.0.tgz", + "integrity": "sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.26.8", + "@babel/helper-validator-option": "^7.25.9", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", + "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", + "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", + "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.0.tgz", + "integrity": "sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.27.0", + "@babel/types": "^7.27.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz", + "integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.27.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz", + "integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz", + "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz", + "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz", + "integrity": "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.26.2", + "@babel/parser": "^7.27.0", + "@babel/types": "^7.27.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.0.tgz", + "integrity": "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.27.0", + "@babel/parser": "^7.27.0", + "@babel/template": "^7.27.0", + "@babel/types": "^7.27.0", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz", + "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", + "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/node": { + "version": "22.13.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.13.tgz", + "integrity": "sha512-ClsL5nMwKaBRwPcCvH8E7+nU4GxHVx1axNvMZTFHMEfNI7oahimt26P5zjVCRrjiIWj6YFXfE1v3dEp94wLcGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.20.0" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/yargs": { + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/are-we-there-yet": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", + "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", + "deprecated": "This package is no longer supported.", + "dev": true, + "license": "ISC", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.8.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.4.tgz", + "integrity": "sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz", + "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dev": true, + "license": "MIT", + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", + "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "caniuse-lite": "^1.0.30001688", + "electron-to-chromium": "^1.5.73", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.1" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001707", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001707.tgz", + "integrity": "sha512-3qtRjw/HQSMlDWf+X79N206fepf4SOOU6SQLMaq/0KkZLmSjPxAkBOQQ+FxbHKfHmYLZFfdWsO3KA90ceHPSnw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", + "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cmake-js": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/cmake-js/-/cmake-js-7.3.0.tgz", + "integrity": "sha512-dXs2zq9WxrV87bpJ+WbnGKv8WUBXDw8blNiwNHoRe/it+ptscxhQHKB1SJXa1w+kocLMeP28Tk4/eTCezg4o+w==", + "dev": true, + "license": "MIT", + "dependencies": { + "axios": "^1.6.5", + "debug": "^4", + "fs-extra": "^11.2.0", + "lodash.isplainobject": "^4.0.6", + "memory-stream": "^1.0.0", + "node-api-headers": "^1.1.0", + "npmlog": "^6.0.2", + "rc": "^1.2.7", + "semver": "^7.5.4", + "tar": "^6.2.0", + "url-join": "^4.0.1", + "which": "^2.0.2", + "yargs": "^17.7.2" + }, + "bin": { + "cmake-js": "bin/cmake-js" + }, + "engines": { + "node": ">= 14.15.0" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true, + "license": "ISC", + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/dedent": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", + "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.123", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.123.tgz", + "integrity": "sha512-refir3NlutEZqlKaBLK0tzlVLe5P2wDKS7UQt/3SpibizgsRAPOsqQC3ffw1nlv3ze5gjRQZYHoPymgVZkplFA==", + "dev": true, + "license": "ISC" + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", + "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fs-extra": { + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz", + "integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs-minipass/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gauge": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "deprecated": "This package is no longer supported.", + "dev": true, + "license": "ISC", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true, + "license": "MIT" + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true, + "license": "ISC" + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true, + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/memory-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/memory-stream/-/memory-stream-1.0.0.tgz", + "integrity": "sha512-Wm13VcsPIMdG96dzILfij09PvuS3APtcKNh7M28FsCA/w6+1mjR7hhPmfFNoilX9xU7wTdhsH5lJAm6XNzdtww==", + "dev": true, + "license": "MIT", + "dependencies": { + "readable-stream": "^3.4.0" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-addon-api": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-api-headers": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/node-api-headers/-/node-api-headers-1.5.0.tgz", + "integrity": "sha512-Yi/FgnN8IU/Cd6KeLxyHkylBUvDTsSScT0Tna2zTrz8klmc8qF2ppj6Q1LHsmOueJWhigQwR4cO2p0XBGW5IaQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "dev": true, + "license": "MIT" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npmlog": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", + "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", + "deprecated": "This package is no longer supported.", + "dev": true, + "license": "ISC", + "dependencies": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-locate/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true, + "license": "MIT" + }, + "node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true, + "license": "MIT" + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve.exports": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", + "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true, + "license": "ISC" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true, + "license": "MIT" + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "dev": true, + "license": "ISC", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/undici-types": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "dev": true, + "license": "MIT" + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/url-join": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", + "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", + "dev": true, + "license": "MIT" + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "dev": true, + "license": "ISC", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/examples/addon.node/package.json b/examples/addon.node/package.json new file mode 100644 index 0000000..50046bf --- /dev/null +++ b/examples/addon.node/package.json @@ -0,0 +1,16 @@ +{ + "name": "addon.node", + "version": "0.0.0", + "description": "", + "main": "index.js", + "author": "Qanhe Chen", + "license": "MIT", + "scripts": { + "test": "jest" + }, + "devDependencies": { + "cmake-js": "^7.1.1", + "jest": "^29.4.0", + "node-addon-api": "^5.0.0" + } +} diff --git a/examples/addon.node/vad-example.js b/examples/addon.node/vad-example.js new file mode 100644 index 0000000..bdbb5ec --- /dev/null +++ b/examples/addon.node/vad-example.js @@ -0,0 +1,132 @@ +const path = require("path"); +const { whisper } = require(path.join( + __dirname, + "../../build/Release/addon.node" +)); +const { promisify } = require("util"); + +const whisperAsync = promisify(whisper); + +// Example with VAD enabled +const vadParams = { + language: "en", + model: path.join(__dirname, "../../models/ggml-base.en.bin"), + fname_inp: path.join(__dirname, "../../samples/jfk.wav"), + use_gpu: true, + flash_attn: false, + no_prints: false, + comma_in_time: true, + translate: false, + no_timestamps: false, + detect_language: false, + audio_ctx: 0, + max_len: 0, + // VAD parameters + vad: true, + vad_model: path.join(__dirname, "../../models/ggml-silero-v6.2.0.bin"), // You need to download this model + vad_threshold: 0.5, + vad_min_speech_duration_ms: 250, + vad_min_silence_duration_ms: 100, + vad_max_speech_duration_s: 30.0, + vad_speech_pad_ms: 30, + vad_samples_overlap: 0.1, + progress_callback: (progress) => { + console.log(`VAD Transcription progress: ${progress}%`); + } +}; + +// Example without VAD (traditional approach) +const traditionalParams = { + language: "en", + model: path.join(__dirname, "../../models/ggml-base.en.bin"), + fname_inp: path.join(__dirname, "../../samples/jfk.wav"), + use_gpu: true, + flash_attn: false, + no_prints: false, + comma_in_time: true, + translate: false, + no_timestamps: false, + detect_language: false, + audio_ctx: 0, + max_len: 0, + vad: false, // Explicitly disable VAD + progress_callback: (progress) => { + console.log(`Traditional transcription progress: ${progress}%`); + } +}; + +async function runVADExample() { + try { + console.log("=== Whisper.cpp Node.js VAD Example ===\n"); + + // Check if VAD model exists + const fs = require('fs'); + if (!fs.existsSync(vadParams.vad_model)) { + console.log("⚠️ VAD model not found. Please download the VAD model first:"); + console.log(" ./models/download-vad-model.sh silero-v6.2.0"); + console.log(" Or run: python models/convert-silero-vad-to-ggml.py"); + console.log("\n Falling back to traditional transcription without VAD...\n"); + + // Run without VAD + console.log("🎵 Running traditional transcription..."); + const traditionalResult = await whisperAsync(traditionalParams); + console.log("\n📝 Traditional transcription result:"); + console.log(traditionalResult); + return; + } + + console.log("🎵 Running transcription with VAD enabled..."); + console.log("VAD Parameters:"); + console.log(` - Threshold: ${vadParams.vad_threshold}`); + console.log(` - Min speech duration: ${vadParams.vad_min_speech_duration_ms}ms`); + console.log(` - Min silence duration: ${vadParams.vad_min_silence_duration_ms}ms`); + console.log(` - Max speech duration: ${vadParams.vad_max_speech_duration_s}s`); + console.log(` - Speech padding: ${vadParams.vad_speech_pad_ms}ms`); + console.log(` - Samples overlap: ${vadParams.vad_samples_overlap}\n`); + + const startTime = Date.now(); + const vadResult = await whisperAsync(vadParams); + const vadDuration = Date.now() - startTime; + + console.log("\n✅ VAD transcription completed!"); + console.log(`⏱️ Processing time: ${vadDuration}ms`); + console.log("\n📝 VAD transcription result:"); + console.log(vadResult); + + // Compare with traditional approach + console.log("\n🔄 Running traditional transcription for comparison..."); + const traditionalStartTime = Date.now(); + const traditionalResult = await whisperAsync(traditionalParams); + const traditionalDuration = Date.now() - traditionalStartTime; + + console.log("\n✅ Traditional transcription completed!"); + console.log(`⏱️ Processing time: ${traditionalDuration}ms`); + console.log("\n📝 Traditional transcription result:"); + console.log(traditionalResult); + + // Performance comparison + console.log("\n📊 Performance Comparison:"); + console.log(`VAD: ${vadDuration}ms`); + console.log(`Traditional: ${traditionalDuration}ms`); + const speedup = traditionalDuration / vadDuration; + if (speedup > 1) { + console.log(`🚀 VAD is ${speedup.toFixed(2)}x faster!`); + } else { + console.log(`ℹ️ Traditional approach was ${(1/speedup).toFixed(2)}x faster in this case.`); + } + + } catch (error) { + console.error("❌ Error during transcription:", error); + } +} + +// Run the example +if (require.main === module) { + runVADExample(); +} + +module.exports = { + runVADExample, + vadParams, + traditionalParams +}; \ No newline at end of file diff --git a/examples/bench.wasm/CMakeLists.txt b/examples/bench.wasm/CMakeLists.txt new file mode 100644 index 0000000..8e134aa --- /dev/null +++ b/examples/bench.wasm/CMakeLists.txt @@ -0,0 +1,49 @@ +# +# libbench +# + +set(TARGET libbench) + +add_executable(${TARGET} + emscripten.cpp + ) + +include(DefaultTargetOptions) + +target_link_libraries(${TARGET} PRIVATE + whisper + ) + +unset(EXTRA_FLAGS) + +if (WHISPER_WASM_SINGLE_FILE) + set(EXTRA_FLAGS "-s SINGLE_FILE=1") + message(STATUS "Embedding WASM inside bench.js") + + add_custom_command( + TARGET ${TARGET} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_BINARY_DIR}/bin/libbench.js + ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/bench.wasm/bench.js + ) +endif() + +set_target_properties(${TARGET} PROPERTIES LINK_FLAGS " \ + --bind \ + -s USE_PTHREADS=1 \ + -s PTHREAD_POOL_SIZE_STRICT=0 \ + -s INITIAL_MEMORY=2000MB \ + -s TOTAL_MEMORY=2000MB \ + -s FORCE_FILESYSTEM=1 \ + -s EXPORTED_RUNTIME_METHODS=\"['print', 'printErr', 'ccall', 'cwrap', 'HEAPU8']\" \ + ${EXTRA_FLAGS} \ + ") + +# +# bench.wasm +# + +set(TARGET bench.wasm) + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/index-tmpl.html ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TARGET}/index.html @ONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../helpers.js ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TARGET}/helpers.js @ONLY) diff --git a/examples/bench.wasm/README.md b/examples/bench.wasm/README.md new file mode 100644 index 0000000..be38c37 --- /dev/null +++ b/examples/bench.wasm/README.md @@ -0,0 +1,47 @@ +# bench.wasm + +Benchmark the performance of whisper.cpp in the browser using WebAssembly + +Link: https://ggml.ai/whisper.cpp/bench.wasm/ + +Terminal version: [examples/bench](/examples/bench) + +## Build instructions + +```bash +# build using Emscripten (v3.1.2) +git clone https://github.com/ggerganov/whisper.cpp +cd whisper.cpp +mkdir build-em && cd build-em +emcmake cmake .. +make -j +``` +The example can then be started by running a local HTTP server: +```console +python3 examples/server.py +``` +And then opening a browser to the following URL: +http://localhost:8000/bench.wasm + +To run the example in a different server, you need to copy the following files +to the server's HTTP path: +``` +# copy the produced page to your HTTP path +cp bin/bench.wasm/* /path/to/html/ +cp bin/libbench.js /path/to/html/ +cp bin/libbench.worker.js /path/to/html/ +``` + +> 📝 **Note:** By default this example is built with `WHISPER_WASM_SINGLE_FILE=ON` +> which means that that a separate .wasm file will not be generated. Instead, the +> WASM module is embedded in the main JS file as a base64 encoded string. To +> generate a separate .wasm file, you need to disable this option by passing +> `-DWHISPER_WASM_SINGLE_FILE=OFF`: +> ```console +> emcmake cmake .. -DWHISPER_WASM_SINGLE_FILE=OFF +> ``` +> This will generate a `libbench.wasm` file in the build/bin directory. + +> 📝 **Note:** As of Emscripten 3.1.58 (April 2024), separate worker.js files are no +> longer generated and the worker is embedded in the main JS file. So the worker +> file will not be generated for versions later than `3.1.58`. diff --git a/examples/bench.wasm/emscripten.cpp b/examples/bench.wasm/emscripten.cpp new file mode 100644 index 0000000..7e9f277 --- /dev/null +++ b/examples/bench.wasm/emscripten.cpp @@ -0,0 +1,87 @@ +#include "whisper.h" + +#include <emscripten.h> +#include <emscripten/bind.h> + +#include <cmath> +#include <string> +#include <thread> +#include <vector> + +constexpr int N_THREAD = 8; + +// TODO: get rid of this vector of contexts - bad idea in the first place +std::vector<struct whisper_context *> g_contexts(4, nullptr); + +std::thread g_worker; + +void bench_main(size_t index) { + const int n_threads = std::min(N_THREAD, (int) std::thread::hardware_concurrency()); + + // whisper context + auto & ctx = g_contexts[index]; + + fprintf(stderr, "%s: running benchmark with %d threads - please wait...\n", __func__, n_threads); + + const int n_mels = whisper_model_n_mels(ctx); + + if (int ret = whisper_set_mel(ctx, nullptr, 0, n_mels)) { + fprintf(stderr, "error: failed to set mel: %d\n", ret); + return; + } + + { + fprintf(stderr, "\n"); + fprintf(stderr, "system_info: n_threads = %d / %d | %s\n", n_threads, std::thread::hardware_concurrency(), whisper_print_system_info()); + } + + if (int ret = whisper_encode(ctx, 0, n_threads) != 0) { + fprintf(stderr, "error: failed to encode model: %d\n", ret); + return; + } + + whisper_print_timings(ctx); + + fprintf(stderr, "\n"); + fprintf(stderr, "If you wish, you can submit these results here:\n"); + fprintf(stderr, "\n"); + fprintf(stderr, " https://github.com/ggml-org/whisper.cpp/issues/89\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Please include the following information:\n"); + fprintf(stderr, "\n"); + fprintf(stderr, " - CPU model\n"); + fprintf(stderr, " - Operating system\n"); + fprintf(stderr, " - Browser\n"); + fprintf(stderr, "\n"); +} + +EMSCRIPTEN_BINDINGS(bench) { + emscripten::function("init", emscripten::optional_override([](const std::string & path_model) { + for (size_t i = 0; i < g_contexts.size(); ++i) { + if (g_contexts[i] == nullptr) { + g_contexts[i] = whisper_init_from_file_with_params(path_model.c_str(), whisper_context_default_params()); + if (g_contexts[i] != nullptr) { + if (g_worker.joinable()) { + g_worker.join(); + } + g_worker = std::thread([i]() { + bench_main(i); + }); + + return i + 1; + } else { + return (size_t) 0; + } + } + } + + return (size_t) 0; + })); + + emscripten::function("free", emscripten::optional_override([](size_t index) { + if (index < g_contexts.size()) { + whisper_free(g_contexts[index]); + g_contexts[index] = nullptr; + } + })); +} diff --git a/examples/bench.wasm/index-tmpl.html b/examples/bench.wasm/index-tmpl.html new file mode 100644 index 0000000..3a94174 --- /dev/null +++ b/examples/bench.wasm/index-tmpl.html @@ -0,0 +1,285 @@ +<!doctype html> +<html lang="en-us"> + <head> + <title>bench : Benchmark whisper.cpp performance in the browser + + + + + + +
+ bench : Benchmark whisper.cpp performance in the browser + +

+ + You can find more about this project on GitHub. + +

+ + More examples: + main | + bench | + stream | + command | + wchess | + +

+ +
+ + Select the model you would like to use and click the "Bench" button.
+ The results will be displayed in the textarea below. + +

+ +
+ Whisper model: + + + + +

+ Quantized models:

+ + + + + + +
+ +
+ +
+ + +
+ +
+ + Debug output: + + +
+ + Troubleshooting + +

+ + The page does some heavy computations, so make sure: + +
    +
  • To use a modern web browser (e.g. Chrome, Firefox)
  • +
  • To use a fast desktop or laptop computer (i.e. not a mobile phone)
  • +
  • Your browser supports WASM Fixed-width SIMD
  • +
+ +
+ + | + Build time: @GIT_DATE@ | + Commit hash: @GIT_SHA1@ | + Commit subject: @GIT_COMMIT_SUBJECT@ | + Source Code | + +
+
+ + + + + + diff --git a/examples/bench/CMakeLists.txt b/examples/bench/CMakeLists.txt new file mode 100644 index 0000000..f255f2d --- /dev/null +++ b/examples/bench/CMakeLists.txt @@ -0,0 +1,8 @@ +set(TARGET whisper-bench) +add_executable(${TARGET} bench.cpp) + +include(DefaultTargetOptions) + +target_link_libraries(${TARGET} PRIVATE whisper ${CMAKE_THREAD_LIBS_INIT}) + +install(TARGETS ${TARGET} RUNTIME) diff --git a/examples/bench/README.md b/examples/bench/README.md new file mode 100644 index 0000000..9002e2d --- /dev/null +++ b/examples/bench/README.md @@ -0,0 +1,51 @@ +# whisper.cpp/examples/bench + +A very basic tool for benchmarking the inference performance on your device. The tool simply runs the Encoder part of +the transformer on some random audio data and records the execution time. This way we can have an objective comparison +of the performance of the model for various setups. + +Benchmark results are tracked in the following Github issue: https://github.com/ggml-org/whisper.cpp/issues/89 + +```bash +# run the bench too on the small.en model using 4 threads +$ ./build/bin/whisper-bench -m ./models/ggml-small.en.bin -t 4 + +whisper_model_load: loading model from './models/ggml-small.en.bin' +whisper_model_load: n_vocab = 51864 +whisper_model_load: n_audio_ctx = 1500 +whisper_model_load: n_audio_state = 768 +whisper_model_load: n_audio_head = 12 +whisper_model_load: n_audio_layer = 12 +whisper_model_load: n_text_ctx = 448 +whisper_model_load: n_text_state = 768 +whisper_model_load: n_text_head = 12 +whisper_model_load: n_text_layer = 12 +whisper_model_load: n_mels = 80 +whisper_model_load: f16 = 1 +whisper_model_load: type = 3 +whisper_model_load: mem_required = 1048.00 MB +whisper_model_load: adding 1607 extra tokens +whisper_model_load: ggml ctx size = 533.05 MB +whisper_model_load: memory size = 68.48 MB +whisper_model_load: model size = 464.44 MB + +whisper_print_timings: load time = 240.82 ms +whisper_print_timings: mel time = 0.00 ms +whisper_print_timings: sample time = 0.00 ms +whisper_print_timings: encode time = 1062.21 ms / 88.52 ms per layer +whisper_print_timings: decode time = 0.00 ms / 0.00 ms per layer +whisper_print_timings: total time = 1303.04 ms + +system_info: n_threads = 4 | AVX2 = 0 | AVX512 = 0 | NEON = 1 | FP16_VA = 1 | WASM_SIMD = 0 | BLAS = 1 | + +If you wish, you can submit these results here: + + https://github.com/ggml-org/whisper.cpp/issues/89 + +Please include the following information: + + - CPU model + - Operating system + - Compiler + +``` diff --git a/examples/bench/bench.cpp b/examples/bench/bench.cpp new file mode 100644 index 0000000..84915c5 --- /dev/null +++ b/examples/bench/bench.cpp @@ -0,0 +1,191 @@ +#include "whisper.h" + +#include +#include +#include +#include + +// command-line parameters +struct whisper_params { + int32_t n_threads = std::min(4, (int32_t) std::thread::hardware_concurrency()); + int32_t what = 0; // what to benchmark: 0 - whisper encoder, 1 - memcpy, 2 - ggml_mul_mat + + std::string model = "models/ggml-base.en.bin"; + + bool use_gpu = true; + bool flash_attn = true; +}; + +void whisper_print_usage(int argc, char ** argv, const whisper_params & params); + +static bool whisper_params_parse(int argc, char ** argv, whisper_params & params) { + for (int i = 1; i < argc; i++) { + std::string arg = argv[i]; + + if (arg == "-h" || arg == "--help") { + whisper_print_usage(argc, argv, params); + exit(0); + } + else if (arg == "-t" || arg == "--threads") { params.n_threads = std::stoi(argv[++i]); } + else if (arg == "-m" || arg == "--model") { params.model = argv[++i]; } + else if (arg == "-w" || arg == "--what") { params.what = atoi(argv[++i]); } + else if (arg == "-ng" || arg == "--no-gpu") { params.use_gpu = false; } + else if (arg == "-fa" || arg == "--flash-attn") { params.flash_attn = true; } + else if (arg == "-nfa" || arg == "--no-flash-attn") { params.flash_attn = false; } + else { + fprintf(stderr, "error: unknown argument: %s\n", arg.c_str()); + whisper_print_usage(argc, argv, params); + exit(0); + } + } + + return true; +} + +void whisper_print_usage(int /*argc*/, char ** argv, const whisper_params & params) { + fprintf(stderr, "\n"); + fprintf(stderr, "usage: %s [options]\n", argv[0]); + fprintf(stderr, "\n"); + fprintf(stderr, "options:\n"); + fprintf(stderr, " -h, --help [default] show this help message and exit\n"); + fprintf(stderr, " -t N, --threads N [%-7d] number of threads to use during computation\n", params.n_threads); + fprintf(stderr, " -m FNAME, --model FNAME [%-7s] model path\n", params.model.c_str()); + fprintf(stderr, " -w N, --what N [%-7d] what to benchmark:\n", params.what); + fprintf(stderr, " %-7s 0 - whisper\n", ""); + fprintf(stderr, " %-7s 1 - memcpy\n", ""); + fprintf(stderr, " %-7s 2 - ggml_mul_mat\n", ""); + fprintf(stderr, " -ng, --no-gpu [%-7s] disable GPU\n", params.use_gpu ? "false" : "true"); + fprintf(stderr, " -fa, --flash-attn [%-7s] enable flash attention\n", params.flash_attn ? "true" : "false"); + fprintf(stderr, " -nfa, --no-flash-attn [%-7s] disable flash attention\n", params.flash_attn ? "false" : "true"); + fprintf(stderr, "\n"); +} + +static int whisper_bench_full(const whisper_params & params) { + // whisper init + + struct whisper_context_params cparams = whisper_context_default_params(); + + cparams.use_gpu = params.use_gpu; + cparams.flash_attn = params.flash_attn; + + { + fprintf(stderr, "\n"); + fprintf(stderr, "system_info: n_threads = %d / %d | %s\n", params.n_threads, std::thread::hardware_concurrency(), whisper_print_system_info()); + } + + struct whisper_context * ctx = whisper_init_from_file_with_params(params.model.c_str(), cparams); + if (ctx == nullptr) { + fprintf(stderr, "error: failed to initialize whisper context\n"); + return 2; + } + + const int n_mels = whisper_model_n_mels(ctx); + + if (int ret = whisper_set_mel(ctx, nullptr, 0, n_mels)) { + fprintf(stderr, "error: failed to set mel: %d\n", ret); + return 3; + } + + whisper_token tokens[512]; + memset(tokens, 0, sizeof(tokens)); + + // TODO: need 2 loops because of the current graph capture logic in the CUDA backend + // https://github.com/ggml-org/llama.cpp/pull/19754 + for (int h = 0; h < 2; ++h) { + // heat encoder + if (int ret = whisper_encode(ctx, 0, params.n_threads) != 0) { + fprintf(stderr, "error: failed to encode: %d\n", ret); + return 4; + } + + // prompt heat + if (int ret = whisper_decode(ctx, tokens, 256, 0, params.n_threads) != 0) { + fprintf(stderr, "error: failed to decode: %d\n", ret); + return 4; + } + + // text-generation heat + for (int i = 0; i < 256; i++) { + if (int ret = whisper_decode(ctx, tokens, 1, i, params.n_threads) != 0) { + fprintf(stderr, "error: failed to decode: %d\n", ret); + return 4; + } + } + + // batched heat + if (int ret = whisper_decode(ctx, tokens, 5, 0, params.n_threads) != 0) { + fprintf(stderr, "error: failed to decode: %d\n", ret); + return 4; + } + } + + whisper_reset_timings(ctx); + + // actual run + if (int ret = whisper_encode(ctx, 0, params.n_threads) != 0) { + fprintf(stderr, "error: failed to encode: %d\n", ret); + return 4; + } + + // text-generation + for (int i = 0; i < 256; i++) { + if (int ret = whisper_decode(ctx, tokens, 1, i, params.n_threads) != 0) { + fprintf(stderr, "error: failed to decode: %d\n", ret); + return 4; + } + } + + // batched decoding + for (int i = 0; i < 64; i++) { + if (int ret = whisper_decode(ctx, tokens, 5, 0, params.n_threads) != 0) { + fprintf(stderr, "error: failed to decode: %d\n", ret); + return 4; + } + } + + // prompt processing + for (int i = 0; i < 16; i++) { + if (int ret = whisper_decode(ctx, tokens, 256, 0, params.n_threads) != 0) { + fprintf(stderr, "error: failed to decode: %d\n", ret); + return 4; + } + } + + whisper_print_timings(ctx); + whisper_free(ctx); + + fprintf(stderr, "\n"); + fprintf(stderr, "If you wish, you can submit these results here:\n"); + fprintf(stderr, "\n"); + fprintf(stderr, " https://github.com/ggml-org/whisper.cpp/issues/89\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Please include the following information:\n"); + fprintf(stderr, "\n"); + fprintf(stderr, " - CPU model\n"); + fprintf(stderr, " - Operating system\n"); + fprintf(stderr, " - Compiler\n"); + fprintf(stderr, "\n"); + + return 0; +} + +int main(int argc, char ** argv) { + ggml_backend_load_all(); + + whisper_params params; + + if (whisper_params_parse(argc, argv, params) == false) { + return 1; + } + + int ret = -1; + + switch (params.what) { + case 0: ret = whisper_bench_full(params); break; + case 1: ret = whisper_bench_memcpy(params.n_threads); break; + case 2: ret = whisper_bench_ggml_mul_mat(params.n_threads); break; + default: fprintf(stderr, "error: unknown benchmark: %d\n", params.what); break; + } + + return ret; +} diff --git a/examples/cli/CMakeLists.txt b/examples/cli/CMakeLists.txt new file mode 100644 index 0000000..3a73776 --- /dev/null +++ b/examples/cli/CMakeLists.txt @@ -0,0 +1,8 @@ +set(TARGET whisper-cli) +add_executable(${TARGET} cli.cpp) + +include(DefaultTargetOptions) + +target_link_libraries(${TARGET} PRIVATE common whisper ${FFMPEG_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) + +install(TARGETS ${TARGET} RUNTIME) diff --git a/examples/cli/README.md b/examples/cli/README.md new file mode 100644 index 0000000..65285c3 --- /dev/null +++ b/examples/cli/README.md @@ -0,0 +1,66 @@ +# whisper.cpp/examples/cli + +This is the main example demonstrating most of the functionality of the Whisper model. +It can be used as a reference for using the `whisper.cpp` library in other projects. + +``` +./build/bin/whisper-cli -h + +usage: ./build/bin/whisper-cli [options] file0 file1 ... +supported audio formats: flac, mp3, ogg, wav + +options: + -h, --help [default] show this help message and exit + -t N, --threads N [4 ] number of threads to use during computation + -p N, --processors N [1 ] number of processors to use during computation + -ot N, --offset-t N [0 ] time offset in milliseconds + -on N, --offset-n N [0 ] segment index offset + -d N, --duration N [0 ] duration of audio to process in milliseconds + -mc N, --max-context N [-1 ] maximum number of text context tokens to store + -ml N, --max-len N [0 ] maximum segment length in characters + -sow, --split-on-word [false ] split on word rather than on token + -bo N, --best-of N [5 ] number of best candidates to keep + -bs N, --beam-size N [5 ] beam size for beam search + -ac N, --audio-ctx N [0 ] audio context size (0 - all) + -wt N, --word-thold N [0.01 ] word timestamp probability threshold + -et N, --entropy-thold N [2.40 ] entropy threshold for decoder fail + -lpt N, --logprob-thold N [-1.00 ] log probability threshold for decoder fail + -nth N, --no-speech-thold N [0.60 ] no speech threshold + -tp, --temperature N [0.00 ] The sampling temperature, between 0 and 1 + -tpi, --temperature-inc N [0.20 ] The increment of temperature, between 0 and 1 + -debug, --debug-mode [false ] enable debug mode (eg. dump log_mel) + -tr, --translate [false ] translate from source language to english + -di, --diarize [false ] stereo audio diarization + -tdrz, --tinydiarize [false ] enable tinydiarize (requires a tdrz model) + -nf, --no-fallback [false ] do not use temperature fallback while decoding + -otxt, --output-txt [false ] output result in a text file + -ovtt, --output-vtt [false ] output result in a vtt file + -osrt, --output-srt [false ] output result in a srt file + -olrc, --output-lrc [false ] output result in a lrc file + -owts, --output-words [false ] output script for generating karaoke video + -fp, --font-path [/System/Library/Fonts/Supplemental/Courier New Bold.ttf] path to a monospace font for karaoke video + -ocsv, --output-csv [false ] output result in a CSV file + -oj, --output-json [false ] output result in a JSON file + -ojf, --output-json-full [false ] include more information in the JSON file + -of FNAME, --output-file FNAME [ ] output file path (without file extension) + -np, --no-prints [false ] do not print anything other than the results + -ps, --print-special [false ] print special tokens + -pc, --print-colors [false ] print colors + -pp, --print-progress [false ] print progress + -nt, --no-timestamps [false ] do not print timestamps + -l LANG, --language LANG [en ] spoken language ('auto' for auto-detect) + -dl, --detect-language [false ] exit after automatically detecting language + --prompt PROMPT [ ] initial prompt (max n_text_ctx/2 tokens) + -m FNAME, --model FNAME [models/ggml-base.en.bin] model path + -f FNAME, --file FNAME [ ] input audio file path + -oved D, --ov-e-device DNAME [CPU ] the OpenVINO device used for encode inference + -dtw MODEL --dtw MODEL [ ] compute token-level timestamps + -ls, --log-score [false ] log best decoder scores of tokens + -ng, --no-gpu [false ] disable GPU + -fa, --flash-attn [false ] flash attention + -sns, --suppress-nst [false ] suppress non-speech tokens + --suppress-regex REGEX [ ] regular expression matching tokens to suppress + --grammar GRAMMAR [ ] GBNF grammar to guide decoding + --grammar-rule RULE [ ] top-level GBNF grammar rule name + --grammar-penalty N [100.0 ] scales down logits of nongrammar tokens +``` diff --git a/examples/cli/cli.cpp b/examples/cli/cli.cpp new file mode 100644 index 0000000..c64976a --- /dev/null +++ b/examples/cli/cli.cpp @@ -0,0 +1,1356 @@ +#include "common.h" +#include "common-whisper.h" + +#include "whisper.h" +#include "grammar-parser.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(_WIN32) +#ifndef NOMINMAX +#define NOMINMAX +#endif +#include +#endif + +// helper function to replace substrings +static void replace_all(std::string & s, const std::string & search, const std::string & replace) { + for (size_t pos = 0; ; pos += replace.length()) { + pos = s.find(search, pos); + if (pos == std::string::npos) break; + s.erase(pos, search.length()); + s.insert(pos, replace); + } +} + +// command-line parameters +struct whisper_params { + int32_t n_threads = std::min(4, (int32_t) std::thread::hardware_concurrency()); + int32_t n_processors = 1; + int32_t offset_t_ms = 0; + int32_t offset_n = 0; + int32_t duration_ms = 0; + int32_t progress_step = 5; + int32_t max_context = -1; + int32_t max_len = 0; + int32_t best_of = whisper_full_default_params(WHISPER_SAMPLING_GREEDY).greedy.best_of; + int32_t beam_size = whisper_full_default_params(WHISPER_SAMPLING_BEAM_SEARCH).beam_search.beam_size; + int32_t audio_ctx = 0; + + float word_thold = 0.01f; + float entropy_thold = 2.40f; + float logprob_thold = -1.00f; + float no_speech_thold = 0.6f; + float grammar_penalty = 100.0f; + float temperature = 0.0f; + float temperature_inc = 0.2f; + + bool debug_mode = false; + bool translate = false; + bool detect_language = false; + bool diarize = false; + bool tinydiarize = false; + bool split_on_word = false; + bool no_fallback = false; + bool output_txt = false; + bool output_vtt = false; + bool output_srt = false; + bool output_wts = false; + bool output_csv = false; + bool output_jsn = false; + bool output_jsn_full = false; + bool output_lrc = false; + bool no_prints = false; + bool print_special = false; + bool print_colors = false; + bool print_confidence= false; + bool print_progress = false; + bool no_timestamps = false; + bool log_score = false; + bool use_gpu = true; + bool flash_attn = true; + int32_t gpu_device = 0; + bool suppress_nst = false; + bool carry_initial_prompt = false; + + std::string language = "en"; + std::string prompt; + std::string font_path = "/System/Library/Fonts/Supplemental/Courier New Bold.ttf"; + std::string model = "models/ggml-base.en.bin"; + std::string grammar; + std::string grammar_rule; + + // [TDRZ] speaker turn string + std::string tdrz_speaker_turn = " [SPEAKER_TURN]"; // TODO: set from command line + + // A regular expression that matches tokens to suppress + std::string suppress_regex; + + std::string openvino_encode_device = "CPU"; + + std::string dtw = ""; + + std::vector fname_inp = {}; + std::vector fname_out = {}; + + grammar_parser::parse_state grammar_parsed; + + // Voice Activity Detection (VAD) parameters + bool vad = false; + std::string vad_model = ""; + float vad_threshold = 0.5f; + int vad_min_speech_duration_ms = 250; + int vad_min_silence_duration_ms = 100; + float vad_max_speech_duration_s = FLT_MAX; + int vad_speech_pad_ms = 30; + float vad_samples_overlap = 0.1f; +}; + +static void whisper_print_usage(int argc, char ** argv, const whisper_params & params); + +static char * whisper_param_turn_lowercase(char * in){ + int string_len = strlen(in); + for (int i = 0; i < string_len; i++){ + *(in+i) = tolower((unsigned char)*(in+i)); + } + return in; +} + +static char * requires_value_error(const std::string & arg) { + fprintf(stderr, "error: argument %s requires value\n", arg.c_str()); + exit(0); +} + +static bool whisper_params_parse(int argc, char ** argv, whisper_params & params) { + if (const char * env_device = std::getenv("WHISPER_ARG_DEVICE")) { + params.gpu_device = std::stoi(env_device); + } + + for (int i = 1; i < argc; i++) { + std::string arg = argv[i]; + + if (arg == "-"){ + params.fname_inp.push_back(arg); + continue; + } + + if (arg[0] != '-') { + params.fname_inp.push_back(arg); + continue; + } + + if (arg == "-h" || arg == "--help") { + whisper_print_usage(argc, argv, params); + exit(0); + } + if (arg == "--version") { + fprintf(stdout, "whisper.cpp version: %s\n", whisper_version()); + exit(0); + } + #define ARGV_NEXT (((i + 1) < argc) ? argv[++i] : requires_value_error(arg)) + else if (arg == "-t" || arg == "--threads") { params.n_threads = std::stoi(ARGV_NEXT); } + else if (arg == "-p" || arg == "--processors") { params.n_processors = std::stoi(ARGV_NEXT); } + else if (arg == "-ot" || arg == "--offset-t") { params.offset_t_ms = std::stoi(ARGV_NEXT); } + else if (arg == "-on" || arg == "--offset-n") { params.offset_n = std::stoi(ARGV_NEXT); } + else if (arg == "-d" || arg == "--duration") { params.duration_ms = std::stoi(ARGV_NEXT); } + else if (arg == "-mc" || arg == "--max-context") { params.max_context = std::stoi(ARGV_NEXT); } + else if (arg == "-ml" || arg == "--max-len") { params.max_len = std::stoi(ARGV_NEXT); } + else if (arg == "-bo" || arg == "--best-of") { params.best_of = std::stoi(ARGV_NEXT); } + else if (arg == "-bs" || arg == "--beam-size") { params.beam_size = std::stoi(ARGV_NEXT); } + else if (arg == "-ac" || arg == "--audio-ctx") { params.audio_ctx = std::stoi(ARGV_NEXT); } + else if (arg == "-wt" || arg == "--word-thold") { params.word_thold = std::stof(ARGV_NEXT); } + else if (arg == "-et" || arg == "--entropy-thold") { params.entropy_thold = std::stof(ARGV_NEXT); } + else if (arg == "-lpt" || arg == "--logprob-thold") { params.logprob_thold = std::stof(ARGV_NEXT); } + else if (arg == "-nth" || arg == "--no-speech-thold") { params.no_speech_thold = std::stof(ARGV_NEXT); } + else if (arg == "-tp" || arg == "--temperature") { params.temperature = std::stof(ARGV_NEXT); } + else if (arg == "-tpi" || arg == "--temperature-inc") { params.temperature_inc = std::stof(ARGV_NEXT); } + else if (arg == "-debug"|| arg == "--debug-mode") { params.debug_mode = true; } + else if (arg == "-tr" || arg == "--translate") { params.translate = true; } + else if (arg == "-di" || arg == "--diarize") { params.diarize = true; } + else if (arg == "-tdrz" || arg == "--tinydiarize") { params.tinydiarize = true; } + else if (arg == "-sow" || arg == "--split-on-word") { params.split_on_word = true; } + else if (arg == "-nf" || arg == "--no-fallback") { params.no_fallback = true; } + else if (arg == "-otxt" || arg == "--output-txt") { params.output_txt = true; } + else if (arg == "-ovtt" || arg == "--output-vtt") { params.output_vtt = true; } + else if (arg == "-osrt" || arg == "--output-srt") { params.output_srt = true; } + else if (arg == "-owts" || arg == "--output-words") { params.output_wts = true; } + else if (arg == "-olrc" || arg == "--output-lrc") { params.output_lrc = true; } + else if (arg == "-fp" || arg == "--font-path") { params.font_path = ARGV_NEXT; } + else if (arg == "-ocsv" || arg == "--output-csv") { params.output_csv = true; } + else if (arg == "-oj" || arg == "--output-json") { params.output_jsn = true; } + else if (arg == "-ojf" || arg == "--output-json-full") { params.output_jsn_full = params.output_jsn = true; } + else if (arg == "-of" || arg == "--output-file") { params.fname_out.emplace_back(ARGV_NEXT); } + else if (arg == "-np" || arg == "--no-prints") { params.no_prints = true; } + else if (arg == "-ps" || arg == "--print-special") { params.print_special = true; } + else if (arg == "-pc" || arg == "--print-colors") { params.print_colors = true; } + else if ( arg == "--print-confidence") { params.print_confidence= true; } + else if (arg == "-pp" || arg == "--print-progress") { params.print_progress = true; } + else if (arg == "-nt" || arg == "--no-timestamps") { params.no_timestamps = true; } + else if (arg == "-l" || arg == "--language") { params.language = whisper_param_turn_lowercase(ARGV_NEXT); } + else if (arg == "-dl" || arg == "--detect-language") { params.detect_language = true; } + else if ( arg == "--prompt") { params.prompt = ARGV_NEXT; } + else if ( arg == "--carry-initial-prompt") { params.carry_initial_prompt = true; } + else if (arg == "-m" || arg == "--model") { params.model = ARGV_NEXT; } + else if (arg == "-f" || arg == "--file") { params.fname_inp.emplace_back(ARGV_NEXT); } + else if (arg == "-oved" || arg == "--ov-e-device") { params.openvino_encode_device = ARGV_NEXT; } + else if (arg == "-dtw" || arg == "--dtw") { params.dtw = ARGV_NEXT; } + else if (arg == "-ls" || arg == "--log-score") { params.log_score = true; } + else if (arg == "-ng" || arg == "--no-gpu") { params.use_gpu = false; } + else if (arg == "-dev" || arg == "--device") { params.gpu_device = std::stoi(ARGV_NEXT); } + else if (arg == "-fa" || arg == "--flash-attn") { params.flash_attn = true; } + else if (arg == "-nfa" || arg == "--no-flash-attn") { params.flash_attn = false; } + else if (arg == "-sns" || arg == "--suppress-nst") { params.suppress_nst = true; } + else if ( arg == "--suppress-regex") { params.suppress_regex = ARGV_NEXT; } + else if ( arg == "--grammar") { params.grammar = ARGV_NEXT; } + else if ( arg == "--grammar-rule") { params.grammar_rule = ARGV_NEXT; } + else if ( arg == "--grammar-penalty") { params.grammar_penalty = std::stof(ARGV_NEXT); } + // Voice Activity Detection (VAD) + else if ( arg == "--vad") { params.vad = true; } + else if (arg == "-vm" || arg == "--vad-model") { params.vad_model = ARGV_NEXT; } + else if (arg == "-vt" || arg == "--vad-threshold") { params.vad_threshold = std::stof(ARGV_NEXT); } + else if (arg == "-vspd" || arg == "--vad-min-speech-duration-ms") { params.vad_min_speech_duration_ms = std::stoi(ARGV_NEXT); } + else if (arg == "-vsd" || arg == "--vad-min-silence-duration-ms") { params.vad_min_silence_duration_ms = std::stoi(ARGV_NEXT); } + else if (arg == "-vmsd" || arg == "--vad-max-speech-duration-s") { params.vad_max_speech_duration_s = std::stof(ARGV_NEXT); } + else if (arg == "-vp" || arg == "--vad-speech-pad-ms") { params.vad_speech_pad_ms = std::stoi(ARGV_NEXT); } + else if (arg == "-vo" || arg == "--vad-samples-overlap") { params.vad_samples_overlap = std::stof(ARGV_NEXT); } + else { + fprintf(stderr, "error: unknown argument: %s\n", arg.c_str()); + whisper_print_usage(argc, argv, params); + exit(0); + } + } + + return true; +} + +static void whisper_print_usage(int /*argc*/, char ** argv, const whisper_params & params) { + fprintf(stderr, "\n"); + fprintf(stderr, "usage: %s [options] file0 file1 ...\n", argv[0]); + fprintf(stderr, "supported audio formats: flac, mp3, ogg, wav\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "options:\n"); + fprintf(stderr, " -h, --help [default] show this help message and exit\n"); + fprintf(stderr, " --version show version information and exit\n"); + fprintf(stderr, " -t N, --threads N [%-7d] number of threads to use during computation\n", params.n_threads); + fprintf(stderr, " -p N, --processors N [%-7d] number of processors to use during computation\n", params.n_processors); + fprintf(stderr, " -ot N, --offset-t N [%-7d] time offset in milliseconds\n", params.offset_t_ms); + fprintf(stderr, " -on N, --offset-n N [%-7d] segment index offset\n", params.offset_n); + fprintf(stderr, " -d N, --duration N [%-7d] duration of audio to process in milliseconds\n", params.duration_ms); + fprintf(stderr, " -mc N, --max-context N [%-7d] maximum number of text context tokens to store\n", params.max_context); + fprintf(stderr, " -ml N, --max-len N [%-7d] maximum segment length in characters\n", params.max_len); + fprintf(stderr, " -sow, --split-on-word [%-7s] split on word rather than on token\n", params.split_on_word ? "true" : "false"); + fprintf(stderr, " -bo N, --best-of N [%-7d] number of best candidates to keep\n", params.best_of); + fprintf(stderr, " -bs N, --beam-size N [%-7d] beam size for beam search\n", params.beam_size); + fprintf(stderr, " -ac N, --audio-ctx N [%-7d] audio context size (0 - all)\n", params.audio_ctx); + fprintf(stderr, " -wt N, --word-thold N [%-7.2f] word timestamp probability threshold\n", params.word_thold); + fprintf(stderr, " -et N, --entropy-thold N [%-7.2f] entropy threshold for decoder fail\n", params.entropy_thold); + fprintf(stderr, " -lpt N, --logprob-thold N [%-7.2f] log probability threshold for decoder fail\n", params.logprob_thold); + fprintf(stderr, " -nth N, --no-speech-thold N [%-7.2f] no speech threshold\n", params.no_speech_thold); + fprintf(stderr, " -tp, --temperature N [%-7.2f] The sampling temperature, between 0 and 1\n", params.temperature); + fprintf(stderr, " -tpi, --temperature-inc N [%-7.2f] The increment of temperature, between 0 and 1\n",params.temperature_inc); + fprintf(stderr, " -debug, --debug-mode [%-7s] enable debug mode (eg. dump log_mel)\n", params.debug_mode ? "true" : "false"); + fprintf(stderr, " -tr, --translate [%-7s] translate from source language to english\n", params.translate ? "true" : "false"); + fprintf(stderr, " -di, --diarize [%-7s] stereo audio diarization\n", params.diarize ? "true" : "false"); + fprintf(stderr, " -tdrz, --tinydiarize [%-7s] enable tinydiarize (requires a tdrz model)\n", params.tinydiarize ? "true" : "false"); + fprintf(stderr, " -nf, --no-fallback [%-7s] do not use temperature fallback while decoding\n", params.no_fallback ? "true" : "false"); + fprintf(stderr, " -otxt, --output-txt [%-7s] output result in a text file\n", params.output_txt ? "true" : "false"); + fprintf(stderr, " -ovtt, --output-vtt [%-7s] output result in a vtt file\n", params.output_vtt ? "true" : "false"); + fprintf(stderr, " -osrt, --output-srt [%-7s] output result in a srt file\n", params.output_srt ? "true" : "false"); + fprintf(stderr, " -olrc, --output-lrc [%-7s] output result in a lrc file\n", params.output_lrc ? "true" : "false"); + fprintf(stderr, " -owts, --output-words [%-7s] output script for generating karaoke video\n", params.output_wts ? "true" : "false"); + fprintf(stderr, " -fp, --font-path [%-7s] path to a monospace font for karaoke video\n", params.font_path.c_str()); + fprintf(stderr, " -ocsv, --output-csv [%-7s] output result in a CSV file\n", params.output_csv ? "true" : "false"); + fprintf(stderr, " -oj, --output-json [%-7s] output result in a JSON file\n", params.output_jsn ? "true" : "false"); + fprintf(stderr, " -ojf, --output-json-full [%-7s] include more information in the JSON file\n", params.output_jsn_full ? "true" : "false"); + fprintf(stderr, " -of FNAME, --output-file FNAME [%-7s] output file path (without file extension)\n", ""); + fprintf(stderr, " -np, --no-prints [%-7s] do not print anything other than the results\n", params.no_prints ? "true" : "false"); + fprintf(stderr, " -ps, --print-special [%-7s] print special tokens\n", params.print_special ? "true" : "false"); + fprintf(stderr, " -pc, --print-colors [%-7s] print colors\n", params.print_colors ? "true" : "false"); + fprintf(stderr, " --print-confidence [%-7s] print confidence\n", params.print_confidence ? "true" : "false"); + fprintf(stderr, " -pp, --print-progress [%-7s] print progress\n", params.print_progress ? "true" : "false"); + fprintf(stderr, " -nt, --no-timestamps [%-7s] do not print timestamps\n", params.no_timestamps ? "true" : "false"); + fprintf(stderr, " -l LANG, --language LANG [%-7s] spoken language ('auto' for auto-detect)\n", params.language.c_str()); + fprintf(stderr, " -dl, --detect-language [%-7s] exit after automatically detecting language\n", params.detect_language ? "true" : "false"); + fprintf(stderr, " --prompt PROMPT [%-7s] initial prompt (max n_text_ctx/2 tokens)\n", params.prompt.c_str()); + fprintf(stderr, " --carry-initial-prompt [%-7s] always prepend initial prompt\n", params.carry_initial_prompt ? "true" : "false"); + fprintf(stderr, " -m FNAME, --model FNAME [%-7s] model path\n", params.model.c_str()); + fprintf(stderr, " -f FNAME, --file FNAME [%-7s] input audio file path\n", ""); + fprintf(stderr, " -oved D, --ov-e-device DNAME [%-7s] the OpenVINO device used for encode inference\n", params.openvino_encode_device.c_str()); + fprintf(stderr, " -dtw MODEL --dtw MODEL [%-7s] compute token-level timestamps\n", params.dtw.c_str()); + fprintf(stderr, " -ls, --log-score [%-7s] log best decoder scores of tokens\n", params.log_score?"true":"false"); + fprintf(stderr, " -ng, --no-gpu [%-7s] disable GPU\n", params.use_gpu ? "false" : "true"); + fprintf(stderr, " -dev N, --device N [%-7d] GPU device ID (default: 0)\n", params.gpu_device); + fprintf(stderr, " -fa, --flash-attn [%-7s] enable flash attention\n", params.flash_attn ? "true" : "false"); + fprintf(stderr, " -nfa, --no-flash-attn [%-7s] disable flash attention\n", params.flash_attn ? "false" : "true"); + fprintf(stderr, " -sns, --suppress-nst [%-7s] suppress non-speech tokens\n", params.suppress_nst ? "true" : "false"); + fprintf(stderr, " --suppress-regex REGEX [%-7s] regular expression matching tokens to suppress\n", params.suppress_regex.c_str()); + fprintf(stderr, " --grammar GRAMMAR [%-7s] GBNF grammar to guide decoding\n", params.grammar.c_str()); + fprintf(stderr, " --grammar-rule RULE [%-7s] top-level GBNF grammar rule name\n", params.grammar_rule.c_str()); + fprintf(stderr, " --grammar-penalty N [%-7.1f] scales down logits of nongrammar tokens\n", params.grammar_penalty); + // Voice Activity Detection (VAD) parameters + fprintf(stderr, "\nVoice Activity Detection (VAD) options:\n"); + fprintf(stderr, " --vad [%-7s] enable Voice Activity Detection (VAD)\n", params.vad ? "true" : "false"); + fprintf(stderr, " -vm FNAME, --vad-model FNAME [%-7s] VAD model path\n", params.vad_model.c_str()); + fprintf(stderr, " -vt N, --vad-threshold N [%-7.2f] VAD threshold for speech recognition\n", params.vad_threshold); + fprintf(stderr, " -vspd N, --vad-min-speech-duration-ms N [%-7d] VAD min speech duration (0.0-1.0)\n", params.vad_min_speech_duration_ms); + fprintf(stderr, " -vsd N, --vad-min-silence-duration-ms N [%-7d] VAD min silence duration (to split segments)\n", params.vad_min_silence_duration_ms); + fprintf(stderr, " -vmsd N, --vad-max-speech-duration-s N [%-7s] VAD max speech duration (auto-split longer)\n", params.vad_max_speech_duration_s == FLT_MAX ? + std::string("FLT_MAX").c_str() : + std::to_string(params.vad_max_speech_duration_s).c_str()); + fprintf(stderr, " -vp N, --vad-speech-pad-ms N [%-7d] VAD speech padding (extend segments)\n", params.vad_speech_pad_ms); + fprintf(stderr, " -vo N, --vad-samples-overlap N [%-7.2f] VAD samples overlap (seconds between segments)\n", params.vad_samples_overlap); + fprintf(stderr, "\n"); +} + +struct whisper_print_user_data { + const whisper_params * params; + + const std::vector> * pcmf32s; + int progress_prev; +}; + +static std::string estimate_diarization_speaker(std::vector> pcmf32s, int64_t t0, int64_t t1, bool id_only = false) { + std::string speaker = ""; + const int64_t n_samples = pcmf32s[0].size(); + + const int64_t is0 = timestamp_to_sample(t0, n_samples, WHISPER_SAMPLE_RATE); + const int64_t is1 = timestamp_to_sample(t1, n_samples, WHISPER_SAMPLE_RATE); + + double energy0 = 0.0f; + double energy1 = 0.0f; + + for (int64_t j = is0; j < is1; j++) { + energy0 += fabs(pcmf32s[0][j]); + energy1 += fabs(pcmf32s[1][j]); + } + + if (energy0 > 1.1*energy1) { + speaker = "0"; + } else if (energy1 > 1.1*energy0) { + speaker = "1"; + } else { + speaker = "?"; + } + + //printf("is0 = %lld, is1 = %lld, energy0 = %f, energy1 = %f, speaker = %s\n", is0, is1, energy0, energy1, speaker.c_str()); + + if (!id_only) { + speaker.insert(0, "(speaker "); + speaker.append(")"); + } + + return speaker; +} + +static void whisper_print_progress_callback(struct whisper_context * /*ctx*/, struct whisper_state * /*state*/, int progress, void * user_data) { + int progress_step = ((whisper_print_user_data *) user_data)->params->progress_step; + int * progress_prev = &(((whisper_print_user_data *) user_data)->progress_prev); + if (progress >= *progress_prev + progress_step) { + *progress_prev += progress_step; + fprintf(stderr, "%s: progress = %3d%%\n", __func__, progress); + } +} + +static void whisper_print_segment_callback(struct whisper_context * ctx, struct whisper_state * /*state*/, int n_new, void * user_data) { + const auto & params = *((whisper_print_user_data *) user_data)->params; + const auto & pcmf32s = *((whisper_print_user_data *) user_data)->pcmf32s; + + const int n_segments = whisper_full_n_segments(ctx); + + std::string speaker = ""; + + int64_t t0 = 0; + int64_t t1 = 0; + + // print the last n_new segments + const int s0 = n_segments - n_new; + + if (s0 == 0) { + printf("\n"); + } + + for (int i = s0; i < n_segments; i++) { + if (!params.no_timestamps || params.diarize) { + t0 = whisper_full_get_segment_t0(ctx, i); + t1 = whisper_full_get_segment_t1(ctx, i); + } + + if (!params.no_timestamps) { + printf("[%s --> %s] ", to_timestamp(t0).c_str(), to_timestamp(t1).c_str()); + } + + if (params.diarize && pcmf32s.size() == 2) { + speaker = estimate_diarization_speaker(pcmf32s, t0, t1); + } + + if (params.print_colors) { + for (int j = 0; j < whisper_full_n_tokens(ctx, i); ++j) { + if (params.print_special == false) { + const whisper_token id = whisper_full_get_token_id(ctx, i, j); + if (id >= whisper_token_eot(ctx)) { + continue; + } + } + + const char * text = whisper_full_get_token_text(ctx, i, j); + const float p = whisper_full_get_token_p (ctx, i, j); + + const int n_colors = (int) k_colors.size(); + int raw_col = (int) (std::pow(p, 3)*float(n_colors)); + if (raw_col < 0) raw_col = 0; + if (raw_col > n_colors - 1) raw_col = n_colors - 1; + const int col = raw_col; + + printf("%s%s%s%s", speaker.c_str(), k_colors[col].c_str(), text, "\033[0m"); + } + } else if (params.print_confidence) { + for (int j = 0; j < whisper_full_n_tokens(ctx, i); ++j) { + if (params.print_special == false) { + const whisper_token id = whisper_full_get_token_id(ctx, i, j); + if (id >= whisper_token_eot(ctx)) { + continue; + } + } + + const char * text = whisper_full_get_token_text(ctx, i, j); + const float p = whisper_full_get_token_p (ctx, i, j); + + int style_idx = 2; // High confidence - dim + if (p < 0.33) { + style_idx = 0; // Low confidence - inverse (highlighted) + } else if (p < 0.66) { + style_idx = 1; // Medium confidence - underlined + } + printf("%s%s%s%s", speaker.c_str(), k_styles[style_idx].c_str(), text, "\033[0m"); + } + } else { + const char * text = whisper_full_get_segment_text(ctx, i); + + printf("%s%s", speaker.c_str(), text); + } + + if (params.tinydiarize) { + if (whisper_full_get_segment_speaker_turn_next(ctx, i)) { + printf("%s", params.tdrz_speaker_turn.c_str()); + } + } + + // with timestamps or speakers: each segment on new line + if (!params.no_timestamps || params.diarize) { + printf("\n"); + } + + fflush(stdout); + } +} + +static void output_txt(struct whisper_context * ctx, std::ofstream & fout, const whisper_params & params, std::vector> pcmf32s) { + const int n_segments = whisper_full_n_segments(ctx); + for (int i = 0; i < n_segments; ++i) { + const char * text = whisper_full_get_segment_text(ctx, i); + std::string speaker = ""; + + if (params.diarize && pcmf32s.size() == 2) + { + const int64_t t0 = whisper_full_get_segment_t0(ctx, i); + const int64_t t1 = whisper_full_get_segment_t1(ctx, i); + speaker = estimate_diarization_speaker(pcmf32s, t0, t1); + } + + if (!speaker.empty()) { + fout << speaker << text; + } else { + while (*text == ' ' || *text == '\t') { + text++; + } + fout << text; + } + fout << "\n"; + } +} + +static void output_vtt(struct whisper_context * ctx, std::ofstream & fout, const whisper_params & params, std::vector> pcmf32s) { + fout << "WEBVTT\n\n"; + + const int n_segments = whisper_full_n_segments(ctx); + for (int i = 0; i < n_segments; ++i) { + const char * text = whisper_full_get_segment_text(ctx, i); + const int64_t t0 = whisper_full_get_segment_t0(ctx, i); + const int64_t t1 = whisper_full_get_segment_t1(ctx, i); + std::string speaker = ""; + + if (params.diarize && pcmf32s.size() == 2) + { + speaker = estimate_diarization_speaker(pcmf32s, t0, t1, true); + speaker.insert(0, ""); + } + + fout << to_timestamp(t0) << " --> " << to_timestamp(t1) << "\n"; + fout << speaker << text << "\n\n"; + } +} + +static void output_srt(struct whisper_context * ctx, std::ofstream & fout, const whisper_params & params, std::vector> pcmf32s) { + const int n_segments = whisper_full_n_segments(ctx); + for (int i = 0; i < n_segments; ++i) { + const char * text = whisper_full_get_segment_text(ctx, i); + const int64_t t0 = whisper_full_get_segment_t0(ctx, i); + const int64_t t1 = whisper_full_get_segment_t1(ctx, i); + std::string speaker = ""; + + if (params.diarize && pcmf32s.size() == 2) + { + speaker = estimate_diarization_speaker(pcmf32s, t0, t1); + } + + fout << i + 1 + params.offset_n << "\n"; + fout << to_timestamp(t0, true) << " --> " << to_timestamp(t1, true) << "\n"; + fout << speaker << text << "\n\n"; + } +} + +static char * escape_double_quotes_and_backslashes(const char * str) { + if (str == NULL) { + return NULL; + } + + size_t escaped_length = strlen(str) + 1; + + for (size_t i = 0; str[i] != '\0'; i++) { + if (str[i] == '"' || str[i] == '\\') { + escaped_length++; + } + } + + char * escaped = (char *)calloc(escaped_length, 1); // pre-zeroed + if (escaped == NULL) { + return NULL; + } + + size_t pos = 0; + for (size_t i = 0; str[i] != '\0'; i++) { + if (str[i] == '"' || str[i] == '\\') { + escaped[pos++] = '\\'; + } + escaped[pos++] = str[i]; + } + + // no need to set zero due to calloc() being used prior + + return escaped; +} + +// double quote should be escaped by another double quote. (rfc4180) +static char * escape_double_quotes_in_csv(const char * str) { + if (str == NULL) { + return NULL; + } + + size_t escaped_length = strlen(str) + 1; + + for (size_t i = 0; str[i] != '\0'; i++) { + if (str[i] == '"') { + escaped_length++; + } + } + + char *escaped = (char *)calloc(escaped_length, 1); // pre-zeroed + if (escaped == NULL) { + return NULL; + } + + size_t pos = 0; + for (size_t i = 0; str[i] != '\0'; i++) { + if (str[i] == '"') { + escaped[pos++] = '"'; + } + escaped[pos++] = str[i]; + } + + // no need to set zero due to calloc() being used prior + + return escaped; +} + +static void output_csv(struct whisper_context * ctx, std::ofstream & fout, const whisper_params & params, std::vector> pcmf32s) { + const int n_segments = whisper_full_n_segments(ctx); + fout << "start,end,"; + if (params.diarize && pcmf32s.size() == 2) + { + fout << "speaker,"; + } + fout << "text\n"; + + for (int i = 0; i < n_segments; ++i) { + const char * text = whisper_full_get_segment_text(ctx, i); + const int64_t t0 = whisper_full_get_segment_t0(ctx, i); + const int64_t t1 = whisper_full_get_segment_t1(ctx, i); + char * text_escaped = escape_double_quotes_in_csv(text); + + //need to multiply times returned from whisper_full_get_segment_t{0,1}() by 10 to get milliseconds. + fout << 10 * t0 << "," << 10 * t1 << ","; + if (params.diarize && pcmf32s.size() == 2) + { + fout << estimate_diarization_speaker(pcmf32s, t0, t1, true) << ","; + } + fout << "\"" << text_escaped << "\"\n"; + } +} + +static void output_score(struct whisper_context * ctx, std::ofstream & fout, const whisper_params & /*params*/, std::vector> /*pcmf32s*/) { + const int n_segments = whisper_full_n_segments(ctx); + // fprintf(stderr,"segments: %d\n",n_segments); + for (int i = 0; i < n_segments; ++i) { + const int n_tokens = whisper_full_n_tokens(ctx, i); + // fprintf(stderr,"tokens: %d\n",n_tokens); + for (int j = 0; j < n_tokens; j++) { + auto token = whisper_full_get_token_text(ctx, i, j); + auto probability = whisper_full_get_token_p(ctx, i, j); + fout << token << '\t' << probability << std::endl; + // fprintf(stderr,"token: %s %f\n",token,probability); + } + } +} + +static void output_json( + struct whisper_context * ctx, + std::ofstream & fout, + const whisper_params & params, + std::vector> pcmf32s) { + const bool full = params.output_jsn_full; + int indent = 0; + + auto doindent = [&]() { + for (int i = 0; i < indent; i++) fout << "\t"; + }; + + auto start_arr = [&](const char *name) { + doindent(); + fout << "\"" << name << "\": [\n"; + indent++; + }; + + auto end_arr = [&](bool end) { + indent--; + doindent(); + fout << (end ? "]\n" : "],\n"); + }; + + auto start_obj = [&](const char *name) { + doindent(); + if (name) { + fout << "\"" << name << "\": {\n"; + } else { + fout << "{\n"; + } + indent++; + }; + + auto end_obj = [&](bool end) { + indent--; + doindent(); + fout << (end ? "}\n" : "},\n"); + }; + + auto start_value = [&](const char *name) { + doindent(); + fout << "\"" << name << "\": "; + }; + + auto value_s = [&](const char *name, const char *val, bool end) { + start_value(name); + char * val_escaped = escape_double_quotes_and_backslashes(val); + fout << "\"" << val_escaped << (end ? "\"\n" : "\",\n"); + free(val_escaped); + }; + + auto end_value = [&](bool end) { + fout << (end ? "\n" : ",\n"); + }; + + auto value_i = [&](const char *name, const int64_t val, bool end) { + start_value(name); + fout << val; + end_value(end); + }; + + auto value_f = [&](const char *name, const float val, bool end) { + start_value(name); + fout << val; + end_value(end); + }; + + auto value_b = [&](const char *name, const bool val, bool end) { + start_value(name); + fout << (val ? "true" : "false"); + end_value(end); + }; + + auto times_o = [&](int64_t t0, int64_t t1, bool end) { + start_obj("timestamps"); + value_s("from", to_timestamp(t0, true).c_str(), false); + value_s("to", to_timestamp(t1, true).c_str(), true); + end_obj(false); + start_obj("offsets"); + value_i("from", t0 * 10, false); + value_i("to", t1 * 10, true); + end_obj(end); + }; + + start_obj(nullptr); + value_s("systeminfo", whisper_print_system_info(), false); + start_obj("model"); + value_s("type", whisper_model_type_readable(ctx), false); + value_b("multilingual", whisper_is_multilingual(ctx), false); + value_i("vocab", whisper_model_n_vocab(ctx), false); + start_obj("audio"); + value_i("ctx", whisper_model_n_audio_ctx(ctx), false); + value_i("state", whisper_model_n_audio_state(ctx), false); + value_i("head", whisper_model_n_audio_head(ctx), false); + value_i("layer", whisper_model_n_audio_layer(ctx), true); + end_obj(false); + start_obj("text"); + value_i("ctx", whisper_model_n_text_ctx(ctx), false); + value_i("state", whisper_model_n_text_state(ctx), false); + value_i("head", whisper_model_n_text_head(ctx), false); + value_i("layer", whisper_model_n_text_layer(ctx), true); + end_obj(false); + value_i("mels", whisper_model_n_mels(ctx), false); + value_i("ftype", whisper_model_ftype(ctx), true); + end_obj(false); + start_obj("params"); + value_s("model", params.model.c_str(), false); + value_s("language", params.language.c_str(), false); + value_b("translate", params.translate, true); + end_obj(false); + start_obj("result"); + value_s("language", whisper_lang_str(whisper_full_lang_id(ctx)), true); + end_obj(false); + start_arr("transcription"); + + const int n_segments = whisper_full_n_segments(ctx); + for (int i = 0; i < n_segments; ++i) { + const char * text = whisper_full_get_segment_text(ctx, i); + + const int64_t t0 = whisper_full_get_segment_t0(ctx, i); + const int64_t t1 = whisper_full_get_segment_t1(ctx, i); + + start_obj(nullptr); + times_o(t0, t1, false); + value_s("text", text, !params.diarize && !params.tinydiarize && !full); + + if (full) { + start_arr("tokens"); + const int n = whisper_full_n_tokens(ctx, i); + + // Merge adjacent tokens whose bytes together form a + // single UTF-8 codepoint. Multi-byte characters (CJK + // in particular) can end up split across whisper + // tokens, which used to produce invalid UTF-8 in the + // JSON string. Refs issue #1798. + struct merged_token { + std::string text; + whisper_token_data data; + int64_t t1; + }; + std::vector merged; + merged.reserve(n); + for (int j = 0; j < n; ) { + auto tok = whisper_full_get_token_data(ctx, i, j); + merged_token m{ whisper_token_to_str(ctx, tok.id), tok, tok.t1 }; + ++j; + while (j < n && utf8_trailing_bytes_needed(m.text) > 0) { + auto tok_next = whisper_full_get_token_data(ctx, i, j); + m.text += whisper_token_to_str(ctx, tok_next.id); + if (tok_next.t1 > -1) { + m.t1 = tok_next.t1; + } + ++j; + } + merged.push_back(std::move(m)); + } + + const int nm = (int) merged.size(); + for (int j = 0; j < nm; ++j) { + const auto & mt = merged[j]; + start_obj(nullptr); + value_s("text", mt.text.c_str(), false); + if (mt.data.t0 > -1 && mt.t1 > -1) { + // If we have per-token timestamps, write them out + times_o(mt.data.t0, mt.t1, false); + } + value_i("id", mt.data.id, false); + value_f("p", mt.data.p, false); + value_f("t_dtw", mt.data.t_dtw, true); + end_obj(j == (nm - 1)); + } + end_arr(!params.diarize && !params.tinydiarize); + } + + if (params.diarize && pcmf32s.size() == 2) { + value_s("speaker", estimate_diarization_speaker(pcmf32s, t0, t1, true).c_str(), true); + } + + if (params.tinydiarize) { + value_b("speaker_turn_next", whisper_full_get_segment_speaker_turn_next(ctx, i), true); + } + end_obj(i == (n_segments - 1)); + } + + end_arr(true); + end_obj(true); +} + +// karaoke video generation +// outputs a bash script that uses ffmpeg to generate a video with the subtitles +// TODO: font parameter adjustments +static bool output_wts(struct whisper_context * ctx, std::ofstream & fout, const whisper_params & params, std::vector> pcmf32s, const char * fname_inp, float t_sec, const char * fname_out) { + static const char * font = params.font_path.c_str(); + + std::ifstream fin(font); + if (!fin.is_open()) { + fprintf(stderr, "%s: font not found at '%s', please specify a monospace font with -fp\n", __func__, font); + return false; + } + + fout << "#!/bin/bash" << "\n"; + fout << "\n"; + + fout << "ffmpeg -i " << fname_inp << " -f lavfi -i color=size=1200x120:duration=" << t_sec << ":rate=25:color=black -vf \""; + + for (int i = 0; i < whisper_full_n_segments(ctx); i++) { + const int64_t t0 = whisper_full_get_segment_t0(ctx, i); + const int64_t t1 = whisper_full_get_segment_t1(ctx, i); + + const int n = whisper_full_n_tokens(ctx, i); + + std::vector tokens(n); + for (int j = 0; j < n; ++j) { + tokens[j] = whisper_full_get_token_data(ctx, i, j); + } + + if (i > 0) { + fout << ","; + } + + // background text + fout << "drawtext=fontfile='" << font << "':fontsize=24:fontcolor=gray:x=(w-text_w)/2:y=h/2:text='':enable='between(t," << t0/100.0 << "," << t0/100.0 << ")'"; + + bool is_first = true; + std::string speaker = ""; + + if (params.diarize && pcmf32s.size() == 2) { + speaker = estimate_diarization_speaker(pcmf32s, t0, t1); + } + + for (int j = 0; j < n; ++j) { + const auto & token = tokens[j]; + + if (tokens[j].id >= whisper_token_eot(ctx)) { + continue; + } + + std::string txt_bg = ""; + std::string txt_fg = ""; // highlight token + std::string txt_ul = ""; // underline + + if (params.diarize && pcmf32s.size() == 2) { + txt_bg = speaker; + txt_fg = speaker; + txt_ul = "\\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ "; + } + + txt_bg.append("> "); + txt_fg.append("> "); + txt_ul.append("\\ \\ "); + + { + for (int k = 0; k < n; ++k) { + const auto & token2 = tokens[k]; + + if (tokens[k].id >= whisper_token_eot(ctx)) { + continue; + } + + const std::string txt = whisper_token_to_str(ctx, token2.id); + + txt_bg += txt; + + if (k == j) { + for (int l = 0; l < (int) txt.size(); ++l) { + txt_fg += txt[l]; + txt_ul += "_"; + } + txt_fg += "|"; + } else { + for (int l = 0; l < (int) txt.size(); ++l) { + txt_fg += "\\ "; + txt_ul += "\\ "; + } + } + } + + ::replace_all(txt_bg, "'", "\u2019"); + ::replace_all(txt_bg, "\"", "\\\""); + ::replace_all(txt_fg, "'", "\u2019"); + ::replace_all(txt_fg, "\"", "\\\""); + } + + if (is_first) { + // background text + fout << ",drawtext=fontfile='" << font << "':fontsize=24:fontcolor=gray:x=(w-text_w)/2:y=h/2:text='" << txt_bg << "':enable='between(t," << t0/100.0 << "," << t1/100.0 << ")'"; + is_first = false; + } + + // foreground text + fout << ",drawtext=fontfile='" << font << "':fontsize=24:fontcolor=lightgreen:x=(w-text_w)/2+8:y=h/2:text='" << txt_fg << "':enable='between(t," << token.t0/100.0 << "," << token.t1/100.0 << ")'"; + + // underline + fout << ",drawtext=fontfile='" << font << "':fontsize=24:fontcolor=lightgreen:x=(w-text_w)/2+8:y=h/2+16:text='" << txt_ul << "':enable='between(t," << token.t0/100.0 << "," << token.t1/100.0 << ")'"; + } + } + + fout << "\" -c:v libx264 -pix_fmt yuv420p -y " << fname_inp << ".mp4" << "\n"; + + fout << "\n\n"; + fout << "echo \"Your video has been saved to " << fname_inp << ".mp4\"" << "\n"; + fout << "\n"; + fout << "echo \" ffplay " << fname_inp << ".mp4\"\n"; + fout << "\n"; + + fout.close(); + + fprintf(stderr, "# %s: run 'source %s' to generate karaoke video\n", __func__, fname_out); + + return true; +} + +static void output_lrc(struct whisper_context * ctx, std::ofstream & fout, const whisper_params & params, std::vector> pcmf32s) { + fout << "[by:whisper.cpp]\n"; + + const int n_segments = whisper_full_n_segments(ctx); + for (int i = 0; i < n_segments; ++i) { + const char * text = whisper_full_get_segment_text(ctx, i); + const int64_t t = whisper_full_get_segment_t0(ctx, i); + + int64_t msec = t * 10; + int64_t min = msec / (1000 * 60); + msec = msec - min * (1000 * 60); + int64_t sec = msec / 1000; + msec = msec - sec * 1000; + + char buf[16]; + snprintf(buf, sizeof(buf), "%02d:%02d.%02d", (int) min, (int) sec, (int) ( msec / 10)); + std::string timestamp_lrc = std::string(buf); + std::string speaker = ""; + + if (params.diarize && pcmf32s.size() == 2) + { + const int64_t t0 = whisper_full_get_segment_t0(ctx, i); + const int64_t t1 = whisper_full_get_segment_t1(ctx, i); + speaker = estimate_diarization_speaker(pcmf32s, t0, t1); + } + + fout << '[' << timestamp_lrc << ']' << speaker << text << "\n"; + } +} + + +static void cb_log_disable(enum ggml_log_level , const char * , void * ) { } + +int main(int argc, char ** argv) { + ggml_backend_load_all(); + +#if defined(_WIN32) + // Set the console output code page to UTF-8, while command line arguments + // are still encoded in the system's code page. In this way, we can print + // non-ASCII characters to the console, and access files with non-ASCII paths. + SetConsoleOutputCP(CP_UTF8); +#endif + + whisper_params params; + + // If the only argument starts with "@", read arguments line-by-line + // from the given file. + std::vector vec_args; + if (argc == 2 && argv != nullptr && argv[1] != nullptr && argv[1][0] == '@') { + // Save the name of the executable. + vec_args.push_back(argv[0]); + + // Open the response file. + char const * rspfile = argv[1] + sizeof(char); + std::ifstream fin(rspfile); + if (fin.is_open() == false) { + fprintf(stderr, "error: response file '%s' not found\n", rspfile); + return 1; + } + + // Read the entire response file. + std::string line; + while (std::getline(fin, line)) { + vec_args.push_back(line); + } + + // Use the contents of the response file as the command-line arguments. + argc = static_cast(vec_args.size()); + argv = static_cast(alloca(argc * sizeof (char *))); + for (int i = 0; i < argc; ++i) { + argv[i] = const_cast(vec_args[i].c_str()); + } + } + + if (whisper_params_parse(argc, argv, params) == false) { + whisper_print_usage(argc, argv, params); + return 1; + } + + // remove non-existent files + for (auto it = params.fname_inp.begin(); it != params.fname_inp.end();) { + const auto fname_inp = it->c_str(); + + if (*it != "-" && !is_file_exist(fname_inp)) { + fprintf(stderr, "error: input file not found '%s'\n", fname_inp); + it = params.fname_inp.erase(it); + continue; + } + + it++; + } + + if (params.fname_inp.empty()) { + fprintf(stderr, "error: no input files specified\n"); + whisper_print_usage(argc, argv, params); + return 2; + } + + if (params.language != "auto" && whisper_lang_id(params.language.c_str()) == -1) { + fprintf(stderr, "error: unknown language '%s'\n", params.language.c_str()); + whisper_print_usage(argc, argv, params); + exit(0); + } + + if (params.diarize && params.tinydiarize) { + fprintf(stderr, "error: cannot use both --diarize and --tinydiarize\n"); + whisper_print_usage(argc, argv, params); + exit(0); + } + + if (params.no_prints) { + whisper_log_set(cb_log_disable, NULL); + } + + // whisper init + struct whisper_context_params cparams = whisper_context_default_params(); + + cparams.use_gpu = params.use_gpu; + cparams.gpu_device = params.gpu_device; + cparams.flash_attn = params.flash_attn; + + if (!params.dtw.empty()) { + cparams.dtw_token_timestamps = true; + cparams.dtw_aheads_preset = WHISPER_AHEADS_NONE; + + if (params.dtw == "tiny") cparams.dtw_aheads_preset = WHISPER_AHEADS_TINY; + if (params.dtw == "tiny.en") cparams.dtw_aheads_preset = WHISPER_AHEADS_TINY_EN; + if (params.dtw == "base") cparams.dtw_aheads_preset = WHISPER_AHEADS_BASE; + if (params.dtw == "base.en") cparams.dtw_aheads_preset = WHISPER_AHEADS_BASE_EN; + if (params.dtw == "small") cparams.dtw_aheads_preset = WHISPER_AHEADS_SMALL; + if (params.dtw == "small.en") cparams.dtw_aheads_preset = WHISPER_AHEADS_SMALL_EN; + if (params.dtw == "medium") cparams.dtw_aheads_preset = WHISPER_AHEADS_MEDIUM; + if (params.dtw == "medium.en") cparams.dtw_aheads_preset = WHISPER_AHEADS_MEDIUM_EN; + if (params.dtw == "large.v1") cparams.dtw_aheads_preset = WHISPER_AHEADS_LARGE_V1; + if (params.dtw == "large.v2") cparams.dtw_aheads_preset = WHISPER_AHEADS_LARGE_V2; + if (params.dtw == "large.v3") cparams.dtw_aheads_preset = WHISPER_AHEADS_LARGE_V3; + if (params.dtw == "large.v3.turbo") cparams.dtw_aheads_preset = WHISPER_AHEADS_LARGE_V3_TURBO; + + if (cparams.dtw_aheads_preset == WHISPER_AHEADS_NONE) { + fprintf(stderr, "error: unknown DTW preset '%s'\n", params.dtw.c_str()); + return 3; + } + } + + struct whisper_context * ctx = whisper_init_from_file_with_params(params.model.c_str(), cparams); + + if (ctx == nullptr) { + fprintf(stderr, "error: failed to initialize whisper context\n"); + return 3; + } + + // initialize openvino encoder. this has no effect on whisper.cpp builds that don't have OpenVINO configured + whisper_ctx_init_openvino_encoder(ctx, nullptr, params.openvino_encode_device.c_str(), nullptr); + + if (!params.grammar.empty()) { + auto & grammar = params.grammar_parsed; + if (is_file_exist(params.grammar.c_str())) { + // read grammar from file + std::ifstream ifs(params.grammar.c_str()); + const std::string txt = std::string((std::istreambuf_iterator(ifs)), std::istreambuf_iterator()); + grammar = grammar_parser::parse(txt.c_str()); + } else { + // read grammar from string + grammar = grammar_parser::parse(params.grammar.c_str()); + } + + // will be empty (default) if there are parse errors + if (grammar.rules.empty()) { + fprintf(stderr, "error: failed to parse grammar \"%s\"\n", params.grammar.c_str()); + return 4; + } else { + fprintf(stderr, "%s: grammar:\n", __func__); + grammar_parser::print_grammar(stderr, grammar); + fprintf(stderr, "\n"); + } + } + + for (int f = 0; f < (int) params.fname_inp.size(); ++f) { + const auto & fname_inp = params.fname_inp[f]; + struct fout_factory { + std::string fname_out; + const size_t basename_length; + const bool is_stdout; + bool used_stdout; + decltype(whisper_print_segment_callback) * const print_segment_callback; + std::ofstream fout; + + fout_factory (const std::string & fname_out_, const std::string & fname_inp, whisper_params & params) : + fname_out{!fname_out_.empty() ? fname_out_ : fname_inp}, + basename_length{fname_out.size()}, + is_stdout{fname_out == "-"}, + used_stdout{}, + print_segment_callback{is_stdout ? nullptr : whisper_print_segment_callback} { + if (!print_segment_callback) { + params.print_progress = false; + } + } + + bool open(const char * ext, const char * function) { + if (is_stdout) { + if (used_stdout) { + fprintf(stderr, "warning: Not appending multiple file formats to stdout\n"); + return false; + } + + used_stdout = true; +#ifdef _WIN32 + fout = std::ofstream{"CON"}; +#else + fout = std::ofstream{"/dev/stdout"}; +#endif + // Not using fprintf stderr here because it might equal stdout + // Also assuming /dev is mounted + return true; + } + + fname_out.resize(basename_length); + fname_out += ext; + fout = std::ofstream{fname_out}; + if (!fout.is_open()) { + fprintf(stderr, "%s: failed to open '%s' for writing\n", __func__, fname_out.c_str()); + return false; + } + fprintf(stderr, "%s: saving output to '%s'\n", function, fname_out.c_str()); + return true; + } + } fout_factory{f < (int) params.fname_out.size() ? params.fname_out[f] : "", fname_inp, params}; + + std::vector pcmf32; // mono-channel F32 PCM + std::vector> pcmf32s; // stereo-channel F32 PCM + + if (!::read_audio_data(fname_inp, pcmf32, pcmf32s, params.diarize)) { + fprintf(stderr, "error: failed to read audio file '%s'\n", fname_inp.c_str()); + continue; + } + + if (!whisper_is_multilingual(ctx)) { + if (params.language != "en" || params.translate) { + params.language = "en"; + params.translate = false; + fprintf(stderr, "%s: WARNING: model is not multilingual, ignoring language and translation options\n", __func__); + } + } + if (params.detect_language) { + params.language = "auto"; + } + + if (!params.no_prints) { + // print system information + fprintf(stderr, "\n"); + fprintf(stderr, "system_info: n_threads = %d / %d | %s\n", + params.n_threads*params.n_processors, std::thread::hardware_concurrency(), whisper_print_system_info()); + + // print some info about the processing + fprintf(stderr, "\n"); + fprintf(stderr, "%s: processing '%s' (%d samples, %.1f sec), %d threads, %d processors, %d beams + best of %d, lang = %s, task = %s, %stimestamps = %d ...\n", + __func__, fname_inp.c_str(), int(pcmf32.size()), float(pcmf32.size())/WHISPER_SAMPLE_RATE, + params.n_threads, params.n_processors, params.beam_size, params.best_of, + params.language.c_str(), + params.translate ? "translate" : "transcribe", + params.tinydiarize ? "tdrz = 1, " : "", + params.no_timestamps ? 0 : 1); + + if (params.print_colors) { + fprintf(stderr, "%s: color scheme: red (low confidence), yellow (medium), green (high confidence)\n", __func__); + } else if (params.print_confidence) { + fprintf(stderr, "%s: confidence: highlighted (low confidence), underlined (medium), dim (high confidence)\n", __func__); + } + fprintf(stderr, "\n"); + } + + // run the inference + { + whisper_full_params wparams = whisper_full_default_params(WHISPER_SAMPLING_GREEDY); + + const bool use_grammar = (!params.grammar_parsed.rules.empty() && !params.grammar_rule.empty()); + wparams.strategy = (params.beam_size > 1 || use_grammar) ? WHISPER_SAMPLING_BEAM_SEARCH : WHISPER_SAMPLING_GREEDY; + + wparams.print_realtime = false; + wparams.print_progress = params.print_progress; + wparams.print_timestamps = !params.no_timestamps; + wparams.print_special = params.print_special; + wparams.translate = params.translate; + wparams.language = params.language.c_str(); + wparams.detect_language = params.detect_language; + wparams.n_threads = params.n_threads; + wparams.n_max_text_ctx = params.max_context >= 0 ? params.max_context : wparams.n_max_text_ctx; + wparams.offset_ms = params.offset_t_ms; + wparams.duration_ms = params.duration_ms; + + wparams.token_timestamps = params.output_wts || params.output_jsn_full || params.max_len > 0; + wparams.thold_pt = params.word_thold; + wparams.max_len = params.output_wts && params.max_len == 0 ? 60 : params.max_len; + wparams.split_on_word = params.split_on_word; + wparams.audio_ctx = params.audio_ctx; + + wparams.debug_mode = params.debug_mode; + + wparams.tdrz_enable = params.tinydiarize; // [TDRZ] + + wparams.suppress_regex = params.suppress_regex.empty() ? nullptr : params.suppress_regex.c_str(); + + wparams.initial_prompt = params.prompt.c_str(); + wparams.carry_initial_prompt = params.carry_initial_prompt; + + wparams.greedy.best_of = params.best_of; + wparams.beam_search.beam_size = params.beam_size; + + wparams.temperature_inc = params.no_fallback ? 0.0f : params.temperature_inc; + wparams.temperature = params.temperature; + + wparams.entropy_thold = params.entropy_thold; + wparams.logprob_thold = params.logprob_thold; + wparams.no_speech_thold = params.no_speech_thold; + + wparams.no_timestamps = params.no_timestamps; + + wparams.suppress_nst = params.suppress_nst; + + wparams.vad = params.vad; + wparams.vad_model_path = params.vad_model.c_str(); + + wparams.vad_params.threshold = params.vad_threshold; + wparams.vad_params.min_speech_duration_ms = params.vad_min_speech_duration_ms; + wparams.vad_params.min_silence_duration_ms = params.vad_min_silence_duration_ms; + wparams.vad_params.max_speech_duration_s = params.vad_max_speech_duration_s; + wparams.vad_params.speech_pad_ms = params.vad_speech_pad_ms; + wparams.vad_params.samples_overlap = params.vad_samples_overlap; + + whisper_print_user_data user_data = { ¶ms, &pcmf32s, 0 }; + + const auto & grammar_parsed = params.grammar_parsed; + auto grammar_rules = grammar_parsed.c_rules(); + + if (use_grammar) { + if (grammar_parsed.symbol_ids.find(params.grammar_rule) == grammar_parsed.symbol_ids.end()) { + fprintf(stderr, "%s: warning: grammar rule '%s' not found - skipping grammar sampling\n", __func__, params.grammar_rule.c_str()); + } else { + wparams.grammar_rules = grammar_rules.data(); + wparams.n_grammar_rules = grammar_rules.size(); + wparams.i_start_rule = grammar_parsed.symbol_ids.at(params.grammar_rule); + wparams.grammar_penalty = params.grammar_penalty; + } + } + + // this callback is called on each new segment + if (!wparams.print_realtime) { + wparams.new_segment_callback = fout_factory.print_segment_callback; + wparams.new_segment_callback_user_data = &user_data; + } + + if (wparams.print_progress) { + wparams.progress_callback = whisper_print_progress_callback; + wparams.progress_callback_user_data = &user_data; + } + + // examples for abort mechanism + // in examples below, we do not abort the processing, but we could if the flag is set to true + + // the callback is called before every encoder run - if it returns false, the processing is aborted + { + static bool is_aborted = false; // NOTE: this should be atomic to avoid data race + + wparams.encoder_begin_callback = [](struct whisper_context * /*ctx*/, struct whisper_state * /*state*/, void * user_data) { + bool is_aborted = *(bool*)user_data; + return !is_aborted; + }; + wparams.encoder_begin_callback_user_data = &is_aborted; + } + + // the callback is called before every computation - if it returns true, the computation is aborted + { + static bool is_aborted = false; // NOTE: this should be atomic to avoid data race + + wparams.abort_callback = [](void * user_data) { + bool is_aborted = *(bool*)user_data; + return is_aborted; + }; + wparams.abort_callback_user_data = &is_aborted; + } + + if (whisper_full_parallel(ctx, wparams, pcmf32.data(), pcmf32.size(), params.n_processors) != 0) { + fprintf(stderr, "%s: failed to process audio\n", argv[0]); + return 10; + } + } + + // output stuff + { + // macros to stringify function name +#define output_func(func, ext, param, ...) if (param && fout_factory.open(ext, #func)) {\ + func(ctx, fout_factory.fout, params, __VA_ARGS__); \ +} +#define output_ext(ext, ...) output_func(output_##ext, "." #ext, params.output_##ext, __VA_ARGS__) + + output_ext(txt, pcmf32s); + output_ext(vtt, pcmf32s); + output_ext(srt, pcmf32s); + output_ext(wts, pcmf32s, fname_inp.c_str(), float(pcmf32.size() + 1000)/WHISPER_SAMPLE_RATE, fout_factory.fname_out.c_str()); + output_ext(csv, pcmf32s); + output_func(output_json, ".json", params.output_jsn, pcmf32s); + output_ext(lrc, pcmf32s); + output_func(output_score, ".score.txt", params.log_score, pcmf32s); + +#undef output_ext +#undef output_func + + if (fout_factory.is_stdout && !fout_factory.used_stdout) { + fprintf(stderr, "warning: '--output-file -' used without any other '--output-*'"); + } + } + } + + if (!params.no_prints) { + whisper_print_timings(ctx); + } + whisper_free(ctx); + + return 0; +} diff --git a/examples/coi-serviceworker.js b/examples/coi-serviceworker.js new file mode 100644 index 0000000..9901474 --- /dev/null +++ b/examples/coi-serviceworker.js @@ -0,0 +1,146 @@ +/*! coi-serviceworker v0.1.7 - Guido Zuidhof and contributors, licensed under MIT */ +let coepCredentialless = false; +if (typeof window === 'undefined') { + self.addEventListener("install", () => self.skipWaiting()); + self.addEventListener("activate", (event) => event.waitUntil(self.clients.claim())); + + self.addEventListener("message", (ev) => { + if (!ev.data) { + return; + } else if (ev.data.type === "deregister") { + self.registration + .unregister() + .then(() => { + return self.clients.matchAll(); + }) + .then(clients => { + clients.forEach((client) => client.navigate(client.url)); + }); + } else if (ev.data.type === "coepCredentialless") { + coepCredentialless = ev.data.value; + } + }); + + self.addEventListener("fetch", function (event) { + const r = event.request; + if (r.cache === "only-if-cached" && r.mode !== "same-origin") { + return; + } + + const request = (coepCredentialless && r.mode === "no-cors") + ? new Request(r, { + credentials: "omit", + }) + : r; + event.respondWith( + fetch(request) + .then((response) => { + if (response.status === 0) { + return response; + } + + const newHeaders = new Headers(response.headers); + newHeaders.set("Cross-Origin-Embedder-Policy", + coepCredentialless ? "credentialless" : "require-corp" + ); + if (!coepCredentialless) { + newHeaders.set("Cross-Origin-Resource-Policy", "cross-origin"); + } + newHeaders.set("Cross-Origin-Opener-Policy", "same-origin"); + + return new Response(response.body, { + status: response.status, + statusText: response.statusText, + headers: newHeaders, + }); + }) + .catch((e) => console.error(e)) + ); + }); + +} else { + (() => { + const reloadedBySelf = window.sessionStorage.getItem("coiReloadedBySelf"); + window.sessionStorage.removeItem("coiReloadedBySelf"); + const coepDegrading = (reloadedBySelf == "coepdegrade"); + + // You can customize the behavior of this script through a global `coi` variable. + const coi = { + shouldRegister: () => !reloadedBySelf, + shouldDeregister: () => false, + coepCredentialless: () => true, + coepDegrade: () => true, + doReload: () => window.location.reload(), + quiet: false, + ...window.coi + }; + + const n = navigator; + const controlling = n.serviceWorker && n.serviceWorker.controller; + + // Record the failure if the page is served by serviceWorker. + if (controlling && !window.crossOriginIsolated) { + window.sessionStorage.setItem("coiCoepHasFailed", "true"); + } + const coepHasFailed = window.sessionStorage.getItem("coiCoepHasFailed"); + + if (controlling) { + // Reload only on the first failure. + const reloadToDegrade = coi.coepDegrade() && !( + coepDegrading || window.crossOriginIsolated + ); + n.serviceWorker.controller.postMessage({ + type: "coepCredentialless", + value: (reloadToDegrade || coepHasFailed && coi.coepDegrade()) + ? false + : coi.coepCredentialless(), + }); + if (reloadToDegrade) { + !coi.quiet && console.log("Reloading page to degrade COEP."); + window.sessionStorage.setItem("coiReloadedBySelf", "coepdegrade"); + coi.doReload("coepdegrade"); + } + + if (coi.shouldDeregister()) { + n.serviceWorker.controller.postMessage({ type: "deregister" }); + } + } + + // If we're already coi: do nothing. Perhaps it's due to this script doing its job, or COOP/COEP are + // already set from the origin server. Also if the browser has no notion of crossOriginIsolated, just give up here. + if (window.crossOriginIsolated !== false || !coi.shouldRegister()) return; + + if (!window.isSecureContext) { + !coi.quiet && console.log("COOP/COEP Service Worker not registered, a secure context is required."); + return; + } + + // In some environments (e.g. Firefox private mode) this won't be available + if (!n.serviceWorker) { + !coi.quiet && console.error("COOP/COEP Service Worker not registered, perhaps due to private mode."); + return; + } + + n.serviceWorker.register(window.document.currentScript.src).then( + (registration) => { + !coi.quiet && console.log("COOP/COEP Service Worker registered", registration.scope); + + registration.addEventListener("updatefound", () => { + !coi.quiet && console.log("Reloading page to make use of updated COOP/COEP Service Worker."); + window.sessionStorage.setItem("coiReloadedBySelf", "updatefound"); + coi.doReload(); + }); + + // If the registration is active, but it's not controlling the page + if (registration.active && !n.serviceWorker.controller) { + !coi.quiet && console.log("Reloading page to make use of COOP/COEP Service Worker."); + window.sessionStorage.setItem("coiReloadedBySelf", "notcontrolling"); + coi.doReload(); + } + }, + (err) => { + !coi.quiet && console.error("COOP/COEP Service Worker failed to register:", err); + } + ); + })(); +} diff --git a/examples/command.wasm/CMakeLists.txt b/examples/command.wasm/CMakeLists.txt new file mode 100644 index 0000000..7c2c429 --- /dev/null +++ b/examples/command.wasm/CMakeLists.txt @@ -0,0 +1,50 @@ +# +# libcommand +# + +set(TARGET libcommand) + +add_executable(${TARGET} + emscripten.cpp + ) + +include(DefaultTargetOptions) + +target_link_libraries(${TARGET} PRIVATE + common + whisper + ) + +unset(EXTRA_FLAGS) + +if (WHISPER_WASM_SINGLE_FILE) + set(EXTRA_FLAGS "-s SINGLE_FILE=1") + message(STATUS "Embedding WASM inside command.js") + + add_custom_command( + TARGET ${TARGET} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_BINARY_DIR}/bin/libcommand.js + ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/command.wasm/command.js + ) +endif() + +set_target_properties(${TARGET} PROPERTIES LINK_FLAGS " \ + --bind \ + -s USE_PTHREADS=1 \ + -s PTHREAD_POOL_SIZE=8 \ + -s INITIAL_MEMORY=1024MB \ + -s TOTAL_MEMORY=1024MB \ + -s FORCE_FILESYSTEM=1 \ + -s EXPORTED_RUNTIME_METHODS=\"['print', 'printErr', 'ccall', 'cwrap', 'HEAPU8']\" \ + ${EXTRA_FLAGS} \ + ") + +# +# command.wasm +# + +set(TARGET command.wasm) + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/index-tmpl.html ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TARGET}/index.html @ONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../helpers.js ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TARGET}/helpers.js @ONLY) diff --git a/examples/command.wasm/README.md b/examples/command.wasm/README.md new file mode 100644 index 0000000..d134f2a --- /dev/null +++ b/examples/command.wasm/README.md @@ -0,0 +1,47 @@ +# command.wasm + +This is a basic Voice Assistant example that accepts voice commands from the microphone. +It runs in fully in the browser via WebAseembly. + +Online demo: https://ggml.ai/whisper.cpp/command.wasm/ + +Terminal version: [examples/command](/examples/command) + +## Build instructions + +```bash +# build using Emscripten (v3.1.2) +git clone https://github.com/ggerganov/whisper.cpp +cd whisper.cpp +mkdir build-em && cd build-em +emcmake cmake .. +make -j libcommand +``` +The example can then be started by running a local HTTP server: +```console +python3 examples/server.py +``` +And then opening a browser to the following URL: +http://localhost:8000/command.wasm/ + +To run the example in a different server, you need to copy the following files +to the server's HTTP path: +``` +cp bin/command.wasm/* /path/to/html/ +cp bin/libcommand.js /path/to/html/ +cp bin/libcommand.worker.js /path/to/html/ +``` + +> 📝 **Note:** By default this example is built with `WHISPER_WASM_SINGLE_FILE=ON` +> which means that that a separate .wasm file will not be generated. Instead, the +> WASM module is embedded in the main JS file as a base64 encoded string. To +> generate a separate .wasm file, you need to disable this option by passing +> `-DWHISPER_WASM_SINGLE_FILE=OFF`: +> ```console +> emcmake cmake .. -DWHISPER_WASM_SINGLE_FILE=OFF +> ``` +> This will generate a `libcommand.wasm` file in the build/bin directory. + +> 📝 **Note:** As of Emscripten 3.1.58 (April 2024), separate worker.js files are no +> longer generated and the worker is embedded in the main JS file. So the worker +> file will not be generated for versions later than `3.1.58`. diff --git a/examples/command.wasm/emscripten.cpp b/examples/command.wasm/emscripten.cpp new file mode 100644 index 0000000..528ff6a --- /dev/null +++ b/examples/command.wasm/emscripten.cpp @@ -0,0 +1,327 @@ +#include "ggml.h" +#include "common.h" +#include "whisper.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +constexpr int N_THREAD = 8; + +std::vector g_contexts(4, nullptr); + +std::mutex g_mutex; +std::thread g_worker; + +std::atomic g_running(false); + +std::string g_status = ""; +std::string g_status_forced = ""; +std::string g_transcribed = ""; + +std::vector g_pcmf32; + +void command_set_status(const std::string & status) { + std::lock_guard lock(g_mutex); + g_status = status; +} + +std::string command_transcribe(whisper_context * ctx, const whisper_full_params & wparams, const std::vector & pcmf32, float & prob, int64_t & t_ms) { + const auto t_start = std::chrono::high_resolution_clock::now(); + + prob = 0.0f; + t_ms = 0; + + if (whisper_full(ctx, wparams, pcmf32.data(), pcmf32.size()) != 0) { + return ""; + } + + int prob_n = 0; + std::string result; + + const int n_segments = whisper_full_n_segments(ctx); + for (int i = 0; i < n_segments; ++i) { + const char * text = whisper_full_get_segment_text(ctx, i); + + result += text; + + const int n_tokens = whisper_full_n_tokens(ctx, i); + for (int j = 0; j < n_tokens; ++j) { + const auto token = whisper_full_get_token_data(ctx, i, j); + + prob += token.p; + ++prob_n; + } + } + + if (prob_n > 0) { + prob /= prob_n; + } + + const auto t_end = std::chrono::high_resolution_clock::now(); + t_ms = std::chrono::duration_cast(t_end - t_start).count(); + + return result; +} + +void command_get_audio(int ms, int sample_rate, std::vector & audio) { + const int64_t n_samples = (ms * sample_rate) / 1000; + + int64_t n_take = 0; + if (n_samples > (int) g_pcmf32.size()) { + n_take = g_pcmf32.size(); + } else { + n_take = n_samples; + } + + audio.resize(n_take); + std::copy(g_pcmf32.end() - n_take, g_pcmf32.end(), audio.begin()); +} + +void command_main(size_t index) { + command_set_status("loading data ..."); + + struct whisper_full_params wparams = whisper_full_default_params(whisper_sampling_strategy::WHISPER_SAMPLING_GREEDY); + + wparams.n_threads = std::min(N_THREAD, (int) std::thread::hardware_concurrency()); + wparams.offset_ms = 0; + wparams.translate = false; + wparams.no_context = true; + wparams.single_segment = true; + wparams.print_realtime = false; + wparams.print_progress = false; + wparams.print_timestamps = true; + wparams.print_special = false; + + wparams.max_tokens = 32; + wparams.audio_ctx = 768; // partial encoder context for better performance + + wparams.language = "en"; + + printf("command: using %d threads\n", wparams.n_threads); + + bool have_prompt = false; + bool ask_prompt = true; + bool print_energy = false; + + float prob0 = 0.0f; + float prob = 0.0f; + + std::vector pcmf32_cur; + std::vector pcmf32_prompt; + + const std::string k_prompt = "Ok Whisper, start listening for commands."; + + // whisper context + auto & ctx = g_contexts[index]; + + const int32_t vad_ms = 2000; + const int32_t prompt_ms = 5000; + const int32_t command_ms = 4000; + + const float vad_thold = 0.1f; + const float freq_thold = -1.0f; + + while (g_running) { + // delay + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + if (ask_prompt) { + fprintf(stdout, "\n"); + fprintf(stdout, "%s: Say the following phrase: '%s%s%s'\n", __func__, "\033[1m", k_prompt.c_str(), "\033[0m"); + fprintf(stdout, "\n"); + + { + char txt[1024]; + snprintf(txt, sizeof(txt), "Say the following phrase: '%s'", k_prompt.c_str()); + command_set_status(txt); + } + + ask_prompt = false; + } + + int64_t t_ms = 0; + + { + command_get_audio(vad_ms, WHISPER_SAMPLE_RATE, pcmf32_cur); + + if (::vad_simple(pcmf32_cur, WHISPER_SAMPLE_RATE, 1000, vad_thold, freq_thold, print_energy)) { + fprintf(stdout, "%s: Speech detected! Processing ...\n", __func__); + command_set_status("Speech detected! Processing ..."); + + if (!have_prompt) { + command_get_audio(prompt_ms, WHISPER_SAMPLE_RATE, pcmf32_cur); + + const auto txt = ::trim(::command_transcribe(ctx, wparams, pcmf32_cur, prob0, t_ms)); + + fprintf(stdout, "%s: Heard '%s%s%s', (t = %d ms)\n", __func__, "\033[1m", txt.c_str(), "\033[0m", (int) t_ms); + + const float sim = similarity(txt, k_prompt); + + if (txt.length() < 0.8*k_prompt.length() || txt.length() > 1.2*k_prompt.length() || sim < 0.8f) { + fprintf(stdout, "%s: WARNING: prompt not recognized, try again\n", __func__); + ask_prompt = true; + } else { + fprintf(stdout, "\n"); + fprintf(stdout, "%s: The prompt has been recognized!\n", __func__); + fprintf(stdout, "%s: Waiting for voice commands ...\n", __func__); + fprintf(stdout, "\n"); + + { + char txt[1024]; + snprintf(txt, sizeof(txt), "Success! Waiting for voice commands ..."); + command_set_status(txt); + } + + // save the audio for the prompt + pcmf32_prompt = pcmf32_cur; + have_prompt = true; + } + } else { + command_get_audio(command_ms, WHISPER_SAMPLE_RATE, pcmf32_cur); + + // prepend the prompt audio + pcmf32_cur.insert(pcmf32_cur.begin(), pcmf32_prompt.begin(), pcmf32_prompt.end()); + + const auto txt = ::trim(::command_transcribe(ctx, wparams, pcmf32_cur, prob, t_ms)); + + prob = 100.0f*(prob - prob0); + + fprintf(stdout, "%s: heard '%s'\n", __func__, txt.c_str()); + + // find the prompt in the text + float best_sim = 0.0f; + size_t best_len = 0; + for (int n = 0.8*k_prompt.size(); n <= 1.2*k_prompt.size(); ++n) { + const auto prompt = txt.substr(0, n); + + const float sim = similarity(prompt, k_prompt); + + //fprintf(stderr, "%s: prompt = '%s', sim = %f\n", __func__, prompt.c_str(), sim); + + if (sim > best_sim) { + best_sim = sim; + best_len = n; + } + } + + const std::string command = ::trim(txt.substr(best_len)); + + fprintf(stdout, "%s: Command '%s%s%s', (t = %d ms)\n", __func__, "\033[1m", command.c_str(), "\033[0m", (int) t_ms); + fprintf(stdout, "\n"); + + { + char txt[1024]; + snprintf(txt, sizeof(txt), "Command '%s', (t = %d ms)", command.c_str(), (int) t_ms); + command_set_status(txt); + } + { + std::lock_guard lock(g_mutex); + g_transcribed = command; + } + } + + g_pcmf32.clear(); + } + } + } + + if (index < g_contexts.size()) { + whisper_free(g_contexts[index]); + g_contexts[index] = nullptr; + } +} + +EMSCRIPTEN_BINDINGS(command) { + emscripten::function("init", emscripten::optional_override([](const std::string & path_model) { + for (size_t i = 0; i < g_contexts.size(); ++i) { + if (g_contexts[i] == nullptr) { + g_contexts[i] = whisper_init_from_file_with_params(path_model.c_str(), whisper_context_default_params()); + if (g_contexts[i] != nullptr) { + g_running = true; + if (g_worker.joinable()) { + g_worker.join(); + } + g_worker = std::thread([i]() { + command_main(i); + }); + + return i + 1; + } else { + return (size_t) 0; + } + } + } + + return (size_t) 0; + })); + + emscripten::function("free", emscripten::optional_override([](size_t index) { + if (g_running) { + g_running = false; + } + })); + + emscripten::function("set_audio", emscripten::optional_override([](size_t index, const emscripten::val & audio) { + --index; + + if (index >= g_contexts.size()) { + return -1; + } + + if (g_contexts[index] == nullptr) { + return -2; + } + + { + std::lock_guard lock(g_mutex); + const int n = audio["length"].as(); + + emscripten::val heap = emscripten::val::module_property("HEAPU8"); + emscripten::val memory = heap["buffer"]; + + g_pcmf32.resize(n); + + emscripten::val memoryView = audio["constructor"].new_(memory, reinterpret_cast(g_pcmf32.data()), n); + memoryView.call("set", audio); + } + + return 0; + })); + + emscripten::function("get_transcribed", emscripten::optional_override([]() { + std::string transcribed; + + { + std::lock_guard lock(g_mutex); + transcribed = std::move(g_transcribed); + } + + return transcribed; + })); + + emscripten::function("get_status", emscripten::optional_override([]() { + std::string status; + + { + std::lock_guard lock(g_mutex); + status = g_status_forced.empty() ? g_status : g_status_forced; + } + + return status; + })); + + emscripten::function("set_status", emscripten::optional_override([](const std::string & status) { + { + std::lock_guard lock(g_mutex); + g_status_forced = status; + } + })); +} diff --git a/examples/command.wasm/index-tmpl.html b/examples/command.wasm/index-tmpl.html new file mode 100644 index 0000000..b8dabba --- /dev/null +++ b/examples/command.wasm/index-tmpl.html @@ -0,0 +1,415 @@ + + + + command : Voice assistant example using Whisper + WebAssembly + + + + + + +
+ command : Voice assistant example using Whisper + WebAssembly + +

+ + You can find more about this project on GitHub. + +

+ + More examples: + main | + bench | + stream | + command | + wchess | + +

+ +
+ + Select the model you would like to use, click the "Start" button and follow the instructions. + +

+ +
+ Whisper model: + + +

+ Quantized models:

+ + + + + +
+ +
+ +
+ + + +
+ +
+ +
+ Status: not started + +
[The recognized voice commands will be displayed here]
+
+ +
+ + Debug output: + + +
+ + Troubleshooting + +

+ + The page does some heavy computations, so make sure: + +
    +
  • To use a modern web browser (e.g. Chrome, Firefox)
  • +
  • To use a fast desktop or laptop computer (i.e. not a mobile phone)
  • +
  • Your browser supports WASM Fixed-width SIMD
  • +
+ +
+ + | + Build time: @GIT_DATE@ | + Commit hash: @GIT_SHA1@ | + Commit subject: @GIT_COMMIT_SUBJECT@ | + Source Code | + +
+
+ + + + + + diff --git a/examples/command/CMakeLists.txt b/examples/command/CMakeLists.txt new file mode 100644 index 0000000..c929a6f --- /dev/null +++ b/examples/command/CMakeLists.txt @@ -0,0 +1,10 @@ +if (WHISPER_SDL2) + set(TARGET whisper-command) + add_executable(${TARGET} command.cpp) + + include(DefaultTargetOptions) + + target_link_libraries(${TARGET} PRIVATE common common-sdl whisper ${CMAKE_THREAD_LIBS_INIT}) + + install(TARGETS ${TARGET} RUNTIME) +endif () diff --git a/examples/command/README.md b/examples/command/README.md new file mode 100644 index 0000000..7eb2bb6 --- /dev/null +++ b/examples/command/README.md @@ -0,0 +1,52 @@ +# whisper.cpp/examples/command + +This is a basic Voice Assistant example that accepts voice commands from the microphone. +More info is available in [issue #171](https://github.com/ggerganov/whisper.cpp/issues/171). + +```bash +# Run with default arguments and small model +./whisper-command -m ./models/ggml-small.en.bin -t 8 + +# On Raspberry Pi, use tiny or base models + "-ac 768" for better performance +./whisper-command -m ./models/ggml-tiny.en.bin -ac 768 -t 3 -c 0 +``` + +https://user-images.githubusercontent.com/1991296/204038393-2f846eae-c255-4099-a76d-5735c25c49da.mp4 + +Web version: [examples/command.wasm](/examples/command.wasm) + +## Guided mode + +"Guided mode" allows you to specify a list of commands (i.e. strings) and the transcription will be guided to classify your command into one from the list. This can be useful in situations where a device is listening only for a small subset of commands. + +Initial tests show that this approach might be extremely efficient in terms of performance, since it integrates very well with the "partial Encoder" idea from #137. + +```bash +# Run in guided mode, the list of allowed commands is in commands.txt +./whisper-command -m ./models/ggml-base.en.bin -cmd ./examples/command/commands.txt + +# On Raspberry Pi, in guided mode you can use "-ac 128" for extra performance +./whisper-command -m ./models/ggml-tiny.en.bin -cmd ./examples/command/commands.txt -ac 128 -t 3 -c 0 +``` + +https://user-images.githubusercontent.com/1991296/207435352-8fc4ed3f-bde5-4555-9b8b-aeeb76bee969.mp4 + + +## Building + +The `whisper-command` tool depends on SDL2 library to capture audio from the microphone. You can build it like this: + +```bash +# Install SDL2 +# On Debian based linux distributions: +sudo apt-get install libsdl2-dev + +# On Fedora Linux: +sudo dnf install SDL2 SDL2-devel + +# Install SDL2 on Mac OS +brew install sdl2 + +cmake -B build -DWHISPER_SDL2=ON +cmake --build build --config Release +``` diff --git a/examples/command/command.cpp b/examples/command/command.cpp new file mode 100644 index 0000000..ff7c037 --- /dev/null +++ b/examples/command/command.cpp @@ -0,0 +1,802 @@ +// Voice assistant example +// +// Speak short text commands to the microphone. +// This program will detect your voice command and convert them to text. +// +// ref: https://github.com/ggml-org/whisper.cpp/issues/171 +// + +#include "common-sdl.h" +#include "common.h" +#include "whisper.h" +#include "grammar-parser.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// command-line parameters +struct whisper_params { + int32_t n_threads = std::min(4, (int32_t) std::thread::hardware_concurrency()); + int32_t prompt_ms = 5000; + int32_t command_ms = 8000; + int32_t capture_id = -1; + int32_t max_tokens = 32; + int32_t audio_ctx = 0; + + float vad_thold = 0.6f; + float freq_thold = 100.0f; + + float grammar_penalty = 100.0f; + + grammar_parser::parse_state grammar_parsed; + + bool translate = false; + bool print_special = false; + bool print_energy = false; + bool no_timestamps = true; + bool use_gpu = true; + bool flash_attn = true; + + std::string language = "en"; + std::string model = "models/ggml-base.en.bin"; + std::string fname_out; + std::string commands; + std::string prompt; + std::string context; + std::string grammar; + + // A regular expression that matches tokens to suppress + std::string suppress_regex; +}; + +void whisper_print_usage(int argc, char ** argv, const whisper_params & params); + +static bool whisper_params_parse(int argc, char ** argv, whisper_params & params) { + for (int i = 1; i < argc; i++) { + std::string arg = argv[i]; + + if (arg == "-h" || arg == "--help") { + whisper_print_usage(argc, argv, params); + exit(0); + } + else if (arg == "-t" || arg == "--threads") { params.n_threads = std::stoi(argv[++i]); } + else if (arg == "-pms" || arg == "--prompt-ms") { params.prompt_ms = std::stoi(argv[++i]); } + else if (arg == "-cms" || arg == "--command-ms") { params.command_ms = std::stoi(argv[++i]); } + else if (arg == "-c" || arg == "--capture") { params.capture_id = std::stoi(argv[++i]); } + else if (arg == "-mt" || arg == "--max-tokens") { params.max_tokens = std::stoi(argv[++i]); } + else if (arg == "-ac" || arg == "--audio-ctx") { params.audio_ctx = std::stoi(argv[++i]); } + else if (arg == "-vth" || arg == "--vad-thold") { params.vad_thold = std::stof(argv[++i]); } + else if (arg == "-fth" || arg == "--freq-thold") { params.freq_thold = std::stof(argv[++i]); } + else if (arg == "-tr" || arg == "--translate") { params.translate = true; } + else if (arg == "-ps" || arg == "--print-special") { params.print_special = true; } + else if (arg == "-pe" || arg == "--print-energy") { params.print_energy = true; } + else if (arg == "-ng" || arg == "--no-gpu") { params.use_gpu = false; } + else if (arg == "-fa" || arg == "--flash-attn") { params.flash_attn = true; } + else if (arg == "-nfa" || arg == "--no-flash-attn") { params.flash_attn = false; } + else if (arg == "-l" || arg == "--language") { params.language = argv[++i]; } + else if (arg == "-m" || arg == "--model") { params.model = argv[++i]; } + else if (arg == "-f" || arg == "--file") { params.fname_out = argv[++i]; } + else if (arg == "-cmd" || arg == "--commands") { params.commands = argv[++i]; } + else if (arg == "-p" || arg == "--prompt") { params.prompt = argv[++i]; } + else if (arg == "-ctx" || arg == "--context") { params.context = argv[++i]; } + else if ( arg == "--grammar") { params.grammar = argv[++i]; } + else if ( arg == "--grammar-penalty") { params.grammar_penalty = std::stof(argv[++i]); } + else if ( arg == "--suppress-regex") { params.suppress_regex = argv[++i]; } + else { + fprintf(stderr, "error: unknown argument: %s\n", arg.c_str()); + whisper_print_usage(argc, argv, params); + exit(0); + } + } + + return true; +} + +void whisper_print_usage(int /*argc*/, char ** argv, const whisper_params & params) { + fprintf(stderr, "\n"); + fprintf(stderr, "usage: %s [options]\n", argv[0]); + fprintf(stderr, "\n"); + fprintf(stderr, "options:\n"); + fprintf(stderr, " -h, --help [default] show this help message and exit\n"); + fprintf(stderr, " -t N, --threads N [%-7d] number of threads to use during computation\n", params.n_threads); + fprintf(stderr, " -pms N, --prompt-ms N [%-7d] prompt duration in milliseconds\n", params.prompt_ms); + fprintf(stderr, " -cms N, --command-ms N [%-7d] command duration in milliseconds\n", params.command_ms); + fprintf(stderr, " -c ID, --capture ID [%-7d] capture device ID\n", params.capture_id); + fprintf(stderr, " -mt N, --max-tokens N [%-7d] maximum number of tokens per audio chunk\n", params.max_tokens); + fprintf(stderr, " -ac N, --audio-ctx N [%-7d] audio context size (0 - all)\n", params.audio_ctx); + fprintf(stderr, " -vth N, --vad-thold N [%-7.2f] voice activity detection threshold\n", params.vad_thold); + fprintf(stderr, " -fth N, --freq-thold N [%-7.2f] high-pass frequency cutoff\n", params.freq_thold); + fprintf(stderr, " -tr, --translate [%-7s] translate from source language to english\n", params.translate ? "true" : "false"); + fprintf(stderr, " -ps, --print-special [%-7s] print special tokens\n", params.print_special ? "true" : "false"); + fprintf(stderr, " -pe, --print-energy [%-7s] print sound energy (for debugging)\n", params.print_energy ? "true" : "false"); + fprintf(stderr, " -ng, --no-gpu [%-7s] disable GPU\n", params.use_gpu ? "false" : "true"); + fprintf(stderr, " -fa, --flash-attn [%-7s] enbale flash attention\n", params.flash_attn ? "true" : "false"); + fprintf(stderr, " -nfa, --no-flash-attn [%-7s] disable flash attention\n", params.flash_attn ? "false" : "true"); + fprintf(stderr, " -l LANG, --language LANG [%-7s] spoken language\n", params.language.c_str()); + fprintf(stderr, " -m FNAME, --model FNAME [%-7s] model path\n", params.model.c_str()); + fprintf(stderr, " -f FNAME, --file FNAME [%-7s] text output file name\n", params.fname_out.c_str()); + fprintf(stderr, " -cmd FNAME, --commands FNAME [%-7s] text file with allowed commands\n", params.commands.c_str()); + fprintf(stderr, " -p, --prompt [%-7s] the required activation prompt\n", params.prompt.c_str()); + fprintf(stderr, " -ctx, --context [%-7s] sample text to help the transcription\n", params.context.c_str()); + fprintf(stderr, " --grammar GRAMMAR [%-7s] GBNF grammar to guide decoding\n", params.grammar.c_str()); + fprintf(stderr, " --grammar-penalty N [%-7.1f] scales down logits of nongrammar tokens\n", params.grammar_penalty); + fprintf(stderr, " --suppress-regex REGEX [%-7s] regular expression matching tokens to suppress\n", params.suppress_regex.c_str()); + fprintf(stderr, "\n"); +} + +static std::string transcribe( + whisper_context * ctx, + const whisper_params & params, + const std::vector & pcmf32, + const std::string & grammar_rule, + float & logprob_min, + float & logprob_sum, + int & n_tokens, + int64_t & t_ms) { + const auto t_start = std::chrono::high_resolution_clock::now(); + + logprob_min = 0.0f; + logprob_sum = 0.0f; + n_tokens = 0; + t_ms = 0; + + //whisper_full_params wparams = whisper_full_default_params(WHISPER_SAMPLING_GREEDY); + whisper_full_params wparams = whisper_full_default_params(WHISPER_SAMPLING_BEAM_SEARCH); + + wparams.print_progress = false; + wparams.print_special = params.print_special; + wparams.print_realtime = false; + wparams.print_timestamps = !params.no_timestamps; + wparams.translate = params.translate; + wparams.no_context = true; + wparams.no_timestamps = params.no_timestamps; + wparams.single_segment = true; + wparams.max_tokens = params.max_tokens; + wparams.language = params.language.c_str(); + wparams.n_threads = params.n_threads; + + wparams.audio_ctx = params.audio_ctx; + + wparams.temperature = 0.4f; + wparams.temperature_inc = 1.0f; + wparams.greedy.best_of = 5; + + wparams.beam_search.beam_size = 5; + + wparams.initial_prompt = params.context.data(); + + wparams.suppress_regex = params.suppress_regex.c_str(); + + const auto & grammar_parsed = params.grammar_parsed; + auto grammar_rules = grammar_parsed.c_rules(); + + if (!params.grammar_parsed.rules.empty() && !grammar_rule.empty()) { + if (grammar_parsed.symbol_ids.find(grammar_rule) == grammar_parsed.symbol_ids.end()) { + fprintf(stderr, "%s: warning: grammar rule '%s' not found - skipping grammar sampling\n", __func__, grammar_rule.c_str()); + } else { + wparams.grammar_rules = grammar_rules.data(); + wparams.n_grammar_rules = grammar_rules.size(); + wparams.i_start_rule = grammar_parsed.symbol_ids.at(grammar_rule); + wparams.grammar_penalty = params.grammar_penalty; + } + } + + if (whisper_full(ctx, wparams, pcmf32.data(), pcmf32.size()) != 0) { + return ""; + } + + std::string result; + + const int n_segments = whisper_full_n_segments(ctx); + for (int i = 0; i < n_segments; ++i) { + const char * text = whisper_full_get_segment_text(ctx, i); + + result += text; + + const int n = whisper_full_n_tokens(ctx, i); + for (int j = 0; j < n; ++j) { + const auto token = whisper_full_get_token_data(ctx, i, j); + + if(token.plog > 0.0f) exit(0); + logprob_min = std::min(logprob_min, token.plog); + logprob_sum += token.plog; + ++n_tokens; + } + } + + const auto t_end = std::chrono::high_resolution_clock::now(); + t_ms = std::chrono::duration_cast(t_end - t_start).count(); + + return result; +} + +static std::vector read_allowed_commands(const std::string & fname) { + std::vector allowed_commands; + + std::ifstream ifs(fname); + if (!ifs.is_open()) { + return allowed_commands; + } + + std::string line; + while (std::getline(ifs, line)) { + line = ::trim(line); + if (line.empty()) { + continue; + } + + std::transform(line.begin(), line.end(),line.begin(), ::tolower); + allowed_commands.push_back(std::move(line)); + } + + return allowed_commands; +} + +static std::vector get_words(const std::string &txt) { + std::vector words; + + std::istringstream iss(txt); + std::string word; + while (iss >> word) { + words.push_back(word); + } + + return words; +} + +// command-list mode +// guide the transcription to match the most likely command from a provided list +static int process_command_list(struct whisper_context * ctx, audio_async &audio, const whisper_params ¶ms, std::ofstream &fout) { + fprintf(stderr, "\n"); + fprintf(stderr, "%s: guided mode\n", __func__); + + std::vector allowed_commands = read_allowed_commands(params.commands); + + if (allowed_commands.empty()) { + fprintf(stderr, "%s: error: failed to read allowed commands from '%s'\n", __func__, params.commands.c_str()); + return 2; + } + + int max_len = 0; + + std::vector> allowed_tokens; + + for (const auto & cmd : allowed_commands) { + whisper_token tokens[1024]; + allowed_tokens.emplace_back(); + + for (int l = 0; l < (int) cmd.size(); ++l) { + // NOTE: very important to add the whitespace ! + // the reason is that the first decoded token starts with a whitespace too! + std::string ss = std::string(" ") + cmd.substr(0, l + 1); + + const int n = whisper_tokenize(ctx, ss.c_str(), tokens, 1024); + if (n < 0) { + fprintf(stderr, "%s: error: failed to tokenize command '%s'\n", __func__, cmd.c_str()); + return 3; + } + + if (n == 1) { + allowed_tokens.back().push_back(tokens[0]); + } + } + + max_len = std::max(max_len, (int) cmd.size()); + } + + fprintf(stderr, "%s: allowed commands [ tokens ]:\n", __func__); + fprintf(stderr, "\n"); + for (int i = 0; i < (int) allowed_commands.size(); ++i) { + fprintf(stderr, " - \033[1m%-*s\033[0m = [", max_len, allowed_commands[i].c_str()); + for (const auto & token : allowed_tokens[i]) { + fprintf(stderr, " %5d", token); + } + fprintf(stderr, " ]\n"); + } + + std::string k_prompt = "select one from the available words: "; + for (int i = 0; i < (int) allowed_commands.size(); ++i) { + if (i > 0) { + k_prompt += ", "; + } + k_prompt += allowed_commands[i]; + } + k_prompt += ". selected word: "; + + // tokenize prompt + std::vector k_tokens; + { + k_tokens.resize(1024); + const int n = whisper_tokenize(ctx, k_prompt.c_str(), k_tokens.data(), 1024); + if (n < 0) { + fprintf(stderr, "%s: error: failed to tokenize prompt '%s'\n", __func__, k_prompt.c_str()); + return 4; + } + k_tokens.resize(n); + } + + fprintf(stderr, "\n"); + fprintf(stderr, "%s: prompt: '%s'\n", __func__, k_prompt.c_str()); + fprintf(stderr, "%s: tokens: [", __func__); + for (const auto & token : k_tokens) { + fprintf(stderr, " %d", token); + } + fprintf(stderr, " ]\n"); + + fprintf(stderr, "\n"); + fprintf(stderr, "%s: listening for a command ...\n", __func__); + fprintf(stderr, "\n"); + + bool is_running = true; + + std::vector pcmf32_cur; + std::vector pcmf32_prompt; + + // main loop + while (is_running) { + // handle Ctrl + C + is_running = sdl_poll_events(); + + // delay + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + audio.get(2000, pcmf32_cur); + + if (::vad_simple(pcmf32_cur, WHISPER_SAMPLE_RATE, 1000, params.vad_thold, params.freq_thold, params.print_energy)) { + fprintf(stdout, "%s: Speech detected! Processing ...\n", __func__); + + const auto t_start = std::chrono::high_resolution_clock::now(); + + whisper_full_params wparams = whisper_full_default_params(WHISPER_SAMPLING_GREEDY); + + wparams.print_progress = false; + wparams.print_special = params.print_special; + wparams.print_realtime = false; + wparams.print_timestamps = !params.no_timestamps; + wparams.translate = params.translate; + wparams.no_context = true; + wparams.single_segment = true; + wparams.max_tokens = 1; + wparams.language = params.language.c_str(); + wparams.n_threads = params.n_threads; + + wparams.audio_ctx = params.audio_ctx; + + wparams.prompt_tokens = k_tokens.data(); + wparams.prompt_n_tokens = k_tokens.size(); + + // run the transformer and a single decoding pass + if (whisper_full(ctx, wparams, pcmf32_cur.data(), pcmf32_cur.size()) != 0) { + fprintf(stderr, "%s: ERROR: whisper_full() failed\n", __func__); + break; + } + + // estimate command probability + // NOTE: not optimal + { + const auto * logits = whisper_get_logits(ctx); + + std::vector probs(whisper_n_vocab(ctx), 0.0f); + + // compute probs from logits via softmax + { + float max = -1e9; + for (int i = 0; i < (int) probs.size(); ++i) { + max = std::max(max, logits[i]); + } + + float sum = 0.0f; + for (int i = 0; i < (int) probs.size(); ++i) { + probs[i] = expf(logits[i] - max); + sum += probs[i]; + } + + for (int i = 0; i < (int) probs.size(); ++i) { + probs[i] /= sum; + } + } + + std::vector> probs_id; + + double psum = 0.0; + for (int i = 0; i < (int) allowed_commands.size(); ++i) { + probs_id.emplace_back(probs[allowed_tokens[i][0]], i); + for (int j = 1; j < (int) allowed_tokens[i].size(); ++j) { + probs_id.back().first += probs[allowed_tokens[i][j]]; + } + probs_id.back().first /= allowed_tokens[i].size(); + psum += probs_id.back().first; + } + + // normalize + for (auto & p : probs_id) { + p.first /= psum; + } + + // sort descending + { + using pair_type = decltype(probs_id)::value_type; + std::sort(probs_id.begin(), probs_id.end(), [](const pair_type & a, const pair_type & b) { + return a.first > b.first; + }); + } + + // print the commands and the respective probabilities + { + fprintf(stdout, "\n"); + for (const auto & cmd : probs_id) { + fprintf(stdout, "%s: %s%-*s%s = %f | ", __func__, "\033[1m", max_len, allowed_commands[cmd.second].c_str(), "\033[0m", cmd.first); + for (int token : allowed_tokens[cmd.second]) { + fprintf(stdout, "'%4s' %f ", whisper_token_to_str(ctx, token), probs[token]); + } + fprintf(stdout, "\n"); + } + } + + // best command + { + const auto t_end = std::chrono::high_resolution_clock::now(); + + const float prob = probs_id[0].first; + const int index = probs_id[0].second; + const char * best_command = allowed_commands[index].c_str(); + + fprintf(stdout, "\n"); + fprintf(stdout, "%s: detected command: %s%s%s | p = %f | t = %d ms\n", __func__, + "\033[1m", best_command, "\033[0m", prob, + (int) std::chrono::duration_cast(t_end - t_start).count()); + fprintf(stdout, "\n"); + if (fout.is_open()) { + fout << best_command << std::endl; + } + } + } + + audio.clear(); + } + } + + return 0; +} + +// always-prompt mode +// transcribe the voice into text after valid prompt +static int always_prompt_transcription(struct whisper_context * ctx, audio_async & audio, const whisper_params & params, std::ofstream & fout) { + bool is_running = true; + bool ask_prompt = true; + + float logprob_min = 0.0f; + float logprob_sum = 0.0f; + int n_tokens = 0; + + std::vector pcmf32_cur; + + const std::string k_prompt = params.prompt; + + const int k_prompt_length = get_words(k_prompt).size(); + + fprintf(stderr, "\n"); + fprintf(stderr, "%s: always-prompt mode\n", __func__); + + // main loop + while (is_running) { + // handle Ctrl + C + is_running = sdl_poll_events(); + + // delay + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + if (ask_prompt) { + fprintf(stdout, "\n"); + fprintf(stdout, "%s: The prompt is: '%s%s%s'\n", __func__, "\033[1m", k_prompt.c_str(), "\033[0m"); + fprintf(stdout, "\n"); + + ask_prompt = false; + } + + { + audio.get(2000, pcmf32_cur); + + if (::vad_simple(pcmf32_cur, WHISPER_SAMPLE_RATE, 1000, params.vad_thold, params.freq_thold, params.print_energy)) { + fprintf(stdout, "%s: Speech detected! Processing ...\n", __func__); + + int64_t t_ms = 0; + + // detect the commands + audio.get(params.command_ms, pcmf32_cur); + + const auto txt = ::trim(::transcribe(ctx, params, pcmf32_cur, "", logprob_min, logprob_sum, n_tokens, t_ms)); + + const auto words = get_words(txt); + + std::string prompt; + std::string command; + + for (int i = 0; i < (int) words.size(); ++i) { + if (i < k_prompt_length) { + prompt += words[i] + " "; + } else { + command += words[i] + " "; + } + } + + const float sim = similarity(prompt, k_prompt); + + //debug + //fprintf(stdout, "command size: %i\n", command_length); + + if ((sim > 0.7f) && (command.size() > 0)) { + fprintf(stdout, "%s: Command '%s%s%s', (t = %d ms)\n", __func__, "\033[1m", command.c_str(), "\033[0m", (int) t_ms); + if (fout.is_open()) { + fout << command << std::endl; + } + } + + fprintf(stdout, "\n"); + + audio.clear(); + } + } + } + + return 0; +} + +// general-purpose mode +// freely transcribe the voice into text +static int process_general_transcription(struct whisper_context * ctx, audio_async & audio, const whisper_params & params, std::ofstream & fout) { + bool is_running = true; + bool have_prompt = false; + bool ask_prompt = true; + + float logprob_min0 = 0.0f; + float logprob_min = 0.0f; + + float logprob_sum0 = 0.0f; + float logprob_sum = 0.0f; + + int n_tokens0 = 0; + int n_tokens = 0; + + std::vector pcmf32_cur; + std::vector pcmf32_prompt; + + std::string k_prompt = "Ok Whisper, start listening for commands."; + if (!params.prompt.empty()) { + k_prompt = params.prompt; + } + + fprintf(stderr, "\n"); + fprintf(stderr, "%s: general-purpose mode\n", __func__); + + // main loop + while (is_running) { + // handle Ctrl + C + is_running = sdl_poll_events(); + + // delay + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + if (ask_prompt) { + fprintf(stdout, "\n"); + fprintf(stdout, "%s: Say the following phrase: '%s%s%s'\n", __func__, "\033[1m", k_prompt.c_str(), "\033[0m"); + fprintf(stdout, "\n"); + + ask_prompt = false; + } + + { + audio.get(2000, pcmf32_cur); + + if (::vad_simple(pcmf32_cur, WHISPER_SAMPLE_RATE, 1000, params.vad_thold, params.freq_thold, params.print_energy)) { + fprintf(stdout, "%s: Speech detected! Processing ...\n", __func__); + + int64_t t_ms = 0; + + if (!have_prompt) { + // wait for activation phrase + audio.get(params.prompt_ms, pcmf32_cur); + + const auto txt = ::trim(::transcribe(ctx, params, pcmf32_cur, "prompt", logprob_min0, logprob_sum0, n_tokens0, t_ms)); + + const float p = 100.0f * std::exp(logprob_min0); + + fprintf(stdout, "%s: Heard '%s%s%s', (t = %d ms, p = %.2f%%)\n", __func__, "\033[1m", txt.c_str(), "\033[0m", (int) t_ms, p); + + const float sim = similarity(txt, k_prompt); + + if (txt.length() < 0.8*k_prompt.length() || txt.length() > 1.2*k_prompt.length() || sim < 0.8f) { + fprintf(stdout, "%s: WARNING: prompt not recognized, try again\n", __func__); + ask_prompt = true; + } else { + fprintf(stdout, "\n"); + fprintf(stdout, "%s: The prompt has been recognized!\n", __func__); + fprintf(stdout, "%s: Waiting for voice commands ...\n", __func__); + fprintf(stdout, "\n"); + + // save the audio for the prompt + pcmf32_prompt = pcmf32_cur; + have_prompt = true; + } + } else { + // we have heard the activation phrase, now detect the commands + audio.get(params.command_ms, pcmf32_cur); + + //printf("len prompt: %.4f\n", pcmf32_prompt.size() / (float) WHISPER_SAMPLE_RATE); + //printf("len command: %.4f\n", pcmf32_cur.size() / (float) WHISPER_SAMPLE_RATE); + + // prepend 3 second of silence + pcmf32_cur.insert(pcmf32_cur.begin(), 3.0f*WHISPER_SAMPLE_RATE, 0.0f); + + // prepend the prompt audio + pcmf32_cur.insert(pcmf32_cur.begin(), pcmf32_prompt.begin(), pcmf32_prompt.end()); + + const auto txt = ::trim(::transcribe(ctx, params, pcmf32_cur, "root", logprob_min, logprob_sum, n_tokens, t_ms)); + + //const float p = 100.0f * std::exp((logprob - logprob0) / (n_tokens - n_tokens0)); + const float p = 100.0f * std::exp(logprob_min); + + //fprintf(stdout, "%s: heard '%s'\n", __func__, txt.c_str()); + + // find the prompt in the text + float best_sim = 0.0f; + size_t best_len = 0; + for (size_t n = 0.8*k_prompt.size(); n <= 1.2*k_prompt.size(); ++n) { + if (n >= txt.size()) { + break; + } + + const auto prompt = txt.substr(0, n); + + const float sim = similarity(prompt, k_prompt); + + //fprintf(stderr, "%s: prompt = '%s', sim = %f\n", __func__, prompt.c_str(), sim); + + if (sim > best_sim) { + best_sim = sim; + best_len = n; + } + } + + fprintf(stdout, "%s: DEBUG: txt = '%s', prob = %.2f%%\n", __func__, txt.c_str(), p); + if (best_len == 0) { + fprintf(stdout, "%s: WARNING: command not recognized, try again\n", __func__); + } else { + // cut the prompt from the decoded text + const std::string command = ::trim(txt.substr(best_len)); + fprintf(stdout, "%s: Command '%s%s%s', (t = %d ms)\n", __func__, "\033[1m", command.c_str(), "\033[0m", (int) t_ms); + if (fout.is_open()) { + fout << command << std::endl; + } + } + + fprintf(stdout, "\n"); + } + + audio.clear(); + } + } + } + + return 0; +} + +int main(int argc, char ** argv) { + ggml_backend_load_all(); + + whisper_params params; + + if (whisper_params_parse(argc, argv, params) == false) { + return 1; + } + + if (whisper_lang_id(params.language.c_str()) == -1) { + fprintf(stderr, "error: unknown language '%s'\n", params.language.c_str()); + whisper_print_usage(argc, argv, params); + exit(0); + } + + // whisper init + + struct whisper_context_params cparams = whisper_context_default_params(); + + cparams.use_gpu = params.use_gpu; + cparams.flash_attn = params.flash_attn; + + struct whisper_context * ctx = whisper_init_from_file_with_params(params.model.c_str(), cparams); + if (ctx == nullptr) { + fprintf(stderr, "error: failed to initialize whisper context\n"); + return 2; + } + + // print some info about the processing + { + fprintf(stderr, "\n"); + if (!whisper_is_multilingual(ctx)) { + if (params.language != "en" || params.translate) { + params.language = "en"; + params.translate = false; + fprintf(stderr, "%s: WARNING: model is not multilingual, ignoring language and translation options\n", __func__); + } + } + fprintf(stderr, "%s: processing, %d threads, lang = %s, task = %s, timestamps = %d ...\n", + __func__, + params.n_threads, + params.language.c_str(), + params.translate ? "translate" : "transcribe", + params.no_timestamps ? 0 : 1); + + fprintf(stderr, "\n"); + } + + // init audio + + audio_async audio(30*1000); + if (!audio.init(params.capture_id, WHISPER_SAMPLE_RATE)) { + fprintf(stderr, "%s: audio.init() failed!\n", __func__); + return 1; + } + + audio.resume(); + + // wait for 1 second to avoid any buffered noise + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + audio.clear(); + + int ret_val = 0; + + if (!params.grammar.empty()) { + auto & grammar = params.grammar_parsed; + if (is_file_exist(params.grammar.c_str())) { + // read grammar from file + std::ifstream ifs(params.grammar.c_str()); + const std::string txt = std::string((std::istreambuf_iterator(ifs)), std::istreambuf_iterator()); + grammar = grammar_parser::parse(txt.c_str()); + } else { + // read grammar from string + grammar = grammar_parser::parse(params.grammar.c_str()); + } + + // will be empty (default) if there are parse errors + if (grammar.rules.empty()) { + ret_val = 1; + } else { + fprintf(stderr, "%s: grammar:\n", __func__); + grammar_parser::print_grammar(stderr, grammar); + fprintf(stderr, "\n"); + } + } + + std::ofstream fout; + if (params.fname_out.length() > 0) { + fout.open(params.fname_out); + if (!fout.is_open()) { + fprintf(stderr, "%s: failed to open output file '%s'!\n", __func__, params.fname_out.c_str()); + return 1; + } + } + + if (ret_val == 0) { + if (!params.commands.empty()) { + ret_val = process_command_list(ctx, audio, params, fout); + } else if (!params.prompt.empty() && params.grammar_parsed.rules.empty()) { + ret_val = always_prompt_transcription(ctx, audio, params, fout); + } else { + ret_val = process_general_transcription(ctx, audio, params, fout); + } + } + + audio.pause(); + + whisper_print_timings(ctx); + whisper_free(ctx); + + return ret_val; +} diff --git a/examples/command/commands.txt b/examples/command/commands.txt new file mode 100644 index 0000000..2653de6 --- /dev/null +++ b/examples/command/commands.txt @@ -0,0 +1,9 @@ +enable +disable +cat +dog +apple +red +blue +green +lightblue diff --git a/examples/common-ggml.cpp b/examples/common-ggml.cpp new file mode 100644 index 0000000..11a5c0a --- /dev/null +++ b/examples/common-ggml.cpp @@ -0,0 +1,246 @@ +#include "common-ggml.h" + +#include +#include + +static const std::map GGML_FTYPE_MAP = { + {"q4_0", GGML_FTYPE_MOSTLY_Q4_0}, + {"q4_1", GGML_FTYPE_MOSTLY_Q4_1}, + {"q5_0", GGML_FTYPE_MOSTLY_Q5_0}, + {"q5_1", GGML_FTYPE_MOSTLY_Q5_1}, + {"q8_0", GGML_FTYPE_MOSTLY_Q8_0}, + {"q2_k", GGML_FTYPE_MOSTLY_Q2_K}, + {"q3_k", GGML_FTYPE_MOSTLY_Q3_K}, + {"q4_k", GGML_FTYPE_MOSTLY_Q4_K}, + {"q5_k", GGML_FTYPE_MOSTLY_Q5_K}, + {"q6_k", GGML_FTYPE_MOSTLY_Q6_K}, +}; + +void ggml_print_ftypes(FILE * fp) { + for (auto it = GGML_FTYPE_MAP.begin(); it != GGML_FTYPE_MAP.end(); it++) { + fprintf(fp, " type = \"%s\" or %d\n", it->first.c_str(), it->second); + } +} + +enum ggml_ftype ggml_parse_ftype(const char * str) { + enum ggml_ftype ftype; + if (str[0] == 'q') { + const auto it = GGML_FTYPE_MAP.find(str); + if (it == GGML_FTYPE_MAP.end()) { + fprintf(stderr, "%s: unknown ftype '%s'\n", __func__, str); + return GGML_FTYPE_UNKNOWN; + } + ftype = it->second; + } else { + ftype = (enum ggml_ftype) atoi(str); + } + + return ftype; +} + +bool ggml_common_quantize_0( + std::ifstream & finp, + std::ofstream & fout, + const ggml_ftype ftype, + const std::vector & to_quant, + const std::vector & to_skip) { + + ggml_type qtype = GGML_TYPE_F32; + + switch (ftype) { + case GGML_FTYPE_MOSTLY_Q4_0: qtype = GGML_TYPE_Q4_0; break; + case GGML_FTYPE_MOSTLY_Q4_1: qtype = GGML_TYPE_Q4_1; break; + case GGML_FTYPE_MOSTLY_Q5_0: qtype = GGML_TYPE_Q5_0; break; + case GGML_FTYPE_MOSTLY_Q5_1: qtype = GGML_TYPE_Q5_1; break; + case GGML_FTYPE_MOSTLY_Q8_0: qtype = GGML_TYPE_Q8_0; break; + case GGML_FTYPE_MOSTLY_Q2_K: qtype = GGML_TYPE_Q2_K; break; + case GGML_FTYPE_MOSTLY_Q3_K: qtype = GGML_TYPE_Q3_K; break; + case GGML_FTYPE_MOSTLY_Q4_K: qtype = GGML_TYPE_Q4_K; break; + case GGML_FTYPE_MOSTLY_Q5_K: qtype = GGML_TYPE_Q5_K; break; + case GGML_FTYPE_MOSTLY_Q6_K: qtype = GGML_TYPE_Q6_K; break; + case GGML_FTYPE_UNKNOWN: + case GGML_FTYPE_ALL_F32: + case GGML_FTYPE_MOSTLY_F16: + case GGML_FTYPE_MOSTLY_Q4_1_SOME_F16: + case GGML_FTYPE_MOSTLY_IQ2_XXS: + case GGML_FTYPE_MOSTLY_IQ2_XS: + case GGML_FTYPE_MOSTLY_IQ2_S: + case GGML_FTYPE_MOSTLY_IQ3_XXS: + case GGML_FTYPE_MOSTLY_IQ3_S: + case GGML_FTYPE_MOSTLY_IQ1_S: + case GGML_FTYPE_MOSTLY_IQ4_NL: + case GGML_FTYPE_MOSTLY_IQ4_XS: + case GGML_FTYPE_MOSTLY_IQ1_M: + case GGML_FTYPE_MOSTLY_BF16: + case GGML_FTYPE_MOSTLY_MXFP4: + case GGML_FTYPE_MOSTLY_NVFP4: + case GGML_FTYPE_MOSTLY_Q1_0: + case GGML_FTYPE_MOSTLY_Q2_0: + { + fprintf(stderr, "%s: invalid model type %d\n", __func__, ftype); + return false; + } + }; + + if (!ggml_is_quantized(qtype)) { + fprintf(stderr, "%s: invalid quantization type %d (%s)\n", __func__, qtype, ggml_type_name(qtype)); + return false; + } + + size_t total_size_org = 0; + size_t total_size_new = 0; + + std::vector work; + + std::vector data_u8; + std::vector data_f16; + std::vector data_f32; + + while (true) { + int32_t n_dims; + int32_t length; + int32_t ttype; + + finp.read(reinterpret_cast(&n_dims), sizeof(n_dims)); + finp.read(reinterpret_cast(&length), sizeof(length)); + finp.read(reinterpret_cast(&ttype), sizeof(ttype)); + + if (finp.eof()) { + break; + } + + int32_t nelements = 1; + int32_t ne[4] = { 1, 1, 1, 1 }; + for (int i = 0; i < n_dims; ++i) { + finp.read (reinterpret_cast(&ne[i]), sizeof(ne[i])); + nelements *= ne[i]; + } + + std::string name(length, 0); + finp.read (&name[0], length); + + printf("%64s - [%5d, %5d, %5d], type = %6s ", name.data(), ne[0], ne[1], ne[2], ggml_type_name((ggml_type) ttype)); + + bool quantize = false; + + // check if we should quantize this tensor + for (const auto & s : to_quant) { + if (std::regex_match(name, std::regex(s))) { + quantize = true; + break; + } + } + + // check if we should skip this tensor + for (const auto & s : to_skip) { + if (std::regex_match(name, std::regex(s))) { + quantize = false; + break; + } + } + + // quantize only 2D tensors + quantize &= (n_dims == 2); + + if (quantize) { + if (ttype != GGML_TYPE_F32 && ttype != GGML_TYPE_F16) { + fprintf(stderr, "%s: unsupported ttype %d (%s) for integer quantization\n", __func__, ttype, ggml_type_name((ggml_type) ttype)); + return false; + } + + if (ttype == GGML_TYPE_F16) { + data_f16.resize(nelements); + finp.read(reinterpret_cast(data_f16.data()), nelements * sizeof(ggml_fp16_t)); + data_f32.resize(nelements); + for (int i = 0; i < nelements; ++i) { + data_f32[i] = ggml_fp16_to_fp32(data_f16[i]); + } + } else { + data_f32.resize(nelements); + finp.read(reinterpret_cast(data_f32.data()), nelements * sizeof(float)); + } + + ttype = qtype; + } else { + const int bpe = (ttype == 0) ? sizeof(float) : sizeof(uint16_t); + + data_u8.resize(nelements*bpe); + finp.read(reinterpret_cast(data_u8.data()), nelements * bpe); + } + + fout.write(reinterpret_cast(&n_dims), sizeof(n_dims)); + fout.write(reinterpret_cast(&length), sizeof(length)); + fout.write(reinterpret_cast(&ttype), sizeof(ttype)); + for (int i = 0; i < n_dims; ++i) { + fout.write(reinterpret_cast(&ne[i]), sizeof(ne[i])); + } + fout.write(&name[0], length); + + if (quantize) { + work.resize(nelements); // for quantization + + size_t cur_size = 0; + switch ((ggml_type) ttype) { + case GGML_TYPE_Q4_0: + case GGML_TYPE_Q4_1: + case GGML_TYPE_Q5_0: + case GGML_TYPE_Q5_1: + case GGML_TYPE_Q8_0: + case GGML_TYPE_Q2_K: + case GGML_TYPE_Q3_K: + case GGML_TYPE_Q4_K: + case GGML_TYPE_Q5_K: + case GGML_TYPE_Q6_K: + { + cur_size = ggml_quantize_chunk((ggml_type) ttype, data_f32.data(), work.data(), 0, nelements/ne[0], ne[0], nullptr); + } break; + case GGML_TYPE_F32: + case GGML_TYPE_F16: + case GGML_TYPE_I8: + case GGML_TYPE_I16: + case GGML_TYPE_I32: + case GGML_TYPE_I64: + case GGML_TYPE_F64: + case GGML_TYPE_Q8_1: + case GGML_TYPE_Q8_K: + case GGML_TYPE_IQ2_XXS: + case GGML_TYPE_IQ2_XS: + case GGML_TYPE_IQ2_S: + case GGML_TYPE_IQ3_XXS: + case GGML_TYPE_IQ3_S: + case GGML_TYPE_IQ1_S: + case GGML_TYPE_IQ4_NL: + case GGML_TYPE_IQ4_XS: + case GGML_TYPE_IQ1_M: + case GGML_TYPE_BF16: + case GGML_TYPE_TQ1_0: + case GGML_TYPE_TQ2_0: + case GGML_TYPE_MXFP4: + case GGML_TYPE_NVFP4: + case GGML_TYPE_Q1_0: + case GGML_TYPE_Q2_0: + case GGML_TYPE_COUNT: + { + fprintf(stderr, "%s: unsupported quantization type %d (%s)\n", __func__, ttype, ggml_type_name((ggml_type) ttype)); + return false; + } + } + + fout.write(reinterpret_cast(work.data()), cur_size); + total_size_new += cur_size; + + printf("size = %8.2f MB -> %8.2f MB\n", nelements * sizeof(float)/1024.0/1024.0, cur_size/1024.0/1024.0); + } else { + printf("size = %8.3f MB\n", data_u8.size()/1024.0/1024.0); + fout.write(reinterpret_cast(data_u8.data()), data_u8.size()); + total_size_new += data_u8.size(); + } + + total_size_org += nelements * sizeof(float); + } + + printf("%s: model size = %8.2f MB\n", __func__, total_size_org/1024.0/1024.0); + printf("%s: quant size = %8.2f MB | ftype = %d (%s)\n", __func__, total_size_new/1024.0/1024.0, ftype, ggml_type_name(qtype)); + + return true; +} diff --git a/examples/common-ggml.h b/examples/common-ggml.h new file mode 100644 index 0000000..477de34 --- /dev/null +++ b/examples/common-ggml.h @@ -0,0 +1,18 @@ +#pragma once + +#include "ggml.h" + +#include +#include +#include + +enum ggml_ftype ggml_parse_ftype(const char * str); + +void ggml_print_ftypes(FILE * fp = stderr); + +bool ggml_common_quantize_0( + std::ifstream & finp, + std::ofstream & fout, + const ggml_ftype ftype, + const std::vector & to_quant, + const std::vector & to_skip); diff --git a/examples/common-sdl.cpp b/examples/common-sdl.cpp new file mode 100644 index 0000000..c18a5f3 --- /dev/null +++ b/examples/common-sdl.cpp @@ -0,0 +1,227 @@ +#include "common-sdl.h" + +#include + +audio_async::audio_async(int len_ms) { + m_len_ms = len_ms; + + m_running = false; +} + +audio_async::~audio_async() { + if (m_dev_id_in) { + SDL_CloseAudioDevice(m_dev_id_in); + } +} + +bool audio_async::init(int capture_id, int sample_rate) { + SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); + + if (SDL_Init(SDL_INIT_AUDIO) < 0) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError()); + return false; + } + + SDL_SetHintWithPriority(SDL_HINT_AUDIO_RESAMPLING_MODE, "medium", SDL_HINT_OVERRIDE); + + { + int nDevices = SDL_GetNumAudioDevices(SDL_TRUE); + fprintf(stderr, "%s: found %d capture devices:\n", __func__, nDevices); + for (int i = 0; i < nDevices; i++) { + fprintf(stderr, "%s: - Capture device #%d: '%s'\n", __func__, i, SDL_GetAudioDeviceName(i, SDL_TRUE)); + } + } + + SDL_AudioSpec capture_spec_requested; + SDL_AudioSpec capture_spec_obtained; + + SDL_zero(capture_spec_requested); + SDL_zero(capture_spec_obtained); + + capture_spec_requested.freq = sample_rate; + capture_spec_requested.format = AUDIO_F32; + capture_spec_requested.channels = 1; + capture_spec_requested.samples = 1024; + capture_spec_requested.callback = [](void * userdata, uint8_t * stream, int len) { + audio_async * audio = (audio_async *) userdata; + audio->callback(stream, len); + }; + capture_spec_requested.userdata = this; + + if (capture_id >= 0) { + fprintf(stderr, "%s: attempt to open capture device %d : '%s' ...\n", __func__, capture_id, SDL_GetAudioDeviceName(capture_id, SDL_TRUE)); + m_dev_id_in = SDL_OpenAudioDevice(SDL_GetAudioDeviceName(capture_id, SDL_TRUE), SDL_TRUE, &capture_spec_requested, &capture_spec_obtained, 0); + } else { + fprintf(stderr, "%s: attempt to open default capture device ...\n", __func__); + m_dev_id_in = SDL_OpenAudioDevice(nullptr, SDL_TRUE, &capture_spec_requested, &capture_spec_obtained, 0); + } + + if (!m_dev_id_in) { + fprintf(stderr, "%s: couldn't open an audio device for capture: %s!\n", __func__, SDL_GetError()); + m_dev_id_in = 0; + + return false; + } else { + fprintf(stderr, "%s: obtained spec for input device (SDL Id = %d):\n", __func__, m_dev_id_in); + fprintf(stderr, "%s: - sample rate: %d\n", __func__, capture_spec_obtained.freq); + fprintf(stderr, "%s: - format: %d (required: %d)\n", __func__, capture_spec_obtained.format, + capture_spec_requested.format); + fprintf(stderr, "%s: - channels: %d (required: %d)\n", __func__, capture_spec_obtained.channels, + capture_spec_requested.channels); + fprintf(stderr, "%s: - samples per frame: %d\n", __func__, capture_spec_obtained.samples); + } + + m_sample_rate = capture_spec_obtained.freq; + + m_audio.resize((m_sample_rate*m_len_ms)/1000); + + return true; +} + +bool audio_async::resume() { + if (!m_dev_id_in) { + fprintf(stderr, "%s: no audio device to resume!\n", __func__); + return false; + } + + if (m_running) { + fprintf(stderr, "%s: already running!\n", __func__); + return false; + } + + SDL_PauseAudioDevice(m_dev_id_in, 0); + + m_running = true; + + return true; +} + +bool audio_async::pause() { + if (!m_dev_id_in) { + fprintf(stderr, "%s: no audio device to pause!\n", __func__); + return false; + } + + if (!m_running) { + fprintf(stderr, "%s: already paused!\n", __func__); + return false; + } + + SDL_PauseAudioDevice(m_dev_id_in, 1); + + m_running = false; + + return true; +} + +bool audio_async::clear() { + if (!m_dev_id_in) { + fprintf(stderr, "%s: no audio device to clear!\n", __func__); + return false; + } + + if (!m_running) { + fprintf(stderr, "%s: not running!\n", __func__); + return false; + } + + { + std::lock_guard lock(m_mutex); + + m_audio_pos = 0; + m_audio_len = 0; + } + + return true; +} + +// callback to be called by SDL +void audio_async::callback(uint8_t * stream, int len) { + if (!m_running) { + return; + } + + size_t n_samples = len / sizeof(float); + + if (n_samples > m_audio.size()) { + n_samples = m_audio.size(); + + stream += (len - (n_samples * sizeof(float))); + } + + //fprintf(stderr, "%s: %zu samples, pos %zu, len %zu\n", __func__, n_samples, m_audio_pos, m_audio_len); + + { + std::lock_guard lock(m_mutex); + + if (m_audio_pos + n_samples > m_audio.size()) { + const size_t n0 = m_audio.size() - m_audio_pos; + + memcpy(&m_audio[m_audio_pos], stream, n0 * sizeof(float)); + memcpy(&m_audio[0], stream + n0 * sizeof(float), (n_samples - n0) * sizeof(float)); + } else { + memcpy(&m_audio[m_audio_pos], stream, n_samples * sizeof(float)); + } + m_audio_pos = (m_audio_pos + n_samples) % m_audio.size(); + m_audio_len = std::min(m_audio_len + n_samples, m_audio.size()); + } +} + +void audio_async::get(int ms, std::vector & result) { + if (!m_dev_id_in) { + fprintf(stderr, "%s: no audio device to get audio from!\n", __func__); + return; + } + + if (!m_running) { + fprintf(stderr, "%s: not running!\n", __func__); + return; + } + + result.clear(); + + { + std::lock_guard lock(m_mutex); + + if (ms <= 0) { + ms = m_len_ms; + } + + size_t n_samples = (m_sample_rate * ms) / 1000; + if (n_samples > m_audio_len) { + n_samples = m_audio_len; + } + + result.resize(n_samples); + + int s0 = m_audio_pos - n_samples; + if (s0 < 0) { + s0 += m_audio.size(); + } + + if (s0 + n_samples > m_audio.size()) { + const size_t n0 = m_audio.size() - s0; + + memcpy(result.data(), &m_audio[s0], n0 * sizeof(float)); + memcpy(&result[n0], &m_audio[0], (n_samples - n0) * sizeof(float)); + } else { + memcpy(result.data(), &m_audio[s0], n_samples * sizeof(float)); + } + } +} + +bool sdl_poll_events() { + SDL_Event event; + while (SDL_PollEvent(&event)) { + switch (event.type) { + case SDL_QUIT: + { + return false; + } + default: + break; + } + } + + return true; +} diff --git a/examples/common-sdl.h b/examples/common-sdl.h new file mode 100644 index 0000000..9ee8a32 --- /dev/null +++ b/examples/common-sdl.h @@ -0,0 +1,49 @@ +#pragma once + +#include +#include + +#include +#include +#include +#include + +// +// SDL Audio capture +// + +class audio_async { +public: + audio_async(int len_ms); + ~audio_async(); + + bool init(int capture_id, int sample_rate); + + // start capturing audio via the provided SDL callback + // keep last len_ms seconds of audio in a circular buffer + bool resume(); + bool pause(); + bool clear(); + + // callback to be called by SDL + void callback(uint8_t * stream, int len); + + // get audio data from the circular buffer + void get(int ms, std::vector & audio); + +private: + SDL_AudioDeviceID m_dev_id_in = 0; + + int m_len_ms = 0; + int m_sample_rate = 0; + + std::atomic_bool m_running; + std::mutex m_mutex; + + std::vector m_audio; + size_t m_audio_pos = 0; + size_t m_audio_len = 0; +}; + +// Return false if need to quit +bool sdl_poll_events(); diff --git a/examples/common-whisper.cpp b/examples/common-whisper.cpp new file mode 100644 index 0000000..b12481c --- /dev/null +++ b/examples/common-whisper.cpp @@ -0,0 +1,247 @@ +#define _USE_MATH_DEFINES // for M_PI + +#include "common-whisper.h" + +#include "common.h" + +#include "whisper.h" + +// third-party utilities +// use your favorite implementations +#define STB_VORBIS_HEADER_ONLY +#include "stb_vorbis.c" /* Enables Vorbis decoding. */ + +#ifdef _WIN32 +#ifndef NOMINMAX + #define NOMINMAX +#endif +#endif + +#define MA_NO_DEVICE_IO +#define MA_NO_THREADING +#define MA_NO_ENCODING +#define MA_NO_GENERATION +#define MA_NO_RESOURCE_MANAGER +#define MA_NO_NODE_GRAPH +#define MINIAUDIO_IMPLEMENTATION +#include "miniaudio.h" + +#ifdef _WIN32 +#include +#include +#endif + +#include +#include + +#ifdef WHISPER_COMMON_FFMPEG +// as implemented in ffmpeg-trancode.cpp only embedded in common lib if whisper built with ffmpeg support +extern bool ffmpeg_decode_audio(const std::string & ifname, std::vector & wav_data, int out_sample_rate = WHISPER_SAMPLE_RATE); +#endif + +// extract f32 PCM frames from an initialized decoder, downmix to mono and keep the stereo split +static bool read_audio_from_decoder(ma_decoder & decoder, std::vector & pcmf32, std::vector> & pcmf32s, bool stereo) { + ma_result result; + ma_uint64 frame_count; + ma_uint64 frames_read; + + if ((result = ma_decoder_get_length_in_pcm_frames(&decoder, &frame_count)) != MA_SUCCESS) { + fprintf(stderr, "error: failed to retrieve the length of the audio data (%s)\n", ma_result_description(result)); + return false; + } + + pcmf32.resize(stereo ? frame_count*2 : frame_count); + + if ((result = ma_decoder_read_pcm_frames(&decoder, pcmf32.data(), frame_count, &frames_read)) != MA_SUCCESS) { + fprintf(stderr, "error: failed to read the frames of the audio data (%s)\n", ma_result_description(result)); + return false; + } + + if (stereo) { + std::vector stereo_data = pcmf32; + pcmf32.resize(frame_count); + for (uint64_t i = 0; i < frame_count; i++) { + pcmf32[i] = (stereo_data[2*i] + stereo_data[2*i + 1]); + } + pcmf32s.resize(2); + pcmf32s[0].resize(frame_count); + pcmf32s[1].resize(frame_count); + for (uint64_t i = 0; i < frame_count; i++) { + pcmf32s[0][i] = stereo_data[2*i]; + pcmf32s[1][i] = stereo_data[2*i + 1]; + } + } + + return true; +} + +bool read_audio_data(const std::string & fname, std::vector & pcmf32, std::vector> & pcmf32s, bool stereo) { + std::vector audio_data; // used for pipe input from stdin or ffmpeg decoding output + + ma_result result; + ma_decoder_config decoder_config; + + struct decoder_guard { + ma_decoder decoder; + bool initialized = false; + ma_decoder * operator&() { return &decoder; } + ~decoder_guard() { + if (initialized) { + ma_decoder_uninit(&decoder); + } + } + }; + decoder_guard decoder{}; + + decoder_config = ma_decoder_config_init(ma_format_f32, stereo ? 2 : 1, WHISPER_SAMPLE_RATE); + + if (fname == "-") { +#ifdef _WIN32 + _setmode(_fileno(stdin), _O_BINARY); +#endif + + uint8_t buf[1024]; + while (true) + { + const size_t n = fread(buf, 1, sizeof(buf), stdin); + if (n == 0) { + break; + } + audio_data.insert(audio_data.end(), buf, buf + n); + } + + result = ma_decoder_init_memory(audio_data.data(), audio_data.size(), &decoder_config, &decoder); + if (result != MA_SUCCESS) { + fprintf(stderr, "%s: failed to open audio data from stdin (%s)\n", __func__, ma_result_description(result)); + return false; + } + decoder.initialized = true; + + fprintf(stderr, "%s: read %zu bytes from stdin\n", __func__, audio_data.size()); + } else { + fprintf(stderr, "%s: reading audio data from '%s' ...\n", __func__, fname.c_str()); + + // first try miniaudio. if it fails (or skipped) - try ffmpeg + { + const char * skip = getenv("WHISPER_COMMON_MINIAUDIO_SKIP"); + if (!skip || strlen(skip) == 0 || strcmp(skip, "0") == 0) { + fprintf(stderr, "%s: trying to decode with miniaudio\n", __func__); + + result = ma_decoder_init_file(fname.c_str(), &decoder_config, &decoder); + if (result == MA_SUCCESS) { + decoder.initialized = true; + } + } else { + fprintf(stderr, "%s: skipping miniaudio\n", __func__); + } + } + +#if defined(WHISPER_COMMON_FFMPEG) + if (!decoder.initialized) { + fprintf(stderr, "%s: trying to decode with ffmpeg\n", __func__); + + if (ffmpeg_decode_audio(fname, audio_data) != 0) { + fprintf(stderr, "%s: failed to ffmpeg decode\n", __func__); + return false; + } + result = ma_decoder_init_memory(audio_data.data(), audio_data.size(), &decoder_config, &decoder); + if (result != MA_SUCCESS) { + fprintf(stderr, "%s: failed to read audio data as wav (%s)\n", __func__, ma_result_description(result)); + return false; + } + decoder.initialized = true; + } +#endif + + if (!decoder.initialized) { + fprintf(stderr, "%s: failed to read audio data\n", __func__); + return false; + } + } + + return read_audio_from_decoder(decoder.decoder, pcmf32, pcmf32s, stereo); +} + +// decode audio bytes already held in memory +bool read_audio_data(const char * buffer, size_t buffer_size, std::vector & pcmf32, std::vector> & pcmf32s, bool stereo) { + ma_decoder_config decoder_config = ma_decoder_config_init(ma_format_f32, stereo ? 2 : 1, WHISPER_SAMPLE_RATE); + ma_decoder decoder; + + if (ma_decoder_init_memory(buffer, buffer_size, &decoder_config, &decoder) != MA_SUCCESS) { + fprintf(stderr, "error: failed to decode audio data from memory buffer\n"); + return false; + } + + bool ok = read_audio_from_decoder(decoder, pcmf32, pcmf32s, stereo); + ma_decoder_uninit(&decoder); + return ok; +} + +// 500 -> 00:05.000 +// 6000 -> 01:00.000 +std::string to_timestamp(int64_t t, bool comma) { + int64_t msec = t * 10; + int64_t hr = msec / (1000 * 60 * 60); + msec = msec - hr * (1000 * 60 * 60); + int64_t min = msec / (1000 * 60); + msec = msec - min * (1000 * 60); + int64_t sec = msec / 1000; + msec = msec - sec * 1000; + + char buf[32]; + snprintf(buf, sizeof(buf), "%02d:%02d:%02d%s%03d", (int) hr, (int) min, (int) sec, comma ? "," : ".", (int) msec); + + return std::string(buf); +} + +int timestamp_to_sample(int64_t t, int n_samples, int whisper_sample_rate) { + return std::max(0, std::min((int) n_samples - 1, (int) ((t*whisper_sample_rate)/100))); +} + +int utf8_trailing_bytes_needed(const std::string & s) { + const int n = (int) s.size(); + int i = n - 1; + while (i >= 0 && ((unsigned char) s[i] & 0xC0) == 0x80) { + --i; + } + if (i < 0) { + return 0; + } + + const unsigned char c = (unsigned char) s[i]; + int expected; + if ((c & 0x80) == 0x00) { + expected = 1; + } else if ((c & 0xE0) == 0xC0) { + expected = 2; + } else if ((c & 0xF0) == 0xE0) { + expected = 3; + } else if ((c & 0xF8) == 0xF0) { + expected = 4; + } else { + return 0; + } + + const int have = n - i; + return have >= expected ? 0 : (expected - have); +} + +bool speak_with_file(const std::string & command, const std::string & text, const std::string & path, int voice_id) { + std::ofstream speak_file(path.c_str()); + if (speak_file.fail()) { + fprintf(stderr, "%s: failed to open speak_file\n", __func__); + return false; + } else { + speak_file.write(text.c_str(), text.size()); + speak_file.close(); + int ret = system((command + " " + std::to_string(voice_id) + " " + path).c_str()); + if (ret != 0) { + fprintf(stderr, "%s: failed to speak\n", __func__); + return false; + } + } + return true; +} + +#undef STB_VORBIS_HEADER_ONLY +#include "stb_vorbis.c" diff --git a/examples/common-whisper.h b/examples/common-whisper.h new file mode 100644 index 0000000..aec430d --- /dev/null +++ b/examples/common-whisper.h @@ -0,0 +1,35 @@ +#pragma once + +#include +#include +#include + +// Read WAV audio file and store the PCM data into pcmf32 +// fname can be a buffer of WAV data instead of a filename +// The sample rate of the audio must be equal to COMMON_SAMPLE_RATE +// If stereo flag is set and the audio has 2 channels, the pcmf32s will contain 2 channel PCM +bool read_audio_data( + const std::string & fname, + std::vector & pcmf32, + std::vector> & pcmf32s, + bool stereo); + +// decode audio bytes already held in memory (uploaded file, network buffer) +bool read_audio_data( + const char * buffer, + size_t buffer_size, + std::vector & pcmf32, + std::vector> & pcmf32s, + bool stereo); + +// convert timestamp to string, 6000 -> 01:00.000 +std::string to_timestamp(int64_t t, bool comma = false); + +// given a timestamp get the sample +int timestamp_to_sample(int64_t t, int n_samples, int whisper_sample_rate); + +// Returns the number of trailing bytes still needed for s to end on a complete UTF-8 codepoint. +int utf8_trailing_bytes_needed(const std::string & s); + +// write text to file, and call system("command voice_id file") +bool speak_with_file(const std::string & command, const std::string & text, const std::string & path, int voice_id); diff --git a/examples/common.cpp b/examples/common.cpp new file mode 100644 index 0000000..8eb633e --- /dev/null +++ b/examples/common.cpp @@ -0,0 +1,675 @@ +#define _USE_MATH_DEFINES // for M_PI + +#include "common.h" + +#include +#include +#include +#include +#include +#include +#include + +// Function to check if the next argument exists +static std::string get_next_arg(int& i, int argc, char** argv, const std::string& flag, gpt_params& params) { + if (i + 1 < argc && argv[i + 1][0] != '-') { + return argv[++i]; + } else { + fprintf(stderr, "error: %s requires one argument.\n", flag.c_str()); + gpt_print_usage(argc, argv, params); + exit(0); + } +} + +bool gpt_params_parse(int argc, char ** argv, gpt_params & params) { + for (int i = 1; i < argc; i++) { + std::string arg = argv[i]; + + if (arg == "-s" || arg == "--seed") { + params.seed = std::stoi(get_next_arg(i, argc, argv, arg, params)); + } else if (arg == "-t" || arg == "--threads") { + params.n_threads = std::stoi(get_next_arg(i, argc, argv, arg, params)); + } else if (arg == "-p" || arg == "--prompt") { + params.prompt = get_next_arg(i, argc, argv, arg, params); + } else if (arg == "-n" || arg == "--n_predict") { + params.n_predict = std::stoi(get_next_arg(i, argc, argv, arg, params)); + } else if (arg == "-np" || arg == "--n_parallel") { + params.n_parallel = std::stoi(get_next_arg(i, argc, argv, arg, params)); + } else if (arg == "--top_k") { + params.top_k = std::stoi(get_next_arg(i, argc, argv, arg, params)); + } else if (arg == "--top_p") { + params.top_p = std::stof(get_next_arg(i, argc, argv, arg, params)); + } else if (arg == "--temp") { + params.temp = std::stof(get_next_arg(i, argc, argv, arg, params)); + } else if (arg == "--repeat-last-n") { + params.repeat_last_n = std::stoi(get_next_arg(i, argc, argv, arg, params)); + } else if (arg == "--repeat-penalty") { + params.repeat_penalty = std::stof(get_next_arg(i, argc, argv, arg, params)); + } else if (arg == "-b" || arg == "--batch_size") { + params.n_batch= std::stoi(get_next_arg(i, argc, argv, arg, params)); + } else if (arg == "-c" || arg == "--context") { + params.n_ctx= std::stoi(get_next_arg(i, argc, argv, arg, params)); + } else if (arg == "-ngl" || arg == "--gpu-layers" || arg == "--n-gpu-layers") { + params.n_gpu_layers = std::stoi(get_next_arg(i, argc, argv, arg, params)); + } else if (arg == "--ignore-eos") { + params.ignore_eos = true; + } else if (arg == "-m" || arg == "--model") { + params.model = get_next_arg(i, argc, argv, arg, params); + } else if (arg == "-i" || arg == "--interactive") { + params.interactive = true; + } else if (arg == "-ip" || arg == "--interactive-port") { + params.interactive = true; + params.interactive_port = std::stoi(get_next_arg(i, argc, argv, arg, params)); + } else if (arg == "-h" || arg == "--help") { + gpt_print_usage(argc, argv, params); + exit(0); + } else if (arg == "-f" || arg == "--file") { + get_next_arg(i, argc, argv, arg, params); + std::ifstream file(argv[i]); + if (!file) { + fprintf(stderr, "error: failed to open file '%s'\n", argv[i]); + break; + } + std::copy(std::istreambuf_iterator(file), std::istreambuf_iterator(), back_inserter(params.prompt)); + if (params.prompt.back() == '\n') { + params.prompt.pop_back(); + } + } else if (arg == "-tt" || arg == "--token_test") { + params.token_test = get_next_arg(i, argc, argv, arg, params); + } + else { + fprintf(stderr, "error: unknown argument: %s\n", arg.c_str()); + gpt_print_usage(argc, argv, params); + exit(0); + } + } + + return true; +} + +void gpt_print_usage(int /*argc*/, char ** argv, const gpt_params & params) { + fprintf(stderr, "usage: %s [options]\n", argv[0]); + fprintf(stderr, "\n"); + fprintf(stderr, "options:\n"); + fprintf(stderr, " -h, --help show this help message and exit\n"); + fprintf(stderr, " -s SEED, --seed SEED RNG seed (default: -1)\n"); + fprintf(stderr, " -t N, --threads N number of threads to use during computation (default: %d)\n", params.n_threads); + fprintf(stderr, " -p PROMPT, --prompt PROMPT\n"); + fprintf(stderr, " prompt to start generation with (default: random)\n"); + fprintf(stderr, " -f FNAME, --file FNAME\n"); + fprintf(stderr, " load prompt from a file\n"); + fprintf(stderr, " -tt TOKEN_TEST, --token_test TOKEN_TEST\n"); + fprintf(stderr, " test tokenization\n"); + fprintf(stderr, " -n N, --n_predict N number of tokens to predict (default: %d)\n", params.n_predict); + fprintf(stderr, " --top_k N top-k sampling (default: %d)\n", params.top_k); + fprintf(stderr, " --top_p N top-p sampling (default: %.1f)\n", params.top_p); + fprintf(stderr, " --temp N temperature (default: %.1f)\n", params.temp); + fprintf(stderr, " --repeat-last-n N last n tokens to consider for penalize (default: %d, 0 = disabled)\n", params.repeat_last_n); + fprintf(stderr, " --repeat-penalty N penalize repeat sequence of tokens (default: %.2f, 1.0 = disabled)\n", (double)params.repeat_penalty); + fprintf(stderr, " -b N, --batch_size N batch size for prompt processing (default: %d)\n", params.n_batch); + fprintf(stderr, " -c N, --context N context / KV cache size (default: %d)\n", params.n_ctx); + fprintf(stderr, " --ignore-eos ignore EOS token during generation\n"); + fprintf(stderr, " -ngl N, --gpu-layers N number of layers to offload to GPU on supported models (default: %d)\n", params.n_gpu_layers); + fprintf(stderr, " -m FNAME, --model FNAME\n"); + fprintf(stderr, " model path (default: %s)\n", params.model.c_str()); + fprintf(stderr, "\n"); +} + +std::string gpt_random_prompt(std::mt19937 & rng) { + const int r = rng() % 10; + switch (r) { + case 0: return "So"; + case 1: return "Once upon a time"; + case 2: return "When"; + case 3: return "The"; + case 4: return "After"; + case 5: return "If"; + case 6: return "import"; + case 7: return "He"; + case 8: return "She"; + case 9: return "They"; + } + + return "The"; +} + +std::string trim(const std::string & s) { + std::regex e("^\\s+|\\s+$"); + return std::regex_replace(s, e, ""); +} + +std::string replace(const std::string & s, const std::string & from, const std::string & to) { + std::string result = s; + size_t pos = 0; + while ((pos = result.find(from, pos)) != std::string::npos) { + result.replace(pos, from.length(), to); + pos += to.length(); + } + return result; +} + +void gpt_vocab::add_special_token(const std::string & token) { + special_tokens.push_back(token); +} + +std::map json_parse(const std::string & fname) { + std::map result; + + // read file into string + std::string json; + { + std::ifstream ifs(fname); + if (!ifs) { + fprintf(stderr, "Failed to open %s\n", fname.c_str()); + exit(1); + } + + json = std::string((std::istreambuf_iterator(ifs)), + (std::istreambuf_iterator())); + } + + if (json[0] != '{') { + return result; + } + + // parse json + { + bool has_key = false; + bool in_token = false; + + std::string str_key = ""; + std::string str_val = ""; + + int n = json.size(); + for (int i = 1; i < n; ++i) { + if (!in_token) { + if (json[i] == ' ') continue; + if (json[i] == '"') { + in_token = true; + continue; + } + } else { + if (json[i] == '\\' && i+1 < n) { + if (has_key == false) { + str_key += json[i]; + } else { + str_val += json[i]; + } + ++i; + } else if (json[i] == '"') { + if (has_key == false) { + has_key = true; + ++i; + while (json[i] == ' ') ++i; + ++i; // : + while (json[i] == ' ') ++i; + if (json[i] != '\"') { + while (json[i] != ',' && json[i] != '}') { + str_val += json[i++]; + } + has_key = false; + } else { + in_token = true; + continue; + } + } else { + has_key = false; + } + + str_key = ::replace(str_key, "\\u0120", " " ); // \u0120 -> space + str_key = ::replace(str_key, "\\u010a", "\n"); // \u010a -> new line + str_key = ::replace(str_key, "\\\"", "\""); // \\\" -> " + + try { + result[str_key] = std::stoi(str_val); + } catch (...) { + //fprintf(stderr, "%s: ignoring key '%s' with value '%s'\n", fname.c_str(), str_key.c_str(), str_val.c_str()); + + } + str_key = ""; + str_val = ""; + in_token = false; + continue; + } + if (has_key == false) { + str_key += json[i]; + } else { + str_val += json[i]; + } + } + } + } + + return result; +} + +void gpt_split_words(std::string str, std::vector& words) { + const std::string pattern = R"('s|'t|'re|'ve|'m|'ll|'d| ?[[:alpha:]]+| ?[[:digit:]]+| ?[^\s[:alpha:][:digit:]]+|\s+(?!\S)|\s+)"; + const std::regex re(pattern); + std::smatch m; + + while (std::regex_search(str, m, re)) { + for (auto x : m) { + words.push_back(x); + } + str = m.suffix(); + } +} + +std::vector gpt_tokenize(const gpt_vocab & vocab, const std::string & text) { + std::vector words; + + // first split the text into words + { + std::string str = text; + + // Generate the subpattern from the special_tokens vector if it's not empty + if (!vocab.special_tokens.empty()) { + const std::regex escape(R"([\[\\\^\$\.\|\?\*\+\(\)\{\}])"); + std::string special_tokens_subpattern; + for (const auto & token : vocab.special_tokens) { + if (!special_tokens_subpattern.empty()) { + special_tokens_subpattern += "|"; + } + special_tokens_subpattern += std::regex_replace(token, escape, R"(\$&)"); + } + + std::regex re(special_tokens_subpattern); + std::smatch m; + // Split the text by special tokens. + while (std::regex_search(str, m, re)) { + // Split the substrings in-between special tokens into words. + gpt_split_words(m.prefix(), words); + // Add matched special tokens as words. + for (auto x : m) { + words.push_back(x); + } + str = m.suffix(); + } + // Remaining text without special tokens will be handled below. + } + + gpt_split_words(str, words); + } + + // find the longest token that forms each word in words: + std::vector tokens; + for (const auto & word : words) { + for (int i = 0; i < (int) word.size(); ){ + for (int j = word.size() - 1; j >= i; j--){ + auto cand = word.substr(i, j-i+1); + auto it = vocab.token_to_id.find(cand); + if (it != vocab.token_to_id.end()){ // word.substr(i, j-i+1) in vocab + tokens.push_back(it->second); + i = j + 1; + break; + } + else if (j == i){ // word.substr(i, 1) has no matching + fprintf(stderr, "%s: unknown token '%s'\n", __func__, word.substr(i, 1).data()); + i++; + } + } + } + } + + return tokens; +} + +static std::vector parse_tokens_from_string(const std::string& input, char delimiter) { + std::vector output; + std::stringstream ss(input); + std::string token; + + while (std::getline(ss, token, delimiter)) { + output.push_back(std::stoi(token)); + } + + return output; +} + +static std::map> extract_tests_from_file(const std::string & fpath_test){ + if (fpath_test.empty()){ + fprintf(stderr, "%s : No test file found.\n", __func__); + return std::map>(); + } + + std::map> tests; + + auto fin = std::ifstream(fpath_test, std::ios_base::in); + const char * delimeter = " => "; + const char del_tok = ','; + std::string line; + while (std::getline(fin, line)) { + size_t delimiterPos = line.find(delimeter); + if (delimiterPos != std::string::npos) { + std::string text = line.substr(0, delimiterPos); + std::string s_tokens = line.substr(delimiterPos + std::strlen(delimeter)); + tests[text] = parse_tokens_from_string(s_tokens, del_tok); + } + } + return tests; +} + +void test_gpt_tokenizer(gpt_vocab & vocab, const std::string & fpath_test){ + std::map> tests = extract_tests_from_file(fpath_test); + + size_t n_fails = 0; + + for (const auto & test : tests) { + std::vector tokens = gpt_tokenize(vocab, test.first); + + if (tokens != test.second){ + n_fails++; + + // print out failure cases + fprintf(stderr, "%s : failed test: '%s'\n", __func__, test.first.c_str()); + fprintf(stderr, "%s : tokens in hf: ", __func__); + for (const auto & t : test.second) { + fprintf(stderr, "%s(%d), ", vocab.id_to_token[t].c_str(), t); + } + fprintf(stderr, "\n"); + fprintf(stderr, "%s : tokens in ggml: ", __func__); + for (const auto & t : tokens) { + fprintf(stderr, "%s(%d), ", vocab.id_to_token[t].c_str(), t); + } + fprintf(stderr, "\n"); + } + } + + fprintf(stderr, "%s : %zu tests failed out of %zu tests.\n", __func__, n_fails, tests.size()); +} + +bool gpt_vocab_init(const std::string & fname, gpt_vocab & vocab) { + printf("%s: loading vocab from '%s'\n", __func__, fname.c_str()); + + vocab.token_to_id = ::json_parse(fname); + + for (const auto & kv : vocab.token_to_id) { + vocab.id_to_token[kv.second] = kv.first; + } + + printf("%s: vocab size = %d\n", __func__, (int) vocab.token_to_id.size()); + + // print the vocabulary + //for (auto kv : vocab.token_to_id) { + // printf("'%s' -> %d\n", kv.first.data(), kv.second); + //} + + return true; +} + +gpt_vocab::id gpt_sample_top_k_top_p( + const gpt_vocab & vocab, + const float * logits, + int top_k, + double top_p, + double temp, + std::mt19937 & rng) { + int n_logits = vocab.id_to_token.size(); + + std::vector> logits_id; + logits_id.reserve(n_logits); + + { + const double scale = 1.0/temp; + for (int i = 0; i < n_logits; ++i) { + logits_id.push_back(std::make_pair(logits[i]*scale, i)); + } + } + + // find the top K tokens + std::partial_sort( + logits_id.begin(), + logits_id.begin() + top_k, logits_id.end(), + [](const std::pair & a, const std::pair & b) { + return a.first > b.first; + }); + + logits_id.resize(top_k); + + double maxl = -INFINITY; + for (const auto & kv : logits_id) { + maxl = std::max(maxl, kv.first); + } + + // compute probs for the top K tokens + std::vector probs; + probs.reserve(logits_id.size()); + + double sum = 0.0; + for (const auto & kv : logits_id) { + double p = exp(kv.first - maxl); + probs.push_back(p); + sum += p; + } + + // normalize the probs + for (auto & p : probs) { + p /= sum; + } + + if (top_p < 1.0f) { + double cumsum = 0.0f; + for (int i = 0; i < top_k; i++) { + cumsum += probs[i]; + if (cumsum >= top_p) { + top_k = i + 1; + probs.resize(top_k); + logits_id.resize(top_k); + break; + } + } + + cumsum = 1.0/cumsum; + for (int i = 0; i < (int) probs.size(); i++) { + probs[i] *= cumsum; + } + } + + //printf("\n"); + //for (int i = 0; i < (int) probs.size(); i++) { + // printf("%d: '%s' %f\n", i, vocab.id_to_token.at(logits_id[i].second).c_str(), probs[i]); + //} + //exit(0); + + std::discrete_distribution<> dist(probs.begin(), probs.end()); + int idx = dist(rng); + + return logits_id[idx].second; +} + +gpt_vocab::id gpt_sample_top_k_top_p_repeat( + const gpt_vocab & vocab, + const float * logits, + const int32_t * last_n_tokens_data, + size_t last_n_tokens_data_size, + int top_k, + double top_p, + double temp, + int repeat_last_n, + float repeat_penalty, + std::mt19937 & rng) { + + int n_logits = vocab.id_to_token.size(); + + const auto * plogits = logits; + + const auto last_n_tokens = std::vector(last_n_tokens_data, last_n_tokens_data + last_n_tokens_data_size); + + if (temp <= 0) { + // select the token with the highest logit directly + float max_logit = plogits[0]; + gpt_vocab::id max_id = 0; + + for (int i = 1; i < n_logits; ++i) { + if (plogits[i] > max_logit) { + max_logit = plogits[i]; + max_id = i; + } + } + return max_id; + } + + + std::vector> logits_id; + logits_id.reserve(n_logits); + + { + const float scale = 1.0f/temp; + for (int i = 0; i < n_logits; ++i) { + // repetition penalty from ctrl paper (https://arxiv.org/abs/1909.05858) + // credit https://github.com/facebookresearch/llama/compare/main...shawwn:llama:main + if (repeat_last_n > 0 && std::find(last_n_tokens.end()-repeat_last_n, last_n_tokens.end(), i) != last_n_tokens.end()) { + // if score < 0 then repetition penalty has to multiplied to reduce the previous token probability + if (plogits[i] < 0.0f) { + logits_id.push_back(std::make_pair(plogits[i]*scale*repeat_penalty, i)); + } else { + logits_id.push_back(std::make_pair(plogits[i]*scale/repeat_penalty, i)); + } + } else { + logits_id.push_back(std::make_pair(plogits[i]*scale, i)); + } + } + } + + // find the top K tokens + std::partial_sort( + logits_id.begin(), + logits_id.begin() + top_k, logits_id.end(), + [](const std::pair & a, const std::pair & b) { + return a.first > b.first; + }); + + logits_id.resize(top_k); + + double maxl = -INFINITY; + for (const auto & kv : logits_id) { + maxl = std::max(maxl, kv.first); + } + + // compute probs for the top K tokens + std::vector probs; + probs.reserve(logits_id.size()); + + double sum = 0.0; + for (const auto & kv : logits_id) { + double p = exp(kv.first - maxl); + probs.push_back(p); + sum += p; + } + + // normalize the probs + for (auto & p : probs) { + p /= sum; + } + + if (top_p < 1.0f) { + double cumsum = 0.0f; + for (int i = 0; i < top_k; i++) { + cumsum += probs[i]; + if (cumsum >= top_p) { + top_k = i + 1; + probs.resize(top_k); + logits_id.resize(top_k); + break; + } + } + + cumsum = 1.0/cumsum; + for (int i = 0; i < (int) probs.size(); i++) { + probs[i] *= cumsum; + } + } + +// printf("\n"); +// for (int i = 0; i < (int) probs.size(); i++) { +// for (int i = 0; i < 10; i++) { +// printf("%d: '%s' %f\n", i, vocab.id_to_token.at(logits_id[i].second).c_str(), probs[i]); +// } + + std::discrete_distribution<> dist(probs.begin(), probs.end()); + int idx = dist(rng); + + return logits_id[idx].second; + +} + +void high_pass_filter(std::vector & data, float cutoff, float sample_rate) { + const float rc = 1.0f / (2.0f * M_PI * cutoff); + const float dt = 1.0f / sample_rate; + const float alpha = dt / (rc + dt); + + float y = data[0]; + + for (size_t i = 1; i < data.size(); i++) { + y = alpha * (y + data[i] - data[i - 1]); + data[i] = y; + } +} + +bool vad_simple(std::vector & pcmf32, int sample_rate, int last_ms, float vad_thold, float freq_thold, bool verbose) { + const int n_samples = pcmf32.size(); + const int n_samples_last = (sample_rate * last_ms) / 1000; + + if (n_samples_last >= n_samples) { + // not enough samples - assume no speech + return false; + } + + if (freq_thold > 0.0f) { + high_pass_filter(pcmf32, freq_thold, sample_rate); + } + + float energy_all = 0.0f; + float energy_last = 0.0f; + + for (int i = 0; i < n_samples; i++) { + energy_all += fabsf(pcmf32[i]); + + if (i >= n_samples - n_samples_last) { + energy_last += fabsf(pcmf32[i]); + } + } + + energy_all /= n_samples; + energy_last /= n_samples_last; + + if (verbose) { + fprintf(stderr, "%s: energy_all: %f, energy_last: %f, vad_thold: %f, freq_thold: %f\n", __func__, energy_all, energy_last, vad_thold, freq_thold); + } + + if (energy_last > vad_thold*energy_all) { + return false; + } + + return true; +} + +float similarity(const std::string & s0, const std::string & s1) { + const size_t len0 = s0.size() + 1; + const size_t len1 = s1.size() + 1; + + std::vector col(len1, 0); + std::vector prevCol(len1, 0); + + for (size_t i = 0; i < len1; i++) { + prevCol[i] = i; + } + + for (size_t i = 0; i < len0; i++) { + col[0] = i; + for (size_t j = 1; j < len1; j++) { + col[j] = std::min(std::min(1 + col[j - 1], 1 + prevCol[j]), prevCol[j - 1] + (i > 0 && s0[i - 1] == s1[j - 1] ? 0 : 1)); + } + col.swap(prevCol); + } + + const float dist = prevCol[len1 - 1]; + + return 1.0f - (dist / std::max(s0.size(), s1.size())); +} + +bool is_file_exist(const char * filename) { + std::ifstream infile(filename); + return infile.good(); +} diff --git a/examples/common.h b/examples/common.h new file mode 100644 index 0000000..8f99df7 --- /dev/null +++ b/examples/common.h @@ -0,0 +1,322 @@ +// Various helper functions and utilities + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +// +// GPT CLI argument parsing +// + +struct gpt_params { + int32_t seed = -1; // RNG seed + int32_t n_threads = std::min(4, (int32_t) std::thread::hardware_concurrency()); + int32_t n_predict = 200; // new tokens to predict + int32_t n_parallel = 1; // number of parallel streams + int32_t n_batch = 32; // batch size for prompt processing + int32_t n_ctx = 2048; // context size (this is the KV cache max size) + int32_t n_gpu_layers = 0; // number of layers to offlload to the GPU + + bool ignore_eos = false; // ignore EOS token when generating text + + // sampling parameters + int32_t top_k = 40; + float top_p = 0.9f; + float temp = 0.9f; + int32_t repeat_last_n = 64; + float repeat_penalty = 1.00f; + + std::string model = "models/gpt-2-117M/ggml-model.bin"; // model path + std::string prompt = ""; + std::string token_test = ""; + + bool interactive = false; + int32_t interactive_port = -1; +}; + +bool gpt_params_parse(int argc, char ** argv, gpt_params & params); + +void gpt_print_usage(int argc, char ** argv, const gpt_params & params); + +std::string gpt_random_prompt(std::mt19937 & rng); + +// +// Vocab utils +// + +std::string trim(const std::string & s); + +std::string replace( + const std::string & s, + const std::string & from, + const std::string & to); + +struct gpt_vocab { + using id = int32_t; + using token = std::string; + + std::map token_to_id; + std::map id_to_token; + std::vector special_tokens; + + void add_special_token(const std::string & token); +}; + +// poor-man's JSON parsing +std::map json_parse(const std::string & fname); + +std::string convert_to_utf8(const std::wstring & input); + +std::wstring convert_to_wstring(const std::string & input); + +void gpt_split_words(std::string str, std::vector& words); + +// split text into tokens +// +// ref: https://github.com/openai/gpt-2/blob/a74da5d99abaaba920de8131d64da2862a8f213b/src/encoder.py#L53 +// +// Regex (Python): +// r"""'s|'t|'re|'ve|'m|'ll|'d| ?\p{L}+| ?\p{N}+| ?[^\s\p{L}\p{N}]+|\s+(?!\S)|\s+""" +// +// Regex (C++): +// R"('s|'t|'re|'ve|'m|'ll|'d| ?[[:alpha:]]+| ?[[:digit:]]+| ?[^\s[:alpha:][:digit:]]+|\s+(?!\S)|\s+)" +// +std::vector gpt_tokenize(const gpt_vocab & vocab, const std::string & text); + +// test outputs of gpt_tokenize +// +// - compare with tokens generated by the huggingface tokenizer +// - test cases are chosen based on the model's main language (under 'prompt' directory) +// - if all sentences are tokenized identically, print 'All tests passed.' +// - otherwise, print sentence, huggingface tokens, ggml tokens +// +void test_gpt_tokenizer(gpt_vocab & vocab, const std::string & fpath_test); + +// load the tokens from encoder.json +bool gpt_vocab_init(const std::string & fname, gpt_vocab & vocab); + +// sample next token given probabilities for each embedding +// +// - consider only the top K tokens +// - from them, consider only the top tokens with cumulative probability > P +// +// TODO: not sure if this implementation is correct +// TODO: temperature is not implemented +// +gpt_vocab::id gpt_sample_top_k_top_p( + const gpt_vocab & vocab, + const float * logits, + int top_k, + double top_p, + double temp, + std::mt19937 & rng); + +gpt_vocab::id gpt_sample_top_k_top_p_repeat( + const gpt_vocab & vocab, + const float * logits, + const int32_t * last_n_tokens_data, + size_t last_n_tokens_data_size, + int top_k, + double top_p, + double temp, + int repeat_last_n, + float repeat_penalty, + std::mt19937 & rng); + +// +// Audio utils +// + +// Write PCM data into WAV audio file +class wav_writer { +private: + std::ofstream file; + uint32_t dataSize = 0; + std::string wav_filename; + + bool write_header(const uint32_t sample_rate, + const uint16_t bits_per_sample, + const uint16_t channels) { + + file.write("RIFF", 4); + file.write("\0\0\0\0", 4); // Placeholder for file size + file.write("WAVE", 4); + file.write("fmt ", 4); + + const uint32_t sub_chunk_size = 16; + const uint16_t audio_format = 1; // PCM format + const uint32_t byte_rate = sample_rate * channels * bits_per_sample / 8; + const uint16_t block_align = channels * bits_per_sample / 8; + + file.write(reinterpret_cast(&sub_chunk_size), 4); + file.write(reinterpret_cast(&audio_format), 2); + file.write(reinterpret_cast(&channels), 2); + file.write(reinterpret_cast(&sample_rate), 4); + file.write(reinterpret_cast(&byte_rate), 4); + file.write(reinterpret_cast(&block_align), 2); + file.write(reinterpret_cast(&bits_per_sample), 2); + file.write("data", 4); + file.write("\0\0\0\0", 4); // Placeholder for data size + + return true; + } + + // It is assumed that PCM data is normalized to a range from -1 to 1 + bool write_audio(const float * data, size_t length) { + for (size_t i = 0; i < length; ++i) { + const int16_t intSample = int16_t(data[i] * 32767); + file.write(reinterpret_cast(&intSample), sizeof(int16_t)); + dataSize += sizeof(int16_t); + } + if (file.is_open()) { + file.seekp(4, std::ios::beg); + uint32_t fileSize = 36 + dataSize; + file.write(reinterpret_cast(&fileSize), 4); + file.seekp(40, std::ios::beg); + file.write(reinterpret_cast(&dataSize), 4); + file.seekp(0, std::ios::end); + } + return true; + } + + bool open_wav(const std::string & filename) { + if (filename != wav_filename) { + if (file.is_open()) { + file.close(); + } + } + if (!file.is_open()) { + file.open(filename, std::ios::binary); + wav_filename = filename; + dataSize = 0; + } + return file.is_open(); + } + +public: + bool open(const std::string & filename, + const uint32_t sample_rate, + const uint16_t bits_per_sample, + const uint16_t channels) { + + if (open_wav(filename)) { + write_header(sample_rate, bits_per_sample, channels); + } else { + return false; + } + + return true; + } + + bool close() { + file.close(); + return true; + } + + bool write(const float * data, size_t length) { + return write_audio(data, length); + } + + ~wav_writer() { + if (file.is_open()) { + file.close(); + } + } +}; + + +// Apply a high-pass frequency filter to PCM audio +// Suppresses frequencies below cutoff Hz +void high_pass_filter( + std::vector & data, + float cutoff, + float sample_rate); + +// Basic voice activity detection (VAD) using audio energy adaptive threshold +bool vad_simple( + std::vector & pcmf32, + int sample_rate, + int last_ms, + float vad_thold, + float freq_thold, + bool verbose); + +// compute similarity between two strings using Levenshtein distance +float similarity(const std::string & s0, const std::string & s1); + +// +// Terminal utils +// + +#define SQR(X) ((X) * (X)) +#define UNCUBE(x) x < 48 ? 0 : x < 115 ? 1 : (x - 35) / 40 + +/** + * Quantizes 24-bit RGB to xterm256 code range [16,256). + */ +static int rgb2xterm256(int r, int g, int b) { + unsigned char cube[] = {0, 0137, 0207, 0257, 0327, 0377}; + int av, ir, ig, ib, il, qr, qg, qb, ql; + av = r * .299 + g * .587 + b * .114 + .5; + ql = (il = av > 238 ? 23 : (av - 3) / 10) * 10 + 8; + qr = cube[(ir = UNCUBE(r))]; + qg = cube[(ig = UNCUBE(g))]; + qb = cube[(ib = UNCUBE(b))]; + if (SQR(qr - r) + SQR(qg - g) + SQR(qb - b) <= + SQR(ql - r) + SQR(ql - g) + SQR(ql - b)) + return ir * 36 + ig * 6 + ib + 020; + return il + 0350; +} + +static std::string set_xterm256_foreground(int r, int g, int b) { + int x = rgb2xterm256(r, g, b); + std::ostringstream oss; + oss << "\033[38;5;" << x << "m"; + return oss.str(); +} + +// Lowest is red, middle is yellow, highest is green. Color scheme from +// Paul Tol; it is colorblind friendly https://sronpersonalpages.nl/~pault +const std::vector k_colors = { + set_xterm256_foreground(220, 5, 12), + set_xterm256_foreground(232, 96, 28), + set_xterm256_foreground(241, 147, 45), + set_xterm256_foreground(246, 193, 65), + set_xterm256_foreground(247, 240, 86), + set_xterm256_foreground(144, 201, 135), + set_xterm256_foreground( 78, 178, 101), +}; + +// ANSI formatting codes +static std::string set_inverse() { + return "\033[7m"; +} + +static std::string set_underline() { + return "\033[4m"; +} + +static std::string set_dim() { + return "\033[2m"; +} + +// Style scheme for different confidence levels +const std::vector k_styles = { + set_inverse(), // Low confidence - inverse (highlighted) + set_underline(), // Medium confidence - underlined + set_dim(), // High confidence - dim +}; + +// +// Other utils +// + +// check if file exists using ifstream +bool is_file_exist(const char * filename); diff --git a/examples/deprecation-warning/CMakeLists.txt b/examples/deprecation-warning/CMakeLists.txt new file mode 100644 index 0000000..55cef03 --- /dev/null +++ b/examples/deprecation-warning/CMakeLists.txt @@ -0,0 +1,6 @@ +add_executable(main ./deprecation-warning.cpp) +add_executable(bench ./deprecation-warning.cpp) +if (WHISPER_SDL2) + add_executable(stream ./deprecation-warning.cpp) + add_executable(command ./deprecation-warning.cpp) +endif() diff --git a/examples/deprecation-warning/README.md b/examples/deprecation-warning/README.md new file mode 100644 index 0000000..e07e134 --- /dev/null +++ b/examples/deprecation-warning/README.md @@ -0,0 +1,17 @@ +# Migration notice for binary filenames + +> [!IMPORTANT] +[2024 Dec 20] Binaries have been renamed w/ a `whisper-` prefix. `main` is now `whisper-cli`, `server` is `whisper-server`, etc (https://github.com/ggerganov/whisper.cpp/pull/2648) + +This migration was important, but it is a breaking change that may not always be immediately obvious to users. + +Please update all scripts and workflows to use the new binary names. + +| Old Filename | New Filename | +| ---- | ---- | +| main | whisper-cli | +| bench | whisper-bench | +| stream | whisper-stream | +| command | whisper-command | +| server | whisper-server | +| talk-llama | whisper-talk-llama | diff --git a/examples/deprecation-warning/deprecation-warning.cpp b/examples/deprecation-warning/deprecation-warning.cpp new file mode 100644 index 0000000..9cac82f --- /dev/null +++ b/examples/deprecation-warning/deprecation-warning.cpp @@ -0,0 +1,38 @@ +// Warns users that this filename was deprecated, and provides a link for more information. + +#include +#include + +// Main +int main(int argc, char** argv) { + std::string filename = "main"; + if (argc >= 1) { + filename = argv[0]; + } + + // Get only the program name from the full path + size_t pos = filename.find_last_of("/\\"); + if (pos != std::string::npos) { + filename = filename.substr(pos+1); + } + + // Append "whisper-" to the beginning of filename to get the replacemnt filename + std::string replacement_filename = "whisper-" + filename; + + // The exception is if the filename is "main", then our replacement filename is "whisper-cli" + if (filename == "main") { + replacement_filename = "whisper-cli"; + } + + if (filename == "main.exe") { + replacement_filename = "whisper-cli.exe"; + } + + fprintf(stdout, "\n"); + fprintf(stdout, "WARNING: The binary '%s' is deprecated.\n", filename.c_str()); + fprintf(stdout, " Please use '%s' instead.\n", replacement_filename.c_str()); + fprintf(stdout, " See https://github.com/ggerganov/whisper.cpp/tree/master/examples/deprecation-warning/README.md for more information.\n"); + fprintf(stdout, "\n"); + + return EXIT_FAILURE; +} diff --git a/examples/ffmpeg-transcode.cpp b/examples/ffmpeg-transcode.cpp new file mode 100644 index 0000000..7657af6 --- /dev/null +++ b/examples/ffmpeg-transcode.cpp @@ -0,0 +1,238 @@ +#ifdef WHISPER_COMMON_FFMPEG + +#include +#include +#include +#include + +extern "C" { +#include +#include +#include +} + +// Write a minimal WAV header into the output buffer. +// Returns the number of bytes written (44 for a standard PCM WAV header). +static size_t wav_header_write(uint8_t * buf, int num_channels, int sample_rate, int bits_per_sample, uint32_t data_size) { + // RIFF header + memcpy(buf, "RIFF", 4); + uint32_t chunk_size = 36 + data_size; + memcpy(buf + 4, &chunk_size, 4); + memcpy(buf + 8, "WAVE", 4); + + // fmt subchunk + memcpy(buf + 12, "fmt ", 4); + uint32_t subchunk1_size = 16; + memcpy(buf + 16, &subchunk1_size, 4); + uint16_t audio_format = 1; // PCM + memcpy(buf + 20, &audio_format, 2); + memcpy(buf + 22, &num_channels, 2); + memcpy(buf + 24, &sample_rate, 4); + + int bytes_per_sample = (bits_per_sample / 8) * num_channels; + int byte_rate = sample_rate * bytes_per_sample; + memcpy(buf + 28, &byte_rate, 4); + memcpy(buf + 32, &bytes_per_sample, 2); + memcpy(buf + 34, &bits_per_sample, 2); + + // data subchunk + memcpy(buf + 36, "data", 4); + memcpy(buf + 40, &data_size, 4); + + return 44; +} + +bool ffmpeg_decode_audio(const std::string & ifname, std::vector & wav_data, int out_sample_rate) { + { + const char * verbose = getenv("WHISPER_COMMON_FFMPEG_VERBOSE"); + if (verbose && strcmp(verbose, "2") == 0) { + av_log_set_level(AV_LOG_DEBUG); + } else if (verbose && strcmp(verbose, "1") == 0) { + av_log_set_level(AV_LOG_VERBOSE); + } else { + av_log_set_level(AV_LOG_WARNING); + } + } + + AVFormatContext * fmt_ctx = nullptr; + if (avformat_open_input(&fmt_ctx, ifname.c_str(), nullptr, nullptr) != 0) { + fprintf(stderr, "error: failed to open input file '%s'\n", ifname.c_str()); + return true; + } + + if (avformat_find_stream_info(fmt_ctx, nullptr) < 0) { + fprintf(stderr, "error: failed to find stream information\n"); + avformat_close_input(&fmt_ctx); + return true; + } + + // Find the first audio stream + int audio_stream_idx = -1; + for (unsigned int i = 0; i < fmt_ctx->nb_streams; i++) { + if (fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + audio_stream_idx = i; + break; + } + } + + if (audio_stream_idx == -1) { + fprintf(stderr, "error: failed to find an audio stream in '%s'\n", ifname.c_str()); + avformat_close_input(&fmt_ctx); + return true; + } + + AVStream * audio_stream = fmt_ctx->streams[audio_stream_idx]; + + // Open the decoder + const AVCodec * codec = avcodec_find_decoder(audio_stream->codecpar->codec_id); + if (!codec) { + fprintf(stderr, "error: failed to find decoder for codec id %d\n", audio_stream->codecpar->codec_id); + avformat_close_input(&fmt_ctx); + return true; + } + + AVCodecContext * codec_ctx = avcodec_alloc_context3(codec); + if (!codec_ctx) { + fprintf(stderr, "error: failed to allocate codec context\n"); + avformat_close_input(&fmt_ctx); + return true; + } + + if (avcodec_parameters_to_context(codec_ctx, audio_stream->codecpar) < 0) { + fprintf(stderr, "error: failed to copy codec parameters to context\n"); + avcodec_free_context(&codec_ctx); + avformat_close_input(&fmt_ctx); + return true; + } + + if (avcodec_open2(codec_ctx, codec, nullptr) < 0) { + fprintf(stderr, "error: failed to open codec\n"); + avcodec_free_context(&codec_ctx); + avformat_close_input(&fmt_ctx); + return true; + } + + // Setup resampler: convert to 16-bit signed PCM, mono, 16000 Hz + const enum AVSampleFormat out_sample_fmt = AV_SAMPLE_FMT_S16; + + AVChannelLayout out_ch_layout = AV_CHANNEL_LAYOUT_MONO; + + SwrContext * swr_ctx = nullptr; + if (swr_alloc_set_opts2(&swr_ctx, &out_ch_layout, out_sample_fmt, out_sample_rate, + &codec_ctx->ch_layout, codec_ctx->sample_fmt, codec_ctx->sample_rate, + 0, nullptr) < 0) { + fprintf(stderr, "error: failed to allocate swr context\n"); + avcodec_free_context(&codec_ctx); + avformat_close_input(&fmt_ctx); + return true; + } + + if (swr_init(swr_ctx) < 0) { + fprintf(stderr, "error: failed to initialize swr context\n"); + swr_free(&swr_ctx); + avcodec_free_context(&codec_ctx); + avformat_close_input(&fmt_ctx); + return true; + } + + // Decode and resample + AVPacket * packet = av_packet_alloc(); + AVFrame * frame = av_frame_alloc(); + + // Buffer to collect resampled output + std::vector pcm_data; + + // Max output samples per swr_convert call + const int max_out_samples = 16 * 1024; + std::vector out_buffer(max_out_samples); + + while (av_read_frame(fmt_ctx, packet) >= 0) { + if (packet->stream_index != audio_stream_idx) { + av_packet_unref(packet); + continue; + } + + int ret = avcodec_send_packet(codec_ctx, packet); + av_packet_unref(packet); + + if (ret < 0) { + continue; + } + + while (ret >= 0) { + ret = avcodec_receive_frame(codec_ctx, frame); + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { + break; + } + if (ret < 0) { + break; + } + + // Resample + int out_samples = av_rescale_rnd(swr_get_delay(swr_ctx, out_sample_rate) + frame->nb_samples, + out_sample_rate, out_sample_rate, AV_ROUND_UP); + if (out_samples > (int)out_buffer.size()) { + out_buffer.resize(out_samples); + } + + const uint8_t * in_data[16] = {0}; + for (int p = 0; p < (int)codec_ctx->ch_layout.nb_channels && p < 16; p++) { + in_data[p] = frame->data[p]; + } + uint8_t * out_data[16] = {0}; + out_data[0] = (uint8_t *)out_buffer.data(); + + int got_samples = swr_convert(swr_ctx, out_data, out_samples, in_data, frame->nb_samples); + if (got_samples > 0) { + pcm_data.insert(pcm_data.end(), out_buffer.begin(), out_buffer.begin() + got_samples); + } + } + } + + // Flush the decoder + avcodec_send_packet(codec_ctx, nullptr); + while (avcodec_receive_frame(codec_ctx, frame) >= 0) { + int out_samples = av_rescale_rnd(swr_get_delay(swr_ctx, out_sample_rate) + frame->nb_samples, + out_sample_rate, out_sample_rate, AV_ROUND_UP); + if (out_samples > (int)out_buffer.size()) { + out_buffer.resize(out_samples); + } + const uint8_t * in_data[16] = {0}; + for (int p = 0; p < (int)codec_ctx->ch_layout.nb_channels && p < 16; p++) { + in_data[p] = frame->data[p]; + } + uint8_t * out_data[16] = {0}; + out_data[0] = (uint8_t *)out_buffer.data(); + + int got_samples = swr_convert(swr_ctx, out_data, out_samples, in_data, frame->nb_samples); + if (got_samples > 0) { + pcm_data.insert(pcm_data.end(), out_buffer.begin(), out_buffer.begin() + got_samples); + } + } + + // Flush the resampler + uint8_t * out_data[16] = {0}; + out_data[0] = (uint8_t *)out_buffer.data(); + int flush_samples = swr_convert(swr_ctx, out_data, max_out_samples, nullptr, 0); + if (flush_samples > 0) { + pcm_data.insert(pcm_data.end(), out_buffer.begin(), out_buffer.begin() + flush_samples); + } + + // Build WAV output + uint32_t data_size = pcm_data.size() * sizeof(int16_t); + wav_data.resize(44 + data_size); + + wav_header_write(wav_data.data(), 1, out_sample_rate, 16, data_size); + memcpy(wav_data.data() + 44, pcm_data.data(), data_size); + + // Cleanup + av_frame_free(&frame); + av_packet_free(&packet); + swr_free(&swr_ctx); + avcodec_free_context(&codec_ctx); + avformat_close_input(&fmt_ctx); + + return false; // success +} + +#endif // WHISPER_COMMON_FFMPEG diff --git a/examples/generate-karaoke.sh b/examples/generate-karaoke.sh new file mode 100755 index 0000000..b30f40f --- /dev/null +++ b/examples/generate-karaoke.sh @@ -0,0 +1,57 @@ +#!/bin/bash + +# Simple tool to record audio from the microphone and generate a karaoke video +# Usage: +# +# cd whisper.cpp +# make +# +# ./examples/generate-karaoke.sh [model] [step_ms] +# +# Press Ctrl+C to stop recording +# + +executable="./build/bin/whisper-cli" +model="base.en" +model_path="models/ggml-$model.bin" + +# require sox and ffmpeg to be installed +if ! command -v sox &> /dev/null +then + echo "sox could not be found" + exit 1 +fi + +if ! command -v ffmpeg &> /dev/null +then + echo "ffmpeg could not be found" + exit 2 +fi + +if [ ! -f "$executable" ]; then + echo "'$executable' does not exist. Please build it first." + exit 3 +fi + +if [ ! -f "$model_path" ]; then + echo "'$model_path' does not exist. Please download it first." + exit 4 +fi + +# record some raw audio +sox -d rec.wav + +# run Whisper +echo "Processing ..." +${executable} -m models/ggml-base.en.bin rec.wav -owts > /dev/null 2>&1 + +# generate Karaoke video +echo "Generating video ..." +source rec.wav.wts > /dev/null 2>&1 + +# play the video +echo "Playing ./rec16.wav.mp4 ..." +ffplay -loglevel 0 -autoexit ./rec.wav.mp4 + +echo "Done" +exit 0 diff --git a/examples/grammar-parser.cpp b/examples/grammar-parser.cpp new file mode 100644 index 0000000..e282fc7 --- /dev/null +++ b/examples/grammar-parser.cpp @@ -0,0 +1,423 @@ +#include "grammar-parser.h" +#include +#include +#include +#include +#include +#include + +namespace grammar_parser { + // NOTE: assumes valid utf8 (but checks for overrun) + // copied from whisper.cpp + static std::pair decode_utf8(const char * src) { + static const int lookup[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 4 }; + uint8_t first_byte = static_cast(*src); + uint8_t highbits = first_byte >> 4; + int len = lookup[highbits]; + uint8_t mask = (1 << (8 - len)) - 1; + uint32_t value = first_byte & mask; + const char * end = src + len; // may overrun! + const char * pos = src + 1; + for ( ; pos < end && *pos; pos++) { + value = (value << 6) + (static_cast(*pos) & 0x3F); + } + return std::make_pair(value, pos); + } + + static uint32_t get_symbol_id(parse_state & state, const char * src, size_t len) { + uint32_t next_id = static_cast(state.symbol_ids.size()); + auto result = state.symbol_ids.insert(std::make_pair(std::string(src, len), next_id)); + return result.first->second; + } + + static uint32_t generate_symbol_id(parse_state & state, const std::string & base_name) { + uint32_t next_id = static_cast(state.symbol_ids.size()); + state.symbol_ids[base_name + '_' + std::to_string(next_id)] = next_id; + return next_id; + } + + static void add_rule( + parse_state & state, + uint32_t rule_id, + const std::vector & rule) { + if (state.rules.size() <= rule_id) { + state.rules.resize(rule_id + 1); + } + state.rules[rule_id] = rule; + } + + static bool is_word_char(char c) { + return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '-' || ('0' <= c && c <= '9'); + } + + static std::pair parse_hex(const char * src, int size) { + const char * pos = src; + const char * end = src + size; + uint32_t value = 0; + for ( ; pos < end && *pos; pos++) { + value <<= 4; + char c = *pos; + if ('a' <= c && c <= 'f') { + value += c - 'a' + 10; + } else if ('A' <= c && c <= 'F') { + value += c - 'A' + 10; + } else if ('0' <= c && c <= '9') { + value += c - '0'; + } else { + break; + } + } + if (pos != end) { + throw std::runtime_error("expecting " + std::to_string(size) + " hex chars at " + src); + } + return std::make_pair(value, pos); + } + + static const char * parse_space(const char * src, bool newline_ok) { + const char * pos = src; + while (*pos == ' ' || *pos == '\t' || *pos == '#' || + (newline_ok && (*pos == '\r' || *pos == '\n'))) { + if (*pos == '#') { + while (*pos && *pos != '\r' && *pos != '\n') { + pos++; + } + } else { + pos++; + } + } + return pos; + } + + static const char * parse_name(const char * src) { + const char * pos = src; + while (is_word_char(*pos)) { + pos++; + } + if (pos == src) { + throw std::runtime_error(std::string("expecting name at ") + src); + } + return pos; + } + + static std::pair parse_char(const char * src) { + if (*src == '\\') { + switch (src[1]) { + case 'x': return parse_hex(src + 2, 2); + case 'u': return parse_hex(src + 2, 4); + case 'U': return parse_hex(src + 2, 8); + case 't': return std::make_pair('\t', src + 2); + case 'r': return std::make_pair('\r', src + 2); + case 'n': return std::make_pair('\n', src + 2); + case '\\': + case '"': + case '[': + case ']': + return std::make_pair(src[1], src + 2); + default: + throw std::runtime_error(std::string("unknown escape at ") + src); + } + } else if (*src) { + return decode_utf8(src); + } + throw std::runtime_error("unexpected end of input"); + } + + static const char * parse_alternates( + parse_state & state, + const char * src, + const std::string & rule_name, + uint32_t rule_id, + bool is_nested); + + static const char * parse_sequence( + parse_state & state, + const char * src, + const std::string & rule_name, + std::vector & out_elements, + bool is_nested) { + size_t last_sym_start = out_elements.size(); + const char * pos = src; + while (*pos) { + if (*pos == '"') { // literal string + pos++; + last_sym_start = out_elements.size(); + while (*pos != '"') { + auto char_pair = parse_char(pos); + pos = char_pair.second; + out_elements.push_back({WHISPER_GRETYPE_CHAR, char_pair.first}); + } + pos = parse_space(pos + 1, is_nested); + } else if (*pos == '[') { // char range(s) + pos++; + enum whisper_gretype start_type = WHISPER_GRETYPE_CHAR; + if (*pos == '^') { + pos++; + start_type = WHISPER_GRETYPE_CHAR_NOT; + } + last_sym_start = out_elements.size(); + while (*pos != ']') { + auto char_pair = parse_char(pos); + pos = char_pair.second; + enum whisper_gretype type = last_sym_start < out_elements.size() + ? WHISPER_GRETYPE_CHAR_ALT + : start_type; + + out_elements.push_back({type, char_pair.first}); + if (pos[0] == '-' && pos[1] != ']') { + auto endchar_pair = parse_char(pos + 1); + pos = endchar_pair.second; + out_elements.push_back({WHISPER_GRETYPE_CHAR_RNG_UPPER, endchar_pair.first}); + } + } + pos = parse_space(pos + 1, is_nested); + } else if (is_word_char(*pos)) { // rule reference + const char * name_end = parse_name(pos); + uint32_t ref_rule_id = get_symbol_id(state, pos, name_end - pos); + pos = parse_space(name_end, is_nested); + last_sym_start = out_elements.size(); + out_elements.push_back({WHISPER_GRETYPE_RULE_REF, ref_rule_id}); + } else if (*pos == '(') { // grouping + // parse nested alternates into synthesized rule + pos = parse_space(pos + 1, true); + uint32_t sub_rule_id = generate_symbol_id(state, rule_name); + pos = parse_alternates(state, pos, rule_name, sub_rule_id, true); + last_sym_start = out_elements.size(); + // output reference to synthesized rule + out_elements.push_back({WHISPER_GRETYPE_RULE_REF, sub_rule_id}); + if (*pos != ')') { + throw std::runtime_error(std::string("expecting ')' at ") + pos); + } + pos = parse_space(pos + 1, is_nested); + } else if (*pos == '*' || *pos == '+' || *pos == '?') { // repetition operator + if (last_sym_start == out_elements.size()) { + throw std::runtime_error(std::string("expecting preceding item to */+/? at ") + pos); + } + + // apply transformation to previous symbol (last_sym_start to end) according to + // rewrite rules: + // S* --> S' ::= S S' | + // S+ --> S' ::= S S' | S + // S? --> S' ::= S | + uint32_t sub_rule_id = generate_symbol_id(state, rule_name); + std::vector sub_rule; + // add preceding symbol to generated rule + sub_rule.insert( + sub_rule.end(), out_elements.begin() + last_sym_start, out_elements.end()); + if (*pos == '*' || *pos == '+') { + // cause generated rule to recurse + sub_rule.push_back({WHISPER_GRETYPE_RULE_REF, sub_rule_id}); + } + // mark start of alternate def + sub_rule.push_back({WHISPER_GRETYPE_ALT, 0}); + if (*pos == '+') { + // add preceding symbol as alternate only for '+' (otherwise empty) + sub_rule.insert( + sub_rule.end(), out_elements.begin() + last_sym_start, out_elements.end()); + } + sub_rule.push_back({WHISPER_GRETYPE_END, 0}); + add_rule(state, sub_rule_id, sub_rule); + + // in original rule, replace previous symbol with reference to generated rule + out_elements.resize(last_sym_start); + out_elements.push_back({WHISPER_GRETYPE_RULE_REF, sub_rule_id}); + + pos = parse_space(pos + 1, is_nested); + } else { + break; + } + } + return pos; + } + + static const char * parse_alternates( + parse_state & state, + const char * src, + const std::string & rule_name, + uint32_t rule_id, + bool is_nested) { + std::vector rule; + const char * pos = parse_sequence(state, src, rule_name, rule, is_nested); + while (*pos == '|') { + rule.push_back({WHISPER_GRETYPE_ALT, 0}); + pos = parse_space(pos + 1, true); + pos = parse_sequence(state, pos, rule_name, rule, is_nested); + } + rule.push_back({WHISPER_GRETYPE_END, 0}); + add_rule(state, rule_id, rule); + return pos; + } + + static const char * parse_rule(parse_state & state, const char * src) { + const char * name_end = parse_name(src); + const char * pos = parse_space(name_end, false); + size_t name_len = name_end - src; + uint32_t rule_id = get_symbol_id(state, src, name_len); + const std::string name(src, name_len); + + if (!(pos[0] == ':' && pos[1] == ':' && pos[2] == '=')) { + throw std::runtime_error(std::string("expecting ::= at ") + pos); + } + pos = parse_space(pos + 3, true); + + pos = parse_alternates(state, pos, name, rule_id, false); + + if (*pos == '\r') { + pos += pos[1] == '\n' ? 2 : 1; + } else if (*pos == '\n') { + pos++; + } else if (*pos) { + throw std::runtime_error(std::string("expecting newline or end at ") + pos); + } + return parse_space(pos, true); + } + + parse_state parse(const char * src) { + try { + parse_state state; + const char * pos = parse_space(src, true); + while (*pos) { + pos = parse_rule(state, pos); + } + return state; + } catch (const std::exception & err) { + fprintf(stderr, "%s: error parsing grammar: %s\n", __func__, err.what()); + return parse_state(); + } + } + + static void print_grammar_char(FILE * file, uint32_t c) { + if (0x20 <= c && c <= 0x7f) { + fprintf(file, "%c", static_cast(c)); + } else { + // cop out of encoding UTF-8 + fprintf(file, "", c); + } + } + + static bool is_char_element(whisper_grammar_element elem) { + switch (elem.type) { + case WHISPER_GRETYPE_CHAR: return true; + case WHISPER_GRETYPE_CHAR_NOT: return true; + case WHISPER_GRETYPE_CHAR_ALT: return true; + case WHISPER_GRETYPE_CHAR_RNG_UPPER: return true; + default: return false; + } + } + + static void print_rule_binary(FILE * file, const std::vector & rule) { + for (auto elem : rule) { + switch (elem.type) { + case WHISPER_GRETYPE_END: fprintf(file, "END"); break; + case WHISPER_GRETYPE_ALT: fprintf(file, "ALT"); break; + case WHISPER_GRETYPE_RULE_REF: fprintf(file, "RULE_REF"); break; + case WHISPER_GRETYPE_CHAR: fprintf(file, "CHAR"); break; + case WHISPER_GRETYPE_CHAR_NOT: fprintf(file, "CHAR_NOT"); break; + case WHISPER_GRETYPE_CHAR_RNG_UPPER: fprintf(file, "CHAR_RNG_UPPER"); break; + case WHISPER_GRETYPE_CHAR_ALT: fprintf(file, "CHAR_ALT"); break; + } + switch (elem.type) { + case WHISPER_GRETYPE_END: + case WHISPER_GRETYPE_ALT: + case WHISPER_GRETYPE_RULE_REF: + fprintf(file, "(%u) ", elem.value); + break; + case WHISPER_GRETYPE_CHAR: + case WHISPER_GRETYPE_CHAR_NOT: + case WHISPER_GRETYPE_CHAR_RNG_UPPER: + case WHISPER_GRETYPE_CHAR_ALT: + fprintf(file, "(\""); + print_grammar_char(file, elem.value); + fprintf(file, "\") "); + break; + } + } + fprintf(file, "\n"); + } + + static void print_rule( + FILE * file, + uint32_t rule_id, + const std::vector & rule, + const std::map & symbol_id_names) { + if (rule.empty() || rule.back().type != WHISPER_GRETYPE_END) { + throw std::runtime_error( + "malformed rule, does not end with WHISPER_GRETYPE_END: " + std::to_string(rule_id)); + } + fprintf(file, "%s ::= ", symbol_id_names.at(rule_id).c_str()); + for (size_t i = 0, end = rule.size() - 1; i < end; i++) { + whisper_grammar_element elem = rule[i]; + switch (elem.type) { + case WHISPER_GRETYPE_END: + throw std::runtime_error( + "unexpected end of rule: " + std::to_string(rule_id) + "," + + std::to_string(i)); + case WHISPER_GRETYPE_ALT: + fprintf(file, "| "); + break; + case WHISPER_GRETYPE_RULE_REF: + fprintf(file, "%s ", symbol_id_names.at(elem.value).c_str()); + break; + case WHISPER_GRETYPE_CHAR: + fprintf(file, "["); + print_grammar_char(file, elem.value); + break; + case WHISPER_GRETYPE_CHAR_NOT: + fprintf(file, "[^"); + print_grammar_char(file, elem.value); + break; + case WHISPER_GRETYPE_CHAR_RNG_UPPER: + if (i == 0 || !is_char_element(rule[i - 1])) { + throw std::runtime_error( + "WHISPER_GRETYPE_CHAR_RNG_UPPER without preceding char: " + + std::to_string(rule_id) + "," + std::to_string(i)); + } + fprintf(file, "-"); + print_grammar_char(file, elem.value); + break; + case WHISPER_GRETYPE_CHAR_ALT: + if (i == 0 || !is_char_element(rule[i - 1])) { + throw std::runtime_error( + "WHISPER_GRETYPE_CHAR_ALT without preceding char: " + + std::to_string(rule_id) + "," + std::to_string(i)); + } + print_grammar_char(file, elem.value); + break; + } + if (is_char_element(elem)) { + switch (rule[i + 1].type) { + case WHISPER_GRETYPE_CHAR_ALT: + case WHISPER_GRETYPE_CHAR_RNG_UPPER: + break; + default: + fprintf(file, "] "); + } + } + } + fprintf(file, "\n"); + } + + void print_grammar(FILE * file, const parse_state & state) { + try { + std::map symbol_id_names; + for (auto kv : state.symbol_ids) { + symbol_id_names[kv.second] = kv.first; + } + for (size_t i = 0, end = state.rules.size(); i < end; i++) { + // fprintf(file, "%zu: ", i); + // print_rule_binary(file, state.rules[i]); + print_rule(file, uint32_t(i), state.rules[i], symbol_id_names); + // fprintf(file, "\n"); + } + } catch (const std::exception & err) { + fprintf(stderr, "\n%s: error printing grammar: %s\n", __func__, err.what()); + } + } + + std::vector parse_state::c_rules() const { + std::vector ret; + for (const auto & rule : rules) { + ret.push_back(rule.data()); + } + return ret; + } +} diff --git a/examples/grammar-parser.h b/examples/grammar-parser.h new file mode 100644 index 0000000..47d019c --- /dev/null +++ b/examples/grammar-parser.h @@ -0,0 +1,29 @@ +// Implements a parser for an extended Backus-Naur form (BNF), producing the +// binary context-free grammar format specified by whisper.h. Supports character +// ranges, grouping, and repetition operators. As an example, a grammar for +// arithmetic might look like: +// +// root ::= expr +// expr ::= term ([-+*/] term)* +// term ::= num | "(" space expr ")" space +// num ::= [0-9]+ space +// space ::= [ \t\n]* + +#pragma once +#include "whisper.h" +#include +#include +#include +#include + +namespace grammar_parser { + struct parse_state { + std::map symbol_ids; + std::vector> rules; + + std::vector c_rules() const; + }; + + parse_state parse(const char * src); + void print_grammar(FILE * file, const parse_state & state); +} diff --git a/examples/helpers.js b/examples/helpers.js new file mode 100644 index 0000000..423bada --- /dev/null +++ b/examples/helpers.js @@ -0,0 +1,191 @@ +// Common Javascript functions used by the examples + +function convertTypedArray(src, type) { + var buffer = new ArrayBuffer(src.byteLength); + var baseView = new src.constructor(buffer).set(src); + return new type(buffer); +} + +var printTextarea = (function() { + var element = document.getElementById('output'); + if (element) element.value = ''; // clear browser cache + return function(text) { + if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' '); + console.log(text); + if (element) { + element.value += text + "\n"; + element.scrollTop = element.scrollHeight; // focus on bottom + } + }; +})(); + +async function clearCache() { + if (confirm('Are you sure you want to clear the cache?\nAll the models will be downloaded again.')) { + indexedDB.deleteDatabase(dbName); + location.reload(); + } +} + +// fetch a remote file from remote URL using the Fetch API +async function fetchRemote(url, cbProgress, cbPrint) { + cbPrint('fetchRemote: downloading with fetch()...'); + + const response = await fetch( + url, + { + method: 'GET', + } + ); + + if (!response.ok) { + cbPrint('fetchRemote: failed to fetch ' + url); + return; + } + + const contentLength = response.headers.get('content-length'); + const total = parseInt(contentLength, 10); + const reader = response.body.getReader(); + + var chunks = []; + var receivedLength = 0; + var progressLast = -1; + + while (true) { + const { done, value } = await reader.read(); + + if (done) { + break; + } + + chunks.push(value); + receivedLength += value.length; + + if (contentLength) { + cbProgress(receivedLength/total); + + var progressCur = Math.round((receivedLength / total) * 10); + if (progressCur != progressLast) { + cbPrint('fetchRemote: fetching ' + 10*progressCur + '% ...'); + progressLast = progressCur; + } + } + } + + var position = 0; + var chunksAll = new Uint8Array(receivedLength); + + for (var chunk of chunks) { + chunksAll.set(chunk, position); + position += chunk.length; + } + + return chunksAll; +} + +// load remote data +// - check if the data is already in the IndexedDB +// - if not, fetch it from the remote URL and store it in the IndexedDB +function loadRemote(url, dst, size_mb, cbProgress, cbReady, cbCancel, cbPrint) { + if (!navigator.storage || !navigator.storage.estimate) { + cbPrint('loadRemote: navigator.storage.estimate() is not supported'); + } else { + // query the storage quota and print it + navigator.storage.estimate().then(function (estimate) { + cbPrint('loadRemote: storage quota: ' + estimate.quota + ' bytes'); + cbPrint('loadRemote: storage usage: ' + estimate.usage + ' bytes'); + }); + } + + // check if the data is already in the IndexedDB + var rq = indexedDB.open(dbName, dbVersion); + + rq.onupgradeneeded = function (event) { + var db = event.target.result; + if (db.version == 1) { + var os = db.createObjectStore('models', { autoIncrement: false }); + cbPrint('loadRemote: created IndexedDB ' + db.name + ' version ' + db.version); + } else { + // clear the database + var os = event.currentTarget.transaction.objectStore('models'); + os.clear(); + cbPrint('loadRemote: cleared IndexedDB ' + db.name + ' version ' + db.version); + } + }; + + rq.onsuccess = function (event) { + var db = event.target.result; + var tx = db.transaction(['models'], 'readonly'); + var os = tx.objectStore('models'); + var rq = os.get(url); + + rq.onsuccess = function (event) { + if (rq.result) { + cbPrint('loadRemote: "' + url + '" is already in the IndexedDB'); + cbReady(dst, rq.result); + } else { + // data is not in the IndexedDB + cbPrint('loadRemote: "' + url + '" is not in the IndexedDB'); + + // alert and ask the user to confirm + if (!confirm( + 'You are about to download ' + size_mb + ' MB of data.\n' + + 'The model data will be cached in the browser for future use.\n\n' + + 'Press OK to continue.')) { + cbCancel(); + return; + } + + fetchRemote(url, cbProgress, cbPrint).then(function (data) { + if (data) { + // store the data in the IndexedDB + var rq = indexedDB.open(dbName, dbVersion); + rq.onsuccess = function (event) { + var db = event.target.result; + var tx = db.transaction(['models'], 'readwrite'); + var os = tx.objectStore('models'); + + var rq = null; + try { + var rq = os.put(data, url); + } catch (e) { + cbPrint('loadRemote: failed to store "' + url + '" in the IndexedDB: \n' + e); + cbCancel(); + return; + } + + rq.onsuccess = function (event) { + cbPrint('loadRemote: "' + url + '" stored in the IndexedDB'); + cbReady(dst, data); + }; + + rq.onerror = function (event) { + cbPrint('loadRemote: failed to store "' + url + '" in the IndexedDB'); + cbCancel(); + }; + }; + } + }); + } + }; + + rq.onerror = function (event) { + cbPrint('loadRemote: failed to get data from the IndexedDB'); + cbCancel(); + }; + }; + + rq.onerror = function (event) { + cbPrint('loadRemote: failed to open IndexedDB'); + cbCancel(); + }; + + rq.onblocked = function (event) { + cbPrint('loadRemote: failed to open IndexedDB: blocked'); + cbCancel(); + }; + + rq.onabort = function (event) { + cbPrint('loadRemote: failed to open IndexedDB: abort'); + cbCancel(); + }; +} diff --git a/examples/json.hpp b/examples/json.hpp new file mode 100644 index 0000000..4d1a37a --- /dev/null +++ b/examples/json.hpp @@ -0,0 +1,24596 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + +/****************************************************************************\ + * Note on documentation: The source files contain links to the online * + * documentation of the public API at https://json.nlohmann.me. This URL * + * contains the most recent documentation and should also be applicable to * + * previous versions; documentation for deprecated functions is not * + * removed, but marked deprecated. See "Generate documentation" section in * + * file docs/README.md. * +\****************************************************************************/ + +#ifndef INCLUDE_NLOHMANN_JSON_HPP_ +#define INCLUDE_NLOHMANN_JSON_HPP_ + +#include // all_of, find, for_each +#include // nullptr_t, ptrdiff_t, size_t +#include // hash, less +#include // initializer_list +#ifndef JSON_NO_IO + #include // istream, ostream +#endif // JSON_NO_IO +#include // random_access_iterator_tag +#include // unique_ptr +#include // accumulate +#include // string, stoi, to_string +#include // declval, forward, move, pair, swap +#include // vector + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// This file contains all macro definitions affecting or depending on the ABI + +#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK + #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH) + #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 11 || NLOHMANN_JSON_VERSION_PATCH != 2 + #warning "Already included a different version of the library!" + #endif + #endif +#endif + +#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum) +#define NLOHMANN_JSON_VERSION_MINOR 11 // NOLINT(modernize-macro-to-enum) +#define NLOHMANN_JSON_VERSION_PATCH 2 // NOLINT(modernize-macro-to-enum) + +#ifndef JSON_DIAGNOSTICS + #define JSON_DIAGNOSTICS 0 +#endif + +#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON + #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0 +#endif + +#if JSON_DIAGNOSTICS + #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag +#else + #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS +#endif + +#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON + #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp +#else + #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON +#endif + +#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION + #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0 +#endif + +// Construct the namespace ABI tags component +#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b +#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \ + NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) + +#define NLOHMANN_JSON_ABI_TAGS \ + NLOHMANN_JSON_ABI_TAGS_CONCAT( \ + NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \ + NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON) + +// Construct the namespace version component +#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \ + _v ## major ## _ ## minor ## _ ## patch +#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \ + NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) + +#if NLOHMANN_JSON_NAMESPACE_NO_VERSION +#define NLOHMANN_JSON_NAMESPACE_VERSION +#else +#define NLOHMANN_JSON_NAMESPACE_VERSION \ + NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \ + NLOHMANN_JSON_VERSION_MINOR, \ + NLOHMANN_JSON_VERSION_PATCH) +#endif + +// Combine namespace components +#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b +#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \ + NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) + +#ifndef NLOHMANN_JSON_NAMESPACE +#define NLOHMANN_JSON_NAMESPACE \ + nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \ + NLOHMANN_JSON_ABI_TAGS, \ + NLOHMANN_JSON_NAMESPACE_VERSION) +#endif + +#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN +#define NLOHMANN_JSON_NAMESPACE_BEGIN \ + namespace nlohmann \ + { \ + inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \ + NLOHMANN_JSON_ABI_TAGS, \ + NLOHMANN_JSON_NAMESPACE_VERSION) \ + { +#endif + +#ifndef NLOHMANN_JSON_NAMESPACE_END +#define NLOHMANN_JSON_NAMESPACE_END \ + } /* namespace (inline namespace) NOLINT(readability/namespace) */ \ + } // namespace nlohmann +#endif + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // transform +#include // array +#include // forward_list +#include // inserter, front_inserter, end +#include // map +#include // string +#include // tuple, make_tuple +#include // is_arithmetic, is_same, is_enum, underlying_type, is_convertible +#include // unordered_map +#include // pair, declval +#include // valarray + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // nullptr_t +#include // exception +#include // runtime_error +#include // to_string +#include // vector + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // array +#include // size_t +#include // uint8_t +#include // string + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // declval, pair +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +template struct make_void +{ + using type = void; +}; +template using void_t = typename make_void::type; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +// https://en.cppreference.com/w/cpp/experimental/is_detected +struct nonesuch +{ + nonesuch() = delete; + ~nonesuch() = delete; + nonesuch(nonesuch const&) = delete; + nonesuch(nonesuch const&&) = delete; + void operator=(nonesuch const&) = delete; + void operator=(nonesuch&&) = delete; +}; + +template class Op, + class... Args> +struct detector +{ + using value_t = std::false_type; + using type = Default; +}; + +template class Op, class... Args> +struct detector>, Op, Args...> +{ + using value_t = std::true_type; + using type = Op; +}; + +template class Op, class... Args> +using is_detected = typename detector::value_t; + +template class Op, class... Args> +struct is_detected_lazy : is_detected { }; + +template class Op, class... Args> +using detected_t = typename detector::type; + +template class Op, class... Args> +using detected_or = detector; + +template class Op, class... Args> +using detected_or_t = typename detected_or::type; + +template class Op, class... Args> +using is_detected_exact = std::is_same>; + +template class Op, class... Args> +using is_detected_convertible = + std::is_convertible, To>; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include + + +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-FileCopyrightText: 2016-2021 Evan Nemerson +// SPDX-License-Identifier: MIT + +/* Hedley - https://nemequ.github.io/hedley + * Created by Evan Nemerson + */ + +#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15) +#if defined(JSON_HEDLEY_VERSION) + #undef JSON_HEDLEY_VERSION +#endif +#define JSON_HEDLEY_VERSION 15 + +#if defined(JSON_HEDLEY_STRINGIFY_EX) + #undef JSON_HEDLEY_STRINGIFY_EX +#endif +#define JSON_HEDLEY_STRINGIFY_EX(x) #x + +#if defined(JSON_HEDLEY_STRINGIFY) + #undef JSON_HEDLEY_STRINGIFY +#endif +#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x) + +#if defined(JSON_HEDLEY_CONCAT_EX) + #undef JSON_HEDLEY_CONCAT_EX +#endif +#define JSON_HEDLEY_CONCAT_EX(a,b) a##b + +#if defined(JSON_HEDLEY_CONCAT) + #undef JSON_HEDLEY_CONCAT +#endif +#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b) + +#if defined(JSON_HEDLEY_CONCAT3_EX) + #undef JSON_HEDLEY_CONCAT3_EX +#endif +#define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c + +#if defined(JSON_HEDLEY_CONCAT3) + #undef JSON_HEDLEY_CONCAT3 +#endif +#define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c) + +#if defined(JSON_HEDLEY_VERSION_ENCODE) + #undef JSON_HEDLEY_VERSION_ENCODE +#endif +#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision)) + +#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR) + #undef JSON_HEDLEY_VERSION_DECODE_MAJOR +#endif +#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000) + +#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR) + #undef JSON_HEDLEY_VERSION_DECODE_MINOR +#endif +#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000) + +#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION) + #undef JSON_HEDLEY_VERSION_DECODE_REVISION +#endif +#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000) + +#if defined(JSON_HEDLEY_GNUC_VERSION) + #undef JSON_HEDLEY_GNUC_VERSION +#endif +#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__) + #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) +#elif defined(__GNUC__) + #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0) +#endif + +#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK) + #undef JSON_HEDLEY_GNUC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_GNUC_VERSION) + #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_MSVC_VERSION) + #undef JSON_HEDLEY_MSVC_VERSION +#endif +#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL) + #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100) +#elif defined(_MSC_FULL_VER) && !defined(__ICL) + #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10) +#elif defined(_MSC_VER) && !defined(__ICL) + #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0) +#endif + +#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK) + #undef JSON_HEDLEY_MSVC_VERSION_CHECK +#endif +#if !defined(JSON_HEDLEY_MSVC_VERSION) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0) +#elif defined(_MSC_VER) && (_MSC_VER >= 1400) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch))) +#elif defined(_MSC_VER) && (_MSC_VER >= 1200) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch))) +#else + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor))) +#endif + +#if defined(JSON_HEDLEY_INTEL_VERSION) + #undef JSON_HEDLEY_INTEL_VERSION +#endif +#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL) + #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE) +#elif defined(__INTEL_COMPILER) && !defined(__ICL) + #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0) +#endif + +#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK) + #undef JSON_HEDLEY_INTEL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_INTEL_VERSION) + #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_INTEL_CL_VERSION) + #undef JSON_HEDLEY_INTEL_CL_VERSION +#endif +#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL) + #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0) +#endif + +#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK) + #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_INTEL_CL_VERSION) + #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_PGI_VERSION) + #undef JSON_HEDLEY_PGI_VERSION +#endif +#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__) + #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__) +#endif + +#if defined(JSON_HEDLEY_PGI_VERSION_CHECK) + #undef JSON_HEDLEY_PGI_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_PGI_VERSION) + #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_SUNPRO_VERSION) + #undef JSON_HEDLEY_SUNPRO_VERSION +#endif +#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10) +#elif defined(__SUNPRO_C) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf) +#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10) +#elif defined(__SUNPRO_CC) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf) +#endif + +#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK) + #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_SUNPRO_VERSION) + #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) + #undef JSON_HEDLEY_EMSCRIPTEN_VERSION +#endif +#if defined(__EMSCRIPTEN__) + #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__) +#endif + +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK) + #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) + #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_ARM_VERSION) + #undef JSON_HEDLEY_ARM_VERSION +#endif +#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION) + #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100) +#elif defined(__CC_ARM) && defined(__ARMCC_VERSION) + #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100) +#endif + +#if defined(JSON_HEDLEY_ARM_VERSION_CHECK) + #undef JSON_HEDLEY_ARM_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_ARM_VERSION) + #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_IBM_VERSION) + #undef JSON_HEDLEY_IBM_VERSION +#endif +#if defined(__ibmxl__) + #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__) +#elif defined(__xlC__) && defined(__xlC_ver__) + #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff) +#elif defined(__xlC__) + #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0) +#endif + +#if defined(JSON_HEDLEY_IBM_VERSION_CHECK) + #undef JSON_HEDLEY_IBM_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_IBM_VERSION) + #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_VERSION) + #undef JSON_HEDLEY_TI_VERSION +#endif +#if \ + defined(__TI_COMPILER_VERSION__) && \ + ( \ + defined(__TMS470__) || defined(__TI_ARM__) || \ + defined(__MSP430__) || \ + defined(__TMS320C2000__) \ + ) +#if (__TI_COMPILER_VERSION__ >= 16000000) + #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif +#endif + +#if defined(JSON_HEDLEY_TI_VERSION_CHECK) + #undef JSON_HEDLEY_TI_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_VERSION) + #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL2000_VERSION) + #undef JSON_HEDLEY_TI_CL2000_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__) + #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL2000_VERSION) + #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL430_VERSION) + #undef JSON_HEDLEY_TI_CL430_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__) + #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL430_VERSION) + #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_ARMCL_VERSION) + #undef JSON_HEDLEY_TI_ARMCL_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__)) + #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK) + #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_ARMCL_VERSION) + #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL6X_VERSION) + #undef JSON_HEDLEY_TI_CL6X_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__) + #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL6X_VERSION) + #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL7X_VERSION) + #undef JSON_HEDLEY_TI_CL7X_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__) + #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL7X_VERSION) + #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CLPRU_VERSION) + #undef JSON_HEDLEY_TI_CLPRU_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__) + #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CLPRU_VERSION) + #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_CRAY_VERSION) + #undef JSON_HEDLEY_CRAY_VERSION +#endif +#if defined(_CRAYC) + #if defined(_RELEASE_PATCHLEVEL) + #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL) + #else + #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0) + #endif +#endif + +#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK) + #undef JSON_HEDLEY_CRAY_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_CRAY_VERSION) + #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_IAR_VERSION) + #undef JSON_HEDLEY_IAR_VERSION +#endif +#if defined(__IAR_SYSTEMS_ICC__) + #if __VER__ > 1000 + #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000)) + #else + #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0) + #endif +#endif + +#if defined(JSON_HEDLEY_IAR_VERSION_CHECK) + #undef JSON_HEDLEY_IAR_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_IAR_VERSION) + #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TINYC_VERSION) + #undef JSON_HEDLEY_TINYC_VERSION +#endif +#if defined(__TINYC__) + #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100) +#endif + +#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK) + #undef JSON_HEDLEY_TINYC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TINYC_VERSION) + #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_DMC_VERSION) + #undef JSON_HEDLEY_DMC_VERSION +#endif +#if defined(__DMC__) + #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf) +#endif + +#if defined(JSON_HEDLEY_DMC_VERSION_CHECK) + #undef JSON_HEDLEY_DMC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_DMC_VERSION) + #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_COMPCERT_VERSION) + #undef JSON_HEDLEY_COMPCERT_VERSION +#endif +#if defined(__COMPCERT_VERSION__) + #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100) +#endif + +#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK) + #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_COMPCERT_VERSION) + #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_PELLES_VERSION) + #undef JSON_HEDLEY_PELLES_VERSION +#endif +#if defined(__POCC__) + #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0) +#endif + +#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK) + #undef JSON_HEDLEY_PELLES_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_PELLES_VERSION) + #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_MCST_LCC_VERSION) + #undef JSON_HEDLEY_MCST_LCC_VERSION +#endif +#if defined(__LCC__) && defined(__LCC_MINOR__) + #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__) +#endif + +#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK) + #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_MCST_LCC_VERSION) + #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_GCC_VERSION) + #undef JSON_HEDLEY_GCC_VERSION +#endif +#if \ + defined(JSON_HEDLEY_GNUC_VERSION) && \ + !defined(__clang__) && \ + !defined(JSON_HEDLEY_INTEL_VERSION) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_ARM_VERSION) && \ + !defined(JSON_HEDLEY_CRAY_VERSION) && \ + !defined(JSON_HEDLEY_TI_VERSION) && \ + !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL430_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \ + !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \ + !defined(__COMPCERT__) && \ + !defined(JSON_HEDLEY_MCST_LCC_VERSION) + #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION +#endif + +#if defined(JSON_HEDLEY_GCC_VERSION_CHECK) + #undef JSON_HEDLEY_GCC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_GCC_VERSION) + #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_HAS_ATTRIBUTE +#endif +#if \ + defined(__has_attribute) && \ + ( \ + (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \ + ) +# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute) +#else +# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE +#endif +#if defined(__has_attribute) + #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) +#else + #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE +#endif +#if defined(__has_attribute) + #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) +#else + #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE +#endif +#if \ + defined(__has_cpp_attribute) && \ + defined(__cplusplus) && \ + (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute) +#else + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS) + #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS +#endif +#if !defined(__cplusplus) || !defined(__has_cpp_attribute) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) +#elif \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_IAR_VERSION) && \ + (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \ + (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0)) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute) +#else + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE +#endif +#if defined(__has_cpp_attribute) && defined(__cplusplus) + #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) +#else + #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE +#endif +#if defined(__has_cpp_attribute) && defined(__cplusplus) + #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) +#else + #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_BUILTIN) + #undef JSON_HEDLEY_HAS_BUILTIN +#endif +#if defined(__has_builtin) + #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin) +#else + #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN) + #undef JSON_HEDLEY_GNUC_HAS_BUILTIN +#endif +#if defined(__has_builtin) + #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) +#else + #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN) + #undef JSON_HEDLEY_GCC_HAS_BUILTIN +#endif +#if defined(__has_builtin) + #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) +#else + #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_FEATURE) + #undef JSON_HEDLEY_HAS_FEATURE +#endif +#if defined(__has_feature) + #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature) +#else + #define JSON_HEDLEY_HAS_FEATURE(feature) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE) + #undef JSON_HEDLEY_GNUC_HAS_FEATURE +#endif +#if defined(__has_feature) + #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) +#else + #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_FEATURE) + #undef JSON_HEDLEY_GCC_HAS_FEATURE +#endif +#if defined(__has_feature) + #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) +#else + #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_EXTENSION) + #undef JSON_HEDLEY_HAS_EXTENSION +#endif +#if defined(__has_extension) + #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension) +#else + #define JSON_HEDLEY_HAS_EXTENSION(extension) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION) + #undef JSON_HEDLEY_GNUC_HAS_EXTENSION +#endif +#if defined(__has_extension) + #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) +#else + #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION) + #undef JSON_HEDLEY_GCC_HAS_EXTENSION +#endif +#if defined(__has_extension) + #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) +#else + #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) + #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute) +#else + #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) + #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) +#else + #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) + #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) +#else + #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_WARNING) + #undef JSON_HEDLEY_HAS_WARNING +#endif +#if defined(__has_warning) + #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning) +#else + #define JSON_HEDLEY_HAS_WARNING(warning) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_WARNING) + #undef JSON_HEDLEY_GNUC_HAS_WARNING +#endif +#if defined(__has_warning) + #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) +#else + #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_WARNING) + #undef JSON_HEDLEY_GCC_HAS_WARNING +#endif +#if defined(__has_warning) + #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) +#else + #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ + defined(__clang__) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR)) + #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_PRAGMA(value) __pragma(value) +#else + #define JSON_HEDLEY_PRAGMA(value) +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH) + #undef JSON_HEDLEY_DIAGNOSTIC_PUSH +#endif +#if defined(JSON_HEDLEY_DIAGNOSTIC_POP) + #undef JSON_HEDLEY_DIAGNOSTIC_POP +#endif +#if defined(__clang__) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop") +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push)) + #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop)) +#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop") +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop") +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") +#else + #define JSON_HEDLEY_DIAGNOSTIC_PUSH + #define JSON_HEDLEY_DIAGNOSTIC_POP +#endif + +/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for + HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ +#endif +#if defined(__cplusplus) +# if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat") +# if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions") +# if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions") +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ + _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \ + xpr \ + JSON_HEDLEY_DIAGNOSTIC_POP +# else +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ + xpr \ + JSON_HEDLEY_DIAGNOSTIC_POP +# endif +# else +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + xpr \ + JSON_HEDLEY_DIAGNOSTIC_POP +# endif +# endif +#endif +#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x +#endif + +#if defined(JSON_HEDLEY_CONST_CAST) + #undef JSON_HEDLEY_CONST_CAST +#endif +#if defined(__cplusplus) +# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast(expr)) +#elif \ + JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \ + ((T) (expr)); \ + JSON_HEDLEY_DIAGNOSTIC_POP \ + })) +#else +# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_REINTERPRET_CAST) + #undef JSON_HEDLEY_REINTERPRET_CAST +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast(expr)) +#else + #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_STATIC_CAST) + #undef JSON_HEDLEY_STATIC_CAST +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast(expr)) +#else + #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_CPP_CAST) + #undef JSON_HEDLEY_CPP_CAST +#endif +#if defined(__cplusplus) +# if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast") +# define JSON_HEDLEY_CPP_CAST(T, expr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \ + ((T) (expr)) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0) +# define JSON_HEDLEY_CPP_CAST(T, expr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("diag_suppress=Pe137") \ + JSON_HEDLEY_DIAGNOSTIC_POP +# else +# define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr)) +# endif +#else +# define JSON_HEDLEY_CPP_CAST(T, expr) (expr) +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)") +#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445") +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996)) +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215") +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)") +#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068)) +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") +#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161") +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)") +#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292)) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098") +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)") +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097") +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunused-function") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505)) +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION +#endif + +#if defined(JSON_HEDLEY_DEPRECATED) + #undef JSON_HEDLEY_DEPRECATED +#endif +#if defined(JSON_HEDLEY_DEPRECATED_FOR) + #undef JSON_HEDLEY_DEPRECATED_FOR +#endif +#if \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since)) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement)) +#elif \ + (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since))) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement))) +#elif defined(__cplusplus) && (__cplusplus >= 201402L) + #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]]) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]]) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) + #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__)) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__)) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated) +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated") + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated") +#else + #define JSON_HEDLEY_DEPRECATED(since) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) +#endif + +#if defined(JSON_HEDLEY_UNAVAILABLE) + #undef JSON_HEDLEY_UNAVAILABLE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since))) +#else + #define JSON_HEDLEY_UNAVAILABLE(available_since) +#endif + +#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT) + #undef JSON_HEDLEY_WARN_UNUSED_RESULT +#endif +#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG) + #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__)) +#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L) + #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]]) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) + #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) +#elif defined(_Check_return_) /* SAL */ + #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_ + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_ +#else + #define JSON_HEDLEY_WARN_UNUSED_RESULT + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) +#endif + +#if defined(JSON_HEDLEY_SENTINEL) + #undef JSON_HEDLEY_SENTINEL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position))) +#else + #define JSON_HEDLEY_SENTINEL(position) +#endif + +#if defined(JSON_HEDLEY_NO_RETURN) + #undef JSON_HEDLEY_NO_RETURN +#endif +#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_NO_RETURN __noreturn +#elif \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) +#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L + #define JSON_HEDLEY_NO_RETURN _Noreturn +#elif defined(__cplusplus) && (__cplusplus >= 201103L) + #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]]) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) + #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return") +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) +#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) + #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;") +#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) + #define JSON_HEDLEY_NO_RETURN __attribute((noreturn)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) + #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) +#else + #define JSON_HEDLEY_NO_RETURN +#endif + +#if defined(JSON_HEDLEY_NO_ESCAPE) + #undef JSON_HEDLEY_NO_ESCAPE +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape) + #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__)) +#else + #define JSON_HEDLEY_NO_ESCAPE +#endif + +#if defined(JSON_HEDLEY_UNREACHABLE) + #undef JSON_HEDLEY_UNREACHABLE +#endif +#if defined(JSON_HEDLEY_UNREACHABLE_RETURN) + #undef JSON_HEDLEY_UNREACHABLE_RETURN +#endif +#if defined(JSON_HEDLEY_ASSUME) + #undef JSON_HEDLEY_ASSUME +#endif +#if \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_ASSUME(expr) __assume(expr) +#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume) + #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr) +#elif \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) + #if defined(__cplusplus) + #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr) + #else + #define JSON_HEDLEY_ASSUME(expr) _nassert(expr) + #endif +#endif +#if \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable() +#elif defined(JSON_HEDLEY_ASSUME) + #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) +#endif +#if !defined(JSON_HEDLEY_ASSUME) + #if defined(JSON_HEDLEY_UNREACHABLE) + #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1))) + #else + #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr) + #endif +#endif +#if defined(JSON_HEDLEY_UNREACHABLE) + #if \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value)) + #else + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE() + #endif +#else + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value) +#endif +#if !defined(JSON_HEDLEY_UNREACHABLE) + #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) +#endif + +JSON_HEDLEY_DIAGNOSTIC_PUSH +#if JSON_HEDLEY_HAS_WARNING("-Wpedantic") + #pragma clang diagnostic ignored "-Wpedantic" +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus) + #pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#endif +#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0) + #if defined(__clang__) + #pragma clang diagnostic ignored "-Wvariadic-macros" + #elif defined(JSON_HEDLEY_GCC_VERSION) + #pragma GCC diagnostic ignored "-Wvariadic-macros" + #endif +#endif +#if defined(JSON_HEDLEY_NON_NULL) + #undef JSON_HEDLEY_NON_NULL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) + #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__))) +#else + #define JSON_HEDLEY_NON_NULL(...) +#endif +JSON_HEDLEY_DIAGNOSTIC_POP + +#if defined(JSON_HEDLEY_PRINTF_FORMAT) + #undef JSON_HEDLEY_PRINTF_FORMAT +#endif +#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check))) +#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check))) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(format) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check))) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check)) +#else + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) +#endif + +#if defined(JSON_HEDLEY_CONSTEXPR) + #undef JSON_HEDLEY_CONSTEXPR +#endif +#if defined(__cplusplus) + #if __cplusplus >= 201103L + #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr) + #endif +#endif +#if !defined(JSON_HEDLEY_CONSTEXPR) + #define JSON_HEDLEY_CONSTEXPR +#endif + +#if defined(JSON_HEDLEY_PREDICT) + #undef JSON_HEDLEY_PREDICT +#endif +#if defined(JSON_HEDLEY_LIKELY) + #undef JSON_HEDLEY_LIKELY +#endif +#if defined(JSON_HEDLEY_UNLIKELY) + #undef JSON_HEDLEY_UNLIKELY +#endif +#if defined(JSON_HEDLEY_UNPREDICTABLE) + #undef JSON_HEDLEY_UNPREDICTABLE +#endif +#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable) + #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr)) +#endif +#if \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability)) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability)) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability)) +# define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 ) +# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 ) +#elif \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PREDICT(expr, expected, probability) \ + (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \ + (__extension__ ({ \ + double hedley_probability_ = (probability); \ + ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \ + })) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \ + (__extension__ ({ \ + double hedley_probability_ = (probability); \ + ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \ + })) +# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1) +# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0) +#else +# define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr)) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr)) +# define JSON_HEDLEY_LIKELY(expr) (!!(expr)) +# define JSON_HEDLEY_UNLIKELY(expr) (!!(expr)) +#endif +#if !defined(JSON_HEDLEY_UNPREDICTABLE) + #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5) +#endif + +#if defined(JSON_HEDLEY_MALLOC) + #undef JSON_HEDLEY_MALLOC +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_MALLOC __attribute__((__malloc__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory") +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_MALLOC __declspec(restrict) +#else + #define JSON_HEDLEY_MALLOC +#endif + +#if defined(JSON_HEDLEY_PURE) + #undef JSON_HEDLEY_PURE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PURE __attribute__((__pure__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) +# define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data") +#elif defined(__cplusplus) && \ + ( \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \ + ) +# define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;") +#else +# define JSON_HEDLEY_PURE +#endif + +#if defined(JSON_HEDLEY_CONST) + #undef JSON_HEDLEY_CONST +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(const) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_CONST __attribute__((__const__)) +#elif \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_CONST _Pragma("no_side_effect") +#else + #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE +#endif + +#if defined(JSON_HEDLEY_RESTRICT) + #undef JSON_HEDLEY_RESTRICT +#endif +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus) + #define JSON_HEDLEY_RESTRICT restrict +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ + defined(__clang__) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_RESTRICT __restrict +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus) + #define JSON_HEDLEY_RESTRICT _Restrict +#else + #define JSON_HEDLEY_RESTRICT +#endif + +#if defined(JSON_HEDLEY_INLINE) + #undef JSON_HEDLEY_INLINE +#endif +#if \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ + (defined(__cplusplus) && (__cplusplus >= 199711L)) + #define JSON_HEDLEY_INLINE inline +#elif \ + defined(JSON_HEDLEY_GCC_VERSION) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0) + #define JSON_HEDLEY_INLINE __inline__ +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_INLINE __inline +#else + #define JSON_HEDLEY_INLINE +#endif + +#if defined(JSON_HEDLEY_ALWAYS_INLINE) + #undef JSON_HEDLEY_ALWAYS_INLINE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) +# define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define JSON_HEDLEY_ALWAYS_INLINE __forceinline +#elif defined(__cplusplus) && \ + ( \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \ + ) +# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) +# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced") +#else +# define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE +#endif + +#if defined(JSON_HEDLEY_NEVER_INLINE) + #undef JSON_HEDLEY_NEVER_INLINE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) + #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__)) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0) + #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline") +#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) + #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never") +#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) + #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) + #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) +#else + #define JSON_HEDLEY_NEVER_INLINE +#endif + +#if defined(JSON_HEDLEY_PRIVATE) + #undef JSON_HEDLEY_PRIVATE +#endif +#if defined(JSON_HEDLEY_PUBLIC) + #undef JSON_HEDLEY_PUBLIC +#endif +#if defined(JSON_HEDLEY_IMPORT) + #undef JSON_HEDLEY_IMPORT +#endif +#if defined(_WIN32) || defined(__CYGWIN__) +# define JSON_HEDLEY_PRIVATE +# define JSON_HEDLEY_PUBLIC __declspec(dllexport) +# define JSON_HEDLEY_IMPORT __declspec(dllimport) +#else +# if \ + JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + ( \ + defined(__TI_EABI__) && \ + ( \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \ + ) \ + ) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden"))) +# define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default"))) +# else +# define JSON_HEDLEY_PRIVATE +# define JSON_HEDLEY_PUBLIC +# endif +# define JSON_HEDLEY_IMPORT extern +#endif + +#if defined(JSON_HEDLEY_NO_THROW) + #undef JSON_HEDLEY_NO_THROW +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__)) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) + #define JSON_HEDLEY_NO_THROW __declspec(nothrow) +#else + #define JSON_HEDLEY_NO_THROW +#endif + +#if defined(JSON_HEDLEY_FALL_THROUGH) + #undef JSON_HEDLEY_FALL_THROUGH +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__)) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough) + #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]]) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough) + #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]]) +#elif defined(__fallthrough) /* SAL */ + #define JSON_HEDLEY_FALL_THROUGH __fallthrough +#else + #define JSON_HEDLEY_FALL_THROUGH +#endif + +#if defined(JSON_HEDLEY_RETURNS_NON_NULL) + #undef JSON_HEDLEY_RETURNS_NON_NULL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__)) +#elif defined(_Ret_notnull_) /* SAL */ + #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_ +#else + #define JSON_HEDLEY_RETURNS_NON_NULL +#endif + +#if defined(JSON_HEDLEY_ARRAY_PARAM) + #undef JSON_HEDLEY_ARRAY_PARAM +#endif +#if \ + defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ + !defined(__STDC_NO_VLA__) && \ + !defined(__cplusplus) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_TINYC_VERSION) + #define JSON_HEDLEY_ARRAY_PARAM(name) (name) +#else + #define JSON_HEDLEY_ARRAY_PARAM(name) +#endif + +#if defined(JSON_HEDLEY_IS_CONSTANT) + #undef JSON_HEDLEY_IS_CONSTANT +#endif +#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR) + #undef JSON_HEDLEY_REQUIRE_CONSTEXPR +#endif +/* JSON_HEDLEY_IS_CONSTEXPR_ is for + HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ +#if defined(JSON_HEDLEY_IS_CONSTEXPR_) + #undef JSON_HEDLEY_IS_CONSTEXPR_ +#endif +#if \ + JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr) +#endif +#if !defined(__cplusplus) +# if \ + JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24) +#if defined(__INTPTR_TYPE__) + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*) +#else + #include + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*) +#endif +# elif \ + ( \ + defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \ + !defined(JSON_HEDLEY_SUNPRO_VERSION) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_IAR_VERSION)) || \ + (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0) +#if defined(__INTPTR_TYPE__) + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0) +#else + #include + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0) +#endif +# elif \ + defined(JSON_HEDLEY_GCC_VERSION) || \ + defined(JSON_HEDLEY_INTEL_VERSION) || \ + defined(JSON_HEDLEY_TINYC_VERSION) || \ + defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \ + defined(JSON_HEDLEY_TI_CL2000_VERSION) || \ + defined(JSON_HEDLEY_TI_CL6X_VERSION) || \ + defined(JSON_HEDLEY_TI_CL7X_VERSION) || \ + defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \ + defined(__clang__) +# define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \ + sizeof(void) != \ + sizeof(*( \ + 1 ? \ + ((void*) ((expr) * 0L) ) : \ +((struct { char v[sizeof(void) * 2]; } *) 1) \ + ) \ + ) \ + ) +# endif +#endif +#if defined(JSON_HEDLEY_IS_CONSTEXPR_) + #if !defined(JSON_HEDLEY_IS_CONSTANT) + #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr) + #endif + #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1)) +#else + #if !defined(JSON_HEDLEY_IS_CONSTANT) + #define JSON_HEDLEY_IS_CONSTANT(expr) (0) + #endif + #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr) +#endif + +#if defined(JSON_HEDLEY_BEGIN_C_DECLS) + #undef JSON_HEDLEY_BEGIN_C_DECLS +#endif +#if defined(JSON_HEDLEY_END_C_DECLS) + #undef JSON_HEDLEY_END_C_DECLS +#endif +#if defined(JSON_HEDLEY_C_DECL) + #undef JSON_HEDLEY_C_DECL +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" { + #define JSON_HEDLEY_END_C_DECLS } + #define JSON_HEDLEY_C_DECL extern "C" +#else + #define JSON_HEDLEY_BEGIN_C_DECLS + #define JSON_HEDLEY_END_C_DECLS + #define JSON_HEDLEY_C_DECL +#endif + +#if defined(JSON_HEDLEY_STATIC_ASSERT) + #undef JSON_HEDLEY_STATIC_ASSERT +#endif +#if \ + !defined(__cplusplus) && ( \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \ + (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + defined(_Static_assert) \ + ) +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message) +#elif \ + (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ + JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message)) +#else +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) +#endif + +#if defined(JSON_HEDLEY_NULL) + #undef JSON_HEDLEY_NULL +#endif +#if defined(__cplusplus) + #if __cplusplus >= 201103L + #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr) + #elif defined(NULL) + #define JSON_HEDLEY_NULL NULL + #else + #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0) + #endif +#elif defined(NULL) + #define JSON_HEDLEY_NULL NULL +#else + #define JSON_HEDLEY_NULL ((void*) 0) +#endif + +#if defined(JSON_HEDLEY_MESSAGE) + #undef JSON_HEDLEY_MESSAGE +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") +# define JSON_HEDLEY_MESSAGE(msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ + JSON_HEDLEY_PRAGMA(message msg) \ + JSON_HEDLEY_DIAGNOSTIC_POP +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg) +#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg) +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#else +# define JSON_HEDLEY_MESSAGE(msg) +#endif + +#if defined(JSON_HEDLEY_WARNING) + #undef JSON_HEDLEY_WARNING +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") +# define JSON_HEDLEY_WARNING(msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ + JSON_HEDLEY_PRAGMA(clang warning msg) \ + JSON_HEDLEY_DIAGNOSTIC_POP +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#else +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg) +#endif + +#if defined(JSON_HEDLEY_REQUIRE) + #undef JSON_HEDLEY_REQUIRE +#endif +#if defined(JSON_HEDLEY_REQUIRE_MSG) + #undef JSON_HEDLEY_REQUIRE_MSG +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if) +# if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat") +# define JSON_HEDLEY_REQUIRE(expr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ + __attribute__((diagnose_if(!(expr), #expr, "error"))) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ + __attribute__((diagnose_if(!(expr), msg, "error"))) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# else +# define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error"))) +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error"))) +# endif +#else +# define JSON_HEDLEY_REQUIRE(expr) +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) +#endif + +#if defined(JSON_HEDLEY_FLAGS) + #undef JSON_HEDLEY_FLAGS +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion")) + #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__)) +#else + #define JSON_HEDLEY_FLAGS +#endif + +#if defined(JSON_HEDLEY_FLAGS_CAST) + #undef JSON_HEDLEY_FLAGS_CAST +#endif +#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0) +# define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("warning(disable:188)") \ + ((T) (expr)); \ + JSON_HEDLEY_DIAGNOSTIC_POP \ + })) +#else +# define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr) +#endif + +#if defined(JSON_HEDLEY_EMPTY_BASES) + #undef JSON_HEDLEY_EMPTY_BASES +#endif +#if \ + (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases) +#else + #define JSON_HEDLEY_EMPTY_BASES +#endif + +/* Remaining macros are deprecated. */ + +#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK) + #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK +#endif +#if defined(__clang__) + #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0) +#else + #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN) + #undef JSON_HEDLEY_CLANG_HAS_BUILTIN +#endif +#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin) + +#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE) + #undef JSON_HEDLEY_CLANG_HAS_FEATURE +#endif +#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature) + +#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION) + #undef JSON_HEDLEY_CLANG_HAS_EXTENSION +#endif +#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension) + +#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_WARNING) + #undef JSON_HEDLEY_CLANG_HAS_WARNING +#endif +#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning) + +#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */ + + +// This file contains all internal macro definitions (except those affecting ABI) +// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them + +// #include + + +// exclude unsupported compilers +#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) + #if defined(__clang__) + #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 + #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" + #endif + #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) + #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800 + #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" + #endif + #endif +#endif + +// C++ language standard detection +// if the user manually specified the used c++ version this is skipped +#if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11) + #if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) + #define JSON_HAS_CPP_20 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 + #elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 + #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) + #define JSON_HAS_CPP_14 + #endif + // the cpp 11 flag is always specified because it is the minimal required version + #define JSON_HAS_CPP_11 +#endif + +#ifdef __has_include + #if __has_include() + #include + #endif +#endif + +#if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM) + #ifdef JSON_HAS_CPP_17 + #if defined(__cpp_lib_filesystem) + #define JSON_HAS_FILESYSTEM 1 + #elif defined(__cpp_lib_experimental_filesystem) + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 + #elif !defined(__has_include) + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 + #elif __has_include() + #define JSON_HAS_FILESYSTEM 1 + #elif __has_include() + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 + #endif + + // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/ + #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support + #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support + #if defined(__clang_major__) && __clang_major__ < 7 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support + #if defined(_MSC_VER) && _MSC_VER < 1914 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before iOS 13 + #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before macOS Catalina + #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + #endif +#endif + +#ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0 +#endif + +#ifndef JSON_HAS_FILESYSTEM + #define JSON_HAS_FILESYSTEM 0 +#endif + +#ifndef JSON_HAS_THREE_WAY_COMPARISON + #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \ + && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L + #define JSON_HAS_THREE_WAY_COMPARISON 1 + #else + #define JSON_HAS_THREE_WAY_COMPARISON 0 + #endif +#endif + +#ifndef JSON_HAS_RANGES + // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has syntax error + #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427 + #define JSON_HAS_RANGES 0 + #elif defined(__cpp_lib_ranges) + #define JSON_HAS_RANGES 1 + #else + #define JSON_HAS_RANGES 0 + #endif +#endif + +#ifdef JSON_HAS_CPP_17 + #define JSON_INLINE_VARIABLE inline +#else + #define JSON_INLINE_VARIABLE +#endif + +#if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address) + #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]] +#else + #define JSON_NO_UNIQUE_ADDRESS +#endif + +// disable documentation warnings on clang +#if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdocumentation" + #pragma clang diagnostic ignored "-Wdocumentation-unknown-command" +#endif + +// allow disabling exceptions +#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION) + #define JSON_THROW(exception) throw exception + #define JSON_TRY try + #define JSON_CATCH(exception) catch(exception) + #define JSON_INTERNAL_CATCH(exception) catch(exception) +#else + #include + #define JSON_THROW(exception) std::abort() + #define JSON_TRY if(true) + #define JSON_CATCH(exception) if(false) + #define JSON_INTERNAL_CATCH(exception) if(false) +#endif + +// override exception macros +#if defined(JSON_THROW_USER) + #undef JSON_THROW + #define JSON_THROW JSON_THROW_USER +#endif +#if defined(JSON_TRY_USER) + #undef JSON_TRY + #define JSON_TRY JSON_TRY_USER +#endif +#if defined(JSON_CATCH_USER) + #undef JSON_CATCH + #define JSON_CATCH JSON_CATCH_USER + #undef JSON_INTERNAL_CATCH + #define JSON_INTERNAL_CATCH JSON_CATCH_USER +#endif +#if defined(JSON_INTERNAL_CATCH_USER) + #undef JSON_INTERNAL_CATCH + #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER +#endif + +// allow overriding assert +#if !defined(JSON_ASSERT) + #include // assert + #define JSON_ASSERT(x) assert(x) +#endif + +// allow to access some private functions (needed by the test suite) +#if defined(JSON_TESTS_PRIVATE) + #define JSON_PRIVATE_UNLESS_TESTED public +#else + #define JSON_PRIVATE_UNLESS_TESTED private +#endif + +/*! +@brief macro to briefly define a mapping between an enum and JSON +@def NLOHMANN_JSON_SERIALIZE_ENUM +@since version 3.4.0 +*/ +#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ + template \ + inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [e](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.first == e; \ + }); \ + j = ((it != std::end(m)) ? it : std::begin(m))->second; \ + } \ + template \ + inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [&j](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.second == j; \ + }); \ + e = ((it != std::end(m)) ? it : std::begin(m))->first; \ + } + +// Ugly macros to avoid uglier copy-paste when specializing basic_json. They +// may be removed in the future once the class is split. + +#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \ + template class ObjectType, \ + template class ArrayType, \ + class StringType, class BooleanType, class NumberIntegerType, \ + class NumberUnsignedType, class NumberFloatType, \ + template class AllocatorType, \ + template class JSONSerializer, \ + class BinaryType> + +#define NLOHMANN_BASIC_JSON_TPL \ + basic_json + +// Macros to simplify conversion from/to types + +#define NLOHMANN_JSON_EXPAND( x ) x +#define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME +#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \ + NLOHMANN_JSON_PASTE64, \ + NLOHMANN_JSON_PASTE63, \ + NLOHMANN_JSON_PASTE62, \ + NLOHMANN_JSON_PASTE61, \ + NLOHMANN_JSON_PASTE60, \ + NLOHMANN_JSON_PASTE59, \ + NLOHMANN_JSON_PASTE58, \ + NLOHMANN_JSON_PASTE57, \ + NLOHMANN_JSON_PASTE56, \ + NLOHMANN_JSON_PASTE55, \ + NLOHMANN_JSON_PASTE54, \ + NLOHMANN_JSON_PASTE53, \ + NLOHMANN_JSON_PASTE52, \ + NLOHMANN_JSON_PASTE51, \ + NLOHMANN_JSON_PASTE50, \ + NLOHMANN_JSON_PASTE49, \ + NLOHMANN_JSON_PASTE48, \ + NLOHMANN_JSON_PASTE47, \ + NLOHMANN_JSON_PASTE46, \ + NLOHMANN_JSON_PASTE45, \ + NLOHMANN_JSON_PASTE44, \ + NLOHMANN_JSON_PASTE43, \ + NLOHMANN_JSON_PASTE42, \ + NLOHMANN_JSON_PASTE41, \ + NLOHMANN_JSON_PASTE40, \ + NLOHMANN_JSON_PASTE39, \ + NLOHMANN_JSON_PASTE38, \ + NLOHMANN_JSON_PASTE37, \ + NLOHMANN_JSON_PASTE36, \ + NLOHMANN_JSON_PASTE35, \ + NLOHMANN_JSON_PASTE34, \ + NLOHMANN_JSON_PASTE33, \ + NLOHMANN_JSON_PASTE32, \ + NLOHMANN_JSON_PASTE31, \ + NLOHMANN_JSON_PASTE30, \ + NLOHMANN_JSON_PASTE29, \ + NLOHMANN_JSON_PASTE28, \ + NLOHMANN_JSON_PASTE27, \ + NLOHMANN_JSON_PASTE26, \ + NLOHMANN_JSON_PASTE25, \ + NLOHMANN_JSON_PASTE24, \ + NLOHMANN_JSON_PASTE23, \ + NLOHMANN_JSON_PASTE22, \ + NLOHMANN_JSON_PASTE21, \ + NLOHMANN_JSON_PASTE20, \ + NLOHMANN_JSON_PASTE19, \ + NLOHMANN_JSON_PASTE18, \ + NLOHMANN_JSON_PASTE17, \ + NLOHMANN_JSON_PASTE16, \ + NLOHMANN_JSON_PASTE15, \ + NLOHMANN_JSON_PASTE14, \ + NLOHMANN_JSON_PASTE13, \ + NLOHMANN_JSON_PASTE12, \ + NLOHMANN_JSON_PASTE11, \ + NLOHMANN_JSON_PASTE10, \ + NLOHMANN_JSON_PASTE9, \ + NLOHMANN_JSON_PASTE8, \ + NLOHMANN_JSON_PASTE7, \ + NLOHMANN_JSON_PASTE6, \ + NLOHMANN_JSON_PASTE5, \ + NLOHMANN_JSON_PASTE4, \ + NLOHMANN_JSON_PASTE3, \ + NLOHMANN_JSON_PASTE2, \ + NLOHMANN_JSON_PASTE1)(__VA_ARGS__)) +#define NLOHMANN_JSON_PASTE2(func, v1) func(v1) +#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2) +#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3) +#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4) +#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5) +#define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6) +#define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7) +#define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8) +#define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9) +#define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10) +#define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) +#define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) +#define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) +#define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) +#define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) +#define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) +#define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) +#define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) +#define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) +#define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) +#define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) +#define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) +#define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) +#define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) +#define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) +#define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) +#define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) +#define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) +#define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) +#define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) +#define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) +#define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) +#define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) +#define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) +#define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) +#define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) +#define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) +#define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) +#define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) +#define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) +#define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) +#define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) +#define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) +#define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) +#define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) +#define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) +#define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) +#define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) +#define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) +#define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) +#define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) +#define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) +#define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) +#define NLOHMANN_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) +#define NLOHMANN_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) +#define NLOHMANN_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) +#define NLOHMANN_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) +#define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) +#define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) +#define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) +#define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) +#define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) +#define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) + +#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1; +#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1); +#define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1); + +/*! +@brief macro +@def NLOHMANN_DEFINE_TYPE_INTRUSIVE +@since version 3.9.0 +*/ +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \ + friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } + +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \ + friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { Type nlohmann_json_default_obj; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } + +/*! +@brief macro +@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE +@since version 3.9.0 +*/ +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \ + inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } + +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \ + inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { Type nlohmann_json_default_obj; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } + + +// inspired from https://stackoverflow.com/a/26745591 +// allows to call any std function as if (e.g. with begin): +// using std::begin; begin(x); +// +// it allows using the detected idiom to retrieve the return type +// of such an expression +#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \ + namespace detail { \ + using std::std_name; \ + \ + template \ + using result_of_##std_name = decltype(std_name(std::declval()...)); \ + } \ + \ + namespace detail2 { \ + struct std_name##_tag \ + { \ + }; \ + \ + template \ + std_name##_tag std_name(T&&...); \ + \ + template \ + using result_of_##std_name = decltype(std_name(std::declval()...)); \ + \ + template \ + struct would_call_std_##std_name \ + { \ + static constexpr auto const value = ::nlohmann::detail:: \ + is_detected_exact::value; \ + }; \ + } /* namespace detail2 */ \ + \ + template \ + struct would_call_std_##std_name : detail2::would_call_std_##std_name \ + { \ + } + +#ifndef JSON_USE_IMPLICIT_CONVERSIONS + #define JSON_USE_IMPLICIT_CONVERSIONS 1 +#endif + +#if JSON_USE_IMPLICIT_CONVERSIONS + #define JSON_EXPLICIT +#else + #define JSON_EXPLICIT explicit +#endif + +#ifndef JSON_DISABLE_ENUM_SERIALIZATION + #define JSON_DISABLE_ENUM_SERIALIZATION 0 +#endif + +#ifndef JSON_USE_GLOBAL_UDLS + #define JSON_USE_GLOBAL_UDLS 1 +#endif + +#if JSON_HAS_THREE_WAY_COMPARISON + #include // partial_ordering +#endif + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +/////////////////////////// +// JSON type enumeration // +/////////////////////////// + +/*! +@brief the JSON type enumeration + +This enumeration collects the different JSON types. It is internally used to +distinguish the stored values, and the functions @ref basic_json::is_null(), +@ref basic_json::is_object(), @ref basic_json::is_array(), +@ref basic_json::is_string(), @ref basic_json::is_boolean(), +@ref basic_json::is_number() (with @ref basic_json::is_number_integer(), +@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()), +@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and +@ref basic_json::is_structured() rely on it. + +@note There are three enumeration entries (number_integer, number_unsigned, and +number_float), because the library distinguishes these three types for numbers: +@ref basic_json::number_unsigned_t is used for unsigned integers, +@ref basic_json::number_integer_t is used for signed integers, and +@ref basic_json::number_float_t is used for floating-point numbers or to +approximate integers which do not fit in the limits of their respective type. + +@sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON +value with the default value for a given type + +@since version 1.0.0 +*/ +enum class value_t : std::uint8_t +{ + null, ///< null value + object, ///< object (unordered set of name/value pairs) + array, ///< array (ordered collection of values) + string, ///< string value + boolean, ///< boolean value + number_integer, ///< number value (signed integer) + number_unsigned, ///< number value (unsigned integer) + number_float, ///< number value (floating-point) + binary, ///< binary array (ordered collection of bytes) + discarded ///< discarded by the parser callback function +}; + +/*! +@brief comparison operator for JSON types + +Returns an ordering that is similar to Python: +- order: null < boolean < number < object < array < string < binary +- furthermore, each type is not smaller than itself +- discarded values are not comparable +- binary is represented as a b"" string in python and directly comparable to a + string; however, making a binary array directly comparable with a string would + be surprising behavior in a JSON file. + +@since version 1.0.0 +*/ +#if JSON_HAS_THREE_WAY_COMPARISON + inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD* +#else + inline bool operator<(const value_t lhs, const value_t rhs) noexcept +#endif +{ + static constexpr std::array order = {{ + 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */, + 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */, + 6 /* binary */ + } + }; + + const auto l_index = static_cast(lhs); + const auto r_index = static_cast(rhs); +#if JSON_HAS_THREE_WAY_COMPARISON + if (l_index < order.size() && r_index < order.size()) + { + return order[l_index] <=> order[r_index]; // *NOPAD* + } + return std::partial_ordering::unordered; +#else + return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index]; +#endif +} + +// GCC selects the built-in operator< over an operator rewritten from +// a user-defined spaceship operator +// Clang, MSVC, and ICC select the rewritten candidate +// (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200) +#if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__) +inline bool operator<(const value_t lhs, const value_t rhs) noexcept +{ + return std::is_lt(lhs <=> rhs); // *NOPAD* +} +#endif + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +/*! +@brief replace all occurrences of a substring by another string + +@param[in,out] s the string to manipulate; changed so that all + occurrences of @a f are replaced with @a t +@param[in] f the substring to replace with @a t +@param[in] t the string to replace @a f + +@pre The search string @a f must not be empty. **This precondition is +enforced with an assertion.** + +@since version 2.0.0 +*/ +template +inline void replace_substring(StringType& s, const StringType& f, + const StringType& t) +{ + JSON_ASSERT(!f.empty()); + for (auto pos = s.find(f); // find first occurrence of f + pos != StringType::npos; // make sure f was found + s.replace(pos, f.size(), t), // replace with t, and + pos = s.find(f, pos + t.size())) // find next occurrence of f + {} +} + +/*! + * @brief string escaping as described in RFC 6901 (Sect. 4) + * @param[in] s string to escape + * @return escaped string + * + * Note the order of escaping "~" to "~0" and "/" to "~1" is important. + */ +template +inline StringType escape(StringType s) +{ + replace_substring(s, StringType{"~"}, StringType{"~0"}); + replace_substring(s, StringType{"/"}, StringType{"~1"}); + return s; +} + +/*! + * @brief string unescaping as described in RFC 6901 (Sect. 4) + * @param[in] s string to unescape + * @return unescaped string + * + * Note the order of escaping "~1" to "/" and "~0" to "~" is important. + */ +template +static void unescape(StringType& s) +{ + replace_substring(s, StringType{"~1"}, StringType{"/"}); + replace_substring(s, StringType{"~0"}, StringType{"~"}); +} + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // size_t + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +/// struct to capture the start position of the current token +struct position_t +{ + /// the total number of characters read + std::size_t chars_read_total = 0; + /// the number of characters read in the current line + std::size_t chars_read_current_line = 0; + /// the number of lines read + std::size_t lines_read = 0; + + /// conversion to size_t to preserve SAX interface + constexpr operator size_t() const + { + return chars_read_total; + } +}; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-FileCopyrightText: 2018 The Abseil Authors +// SPDX-License-Identifier: MIT + + + +#include // array +#include // size_t +#include // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type +#include // index_sequence, make_index_sequence, index_sequence_for + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +template +using uncvref_t = typename std::remove_cv::type>::type; + +#ifdef JSON_HAS_CPP_14 + +// the following utilities are natively available in C++14 +using std::enable_if_t; +using std::index_sequence; +using std::make_index_sequence; +using std::index_sequence_for; + +#else + +// alias templates to reduce boilerplate +template +using enable_if_t = typename std::enable_if::type; + +// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h +// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0. + +//// START OF CODE FROM GOOGLE ABSEIL + +// integer_sequence +// +// Class template representing a compile-time integer sequence. An instantiation +// of `integer_sequence` has a sequence of integers encoded in its +// type through its template arguments (which is a common need when +// working with C++11 variadic templates). `absl::integer_sequence` is designed +// to be a drop-in replacement for C++14's `std::integer_sequence`. +// +// Example: +// +// template< class T, T... Ints > +// void user_function(integer_sequence); +// +// int main() +// { +// // user_function's `T` will be deduced to `int` and `Ints...` +// // will be deduced to `0, 1, 2, 3, 4`. +// user_function(make_integer_sequence()); +// } +template +struct integer_sequence +{ + using value_type = T; + static constexpr std::size_t size() noexcept + { + return sizeof...(Ints); + } +}; + +// index_sequence +// +// A helper template for an `integer_sequence` of `size_t`, +// `absl::index_sequence` is designed to be a drop-in replacement for C++14's +// `std::index_sequence`. +template +using index_sequence = integer_sequence; + +namespace utility_internal +{ + +template +struct Extend; + +// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency. +template +struct Extend, SeqSize, 0> +{ + using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >; +}; + +template +struct Extend, SeqSize, 1> +{ + using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >; +}; + +// Recursion helper for 'make_integer_sequence'. +// 'Gen::type' is an alias for 'integer_sequence'. +template +struct Gen +{ + using type = + typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type; +}; + +template +struct Gen +{ + using type = integer_sequence; +}; + +} // namespace utility_internal + +// Compile-time sequences of integers + +// make_integer_sequence +// +// This template alias is equivalent to +// `integer_sequence`, and is designed to be a drop-in +// replacement for C++14's `std::make_integer_sequence`. +template +using make_integer_sequence = typename utility_internal::Gen::type; + +// make_index_sequence +// +// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`, +// and is designed to be a drop-in replacement for C++14's +// `std::make_index_sequence`. +template +using make_index_sequence = make_integer_sequence; + +// index_sequence_for +// +// Converts a typename pack into an index sequence of the same length, and +// is designed to be a drop-in replacement for C++14's +// `std::index_sequence_for()` +template +using index_sequence_for = make_index_sequence; + +//// END OF CODE FROM GOOGLE ABSEIL + +#endif + +// dispatch utility (taken from ranges-v3) +template struct priority_tag : priority_tag < N - 1 > {}; +template<> struct priority_tag<0> {}; + +// taken from ranges-v3 +template +struct static_const +{ + static JSON_INLINE_VARIABLE constexpr T value{}; +}; + +#ifndef JSON_HAS_CPP_17 + template + constexpr T static_const::value; +#endif + +template +inline constexpr std::array make_array(Args&& ... args) +{ + return std::array {{static_cast(std::forward(args))...}}; +} + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // numeric_limits +#include // false_type, is_constructible, is_integral, is_same, true_type +#include // declval +#include // tuple + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // random_access_iterator_tag + +// #include + +// #include + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +template +struct iterator_types {}; + +template +struct iterator_types < + It, + void_t> +{ + using difference_type = typename It::difference_type; + using value_type = typename It::value_type; + using pointer = typename It::pointer; + using reference = typename It::reference; + using iterator_category = typename It::iterator_category; +}; + +// This is required as some compilers implement std::iterator_traits in a way that +// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341. +template +struct iterator_traits +{ +}; + +template +struct iterator_traits < T, enable_if_t < !std::is_pointer::value >> + : iterator_types +{ +}; + +template +struct iterator_traits::value>> +{ + using iterator_category = std::random_access_iterator_tag; + using value_type = T; + using difference_type = ptrdiff_t; + using pointer = T*; + using reference = T&; +}; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN + +NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin); + +NLOHMANN_JSON_NAMESPACE_END + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN + +NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end); + +NLOHMANN_JSON_NAMESPACE_END + +// #include + +// #include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + +#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_ + #define INCLUDE_NLOHMANN_JSON_FWD_HPP_ + + #include // int64_t, uint64_t + #include // map + #include // allocator + #include // string + #include // vector + + // #include + + + /*! + @brief namespace for Niels Lohmann + @see https://github.com/nlohmann + @since version 1.0.0 + */ + NLOHMANN_JSON_NAMESPACE_BEGIN + + /*! + @brief default JSONSerializer template argument + + This serializer ignores the template arguments and uses ADL + ([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl)) + for serialization. + */ + template + struct adl_serializer; + + /// a class to store JSON values + /// @sa https://json.nlohmann.me/api/basic_json/ + template class ObjectType = + std::map, + template class ArrayType = std::vector, + class StringType = std::string, class BooleanType = bool, + class NumberIntegerType = std::int64_t, + class NumberUnsignedType = std::uint64_t, + class NumberFloatType = double, + template class AllocatorType = std::allocator, + template class JSONSerializer = + adl_serializer, + class BinaryType = std::vector> + class basic_json; + + /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document + /// @sa https://json.nlohmann.me/api/json_pointer/ + template + class json_pointer; + + /*! + @brief default specialization + @sa https://json.nlohmann.me/api/json/ + */ + using json = basic_json<>; + + /// @brief a minimal map-like container that preserves insertion order + /// @sa https://json.nlohmann.me/api/ordered_map/ + template + struct ordered_map; + + /// @brief specialization that maintains the insertion order of object keys + /// @sa https://json.nlohmann.me/api/ordered_json/ + using ordered_json = basic_json; + + NLOHMANN_JSON_NAMESPACE_END + +#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_ + + +NLOHMANN_JSON_NAMESPACE_BEGIN +/*! +@brief detail namespace with internal helper functions + +This namespace collects functions that should not be exposed, +implementations of some @ref basic_json methods, and meta-programming helpers. + +@since version 2.1.0 +*/ +namespace detail +{ + +///////////// +// helpers // +///////////// + +// Note to maintainers: +// +// Every trait in this file expects a non CV-qualified type. +// The only exceptions are in the 'aliases for detected' section +// (i.e. those of the form: decltype(T::member_function(std::declval()))) +// +// In this case, T has to be properly CV-qualified to constraint the function arguments +// (e.g. to_json(BasicJsonType&, const T&)) + +template struct is_basic_json : std::false_type {}; + +NLOHMANN_BASIC_JSON_TPL_DECLARATION +struct is_basic_json : std::true_type {}; + +// used by exceptions create() member functions +// true_type for pointer to possibly cv-qualified basic_json or std::nullptr_t +// false_type otherwise +template +struct is_basic_json_context : + std::integral_constant < bool, + is_basic_json::type>::type>::value + || std::is_same::value > +{}; + +////////////////////// +// json_ref helpers // +////////////////////// + +template +class json_ref; + +template +struct is_json_ref : std::false_type {}; + +template +struct is_json_ref> : std::true_type {}; + +////////////////////////// +// aliases for detected // +////////////////////////// + +template +using mapped_type_t = typename T::mapped_type; + +template +using key_type_t = typename T::key_type; + +template +using value_type_t = typename T::value_type; + +template +using difference_type_t = typename T::difference_type; + +template +using pointer_t = typename T::pointer; + +template +using reference_t = typename T::reference; + +template +using iterator_category_t = typename T::iterator_category; + +template +using to_json_function = decltype(T::to_json(std::declval()...)); + +template +using from_json_function = decltype(T::from_json(std::declval()...)); + +template +using get_template_function = decltype(std::declval().template get()); + +// trait checking if JSONSerializer::from_json(json const&, udt&) exists +template +struct has_from_json : std::false_type {}; + +// trait checking if j.get is valid +// use this trait instead of std::is_constructible or std::is_convertible, +// both rely on, or make use of implicit conversions, and thus fail when T +// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958) +template +struct is_getable +{ + static constexpr bool value = is_detected::value; +}; + +template +struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> +{ + using serializer = typename BasicJsonType::template json_serializer; + + static constexpr bool value = + is_detected_exact::value; +}; + +// This trait checks if JSONSerializer::from_json(json const&) exists +// this overload is used for non-default-constructible user-defined-types +template +struct has_non_default_from_json : std::false_type {}; + +template +struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> +{ + using serializer = typename BasicJsonType::template json_serializer; + + static constexpr bool value = + is_detected_exact::value; +}; + +// This trait checks if BasicJsonType::json_serializer::to_json exists +// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion. +template +struct has_to_json : std::false_type {}; + +template +struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> +{ + using serializer = typename BasicJsonType::template json_serializer; + + static constexpr bool value = + is_detected_exact::value; +}; + +template +using detect_key_compare = typename T::key_compare; + +template +struct has_key_compare : std::integral_constant::value> {}; + +// obtains the actual object key comparator +template +struct actual_object_comparator +{ + using object_t = typename BasicJsonType::object_t; + using object_comparator_t = typename BasicJsonType::default_object_comparator_t; + using type = typename std::conditional < has_key_compare::value, + typename object_t::key_compare, object_comparator_t>::type; +}; + +template +using actual_object_comparator_t = typename actual_object_comparator::type; + +/////////////////// +// is_ functions // +/////////////////// + +// https://en.cppreference.com/w/cpp/types/conjunction +template struct conjunction : std::true_type { }; +template struct conjunction : B { }; +template +struct conjunction +: std::conditional(B::value), conjunction, B>::type {}; + +// https://en.cppreference.com/w/cpp/types/negation +template struct negation : std::integral_constant < bool, !B::value > { }; + +// Reimplementation of is_constructible and is_default_constructible, due to them being broken for +// std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367). +// This causes compile errors in e.g. clang 3.5 or gcc 4.9. +template +struct is_default_constructible : std::is_default_constructible {}; + +template +struct is_default_constructible> + : conjunction, is_default_constructible> {}; + +template +struct is_default_constructible> + : conjunction, is_default_constructible> {}; + +template +struct is_default_constructible> + : conjunction...> {}; + +template +struct is_default_constructible> + : conjunction...> {}; + + +template +struct is_constructible : std::is_constructible {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_constructible> : is_default_constructible> {}; + + +template +struct is_iterator_traits : std::false_type {}; + +template +struct is_iterator_traits> +{ + private: + using traits = iterator_traits; + + public: + static constexpr auto value = + is_detected::value && + is_detected::value && + is_detected::value && + is_detected::value && + is_detected::value; +}; + +template +struct is_range +{ + private: + using t_ref = typename std::add_lvalue_reference::type; + + using iterator = detected_t; + using sentinel = detected_t; + + // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator + // and https://en.cppreference.com/w/cpp/iterator/sentinel_for + // but reimplementing these would be too much work, as a lot of other concepts are used underneath + static constexpr auto is_iterator_begin = + is_iterator_traits>::value; + + public: + static constexpr bool value = !std::is_same::value && !std::is_same::value && is_iterator_begin; +}; + +template +using iterator_t = enable_if_t::value, result_of_begin())>>; + +template +using range_value_t = value_type_t>>; + +// The following implementation of is_complete_type is taken from +// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/ +// and is written by Xiang Fan who agreed to using it in this library. + +template +struct is_complete_type : std::false_type {}; + +template +struct is_complete_type : std::true_type {}; + +template +struct is_compatible_object_type_impl : std::false_type {}; + +template +struct is_compatible_object_type_impl < + BasicJsonType, CompatibleObjectType, + enable_if_t < is_detected::value&& + is_detected::value >> +{ + using object_t = typename BasicJsonType::object_t; + + // macOS's is_constructible does not play well with nonesuch... + static constexpr bool value = + is_constructible::value && + is_constructible::value; +}; + +template +struct is_compatible_object_type + : is_compatible_object_type_impl {}; + +template +struct is_constructible_object_type_impl : std::false_type {}; + +template +struct is_constructible_object_type_impl < + BasicJsonType, ConstructibleObjectType, + enable_if_t < is_detected::value&& + is_detected::value >> +{ + using object_t = typename BasicJsonType::object_t; + + static constexpr bool value = + (is_default_constructible::value && + (std::is_move_assignable::value || + std::is_copy_assignable::value) && + (is_constructible::value && + std::is_same < + typename object_t::mapped_type, + typename ConstructibleObjectType::mapped_type >::value)) || + (has_from_json::value || + has_non_default_from_json < + BasicJsonType, + typename ConstructibleObjectType::mapped_type >::value); +}; + +template +struct is_constructible_object_type + : is_constructible_object_type_impl {}; + +template +struct is_compatible_string_type +{ + static constexpr auto value = + is_constructible::value; +}; + +template +struct is_constructible_string_type +{ + // launder type through decltype() to fix compilation failure on ICPC +#ifdef __INTEL_COMPILER + using laundered_type = decltype(std::declval()); +#else + using laundered_type = ConstructibleStringType; +#endif + + static constexpr auto value = + conjunction < + is_constructible, + is_detected_exact>::value; +}; + +template +struct is_compatible_array_type_impl : std::false_type {}; + +template +struct is_compatible_array_type_impl < + BasicJsonType, CompatibleArrayType, + enable_if_t < + is_detected::value&& + is_iterator_traits>>::value&& +// special case for types like std::filesystem::path whose iterator's value_type are themselves +// c.f. https://github.com/nlohmann/json/pull/3073 + !std::is_same>::value >> +{ + static constexpr bool value = + is_constructible>::value; +}; + +template +struct is_compatible_array_type + : is_compatible_array_type_impl {}; + +template +struct is_constructible_array_type_impl : std::false_type {}; + +template +struct is_constructible_array_type_impl < + BasicJsonType, ConstructibleArrayType, + enable_if_t::value >> + : std::true_type {}; + +template +struct is_constructible_array_type_impl < + BasicJsonType, ConstructibleArrayType, + enable_if_t < !std::is_same::value&& + !is_compatible_string_type::value&& + is_default_constructible::value&& +(std::is_move_assignable::value || + std::is_copy_assignable::value)&& +is_detected::value&& +is_iterator_traits>>::value&& +is_detected::value&& +// special case for types like std::filesystem::path whose iterator's value_type are themselves +// c.f. https://github.com/nlohmann/json/pull/3073 +!std::is_same>::value&& + is_complete_type < + detected_t>::value >> +{ + using value_type = range_value_t; + + static constexpr bool value = + std::is_same::value || + has_from_json::value || + has_non_default_from_json < + BasicJsonType, + value_type >::value; +}; + +template +struct is_constructible_array_type + : is_constructible_array_type_impl {}; + +template +struct is_compatible_integer_type_impl : std::false_type {}; + +template +struct is_compatible_integer_type_impl < + RealIntegerType, CompatibleNumberIntegerType, + enable_if_t < std::is_integral::value&& + std::is_integral::value&& + !std::is_same::value >> +{ + // is there an assert somewhere on overflows? + using RealLimits = std::numeric_limits; + using CompatibleLimits = std::numeric_limits; + + static constexpr auto value = + is_constructible::value && + CompatibleLimits::is_integer && + RealLimits::is_signed == CompatibleLimits::is_signed; +}; + +template +struct is_compatible_integer_type + : is_compatible_integer_type_impl {}; + +template +struct is_compatible_type_impl: std::false_type {}; + +template +struct is_compatible_type_impl < + BasicJsonType, CompatibleType, + enable_if_t::value >> +{ + static constexpr bool value = + has_to_json::value; +}; + +template +struct is_compatible_type + : is_compatible_type_impl {}; + +template +struct is_constructible_tuple : std::false_type {}; + +template +struct is_constructible_tuple> : conjunction...> {}; + +template +struct is_json_iterator_of : std::false_type {}; + +template +struct is_json_iterator_of : std::true_type {}; + +template +struct is_json_iterator_of : std::true_type +{}; + +// checks if a given type T is a template specialization of Primary +template