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.
Files changed (269) hide show
  1. {libspeech-0.3.0 → libspeech-0.4.0}/.github/workflows/cmake.yml +24 -2
  2. {libspeech-0.3.0 → libspeech-0.4.0}/.github/workflows/wheels.yml +3 -1
  3. libspeech-0.4.0/CHANGELOG.md +252 -0
  4. {libspeech-0.3.0 → libspeech-0.4.0}/CMakeLists.txt +16 -229
  5. {libspeech-0.3.0 → libspeech-0.4.0}/CONTRIBUTING.md +43 -8
  6. libspeech-0.4.0/LICENSE +202 -0
  7. libspeech-0.4.0/NOTICE +12 -0
  8. libspeech-0.4.0/PKG-INFO +357 -0
  9. libspeech-0.4.0/README.md +327 -0
  10. {libspeech-0.3.0 → libspeech-0.4.0}/audioflux_issues.md +4 -4
  11. libspeech-0.4.0/benchmarks/.gitignore +3 -0
  12. {libspeech-0.3.0 → libspeech-0.4.0}/benchmarks/CMakeLists.txt +30 -4
  13. libspeech-0.4.0/benchmarks/README.md +83 -0
  14. libspeech-0.4.0/benchmarks/cmake/Download.cmake +26 -0
  15. {libspeech-0.3.0 → libspeech-0.4.0}/benchmarks/cpp/bench_stft.cpp +16 -16
  16. libspeech-0.4.0/benchmarks/profile/README.md +40 -0
  17. libspeech-0.4.0/benchmarks/profile/prof_dct.cpp +15 -0
  18. libspeech-0.4.0/benchmarks/profile/prof_dsp.cpp +51 -0
  19. libspeech-0.4.0/benchmarks/profile/prof_dsp.py +122 -0
  20. libspeech-0.4.0/benchmarks/profile/prof_models.cpp +78 -0
  21. libspeech-0.4.0/benchmarks/python/CMakeLists.txt +163 -0
  22. libspeech-0.4.0/benchmarks/python/bench_op_memory_driver.py +85 -0
  23. libspeech-0.4.0/benchmarks/python/bench_op_memory_one.py +91 -0
  24. libspeech-0.4.0/benchmarks/python/bench_sizes.py +61 -0
  25. libspeech-0.4.0/benchmarks/python/bench_throughput.py +106 -0
  26. libspeech-0.4.0/benchmarks/python/corpus.py +91 -0
  27. libspeech-0.4.0/benchmarks/python/ops.py +254 -0
  28. libspeech-0.4.0/benchmarks/python/requirements.txt +13 -0
  29. libspeech-0.4.0/benchmarks/python/system_info.py +74 -0
  30. libspeech-0.4.0/benchmarks/report/CMakeLists.txt +58 -0
  31. libspeech-0.4.0/benchmarks/report/generate_report.py +138 -0
  32. libspeech-0.4.0/benchmarks/report/template.html.jinja2 +128 -0
  33. {libspeech-0.3.0 → libspeech-0.4.0}/checklist.md +18 -23
  34. libspeech-0.4.0/data/models.csv +15 -0
  35. libspeech-0.4.0/docs/CMakeLists.txt +176 -0
  36. libspeech-0.4.0/docs/CreateDocs.cmake +52 -0
  37. libspeech-0.4.0/docs/FinishPages.cmake +42 -0
  38. libspeech-0.4.0/docs/InjectComment.cmake +85 -0
  39. libspeech-0.4.0/docs/SpeechPages.cmake +198 -0
  40. libspeech-0.4.0/docs/api-renames.md +112 -0
  41. libspeech-0.4.0/docs/convert_page.py +392 -0
  42. libspeech-0.4.0/docs/cpp/CreateDocs.cmake +62 -0
  43. libspeech-0.4.0/docs/cpp/Doxyfile.in +62 -0
  44. libspeech-0.4.0/docs/cpp/footer.html.in +27 -0
  45. libspeech-0.4.0/docs/cpp/index-docs.json +9 -0
  46. libspeech-0.4.0/docs/cpp/index-example.txt +24 -0
  47. libspeech-0.4.0/docs/cpp/index-install.txt +19 -0
  48. libspeech-0.4.0/docs/cpp/mainpage.md +68 -0
  49. libspeech-0.4.0/docs/generate_index.py +196 -0
  50. libspeech-0.4.0/docs/images/libspeech-logo.txt +7 -0
  51. libspeech-0.4.0/docs/index.html.in +286 -0
  52. libspeech-0.4.0/docs/initial_comment.in +15 -0
  53. libspeech-0.4.0/docs/page.html.in +419 -0
  54. libspeech-0.4.0/docs/python/CreateDocs.cmake +59 -0
  55. libspeech-0.4.0/docs/python/index-docs.json +9 -0
  56. libspeech-0.4.0/docs/python/index-example.txt +21 -0
  57. libspeech-0.4.0/docs/python/index-install.txt +11 -0
  58. libspeech-0.4.0/docs/python/source/_static/custom.css +233 -0
  59. libspeech-0.4.0/docs/python/source/_themes/speech/layout.html +202 -0
  60. libspeech-0.4.0/docs/python/source/_themes/speech/page.html +2 -0
  61. libspeech-0.4.0/docs/python/source/_themes/speech/speech-footer.html +36 -0
  62. libspeech-0.4.0/docs/python/source/_themes/speech/speech-nav.html +14 -0
  63. libspeech-0.4.0/docs/python/source/_themes/speech/speech-topbar.html +27 -0
  64. libspeech-0.4.0/docs/python/source/_themes/speech/static/speech-docs.css +418 -0
  65. libspeech-0.4.0/docs/python/source/_themes/speech/static/speech-sphinx.css +741 -0
  66. libspeech-0.4.0/docs/python/source/_themes/speech/theme.toml +9 -0
  67. libspeech-0.4.0/docs/python/source/conf.py +87 -0
  68. libspeech-0.4.0/docs/python/source/dsp.rst +35 -0
  69. libspeech-0.4.0/docs/python/source/index.rst +32 -0
  70. libspeech-0.4.0/docs/python/source/io.rst +5 -0
  71. libspeech-0.4.0/docs/python/source/models.rst +9 -0
  72. libspeech-0.4.0/docs/python/source/utils.rst +17 -0
  73. libspeech-0.4.0/docs/section.html.in +471 -0
  74. libspeech-0.4.0/docs/speech-docs.css +436 -0
  75. libspeech-0.4.0/docs/supported_langs.json +49 -0
  76. {libspeech-0.3.0 → libspeech-0.4.0}/examples/common.h +1 -1
  77. {libspeech-0.3.0 → libspeech-0.4.0}/examples/main.cpp +40 -35
  78. {libspeech-0.3.0 → libspeech-0.4.0}/examples/silero_app/main.cpp +8 -8
  79. libspeech-0.4.0/include/libspeech/audio.h +52 -0
  80. libspeech-0.4.0/include/libspeech/detail/log.h +197 -0
  81. libspeech-0.4.0/include/libspeech/detail/uninit_vector.h +48 -0
  82. {libspeech-0.3.0 → libspeech-0.4.0}/include/libspeech/dsp/dct.h +29 -4
  83. libspeech-0.4.0/include/libspeech/dsp/fft.h +128 -0
  84. libspeech-0.4.0/include/libspeech/dsp/mfcc.h +99 -0
  85. libspeech-0.4.0/include/libspeech/dsp/resample.h +123 -0
  86. libspeech-0.4.0/include/libspeech/dsp/simd.h +49 -0
  87. libspeech-0.4.0/include/libspeech/dsp/stft.h +211 -0
  88. {libspeech-0.3.0 → libspeech-0.4.0}/include/libspeech/dsp/window.h +3 -4
  89. libspeech-0.4.0/include/libspeech/dsp/window_type.h +34 -0
  90. libspeech-0.4.0/include/libspeech/models/base_model.h +51 -0
  91. libspeech-0.4.0/include/libspeech/models/denoiser.h +106 -0
  92. libspeech-0.4.0/include/libspeech/models/dpdfnet_denoiser.h +64 -0
  93. libspeech-0.4.0/include/libspeech/models/facebook_denoiser.h +45 -0
  94. libspeech-0.4.0/include/libspeech/models/gtcrn_denoiser.h +58 -0
  95. libspeech-0.4.0/include/libspeech/models/model_files.h +73 -0
  96. {libspeech-0.3.0 → libspeech-0.4.0}/include/libspeech/models/onnx_model.h +5 -3
  97. libspeech-0.4.0/include/libspeech/models/providers.h +27 -0
  98. {libspeech-0.3.0 → libspeech-0.4.0}/include/libspeech/models/silero_vad.h +13 -12
  99. libspeech-0.4.0/include/libspeech/models/speechbrain_denoiser.h +45 -0
  100. libspeech-0.4.0/include/libspeech/span.h +420 -0
  101. libspeech-0.4.0/include/libspeech/utils/log.h +43 -0
  102. {libspeech-0.3.0 → libspeech-0.4.0}/include/libspeech/utils/utils.h +11 -4
  103. {libspeech-0.3.0 → libspeech-0.4.0}/include/libspeech/version.h +1 -1
  104. {libspeech-0.3.0 → libspeech-0.4.0}/pyproject.toml +49 -5
  105. libspeech-0.4.0/src/audio.cpp +436 -0
  106. libspeech-0.4.0/src/bindings/python/CMakeLists.txt +275 -0
  107. {libspeech-0.3.0 → libspeech-0.4.0}/src/bindings/python/bind_audio.cpp +14 -14
  108. libspeech-0.4.0/src/bindings/python/bind_dsp.cpp +374 -0
  109. {libspeech-0.3.0 → libspeech-0.4.0}/src/bindings/python/bind_io.cpp +29 -14
  110. libspeech-0.4.0/src/bindings/python/bind_models.cpp +214 -0
  111. {libspeech-0.3.0 → libspeech-0.4.0}/src/bindings/python/libspeech/__init__.py +30 -1
  112. libspeech-0.4.0/src/bindings/python/libspeech/_functional.py +232 -0
  113. libspeech-0.4.0/src/bindings/python/libspeech/py.typed +0 -0
  114. libspeech-0.4.0/src/bindings/python/ndarray_util.h +54 -0
  115. libspeech-0.4.0/src/dsp/dct.cpp +148 -0
  116. libspeech-0.4.0/src/dsp/fft.cpp +232 -0
  117. libspeech-0.4.0/src/dsp/mfcc.cpp +199 -0
  118. libspeech-0.4.0/src/dsp/real_fft.cpp +262 -0
  119. libspeech-0.4.0/src/dsp/real_fft.h +89 -0
  120. libspeech-0.4.0/src/dsp/resample.cpp +746 -0
  121. libspeech-0.4.0/src/dsp/simd.cpp +81 -0
  122. libspeech-0.4.0/src/dsp/simd_internal.h +97 -0
  123. libspeech-0.4.0/src/dsp/stft.cpp +540 -0
  124. {libspeech-0.3.0 → libspeech-0.4.0}/src/dsp/window.cpp +8 -6
  125. libspeech-0.4.0/src/dsp/window_type_internal.h +38 -0
  126. libspeech-0.4.0/src/models/base_model.cpp +51 -0
  127. libspeech-0.4.0/src/models/denoiser.cpp +85 -0
  128. libspeech-0.4.0/src/models/dpdfnet_denoiser.cpp +190 -0
  129. libspeech-0.4.0/src/models/facebook_denoiser.cpp +32 -0
  130. libspeech-0.4.0/src/models/gtcrn_denoiser.cpp +124 -0
  131. libspeech-0.4.0/src/models/model_files.cpp +266 -0
  132. libspeech-0.4.0/src/models/model_files_detail.h +39 -0
  133. libspeech-0.4.0/src/models/onnx_denoiser_impl.h +99 -0
  134. {libspeech-0.3.0 → libspeech-0.4.0}/src/models/onnx_model.cpp +5 -5
  135. libspeech-0.4.0/src/models/providers.cpp +31 -0
  136. {libspeech-0.3.0 → libspeech-0.4.0}/src/models/silero_vad.cpp +15 -15
  137. libspeech-0.4.0/src/models/spectral.h +188 -0
  138. libspeech-0.4.0/src/models/speechbrain_denoiser.cpp +27 -0
  139. libspeech-0.4.0/src/third_party/audioflux/UPSTREAM_PATCHES.md +14 -0
  140. {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/src/dsp/resample_algorithm.c +17 -0
  141. {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/src/dsp/resample_algorithm.h +7 -0
  142. libspeech-0.4.0/src/utils/utils.cpp +159 -0
  143. {libspeech-0.3.0 → libspeech-0.4.0}/tests/CMakeLists.txt +3 -0
  144. libspeech-0.4.0/tests/dsp/test_complex_views.cpp +255 -0
  145. {libspeech-0.3.0 → libspeech-0.4.0}/tests/dsp/test_dct.cpp +10 -10
  146. libspeech-0.4.0/tests/dsp/test_fast_paths.cpp +639 -0
  147. libspeech-0.4.0/tests/dsp/test_fft.cpp +124 -0
  148. libspeech-0.4.0/tests/dsp/test_fft_into.cpp +171 -0
  149. libspeech-0.4.0/tests/dsp/test_istft.cpp +188 -0
  150. libspeech-0.4.0/tests/dsp/test_mfcc.cpp +128 -0
  151. libspeech-0.4.0/tests/dsp/test_resample.cpp +134 -0
  152. libspeech-0.4.0/tests/dsp/test_span.cpp +293 -0
  153. libspeech-0.4.0/tests/dsp/test_stft.cpp +102 -0
  154. libspeech-0.4.0/tests/dsp/test_window.cpp +69 -0
  155. {libspeech-0.3.0 → libspeech-0.4.0}/tests/models/CMakeLists.txt +3 -1
  156. {libspeech-0.3.0 → libspeech-0.4.0}/tests/models/test_default_model_cache_dir.cpp +30 -30
  157. libspeech-0.4.0/tests/models/test_denoiser.cpp +98 -0
  158. libspeech-0.4.0/tests/models/test_log.cpp +70 -0
  159. libspeech-0.4.0/tests/models/test_model_files.cpp +483 -0
  160. libspeech-0.4.0/tests/models/test_providers.cpp +24 -0
  161. libspeech-0.4.0/tests/models/test_spectral.cpp +160 -0
  162. {libspeech-0.3.0 → libspeech-0.4.0}/tests/python/CMakeLists.txt +19 -0
  163. libspeech-0.4.0/tests/python/conftest.py +19 -0
  164. {libspeech-0.3.0 → libspeech-0.4.0}/tests/python/test_dsp.py +16 -0
  165. libspeech-0.4.0/tests/python/test_functional.py +197 -0
  166. libspeech-0.4.0/tests/python/test_librosa_compat.py +427 -0
  167. libspeech-0.4.0/tests/python/test_logging.py +107 -0
  168. libspeech-0.4.0/tests/python/test_model_files.py +396 -0
  169. libspeech-0.4.0/tests/python/test_models.py +250 -0
  170. libspeech-0.4.0/tests/python/test_numpy_api.py +426 -0
  171. libspeech-0.4.0/tests/python/test_providers.py +19 -0
  172. libspeech-0.4.0/tests/python/test_simd.py +90 -0
  173. {libspeech-0.3.0 → libspeech-0.4.0}/version.py +2 -2
  174. libspeech-0.3.0/LICENSE +0 -36
  175. libspeech-0.3.0/PKG-INFO +0 -250
  176. libspeech-0.3.0/README.md +0 -224
  177. libspeech-0.3.0/docs/CMakeLists.txt +0 -44
  178. libspeech-0.3.0/include/libspeech/audio.h +0 -46
  179. libspeech-0.3.0/include/libspeech/dsp/fft.h +0 -73
  180. libspeech-0.3.0/include/libspeech/dsp/mfcc.h +0 -72
  181. libspeech-0.3.0/include/libspeech/dsp/resample.h +0 -64
  182. libspeech-0.3.0/include/libspeech/dsp/stft.h +0 -81
  183. libspeech-0.3.0/include/libspeech/models/base_model.h +0 -33
  184. libspeech-0.3.0/include/libspeech/models/denoiser.h +0 -38
  185. libspeech-0.3.0/include/libspeech/models/facebook_denoiser.h +0 -44
  186. libspeech-0.3.0/include/libspeech/models/speechbrain_denoiser.h +0 -44
  187. libspeech-0.3.0/src/audio.cpp +0 -412
  188. libspeech-0.3.0/src/bindings/python/bind_dsp.cpp +0 -85
  189. libspeech-0.3.0/src/bindings/python/bind_models.cpp +0 -58
  190. libspeech-0.3.0/src/dsp/dct.cpp +0 -47
  191. libspeech-0.3.0/src/dsp/fft.cpp +0 -104
  192. libspeech-0.3.0/src/dsp/mfcc.cpp +0 -128
  193. libspeech-0.3.0/src/dsp/resample.cpp +0 -136
  194. libspeech-0.3.0/src/dsp/stft.cpp +0 -124
  195. libspeech-0.3.0/src/models/base_model.cpp +0 -46
  196. libspeech-0.3.0/src/models/denoiser.cpp +0 -22
  197. libspeech-0.3.0/src/models/facebook_denoiser.cpp +0 -75
  198. libspeech-0.3.0/src/models/speechbrain_denoiser.cpp +0 -85
  199. libspeech-0.3.0/src/third_party/audioflux/UPSTREAM_PATCHES.md +0 -6
  200. libspeech-0.3.0/src/utils/utils.cpp +0 -117
  201. libspeech-0.3.0/tests/dsp/test_fft.cpp +0 -124
  202. libspeech-0.3.0/tests/dsp/test_mfcc.cpp +0 -128
  203. libspeech-0.3.0/tests/dsp/test_resample.cpp +0 -82
  204. libspeech-0.3.0/tests/dsp/test_stft.cpp +0 -102
  205. libspeech-0.3.0/tests/dsp/test_window.cpp +0 -67
  206. libspeech-0.3.0/tests/models/test_denoiser.cpp +0 -43
  207. libspeech-0.3.0/tests/python/test_models.py +0 -39
  208. {libspeech-0.3.0 → libspeech-0.4.0}/.clang-format +0 -0
  209. {libspeech-0.3.0 → libspeech-0.4.0}/.github/workflows/orchestrator.yml +0 -0
  210. {libspeech-0.3.0 → libspeech-0.4.0}/.gitignore +0 -0
  211. {libspeech-0.3.0 → libspeech-0.4.0}/.gitmodules +0 -0
  212. {libspeech-0.3.0 → libspeech-0.4.0}/benchmarks/cpp/CMakeLists.txt +0 -0
  213. {libspeech-0.3.0 → libspeech-0.4.0}/cmake/AudioFlux.cmake +0 -0
  214. {libspeech-0.3.0 → libspeech-0.4.0}/cmake/Conan.cmake +0 -0
  215. {libspeech-0.3.0 → libspeech-0.4.0}/cmake/DynamicVersion.cmake +0 -0
  216. {libspeech-0.3.0 → libspeech-0.4.0}/cmake/FixLCovPaths.cmake +0 -0
  217. {libspeech-0.3.0 → libspeech-0.4.0}/cmake/GenerateIframe.cmake +0 -0
  218. {libspeech-0.3.0 → libspeech-0.4.0}/cmake/ONNXRuntime.cmake +0 -0
  219. {libspeech-0.3.0 → libspeech-0.4.0}/cmake/PyProject.cmake +0 -0
  220. {libspeech-0.3.0 → libspeech-0.4.0}/cmake/coverage_iframe.html.in +0 -0
  221. {libspeech-0.3.0 → libspeech-0.4.0}/conanfile.txt +0 -0
  222. {libspeech-0.3.0 → libspeech-0.4.0}/conda.recipe/meta.yaml +0 -0
  223. {libspeech-0.3.0 → libspeech-0.4.0}/docs/Doxyfile.in +0 -0
  224. {libspeech-0.3.0 → libspeech-0.4.0}/docs/logo/README.md +0 -0
  225. {libspeech-0.3.0 → libspeech-0.4.0}/docs/logo/libspeech-logo-pods.svg +0 -0
  226. {libspeech-0.3.0 → libspeech-0.4.0}/docs/logo/libspeech-logo.svg +0 -0
  227. {libspeech-0.3.0 → libspeech-0.4.0}/examples/denoiser_app/controler.h +0 -0
  228. {libspeech-0.3.0 → libspeech-0.4.0}/examples/denoiser_app/main.cpp +0 -0
  229. {libspeech-0.3.0 → libspeech-0.4.0}/git-submodule.sh +0 -0
  230. {libspeech-0.3.0 → libspeech-0.4.0}/include/libspeech/export.h +0 -0
  231. {libspeech-0.3.0 → libspeech-0.4.0}/src/bindings/python/about.cpp +0 -0
  232. {libspeech-0.3.0 → libspeech-0.4.0}/src/speech_umbrella_placeholder.cpp +0 -0
  233. {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/README.md +0 -0
  234. {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/aixlog/LICENSE +0 -0
  235. {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/aixlog/README.md +0 -0
  236. {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/aixlog/include/aixlog.hpp +0 -0
  237. {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/LICENSE.md +0 -0
  238. {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/README.md +0 -0
  239. {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/include/dsp/resample_algorithm.h +0 -0
  240. {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/include/flux_base.h +0 -0
  241. {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/include/stft_algorithm.h +0 -0
  242. {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/include/util/flux_util.h +0 -0
  243. {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/include/util/flux_wave.h +0 -0
  244. {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/include/vector/flux_complex.h +0 -0
  245. {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/include/vector/flux_vector.h +0 -0
  246. {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/src/dsp/fft_algorithm.c +0 -0
  247. {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/src/dsp/fft_algorithm.h +0 -0
  248. {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/src/dsp/filterDesign_fir.c +0 -0
  249. {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/src/dsp/filterDesign_fir.h +0 -0
  250. {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/src/dsp/flux_window.c +0 -0
  251. {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/src/dsp/flux_window.h +0 -0
  252. {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/src/flux_base.h +0 -0
  253. {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/src/stft_algorithm.c +0 -0
  254. {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/src/stft_algorithm.h +0 -0
  255. {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/src/util/flux_util.c +0 -0
  256. {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/src/util/flux_util.h +0 -0
  257. {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/src/util/flux_wave.c +0 -0
  258. {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/src/util/flux_wave.h +0 -0
  259. {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/src/vector/flux_complex.c +0 -0
  260. {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/src/vector/flux_complex.h +0 -0
  261. {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/src/vector/flux_vector.c +0 -0
  262. {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/src/vector/flux_vector.h +0 -0
  263. {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/src/vector/flux_vectorOp.c +0 -0
  264. {libspeech-0.3.0 → libspeech-0.4.0}/src/third_party/audioflux/src/vector/flux_vectorOp.h +0 -0
  265. {libspeech-0.3.0 → libspeech-0.4.0}/tests/coverage_dashboard.html.in +0 -0
  266. {libspeech-0.3.0 → libspeech-0.4.0}/tests/genhtml.css +0 -0
  267. {libspeech-0.3.0 → libspeech-0.4.0}/tests/python/test_audio.py +0 -0
  268. {libspeech-0.3.0 → libspeech-0.4.0}/tests/utest/utest.h +0 -0
  269. {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
- -DBUILD_MODELS=OFF \
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/html
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@v3.4.1
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 target (docs/)" off)
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
- find_package(Python 3.8
373
- REQUIRED COMPONENTS Interpreter Development.Module
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
- target_include_directories(${NB_MODULE} PRIVATE include src)
467
- target_compile_definitions(${NB_MODULE} PRIVATE NB_MODULE_NAME=${NB_MODULE})
468
- target_link_libraries(${NB_MODULE} PRIVATE speech::speech)
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,