diff --git a/.gitignore b/.gitignore index 12f12aae..d0fa2394 100644 --- a/.gitignore +++ b/.gitignore @@ -74,4 +74,5 @@ docs/_build/ # Other build target -.idea \ No newline at end of file +.idea +node-test/ diff --git a/Cargo.lock b/Cargo.lock index 1e4dfd7c..3c8c5dae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,37 +17,6 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" -[[package]] -name = "aho-corasick" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" -dependencies = [ - "memchr", -] - -[[package]] -name = "alsa" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2562ad8dcf0f789f65c6fdaad8a8a9708ed6b488e649da28c01656ad66b8b47" -dependencies = [ - "alsa-sys", - "bitflags 1.3.2", - "libc", - "nix", -] - -[[package]] -name = "alsa-sys" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db8fee663d06c4e303404ef5f40488a53e062f89ba8bfed81f42325aafad1527" -dependencies = [ - "libc", - "pkg-config", -] - [[package]] name = "arrayvec" version = "0.7.4" @@ -267,26 +236,6 @@ version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" -[[package]] -name = "bindgen" -version = "0.69.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" -dependencies = [ - "bitflags 2.4.2", - "cexpr", - "clang-sys", - "itertools", - "lazy_static", - "lazycell", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex", - "syn 2.0.50", -] - [[package]] name = "bitflags" version = "1.3.2" @@ -344,24 +293,6 @@ name = "cc" version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f9fa1897e4325be0d68d48df6aa1a71ac2ed4d27723887e7754192705350730" -dependencies = [ - "libc", -] - -[[package]] -name = "cesu8" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" - -[[package]] -name = "cexpr" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" -dependencies = [ - "nom", -] [[package]] name = "cfg-if" @@ -379,33 +310,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "clang-sys" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" -dependencies = [ - "glob", - "libc", - "libloading", -] - -[[package]] -name = "claxon" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bfbf56724aa9eca8afa4fcfadeb479e722935bb2a0900c2d37e0cc477af0688" - -[[package]] -name = "combine" -version = "4.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4" -dependencies = [ - "bytes", - "memchr", -] - [[package]] name = "concurrent-queue" version = "2.4.0" @@ -415,57 +319,6 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "core-foundation-sys" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" - -[[package]] -name = "coreaudio-rs" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "321077172d79c662f64f5071a03120748d5bb652f5231570141be24cfcd2bace" -dependencies = [ - "bitflags 1.3.2", - "core-foundation-sys", - "coreaudio-sys", -] - -[[package]] -name = "coreaudio-sys" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f01585027057ff5f0a5bf276174ae4c1594a2c5bde93d5f46a016d76270f5a9" -dependencies = [ - "bindgen", -] - -[[package]] -name = "cpal" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d959d90e938c5493000514b446987c07aed46c668faaa7d34d6c7a67b1a578c" -dependencies = [ - "alsa", - "core-foundation-sys", - "coreaudio-rs", - "dasp_sample", - "jni 0.19.0", - "js-sys", - "libc", - "mach2", - "ndk", - "ndk-context", - "oboe", - "once_cell", - "parking_lot", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "windows", -] - [[package]] name = "crc32fast" version = "1.4.0" @@ -481,18 +334,6 @@ version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" -[[package]] -name = "dasp_sample" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f" - -[[package]] -name = "either" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" - [[package]] name = "encoding_rs" version = "0.8.33" @@ -502,12 +343,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - [[package]] name = "errno" version = "0.3.8" @@ -577,6 +412,12 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "extended" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af9673d8203fcb076b19dfd17e38b3d4ae9f44959416ea532ce72415a6020365" + [[package]] name = "fastrand" version = "1.9.0" @@ -592,12 +433,6 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" -[[package]] -name = "fuchsia-cprng" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" - [[package]] name = "futures" version = "0.3.30" @@ -682,7 +517,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn", ] [[package]] @@ -721,12 +556,6 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" -[[package]] -name = "glob" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" - [[package]] name = "gloo-timers" version = "0.2.6" @@ -739,12 +568,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "hashbrown" -version = "0.14.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" - [[package]] name = "heck" version = "0.4.1" @@ -757,22 +580,6 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd5256b483761cd23699d0da46cc6fd2ee3be420bbe6d020ae4a091e70b7e9fd" -[[package]] -name = "hound" -version = "3.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62adaabb884c94955b19907d60019f4e145d091c75345379e70d1ee696f7854f" - -[[package]] -name = "indexmap" -version = "2.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233cf39063f058ea2caae4091bf4a3ef70a653afbc026f5c4a4135d114e3c177" -dependencies = [ - "equivalent", - "hashbrown", -] - [[package]] name = "indoc" version = "2.0.4" @@ -799,55 +606,12 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - [[package]] name = "itoa" version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" -[[package]] -name = "jni" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6df18c2e3db7e453d3c6ac5b3e9d5182664d28788126d39b91f2d1e22b017ec" -dependencies = [ - "cesu8", - "combine", - "jni-sys", - "log", - "thiserror", - "walkdir", -] - -[[package]] -name = "jni" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "039022cdf4d7b1cf548d31f60ae783138e5fd42013f6271049d7df7afadef96c" -dependencies = [ - "cesu8", - "combine", - "jni-sys", - "log", - "thiserror", - "walkdir", -] - -[[package]] -name = "jni-sys" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" - [[package]] name = "js-sys" version = "0.3.68" @@ -872,39 +636,12 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - -[[package]] -name = "lewton" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "777b48df9aaab155475a83a7df3070395ea1ac6902f5cd062b8f2b028075c030" -dependencies = [ - "byteorder", - "ogg", - "tinyvec", -] - [[package]] name = "libc" version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" -[[package]] -name = "libloading" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] - [[package]] name = "linux-raw-sys" version = "0.3.8" @@ -936,15 +673,6 @@ dependencies = [ "value-bag", ] -[[package]] -name = "mach2" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" -dependencies = [ - "libc", -] - [[package]] name = "memchr" version = "2.7.1" @@ -960,12 +688,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - [[package]] name = "miniz_oxide" version = "0.7.2" @@ -975,56 +697,6 @@ dependencies = [ "adler", ] -[[package]] -name = "ndk" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "451422b7e4718271c8b5b3aadf5adedba43dc76312454b387e98fae0fc951aa0" -dependencies = [ - "bitflags 1.3.2", - "jni-sys", - "ndk-sys", - "num_enum", - "raw-window-handle", - "thiserror", -] - -[[package]] -name = "ndk-context" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" - -[[package]] -name = "ndk-sys" -version = "0.4.1+23.1.7779620" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cf2aae958bd232cac5069850591667ad422d263686d75b52a065f9badeee5a3" -dependencies = [ - "jni-sys", -] - -[[package]] -name = "nix" -version = "0.24.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" -dependencies = [ - "bitflags 1.3.2", - "cfg-if", - "libc", -] - -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - [[package]] name = "num-complex" version = "0.4.5" @@ -1035,14 +707,12 @@ dependencies = [ ] [[package]] -name = "num-derive" -version = "0.3.3" +name = "num-integer" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", + "num-traits", ] [[package]] @@ -1064,27 +734,6 @@ dependencies = [ "libc", ] -[[package]] -name = "num_enum" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" -dependencies = [ - "num_enum_derive", -] - -[[package]] -name = "num_enum_derive" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "object" version = "0.32.2" @@ -1094,38 +743,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "oboe" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8868cc237ee02e2d9618539a23a8d228b9bb3fc2e7a5b11eed3831de77c395d0" -dependencies = [ - "jni 0.20.0", - "ndk", - "ndk-context", - "num-derive", - "num-traits", - "oboe-sys", -] - -[[package]] -name = "oboe-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f44155e7fb718d3cfddcf70690b2b51ac4412f347cd9e4fbe511abe9cd7b5f2" -dependencies = [ - "cc", -] - -[[package]] -name = "ogg" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6951b4e8bf21c8193da321bcce9c9dd2e13c858fe078bf9054a288b419ae5d6e" -dependencies = [ - "byteorder", -] - [[package]] name = "once_cell" version = "1.19.0" @@ -1184,12 +801,6 @@ dependencies = [ "futures-io", ] -[[package]] -name = "pkg-config" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" - [[package]] name = "polling" version = "2.8.0" @@ -1221,13 +832,12 @@ dependencies = [ ] [[package]] -name = "proc-macro-crate" -version = "1.3.1" +name = "primal-check" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +checksum = "9df7f93fd637f083201473dab4fee2db4c429d32e55e3299980ab3957ab916a0" dependencies = [ - "once_cell", - "toml_edit", + "num-integer", ] [[package]] @@ -1299,7 +909,7 @@ dependencies = [ "proc-macro2", "pyo3-macros-backend", "quote", - "syn 2.0.50", + "syn", ] [[package]] @@ -1311,7 +921,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.50", + "syn", ] [[package]] @@ -1324,46 +934,12 @@ dependencies = [ ] [[package]] -name = "rand" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" -dependencies = [ - "fuchsia-cprng", - "libc", - "rand_core 0.3.1", - "rdrand", - "winapi", -] - -[[package]] -name = "rand_core" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -dependencies = [ - "rand_core 0.4.2", -] - -[[package]] -name = "rand_core" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" - -[[package]] -name = "raw-window-handle" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" - -[[package]] -name = "rdrand" -version = "0.4.0" +name = "realfft" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +checksum = "953d9f7e5cdd80963547b456251296efc2626ed4e3cbf36c869d9564e0220571" dependencies = [ - "rand_core 0.3.1", + "rustfft", ] [[package]] @@ -1376,54 +952,15 @@ dependencies = [ ] [[package]] -name = "regex" -version = "1.10.3" +name = "rubato" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" +checksum = "b5d18b486e7d29a408ef3f825bc1327d8f87af091c987ca2f5b734625940e234" dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" - -[[package]] -name = "remove_dir_all" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" -dependencies = [ - "winapi", -] - -[[package]] -name = "rodio" -version = "0.17.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b1bb7b48ee48471f55da122c0044fcc7600cfcc85db88240b89cb832935e611" -dependencies = [ - "claxon", - "cpal", - "hound", - "lewton", - "symphonia", + "num-complex", + "num-integer", + "num-traits", + "realfft", ] [[package]] @@ -1433,10 +970,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] -name = "rustc-hash" -version = "1.1.0" +name = "rustfft" +version = "6.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +checksum = "43806561bc506d0c5d160643ad742e3161049ac01027b5e6d7524091fd401d86" +dependencies = [ + "num-complex", + "num-integer", + "num-traits", + "primal-check", + "strength_reduce", + "transpose", + "version_check", +] [[package]] name = "rustix" @@ -1471,15 +1017,6 @@ version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - [[package]] name = "scopeguard" version = "1.2.0" @@ -1503,7 +1040,7 @@ checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn", ] [[package]] @@ -1530,20 +1067,13 @@ dependencies = [ "futures", "pyo3", "pyo3-asyncio", - "rodio", + "rubato", "serde", "serde_json", - "tempdir", - "tempfile", + "symphonia", "tokio", ] -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - [[package]] name = "signal-hook-registry" version = "1.4.1" @@ -1578,25 +1108,53 @@ dependencies = [ "winapi", ] +[[package]] +name = "strength_reduce" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe895eb47f22e2ddd4dabc02bce419d2e643c8e3b585c78158b349195bc24d82" + [[package]] name = "symphonia" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62e48dba70095f265fdb269b99619b95d04c89e619538138383e63310b14d941" +checksum = "815c942ae7ee74737bb00f965fa5b5a2ac2ce7b6c01c0cc169bbeaf7abd5f5a9" dependencies = [ "lazy_static", + "symphonia-bundle-flac", "symphonia-bundle-mp3", + "symphonia-codec-aac", + "symphonia-codec-adpcm", + "symphonia-codec-alac", + "symphonia-codec-pcm", + "symphonia-codec-vorbis", "symphonia-core", + "symphonia-format-caf", + "symphonia-format-isomp4", + "symphonia-format-mkv", + "symphonia-format-ogg", + "symphonia-format-riff", "symphonia-metadata", ] +[[package]] +name = "symphonia-bundle-flac" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72e34f34298a7308d4397a6c7fbf5b84c5d491231ce3dd379707ba673ab3bd97" +dependencies = [ + "log", + "symphonia-core", + "symphonia-metadata", + "symphonia-utils-xiph", +] + [[package]] name = "symphonia-bundle-mp3" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f31d7fece546f1e6973011a9eceae948133bbd18fd3d52f6073b1e38ae6368a" +checksum = "c01c2aae70f0f1fb096b6f0ff112a930b1fb3626178fba3ae68b09dce71706d4" dependencies = [ - "bitflags 1.3.2", "lazy_static", "log", "symphonia-core", @@ -1604,141 +1162,179 @@ dependencies = [ ] [[package]] -name = "symphonia-core" -version = "0.5.3" +name = "symphonia-codec-aac" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7c73eb88fee79705268cc7b742c7bc93a7b76e092ab751d0833866970754142" +checksum = "cdbf25b545ad0d3ee3e891ea643ad115aff4ca92f6aec472086b957a58522f70" dependencies = [ - "arrayvec", - "bitflags 1.3.2", - "bytemuck", "lazy_static", "log", + "symphonia-core", ] [[package]] -name = "symphonia-metadata" -version = "0.5.3" +name = "symphonia-codec-adpcm" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89c3e1937e31d0e068bbe829f66b2f2bfaa28d056365279e0ef897172c3320c0" +checksum = "c94e1feac3327cd616e973d5be69ad36b3945f16b06f19c6773fc3ac0b426a0f" dependencies = [ - "encoding_rs", - "lazy_static", "log", "symphonia-core", ] [[package]] -name = "syn" -version = "1.0.109" +name = "symphonia-codec-alac" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +checksum = "2d8a6666649a08412906476a8b0efd9b9733e241180189e9f92b09c08d0e38f3" dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", + "log", + "symphonia-core", ] [[package]] -name = "syn" -version = "2.0.50" +name = "symphonia-codec-pcm" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74f1bdc9872430ce9b75da68329d1c1746faf50ffac5f19e02b71e37ff881ffb" +checksum = "f395a67057c2ebc5e84d7bb1be71cce1a7ba99f64e0f0f0e303a03f79116f89b" dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", + "log", + "symphonia-core", ] [[package]] -name = "target-lexicon" -version = "0.12.14" +name = "symphonia-codec-vorbis" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" +checksum = "5a98765fb46a0a6732b007f7e2870c2129b6f78d87db7987e6533c8f164a9f30" +dependencies = [ + "log", + "symphonia-core", + "symphonia-utils-xiph", +] [[package]] -name = "tempdir" -version = "0.3.7" +name = "symphonia-core" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" +checksum = "798306779e3dc7d5231bd5691f5a813496dc79d3f56bf82e25789f2094e022c3" dependencies = [ - "rand", - "remove_dir_all", + "arrayvec", + "bitflags 1.3.2", + "bytemuck", + "lazy_static", + "log", ] [[package]] -name = "tempfile" -version = "3.10.0" +name = "symphonia-format-caf" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a365e8cd18e44762ef95d87f284f4b5cd04107fec2ff3052bd6a3e6069669e67" +checksum = "e43c99c696a388295a29fe71b133079f5d8b18041cf734c5459c35ad9097af50" dependencies = [ - "cfg-if", - "fastrand 2.0.1", - "rustix 0.38.31", - "windows-sys 0.52.0", + "log", + "symphonia-core", + "symphonia-metadata", ] [[package]] -name = "thiserror" -version = "1.0.57" +name = "symphonia-format-isomp4" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" +checksum = "abfdf178d697e50ce1e5d9b982ba1b94c47218e03ec35022d9f0e071a16dc844" dependencies = [ - "thiserror-impl", + "encoding_rs", + "log", + "symphonia-core", + "symphonia-metadata", + "symphonia-utils-xiph", ] [[package]] -name = "thiserror-impl" -version = "1.0.57" +name = "symphonia-format-mkv" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" +checksum = "1bb43471a100f7882dc9937395bd5ebee8329298e766250b15b3875652fe3d6f" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.50", + "lazy_static", + "log", + "symphonia-core", + "symphonia-metadata", + "symphonia-utils-xiph", ] [[package]] -name = "tinyvec" -version = "1.6.0" +name = "symphonia-format-ogg" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "ada3505789516bcf00fc1157c67729eded428b455c27ca370e41f4d785bfa931" dependencies = [ - "tinyvec_macros", + "log", + "symphonia-core", + "symphonia-metadata", + "symphonia-utils-xiph", ] [[package]] -name = "tinyvec_macros" -version = "0.1.1" +name = "symphonia-format-riff" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" +checksum = "05f7be232f962f937f4b7115cbe62c330929345434c834359425e043bfd15f50" +dependencies = [ + "extended", + "log", + "symphonia-core", + "symphonia-metadata", +] [[package]] -name = "tokio" -version = "1.36.0" +name = "symphonia-metadata" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" +checksum = "bc622b9841a10089c5b18e99eb904f4341615d5aa55bbf4eedde1be721a4023c" dependencies = [ - "backtrace", - "num_cpus", - "pin-project-lite", + "encoding_rs", + "lazy_static", + "log", + "symphonia-core", +] + +[[package]] +name = "symphonia-utils-xiph" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "484472580fa49991afda5f6550ece662237b00c6f562c7d9638d1b086ed010fe" +dependencies = [ + "symphonia-core", + "symphonia-metadata", ] [[package]] -name = "toml_datetime" -version = "0.6.5" +name = "syn" +version = "2.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +checksum = "74f1bdc9872430ce9b75da68329d1c1746faf50ffac5f19e02b71e37ff881ffb" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] [[package]] -name = "toml_edit" -version = "0.19.15" +name = "target-lexicon" +version = "0.12.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" + +[[package]] +name = "tokio" +version = "1.36.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" dependencies = [ - "indexmap", - "toml_datetime", - "winnow", + "backtrace", + "num_cpus", + "pin-project-lite", ] [[package]] @@ -1757,6 +1353,16 @@ version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +[[package]] +name = "transpose" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad61aed86bc3faea4300c7aee358b4c6d0c8d6ccc36524c96e4c92ccf26e77e" +dependencies = [ + "num-integer", + "strength_reduce", +] + [[package]] name = "unicode-ident" version = "1.0.12" @@ -1776,20 +1382,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "126e423afe2dd9ac52142e7e9d5ce4135d7e13776c529d27fd6bc49f19e3280b" [[package]] -name = "waker-fn" -version = "1.1.1" +name = "version_check" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] -name = "walkdir" -version = "2.4.0" +name = "waker-fn" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" -dependencies = [ - "same-file", - "winapi-util", -] +checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690" [[package]] name = "wasm-bindgen" @@ -1812,7 +1414,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.50", + "syn", "wasm-bindgen-shared", ] @@ -1846,7 +1448,7 @@ checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" dependencies = [ "proc-macro2", "quote", - "syn 2.0.50", + "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -1883,30 +1485,12 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -[[package]] -name = "winapi-util" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" -dependencies = [ - "winapi", -] - [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows" -version = "0.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdacb41e6a96a052c6cb63a144f24900236121c6f63f4f8219fef5977ecb0c25" -dependencies = [ - "windows-targets 0.42.2", -] - [[package]] name = "windows-sys" version = "0.48.0" @@ -1925,21 +1509,6 @@ dependencies = [ "windows-targets 0.52.0", ] -[[package]] -name = "windows-targets" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - [[package]] name = "windows-targets" version = "0.48.5" @@ -1970,12 +1539,6 @@ dependencies = [ "windows_x86_64_msvc 0.52.0", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" @@ -1988,12 +1551,6 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - [[package]] name = "windows_aarch64_msvc" version = "0.48.5" @@ -2006,12 +1563,6 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - [[package]] name = "windows_i686_gnu" version = "0.48.5" @@ -2024,12 +1575,6 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - [[package]] name = "windows_i686_msvc" version = "0.48.5" @@ -2042,12 +1587,6 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - [[package]] name = "windows_x86_64_gnu" version = "0.48.5" @@ -2060,12 +1599,6 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" @@ -2078,12 +1611,6 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - [[package]] name = "windows_x86_64_msvc" version = "0.48.5" @@ -2095,12 +1622,3 @@ name = "windows_x86_64_msvc" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" - -[[package]] -name = "winnow" -version = "0.5.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" -dependencies = [ - "memchr", -] diff --git a/Cargo.toml b/Cargo.toml index 0979a26b..de63a522 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,8 +11,6 @@ crate-type = ["cdylib", "lib"] [dependencies] tokio = { version = "1.36.0" } -tempfile = "3.10.0" -rodio = {version = "0.17.3"} serde_json = "1.0.114" blocking = { version = "1.5.1", features = [] } byteorder = "1.5.0" @@ -22,9 +20,10 @@ chfft = {version = "0.3.4"} futures = { version = "0.3.30", features = [] } serde = { version = "1.0.196", features = ["derive"] } bytes = "1.5.0" -tempdir = "0.3.7" pyo3 = "0.20.2" pyo3-asyncio = { version = "0.20.0", features = ["async-std-runtime", "async-std", "tokio", "tokio-runtime"] } +symphonia = { version = "0.5.4", features = ["all"] } +rubato = "0.15.0" [features] default = ["pyo3/extension-module"] diff --git a/src/fingerprinting/algorithm.rs b/src/fingerprinting/algorithm.rs index 36fd3a4a..250ce142 100644 --- a/src/fingerprinting/algorithm.rs +++ b/src/fingerprinting/algorithm.rs @@ -1,10 +1,11 @@ -use crate::fingerprinting::ffmpeg_wrapper::{decode_with_ffmpeg, decode_with_ffmpeg_from_bytes}; use crate::fingerprinting::hanning::HANNING_WINDOW_2048_MULTIPLIERS; use crate::fingerprinting::signature_format::{DecodedSignature, FrequencyBand, FrequencyPeak}; +use crate::fingerprinting::resample::resample; +use crate::fingerprinting::decode::samples_from_bytes; use chfft::RFft1D; use std::collections::HashMap; use std::error::Error; -use std::io::{BufReader, Cursor}; +use std::fs; pub struct SignatureGenerator { ring_buffer_of_samples: Vec, @@ -20,32 +21,25 @@ pub struct SignatureGenerator { } impl SignatureGenerator { + fn pcm_samples_from_bytes(bytes: Vec) -> Result, Box> { + let (signal_spec, samples) = samples_from_bytes(bytes, usize::MAX, 0)?; + let raw_pcm_samples = resample(signal_spec, samples)?; + Ok(raw_pcm_samples) + } pub fn make_signature_from_bytes(bytes: Vec) -> Result> { // Create a cursor around the byte array for decoding - let cursor = Cursor::new(bytes.clone()); - - let decoder = rodio::Decoder::new(cursor).or_else(|_decoding_error| { - // Use the original bytes vector here - decode_with_ffmpeg_from_bytes(&bytes) - })?; - - // Convert the decoded samples to 16 kHz mono PCM, similar to make_signature_from_file - // Here, we use UniformSourceIterator from rodio to downsample and convert to mono if necessary - let converted_file = rodio::source::UniformSourceIterator::new(decoder, 1, 16000); - let raw_pcm_samples: Vec = converted_file.collect(); + let raw_pcm_samples = SignatureGenerator::pcm_samples_from_bytes(bytes)?; // Process the PCM samples as in make_signature_from_buffer let slice_len = raw_pcm_samples.len().min(12 * 16000); let mut raw_pcm_samples_slice = &raw_pcm_samples[..slice_len]; if raw_pcm_samples_slice.len() > 12 * 16000 { let middle = raw_pcm_samples.len() / 2; - raw_pcm_samples_slice = - &raw_pcm_samples_slice[middle - (6 * 16000)..middle + (6 * 16000)]; + raw_pcm_samples_slice = &raw_pcm_samples_slice[middle - (6 * 16000)..middle + (6 * 16000)]; } // Generate signature from buffer - let signature = - SignatureGenerator::make_signature_from_buffer(raw_pcm_samples_slice.to_vec()); + let signature = SignatureGenerator::make_signature_from_buffer(raw_pcm_samples_slice.to_vec()); // Return the generated signature Ok(signature) @@ -53,29 +47,13 @@ impl SignatureGenerator { pub fn make_signature_from_file(file_path: &str) -> Result> { // Decode the .WAV, .MP3, .OGG or .FLAC file - let mut decoder = rodio::Decoder::new(BufReader::new(std::fs::File::open(file_path)?)); - - if let Err(ref _decoding_error) = decoder { - // Try to decode with FFMpeg, if available, in case of failure with - // Rodio (most likely due to the use of a format unsupported by - // Rodio, such as .WMA or .MP4/.AAC) - - if let Some(new_decoder) = decode_with_ffmpeg(file_path) { - decoder = Ok(new_decoder); - } - } + let raw_pcm_samples = SignatureGenerator::pcm_samples_from_bytes(fs::read(file_path)?)?; - // Downsample the raw PCM samples to 16 KHz, and skip to the middle of the file - // in order to increase recognition odds. Take 12 seconds of sample. - - let converted_file = rodio::source::UniformSourceIterator::new(decoder?, 1, 16000); - let raw_pcm_samples: Vec = converted_file.collect(); let mut raw_pcm_samples_slice: &[i16] = &raw_pcm_samples; let slice_len = raw_pcm_samples_slice.len().min(12 * 16000); if raw_pcm_samples_slice.len() > 12 * 16000 { let middle = raw_pcm_samples.len() / 2; - raw_pcm_samples_slice = - &raw_pcm_samples_slice[middle - (6 * 16000)..middle + (6 * 16000)]; + raw_pcm_samples_slice = &raw_pcm_samples_slice[middle - (6 * 16000)..middle + (6 * 16000)]; } // println!("PRE BUF"); // println!("{} len slice", slice_len); @@ -304,4 +282,4 @@ impl SignatureGenerator { } } } -} +} \ No newline at end of file diff --git a/src/fingerprinting/decode.rs b/src/fingerprinting/decode.rs new file mode 100644 index 00000000..7af6cfc7 --- /dev/null +++ b/src/fingerprinting/decode.rs @@ -0,0 +1,71 @@ +use std::io::Cursor; + +use symphonia::core::io::MediaSourceStream; +use symphonia::core::audio::{Channels, SampleBuffer, SignalSpec}; +use symphonia::core::errors::Error; +use symphonia::core::codecs::{DecoderOptions, CODEC_TYPE_NULL}; +use symphonia::core::formats::FormatOptions; +use symphonia::core::meta::MetadataOptions; +use symphonia::core::probe::Hint; + +pub fn samples_from_bytes( + bytes: Vec, + seconds: usize, + offset: usize +) -> Result<(SignalSpec, Vec), Error> { + // Create the media source stream. + let mss = MediaSourceStream::new(Box::new(Cursor::new(bytes)), Default::default()); + + let probe_result = symphonia::default::get_probe().format(&Hint::new(), mss, &FormatOptions::default(), &MetadataOptions::default())?; + + // Get the instantiated format reader. + let mut format = probe_result.format; + + // Find the first audio track with a known (decodeable) codec. + let track = format + .tracks() + .iter() + .find(|t| t.codec_params.codec != CODEC_TYPE_NULL) + .ok_or(Error::Unsupported("codec"))?; + + // Create a decoder for the track. + let mut decoder = symphonia::default::get_codecs().make(&track.codec_params, &DecoderOptions::default())?; + + // Store the track identifier, it will be used to filter packets. + let track_id = track.id; + + let mut spec: SignalSpec = SignalSpec::new(track.codec_params.sample_rate.unwrap_or(96000), Channels::FRONT_LEFT | Channels::FRONT_RIGHT); + let mut aggregate_samples: Vec = Vec::with_capacity(12 * spec.rate as usize * 2); + let mut sample_buf = SampleBuffer::::new(0, spec); + loop { + // Get the next packet from the format reader. + let packet = match format.next_packet() { + Ok(packet) => packet, + Err(_) => break, + }; + // If the packet does not belong to the selected track, skip it. + if packet.track_id() != track_id { + continue; + } + + match decoder.decode(&packet) { + Ok(audio_buf) => { + spec = *audio_buf.spec(); + if sample_buf.capacity() < audio_buf.capacity() { + sample_buf = SampleBuffer::::new(audio_buf.capacity() as u64, spec); + } + + sample_buf.copy_interleaved_ref(audio_buf); + aggregate_samples.extend_from_slice(sample_buf.samples()); + + if aggregate_samples.len() >= ((seconds + offset) * spec.rate as usize * spec.channels.count()) { + break; + } + } + Err(err) => return Err(err), + } + } + + Ok((spec, aggregate_samples)) +} + diff --git a/src/fingerprinting/ffmpeg_wrapper.rs b/src/fingerprinting/ffmpeg_wrapper.rs deleted file mode 100644 index 7d34aad7..00000000 --- a/src/fingerprinting/ffmpeg_wrapper.rs +++ /dev/null @@ -1,143 +0,0 @@ -use std::error::Error; -use std::fs::File; -use std::io::{BufReader, Write}; - -#[cfg(windows)] -use std::os::windows::process::CommandExt; - -use rodio::Decoder; -use std::io::Cursor; -use std::process::Command; -use tempfile::Builder; - -/// This function used to decode a file with FFMpeg, if it is installed on -/// the system, in the case where Rodio can't decode the concerned format -/// (for example with .WMA, .M4A, etc.). - -pub fn decode_with_ffmpeg(file_path: &str) -> Option>> { - // Find the path for FFMpeg, in the case where it is installed - - let mut possible_ffmpeg_paths: Vec<&str> = vec!["ffmpeg", "ffmpeg.exe"]; - - let mut current_dir_ffmpeg_path = - std::env::current_exe().expect("failed current_dir_ffmpeg_path"); - current_dir_ffmpeg_path.pop(); - current_dir_ffmpeg_path.push("ffmpeg.exe"); - possible_ffmpeg_paths.push(current_dir_ffmpeg_path.to_str().unwrap()); - let mut actual_ffmpeg_path: Option<&str> = None; - - for possible_path in possible_ffmpeg_paths { - // Use .output() to execute the subprocess testing for FFMpeg - // presence and correct execution, so that it does not pollute - // the standard or error output in any way - - let mut command = Command::new(possible_path); - #[cfg(windows)] - let command = command.creation_flags(0x08000000); - let command = command.arg("-version"); - - if let Ok(process) = command.output() { - if process.status.success() { - actual_ffmpeg_path = Some(possible_path); - break; - } - } - } - - // If FFMpeg is available, use it to convert the input file - // from whichever format to a .WAV (because Rodio has its - // decoding support limited to .WAV, .FLAC, .OGG, .MP3, which - // makes that .MP4/.AAC, .OPUS or .WMA are not supported, and - // Rodio's minimp3 .MP3 decoder seems to crash on Windows anyway) - if let Some(ffmpeg_path) = actual_ffmpeg_path { - // Create a sink file for FFMpeg - - let sink_file = Builder::new().suffix(".wav").tempfile().unwrap(); - - let sink_file_path = sink_file.into_temp_path(); - // Try to convert the input video or audio file to a standard - // .WAV s16le PCM file using FFMpeg, and pass it to Rodio - // later in the case where it succeeded - - let mut command = Command::new(ffmpeg_path); - - #[cfg(windows)] - let command = command.creation_flags(0x08000000); - - let command = command.args(["-y", "-i", file_path, sink_file_path.to_str().unwrap()]); - - // Set "CREATE_NO_WINDOW" on Windows, see - // https://stackoverflow.com/a/60958956/662399 - - if let Ok(process) = command.output() { - if process.status.success() { - let res = Decoder::new(BufReader::new( - File::open(sink_file_path.to_str().unwrap()).unwrap(), - )) - .expect("failed to decode with ffmpeg"); - return Some(res); - } - } else { - return None; - } - } - None -} - -pub fn decode_with_ffmpeg_from_bytes( - bytes: &[u8], -) -> Result>>, Box> { - // Create a temporary file for the input - let mut temp_file = Builder::new().suffix(".tmp").tempfile()?; - temp_file.write_all(bytes)?; - let file_path = temp_file.path().to_str().unwrap().to_string(); - - // Find the FFmpeg path - let mut possible_ffmpeg_paths = vec!["ffmpeg", "ffmpeg.exe"]; - let mut current_dir_ffmpeg_path = - std::env::current_exe().expect("failed current_dir_ffmpeg_path"); - current_dir_ffmpeg_path.pop(); - current_dir_ffmpeg_path.push("ffmpeg.exe"); - possible_ffmpeg_paths.push(current_dir_ffmpeg_path.to_str().unwrap()); - - let mut actual_ffmpeg_path = None; - for possible_path in &possible_ffmpeg_paths { - let mut command = Command::new(possible_path); - #[cfg(windows)] - let command = command.creation_flags(0x08000000); - let command = command.arg("-version"); - - if let Ok(process) = command.output() { - if process.status.success() { - actual_ffmpeg_path = Some(*possible_path); - break; - } - } - } - - if let Some(ffmpeg_path) = actual_ffmpeg_path { - // Create a temporary file for the output - let sink_file = Builder::new().suffix(".wav").tempfile()?; - let sink_file_path = sink_file.path().to_str().unwrap().to_string(); - - // Convert to WAV format - let mut command = Command::new(ffmpeg_path); - #[cfg(windows)] - let command = command.creation_flags(0x08000000); - let command = command.args(["-y", "-i", &file_path, &sink_file_path]); - - if let Ok(process) = command.output() { - if process.status.success() { - // Read the converted file into a Vec - let converted_bytes = std::fs::read(sink_file_path)?; - - // Create a Cursor around the converted bytes and create a Decoder - let cursor = Cursor::new(converted_bytes); - let decoder = Decoder::new(cursor)?; - - return Ok(decoder); - } - } - } - Err("FFmpeg not found or failed to convert audio".into()) -} diff --git a/src/fingerprinting/mod.rs b/src/fingerprinting/mod.rs index 7a479f1a..6d3ea2aa 100644 --- a/src/fingerprinting/mod.rs +++ b/src/fingerprinting/mod.rs @@ -1,5 +1,6 @@ pub mod algorithm; pub mod communication; -pub mod ffmpeg_wrapper; pub mod hanning; pub mod signature_format; +pub mod decode; +pub mod resample; \ No newline at end of file diff --git a/src/fingerprinting/resample.rs b/src/fingerprinting/resample.rs new file mode 100644 index 00000000..86a617b3 --- /dev/null +++ b/src/fingerprinting/resample.rs @@ -0,0 +1,41 @@ +use rubato::Resampler; +use rubato::SincFixedIn; +use rubato::SincInterpolationType; +use rubato::SincInterpolationParameters; +use symphonia::core::audio::SignalSpec; +use std::error::Error; + +pub fn resample(spec: SignalSpec, samples: Vec) -> Result, Box> { + let target_rate = 16_000; + let resample_ratio = target_rate as f64 / spec.rate as f64; + let max_resample_ratio_relative = 2.0; + let channel_count = spec.channels.count(); + let chunk_size = samples.len() / channel_count; + let parameters = SincInterpolationParameters { + sinc_len: 256, + f_cutoff: 0.95, + interpolation: SincInterpolationType::Cubic, + oversampling_factor: 160, + window: rubato::WindowFunction::BlackmanHarris2, + }; + let mut resampler = SincFixedIn::new( + resample_ratio, + max_resample_ratio_relative, + parameters, + chunk_size, + 1, + )?; + + let mut mono_samples = vec![0f32; samples.len() / channel_count]; + for (i, sample) in samples.iter().enumerate() { + mono_samples[i / channel_count] += sample / channel_count as f32; + } + + let resampled_samples = resampler.process(&[&mono_samples], None)?; + let result: Vec = resampled_samples[0] + .iter() + .map(|&sample| (sample * i16::MAX as f32) as i16) + .collect(); + + Ok(result) +} \ No newline at end of file