From 4b8ce743a806659daecfb9e505d7bf88e721319e Mon Sep 17 00:00:00 2001 From: Alexander Kalashnikov Date: Thu, 30 May 2024 12:08:47 +0300 Subject: [PATCH] Rust example --- examples/rust-example/.gitignore | 2 + examples/rust-example/Cargo.lock | 781 ++++++++++++++++++++++++++ examples/rust-example/Cargo.toml | 9 + examples/rust-example/README.md | 19 + examples/rust-example/src/main.rs | 36 ++ examples/rust-example/src/silero.rs | 59 ++ examples/rust-example/src/utils.rs | 60 ++ examples/rust-example/src/vad_iter.rs | 223 ++++++++ 8 files changed, 1189 insertions(+) create mode 100644 examples/rust-example/.gitignore create mode 100644 examples/rust-example/Cargo.lock create mode 100644 examples/rust-example/Cargo.toml create mode 100644 examples/rust-example/README.md create mode 100644 examples/rust-example/src/main.rs create mode 100644 examples/rust-example/src/silero.rs create mode 100644 examples/rust-example/src/utils.rs create mode 100644 examples/rust-example/src/vad_iter.rs diff --git a/examples/rust-example/.gitignore b/examples/rust-example/.gitignore new file mode 100644 index 0000000..11bed72 --- /dev/null +++ b/examples/rust-example/.gitignore @@ -0,0 +1,2 @@ +target/ +recorder.wav \ No newline at end of file diff --git a/examples/rust-example/Cargo.lock b/examples/rust-example/Cargo.lock new file mode 100644 index 0000000..6619841 --- /dev/null +++ b/examples/rust-example/Cargo.lock @@ -0,0 +1,781 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "cc" +version = "1.0.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "filetime" +version = "0.2.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "windows-sys", +] + +[[package]] +name = "flate2" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "half" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" +dependencies = [ + "cfg-if", + "crunchy", +] + +[[package]] +name = "hound" +version = "3.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62adaabb884c94955b19907d60019f4e145d091c75345379e70d1ee696f7854f" + +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "js-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "libc" +version = "0.2.155" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" + +[[package]] +name = "libloading" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" +dependencies = [ + "cfg-if", + "windows-targets", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" + +[[package]] +name = "matrixmultiply" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7574c1cf36da4798ab73da5b215bbf444f50718207754cb522201d78d1cd0ff2" +dependencies = [ + "autocfg", + "rawpointer", +] + +[[package]] +name = "miniz_oxide" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" +dependencies = [ + "adler", +] + +[[package]] +name = "ndarray" +version = "0.15.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb12d4e967ec485a5f71c6311fe28158e9d6f4bc4a447b474184d0f91a8fa32" +dependencies = [ + "matrixmultiply", + "num-complex", + "num-integer", + "num-traits", + "rawpointer", +] + +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "ort" +version = "2.0.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bc80894094c6a875bfac64415ed456fa661081a278a035e22be661305c87e14" +dependencies = [ + "half", + "js-sys", + "libloading", + "ndarray", + "ort-sys", + "thiserror", + "tracing", + "web-sys", +] + +[[package]] +name = "ort-sys" +version = "2.0.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3d9c1373fc813d3f024d394f621f4c6dde0734c79b1c17113c3bb5bf0084bbe" +dependencies = [ + "flate2", + "sha2", + "tar", + "ureq", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "proc-macro2" +version = "1.0.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec96c6a92621310b51366f1e28d05ef11489516e93be030060e5fc12024a49d6" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rawpointer" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" + +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin", + "untrusted", + "windows-sys", +] + +[[package]] +name = "rust-example" +version = "0.1.0" +dependencies = [ + "hound", + "ndarray", + "ort", +] + +[[package]] +name = "rustix" +version = "0.38.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +dependencies = [ + "bitflags 2.5.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "rustls" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" +dependencies = [ + "log", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pki-types" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" + +[[package]] +name = "rustls-webpki" +version = "0.102.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff448f7e92e913c4b7d4c6d8e4540a1724b319b4152b8aef6d4cf8339712b33e" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + +[[package]] +name = "syn" +version = "2.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tar" +version = "0.4.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb" +dependencies = [ + "filetime", + "libc", + "xattr", +] + +[[package]] +name = "thiserror" +version = "1.0.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-bidi" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-normalization" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "ureq" +version = "2.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d11a831e3c0b56e438a28308e7c810799e3c118417f342d30ecec080105395cd" +dependencies = [ + "base64", + "log", + "once_cell", + "rustls", + "rustls-pki-types", + "rustls-webpki", + "url", + "webpki-roots", +] + +[[package]] +name = "url" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" + +[[package]] +name = "web-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki-roots" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3de34ae270483955a94f4b21bdaaeb83d508bb84a01435f393818edb0012009" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" + +[[package]] +name = "xattr" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8da84f1a25939b27f6820d92aed108f83ff920fdf11a7b19366c27c4cda81d4f" +dependencies = [ + "libc", + "linux-raw-sys", + "rustix", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" diff --git a/examples/rust-example/Cargo.toml b/examples/rust-example/Cargo.toml new file mode 100644 index 0000000..d3e72a3 --- /dev/null +++ b/examples/rust-example/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "rust-example" +version = "0.1.0" +edition = "2021" + +[dependencies] +ort = { version = "2.0.0-rc.2", features = ["load-dynamic", "ndarray"] } +ndarray = "0.15" +hound = "3" diff --git a/examples/rust-example/README.md b/examples/rust-example/README.md new file mode 100644 index 0000000..cd55bb2 --- /dev/null +++ b/examples/rust-example/README.md @@ -0,0 +1,19 @@ +# Stream example in Rust +Made after [C++ stream example](https://github.com/snakers4/silero-vad/tree/master/examples/cpp) + +## Dependencies +- To build Rust crate `ort` you need `cc` installed. + +## Usage +Just +``` +cargo run +``` +If you run example outside of this repo adjust environment variable +``` +SILERO_MODEL_PATH=/path/to/silero_vad.onnx cargo run +``` +If you need to test against other wav file, not `recorder.wav`, specify it as the first argument +``` +cargo run -- /path/to/audio/file.wav +``` \ No newline at end of file diff --git a/examples/rust-example/src/main.rs b/examples/rust-example/src/main.rs new file mode 100644 index 0000000..bf48d0c --- /dev/null +++ b/examples/rust-example/src/main.rs @@ -0,0 +1,36 @@ +mod silero; +mod utils; +mod vad_iter; + +fn main() { + let model_path = std::env::var("SILERO_MODEL_PATH") + .unwrap_or_else(|_| String::from("../../files/silero_vad.onnx")); + let audio_path = std::env::args() + .nth(1) + .unwrap_or_else(|| String::from("recorder.wav")); + let mut wav_reader = hound::WavReader::open(audio_path).unwrap(); + let sample_rate = match wav_reader.spec().sample_rate { + 8000 => utils::SampleRate::EightkHz, + 16000 => utils::SampleRate::SixteenkHz, + _ => panic!("Unsupported sample rate. Expect 8 kHz or 16 kHz."), + }; + if wav_reader.spec().sample_format != hound::SampleFormat::Int { + panic!("Unsupported sample format. Expect Int."); + } + let content = wav_reader + .samples() + .filter_map(|x| x.ok()) + .collect::>(); + assert!(!content.is_empty()); + let silero = silero::Silero::new(sample_rate, model_path).unwrap(); + let vad_params = utils::VadParams { + sample_rate: sample_rate.into(), + ..Default::default() + }; + let mut vad_iterator = vad_iter::VadIter::new(silero, vad_params); + vad_iterator.process(&content).unwrap(); + for timestamp in vad_iterator.speeches() { + println!("{}", timestamp); + } + println!("Finished."); +} diff --git a/examples/rust-example/src/silero.rs b/examples/rust-example/src/silero.rs new file mode 100644 index 0000000..22f154c --- /dev/null +++ b/examples/rust-example/src/silero.rs @@ -0,0 +1,59 @@ +use crate::utils; +use ndarray::{Array, Array2, ArrayBase, ArrayD, Dim, IxDynImpl, OwnedRepr}; +use std::path::Path; + +#[derive(Debug)] +pub struct Silero { + session: ort::Session, + sample_rate: ArrayBase, Dim<[usize; 1]>>, + h: ArrayBase, Dim>, + c: ArrayBase, Dim>, +} + +impl Silero { + pub fn new( + sample_rate: utils::SampleRate, + model_path: impl AsRef, + ) -> Result { + let session = ort::Session::builder()?.commit_from_file(model_path)?; + let h = ArrayD::::zeros([2, 1, 64].as_slice()); + let c = ArrayD::::zeros([2, 1, 64].as_slice()); + let sample_rate = Array::from_shape_vec([1], vec![sample_rate.into()]).unwrap(); + Ok(Self { + session, + sample_rate, + h, + c, + }) + } + + pub fn reset(&mut self) { + self.h = ArrayD::::zeros([2, 1, 64].as_slice()); + self.c = ArrayD::::zeros([2, 1, 64].as_slice()); + } + + pub fn calc_level(&mut self, audio_frame: &[i16]) -> Result { + let data = audio_frame + .iter() + .map(|x| (*x as f32) / (i16::MAX as f32)) + .collect::>(); + let frame = Array2::::from_shape_vec([1, data.len()], data).unwrap(); + let inps = ort::inputs![ + frame, + self.sample_rate.clone(), + std::mem::take(&mut self.h), + std::mem::take(&mut self.c) + ]?; + let res = self + .session + .run(ort::SessionInputs::ValueSlice::<4>(&inps))?; + self.h = res["hn"].try_extract_tensor().unwrap().to_owned(); + self.c = res["cn"].try_extract_tensor().unwrap().to_owned(); + Ok(*res["output"] + .try_extract_raw_tensor::() + .unwrap() + .1 + .first() + .unwrap()) + } +} diff --git a/examples/rust-example/src/utils.rs b/examples/rust-example/src/utils.rs new file mode 100644 index 0000000..8207920 --- /dev/null +++ b/examples/rust-example/src/utils.rs @@ -0,0 +1,60 @@ +#[derive(Debug, Clone, Copy)] +pub enum SampleRate { + EightkHz, + SixteenkHz, +} + +impl From for i64 { + fn from(value: SampleRate) -> Self { + match value { + SampleRate::EightkHz => 8000, + SampleRate::SixteenkHz => 16000, + } + } +} + +impl From for usize { + fn from(value: SampleRate) -> Self { + match value { + SampleRate::EightkHz => 8000, + SampleRate::SixteenkHz => 16000, + } + } +} + +#[derive(Debug)] +pub struct VadParams { + pub frame_size: usize, + pub threshold: f32, + pub min_silence_duration_ms: usize, + pub speech_pad_ms: usize, + pub min_speech_duration_ms: usize, + pub max_speech_duration_s: f32, + pub sample_rate: usize, +} + +impl Default for VadParams { + fn default() -> Self { + Self { + frame_size: 64, + threshold: 0.5, + min_silence_duration_ms: 0, + speech_pad_ms: 64, + min_speech_duration_ms: 64, + max_speech_duration_s: f32::INFINITY, + sample_rate: 16000, + } + } +} + +#[derive(Debug, Default)] +pub struct TimeStamp { + pub start: i64, + pub end: i64, +} + +impl std::fmt::Display for TimeStamp { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "[start:{:08}, end:{:08}]", self.start, self.end) + } +} diff --git a/examples/rust-example/src/vad_iter.rs b/examples/rust-example/src/vad_iter.rs new file mode 100644 index 0000000..1b8ae6d --- /dev/null +++ b/examples/rust-example/src/vad_iter.rs @@ -0,0 +1,223 @@ +use crate::{silero, utils}; + +const DEBUG_SPEECH_PROB: bool = true; +#[derive(Debug)] +pub struct VadIter { + silero: silero::Silero, + params: Params, + state: State, +} + +impl VadIter { + pub fn new(silero: silero::Silero, params: utils::VadParams) -> Self { + Self { + silero, + params: Params::from(params), + state: State::new(), + } + } + + pub fn process(&mut self, samples: &[i16]) -> Result<(), ort::Error> { + self.reset_states(); + for audio_frame in samples.chunks_exact(self.params.frame_size_samples) { + let speech_prob = self.silero.calc_level(audio_frame)?; + self.state.update(&self.params, speech_prob); + } + self.state.check_for_last_speech(samples.len()); + Ok(()) + } + + pub fn speeches(&self) -> &[utils::TimeStamp] { + &self.state.speeches + } +} + +impl VadIter { + fn reset_states(&mut self) { + self.silero.reset(); + self.state = State::new() + } +} + +#[allow(unused)] +#[derive(Debug)] +struct Params { + frame_size: usize, + threshold: f32, + min_silence_duration_ms: usize, + speech_pad_ms: usize, + min_speech_duration_ms: usize, + max_speech_duration_s: f32, + sample_rate: usize, + sr_per_ms: usize, + frame_size_samples: usize, + min_speech_samples: usize, + speech_pad_samples: usize, + max_speech_samples: f32, + min_silence_samples: usize, + min_silence_samples_at_max_speech: usize, +} + +impl From for Params { + fn from(value: utils::VadParams) -> Self { + let frame_size = value.frame_size; + let threshold = value.threshold; + let min_silence_duration_ms = value.min_silence_duration_ms; + let speech_pad_ms = value.speech_pad_ms; + let min_speech_duration_ms = value.min_speech_duration_ms; + let max_speech_duration_s = value.max_speech_duration_s; + let sample_rate = value.sample_rate; + let sr_per_ms = sample_rate / 1000; + let frame_size_samples = frame_size * sr_per_ms; + let min_speech_samples = sr_per_ms * min_speech_duration_ms; + let speech_pad_samples = sr_per_ms * speech_pad_ms; + let max_speech_samples = sample_rate as f32 * max_speech_duration_s + - frame_size_samples as f32 + - 2.0 * speech_pad_samples as f32; + let min_silence_samples = sr_per_ms * min_silence_duration_ms; + let min_silence_samples_at_max_speech = sr_per_ms * 98; + Self { + frame_size, + threshold, + min_silence_duration_ms, + speech_pad_ms, + min_speech_duration_ms, + max_speech_duration_s, + sample_rate, + sr_per_ms, + frame_size_samples, + min_speech_samples, + speech_pad_samples, + max_speech_samples, + min_silence_samples, + min_silence_samples_at_max_speech, + } + } +} + +#[derive(Debug, Default)] +struct State { + current_sample: usize, + temp_end: usize, + next_start: usize, + prev_end: usize, + triggered: bool, + current_speech: utils::TimeStamp, + speeches: Vec, +} + +impl State { + fn new() -> Self { + Default::default() + } + + fn update(&mut self, params: &Params, speech_prob: f32) { + self.current_sample += params.frame_size_samples; + if speech_prob > params.threshold { + if self.temp_end != 0 { + self.temp_end = 0; + if self.next_start < self.prev_end { + self.next_start = self + .current_sample + .saturating_sub(params.frame_size_samples) + } + } + if !self.triggered { + self.debug(speech_prob, params, "start"); + self.triggered = true; + self.current_speech.start = + self.current_sample as i64 - params.frame_size_samples as i64; + } + return; + } + if self.triggered + && (self.current_sample as i64 - self.current_speech.start) as f32 + > params.max_speech_samples + { + if self.prev_end > 0 { + self.current_speech.end = self.prev_end as _; + self.take_speech(); + if self.next_start < self.prev_end { + self.triggered = false + } else { + self.current_speech.start = self.next_start as _; + } + self.prev_end = 0; + self.next_start = 0; + self.temp_end = 0; + } else { + self.current_speech.end = self.current_sample as _; + self.take_speech(); + self.prev_end = 0; + self.next_start = 0; + self.temp_end = 0; + self.triggered = false; + } + return; + } + if speech_prob >= (params.threshold - 0.15) && (speech_prob < params.threshold) { + if self.triggered { + self.debug(speech_prob, params, "speaking") + } else { + self.debug(speech_prob, params, "silence") + } + } + if self.triggered && speech_prob < (params.threshold - 0.15) { + self.debug(speech_prob, params, "end"); + if self.temp_end == 0 { + self.temp_end = self.current_sample; + } + if self.current_sample.saturating_sub(self.temp_end) + > params.min_silence_samples_at_max_speech + { + self.prev_end = self.temp_end; + } + if self.current_sample.saturating_sub(self.temp_end) >= params.min_silence_samples { + self.current_speech.end = self.temp_end as _; + if self.current_speech.end - self.current_speech.start + > params.min_speech_samples as _ + { + self.take_speech(); + self.prev_end = 0; + self.next_start = 0; + self.temp_end = 0; + self.triggered = false; + } + } + } + } + + fn take_speech(&mut self) { + self.speeches.push(std::mem::take(&mut self.current_speech)); // current speech becomes TimeStamp::default() due to take() + } + + fn check_for_last_speech(&mut self, last_sample: usize) { + if self.current_speech.start > 0 { + self.current_speech.end = last_sample as _; + self.take_speech(); + self.prev_end = 0; + self.next_start = 0; + self.temp_end = 0; + self.triggered = false; + } + } + + fn debug(&self, speech_prob: f32, params: &Params, title: &str) { + if DEBUG_SPEECH_PROB { + let speech = self.current_sample as f32 + - params.frame_size_samples as f32 + - if title == "end" { + params.speech_pad_samples + } else { + 0 + } as f32; // minus window_size_samples to get precise start time point. + println!( + "[{:10}: {:.3} s ({:.3}) {:8}]", + title, + speech / params.sample_rate as f32, + speech_prob, + self.current_sample - params.frame_size_samples, + ); + } + } +}