react-native-executorch 0.10.5 → 0.10.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -1
- package/android/build.gradle.kts +4 -3
- package/ios/RnExecutorch.mm +15 -17
- package/lib/module/fetcher/fetcher.js +35 -122
- package/lib/module/fetcher/fetcher.js.map +1 -1
- package/lib/module/fetcher/telemetry.js +1 -1
- package/lib/module/index.js +12 -13
- package/lib/module/index.js.map +1 -1
- package/lib/module/models.js +4 -2
- package/lib/module/models.js.map +1 -1
- package/lib/typescript/src/fetcher/fetcher.d.ts +3 -7
- package/lib/typescript/src/fetcher/fetcher.d.ts.map +1 -1
- package/lib/typescript/src/models.d.ts.map +1 -1
- package/package.json +9 -7
- package/react-native-executorch.podspec +6 -2
- package/src/fetcher/fetcher.ts +38 -131
- package/src/fetcher/telemetry.ts +1 -1
- package/src/models.ts +6 -1
- package/third-party/common/phonemis/CMakeLists.txt +70 -14
- package/third-party/common/phonemis/README.md +183 -33
- package/third-party/common/phonemis/THIRD_PARTY_NOTICES.md +57 -0
- package/third-party/common/phonemis/knowledge/code_style.md +642 -0
- package/third-party/common/phonemis/licenses/Unicode-3.0.txt +39 -0
- package/third-party/common/phonemis/licenses/misaki-Apache-2.0.txt +201 -0
- package/third-party/common/phonemis/licenses/nlohmann-json-MIT.txt +21 -0
- package/third-party/common/phonemis/licenses/xsimd-BSD-3-Clause.txt +29 -0
- package/third-party/common/phonemis/src/phonemis/base/config.h +6 -0
- package/third-party/common/phonemis/src/phonemis/base/ipipeline.cpp +75 -0
- package/third-party/common/phonemis/src/phonemis/base/ipipeline.h +21 -0
- package/third-party/common/phonemis/src/phonemis/base/phonemizer/constants.h +2 -5
- package/third-party/common/phonemis/src/phonemis/base/phonemizer/lexicon_phonemizer.cpp +3 -4
- package/third-party/common/phonemis/src/phonemis/base/phonemizer/nn/neural_phonemizer.cpp +17 -8
- package/third-party/common/phonemis/src/phonemis/base/phonemizer/nn/neural_phonemizer.h +4 -0
- package/third-party/common/phonemis/src/phonemis/base/phonemizer/nn/tokenizer.cpp +21 -6
- package/third-party/common/phonemis/src/phonemis/base/phonemizer/nn/tokenizer.h +13 -4
- package/third-party/common/phonemis/src/phonemis/base/pipeline.cpp +8 -0
- package/third-party/common/phonemis/src/phonemis/base/pipeline.h +19 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/common/conditions.cpp +37 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/common/conditions.h +45 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/common/constants.h +10 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/common/context.cpp +105 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/common/context.h +49 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/common/document.cpp +173 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/common/document.h +67 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/common/text.cpp +75 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/common/text.h +60 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/common/types.h +18 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/config.h +53 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/layer.h +9 -7
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/normalize/constants.h +20 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/normalize/layer.cpp +89 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/normalize/layer.h +35 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/normalize/types.h +16 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/kind.h +40 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/layer.h +382 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/notation.h +30 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/numerals.cpp +51 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/numerals.h +31 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/pattern.h +30 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/pattern_set.cpp +17 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/pattern_set.h +31 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/patterns.cpp +811 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/patterns.h +285 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/primitives.cpp +64 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/primitives.h +23 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/num2word/types.h +94 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/sanitizer/layer.cpp +19 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/{sanitizer_layer.h → layers/sanitizer/layer.h} +8 -8
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/sym2word/layer.cpp +65 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/sym2word/layer.h +29 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/term2word/layer.cpp +170 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/term2word/layer.h +40 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/term2word/types.h +25 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/trim/layer.cpp +47 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/layers/trim/layer.h +19 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/preprocessor.cpp +60 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/preprocessor.h +45 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/processor.cpp +6 -7
- package/third-party/common/phonemis/src/phonemis/base/processor/processor.h +14 -10
- package/third-party/common/phonemis/src/phonemis/base/tagger/hmm_tagger.cpp +89 -52
- package/third-party/common/phonemis/src/phonemis/base/tagger/hmm_tagger.h +16 -9
- package/third-party/common/phonemis/src/phonemis/base/tokenizer/tokenizer.cpp +13 -12
- package/third-party/common/phonemis/src/phonemis/lang/de/constants.h +183 -19
- package/third-party/common/phonemis/src/phonemis/lang/de/num2word.cpp +355 -309
- package/third-party/common/phonemis/src/phonemis/lang/de/num2word.h +42 -17
- package/third-party/common/phonemis/src/phonemis/lang/de/patterns.cpp +56 -0
- package/third-party/common/phonemis/src/phonemis/lang/de/patterns.h +15 -0
- package/third-party/common/phonemis/src/phonemis/lang/de/pipeline.h +3 -3
- package/third-party/common/phonemis/src/phonemis/lang/en/constants.h +181 -30
- package/third-party/common/phonemis/src/phonemis/lang/en/hmm_tagger.cpp +5 -7
- package/third-party/common/phonemis/src/phonemis/lang/en/num2word.cpp +232 -135
- package/third-party/common/phonemis/src/phonemis/lang/en/num2word.h +41 -16
- package/third-party/common/phonemis/src/phonemis/lang/en/pipeline.h +3 -10
- package/third-party/common/phonemis/src/phonemis/lang/es/constants.h +182 -60
- package/third-party/common/phonemis/src/phonemis/lang/es/num2word.cpp +247 -212
- package/third-party/common/phonemis/src/phonemis/lang/es/num2word.h +38 -18
- package/third-party/common/phonemis/src/phonemis/lang/es/patterns.cpp +50 -0
- package/third-party/common/phonemis/src/phonemis/lang/es/patterns.h +15 -0
- package/third-party/common/phonemis/src/phonemis/lang/es/pipeline.h +3 -3
- package/third-party/common/phonemis/src/phonemis/lang/fr/constants.h +152 -26
- package/third-party/common/phonemis/src/phonemis/lang/fr/num2word.cpp +252 -179
- package/third-party/common/phonemis/src/phonemis/lang/fr/num2word.h +38 -15
- package/third-party/common/phonemis/src/phonemis/lang/fr/patterns.cpp +83 -0
- package/third-party/common/phonemis/src/phonemis/lang/fr/patterns.h +15 -0
- package/third-party/common/phonemis/src/phonemis/lang/fr/pipeline.h +3 -3
- package/third-party/common/phonemis/src/phonemis/lang/hi/constants.h +62 -10
- package/third-party/common/phonemis/src/phonemis/lang/hi/num2word.cpp +74 -123
- package/third-party/common/phonemis/src/phonemis/lang/hi/num2word.h +27 -16
- package/third-party/common/phonemis/src/phonemis/lang/hi/pipeline.h +5 -3
- package/third-party/common/phonemis/src/phonemis/lang/it/constants.h +122 -42
- package/third-party/common/phonemis/src/phonemis/lang/it/num2word.cpp +200 -207
- package/third-party/common/phonemis/src/phonemis/lang/it/num2word.h +30 -18
- package/third-party/common/phonemis/src/phonemis/lang/it/patterns.cpp +25 -0
- package/third-party/common/phonemis/src/phonemis/lang/it/patterns.h +15 -0
- package/third-party/common/phonemis/src/phonemis/lang/it/pipeline.h +3 -3
- package/third-party/common/phonemis/src/phonemis/lang/pl/constants.h +346 -77
- package/third-party/common/phonemis/src/phonemis/lang/pl/num2word.cpp +631 -246
- package/third-party/common/phonemis/src/phonemis/lang/pl/num2word.h +47 -15
- package/third-party/common/phonemis/src/phonemis/lang/pl/pipeline.h +6 -6
- package/third-party/common/phonemis/src/phonemis/lang/pt/constants.h +201 -0
- package/third-party/common/phonemis/src/phonemis/lang/pt/num2word.cpp +365 -0
- package/third-party/common/phonemis/src/phonemis/lang/pt/num2word.h +53 -0
- package/third-party/common/phonemis/src/phonemis/lang/pt/pipeline.h +4 -2
- package/third-party/common/phonemis/src/phonemis/main.cpp +42 -11
- package/third-party/common/phonemis/src/phonemis/protophone/meta.h +24 -0
- package/third-party/common/phonemis/src/phonemis/protophone/numeric.h +26 -0
- package/third-party/common/phonemis/src/phonemis/protophone/protophone.cpp +525 -0
- package/third-party/common/phonemis/src/phonemis/protophone/protophone.h +80 -0
- package/third-party/common/phonemis/src/phonemis/protophone/tensor.h +76 -0
- package/third-party/common/phonemis/src/phonemis/protophone/tensor_utils.h +89 -0
- package/third-party/common/phonemis/src/phonemis/protophone/tensor_view.h +125 -0
- package/third-party/common/phonemis/src/phonemis/protophone/types.h +43 -0
- package/third-party/common/phonemis/src/phonemis/utils/strings.h +20 -14
- package/third-party/common/phonemis/src/phonemis/utils/unicode.h +15 -1
- package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_arithmetic.hpp +267 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_bit.hpp +232 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_cast.hpp +43 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_complex.hpp +112 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_details.hpp +386 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_logical.hpp +240 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_math.hpp +2601 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_memory.hpp +1006 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_rounding.hpp +72 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_swizzle.hpp +260 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/common/xsimd_common_trigo.hpp +996 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/utils/shifts.hpp +82 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx.hpp +2111 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx2.hpp +1591 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx2_128.hpp +170 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512bw.hpp +724 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512cd.hpp +28 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512dq.hpp +270 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512er.hpp +17 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512f.hpp +2919 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512ifma.hpp +17 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512pf.hpp +17 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512vbmi.hpp +76 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512vbmi2.hpp +130 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512vnni_avx512bw.hpp +17 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx512vnni_avx512vbmi2.hpp +17 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avx_128.hpp +164 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_avxvnni.hpp +17 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_common.hpp +26 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_common_fwd.hpp +127 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_constants.hpp +393 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_emulated.hpp +787 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_fma3_avx.hpp +93 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_fma3_avx2.hpp +46 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_fma3_sse.hpp +97 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_fma4.hpp +92 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_i8mm_neon64.hpp +17 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_isa.hpp +148 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_neon.hpp +3580 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_neon64.hpp +1614 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_rvv.hpp +1515 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_scalar.hpp +1210 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_sse2.hpp +2333 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_sse3.hpp +66 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_sse4_1.hpp +510 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_sse4_2.hpp +44 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_ssse3.hpp +186 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_sve.hpp +1186 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_vsx.hpp +947 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_vxe.hpp +787 -0
- package/third-party/common/phonemis/src/third-party/xsimd/arch/xsimd_wasm.hpp +1819 -0
- package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_arch.hpp +242 -0
- package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_config.hpp +633 -0
- package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_cpu_features.hpp +50 -0
- package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_cpu_features_arm.hpp +132 -0
- package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_cpu_features_ppc.hpp +54 -0
- package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_cpu_features_riscv.hpp +95 -0
- package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_cpu_features_s390x.hpp +56 -0
- package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_cpu_features_x86.hpp +1121 -0
- package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_cpuid.hpp +144 -0
- package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_getauxval.hpp +159 -0
- package/third-party/common/phonemis/src/third-party/xsimd/config/xsimd_macros.hpp +78 -0
- package/third-party/common/phonemis/src/third-party/xsimd/math/xsimd_rem_pio2.hpp +707 -0
- package/third-party/common/phonemis/src/third-party/xsimd/memory/xsimd_aligned_allocator.hpp +349 -0
- package/third-party/common/phonemis/src/third-party/xsimd/memory/xsimd_alignment.hpp +102 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_all_registers.hpp +57 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_api.hpp +3106 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx2_register.hpp +57 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512bw_register.hpp +51 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512cd_register.hpp +51 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512dq_register.hpp +51 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512er_register.hpp +51 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512f_register.hpp +77 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512ifma_register.hpp +51 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512pf_register.hpp +51 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512vbmi2_register.hpp +51 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512vbmi_register.hpp +51 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512vnni_avx512bw_register.hpp +54 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx512vnni_avx512vbmi2_register.hpp +53 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avx_register.hpp +79 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_avxvnni_register.hpp +44 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_batch.hpp +1666 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_batch_constant.hpp +572 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_batch_fwd.hpp +41 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_common_arch.hpp +49 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_emulated_register.hpp +80 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_fma3_avx2_register.hpp +50 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_fma3_avx_register.hpp +50 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_fma3_sse_register.hpp +50 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_fma4_register.hpp +50 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_i8mm_neon64_register.hpp +55 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_neon64_register.hpp +55 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_neon_register.hpp +130 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_register.hpp +96 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_rvv_register.hpp +491 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_sse2_register.hpp +59 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_sse3_register.hpp +49 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_sse4_1_register.hpp +48 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_sse4_2_register.hpp +48 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_ssse3_register.hpp +48 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_sve_register.hpp +216 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_traits.hpp +409 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_utils.hpp +462 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_vsx_register.hpp +84 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_vxe_register.hpp +86 -0
- package/third-party/common/phonemis/src/third-party/xsimd/types/xsimd_wasm_register.hpp +59 -0
- package/third-party/common/phonemis/src/third-party/xsimd/utils/bits.hpp +122 -0
- package/third-party/common/phonemis/src/third-party/xsimd/utils/xsimd_type_traits.hpp +145 -0
- package/third-party/common/phonemis/src/third-party/xsimd/xsimd.hpp +43 -0
- package/third-party/common/phonemis/src/phonemis/base/processor/constants.h +0 -11
- package/third-party/common/phonemis/src/phonemis/base/processor/num2word/config.h +0 -16
- package/third-party/common/phonemis/src/phonemis/base/processor/num2word/layer.cpp +0 -271
- package/third-party/common/phonemis/src/phonemis/base/processor/num2word/layer.h +0 -45
- package/third-party/common/phonemis/src/phonemis/base/processor/num2word/types.h +0 -29
- package/third-party/common/phonemis/src/phonemis/base/processor/sanitizer_layer.cpp +0 -22
- package/third-party/common/phonemis/src/phonemis/base/processor/trim_layer.cpp +0 -40
- package/third-party/common/phonemis/src/phonemis/base/processor/trim_layer.h +0 -22
package/src/fetcher/fetcher.ts
CHANGED
|
@@ -14,9 +14,11 @@ const IS_ANDROID = Platform.OS === 'android';
|
|
|
14
14
|
// Persistent, per-app directory where downloaded model assets are cached.
|
|
15
15
|
// iOS: internal DocumentDir (not CacheDir) so the OS won't evict large models
|
|
16
16
|
// between runs and force a costly re-download.
|
|
17
|
-
// Android: the app-private EXTERNAL files dir (getExternalFilesDir)
|
|
18
|
-
// system DownloadManager
|
|
19
|
-
//
|
|
17
|
+
// Android: the app-private EXTERNAL files dir (getExternalFilesDir). It was
|
|
18
|
+
// picked so the system DownloadManager could stage into it; that backend
|
|
19
|
+
// is gone, but every model already on disk lives here, so moving the
|
|
20
|
+
// cache now would silently orphan all of them and re-download multi-GB
|
|
21
|
+
// files. Falls back to DocumentDir if unmounted.
|
|
20
22
|
const ANDROID_DIRECTORY = RNBlobUtil.fs.dirs.SDCardDir || RNBlobUtil.fs.dirs.DocumentDir;
|
|
21
23
|
const RNE_DIRECTORY = IS_ANDROID
|
|
22
24
|
? `${ANDROID_DIRECTORY}/react-native-executorch`
|
|
@@ -31,9 +33,7 @@ export interface DownloadOptions {
|
|
|
31
33
|
onProgress?: (progress: number) => void;
|
|
32
34
|
/**
|
|
33
35
|
* Aborts the download. The bytes fetched so far are kept so a later
|
|
34
|
-
* {@link download} of the same source resumes instead of restarting
|
|
35
|
-
* Android without the optional background downloader, where the system
|
|
36
|
-
* DownloadManager discards a cancelled transfer.
|
|
36
|
+
* {@link download} of the same source resumes instead of restarting.
|
|
37
37
|
*/
|
|
38
38
|
signal?: AbortSignal;
|
|
39
39
|
/**
|
|
@@ -176,24 +176,6 @@ async function foldResumedChunkIntoPartial(
|
|
|
176
176
|
await RNBlobUtil.fs.unlink(chunkPath).catch(() => {});
|
|
177
177
|
}
|
|
178
178
|
|
|
179
|
-
// DownloadManager's byte counter is 64-bit, but blob-util reads it out of the
|
|
180
|
-
// cursor with `getInt`, so what reaches JS is the low 32 bits reinterpreted as
|
|
181
|
-
// a signed int: past 2 GB it arrives NEGATIVE and wraps every 4 GB after that.
|
|
182
|
-
// Multi-GB LLM models spend most of their download inside that range, which is
|
|
183
|
-
// what collapsed their progress bar. The counter only ever grows, so the
|
|
184
|
-
// discarded high bits can be rebuilt by counting how often the low ones wrap.
|
|
185
|
-
const UINT32 = 0x100000000;
|
|
186
|
-
function reassemble32BitCounter(): (raw: number) => number {
|
|
187
|
-
let wraps = 0;
|
|
188
|
-
let previous = 0;
|
|
189
|
-
return (raw) => {
|
|
190
|
-
const low = raw < 0 ? raw + UINT32 : raw;
|
|
191
|
-
if (low < previous) wraps += 1;
|
|
192
|
-
previous = low;
|
|
193
|
-
return low + wraps * UINT32;
|
|
194
|
-
};
|
|
195
|
-
}
|
|
196
|
-
|
|
197
179
|
// Reports absolute bytes for one file. `total` is 0 when the transfer does not
|
|
198
180
|
// know the length yet — the receiver keeps using whatever length it already
|
|
199
181
|
// had rather than treating the file as complete.
|
|
@@ -249,8 +231,7 @@ async function downloadUrl(url: string, cb: DownloadUrlCallbacks): Promise<strin
|
|
|
249
231
|
// something a later download would CONTINUE from: the staged `.partial` and,
|
|
250
232
|
// with the background downloader in play, a paused task holding resume data.
|
|
251
233
|
// Clear it, or "download it again" quietly resumes the very attempt the
|
|
252
|
-
// caller is trying to replace.
|
|
253
|
-
// here — it unlinks its own staging file before every transfer.
|
|
234
|
+
// caller is trying to replace.
|
|
254
235
|
await discardPartialDownload(dest);
|
|
255
236
|
} else if (await RNBlobUtil.fs.exists(dest)) {
|
|
256
237
|
// Cache hit — nothing to download.
|
|
@@ -296,30 +277,19 @@ async function startDownload(url: string, dest: string, entry: InFlightDownload)
|
|
|
296
277
|
};
|
|
297
278
|
|
|
298
279
|
// The optional background downloader wins on BOTH platforms when the app has
|
|
299
|
-
// it
|
|
300
|
-
//
|
|
301
|
-
//
|
|
302
|
-
// Without it each platform falls back to the best it can do on its own, and
|
|
303
|
-
// only iOS loses background transfers by doing so — blob-util's in-process
|
|
304
|
-
// reader is broken on Android (RonRadtke/react-native-blob-util#475: it stops
|
|
305
|
-
// after 8 KB), so the system DownloadManager is not a preference there but the
|
|
306
|
-
// only backend that works at all.
|
|
280
|
+
// it; without it both fall back to the same in-process stream. One mechanism
|
|
281
|
+
// plus one shared fallback, so a caller sees the same behavior everywhere.
|
|
307
282
|
const backgroundDownloader = loadBackgroundDownloader();
|
|
308
283
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
} else if (IS_ANDROID) {
|
|
313
|
-
path = await downloadUrlViaAndroidDownloadManager(url, dest, cb);
|
|
314
|
-
} else {
|
|
315
|
-
path = await downloadUrlViaIosStream(url, dest, cb);
|
|
316
|
-
}
|
|
284
|
+
const path = backgroundDownloader
|
|
285
|
+
? await downloadUrlViaBackgroundSession(backgroundDownloader, url, dest, cb)
|
|
286
|
+
: await downloadUrlViaStream(url, dest, cb);
|
|
317
287
|
|
|
318
|
-
// Neither backend is guaranteed to emit a last sample at 100%: blob-util
|
|
319
|
-
//
|
|
320
|
-
//
|
|
321
|
-
//
|
|
322
|
-
//
|
|
288
|
+
// Neither backend is guaranteed to emit a last sample at 100%: blob-util only
|
|
289
|
+
// started reporting the final event reliably in 0.25.0, and the background
|
|
290
|
+
// downloader throttles its own. Without this a finished file stays stuck a
|
|
291
|
+
// little short of its own size, and in a multi-file config that shortfall is
|
|
292
|
+
// what the user sees while the remaining files download.
|
|
323
293
|
const finalSize = await fileSize(path);
|
|
324
294
|
if (finalSize > 0) cb.onBytes?.(finalSize, finalSize);
|
|
325
295
|
|
|
@@ -347,72 +317,6 @@ function joinDownload(entry: InFlightDownload, cb: DownloadUrlCallbacks): Promis
|
|
|
347
317
|
});
|
|
348
318
|
}
|
|
349
319
|
|
|
350
|
-
// Android fallback used when that optional dependency is absent: the system
|
|
351
|
-
// DownloadManager streams to app-private external storage. blob-util's
|
|
352
|
-
// in-process reader cannot stand in for it — upstream #475 makes that path stop
|
|
353
|
-
// after 8 KB — and DownloadManager also handles files larger than 2 GB, keeps
|
|
354
|
-
// downloading while the app is in the background or killed, and resumes across
|
|
355
|
-
// transient network drops on its own, so no manual Range logic.
|
|
356
|
-
async function downloadUrlViaAndroidDownloadManager(
|
|
357
|
-
url: string,
|
|
358
|
-
dest: string,
|
|
359
|
-
cb: DownloadUrlCallbacks
|
|
360
|
-
): Promise<string> {
|
|
361
|
-
const tmp = `${dest}.downloading`;
|
|
362
|
-
await RNBlobUtil.fs.unlink(tmp).catch(() => {});
|
|
363
|
-
|
|
364
|
-
if (cb.signal?.aborted) throw abortError();
|
|
365
|
-
|
|
366
|
-
const task = RNBlobUtil.config({
|
|
367
|
-
addAndroidDownloads: {
|
|
368
|
-
useDownloadManager: true,
|
|
369
|
-
path: tmp,
|
|
370
|
-
notification: false,
|
|
371
|
-
mediaScannable: false,
|
|
372
|
-
mime: 'application/octet-stream',
|
|
373
|
-
},
|
|
374
|
-
}).fetch('GET', url);
|
|
375
|
-
|
|
376
|
-
const onAbort = () => task.cancel();
|
|
377
|
-
cb.signal?.addEventListener('abort', onAbort);
|
|
378
|
-
|
|
379
|
-
// DownloadManager reports total as -1 until the size is known; pass that on
|
|
380
|
-
// as 0 rather than echoing the received count, which would otherwise look
|
|
381
|
-
// like a file that is complete at every sample.
|
|
382
|
-
const absoluteBytes = reassemble32BitCounter();
|
|
383
|
-
task.progress({ count: 100 }, (received, total) => {
|
|
384
|
-
const tot = Number(total);
|
|
385
|
-
cb.onBytes?.(absoluteBytes(Number(received)), tot > 0 ? tot : 0);
|
|
386
|
-
});
|
|
387
|
-
|
|
388
|
-
try {
|
|
389
|
-
await task;
|
|
390
|
-
} catch (e) {
|
|
391
|
-
await RNBlobUtil.fs.unlink(tmp).catch(() => {});
|
|
392
|
-
throw cb.signal?.aborted ? abortError() : e;
|
|
393
|
-
} finally {
|
|
394
|
-
cb.signal?.removeEventListener('abort', onAbort);
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
// DownloadManager doesn't surface an HTTP status; an empty file means failure.
|
|
398
|
-
const size = await fileSize(tmp);
|
|
399
|
-
if (size <= 0) {
|
|
400
|
-
await RNBlobUtil.fs.unlink(tmp).catch(() => {});
|
|
401
|
-
throw RnExecuTorchError('DOWNLOAD_FAILED', `Download of ${url} failed (empty response).`);
|
|
402
|
-
}
|
|
403
|
-
// A non-empty file is not necessarily a complete one, and DownloadManager
|
|
404
|
-
// gives us no status to check. Promoting a short file would cache it under
|
|
405
|
-
// its final name forever — the existence-only cache check can't tell the
|
|
406
|
-
// difference, and a truncated .pte only fails much later, at load.
|
|
407
|
-
const expected = await expectedBytesFor(url, cb.expectedBytes, cb.signal);
|
|
408
|
-
if (isTruncated(size, expected)) {
|
|
409
|
-
await RNBlobUtil.fs.unlink(tmp).catch(() => {});
|
|
410
|
-
throw incompleteError(url, size, expected);
|
|
411
|
-
}
|
|
412
|
-
await RNBlobUtil.fs.mv(tmp, dest);
|
|
413
|
-
return dest;
|
|
414
|
-
}
|
|
415
|
-
|
|
416
320
|
// One background task per destination file, under an id that stays the same
|
|
417
321
|
// across app launches: that is what lets a later call adopt a transfer this
|
|
418
322
|
// process never started.
|
|
@@ -579,14 +483,19 @@ async function downloadUrlViaBackgroundSession(
|
|
|
579
483
|
return dest;
|
|
580
484
|
}
|
|
581
485
|
|
|
582
|
-
//
|
|
583
|
-
//
|
|
584
|
-
// suspended — iOS tears the connection down about a
|
|
585
|
-
//
|
|
586
|
-
//
|
|
587
|
-
// `canResume` is set to `false` on an
|
|
588
|
-
// if partial-file assembly ever fails.
|
|
589
|
-
|
|
486
|
+
// The fallback used on either platform when that optional dependency is absent:
|
|
487
|
+
// blob-util streams the response straight to disk, in process. It does NOT
|
|
488
|
+
// survive the app being suspended — iOS tears the connection down about a
|
|
489
|
+
// second later, and Android may kill the process outright — so an interrupted
|
|
490
|
+
// transfer is picked up by the next `download` call instead: it resumes from a
|
|
491
|
+
// `.partial` file via an HTTP Range request. `canResume` is set to `false` on an
|
|
492
|
+
// internal retry to avoid recursing forever if partial-file assembly ever fails.
|
|
493
|
+
//
|
|
494
|
+
// This path needs react-native-blob-util >=0.24.11 on Android. 0.24.10's reader
|
|
495
|
+
// stopped after exactly 8 KB with "Download interrupted"
|
|
496
|
+
// (RonRadtke/react-native-blob-util#475), which is why Android used the system
|
|
497
|
+
// DownloadManager until that fix shipped.
|
|
498
|
+
async function downloadUrlViaStream(
|
|
590
499
|
url: string,
|
|
591
500
|
dest: string,
|
|
592
501
|
cb: DownloadUrlCallbacks,
|
|
@@ -638,9 +547,9 @@ async function downloadUrlViaIosStream(
|
|
|
638
547
|
});
|
|
639
548
|
}
|
|
640
549
|
|
|
641
|
-
//
|
|
642
|
-
//
|
|
643
|
-
//
|
|
550
|
+
// blob-util floors the rate at one event per 250 ms regardless, so this only
|
|
551
|
+
// means a large file advances in ~1% steps instead of the 5% ones that made a
|
|
552
|
+
// multi-GB download look stalled between jumps.
|
|
644
553
|
task.progress({ count: 100 }, (received, total) => {
|
|
645
554
|
const recv = Number(received);
|
|
646
555
|
const tot = Number(total);
|
|
@@ -733,14 +642,14 @@ async function downloadUrlViaIosStream(
|
|
|
733
642
|
// once as a plain full download so correctness never depends on resume.
|
|
734
643
|
await RNBlobUtil.fs.unlink(part).catch(() => {});
|
|
735
644
|
await RNBlobUtil.fs.unlink(target).catch(() => {});
|
|
736
|
-
if (canResume) return
|
|
645
|
+
if (canResume) return downloadUrlViaStream(url, dest, cb, false);
|
|
737
646
|
throw assemblyErr;
|
|
738
647
|
}
|
|
739
648
|
|
|
740
649
|
if (restart) {
|
|
741
650
|
await RNBlobUtil.fs.unlink(part).catch(() => {});
|
|
742
651
|
await RNBlobUtil.fs.unlink(target).catch(() => {});
|
|
743
|
-
return
|
|
652
|
+
return downloadUrlViaStream(url, dest, cb, false);
|
|
744
653
|
}
|
|
745
654
|
|
|
746
655
|
// The transfer can also report success while the body was cut short — a
|
|
@@ -756,7 +665,7 @@ async function downloadUrlViaIosStream(
|
|
|
756
665
|
// start over rather than fail. A fresh transfer that overshoots is a wrong
|
|
757
666
|
// expectation instead, and falls through to be accepted.
|
|
758
667
|
await RNBlobUtil.fs.unlink(part).catch(() => {});
|
|
759
|
-
return
|
|
668
|
+
return downloadUrlViaStream(url, dest, cb, false);
|
|
760
669
|
}
|
|
761
670
|
if (isTruncated(assembled, expected)) {
|
|
762
671
|
// Short: keep the partial so the next call resumes and finishes it.
|
|
@@ -859,10 +768,8 @@ function substituteRemoteSources<T>(node: T, resolved: ReadonlyMap<string, strin
|
|
|
859
768
|
* and survive it being killed. The fetcher uses it automatically on both platforms
|
|
860
769
|
* when it is present, so the behavior is the same on each; nothing else changes.
|
|
861
770
|
*
|
|
862
|
-
* Without it
|
|
863
|
-
*
|
|
864
|
-
* and on iOS a streaming request that stops when the app is suspended and is
|
|
865
|
-
* resumed by the next `download` call.
|
|
771
|
+
* Without it both platforms fall back to the same streaming request, which stops
|
|
772
|
+
* when the app is suspended and is resumed by the next `download` call.
|
|
866
773
|
* @category Utils / Functions
|
|
867
774
|
* @typeParam T The shape of the value being resolved.
|
|
868
775
|
* @param source A URL, a local path, or any nested object/array holding them.
|
package/src/fetcher/telemetry.ts
CHANGED
|
@@ -10,7 +10,7 @@ const DOWNLOAD_EVENT_ENDPOINT = 'https://ai.swmansion.com/telemetry/downloads/ap
|
|
|
10
10
|
// self-referencing import would need package `exports` support in the consuming
|
|
11
11
|
// bundler to load at all. A wrong value here is analytics noise; a failed
|
|
12
12
|
// import would break the bundle.
|
|
13
|
-
const LIB_VERSION = '0.10.
|
|
13
|
+
const LIB_VERSION = '0.10.7';
|
|
14
14
|
|
|
15
15
|
// Anonymous analytics are on by default; apps opt out via setTelemetryEnabled.
|
|
16
16
|
let telemetryEnabled = true;
|
package/src/models.ts
CHANGED
|
@@ -922,10 +922,15 @@ const LFM2_5_EMBEDDING_350M_MLX_INT4: TextEmbedderModel = {
|
|
|
922
922
|
// =============================================================================
|
|
923
923
|
// Image Embeddings
|
|
924
924
|
// =============================================================================
|
|
925
|
+
// The exported image towers expect CLIP-normalized pixels (mean
|
|
926
|
+
// [0.48145466, 0.4578275, 0.40821073], std [0.26862954, 0.26130258, 0.27577711]).
|
|
925
927
|
const CLIP_IMAGE_EMBEDDINGS_OPTS = {
|
|
926
928
|
resizeMode: 'stretch' as const,
|
|
927
929
|
interpolation: 'linear' as const,
|
|
928
|
-
normalizeOpts: {
|
|
930
|
+
normalizeOpts: {
|
|
931
|
+
alpha: [1 / (255.0 * 0.26862954), 1 / (255.0 * 0.26130258), 1 / (255.0 * 0.27577711)],
|
|
932
|
+
beta: [-0.48145466 / 0.26862954, -0.4578275 / 0.26130258, -0.40821073 / 0.27577711],
|
|
933
|
+
},
|
|
929
934
|
};
|
|
930
935
|
const CLIP_VIT_BASE_PATCH32_IMAGE_XNNPACK_FP32: ImageEmbedderModel = {
|
|
931
936
|
modelPath: `${BASE_URL}-clip-vit-base-patch32/${NEXT_VERSION_TAG}/xnnpack/clip_vit_base_patch32_image_xnnpack_fp32.pte`,
|
|
@@ -1,45 +1,101 @@
|
|
|
1
|
+
# ------------------------
|
|
2
|
+
# --- Project metadata ---
|
|
3
|
+
# ------------------------
|
|
1
4
|
cmake_minimum_required(VERSION 3.10)
|
|
2
5
|
project(phonemis VERSION 1.0 LANGUAGES CXX)
|
|
3
6
|
|
|
7
|
+
# ---------------------
|
|
4
8
|
# --- Configuration ---
|
|
9
|
+
# ---------------------
|
|
5
10
|
set(CMAKE_CXX_STANDARD 20)
|
|
6
11
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
7
12
|
|
|
13
|
+
# By default, we only build a static library.
|
|
14
|
+
# Building the tests (-DBUILD_TESTS=ON) and building the sample runner (-DBUILD_RUNNER=ON) must
|
|
15
|
+
# be explciitely specified as CMAKE options.
|
|
8
16
|
option(BUILD_RUNNER "Build phonemis runner" OFF)
|
|
9
17
|
option(BUILD_TESTS "Build tests" OFF)
|
|
10
18
|
|
|
19
|
+
# Additional option to specify the usage of ExecuTorch for neural model inference.
|
|
20
|
+
# To use it, you must explicitely link the package with ExecuTorch libs or
|
|
21
|
+
# build it together.
|
|
22
|
+
option(ET_ON "Use ExecuTorch" OFF)
|
|
23
|
+
|
|
24
|
+
# ----------------
|
|
11
25
|
# --- Includes ---
|
|
26
|
+
# ----------------
|
|
12
27
|
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src)
|
|
13
28
|
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/third-party)
|
|
14
29
|
|
|
30
|
+
# --------------------
|
|
15
31
|
# --- Source Files ---
|
|
32
|
+
# --------------------
|
|
16
33
|
file(GLOB_RECURSE LIB_SOURCES CONFIGURE_DEPENDS
|
|
17
|
-
|
|
34
|
+
${CMAKE_CURRENT_SOURCE_DIR}/src/phonemis/*.cpp
|
|
18
35
|
)
|
|
19
36
|
# Exclude main.cpp from the static library
|
|
20
37
|
list(FILTER LIB_SOURCES EXCLUDE REGEX "main\\.cpp$")
|
|
21
38
|
|
|
22
|
-
#
|
|
39
|
+
# Exclude protophone sources when ExecuTorch is used
|
|
40
|
+
if(ET_ON)
|
|
41
|
+
list(FILTER LIB_SOURCES EXCLUDE REGEX "${CMAKE_CURRENT_SOURCE_DIR}/src/phonemis/protophone/")
|
|
42
|
+
endif()
|
|
23
43
|
|
|
44
|
+
# ---------------
|
|
45
|
+
# --- Targets ---
|
|
46
|
+
# ---------------
|
|
24
47
|
# Always build the static library
|
|
25
48
|
add_library(phonemis STATIC ${LIB_SOURCES})
|
|
26
49
|
|
|
50
|
+
if(ET_ON)
|
|
51
|
+
target_compile_definitions(phonemis PRIVATE ET_ON)
|
|
52
|
+
endif()
|
|
53
|
+
|
|
54
|
+
# Threading support (std::thread in the Protophone convolution stage).
|
|
55
|
+
find_package(Threads REQUIRED)
|
|
56
|
+
target_link_libraries(phonemis PUBLIC Threads::Threads)
|
|
57
|
+
|
|
58
|
+
# SIMD architecture selection (xsimd)
|
|
59
|
+
# xsimd picks its widest batch type at compile time from the enabled ISA. ARM
|
|
60
|
+
# targets (Android arm64-v8a, iOS arm64) already imply NEON, so nothing is
|
|
61
|
+
# needed there. For native x86_64 desktop builds we opt into AVX2 + FMA. The
|
|
62
|
+
# flag is PUBLIC so every translation unit (and the tests) share the same
|
|
63
|
+
# default arch, keeping xsimd's alignment/ABI consistent across the boundary.
|
|
64
|
+
if(NOT ET_ON AND NOT ANDROID AND NOT CMAKE_SYSTEM_NAME STREQUAL "iOS"
|
|
65
|
+
AND CMAKE_SYSTEM_PROCESSOR MATCHES "(x86_64|AMD64|amd64)")
|
|
66
|
+
include(CheckCXXCompilerFlag)
|
|
67
|
+
check_cxx_compiler_flag("-mavx2" PHONEMIS_HAS_AVX2)
|
|
68
|
+
check_cxx_compiler_flag("-mfma" PHONEMIS_HAS_FMA)
|
|
69
|
+
if(PHONEMIS_HAS_AVX2)
|
|
70
|
+
target_compile_options(phonemis PUBLIC -mavx2)
|
|
71
|
+
endif()
|
|
72
|
+
if(PHONEMIS_HAS_FMA)
|
|
73
|
+
target_compile_options(phonemis PUBLIC -mfma)
|
|
74
|
+
endif()
|
|
75
|
+
endif()
|
|
76
|
+
|
|
27
77
|
# Build runner if requested
|
|
28
78
|
if(BUILD_RUNNER)
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
79
|
+
set(MAIN_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/src/phonemis/main.cpp)
|
|
80
|
+
add_executable(phonemis_runner ${MAIN_SOURCE})
|
|
81
|
+
target_link_libraries(phonemis_runner PRIVATE phonemis)
|
|
32
82
|
endif()
|
|
33
83
|
|
|
34
84
|
# Build tests if requested
|
|
35
85
|
if(BUILD_TESTS)
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
86
|
+
file(GLOB TEST_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/test/*.cpp)
|
|
87
|
+
|
|
88
|
+
add_executable(phonemis_test ${TEST_SOURCES})
|
|
89
|
+
target_link_libraries(phonemis_test PRIVATE phonemis)
|
|
90
|
+
|
|
91
|
+
target_include_directories(phonemis_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/test)
|
|
92
|
+
target_include_directories(phonemis_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
|
93
|
+
target_compile_definitions(phonemis_test PRIVATE PHONEMIS_PROJECT_ROOT="${CMAKE_CURRENT_SOURCE_DIR}")
|
|
94
|
+
target_compile_options(phonemis_test PRIVATE -Wno-deprecated-declarations)
|
|
95
|
+
|
|
96
|
+
# Always add previously excluded Protophone sources.
|
|
97
|
+
if(ET_ON)
|
|
98
|
+
file(GLOB_RECURSE PROTOPHONE_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/phonemis/protophone/*.cpp)
|
|
99
|
+
target_sources(phonemis_test PRIVATE ${PROTOPHONE_SOURCES})
|
|
100
|
+
endif()
|
|
45
101
|
endif()
|
|
@@ -1,29 +1,54 @@
|
|
|
1
1
|
# Phonemis
|
|
2
2
|
|
|
3
|
-

|
|
4
|
-
|
|
5
3
|
## From Text to Sound
|
|
6
|
-
|
|
4
|
+
|
|
5
|
+
Phonemis is a high-performance C++ library for **Grapheme-to-Phoneme (G2P)** conversion. It
|
|
6
|
+
delivers universal **IPA phonemization** across many platforms with **zero external
|
|
7
|
+
dependencies**, making it an ideal frontend for text-to-speech systems on desktop, mobile, and
|
|
8
|
+
embedded devices.
|
|
7
9
|
|
|
8
10
|
Currently supported languages:
|
|
9
|
-
* 🇺🇸 English (US)
|
|
10
|
-
* 🇬🇧 English (British)
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
* 🇺🇸 English (US) — `en-us`
|
|
13
|
+
* 🇬🇧 English (British) — `en-gb`
|
|
14
|
+
* 🇩🇪 German — `de`
|
|
15
|
+
* 🇫🇷 French — `fr`
|
|
16
|
+
* 🇪🇸 Spanish — `es`
|
|
17
|
+
* 🇮🇹 Italian — `it`
|
|
18
|
+
* 🇵🇱 Polish — `pl`
|
|
19
|
+
* 🇵🇹 Portuguese — `pt`
|
|
20
|
+
* 🇮🇳 Hindi — `hi`
|
|
14
21
|
|
|
15
|
-
|
|
16
|
-
2. **Rule-based Tokenizer**: The text is segmented into tokens based on linguistic rules, separating words from punctuation and handling special cases.
|
|
17
|
-
3. **Part-of-Speech Tagging**: A Hidden Markov Model (HMM) bigram tagger is employed to assign grammatical categories to words. This model is trained on the Brown Corpus to resolve homograph ambiguities based on context.
|
|
18
|
-
4. **Viterbi Decoding**: The optimal sequence of tags is determined using the [Viterbi algorithm](https://en.wikipedia.org/wiki/Viterbi_algorithm), ensuring the most probable grammatical structure is selected.
|
|
19
|
-
5. **Lexicon-based Phonemization**: Words are converted to phonemes using extensive dictionaries, with fallback mechanisms for unknown tokens.
|
|
22
|
+
## Repository Structure
|
|
20
23
|
|
|
21
|
-
|
|
24
|
+
```
|
|
25
|
+
phonemis/
|
|
26
|
+
├── data/ # Bundled resources (one subdirectory per language)
|
|
27
|
+
├── src/
|
|
28
|
+
│ ├── phonemis/
|
|
29
|
+
│ │ ├── base/ # Core API: Pipeline, IPipeline, Config, phonemizer, tokenizer
|
|
30
|
+
│ │ ├── lang/ # Language-specific modules (en/, de/, fr/, …)
|
|
31
|
+
│ │ ├── protophone/ # Pure C++ neural model inference engine
|
|
32
|
+
│ │ └── utils/ # Conversions, string utilities, Unicode support
|
|
33
|
+
│ └── third-party/ # Bundled header-only dependencies (xsimd)
|
|
34
|
+
└── CMakeLists.txt
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Every language folder under `data/` contains the resources needed for phonemization — a lexicon
|
|
38
|
+
JSON file (word-to-phoneme dictionary), a Protophone model weights file (`.bin`) for neural
|
|
39
|
+
inference, and optionally a tagger JSON file for part-of-speech disambiguation (currently
|
|
40
|
+
available for English). These are the files you point to in `phonemizer::Config`.
|
|
22
41
|
|
|
23
42
|
## Installation
|
|
24
43
|
|
|
25
|
-
###
|
|
26
|
-
|
|
44
|
+
### Requirements
|
|
45
|
+
- **C++20** compiler
|
|
46
|
+
- **CMake** ≥ 3.10
|
|
47
|
+
- **xsimd** (bundled as a header-only library under `src/third-party/`)
|
|
48
|
+
|
|
49
|
+
### Building the Library
|
|
50
|
+
|
|
51
|
+
The below script builds the package as a static library:
|
|
27
52
|
|
|
28
53
|
```bash
|
|
29
54
|
mkdir build
|
|
@@ -32,39 +57,164 @@ cmake ..
|
|
|
32
57
|
make
|
|
33
58
|
```
|
|
34
59
|
|
|
60
|
+
### Build Options
|
|
61
|
+
|
|
62
|
+
| Option | Default | Description |
|
|
63
|
+
|--------|---------|-------------|
|
|
64
|
+
| `-DBUILD_RUNNER=ON` | OFF | Builds the `phonemis_runner` CLI tool |
|
|
65
|
+
| `-DBUILD_TESTS=ON` | OFF | Builds the test suite |
|
|
66
|
+
| `-DET_ON=ON` | OFF | Enables ExecuTorch inference (see below) |
|
|
67
|
+
|
|
68
|
+
### ExecuTorch Integration
|
|
69
|
+
|
|
70
|
+
With `ET_ON=ON`, the built-in Protophone sources are excluded and neural phonemization is
|
|
71
|
+
delegated to ExecuTorch. You must link against the ExecuTorch runtime:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
cmake .. -DET_ON=ON -DCMAKE_PREFIX_PATH=/path/to/executorch
|
|
75
|
+
make
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
When `ET_ON` is left OFF (the default), all neural inference runs through the built-in
|
|
79
|
+
Protophone model — no external runtime dependencies required.
|
|
80
|
+
|
|
81
|
+
### SIMD Acceleration
|
|
82
|
+
|
|
83
|
+
SIMD is configured automatically at build time:
|
|
84
|
+
- **x86_64 desktop** (non-Emscripten, non-Android, non-iOS): AVX2 + FMA are enabled if the
|
|
85
|
+
compiler supports them (`-mavx2 -mfma`), accelerating Protophone's convolution and mixing
|
|
86
|
+
stages.
|
|
87
|
+
- **ARM** (Android arm64-v8a, iOS arm64): NEON is implicitly available and used by xsimd with
|
|
88
|
+
no extra flags.
|
|
89
|
+
|
|
35
90
|
### Mobile Builds
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
91
|
+
|
|
92
|
+
Dedicated scripts are provided for cross-compiling:
|
|
93
|
+
- **Android**: Produces `.a` libraries for armeabi-v7a, arm64-v8a, x86, and x86_64 ABIs.
|
|
94
|
+
- **iOS**: Produces a universal static library or framework.
|
|
39
95
|
|
|
40
96
|
## Sample Usage
|
|
41
97
|
|
|
42
|
-
|
|
98
|
+
All lexicons and trained neural model weights are bundled in the `./data/` subdirectory, organized
|
|
99
|
+
by language code. The example below uses the English (US) resources:
|
|
43
100
|
|
|
44
101
|
```cpp
|
|
45
|
-
#include <phonemis/pipeline.h>
|
|
46
|
-
#include <phonemis/
|
|
102
|
+
#include <phonemis/base/pipeline.h>
|
|
103
|
+
#include <phonemis/utils/conversions.h>
|
|
47
104
|
#include <iostream>
|
|
48
105
|
|
|
49
|
-
using namespace phonemis;
|
|
50
|
-
using namespace phonemis::utilities;
|
|
51
|
-
|
|
52
106
|
int main() {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
107
|
+
using namespace phonemis;
|
|
108
|
+
|
|
109
|
+
phonemizer::Config phon_config;
|
|
110
|
+
phon_config.lang = "en-us";
|
|
111
|
+
phon_config.lexicon_filepath = "data/en-us/lexicon_full.json";
|
|
112
|
+
phon_config.nn_model_filepath = "data/en-us/phonemizer_en_us.bin";
|
|
113
|
+
|
|
114
|
+
Config config;
|
|
115
|
+
config.lang = "en-us";
|
|
116
|
+
config.phonemizer = phon_config;
|
|
56
117
|
|
|
57
|
-
|
|
58
|
-
Pipeline pipeline(Lang::EN_US, tagger_path, lexicon_path);
|
|
118
|
+
Pipeline pipeline(config);
|
|
59
119
|
|
|
60
|
-
// Process text
|
|
61
120
|
std::string text = "I love it! This is the best day of my entire life.";
|
|
62
|
-
auto phonemes = pipeline
|
|
121
|
+
auto phonemes = pipeline(text);
|
|
63
122
|
|
|
64
|
-
// Output result
|
|
65
123
|
std::cout << "Text: " << text << "\n";
|
|
66
|
-
std::cout << "Phonemes: " <<
|
|
124
|
+
std::cout << "Phonemes: " << utils::conversions::u32_to_utf8(phonemes) << "\n";
|
|
67
125
|
|
|
68
126
|
return 0;
|
|
69
127
|
}
|
|
70
128
|
```
|
|
129
|
+
|
|
130
|
+
The `Pipeline::operator()` accepts both `std::string_view` (UTF-8) and `std::u32string_view`
|
|
131
|
+
(UTF-32), returning phonemes as `std::u32string`. Individual pipeline stages —
|
|
132
|
+
`preprocess()`, `process()`, `postprocess()` — are also exposed.
|
|
133
|
+
|
|
134
|
+
### Customizing preprocessing
|
|
135
|
+
|
|
136
|
+
Before phonemization, the text goes through layers which read it out loud: character and
|
|
137
|
+
whitespace normalization, abbreviations and web addresses, numbers, symbols, and character fixes. Each can be
|
|
138
|
+
turned off, and a language's own abbreviations and symbols can be extended or overridden:
|
|
139
|
+
|
|
140
|
+
```cpp
|
|
141
|
+
Config config;
|
|
142
|
+
config.lang = "en-us";
|
|
143
|
+
config.phonemizer = phon_config;
|
|
144
|
+
config.preprocessor = {
|
|
145
|
+
.symbols = false, // Keep "&", "+", ... as written
|
|
146
|
+
.abbreviations = {{U"approx.", {U"approximately"}}}, // Added to the language's own
|
|
147
|
+
};
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
| Field | Layer | Example |
|
|
151
|
+
|---|---|---|
|
|
152
|
+
| `normalize` | one form of each character | `’` → `'`, `„a“` → `"a"`, `a – b` → `a - b`, `…` → `...` |
|
|
153
|
+
| `trim` | whitespace normalization | `" a b , c"` → `"a b, c"` |
|
|
154
|
+
| `terms` | abbreviations, web addresses | `e.g.` → *for example*, `example.com` → *example dot com* |
|
|
155
|
+
| `numbers` | numbers, dates, money, units, ... | `$5` → *five dollars* |
|
|
156
|
+
| `symbols` | remaining symbols | `&` → *and* |
|
|
157
|
+
| `sanitize` | language's character fixes, if it has any | |
|
|
158
|
+
| `abbreviations`, `symbol_words` | extra table entries | `{U"™", {U"trademark"}}` |
|
|
159
|
+
|
|
160
|
+
All layers are on by default, and always run in this order: normalize, trim, terms, numbers, symbols, sanitize.
|
|
161
|
+
|
|
162
|
+
### CLI Runner
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
./build/phonemis_runner --lang en-us \
|
|
166
|
+
--lexicon data/en-us/lexicon_full.json \
|
|
167
|
+
--model data/en-us/phonemizer_en_us.bin \
|
|
168
|
+
"Hello world"
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## The Mechanics of Pronunciation
|
|
172
|
+
|
|
173
|
+
Phonemis combines three complementary phonemization strategies, selected per word to maximize
|
|
174
|
+
accuracy:
|
|
175
|
+
|
|
176
|
+
### Rule-based
|
|
177
|
+
|
|
178
|
+
A language-aware tokenizer segments text using configurable rules for words, punctuation, and
|
|
179
|
+
special characters. A number-to-word layer verbalizes digits, dates, currencies, fractions, and
|
|
180
|
+
ordinals into their textual forms according to language-specific conventions (e.g., German
|
|
181
|
+
"einundzwanzig" unit-before-tens order, comma decimal separator).
|
|
182
|
+
|
|
183
|
+
### Lexicon (lookup-based)
|
|
184
|
+
|
|
185
|
+
An O(1) dictionary lookup provides the fastest and most reliable phonemization. It is cheap, can
|
|
186
|
+
be prepared offline, and handles exception words like "read" (present vs. past tense) correctly.
|
|
187
|
+
Other languages can be extended simply by providing a lexicon JSON file.
|
|
188
|
+
|
|
189
|
+
### Neural (Protophone)
|
|
190
|
+
|
|
191
|
+
For words not found in the lexicon, a neural phonemizer takes over. **Protophone** is a pure
|
|
192
|
+
C++ CTC-based model with SIMD-accelerated inference via xsimd (AVX2+FMA on x86_64, NEON on ARM).
|
|
193
|
+
When built with `ET_ON=ON`, inference is delegated to **ExecuTorch** instead, enabling optimized
|
|
194
|
+
on-device acceleration.
|
|
195
|
+
|
|
196
|
+
These strategies are combined through a **hybrid phonemizer**: the lexicon is tried first, and
|
|
197
|
+
the neural model serves as a fallback. Each level can be individually enabled or disabled via
|
|
198
|
+
configuration.
|
|
199
|
+
|
|
200
|
+
### Extending to a New Language
|
|
201
|
+
|
|
202
|
+
Phonemis is designed to be contribution-friendly. Adding support for a new language requires
|
|
203
|
+
three files under `src/phonemis/lang/XX/`:
|
|
204
|
+
|
|
205
|
+
| File | Purpose | Requirement |
|
|
206
|
+
|------|---------|-------------|
|
|
207
|
+
| `constants.h` | Language-specific data: number words (cardinals, ordinals), currencies, units, months, symbol words, tokenizer special-character rules. | Mandatory |
|
|
208
|
+
| `num2word.h` / `num2word.cpp` | Number verbalizer extending `processor::num2word::Num2WordLayer<NumberReading>`: the language's number notation, its own patterns (dates, phones, ordinal suffixes), how context decides a reading (`resolve`) and the readings themselves (`read_*`). | Mandatory |
|
|
209
|
+
| `patterns.h` / `patterns.cpp` | Number patterns the generic ones do not cover (Roman ordinals, law numbers). | Optional |
|
|
210
|
+
| `pipeline.h` | Pipeline class extending `IPipeline`. Orchestrates preprocessing layers (trimming, number and symbol verbalization), a tokenizer, and a `HybridPhonemizer<LexiconPhonemizer, NeuralPhonemizer>`. | Mandatory |
|
|
211
|
+
| Lexicon JSON / Protophone model | Word-to-phoneme mappings **or** trained neural model (`.bin`). | At least one required |
|
|
212
|
+
|
|
213
|
+
Then register the language in the factory method at `src/phonemis/base/pipeline.cpp`.
|
|
214
|
+
|
|
215
|
+
## License
|
|
216
|
+
|
|
217
|
+
The source code of Phonemis is released under the [MIT license](LICENSE). Some of the data in `data/` and the bundled
|
|
218
|
+
libraries in `src/third-party/` come from other projects under their own licenses: see
|
|
219
|
+
[THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md). In particular, the English part-of-speech tagger (`tagger.json`)
|
|
220
|
+
is derived from a corpus licensed for non-commercial use only, so leave out `Config::tagger` in commercial products.
|