libspeech 0.3.0__tar.gz → 0.4.0__tar.gz
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.
- {libspeech-0.3.0 → libspeech-0.4.0}/.github/workflows/cmake.yml +24 -2
- {libspeech-0.3.0 → libspeech-0.4.0}/.github/workflows/wheels.yml +3 -1
- libspeech-0.4.0/CHANGELOG.md +252 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/CMakeLists.txt +16 -229
- {libspeech-0.3.0 → libspeech-0.4.0}/CONTRIBUTING.md +43 -8
- libspeech-0.4.0/LICENSE +202 -0
- libspeech-0.4.0/NOTICE +12 -0
- libspeech-0.4.0/PKG-INFO +357 -0
- libspeech-0.4.0/README.md +327 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/audioflux_issues.md +4 -4
- libspeech-0.4.0/benchmarks/.gitignore +3 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/benchmarks/CMakeLists.txt +30 -4
- libspeech-0.4.0/benchmarks/README.md +83 -0
- libspeech-0.4.0/benchmarks/cmake/Download.cmake +26 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/benchmarks/cpp/bench_stft.cpp +16 -16
- libspeech-0.4.0/benchmarks/profile/README.md +40 -0
- libspeech-0.4.0/benchmarks/profile/prof_dct.cpp +15 -0
- libspeech-0.4.0/benchmarks/profile/prof_dsp.cpp +51 -0
- libspeech-0.4.0/benchmarks/profile/prof_dsp.py +122 -0
- libspeech-0.4.0/benchmarks/profile/prof_models.cpp +78 -0
- libspeech-0.4.0/benchmarks/python/CMakeLists.txt +163 -0
- libspeech-0.4.0/benchmarks/python/bench_op_memory_driver.py +85 -0
- libspeech-0.4.0/benchmarks/python/bench_op_memory_one.py +91 -0
- libspeech-0.4.0/benchmarks/python/bench_sizes.py +61 -0
- libspeech-0.4.0/benchmarks/python/bench_throughput.py +106 -0
- libspeech-0.4.0/benchmarks/python/corpus.py +91 -0
- libspeech-0.4.0/benchmarks/python/ops.py +254 -0
- libspeech-0.4.0/benchmarks/python/requirements.txt +13 -0
- libspeech-0.4.0/benchmarks/python/system_info.py +74 -0
- libspeech-0.4.0/benchmarks/report/CMakeLists.txt +58 -0
- libspeech-0.4.0/benchmarks/report/generate_report.py +138 -0
- libspeech-0.4.0/benchmarks/report/template.html.jinja2 +128 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/checklist.md +18 -23
- libspeech-0.4.0/data/models.csv +15 -0
- libspeech-0.4.0/docs/CMakeLists.txt +176 -0
- libspeech-0.4.0/docs/CreateDocs.cmake +52 -0
- libspeech-0.4.0/docs/FinishPages.cmake +42 -0
- libspeech-0.4.0/docs/InjectComment.cmake +85 -0
- libspeech-0.4.0/docs/SpeechPages.cmake +198 -0
- libspeech-0.4.0/docs/api-renames.md +112 -0
- libspeech-0.4.0/docs/convert_page.py +392 -0
- libspeech-0.4.0/docs/cpp/CreateDocs.cmake +62 -0
- libspeech-0.4.0/docs/cpp/Doxyfile.in +62 -0
- libspeech-0.4.0/docs/cpp/footer.html.in +27 -0
- libspeech-0.4.0/docs/cpp/index-docs.json +9 -0
- libspeech-0.4.0/docs/cpp/index-example.txt +24 -0
- libspeech-0.4.0/docs/cpp/index-install.txt +19 -0
- libspeech-0.4.0/docs/cpp/mainpage.md +68 -0
- libspeech-0.4.0/docs/generate_index.py +196 -0
- libspeech-0.4.0/docs/images/libspeech-logo.txt +7 -0
- libspeech-0.4.0/docs/index.html.in +286 -0
- libspeech-0.4.0/docs/initial_comment.in +15 -0
- libspeech-0.4.0/docs/page.html.in +419 -0
- libspeech-0.4.0/docs/python/CreateDocs.cmake +59 -0
- libspeech-0.4.0/docs/python/index-docs.json +9 -0
- libspeech-0.4.0/docs/python/index-example.txt +21 -0
- libspeech-0.4.0/docs/python/index-install.txt +11 -0
- libspeech-0.4.0/docs/python/source/_static/custom.css +233 -0
- libspeech-0.4.0/docs/python/source/_themes/speech/layout.html +202 -0
- libspeech-0.4.0/docs/python/source/_themes/speech/page.html +2 -0
- libspeech-0.4.0/docs/python/source/_themes/speech/speech-footer.html +36 -0
- libspeech-0.4.0/docs/python/source/_themes/speech/speech-nav.html +14 -0
- libspeech-0.4.0/docs/python/source/_themes/speech/speech-topbar.html +27 -0
- libspeech-0.4.0/docs/python/source/_themes/speech/static/speech-docs.css +418 -0
- libspeech-0.4.0/docs/python/source/_themes/speech/static/speech-sphinx.css +741 -0
- libspeech-0.4.0/docs/python/source/_themes/speech/theme.toml +9 -0
- libspeech-0.4.0/docs/python/source/conf.py +87 -0
- libspeech-0.4.0/docs/python/source/dsp.rst +35 -0
- libspeech-0.4.0/docs/python/source/index.rst +32 -0
- libspeech-0.4.0/docs/python/source/io.rst +5 -0
- libspeech-0.4.0/docs/python/source/models.rst +9 -0
- libspeech-0.4.0/docs/python/source/utils.rst +17 -0
- libspeech-0.4.0/docs/section.html.in +471 -0
- libspeech-0.4.0/docs/speech-docs.css +436 -0
- libspeech-0.4.0/docs/supported_langs.json +49 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/examples/common.h +1 -1
- {libspeech-0.3.0 → libspeech-0.4.0}/examples/main.cpp +40 -35
- {libspeech-0.3.0 → libspeech-0.4.0}/examples/silero_app/main.cpp +8 -8
- libspeech-0.4.0/include/libspeech/audio.h +52 -0
- libspeech-0.4.0/include/libspeech/detail/log.h +197 -0
- libspeech-0.4.0/include/libspeech/detail/uninit_vector.h +48 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/include/libspeech/dsp/dct.h +29 -4
- libspeech-0.4.0/include/libspeech/dsp/fft.h +128 -0
- libspeech-0.4.0/include/libspeech/dsp/mfcc.h +99 -0
- libspeech-0.4.0/include/libspeech/dsp/resample.h +123 -0
- libspeech-0.4.0/include/libspeech/dsp/simd.h +49 -0
- libspeech-0.4.0/include/libspeech/dsp/stft.h +211 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/include/libspeech/dsp/window.h +3 -4
- libspeech-0.4.0/include/libspeech/dsp/window_type.h +34 -0
- libspeech-0.4.0/include/libspeech/models/base_model.h +51 -0
- libspeech-0.4.0/include/libspeech/models/denoiser.h +106 -0
- libspeech-0.4.0/include/libspeech/models/dpdfnet_denoiser.h +64 -0
- libspeech-0.4.0/include/libspeech/models/facebook_denoiser.h +45 -0
- libspeech-0.4.0/include/libspeech/models/gtcrn_denoiser.h +58 -0
- libspeech-0.4.0/include/libspeech/models/model_files.h +73 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/include/libspeech/models/onnx_model.h +5 -3
- libspeech-0.4.0/include/libspeech/models/providers.h +27 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/include/libspeech/models/silero_vad.h +13 -12
- libspeech-0.4.0/include/libspeech/models/speechbrain_denoiser.h +45 -0
- libspeech-0.4.0/include/libspeech/span.h +420 -0
- libspeech-0.4.0/include/libspeech/utils/log.h +43 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/include/libspeech/utils/utils.h +11 -4
- {libspeech-0.3.0 → libspeech-0.4.0}/include/libspeech/version.h +1 -1
- {libspeech-0.3.0 → libspeech-0.4.0}/pyproject.toml +49 -5
- libspeech-0.4.0/src/audio.cpp +436 -0
- libspeech-0.4.0/src/bindings/python/CMakeLists.txt +275 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/src/bindings/python/bind_audio.cpp +14 -14
- libspeech-0.4.0/src/bindings/python/bind_dsp.cpp +374 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/src/bindings/python/bind_io.cpp +29 -14
- libspeech-0.4.0/src/bindings/python/bind_models.cpp +214 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/src/bindings/python/libspeech/__init__.py +30 -1
- libspeech-0.4.0/src/bindings/python/libspeech/_functional.py +232 -0
- libspeech-0.4.0/src/bindings/python/libspeech/py.typed +0 -0
- libspeech-0.4.0/src/bindings/python/ndarray_util.h +54 -0
- libspeech-0.4.0/src/dsp/dct.cpp +148 -0
- libspeech-0.4.0/src/dsp/fft.cpp +232 -0
- libspeech-0.4.0/src/dsp/mfcc.cpp +199 -0
- libspeech-0.4.0/src/dsp/real_fft.cpp +262 -0
- libspeech-0.4.0/src/dsp/real_fft.h +89 -0
- libspeech-0.4.0/src/dsp/resample.cpp +746 -0
- libspeech-0.4.0/src/dsp/simd.cpp +81 -0
- libspeech-0.4.0/src/dsp/simd_internal.h +97 -0
- libspeech-0.4.0/src/dsp/stft.cpp +540 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/src/dsp/window.cpp +8 -6
- libspeech-0.4.0/src/dsp/window_type_internal.h +38 -0
- libspeech-0.4.0/src/models/base_model.cpp +51 -0
- libspeech-0.4.0/src/models/denoiser.cpp +85 -0
- libspeech-0.4.0/src/models/dpdfnet_denoiser.cpp +190 -0
- libspeech-0.4.0/src/models/facebook_denoiser.cpp +32 -0
- libspeech-0.4.0/src/models/gtcrn_denoiser.cpp +124 -0
- libspeech-0.4.0/src/models/model_files.cpp +266 -0
- libspeech-0.4.0/src/models/model_files_detail.h +39 -0
- libspeech-0.4.0/src/models/onnx_denoiser_impl.h +99 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/src/models/onnx_model.cpp +5 -5
- libspeech-0.4.0/src/models/providers.cpp +31 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/src/models/silero_vad.cpp +15 -15
- libspeech-0.4.0/src/models/spectral.h +188 -0
- libspeech-0.4.0/src/models/speechbrain_denoiser.cpp +27 -0
- libspeech-0.4.0/src/third_party/audioflux/UPSTREAM_PATCHES.md +14 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/src/dsp/resample_algorithm.c +17 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/src/dsp/resample_algorithm.h +7 -0
- libspeech-0.4.0/src/utils/utils.cpp +159 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/tests/CMakeLists.txt +3 -0
- libspeech-0.4.0/tests/dsp/test_complex_views.cpp +255 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/tests/dsp/test_dct.cpp +10 -10
- libspeech-0.4.0/tests/dsp/test_fast_paths.cpp +639 -0
- libspeech-0.4.0/tests/dsp/test_fft.cpp +124 -0
- libspeech-0.4.0/tests/dsp/test_fft_into.cpp +171 -0
- libspeech-0.4.0/tests/dsp/test_istft.cpp +188 -0
- libspeech-0.4.0/tests/dsp/test_mfcc.cpp +128 -0
- libspeech-0.4.0/tests/dsp/test_resample.cpp +134 -0
- libspeech-0.4.0/tests/dsp/test_span.cpp +293 -0
- libspeech-0.4.0/tests/dsp/test_stft.cpp +102 -0
- libspeech-0.4.0/tests/dsp/test_window.cpp +69 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/tests/models/CMakeLists.txt +3 -1
- {libspeech-0.3.0 → libspeech-0.4.0}/tests/models/test_default_model_cache_dir.cpp +30 -30
- libspeech-0.4.0/tests/models/test_denoiser.cpp +98 -0
- libspeech-0.4.0/tests/models/test_log.cpp +70 -0
- libspeech-0.4.0/tests/models/test_model_files.cpp +483 -0
- libspeech-0.4.0/tests/models/test_providers.cpp +24 -0
- libspeech-0.4.0/tests/models/test_spectral.cpp +160 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/tests/python/CMakeLists.txt +19 -0
- libspeech-0.4.0/tests/python/conftest.py +19 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/tests/python/test_dsp.py +16 -0
- libspeech-0.4.0/tests/python/test_functional.py +197 -0
- libspeech-0.4.0/tests/python/test_librosa_compat.py +427 -0
- libspeech-0.4.0/tests/python/test_logging.py +107 -0
- libspeech-0.4.0/tests/python/test_model_files.py +396 -0
- libspeech-0.4.0/tests/python/test_models.py +250 -0
- libspeech-0.4.0/tests/python/test_numpy_api.py +426 -0
- libspeech-0.4.0/tests/python/test_providers.py +19 -0
- libspeech-0.4.0/tests/python/test_simd.py +90 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/version.py +2 -2
- libspeech-0.3.0/LICENSE +0 -36
- libspeech-0.3.0/PKG-INFO +0 -250
- libspeech-0.3.0/README.md +0 -224
- libspeech-0.3.0/docs/CMakeLists.txt +0 -44
- libspeech-0.3.0/include/libspeech/audio.h +0 -46
- libspeech-0.3.0/include/libspeech/dsp/fft.h +0 -73
- libspeech-0.3.0/include/libspeech/dsp/mfcc.h +0 -72
- libspeech-0.3.0/include/libspeech/dsp/resample.h +0 -64
- libspeech-0.3.0/include/libspeech/dsp/stft.h +0 -81
- libspeech-0.3.0/include/libspeech/models/base_model.h +0 -33
- libspeech-0.3.0/include/libspeech/models/denoiser.h +0 -38
- libspeech-0.3.0/include/libspeech/models/facebook_denoiser.h +0 -44
- libspeech-0.3.0/include/libspeech/models/speechbrain_denoiser.h +0 -44
- libspeech-0.3.0/src/audio.cpp +0 -412
- libspeech-0.3.0/src/bindings/python/bind_dsp.cpp +0 -85
- libspeech-0.3.0/src/bindings/python/bind_models.cpp +0 -58
- libspeech-0.3.0/src/dsp/dct.cpp +0 -47
- libspeech-0.3.0/src/dsp/fft.cpp +0 -104
- libspeech-0.3.0/src/dsp/mfcc.cpp +0 -128
- libspeech-0.3.0/src/dsp/resample.cpp +0 -136
- libspeech-0.3.0/src/dsp/stft.cpp +0 -124
- libspeech-0.3.0/src/models/base_model.cpp +0 -46
- libspeech-0.3.0/src/models/denoiser.cpp +0 -22
- libspeech-0.3.0/src/models/facebook_denoiser.cpp +0 -75
- libspeech-0.3.0/src/models/speechbrain_denoiser.cpp +0 -85
- libspeech-0.3.0/src/third_party/audioflux/UPSTREAM_PATCHES.md +0 -6
- libspeech-0.3.0/src/utils/utils.cpp +0 -117
- libspeech-0.3.0/tests/dsp/test_fft.cpp +0 -124
- libspeech-0.3.0/tests/dsp/test_mfcc.cpp +0 -128
- libspeech-0.3.0/tests/dsp/test_resample.cpp +0 -82
- libspeech-0.3.0/tests/dsp/test_stft.cpp +0 -102
- libspeech-0.3.0/tests/dsp/test_window.cpp +0 -67
- libspeech-0.3.0/tests/models/test_denoiser.cpp +0 -43
- libspeech-0.3.0/tests/python/test_models.py +0 -39
- {libspeech-0.3.0 → libspeech-0.4.0}/.clang-format +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/.github/workflows/orchestrator.yml +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/.gitignore +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/.gitmodules +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/benchmarks/cpp/CMakeLists.txt +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/cmake/AudioFlux.cmake +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/cmake/Conan.cmake +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/cmake/DynamicVersion.cmake +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/cmake/FixLCovPaths.cmake +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/cmake/GenerateIframe.cmake +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/cmake/ONNXRuntime.cmake +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/cmake/PyProject.cmake +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/cmake/coverage_iframe.html.in +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/conanfile.txt +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/conda.recipe/meta.yaml +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/docs/Doxyfile.in +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/docs/logo/README.md +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/docs/logo/libspeech-logo-pods.svg +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/docs/logo/libspeech-logo.svg +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/examples/denoiser_app/controler.h +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/examples/denoiser_app/main.cpp +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/git-submodule.sh +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/include/libspeech/export.h +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/src/bindings/python/about.cpp +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/src/speech_umbrella_placeholder.cpp +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/README.md +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/aixlog/LICENSE +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/aixlog/README.md +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/aixlog/include/aixlog.hpp +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/LICENSE.md +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/README.md +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/include/dsp/resample_algorithm.h +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/include/flux_base.h +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/include/stft_algorithm.h +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/include/util/flux_util.h +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/include/util/flux_wave.h +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/include/vector/flux_complex.h +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/include/vector/flux_vector.h +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/src/dsp/fft_algorithm.c +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/src/dsp/fft_algorithm.h +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/src/dsp/filterDesign_fir.c +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/src/dsp/filterDesign_fir.h +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/src/dsp/flux_window.c +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/src/dsp/flux_window.h +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/src/flux_base.h +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/src/stft_algorithm.c +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/src/stft_algorithm.h +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/src/util/flux_util.c +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/src/util/flux_util.h +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/src/util/flux_wave.c +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/src/util/flux_wave.h +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/src/vector/flux_complex.c +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/src/vector/flux_complex.h +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/src/vector/flux_vector.c +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/src/vector/flux_vector.h +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/src/vector/flux_vectorOp.c +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/src/vector/flux_vectorOp.h +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/tests/coverage_dashboard.html.in +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/tests/genhtml.css +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/tests/python/test_audio.py +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/tests/utest/utest.h +0 -0
- {libspeech-0.3.0 → libspeech-0.4.0}/tests/utest/utest_main.cxx +0 -0
|
@@ -58,6 +58,20 @@ jobs:
|
|
|
58
58
|
steps:
|
|
59
59
|
- name: Checkout repository
|
|
60
60
|
uses: actions/checkout@v6
|
|
61
|
+
with:
|
|
62
|
+
submodules: true
|
|
63
|
+
|
|
64
|
+
- name: Set up Python
|
|
65
|
+
uses: actions/setup-python@v6
|
|
66
|
+
with:
|
|
67
|
+
python-version: "3.11"
|
|
68
|
+
cache: "pip"
|
|
69
|
+
|
|
70
|
+
# httpp: needed at CMake-configure time (see build-and-test above). The rest are the docs
|
|
71
|
+
# tools: Sphinx (Python reference), doxygen-awesome-css (C++ theme), markdown-it-py (pages).
|
|
72
|
+
# The Python reference imports the package built in the build tree, so this is a full build.
|
|
73
|
+
- name: Install python dependencies
|
|
74
|
+
run: pip install httpp sphinx doxygen-awesome-css markdown-it-py
|
|
61
75
|
|
|
62
76
|
- name: Install Doxygen + graphviz
|
|
63
77
|
run: |
|
|
@@ -67,7 +81,9 @@ jobs:
|
|
|
67
81
|
- name: Configure CMake
|
|
68
82
|
run: |
|
|
69
83
|
cmake -B build \
|
|
70
|
-
-
|
|
84
|
+
-DCMAKE_BUILD_TYPE=Release \
|
|
85
|
+
-DBUILD_MODELS=ON \
|
|
86
|
+
-DBUILD_PYTHON=ON \
|
|
71
87
|
-DBUILD_TESTS=OFF \
|
|
72
88
|
-DBUILD_DOCS=ON
|
|
73
89
|
|
|
@@ -78,7 +94,7 @@ jobs:
|
|
|
78
94
|
uses: actions/upload-artifact@v7
|
|
79
95
|
with:
|
|
80
96
|
name: cmake-documentation
|
|
81
|
-
path: build/docs/out
|
|
97
|
+
path: build/docs/out
|
|
82
98
|
retention-days: 5
|
|
83
99
|
|
|
84
100
|
build-coverage:
|
|
@@ -126,6 +142,12 @@ jobs:
|
|
|
126
142
|
- name: Generate coverage report
|
|
127
143
|
run: cmake --build build --target speech_coverage
|
|
128
144
|
|
|
145
|
+
# Heavy end-to-end Denoiser test (downloads the ONNX model, ~1 GB RAM). It carries the
|
|
146
|
+
# `models` pytest marker, so the normal pytest runs (wheels.yml / cibuildwheel, the coverage
|
|
147
|
+
# run above) skip it; this is the one place it runs (pytest -m models).
|
|
148
|
+
- name: Run model tests (pytest -m models)
|
|
149
|
+
run: cmake --build build --target speech_test_python_models_e2e
|
|
150
|
+
|
|
129
151
|
- name: Upload coverage to Codecov
|
|
130
152
|
uses: codecov/codecov-action@v5
|
|
131
153
|
with:
|
|
@@ -57,7 +57,7 @@ jobs:
|
|
|
57
57
|
submodules: true
|
|
58
58
|
|
|
59
59
|
- name: Build wheels
|
|
60
|
-
uses: pypa/cibuildwheel@
|
|
60
|
+
uses: pypa/cibuildwheel@v4.2.0
|
|
61
61
|
env:
|
|
62
62
|
# ONNX Runtime's own v1.21.0 release notes state outright: "All
|
|
63
63
|
# macOS packages now require macOS version >= 13.3." Without this,
|
|
@@ -85,6 +85,8 @@ jobs:
|
|
|
85
85
|
# cp38 is excluded: httpp (a build-time dependency, see above) only
|
|
86
86
|
# ships wheels from cp39-abi3 up on PyPI, not cp38 -- building a
|
|
87
87
|
# cp38 wheel here would require httpp built from source instead.
|
|
88
|
+
# (cibuildwheel 4.2 builds CPython 3.15 by default; this explicit list keeps the
|
|
89
|
+
# matrix at 3.9-3.12 -- the cp312 wheel is abi3, so it also serves 3.13 and newer.)
|
|
88
90
|
CIBW_BUILD: "cp39-* cp310-* cp311-* cp312-*"
|
|
89
91
|
# Per-Python-version env var overrides (SKBUILD_WHEEL_PY_API=cp312
|
|
90
92
|
# for the cp312 build only, so scikit-build-core tags it as a
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to libspeech. The version lives in `include/libspeech/version.h`.
|
|
4
|
+
This file starts at 0.3.1; older history is in `git log`.
|
|
5
|
+
|
|
6
|
+
## Unreleased
|
|
7
|
+
|
|
8
|
+
## 0.4.0 (2026-10-17)
|
|
9
|
+
|
|
10
|
+
Needs **httpp 0.7.x** (`httpp>=0.7,<0.8`, in `pyproject.toml`): the download lock and the SHA-256 functions used
|
|
11
|
+
here are not in 0.6.x, and httpp's API is still changing, so the range is deliberately narrow.
|
|
12
|
+
|
|
13
|
+
### Breaking
|
|
14
|
+
- **C++ API renamed to snake_case, STL style** (types, enumerators, functions, methods,
|
|
15
|
+
constants). A few names changed beyond case because a type cannot share a method's name:
|
|
16
|
+
`STFT::stft` → `stft::compute`, `Resample::resample` → `resample::process`,
|
|
17
|
+
`Spectrogram` → `complex_spectrogram`, `DctII` → `dct_ii_plan`,
|
|
18
|
+
`Denoiser::Create` → `denoiser::create`. Full old → new table: `docs/api-renames.md`.
|
|
19
|
+
Python class names (`libspeech.STFT`, ...) are unchanged.
|
|
20
|
+
- **`window_type`** (`enum class`, `include/libspeech/dsp/window_type.h`) replaces AudioFlux's
|
|
21
|
+
`WindowType`/`Window_*` in the public headers; no AudioFlux header is public any more.
|
|
22
|
+
- **`denoiser` is single-inheritance** (pimpl backends `facebook_denoiser`, `speechbrain_denoiser`);
|
|
23
|
+
`process()`/`close()` are non-virtual in the base.
|
|
24
|
+
- **Default log level is now `warning`** (it used to print everything). Use
|
|
25
|
+
`libspeech.set_log_level("debug")`, `speech::utils::set_log_level` or `LIBSPEECH_LOG`.
|
|
26
|
+
- **`istft` with an invalid `method` raises** (only 0/1, or `"weighted"`/`"plain"` in Python).
|
|
27
|
+
- **`nanobind>=2.0.0`** is required to build the Python bindings.
|
|
28
|
+
|
|
29
|
+
### Changed
|
|
30
|
+
- **License is now Apache-2.0** (was declared as MIT in the README/pyproject, while the `LICENSE` file actually held
|
|
31
|
+
pybind11's BSD-3 text). `LICENSE` is the standard Apache-2.0 text, `NOTICE` names the third-party code and says
|
|
32
|
+
that the downloaded models keep their own licenses. Copies of libspeech already distributed under MIT stay MIT.
|
|
33
|
+
|
|
34
|
+
### Added
|
|
35
|
+
- **Verified model downloads.** A model now always comes with two small files next to it, and all three
|
|
36
|
+
are downloaded: `<model>.onnx.sha256` (one line, `<sha256> <file name>`, as `sha256sum` writes it) and
|
|
37
|
+
`<model>.onnx.readme` (what the model is, who made it, license, provenance). The checksum file is fetched
|
|
38
|
+
**first** and must be exactly that one line (an HTML error page is rejected); then the readme (so a missing
|
|
39
|
+
one fails before the big download); then the model, which httpp checks against the checksum and deletes if it
|
|
40
|
+
does not match. The checksum and readme are installed next to the model only after it arrived and matched,
|
|
41
|
+
so a failed or interrupted download no longer leaves a broken file behind that later calls would trust
|
|
42
|
+
(`download_file` skipped any existing file). A cached model is hashed on every load and downloaded again if
|
|
43
|
+
it does not match; a model cached by an older version just gets its two files. A bare model name (the
|
|
44
|
+
`models` release) must have all three; an explicit URL may lack the sidecar files and is then used unverified
|
|
45
|
+
with a warning (a malformed checksum file is still an error).
|
|
46
|
+
- **Several processes, one download.** The lock is httpp's: `httpp::download` always takes `<file>.lock/`,
|
|
47
|
+
whose `alive` file the downloading process keeps rewriting. Another process (or thread) that wants the same
|
|
48
|
+
model waits and then finds the finished file instead of downloading it again; a lock that stops being
|
|
49
|
+
updated belongs to a dead process and is taken over. A download that was killed is resumed from its `.part`
|
|
50
|
+
file and verified against the checksum. The checksum and readme are fetched under per-download temporary
|
|
51
|
+
names (`*.<tag>.new`), so a failed refresh (`ignore_cache`) leaves the old cache as it was. A cache hit
|
|
52
|
+
never takes the lock.
|
|
53
|
+
- **`ignore_cache`**: `Denoiser(..., ignore_cache=True)`, `SileroVad(..., ignore_cache=True)`,
|
|
54
|
+
`libspeech.fetch_model(..., ignore_cache=True)`; C++ `denoiser::create(..., ignore_cache)`, the model
|
|
55
|
+
constructors and `fetch_options::ignore_cache`. Downloads everything again; if that fails the old cache is untouched.
|
|
56
|
+
- **Readme API**: `Denoiser.readme()`, `SileroVad.readme()`, `libspeech.model_readme(name)`; C++
|
|
57
|
+
`denoiser::readme()`, `base_model::readme()`, `speech::models::model_readme(name)`. Also `model_path`
|
|
58
|
+
and `sha256` on loaded models, `libspeech.fetch_model(name)` (returns the verified path without loading
|
|
59
|
+
the model) and C++ `speech::models::fetch_model` / `fetch_options` / `parse_checksum`.
|
|
60
|
+
- **SHA-256**: `libspeech.sha256(bytes)`, `libspeech.sha256_file(path)`, C++ `speech::utils::sha256_hex` /
|
|
61
|
+
`sha256_file` (chunked, any file size). The hashing itself is httpp's (`httpp::sha256_hex`), which also
|
|
62
|
+
verifies the downloads; no SHA-256 code is vendored.
|
|
63
|
+
- **`data/models.csv`**: every model in the `models` release (name, file, backend, sample rate, size, sha256,
|
|
64
|
+
license, `commercial_use`, source, notes). A test checks it against the release's `.sha256` files.
|
|
65
|
+
- Python `libspeech.stft(...)` / `libspeech.istft(...)` (librosa style, NumPy in/out), and
|
|
66
|
+
`STFT.stft_complex`, `STFT.istft`, `FFT.fft`/`FFT.ifft` returning `complex64`.
|
|
67
|
+
- C++ `istft` (inverse real FFT, one-sided or full input, AudioFlux-compatible normalisation),
|
|
68
|
+
`fft::forward_into/inverse_into/dct_into/idct_into`, `span<T>`/`frame_view<T>` and complex
|
|
69
|
+
views (`as_complex`, `split_complex_span`, `complex_spectrogram::frames()`).
|
|
70
|
+
- Real-FFT fast path for real input up to 2^17 points.
|
|
71
|
+
- `Denoiser`: `close()`, `closed`, context manager, `sample_rate`, `num_threads`
|
|
72
|
+
(default 1, 0 = automatic), NumPy overload, GIL released while running, `Denoiser("facebook")`
|
|
73
|
+
with the default model, `denoiser(x)`.
|
|
74
|
+
- Logger with a public API (`set_log_level`, `get_log_level`, `LIBSPEECH_LOG`), output
|
|
75
|
+
`time [level] (tag) message`; it no longer takes over `std::clog`.
|
|
76
|
+
- Type stubs: `py.typed` and one `.pyi` per compiled module, generated with
|
|
77
|
+
`python -m nanobind.stubgen` in `src/bindings/python/CMakeLists.txt` and installed with the
|
|
78
|
+
wheel.
|
|
79
|
+
- **`resample_quality`** (`best` default, `high`, `medium`, `fast`; Python
|
|
80
|
+
`Resample(src, dst, "medium")`) trades passband width and alias rejection for speed. Python,
|
|
81
|
+
44.1 → 16 kHz, one core, min of 60 runs, 10 s / 60 s of audio, in ms: best 2.5 / 15.4,
|
|
82
|
+
high 1.9 / 11.9, medium 1.35 / 8.2, fast 0.77 / 4.7, against librosa 2.3 / 13.5, soxr MQ
|
|
83
|
+
2.0 / 11.7, soxr LQ 1.8 / 10.5. Quality, measured with pure tones: aliases rejected by
|
|
84
|
+
> 150 dB (best), 135 (high), 124 (medium), 107 (fast) at 12 kHz; passband loss at 7 kHz
|
|
85
|
+
0.00 / 0.00 / 0.07 / 2.3 dB. soxr keeps a flatter passband close to 8 kHz (-0.02 dB at
|
|
86
|
+
7.4 kHz against -1.1 dB for `best` and -2.0 dB for `medium`), so the levels are not an
|
|
87
|
+
equal-quality comparison with soxr.
|
|
88
|
+
- **Denoiser backends `gtcrn` and `dpdfnet`** (`gtcrn_denoiser`, `dpdfnet_denoiser`;
|
|
89
|
+
`Denoiser("gtcrn")`, `Denoiser("dpdfnet", model="dpdfnet4")`). Small streaming models that work
|
|
90
|
+
on the STFT one frame at a time and carry their state, so any input length works. GTCRN (0.5 MB,
|
|
91
|
+
16 kHz) and DPDFNet (`dpdfnet_baseline`, `dpdfnet2` (default), `dpdfnet4`, `dpdfnet8` at 16 kHz,
|
|
92
|
+
`dpdfnet2_48khz_hr` at 48 kHz; pass `sample_rate=48000` for that one) are Ceva's / the GTCRN
|
|
93
|
+
authors' public ONNX exports, hosted in the `models` release (each with a `.readme` and `.sha256`)
|
|
94
|
+
and downloaded on first use. Checked against sherpa-onnx 1.13.8 on its
|
|
95
|
+
9.8 s sample clip: max |difference| 1.5e-7 (float precision) for GTCRN and the four 16 kHz
|
|
96
|
+
DPDFNet models, 1.4e-5 for the 48 kHz one. Two deliberate differences: the output always has the
|
|
97
|
+
input's length (sherpa-onnx drops the last `len % hop` samples), and DPDFNet's 4-hop latency is
|
|
98
|
+
compensated by flushing the model with silence, so its last 40 ms are real output instead of
|
|
99
|
+
zeros. Single thread, 9.8 s of audio (not compared to anything else): GTCRN 0.8 s,
|
|
100
|
+
`dpdfnet_baseline` 1.4 s, `dpdfnet2` 2.9 s, `dpdfnet4` 4.0 s, `dpdfnet8` 6.3 s. DPDFNet's
|
|
101
|
+
optional attenuation limit is not exposed.
|
|
102
|
+
- `libspeech.available_providers()` and `libspeech.is_cuda_available()` (C++:
|
|
103
|
+
`speech::models::available_providers/is_cuda_available`): the ONNX Runtime providers of the loaded
|
|
104
|
+
build, and whether CUDA can really be created. Models still run on the CPU; selecting a provider
|
|
105
|
+
for a session is not implemented yet.
|
|
106
|
+
- Test marker `models` (real-model tests, run by `cmake.yml` only: `pytest -m models`).
|
|
107
|
+
- `benchmarks/profile/`: profiling README and C++ timing scripts for DCT/FFT (2026-10-05).
|
|
108
|
+
- DSP loops link `OpenMP_CXX`; the README documents the SIMD backends and the architecture-agnostic
|
|
109
|
+
vectorization logic (2026-10-02).
|
|
110
|
+
|
|
111
|
+
### Changed
|
|
112
|
+
- **httpp 0.7.x is required** (see above); libspeech no longer has its own download lock or SHA-256 code.
|
|
113
|
+
- Resample output is numerically more accurate than before (up to ~6e-3 different from the
|
|
114
|
+
old kernel). The default (`best`) is still ~8–18% slower than librosa/soxr on one core; use
|
|
115
|
+
`resample_quality` to trade accuracy for speed.
|
|
116
|
+
- **Documentation site rebuilt like ctoon's**: `-DBUILD_DOCS=ON` + `--target speech_docs` builds the
|
|
117
|
+
C++ reference (Doxygen, with doxygen-awesome-css), the Python reference (Sphinx, from the package
|
|
118
|
+
staged in the build tree), a route index (`docs/supported_langs.json`) and Markdown pages
|
|
119
|
+
(changelog, C++ API renames, contributing) into `<build>/docs/out/`; `speech_docs_cpp` and
|
|
120
|
+
`speech_docs_python` build one part. Needs `pip install sphinx doxygen-awesome-css markdown-it-py`.
|
|
121
|
+
- The Python bindings' CMake code moved from the top-level `CMakeLists.txt` to
|
|
122
|
+
`src/bindings/python/CMakeLists.txt`; `cmake/generate_stubs.cmake` is gone.
|
|
123
|
+
- Wheels: cibuildwheel 3.4.1 → 4.2.0 with explicit CPython version constraints; delvewheel repair is
|
|
124
|
+
disabled on Windows (it caused a missing `speech.dll`); the test dependencies exclude Intel macOS and
|
|
125
|
+
Python 3.15+ (numba → llvmlite wheel availability).
|
|
126
|
+
- The Python bindings bake the runtime library file names (ONNX Runtime, httpp) into `_about` at build time
|
|
127
|
+
instead of guessing them at import time (which failed because `dlopen` ignores the RPATH).
|
|
128
|
+
- Benchmarks import NumPy in isolation, so the timings are fair.
|
|
129
|
+
|
|
130
|
+
### Fixed
|
|
131
|
+
- **Windows: `SPEECH_LOG(ERROR)` messages were never printed.** `<windows.h>` defines `ERROR` as 0,
|
|
132
|
+
so the macro mapped it to the trace level. The severity is now pasted into a name
|
|
133
|
+
(`SPEECH_LOG_LEVEL_ERROR`) instead of being macro-expanded. Regression test on every platform
|
|
134
|
+
(`log.error_severity_is_not_hijacked_by_a_windows_style_error_macro`).
|
|
135
|
+
- **Windows wheel build: stub generation failed** with `No module named 'libspeech._about'`.
|
|
136
|
+
Multi-config generators (Visual Studio, Xcode, Ninja Multi-Config) append `Release/` to a plain
|
|
137
|
+
`LIBRARY_OUTPUT_DIRECTORY`, so the staged package was missing its modules; the staging directory is
|
|
138
|
+
now a generator expression, which switches that suffix off.
|
|
139
|
+
- `audio_callback` initialised a local `output` from itself (it shadowed the `output` parameter),
|
|
140
|
+
which is undefined behaviour (MSVC C4700).
|
|
141
|
+
- `Denoiser.create(...)` failed with "Unable to convert function return value".
|
|
142
|
+
- Destroying a `Denoiser` aborted the process (`free(): invalid pointer`, multiple-inheritance
|
|
143
|
+
pointer offset).
|
|
144
|
+
- **Facebook denoiser silently dropped everything after ~32 s of input** (the exported graph
|
|
145
|
+
works on a fixed window); longer input is now processed in overlapping, cross-faded windows
|
|
146
|
+
and the output has the input's length.
|
|
147
|
+
- **The Facebook models (`facebook-denoiser-dns48.onnx`, `-dns64.onnx`, `-master64.onnx`) take 4 to 7 s per call whatever the input length.** The graph
|
|
148
|
+
was traced with a 512000-sample example, so its `valid_length` was baked in as the constant
|
|
149
|
+
512085 and every input was zero-padded to ~32 s. A re-published model computes `valid_length`
|
|
150
|
+
from the input length inside the graph (same weights; 38 nodes replace the constant), measured
|
|
151
|
+
on one core, dns64: 0.1 s → 0.03 s, 1 s → 0.23 s, 5 s → 1.0 s, 32 s → ~7 s (dns48 1 s → 0.14 s,
|
|
152
|
+
master64 1 s → 0.17 s). All three had the same baked constant and are patched the same way. Output equals the old
|
|
153
|
+
model for 32 s inputs and differs by ~1e-3 (peak, at the tail) for 1 to 5 s inputs; not
|
|
154
|
+
compared against the PyTorch reference or on real speech. Existing installs keep the old file
|
|
155
|
+
in `~/.libspeech/` until it is deleted.
|
|
156
|
+
- `tests/python/test_logging.py` no longer relies on AudioFlux rejecting `FFT(99)` to produce an
|
|
157
|
+
error line (it failed on Windows CI).
|
|
158
|
+
- The real-FFT STFT path takes its analysis window from `window_calFFTWindow()`, the same function the
|
|
159
|
+
vendored AudioFlux uses, instead of reading it out of the opaque `stftObj_`; regression test for every
|
|
160
|
+
supported window type (`tests/dsp/test_fast_paths.cpp`).
|
|
161
|
+
- Python binding memory leak of `Denoiser` (the C++ object is held through a `shared_ptr` now); `close()`
|
|
162
|
+
frees the model's memory explicitly.
|
|
163
|
+
|
|
164
|
+
### Known issues
|
|
165
|
+
- Not run on Windows/macOS/ARM, or with several cores, while this version was written (Linux, x86-64 only);
|
|
166
|
+
the new download code has never been compiled with MSVC. Check CI.
|
|
167
|
+
- GPU is not used: models run on the CPU (`available_providers()` / `is_cuda_available()` only report).
|
|
168
|
+
- The Facebook denoiser models are licensed CC-BY-NC-4.0 (non-commercial); `data/models.csv` says so
|
|
169
|
+
(`commercial_use=no`), and so does the model's `.readme`.
|
|
170
|
+
- A process killed during a download leaves its `*.new` files in the cache directory (harmless, not reused).
|
|
171
|
+
If two processes take over the same dead lock at the same moment they can write the same `.part` file;
|
|
172
|
+
the checksum catches the damage and the download fails instead of installing it.
|
|
173
|
+
- `STFT` outside n_fft 16..8192 uses the AudioFlux fallback, which is mutex-locked; `FFT` is not
|
|
174
|
+
thread-safe.
|
|
175
|
+
|
|
176
|
+
## 0.3.1 (2026-10-01; the version was bumped, no git tag)
|
|
177
|
+
|
|
178
|
+
### Added
|
|
179
|
+
- Python benchmark suite (`benchmarks/`) comparing libspeech with librosa, audioflux, scipy and soundfile for
|
|
180
|
+
time, memory and install size, with a standalone HTML report (`report/`); the CMake targets skip Python when
|
|
181
|
+
there is no interpreter.
|
|
182
|
+
- `benchmarks/README.md` documents the measured results and the optimized paths: flat spectrogram, block-wise
|
|
183
|
+
MFCC with sparse mel filters, AVX2+FMA resampling dispatch, memory-efficient `load`/`to_numpy`.
|
|
184
|
+
|
|
185
|
+
### Changed
|
|
186
|
+
- README: table of contents, dependency text now names `httpp` (not httplib + Mbed TLS), the STFT/OpenMP
|
|
187
|
+
benchmark explanation separates single-core from multi-core results; the benchmarking section was removed
|
|
188
|
+
from the README (the raw data is kept locally).
|
|
189
|
+
|
|
190
|
+
## 0.3.0 (2026-09-29)
|
|
191
|
+
|
|
192
|
+
### Added
|
|
193
|
+
- Build options for documentation and coverage (`-DBUILD_DOCS=ON`, `-DBUILD_COVERAGE=ON`); coverage of all
|
|
194
|
+
components is merged into one `speech_coverage_total` report; CI builds with `BUILD_PYTHON=ON` so the tests
|
|
195
|
+
are installed and reported.
|
|
196
|
+
|
|
197
|
+
### Removed
|
|
198
|
+
- The `dr_libs` submodule: `miniaudio` already embeds `dr_wav`, `dr_mp3` and `dr_flac`.
|
|
199
|
+
- The command-line tool, and the unused Python files `libspeech/core.py` and `libspeech/__main__.py`
|
|
200
|
+
(0 % coverage, leftovers of an earlier split).
|
|
201
|
+
|
|
202
|
+
## 0.2.0 (2026-09-27)
|
|
203
|
+
|
|
204
|
+
### Fixed
|
|
205
|
+
- The CPython 3.12 wheel got the wrong ABI tag: the `CIBW_ENVIRONMENT_CP312` variable did nothing
|
|
206
|
+
(cibuildwheel ignores Python-version suffixes) and was removed; `tool.cibuildwheel.overrides` now forces
|
|
207
|
+
`cp312-abi3`.
|
|
208
|
+
- Clang's `-Wc23-extensions` warning caused by the vendored miniaudio is silenced.
|
|
209
|
+
|
|
210
|
+
## 0.1.1 (2026-09-26)
|
|
211
|
+
|
|
212
|
+
### Fixed
|
|
213
|
+
- Linux wheels ship and load ONNX Runtime under its SONAME (`libonnxruntime.so.1`) instead of the
|
|
214
|
+
fully-versioned file name; CMake's `install()` followed the symlinks and shipped duplicate ~20 MB copies.
|
|
215
|
+
|
|
216
|
+
## 0.1.0 (2026-09-26)
|
|
217
|
+
|
|
218
|
+
First tagged release. Everything from 2026-08-27 up to the first release:
|
|
219
|
+
|
|
220
|
+
### Added
|
|
221
|
+
- `speech::dsp` as a standalone static library (`speech_dsp`), a direct DCT-II implementation, and an STFT
|
|
222
|
+
of its own; AudioFlux is no longer a submodule (a subset of its C sources lives in `src/third_party/`,
|
|
223
|
+
moved there from `src/vendor/`); `fftObj_idct()`'s input mutation is documented; `resampleObj_setSamplate`
|
|
224
|
+
handles identity resamples.
|
|
225
|
+
- `BUILD_MODELS` (replaces `SPEECH_DSP_ONLY`) to build the DSP layer alone, and a unit-test build option.
|
|
226
|
+
- Python bindings for the speech models (`bind_models`), Python tests, version handling
|
|
227
|
+
(`include/libspeech/version.h`), `CONTRIBUTING.md`, a standalone benchmarking project for STFT.
|
|
228
|
+
- Model downloads use `httpp` (HTTP client with a progress bar), replacing httplib, Mbed TLS and indicators.
|
|
229
|
+
- CI: a matrix build for CMake and an orchestrator for the wheels and the release.
|
|
230
|
+
|
|
231
|
+
### Fixed
|
|
232
|
+
- Windows/MSVC: compilation (`NOMINMAX`, `M_PI`, `setenv`), AudioFlux and ONNX Runtime compatibility,
|
|
233
|
+
public API symbols exported from the DLL, static library members forced into `speech.dll`, ONNX Runtime and
|
|
234
|
+
httpp DLLs copied beside executables, `speech.dll` installed in the wheel, DLL load failures diagnosed.
|
|
235
|
+
- macOS: arm64 suffix for ONNX Runtime, universal2 ONNX Runtime and dylib names, deployment target 13.3,
|
|
236
|
+
wheel repair.
|
|
237
|
+
- Wheels: `$ORIGIN` RPATH and the ONNX Runtime SONAME shipped; musllinux and win32 wheels are skipped (ONNX
|
|
238
|
+
Runtime is glibc-only); the runtime library file names are baked into `_about`; httpp is required
|
|
239
|
+
unconditionally and loaded from pip instead of being bundled; the `pefile` dependency was replaced by an
|
|
240
|
+
inline PE import-table parser and then removed; Python bindings consolidated with explicit install rules for
|
|
241
|
+
the nested package.
|
|
242
|
+
|
|
243
|
+
## Before 0.1.0 (2025-03-14 to 2025-03-31)
|
|
244
|
+
|
|
245
|
+
The first prototype, in the order of the commits:
|
|
246
|
+
- Audio I/O with miniaudio and dr_libs, a `speech` namespace for `Audio`, a fixed `play()`, Python audio
|
|
247
|
+
bindings, `seconds`, a format function and `operator=`.
|
|
248
|
+
- ONNX Runtime support with a base model class, model download with a progress bar (indicators, then a
|
|
249
|
+
generated progress-bar source), and Silero VAD (fixed on 2025-03-17).
|
|
250
|
+
- AudioFlux (first as a submodule, then static) and `resample`; glog replaced by AixLog.
|
|
251
|
+
- A GitHub workflow, a different way to install onnxruntime for CPython, a simple HTML test, README and the
|
|
252
|
+
libspeech logo (many iterations).
|
|
@@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.19)
|
|
|
3
3
|
option(BUILD_PYTHON "export python module" off)
|
|
4
4
|
option(BUILD_TESTS "build unit tests (speech::dsp only, no ONNXRuntime/httpp needed)" on)
|
|
5
5
|
option(BUILD_MODELS "build speech::models + the speech library (needs ONNXRuntime download + the httpp package); off configures speech::dsp + tests only" on)
|
|
6
|
-
option(BUILD_DOCS "build the speech_docs Doxygen
|
|
6
|
+
option(BUILD_DOCS "build the speech_docs targets: Doxygen C++ docs, Sphinx Python docs, index and pages (docs/)" off)
|
|
7
7
|
option(BUILD_COVERAGE "instrument speech_dsp with --coverage and enable the speech_coverage_cpp_dsp target (needs lcov/genhtml); OFF by default so a normal build isn't broken just because lcov happens to be installed" off)
|
|
8
8
|
|
|
9
9
|
set(CMAKE_C_STANDARD 99 CACHE STRING "C version selection")
|
|
@@ -98,6 +98,11 @@ target_include_directories(speech_dsp
|
|
|
98
98
|
PRIVATE src/third_party/audioflux/src # private AudioFlux headers (fft_algorithm.h, stft_algorithm.h, ...)
|
|
99
99
|
)
|
|
100
100
|
target_link_libraries(speech_dsp PUBLIC audioflux)
|
|
101
|
+
# The STFT/MFCC frame loops carry `#pragma omp`; cmake/AudioFlux.cmake only links the
|
|
102
|
+
# C flavour of OpenMP (for AudioFlux's own C code), so the C++ flavour is linked here.
|
|
103
|
+
if(LIBSPEECH_ENABLE_OPENMP AND OpenMP_CXX_FOUND)
|
|
104
|
+
target_link_libraries(speech_dsp PUBLIC OpenMP::OpenMP_CXX)
|
|
105
|
+
endif()
|
|
101
106
|
|
|
102
107
|
# See include/libspeech/export.h -- this makes SPEECH_API expand to
|
|
103
108
|
# __declspec(dllexport) for FFT/STFT/MFCC/Resample when compiled here (as
|
|
@@ -110,15 +115,15 @@ if(BUILD_TESTS)
|
|
|
110
115
|
add_subdirectory(tests)
|
|
111
116
|
endif()
|
|
112
117
|
|
|
113
|
-
if(BUILD_DOCS)
|
|
114
|
-
add_subdirectory(docs)
|
|
115
|
-
endif()
|
|
116
|
-
|
|
117
118
|
if(NOT BUILD_MODELS)
|
|
118
119
|
message(STATUS "BUILD_MODELS=off: configuring speech::dsp + tests only, skipping ONNXRuntime/models/audio I/O.")
|
|
119
120
|
if(BUILD_TESTS)
|
|
120
121
|
speech_coverage_finalize()
|
|
121
122
|
endif()
|
|
123
|
+
# C++ docs only: the Python docs need the bindings, which this configuration skips
|
|
124
|
+
if(BUILD_DOCS)
|
|
125
|
+
add_subdirectory(docs)
|
|
126
|
+
endif()
|
|
122
127
|
return()
|
|
123
128
|
endif()
|
|
124
129
|
|
|
@@ -338,7 +343,7 @@ elseif(BUILD_PYTHON)
|
|
|
338
343
|
# to support a much older pip.
|
|
339
344
|
execute_process(
|
|
340
345
|
COMMAND "${Python3_EXECUTABLE}" -m pip install --break-system-packages
|
|
341
|
-
nanobind ninja pytest-xdist pip-tools # build requirements
|
|
346
|
+
nanobind ninja numpy pytest-xdist pip-tools # build + test requirements
|
|
342
347
|
OUTPUT_QUIET COMMAND_ERROR_IS_FATAL ANY
|
|
343
348
|
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
|
344
349
|
)
|
|
@@ -369,230 +374,12 @@ endif()
|
|
|
369
374
|
|
|
370
375
|
|
|
371
376
|
if(DEFINED PYTHON_PROJECT_NAME)
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
OPTIONAL_COMPONENTS Development.SABIModule)
|
|
375
|
-
find_package(nanobind CONFIG REQUIRED)
|
|
376
|
-
|
|
377
|
-
set(NB_MODULE _about)
|
|
378
|
-
nanobind_add_module(${NB_MODULE} STABLE_ABI NB_STATIC ${PROJECT_SOURCE_DIR}/src/bindings/python/about.cpp)
|
|
379
|
-
libspeech_set_origin_rpath(${NB_MODULE})
|
|
380
|
-
|
|
381
|
-
# __init__.py's cdll.LoadLibrary() calls need the *exact* on-disk
|
|
382
|
-
# filename of each preloaded runtime library (speech itself, httpp,
|
|
383
|
-
# ONNXRuntime) -- these vary by platform (libspeech.so / speech.dll /
|
|
384
|
-
# libspeech.dylib, etc.) and, for ONNXRuntime, by version too. RPATH
|
|
385
|
-
# (see libspeech_set_origin_rpath above) can't help with any of this:
|
|
386
|
-
# it only lets the OS loader resolve a DT_NEEDED entry when one
|
|
387
|
-
# already-loaded .so pulls in another at normal link time. ctypes'
|
|
388
|
-
# cdll.LoadLibrary() is a direct, explicit dlopen()/LoadLibrary() call
|
|
389
|
-
# from Python itself, entirely bypassing that mechanism -- it needs the
|
|
390
|
-
# literal filename handed to it, RPATH or not.
|
|
391
|
-
#
|
|
392
|
-
# Rather than have __init__.py guess that filename per-platform (with
|
|
393
|
-
# if/else branches or fragile globs), compute it once, here, where
|
|
394
|
-
# CMake already knows it precisely, and bake it into _about (already a
|
|
395
|
-
# tiny, dependency-free nanobind module that __init__.py imports first,
|
|
396
|
-
# for __version__) as extra module attributes -- alongside __version__,
|
|
397
|
-
# the same way this file already bakes VERSION_INFO in below.
|
|
398
|
-
# $<TARGET_FILE_NAME:...> is a generator expression, resolved once CMake
|
|
399
|
-
# knows the real output name of each target.
|
|
400
|
-
# On Linux, ship (and load) the library under its SONAME
|
|
401
|
-
# (libonnxruntime.so.1) rather than the fully-versioned filename
|
|
402
|
-
# (libonnxruntime.so.1.21.0): both names used to be installed as full
|
|
403
|
-
# ~20MB copies (the SONAME file is a symlink on the upstream release
|
|
404
|
-
# tarball, but CMake's install(FILES ...)/file(COPY ...) dereference
|
|
405
|
-
# symlinks, and it turns out the wheel-building step also flattens an
|
|
406
|
-
# install-time symlink back into a second real copy when zipping -- so
|
|
407
|
-
# there is no way to keep both names *and* avoid shipping the bytes
|
|
408
|
-
# twice). Since the SONAME is the one name every consumer .so's
|
|
409
|
-
# DT_NEEDED entry actually requires at runtime, standardize the
|
|
410
|
-
# explicit ctypes preload in __init__.py on that same name too and
|
|
411
|
-
# stop installing the fully-versioned name altogether -- one file,
|
|
412
|
-
# one name, used both places. Windows/macOS have no such SONAME split
|
|
413
|
-
# (see cmake/ONNXRuntime.cmake) so they keep using ONNXRUNTIME_LIB_FILE.
|
|
414
|
-
if(ONNXRUNTIME_SONAME_FILE)
|
|
415
|
-
get_filename_component(_ONNXRUNTIME_LIB_FILENAME "${ONNXRUNTIME_SONAME_FILE}" NAME)
|
|
416
|
-
else()
|
|
417
|
-
get_filename_component(_ONNXRUNTIME_LIB_FILENAME "${ONNXRUNTIME_LIB_FILE}" NAME)
|
|
418
|
-
endif()
|
|
419
|
-
target_compile_definitions(${NB_MODULE} PRIVATE
|
|
420
|
-
VERSION_INFO=${PROJECT_VERSION}
|
|
421
|
-
NB_MODULE_NAME=${NB_MODULE}
|
|
422
|
-
LIB_PATH=$<TARGET_FILE_NAME:speech>
|
|
423
|
-
HTTPP_LIB_PATH=$<TARGET_FILE_NAME:httpp::httpp_core>
|
|
424
|
-
ONNXRUNTIME_LIB_PATH=${_ONNXRUNTIME_LIB_FILENAME})
|
|
425
|
-
|
|
426
|
-
# CONFIGURE_DEPENDS: best-effort auto-detection of new bind_*.cpp files
|
|
427
|
-
# without a manual reconfigure. This is NOT guaranteed by CMake to work
|
|
428
|
-
# on every generator/environment (e.g. observed unreliable with the Unix
|
|
429
|
-
# Makefiles generator in some setups) -- if a newly added binding module
|
|
430
|
-
# doesn't show up after `cmake --build`, run `cmake ..` (or delete and
|
|
431
|
-
# recreate the build directory) once to force a fresh configure.
|
|
432
|
-
file(GLOB PYTHON_BIND_MODULES_PATH CONFIGURE_DEPENDS ${PROJECT_SOURCE_DIR}/src/bindings/python/bind_*.cpp)
|
|
433
|
-
set(PYTHON_BIND_MODULES "${NB_MODULE}")
|
|
434
|
-
foreach(NB_MODULE_SOURCE IN LISTS PYTHON_BIND_MODULES_PATH)
|
|
435
|
-
get_filename_component(NB_MODULE ${NB_MODULE_SOURCE} NAME_WE)
|
|
436
|
-
string(REGEX REPLACE "bind_(.*)" "speech_\\1_py" NB_MODULE ${NB_MODULE})
|
|
437
|
-
list(APPEND PYTHON_BIND_MODULES ${NB_MODULE})
|
|
438
|
-
|
|
439
|
-
message(STATUS "Found module: ${NB_MODULE}")
|
|
440
|
-
|
|
441
|
-
# We are now ready to compile the actual extension module
|
|
442
|
-
nanobind_add_module(
|
|
443
|
-
# Name of the extension
|
|
444
|
-
${NB_MODULE}
|
|
445
|
-
|
|
446
|
-
# Target the stable ABI for Python 3.12+, which reduces
|
|
447
|
-
# the number of binary wheels that must be built. This
|
|
448
|
-
# does nothing on older Python versions
|
|
449
|
-
STABLE_ABI
|
|
450
|
-
|
|
451
|
-
# Build libnanobind statically and merge it into the
|
|
452
|
-
# extension (which itself remains a shared library)
|
|
453
|
-
#
|
|
454
|
-
# If your project builds multiple extensions, you can
|
|
455
|
-
# replace this flag by NB_SHARED to conserve space by
|
|
456
|
-
# reusing a shared libnanobind across libraries
|
|
457
|
-
NB_STATIC
|
|
458
|
-
|
|
459
|
-
# Source code goes here -- one file per module (ctoon's
|
|
460
|
-
# convention: src/bindings/python/bind_X.cpp -> speech_X_py),
|
|
461
|
-
# unlike _about above which is a single nanobind_add_module
|
|
462
|
-
# call named directly rather than discovered by this glob.
|
|
463
|
-
${NB_MODULE_SOURCE}
|
|
464
|
-
)
|
|
377
|
+
add_subdirectory(${PROJECT_SOURCE_DIR}/src/bindings/python)
|
|
378
|
+
endif()
|
|
465
379
|
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
libspeech_set_origin_rpath(${NB_MODULE})
|
|
470
|
-
endforeach()
|
|
471
|
-
|
|
472
|
-
if(DEFINED SKBUILD)
|
|
473
|
-
# `speech` (line ~221: add_library(speech SHARED ...)) is a real
|
|
474
|
-
# SHARED library, not a MODULE (unlike ${PYTHON_BIND_MODULES}, the
|
|
475
|
-
# nanobind extension .pyd/.so files, which install fine under
|
|
476
|
-
# LIBRARY alone on every platform). CMake's install(TARGETS) docs
|
|
477
|
-
# spell out the platform split this causes: "For DLL platforms
|
|
478
|
-
# (Windows) the DLL part of a shared library is treated as a
|
|
479
|
-
# RUNTIME target, while the corresponding import library is
|
|
480
|
-
# treated as an ARCHIVE target. On non-DLL platforms shared
|
|
481
|
-
# libraries are treated as LIBRARY targets." LIBRARY DESTINATION
|
|
482
|
-
# alone is therefore complete on Linux/macOS but, on Windows,
|
|
483
|
-
# speech.dll itself belongs to a target kind (RUNTIME) this rule
|
|
484
|
-
# never mentions -- so it silently isn't installed at all: no
|
|
485
|
-
# error, no warning, just a wheel with every OTHER file in place
|
|
486
|
-
# and speech.dll simply missing, which is indistinguishable at
|
|
487
|
-
# runtime from "installed but failed to load one of its
|
|
488
|
-
# dependencies" (identical ctypes error either way) until you
|
|
489
|
-
# actually go looking for the file.
|
|
490
|
-
install (TARGETS ${PYTHON_BIND_MODULES} speech
|
|
491
|
-
CONFIGURATIONS Release
|
|
492
|
-
LIBRARY DESTINATION ${PYTHON_PROJECT_NAME}
|
|
493
|
-
RUNTIME DESTINATION ${PYTHON_PROJECT_NAME})
|
|
494
|
-
|
|
495
|
-
# The pure-Python files (currently just __init__.py) need
|
|
496
|
-
# their own explicit install rule -- scikit-build-core's automatic
|
|
497
|
-
# Python-package discovery only looks for an immediate src/<name>
|
|
498
|
-
# layout, so now that the package lives nested under
|
|
499
|
-
# src/bindings/python/${PROJECT_NAME} (ctoon's own convention,
|
|
500
|
-
# matched here on request), it no longer finds it on its own: the
|
|
501
|
-
# compiled extensions above still land in the wheel fine (that
|
|
502
|
-
# goes through install(TARGETS), unrelated to this discovery), but
|
|
503
|
-
# without this, the wheel would ship no __init__.py at all --
|
|
504
|
-
# `import libspeech` would "succeed" only as an empty implicit
|
|
505
|
-
# namespace package, silently missing everything real. Same
|
|
506
|
-
# pattern ctoon itself uses for exactly this reason (see its
|
|
507
|
-
# src/bindings/python/CMakeLists.txt).
|
|
508
|
-
install(DIRECTORY ${PROJECT_SOURCE_DIR}/src/bindings/python/${PROJECT_NAME}/
|
|
509
|
-
DESTINATION ${SKBUILD_PROJECT_NAME}
|
|
510
|
-
FILES_MATCHING PATTERN "*.py")
|
|
511
|
-
|
|
512
|
-
# ONNXRuntime ships as a shared library that the compiled extension
|
|
513
|
-
# modules dlopen symbols from at import time (see __init__.py's
|
|
514
|
-
# cdll.LoadLibrary() calls), so it has to be copied into the wheel
|
|
515
|
-
# next to those extensions rather than relied upon via RPATH:
|
|
516
|
-
# RPATH would only point back at wherever it got downloaded to on
|
|
517
|
-
# the *build* machine, which has no reason to exist on whatever
|
|
518
|
-
# machine later installs this wheel.
|
|
519
|
-
#
|
|
520
|
-
# httpp is NOT bundled here -- __init__.py loads it from the
|
|
521
|
-
# separately pip-installed httpp package instead (see __init__.py).
|
|
522
|
-
#
|
|
523
|
-
# ONNXRUNTIME_SONAME_FILE (see cmake/ONNXRuntime.cmake) is the name
|
|
524
|
-
# every compiled .so's DT_NEEDED entry actually requires at
|
|
525
|
-
# runtime (libonnxruntime.so.1 on Linux), not the fully-versioned
|
|
526
|
-
# ONNXRUNTIME_LIB_FILE one -- without a file by that exact name,
|
|
527
|
-
# `auditwheel repair` fails to find/bundle it at all.
|
|
528
|
-
#
|
|
529
|
-
# On disk (in the upstream release tarball) that name is a
|
|
530
|
-
# symlink to ONNXRUNTIME_LIB_FILE, which is why it used to look
|
|
531
|
-
# free to ship both: but CMake's install(FILES ...) dereferences
|
|
532
|
-
# symlinks, AND the wheel-building step separately flattens an
|
|
533
|
-
# install-time symlink back into a real copy when zipping -- so
|
|
534
|
-
# shipping *both* names always costs a full second ~20MB copy no
|
|
535
|
-
# matter which way the symlink is recreated. Since the SONAME is
|
|
536
|
-
# the only name anything actually needs to dlopen/link against at
|
|
537
|
-
# runtime (see the ONNXRUNTIME_LIB_PATH comment above), install
|
|
538
|
-
# the real bytes under that name ONLY and drop the fully-versioned
|
|
539
|
-
# name from the wheel entirely -- one ~20MB file instead of two.
|
|
540
|
-
# ONNXRUNTIME_PROVIDERS_SHARED_FILE (Windows only) is the companion
|
|
541
|
-
# onnxruntime_providers_shared.dll upstream ships alongside
|
|
542
|
-
# onnxruntime.dll -- see cmake/ONNXRuntime.cmake for why.
|
|
543
|
-
if(ONNXRUNTIME_SONAME_FILE)
|
|
544
|
-
get_filename_component(_ONNXRUNTIME_SONAME_FILENAME "${ONNXRUNTIME_SONAME_FILE}" NAME)
|
|
545
|
-
# RENAME so only one copy of the (large) file is ever written
|
|
546
|
-
# -- under the SONAME, not the fully-versioned name.
|
|
547
|
-
install(FILES "${ONNXRUNTIME_LIB_FILE}"
|
|
548
|
-
DESTINATION ${SKBUILD_PROJECT_NAME}
|
|
549
|
-
RENAME "${_ONNXRUNTIME_SONAME_FILENAME}")
|
|
550
|
-
else()
|
|
551
|
-
install(FILES "${ONNXRUNTIME_LIB_FILE}"
|
|
552
|
-
DESTINATION ${SKBUILD_PROJECT_NAME})
|
|
553
|
-
endif()
|
|
554
|
-
if(ONNXRUNTIME_PROVIDERS_SHARED_FILE)
|
|
555
|
-
install(FILES "${ONNXRUNTIME_PROVIDERS_SHARED_FILE}"
|
|
556
|
-
DESTINATION ${SKBUILD_PROJECT_NAME})
|
|
557
|
-
endif()
|
|
558
|
-
else()
|
|
559
|
-
file(COPY ${PROJECT_SOURCE_DIR}/src/bindings/python/${PROJECT_NAME} DESTINATION ${PYTHON_PROJECT_NAME})
|
|
560
|
-
if(ONNXRUNTIME_SONAME_FILE)
|
|
561
|
-
# Same fix as the scikit-build install(FILES ...) branch above:
|
|
562
|
-
# ship the real bytes under the SONAME only (one ~20MB file,
|
|
563
|
-
# not the fully-versioned name too), since that's the only
|
|
564
|
-
# name anything actually dlopens/links against at runtime.
|
|
565
|
-
get_filename_component(_ONNXRUNTIME_SONAME_FILENAME "${ONNXRUNTIME_SONAME_FILE}" NAME)
|
|
566
|
-
file(COPY_FILE "${ONNXRUNTIME_LIB_FILE}"
|
|
567
|
-
"${PYTHON_PROJECT_NAME}/${PROJECT_NAME}/${_ONNXRUNTIME_SONAME_FILENAME}")
|
|
568
|
-
else()
|
|
569
|
-
file(COPY ${ONNXRUNTIME_LIB_FILE} DESTINATION ${PYTHON_PROJECT_NAME}/${PROJECT_NAME})
|
|
570
|
-
endif()
|
|
571
|
-
if(ONNXRUNTIME_PROVIDERS_SHARED_FILE)
|
|
572
|
-
file(COPY ${ONNXRUNTIME_PROVIDERS_SHARED_FILE} DESTINATION ${PYTHON_PROJECT_NAME}/${PROJECT_NAME})
|
|
573
|
-
endif()
|
|
574
|
-
|
|
575
|
-
foreach(_core IN LISTS PYTHON_BIND_MODULES)
|
|
576
|
-
set_target_properties(${_core} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PYTHON_PROJECT_NAME}/${PROJECT_NAME})
|
|
577
|
-
endforeach()
|
|
578
|
-
|
|
579
|
-
# speech itself must land inside the package directory too --
|
|
580
|
-
# __init__.py's `cdll.LoadLibrary(_here / LIB_PATH)` looks for it
|
|
581
|
-
# right next to _audio.abi3.so/_about.abi3.so, not in the
|
|
582
|
-
# top-level build directory (where it would otherwise default to).
|
|
583
|
-
# Both output-directory properties are needed for the same DLL-
|
|
584
|
-
# platform-split reason as the SKBUILD install(TARGETS) rule above:
|
|
585
|
-
# LIBRARY_OUTPUT_DIRECTORY alone places the .dll correctly on
|
|
586
|
-
# Linux/macOS but is silently ignored for it on Windows, where a
|
|
587
|
-
# SHARED library's DLL is governed by RUNTIME_OUTPUT_DIRECTORY
|
|
588
|
-
# instead (LIBRARY_OUTPUT_DIRECTORY only affects its .lib import
|
|
589
|
-
# library there) -- so on Windows the .dll would otherwise default
|
|
590
|
-
# to landing directly under ${PYTHON_PROJECT_NAME} instead of
|
|
591
|
-
# ${PYTHON_PROJECT_NAME}/${PROJECT_NAME}, right alongside it.
|
|
592
|
-
set_target_properties(speech PROPERTIES
|
|
593
|
-
LIBRARY_OUTPUT_DIRECTORY ${PYTHON_PROJECT_NAME}/${PROJECT_NAME}
|
|
594
|
-
RUNTIME_OUTPUT_DIRECTORY ${PYTHON_PROJECT_NAME}/${PROJECT_NAME})
|
|
595
|
-
endif()
|
|
380
|
+
# After the Python bindings: the Sphinx docs import the package staged in the build tree
|
|
381
|
+
if(BUILD_DOCS)
|
|
382
|
+
add_subdirectory(docs)
|
|
596
383
|
endif()
|
|
597
384
|
|
|
598
385
|
# Python tests need the bindings fully configured above (the _audio target,
|