From: Max Value Date: Sat, 7 Mar 2026 14:40:18 +0000 (+0000) Subject: exhibition changes X-Git-Url: https://git.ozva.co.uk/?a=commitdiff_plain;h=refs%2Fheads%2Fmain;p=rust_fft exhibition changes --- diff --git a/Cargo.lock b/Cargo.lock index b7efc4e..61f2e08 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -45,7 +45,7 @@ version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "once_cell", "version_check", "zerocopy", @@ -80,7 +80,7 @@ checksum = "ed7572b7ba83a31e20d1b48970ee402d2e3e0537dcfe0a3ff4d6eb7508617d43" dependencies = [ "alsa-sys", "bitflags 2.6.0", - "cfg-if", + "cfg-if 1.0.0", "libc", ] @@ -207,7 +207,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cfg-if", + "cfg-if 1.0.0", "libc", "miniz_oxide 0.8.0", "object", @@ -215,6 +215,29 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "bindgen" +version = "0.65.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfdf7b466f9a4903edc73f95d6d2bcd5baf8ae620638762244d3f60143643cc5" +dependencies = [ + "bitflags 1.3.2", + "cexpr", + "clang-sys", + "lazy_static", + "lazycell", + "log", + "peeking_take_while", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn 2.0.87", + "which", +] + [[package]] name = "bindgen" version = "0.70.1" @@ -320,9 +343,9 @@ checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytemuck" -version = "1.18.0" +version = "1.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94bbb0ad554ad961ddc5da507a12a29b14e4ae5bda06b19f575a3e6079d2e2ae" +checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" [[package]] name = "byteorder" @@ -392,6 +415,12 @@ dependencies = [ "target-lexicon", ] +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + [[package]] name = "cfg-if" version = "1.0.0" @@ -415,6 +444,34 @@ dependencies = [ "libloading 0.8.5", ] +[[package]] +name = "cocoa" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c49e86fc36d5704151f5996b7b3795385f50ce09e3be0f47a0cfde869681cf8" +dependencies = [ + "bitflags 1.3.2", + "block", + "core-foundation 0.7.0", + "core-graphics 0.19.2", + "foreign-types 0.3.2", + "libc", + "objc", +] + +[[package]] +name = "cocoa-foundation" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81411967c50ee9a1fc11365f8c585f863a22a9697c89239c452292c40ba79b0d" +dependencies = [ + "bitflags 2.6.0", + "block", + "core-foundation 0.10.1", + "core-graphics-types 0.2.0", + "objc", +] + [[package]] name = "codespan-reporting" version = "0.11.1" @@ -447,22 +504,60 @@ dependencies = [ "memchr", ] +[[package]] +name = "core-foundation" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171" +dependencies = [ + "core-foundation-sys 0.7.0", + "libc", +] + [[package]] name = "core-foundation" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ - "core-foundation-sys", + "core-foundation-sys 0.8.7", + "libc", +] + +[[package]] +name = "core-foundation" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +dependencies = [ + "core-foundation-sys 0.8.7", "libc", ] +[[package]] +name = "core-foundation-sys" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" + [[package]] name = "core-foundation-sys" version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +[[package]] +name = "core-graphics" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3889374e6ea6ab25dba90bb5d96202f61108058361f6dc72e8b03e6f8bbe923" +dependencies = [ + "bitflags 1.3.2", + "core-foundation 0.7.0", + "foreign-types 0.3.2", + "libc", +] + [[package]] name = "core-graphics" version = "0.22.3" @@ -470,8 +565,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" dependencies = [ "bitflags 1.3.2", - "core-foundation", - "core-graphics-types", + "core-foundation 0.9.4", + "core-graphics-types 0.1.3", "foreign-types 0.3.2", "libc", ] @@ -483,8 +578,44 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" dependencies = [ "bitflags 1.3.2", - "core-foundation", + "core-foundation 0.9.4", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" +dependencies = [ + "bitflags 2.6.0", + "core-foundation 0.10.1", + "libc", +] + +[[package]] +name = "core-media-sys" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "273bf3fc5bf51fd06a7766a84788c1540b6527130a0bce39e00567d6ab9f31f1" +dependencies = [ + "cfg-if 0.1.10", + "core-foundation-sys 0.7.0", + "libc", +] + +[[package]] +name = "core-video-sys" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34ecad23610ad9757664d644e369246edde1803fcb43ed72876565098a5d3828" +dependencies = [ + "cfg-if 0.1.10", + "core-foundation-sys 0.7.0", + "core-graphics 0.19.2", "libc", + "metal 0.18.0", + "objc", ] [[package]] @@ -494,7 +625,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "321077172d79c662f64f5071a03120748d5bb652f5231570141be24cfcd2bace" dependencies = [ "bitflags 1.3.2", - "core-foundation-sys", + "core-foundation-sys 0.8.7", "coreaudio-sys", ] @@ -504,7 +635,7 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2ce857aa0b77d77287acc1ac3e37a05a8c95a2af3647d23b15f263bdaeb7562b" dependencies = [ - "bindgen", + "bindgen 0.70.1", ] [[package]] @@ -514,7 +645,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "873dab07c8f743075e57f524c583985fbaf745602acbe916a01539364369a779" dependencies = [ "alsa", - "core-foundation-sys", + "core-foundation-sys 0.8.7", "coreaudio-rs", "dasp_sample", "jni", @@ -545,7 +676,7 @@ version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -637,6 +768,12 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + [[package]] name = "either" version = "1.13.0" @@ -649,6 +786,16 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + [[package]] name = "exr" version = "1.73.0" @@ -689,6 +836,18 @@ dependencies = [ "miniz_oxide 0.8.0", ] +[[package]] +name = "flume" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" +dependencies = [ + "futures-core", + "futures-sink", + "nanorand", + "spin", +] + [[package]] name = "foreign-types" version = "0.3.2" @@ -824,9 +983,11 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", + "js-sys", "libc", "wasi 0.11.0+wasi-snapshot-preview1", + "wasm-bindgen", ] [[package]] @@ -835,7 +996,7 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "r-efi", "wasi 0.14.7+wasi-0.2.4", @@ -939,7 +1100,7 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "crunchy", ] @@ -986,6 +1147,15 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" +[[package]] +name = "home" +version = "0.5.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" +dependencies = [ + "windows-sys 0.61.2", +] + [[package]] name = "hound" version = "3.5.1" @@ -1057,7 +1227,7 @@ version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "js-sys", "wasm-bindgen", "web-sys", @@ -1099,7 +1269,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" dependencies = [ "cesu8", - "cfg-if", + "cfg-if 1.0.0", "combine", "jni-sys", "log", @@ -1155,6 +1325,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + [[package]] name = "lebe" version = "0.5.2" @@ -1184,7 +1360,7 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "winapi", ] @@ -1194,7 +1370,7 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "windows-targets 0.52.6", ] @@ -1209,6 +1385,12 @@ dependencies = [ "redox_syscall 0.4.1", ] +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + [[package]] name = "lock_api" version = "0.4.12" @@ -1258,7 +1440,7 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -1285,6 +1467,21 @@ dependencies = [ "autocfg", ] +[[package]] +name = "metal" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e198a0ee42bdbe9ef2c09d0b9426f3b2b47d90d93a4a9b0395c4cea605e92dc0" +dependencies = [ + "bitflags 1.3.2", + "block", + "cocoa", + "core-graphics 0.19.2", + "foreign-types 0.3.2", + "log", + "objc", +] + [[package]] name = "metal" version = "0.26.0" @@ -1293,7 +1490,7 @@ checksum = "623b5e6cefd76e58f774bd3cc0c6f5c7615c58c03a97815245a25c3c9bdee318" dependencies = [ "bitflags 2.6.0", "block", - "core-graphics-types", + "core-graphics-types 0.1.3", "foreign-types 0.5.0", "log", "objc", @@ -1337,6 +1534,31 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "mozjpeg" +version = "0.10.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7891b80aaa86097d38d276eb98b3805d6280708c4e0a1e6f6aed9380c51fec9" +dependencies = [ + "arrayvec", + "bytemuck", + "libc", + "mozjpeg-sys", + "rgb", +] + +[[package]] +name = "mozjpeg-sys" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f0dc668bf9bf888c88e2fb1ab16a406d2c380f1d082b20d51dd540ab2aa70c1" +dependencies = [ + "cc", + "dunce", + "libc", + "nasm-rs", +] + [[package]] name = "naga" version = "0.13.0" @@ -1358,6 +1580,25 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "nanorand" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" +dependencies = [ + "getrandom 0.2.15", +] + +[[package]] +name = "nasm-rs" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34f676553b60ccbb76f41f9ae8f2428dac3f259ff8f1c2468a174778d06a1af9" +dependencies = [ + "jobserver", + "log", +] + [[package]] name = "ndk" version = "0.7.0" @@ -1423,7 +1664,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" dependencies = [ "bitflags 1.3.2", - "cfg-if", + "cfg-if 1.0.0", "libc", "memoffset", ] @@ -1436,11 +1677,77 @@ checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4" dependencies = [ "autocfg", "bitflags 1.3.2", - "cfg-if", + "cfg-if 1.0.0", "libc", "memoffset", ] +[[package]] +name = "nokhwa" +version = "0.10.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4cae50786bfa1214ed441f98addbea51ca1b9aaa9e4bf5369cda36654b3efaa" +dependencies = [ + "flume", + "image", + "nokhwa-bindings-linux", + "nokhwa-bindings-macos", + "nokhwa-bindings-windows", + "nokhwa-core", + "paste", + "thiserror 2.0.16", +] + +[[package]] +name = "nokhwa-bindings-linux" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bd666aaa41d14357817bd9a981773a73c4d00b34d344cfc244e47ebd397b1ec" +dependencies = [ + "nokhwa-core", + "v4l", +] + +[[package]] +name = "nokhwa-bindings-macos" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de78eb4a2d47a68f490899aa0516070d7a972f853ec2bb374ab53be0bd39b60f" +dependencies = [ + "block", + "cocoa-foundation", + "core-foundation 0.10.1", + "core-media-sys", + "core-video-sys", + "flume", + "nokhwa-core", + "objc", + "once_cell", +] + +[[package]] +name = "nokhwa-bindings-windows" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899799275c93ef69bbe8cb888cf6f8249abe751cbc50be5299105022aec14a1c" +dependencies = [ + "nokhwa-core", + "once_cell", + "windows 0.62.2", +] + +[[package]] +name = "nokhwa-core" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "109975552bbd690894f613bce3d408222911e317197c72b2e8b9a1912dc261ae" +dependencies = [ + "bytes", + "image", + "mozjpeg", + "thiserror 2.0.16", +] + [[package]] name = "nom" version = "7.1.3" @@ -1707,7 +2014,7 @@ version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "redox_syscall 0.5.3", "smallvec", @@ -1720,6 +2027,12 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" + [[package]] name = "percent-encoding" version = "2.3.1" @@ -1820,6 +2133,16 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "prettyplease" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" +dependencies = [ + "proc-macro2", + "syn 2.0.87", +] + [[package]] name = "primal-check" version = "0.3.4" @@ -1987,7 +2310,7 @@ dependencies = [ "av1-grain", "bitstream-io", "built", - "cfg-if", + "cfg-if 1.0.0", "interpolate_name", "itertools 0.12.1", "libc", @@ -2032,9 +2355,9 @@ checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" [[package]] name = "rayon" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" dependencies = [ "either", "rayon-core", @@ -2042,9 +2365,9 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.12.1" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" dependencies = [ "crossbeam-deque", "crossbeam-utils", @@ -2106,6 +2429,15 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +[[package]] +name = "relative-path" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bca40a312222d8ba74837cb474edef44b37f561da5f773981007a10bbaa992b0" +dependencies = [ + "serde", +] + [[package]] name = "renderdoc-sys" version = "1.1.0" @@ -2113,18 +2445,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" [[package]] -name = "rgb" -version = "0.8.50" +name = "resampler" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a" +checksum = "80f5ab61459422b1a350caae1aadef48ebae234b12e80248e9ba9557018ef060" [[package]] -name = "rscam" -version = "0.5.5" +name = "rgb" +version = "0.8.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89056084211cd54924fedf2e2199b906409d1f795cfd8e7e3271061742457018" +checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a" dependencies = [ - "libc", + "bytemuck", ] [[package]] @@ -2136,11 +2468,15 @@ dependencies = [ "hound", "image", "libc", + "nokhwa", "npyz", "rand 0.9.2", - "rscam", + "rayon", + "relative-path", + "resampler", "rustfft", "show-image", + "vcpkg", ] [[package]] @@ -2166,9 +2502,9 @@ dependencies = [ [[package]] name = "rustfft" -version = "6.2.0" +version = "6.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43806561bc506d0c5d160643ad742e3161049ac01027b5e6d7524091fd401d86" +checksum = "21db5f9893e91f41798c88680037dba611ca6674703c1a18601b01a72c8adb89" dependencies = [ "num-complex", "num-integer", @@ -2176,7 +2512,19 @@ dependencies = [ "primal-check", "strength_reduce", "transpose", - "version_check", +] + +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags 2.6.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.59.0", ] [[package]] @@ -2254,7 +2602,7 @@ version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "cpufeatures", "digest", ] @@ -2350,6 +2698,15 @@ dependencies = [ "wayland-protocols", ] +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + [[package]] name = "spirv" version = "0.2.0+1.5.4" @@ -2488,7 +2845,7 @@ dependencies = [ "arrayref", "arrayvec", "bytemuck", - "cfg-if", + "cfg-if 1.0.0", "png", "tiny-skia-path", ] @@ -2595,6 +2952,26 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "229730647fbc343e3a80e463c1db7f78f3855d3f3739bee0dda773c9a037c90a" +[[package]] +name = "v4l" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8fbfea44a46799d62c55323f3c55d06df722fbe577851d848d328a1041c3403" +dependencies = [ + "bitflags 1.3.2", + "libc", + "v4l2-sys-mit", +] + +[[package]] +name = "v4l2-sys-mit" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6779878362b9bacadc7893eac76abe69612e8837ef746573c4a5239daf11990b" +dependencies = [ + "bindgen 0.65.1", +] + [[package]] name = "v_frame" version = "0.3.8" @@ -2606,6 +2983,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + [[package]] name = "vec_map" version = "0.8.2" @@ -2664,7 +3047,7 @@ version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "once_cell", "wasm-bindgen-macro", ] @@ -2690,7 +3073,7 @@ version = "0.4.43" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "js-sys", "wasm-bindgen", "web-sys", @@ -2821,7 +3204,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "752e44d3998ef35f71830dd1ad3da513e628e2e4d4aedb0ab580f850827a0b41" dependencies = [ "arrayvec", - "cfg-if", + "cfg-if 1.0.0", "js-sys", "log", "naga", @@ -2873,7 +3256,7 @@ dependencies = [ "bit-set", "bitflags 2.6.0", "block", - "core-graphics-types", + "core-graphics-types 0.1.3", "d3d12", "glow", "gpu-alloc", @@ -2885,7 +3268,7 @@ dependencies = [ "libc", "libloading 0.8.5", "log", - "metal", + "metal 0.26.0", "naga", "objc", "parking_lot", @@ -2913,6 +3296,18 @@ dependencies = [ "web-sys", ] +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix", +] + [[package]] name = "widestring" version = "1.1.0" @@ -2965,20 +3360,103 @@ version = "0.54.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9252e5725dbed82865af151df558e754e4a3c2c30818359eb17465f1346a1b49" dependencies = [ - "windows-core", + "windows-core 0.54.0", "windows-targets 0.52.6", ] +[[package]] +name = "windows" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580" +dependencies = [ + "windows-collections", + "windows-core 0.62.2", + "windows-future", + "windows-numerics", +] + +[[package]] +name = "windows-collections" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610" +dependencies = [ + "windows-core 0.62.2", +] + [[package]] name = "windows-core" version = "0.54.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12661b9c89351d684a50a8a643ce5f608e20243b9fb84687800163429f161d65" dependencies = [ - "windows-result", + "windows-result 0.1.2", "windows-targets 0.52.6", ] +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result 0.4.1", + "windows-strings", +] + +[[package]] +name = "windows-future" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb" +dependencies = [ + "windows-core 0.62.2", + "windows-link", + "windows-threading", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-numerics" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26" +dependencies = [ + "windows-core 0.62.2", + "windows-link", +] + [[package]] name = "windows-result" version = "0.1.2" @@ -2988,6 +3466,24 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", +] + [[package]] name = "windows-sys" version = "0.45.0" @@ -3015,6 +3511,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + [[package]] name = "windows-targets" version = "0.42.2" @@ -3061,6 +3566,15 @@ dependencies = [ "windows_x86_64_msvc 0.52.6", ] +[[package]] +name = "windows-threading" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37" +dependencies = [ + "windows-link", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.42.2" @@ -3202,8 +3716,8 @@ dependencies = [ "android-activity", "bitflags 1.3.2", "cfg_aliases", - "core-foundation", - "core-graphics", + "core-foundation 0.9.4", + "core-graphics 0.22.3", "dispatch", "instant", "libc", diff --git a/Cargo.toml b/Cargo.toml index 4a1f932..de4e9d8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ name = "rust_fft" version = "0.1.0" edition = "2021" build = "build.rs" -include = ["src/perspective.cpp"] +include = ["src/process.cpp", "src/barrel.cpp", "src/color.cpp", "src/homography.cpp"] [dependencies] libc = "0.2.161" @@ -12,16 +12,13 @@ image = "0.25.4" show-image = {version = "0.14.0", features = ["image"]} hound = "3.5.1" cpal = "0.15.3" -rscam = "0.5.5" npyz = "0.8.4" rand = "0.9.2" nokhwa = {version = "0.10.10", features = ["input-native"]} relative-path = "2.0.1" -yuv = "0.8.9" -lowpass-filter = "0.3.2" +rayon = "1.11.0" +resampler = "0.4.1" [build-dependencies] +vcpkg = "0.2" cc = "1.0" - -[env] -CXXFLAGS = "-Wunused-parameter -lopencv_core -lopencv_highgui -lopencv_xfeatures2d -lopencv_calib3d -lopencv_videoio -lopencv_imgcodecs -lopencv_features2d -lopencv_imgproc -lstdc++" diff --git a/build.rs b/build.rs index dd58d6f..2bb9495 100644 --- a/build.rs +++ b/build.rs @@ -2,26 +2,43 @@ fn main() { println!("cargo::rerun-if-changed=src/process.cpp"); println!("cargo::rerun-if-changed=src/homography.cpp"); println!("cargo::rerun-if-changed=src/color.cpp"); - println!("cargo::rustc-env=CXXFLAGS=-Wunused-parameter -lopencv_core -lopencv_highgui -lopencv_xfeatures2d -lopencv_calib3d -lopencv_videoio -lopencv_imgcodecs -lopencv_imgproc -lopencv_features2d"); + println!("cargo::rerun-if-changed=src/barrel.cpp"); + + println!("cargo:rustc-link-search=native=D:\\vcpkg\\installed\\x64-windows-static-md\\lib"); + + println!("cargo:rustc-link-lib=static=opencv_core4"); + println!("cargo:rustc-link-lib=static=opencv_imgproc4"); + println!("cargo:rustc-link-lib=static=opencv_imgcodecs4"); + println!("cargo:rustc-link-lib=static=opencv_highgui4"); + + let mut config = vcpkg::Config::new(); + config.vcpkg_root([r"D:\", "vcpkg"].iter().collect::()); + let lib = config.find_package("opencv4").unwrap(); + let mut path = lib.include_paths[0].clone(); + path.push("opencv4"); + + println!("{:?}", lib); cc::Build::new() .file("src/process.cpp") .cpp(true) - .include("/usr/include/opencv4/") + .include(&path) // definitions cross language - .define("WINDOW_SIZE", "128") - .define("CHUNK_SIZE", "72") - .define("IMAGE_WIDTH", "1920") - .define("IMAGE_HEIGHT", "1080") + .define("WINDOW_SIZE", "64") + .define("CHUNK_SIZE", "128") + .define("CANVAS_WIDTH", "500") + .define("CANVAS_HEIGHT", "1000") + .define("IMAGE_WIDTH", "1080") + .define("IMAGE_HEIGHT", "1920") .define("LUT_SIZE", "12") //.define("USE_LUT", None) + //.define("PASSTHROUGH", None) .compile("process.a"); - println!("cargo::rustc-flags=-lopencv_core -lopencv_highgui -lopencv_xfeatures2d -lopencv_calib3d -lopencv_videoio -lopencv_imgcodecs -lopencv_imgproc -lopencv_features2d"); - - println!("cargo:rustc-env=WGPU_BACKEND=gl"); // fix show_image bug(?) + println!("cargo:rustc-env=WGPU_BACKEND=primary"); // fix show_image bug(?) println!("cargo:rustc-env=WGPU_POWER_PREF=high"); // can switch to low if performance issues + } diff --git a/src/barrel.cpp b/src/barrel.cpp index f2af095..44de751 100644 --- a/src/barrel.cpp +++ b/src/barrel.cpp @@ -1,11 +1,15 @@ -#include "opencv4/opencv2/imgproc.hpp" +#include "opencv2/imgproc.hpp" +#include +#include +#include +using namespace std; using namespace cv; void ApplyUndistort(uint8_t *camera_ptr, float *xmat_ptr, float *ymat_ptr) { - Mat xmat (IMAGE_HEIGHT, IMAGE_WIDTH, CV_32F, xmat_ptr); - Mat ymat (IMAGE_HEIGHT, IMAGE_WIDTH, CV_32F, ymat_ptr); + Mat xmat (IMAGE_HEIGHT, IMAGE_WIDTH, CV_16SC2, xmat_ptr); + Mat ymat (IMAGE_HEIGHT, IMAGE_WIDTH, CV_16UC1, ymat_ptr); Mat capture(IMAGE_HEIGHT, IMAGE_WIDTH, CV_8UC3, camera_ptr); Mat buffer = capture.clone(); @@ -23,4 +27,7 @@ void ApplyUndistort(uint8_t *camera_ptr, float *xmat_ptr, float *ymat_ptr) */ remap(buffer, capture, xmat, ymat, INTER_NEAREST); + + cv::imshow("Testing", capture); + int k = waitKey(0); // Wait for a keystroke in the window } diff --git a/src/capture.cpp b/src/capture.cpp new file mode 100644 index 0000000..afff7dc --- /dev/null +++ b/src/capture.cpp @@ -0,0 +1 @@ +#include "DeckLink X.Y\Win\Include\DeckLinkAPI.idl"; \ No newline at end of file diff --git a/src/color.cpp b/src/color.cpp index 6cdd2ba..936a4d5 100644 --- a/src/color.cpp +++ b/src/color.cpp @@ -1,26 +1,20 @@ #include -#include "opencv4/opencv2/core.hpp" - -#ifndef LUT_SIZE -const int IMAGE_WIDTH = 1920; -const int IMAGE_HEIGHT = 1080; -const int LUT_SIZE = 12; -#endif +#include "opencv2/core.hpp" using namespace std; using namespace cv; // is this damn well right?!?! -const float SCALER = ((float)LUT_SIZE - 1.) / 255.; +const float SCALER = ((float) LUT_SIZE - 1.) / 255.; void ApplyCorrection(uint8_t *buffer_ptr, uint8_t *lut_ptr) { try { - Mat capture(IMAGE_HEIGHT, IMAGE_WIDTH, CV_8UC3, buffer_ptr); + Mat buffer(CHUNK_SIZE, WINDOW_SIZE, CV_8UC3, buffer_ptr); - MatIterator_> it = capture.begin>(); - MatIterator_> it_end = capture.end>(); + MatIterator_> it = buffer.begin>(); + MatIterator_> it_end = buffer.end>(); /* * Pretty sure that because we're not actually using opencv for anything @@ -35,9 +29,9 @@ void ApplyCorrection(uint8_t *buffer_ptr, uint8_t *lut_ptr) Point3_ scaled (pixel); scaled *= SCALER; - int r = floor(scaled.z); - int g = floor(scaled.y); - int b = floor(scaled.x); + int r = (int) floor(scaled.z); + int g = (int) floor(scaled.y); + int b = (int) floor(scaled.x); int idx = (((LUT_SIZE * LUT_SIZE) * r) + (LUT_SIZE * g)+ b) * 3; @@ -75,7 +69,7 @@ void ApplyCorrection(uint8_t *buffer_ptr, uint8_t *lut_ptr) } catch (const std::exception &e) // handle exceptions for rust { - std::cout << "Exception " << e.what() << std::endl; + std::cout << "Exception BANG! " << e.what() << std::endl; } } diff --git a/src/color_functions.rs b/src/color_functions.rs new file mode 100644 index 0000000..9a6cbe8 --- /dev/null +++ b/src/color_functions.rs @@ -0,0 +1,60 @@ +use crate::{HUE_MIN, HUE_REL}; + + +pub fn _hsv_to_rgb (h: f32, s: f32, v:f32) -> (f32, f32, f32) { + let mut _h = h * (HUE_REL / 255f32); // [0, HUE_REL) <- should this be ... * (360 / 256) ????????? + let _s = s / 255f32; // [0, 1] + let _v = v / 255f32; // [0, 1] + + _h += HUE_MIN; // [HUE_MIN, HUE_MAX) + _h /= 60f32; + + let c = _s * _v; + let m = _v - c; + let x = c * (1f32 - (_h.rem_euclid(2f32) - 1f32).abs()); + + let (mut r, mut g, mut b) = match _h.floor() { + 0.0 => (c, x, 0f32), + 1.0 => (x, c, 0f32), + 2.0 => (0f32, c, x), + 3.0 => (0f32, x, c), + 4.0 => (x, 0f32, c), + _ => (c, 0f32, x) + }; + + r = (r + m) * 255f32; + g = (g + m) * 255f32; + b = (b + m) * 255f32; + + (r, g, b) +} + +pub fn _rgb_to_hsv (r: f32, g: f32, b:f32) -> (f32, f32, f32) { + let v = r.max(g).max(b); + let c = (v - r.min(g).min(b)) * 255f32; + let s = if v == 0f32 { 0f32 } else { c / v }; + + let mut h = if c == 0f32 { + // case 1: + 0f32 + } else if v == r { + // case 2: + 60f32 * ((g - b) / c).rem_euclid(6f32) + } else if v == g { + // case 3: + 60f32 * (((b - r) / c) + 2f32) + } else { + // case 4: + 60f32 * (((r - g) / c) + 4f32) + }; + h *= 255f32 / 360f32; + + (h, s, v) +} + +pub fn _rgb_to_sv (r: f32, g: f32, b:f32) -> (f32, f32) { + let v = r.max(g).max(b); + let s = if v == 0f32 { 0f32 } else { ((v - r.min(g).min(b)) * 255f32) / v }; // only do "c" if we need to + + (s, v) +} \ No newline at end of file diff --git a/src/generate_distort.py b/src/generate_distort.py index 696e843..61bf320 100644 --- a/src/generate_distort.py +++ b/src/generate_distort.py @@ -45,6 +45,9 @@ newcameramtx, roi = cv.getOptimalNewCameraMatrix(mtx, dist, (w,h), 1, (w,h)) # undistort mapx, mapy = cv.initUndistortRectifyMap(mtx, dist, None, newcameramtx, (w,h), 5) + +mapx, mapy = cv.convertMaps(mapx, mapy, cv.CV_16SC2) + dst = cv.remap(img, mapx, mapy, cv.INTER_LINEAR) np.save("./data/mapx.npy", mapx) @@ -55,7 +58,7 @@ x, y, w, h = roi dst = dst[y:y+h, x:x+w] img = cv.resize(img, (w, h)) -dst = np.concat((dst, img), axis=1) +dst = np.concat((img, dst), axis=1) cv.namedWindow("Result", cv.WINDOW_GUI_NORMAL) cv.imshow('Result', dst) diff --git a/src/generate_lut.py b/src/generate_lut.py old mode 100755 new mode 100644 index d4db011..d0e1f64 --- a/src/generate_lut.py +++ b/src/generate_lut.py @@ -26,6 +26,6 @@ if __name__ == "__main__": if PASSTHROUGH and CAST_TEST: validate(lut) - save("./data/cube.npy", lut.lut) + save("cube.npy", lut.lut) diff --git a/src/homography.cpp b/src/homography.cpp index c68c21b..ffaf80b 100644 --- a/src/homography.cpp +++ b/src/homography.cpp @@ -1,7 +1,9 @@ -#include "opencv4/opencv2/xfeatures2d.hpp" -#include "opencv4/opencv2/calib3d.hpp" -#include "opencv4/opencv2/imgproc.hpp" -#include "opencv4/opencv2/imgcodecs.hpp" +#include "opencv2/calib3d.hpp" +#include "opencv2/xfeatures2d.hpp" +#include "opencv2/imgproc.hpp" +#include "opencv2/imgcodecs.hpp" +#include +#include using namespace cv; using namespace cv::xfeatures2d; @@ -10,12 +12,14 @@ void FuncGetHomography(uint8_t *camera_ptr, double *homography_ptr) { try { - Mat img1 = imread( samples::findFile("./test/calibration.jpg")/*, IMREAD_GRAYSCALE */); + Mat img1 = imread( samples::findFile("./test/towers.jpg")/*, IMREAD_GRAYSCALE */); Mat img2(IMAGE_HEIGHT, IMAGE_WIDTH, CV_8UC3, camera_ptr); + cvtColor(img2, img2, COLOR_RGB2BGR); // detect keypoints and compute descriptors int minHessian = 400; Ptr detector = SURF::create( minHessian ); + (*detector).setExtended(true); std::vector keypoints1, keypoints2; Mat descriptors1, descriptors2; @@ -56,6 +60,13 @@ void FuncGetHomography(uint8_t *camera_ptr, double *homography_ptr) // copy the result to the homography location const double* result_ptr = homography.ptr(0); std::memcpy(homography_ptr, result_ptr, 72); // size of [f64; 9] + + Mat output; + drawMatches(img1, keypoints1, img2, keypoints2, good_matches, output); + + namedWindow("testing", WINDOW_NORMAL); + imshow("testing", output); + int k = waitKey(0); // Wait for a keystroke in the window } catch (const std::exception &e) // handle exceptions for rust { @@ -63,13 +74,51 @@ void FuncGetHomography(uint8_t *camera_ptr, double *homography_ptr) } } -void ApplyHomography(uint8_t *camera_ptr, uint8_t *buffer_ptr, double *homography_ptr) +#ifndef CUDA + +void ApplyHomography(uint8_t *camera_ptr, uint8_t *buffer_ptr, double *homography_ptr) // validated! { Mat capture(IMAGE_HEIGHT, IMAGE_WIDTH, CV_8UC3, camera_ptr); + Mat result(CANVAS_HEIGHT, CANVAS_WIDTH, CV_8UC3); + Mat homography(3, 3, CV_64F, homography_ptr); + +#ifdef PASSTHROUGH + Mat buffer(CHUNK_SIZE, WINDOW_SIZE, CV_8UC3); +#else Mat buffer(CHUNK_SIZE, WINDOW_SIZE, CV_8UC3, buffer_ptr); +#endif // PASSTHROUGH + + warpPerspective(capture, result, homography, Size(CANVAS_WIDTH, CANVAS_HEIGHT)); // try INTER_LINEAR + resize(result, buffer, Size(WINDOW_SIZE, CHUNK_SIZE), 0, 0, INTER_NEAREST); // make sure this is right it would probably be a nebulous one to figure out +} + +#else + +#include "opencv2/gpu/gpu.hpp" + +void ApplyHomography(uint8_t* camera_ptr, uint8_t* buffer_ptr, double* homography_ptr) // validated! +{ + Mat capture(IMAGE_HEIGHT, IMAGE_WIDTH, CV_8UC3, camera_ptr); Mat homography(3, 3, CV_64F, homography_ptr); - warpPerspective(capture, capture, homography, capture.size()); - resize(capture, buffer, buffer.size()); +#ifdef PASSTHROUGH + Mat buffer(CHUNK_SIZE, WINDOW_SIZE, CV_8UC3); +#else + Mat buffer(CHUNK_SIZE, WINDOW_SIZE, CV_8UC3, buffer_ptr); +#endif // PASSTHROUGH + + GpuMat capture_gpu(IMAGE_HEIGHT, IMAGE_WIDTH, CV_8UC3); + GpuMat result_gpu(CANVAS_HEIGHT, CANVAS_WIDTH, CV_8UC3); + GpuMat homography_gpu(3, 3, CV_64F); + GpuMat buffer_gpu(CHUNK_SIZE, WINDOW_SIZE, CV_8UC3); + + capture_gpu.upload(capture); + homography_gpu.upload(homography); + + gpu::warpPerspective(capture_gpu, result_gpu, homography_gpu, Size(CANVAS_WIDTH, CANVAS_HEIGHT)); // vvv try INTER_LINEAR + gpu::resize(result_gpu, buffer_gpu, Size(WINDOW_SIZE, CHUNK_SIZE), 0, 0, INTER_NEAREST); // make sure this is right it would probably be a nebulous one to figure out + + buffer.download(buffer_gpu); } +#endif // CUDA diff --git a/src/image_array.rs b/src/image_array.rs index d2de10f..921debf 100644 --- a/src/image_array.rs +++ b/src/image_array.rs @@ -1,214 +1,230 @@ -use image::ImageFormat; -use nokhwa::{Camera, FormatDecoder}; +use nokhwa::{Camera, query}; use nokhwa::utils::{ RequestedFormat, CameraIndex, CameraFormat, Resolution, - FrameFormat, - RequestedFormatType + RequestedFormatType, + ApiBackend }; +use nokhwa::utils::KnownCameraControl::*; +use nokhwa::utils::ControlValueSetter::*; use nokhwa::pixel_format::{RgbFormat, YuyvFormat}; use rustfft::num_complex::Complex; use npyz::NpyFile; -use yuv::{yuyv422_to_rgb, YuvPackedImage, YuvRange, YuvStandardMatrix}; - use std::io::BufReader; use std::fs::File; +use relative_path::RelativePath; + +use rayon::prelude::*; use crate::{ GetHomography, ProcessCapture, LUT_LENGTH, + LUT_PATH, + MAPX_PATH, + MAPY_PATH, SPECTOGRAM_AREA, IMAGE_AREA, - IMAGE_WIDTH, - IMAGE_HEIGHT, VOLUME_MIN, VOLUME_REL, AMPLITUDE_REL, AMPLITUDE_MIN, ANGLE_REL, ANGLE_MIN, - FPS + FPS, + PASSTHROUGH, + IMAGE_WIDTH, + IMAGE_HEIGHT, + IMAGE_FORMAT, + DEBUG +}; + +use crate::color_functions::{ + _hsv_to_rgb, + _rgb_to_sv }; pub struct ImageArray { pub data: Vec, homography: [f64; 9], lut: [u8; LUT_LENGTH], + mapx_ptr: usize, + mapy_ptr: usize, camera_buffer: Vec, - camera: Camera, - chunks: usize + camera: Camera } impl ImageArray { - pub fn new (homography: [f64; 9]) -> Self { - + pub fn new (homography: [f64; 9], index: u32, mapx_ptr: usize, mapy_ptr: usize, focus: i64) -> Self { + // digest the numpy array and setup lut - let file = BufReader::new(File::open("./data/cube.npy").unwrap()); + let lut_path = RelativePath::new(LUT_PATH).as_str(); + let file = BufReader::new(File::open(lut_path).unwrap()); let npy = NpyFile::new(file).unwrap(); - - // this is a little silly i should handle these things let lut: [u8; LUT_LENGTH] = npy.into_vec().unwrap().try_into().unwrap(); - - // setup the camera - let index = CameraIndex::Index(2); - let format = CameraFormat::new( - Resolution { width_x: 1920, height_y: 1080 }, - FrameFormat::YUYV, - FPS as u32 - ); - let requested = RequestedFormat::new::( - RequestedFormatType::Closest(format) + + // setup the camera formats + let index = CameraIndex::Index(index); + let format = RequestedFormat::new::( + RequestedFormatType::Closest( + CameraFormat::new( + Resolution { width_x: IMAGE_WIDTH as u32, height_y: IMAGE_HEIGHT as u32}, + IMAGE_FORMAT, + FPS as u32 + ) + ) ); - - let mut camera = Camera::new(index, requested).unwrap(); + + if DEBUG { + // open the camera with its default to get the list of all its formats & print the backend info + println!("{:#?}", query(ApiBackend::MediaFoundation)); + let mut camera = Camera::new(index.clone(), RequestedFormat::new::(RequestedFormatType::None)).unwrap(); + println!("{:?}", camera.compatible_list_by_resolution(IMAGE_FORMAT)); + println!("{:?}", camera.supported_camera_controls().unwrap()); + }; + + let mut camera = Camera::new(index, format).unwrap(); camera.open_stream().unwrap(); - // self + camera.set_camera_control(Brightness, Integer(255)).unwrap(); + camera.set_camera_control(Contrast, Integer(128)).unwrap(); + camera.set_camera_control(Saturation, Integer(128)).unwrap(); + camera.set_camera_control(Sharpness, Integer(0)).unwrap(); + camera.set_camera_control(WhiteBalance, Integer(5000)).unwrap(); + camera.set_camera_control(BacklightComp, Integer(0)).unwrap(); + camera.set_camera_control(Gain, Integer(0)).unwrap(); + camera.set_camera_control(Exposure, Integer(-2)).unwrap(); + camera.set_camera_control(Zoom, Integer(100)).unwrap(); + camera.set_camera_control(Focus, Integer(focus)).unwrap(); + Self { data: vec![0u8; SPECTOGRAM_AREA * 3], homography, lut, + mapx_ptr, + mapy_ptr, camera_buffer: vec![0u8; IMAGE_AREA], - camera, - chunks: SPECTOGRAM_AREA + camera } } pub fn read_camera (&mut self) { - let frame = self.camera.frame().unwrap(); - - // some code to turn the yuyv into rgb if we need it! - // let stride = (IMAGE_WIDTH * 3) as u32; - // let vuvy = YuvPackedImage{ - // yuy: frame.buffer(), - // yuy_stride: stride, - // width: IMAGE_WIDTH as u32, - // height: IMAGE_HEIGHT as u32 - // }; - // let mut rgb = [0u8; IMAGE_AREA]; - // yuyv422_to_rgb( - // &vuvy, - // &mut rgb, - // stride, - // YuvRange::Full, - // YuvStandardMatrix::Bt601 - // ).unwrap(); - + let frame = self.camera.frame().expect(&format!("Oh no! Camera {} failed", self.camera.info())); let decoder = frame.decode_image::().unwrap(); - decoder.save_with_format("./image.png", ImageFormat::Png).unwrap(); - - self.camera_buffer = decoder.into_vec()[..].into(); // something is wrong here - - + self.camera_buffer = decoder.into_raw()[..].into(); + unsafe { ProcessCapture ( self.camera_buffer.as_ptr() as usize, - self.data.as_ptr() as usize, - self.homography.as_ptr() as usize, - self.lut.as_ptr() as usize + self.data.as_ptr() as usize, + self.homography.as_ptr() as usize, + self.lut.as_ptr() as usize, + self.mapx_ptr, + self.mapy_ptr ); - } + }; } pub fn calibrate (&mut self) { - // hopefully dont need this ! - // for _i in 0..10 { - // self.camera_buffer = self.camera.capture().unwrap()[..].try_into().expect("Image is wrong size"); //delete assignment - // } + // read straight from the camera so as to not make "read_camera" too convoluted + for _ in 0..100 { + self.camera.frame().unwrap(); + } + let frame = self.camera.frame().unwrap(); + let decoder = frame.decode_image::().unwrap(); + self.camera_buffer = decoder.into_raw()[..].into(); // enter unsafe and get the homography array - unsafe { - GetHomography(self.camera_buffer.as_ptr() as usize, self.homography.as_ptr() as usize); + if !PASSTHROUGH { + unsafe { + GetHomography( + self.camera_buffer.as_ptr() as usize, + self.homography.as_ptr() as usize, + self.mapx_ptr, + self.mapy_ptr + ); + } } + if DEBUG { println!("{:#?}", self.homography); } } pub fn read_buffer (&mut self, buffer: &[Complex]) { - let mut r: f32; - let mut theta: f32; - let mut amplitude: f32; - - let mut hue: f32; - let mut angle: f32; - - let mut d:f32; - let mut s:f32; - let mut v:f32; - let mut c:f32; - let mut m:f32; - let mut x:f32; - let mut g:f32; - let mut b:f32; - - for i in 0..self.chunks { - (r, theta) = buffer[i].to_polar(); - - // make linear and normalize - amplitude = 20f32 * r.log10(); + /* + hsv -> amplitude, angle, extra + extra and spectrogram become seperated + + hsv -> angle, amplitude, extra + extra and spectrogram become seperated + + hsv -> angle, extra, amplitude + good but color split down middle in strange way + hue mapped to phase is also poor + + hsv -> amplitude, extra, angle + Looks more integrated but not that much + good noise + + hsv -> extra, angle, amplitude + enjoy the colors -> laurens fave looks cohesive + visually more interesting. makes the spectrograms minimal & sounds clear + + hsv -> extra, amplitude, angle + similar to last but slightly worse could be workable but + + rgb -> all + just different combinations of colors + fairly seperated + + hsplit -> angle, amplitude + + hsplit -> amplitude, angle + + */ + (0..SPECTOGRAM_AREA).into_par_iter().zip(self.data.par_chunks_mut(3)).for_each(|(i, rgb)| { + let (norm, theta) = buffer[i].to_polar(); + + // scale amplitude + let mut amplitude = 20f32 * norm.log10(); amplitude = ((amplitude - VOLUME_MIN) / (VOLUME_REL / AMPLITUDE_REL)) + AMPLITUDE_MIN; - - hue = (180f32 / 255f32) * amplitude; - - angle = (theta.to_degrees() + 180f32) * (ANGLE_REL / 360f32) + ANGLE_MIN; - - d = hue * (1f32 / 30f32); - s = angle / 255f32; - v = amplitude / 255f32; - - c = s * v; - m = v - c; - x = c * (1f32 - (d.rem_euclid(2f32) - 1f32).abs()); - - (r, g, b) = match d.floor() { - 0.0 => (c, x, 0f32), - 1.0 => (x, c, 0f32), - 2.0 => (0f32, c, x), - 3.0 => (0f32, x, c), - 4.0 => (x, 0f32, c), - _ => (c, 0f32, x) - }; - - self.data[i*3] = ((r + m) * 255f32) as u8; - self.data[i*3+1] = ((g + m) * 255f32) as u8; - self.data[i*3+2] = ((b + m) * 255f32) as u8; - } + + // scale angle + let angle = (theta.to_degrees() + 180f32) * (ANGLE_REL / 360f32) + ANGLE_MIN; + + // ============================================== + let (r, g, b) = _hsv_to_rgb(amplitude, angle, amplitude); + // ============================================== + + rgb[0] = r as u8; + rgb[1] = g as u8; + rgb[2] = b as u8; + }); } pub fn write_buffer (&mut self, buffer: &mut [Complex]) { - let mut r: f32; - let mut amplitude: f32; - - let mut angle: f32; - - let mut s:f32; - let mut v:f32; - let mut c:f32; - let mut g:f32; - let mut b:f32; + (0..SPECTOGRAM_AREA).into_par_iter().zip(buffer.par_iter_mut()).for_each(|(i, buffer_point)| { + let r = self.data[i*3] as f32; + let g = self.data[i*3+1] as f32; + let b = self.data[i*3+2] as f32; - for i in 0..self.chunks { - r = self.data[i*3] as f32; - g = self.data[i*3+1] as f32; - b = self.data[i*3+2] as f32; - - v = r.max(g).max(b); - c = (v - r.min(g).min(b)) * 255f32; - s = if v == 0f32 { 0f32 } else { c / v }; - - amplitude = (v - AMPLITUDE_MIN) * (VOLUME_REL / AMPLITUDE_REL) + VOLUME_MIN; + // ========================================== + let (mut angle, mut amplitude) = _rgb_to_sv(r, g, b); + // ========================================== + // scale amplitude + amplitude = (amplitude - AMPLITUDE_MIN) * (VOLUME_REL / AMPLITUDE_REL) + VOLUME_MIN; amplitude = 10f32.powf(amplitude / 20f32); - - angle = (s - ANGLE_MIN) / (ANGLE_REL / 360f32) - 180f32; + + // scale angle + angle = (angle - ANGLE_MIN) / (ANGLE_REL / 360f32) - 180f32; angle = angle.to_radians(); - buffer[i] = Complex::from_polar(amplitude, angle); - } + *buffer_point = Complex::from_polar(amplitude, angle); + }); } } diff --git a/src/lut/camera.py b/src/lut/camera.py index 691d8da..b61890b 100644 --- a/src/lut/camera.py +++ b/src/lut/camera.py @@ -15,8 +15,7 @@ class Camera(): # get image from camera and fix perspective def get(self, image): - small = cv.resize(image, (640,360)) - cv.imshow("LUT Calibration", small) + cv.imshow("LUT Calibration", image) cv.waitKey(CAP_WAIT) if PASSTHROUGH: diff --git a/src/lut/config.py b/src/lut/config.py index 0239b42..9695e48 100644 --- a/src/lut/config.py +++ b/src/lut/config.py @@ -6,12 +6,12 @@ optimal, conventially 33 is used. This will need to be tested with a camera. """ LUT_SIZE = 12 -IMAGE_WIDTH = 1920 #1920 -IMAGE_HEIGHT = 1080 #1080 +IMAGE_WIDTH = 500 #1920 +IMAGE_HEIGHT = 1000 #1080 # size of the qr codes and the space around them (px) -QR_SIZE = 300 -QR_PADDING = 10 +QR_SIZE = 200 +QR_PADDING = 5 # the wait time between each camera check after we stop generating WAIT_TIME = 0.1 #s diff --git a/src/lut/cube.py b/src/lut/cube.py old mode 100755 new mode 100644 diff --git a/src/lut/graph.py b/src/lut/graph.py old mode 100755 new mode 100644 diff --git a/src/lut/test.py b/src/lut/test.py old mode 100755 new mode 100644 diff --git a/src/main.rs b/src/main.rs index 0d4153c..335eabf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,195 +1,621 @@ use rustfft::algorithm::Radix4; use rustfft::{Fft, FftDirection}; use rustfft::num_complex::Complex; -use show_image::{ImageView, ImageInfo, create_window, event}; + +use show_image::{ + ImageView, + ImageInfo, + ArcImage, + create_window, + event, + Color, + WindowOptions +}; + use cpal::{StreamConfig, BufferSize, SampleRate}; use cpal::traits::{DeviceTrait, HostTrait, StreamTrait}; + use std::sync::{Arc, Mutex}; use std::sync::mpsc; -use image::ImageReader; +use std::time::SystemTime; + +use image::{ImageReader, ImageBuffer, Rgb}; + use relative_path::RelativePath; + +use nokhwa::utils::FrameFormat; + +use rayon::prelude::*; + +use npyz::NpyFile; + +use resampler::{Attenuation, Latency, ResamplerFir, SampleRate as ResamplerSampleRate}; + +use std::io::{BufReader, Write}; +use std::fs::File; mod image_array; mod sample_buffer; +mod style_utils; +mod color_functions; +mod utils; use image_array::ImageArray; use sample_buffer::SampleBuffer; -use lowpass_filter::LowpassFilter; +/* +NOTES: + - to calibrate you have to press enter on the images in the order of A-B-C. + - the sample rate is based only off file A and the others are assumed to be the same + - could paralelize the fft calls to speed them up? + - need to look at how images are displayed to the screen, very inneffective +*/ -const WINDOW_SIZE: usize = 128; -const CHUNK_SIZE: usize = 72; +const WINDOW_SIZE: usize = 64; // 32 +const CHUNK_SIZE: usize = 128; // 64 const SPECTOGRAM_AREA: usize = WINDOW_SIZE * CHUNK_SIZE; +// config of the display windows +// note: this is only used for the show_image config +const CANVAS_WIDTH: usize = 500; +const CANVAS_HEIGHT: usize = 1000; + // configuration of the camera used -const IMAGE_WIDTH: usize = 1920; -const IMAGE_HEIGHT: usize = 1080; +const IMAGE_WIDTH: usize = 1080; +const IMAGE_HEIGHT: usize = 1920; const IMAGE_AREA: usize = IMAGE_WIDTH * IMAGE_HEIGHT * 3; -const FPS: usize = 5; +const IMAGE_FORMAT: FrameFormat = FrameFormat::NV12; +const FPS: usize = 30; + +const CAM_A_IDX: u32 = 1; +const CAM_B_IDX: u32 = 2; +const CAM_C_IDX: u32 = 0; + +const DEV_C12_IDX: usize = 4; +const DEV_C34_IDX: usize = 2; +const DEV_C56_IDX: usize = 7; +const DEV_C78_IDX: usize = 6; +/* +const DEV_C12_IDX: usize = 0; +const DEV_C34_IDX: usize = 0; +const DEV_C56_IDX: usize = 0; +const DEV_C78_IDX: usize = 0; +*/ // maximum and minimum pixel values of angle and amplitude. could be confined to // improve performance for quiet sounds. -const AMPLITUDE_MAX: f32 = 255.0; -const AMPLITUDE_MIN: f32 = 0.0; +const AMPLITUDE_MAX: f32 = 245.0; +const AMPLITUDE_MIN: f32 = 10.0; const AMPLITUDE_REL: f32 = AMPLITUDE_MAX - AMPLITUDE_MIN; -const ANGLE_MAX: f32 = 255.0; -const ANGLE_MIN: f32 = 0.0; +const ANGLE_MAX: f32 = 245.0; +const ANGLE_MIN: f32 = 10.0; const ANGLE_REL: f32 = ANGLE_MAX - ANGLE_MIN; +// this is a scaling specific to hue that applies idependant of which thing is mapped to it +const HUE_MAX: f32 = 0.0; // in range of [0,360) +const HUE_MIN: f32 = 360.0; +const HUE_REL: f32 = HUE_MAX - HUE_MIN; + // because of the opposingly logarithmic properties of both noise error and volume // this maximum value is important. -40 to 100 may not work under real conditions, // and -40 to 65 or even lower may produce better results. -const VOLUME_MAX: f32 = 65.0; // 60 - 65 +const VOLUME_MAX: f32 = 60.0; // 60 - 65 const VOLUME_MIN: f32 = -40.0; const VOLUME_REL: f32 = VOLUME_MAX - VOLUME_MIN; const LUT_SIZE: usize = 12; const LUT_LENGTH: usize = LUT_SIZE * LUT_SIZE * LUT_SIZE * 3; +const LUT_PATH: &str = "./data/cube.npy"; -const DEBUG_MODE: bool = true; +const MAPX_PATH: &str = "./data/mapx.npy"; +const MAPY_PATH: &str = "./data/mapy.npy"; -const CALIBRATION_PATH: &str = "./test/calibration.jpg"; -const AUDIO_PATH: &str = "./test/example.wav"; +const PASSTHROUGH: bool = false; +const DEBUG: bool = true; +const CALIBRATE: bool = true; + +const CALIBRATION_PATH: &str = "./test/towers.jpg"; + const AUDIO_PATH_A: &str = "./test/example_hq.wav"; + const AUDIO_PATH_B: &str = "./test/example_hq.wav"; + const AUDIO_PATH_C: &str = "./test/example_hq.wav"; +//const AUDIO_PATH_A: &str = "test/threshold-A_03.wav"; +//const AUDIO_PATH_B: &str = "test/threshold-B_03.wav"; +//const AUDIO_PATH_C: &str = "test/threshold-C_03.wav"; + +const AUDIO_A_C1: f32 = 1.0; const AUDIO_A_C2: f32 = 0.0; +const AUDIO_A_C3: f32 = 0.0; const AUDIO_A_C4: f32 = 0.0; +const AUDIO_A_C5: f32 = 0.0; const AUDIO_A_C6: f32 = 0.0; +const AUDIO_A_C7: f32 = 0.0; const AUDIO_A_C8: f32 = 0.0; + +const AUDIO_B_C1: f32 = 0.0; const AUDIO_B_C2: f32 = 0.0; +const AUDIO_B_C3: f32 = 0.0; const AUDIO_B_C4: f32 = 0.0; +const AUDIO_B_C5: f32 = 0.0; const AUDIO_B_C6: f32 = 1.0; +const AUDIO_B_C7: f32 = 0.0; const AUDIO_B_C8: f32 = 0.0; + +const AUDIO_C_C1: f32 = 0.0; const AUDIO_C_C2: f32 = 0.0; +const AUDIO_C_C3: f32 = 0.0; const AUDIO_C_C4: f32 = 0.0; +const AUDIO_C_C5: f32 = 1.0; const AUDIO_C_C6: f32 = 0.0; +const AUDIO_C_C7: f32 = 0.0; const AUDIO_C_C8: f32 = 0.0; + +const OUTPUT_RATE: usize = 48000;//Hz // feedback config -const WET: f32 = 0.0; +const WET: f32 = 0.9; const DRY: f32 = 1.0; -// audio effects and filtering -const MAIN_LOWPASS: f32 = 20000.0; -const FEEDBACK_LOWPASS: f32 = 20000.0; -const FILTER_SCALING: f32 = 1. / 65535.; // to bring any signal down to +-1 - extern "C" { - fn GetHomography(camera_ptr: usize, homography_ptr: usize); - fn ProcessCapture(camera_ptr: usize, buffer_ptr: usize, homography_ptr: usize, lut_ptr: usize); + fn GetHomography(camera_ptr: usize, homography_ptr: usize, xmap_ptr: usize, ymap_ptr: usize); + fn ProcessCapture(camera_ptr: usize, buffer_ptr: usize, homography_ptr: usize, lut_ptr: usize, xmap_ptr: usize, ymap_ptr: usize); } #[show_image::main] fn main () -> Result<(), Box> { + println!(" * Info: max delay is {}ms", 44100000 / SPECTOGRAM_AREA); + + println!(" * Reserving memory"); + // pregenerate the fft transformers let forward_transform = Radix4::::new(WINDOW_SIZE, FftDirection::Forward); let inverse_transform = Radix4::::new(WINDOW_SIZE, FftDirection::Inverse); let scratch_size = forward_transform.get_inplace_scratch_len(); // preallocate complex space for the ffts - let mut buffer = vec![Complex{re: 0f32, im: 0f32}; SPECTOGRAM_AREA]; + let mut buffer_a = vec![Complex{re: 0f32, im: 0f32}; SPECTOGRAM_AREA]; + let mut buffer_b = vec![Complex{re: 0f32, im: 0f32}; SPECTOGRAM_AREA]; + let mut buffer_c = vec![Complex{re: 0f32, im: 0f32}; SPECTOGRAM_AREA]; let mut scratch = vec![Complex{re: 0f32, im: 0f32}; scratch_size]; // setup communication between the main thread and the audio thread - let (tx, rx) = mpsc::channel(); - let sample_buffer = Arc::new(Mutex::new([0i16; 2*SPECTOGRAM_AREA])); - let mut samples = SampleBuffer::new(sample_buffer.clone(), tx); + let (tx_c12, rx_c12) = mpsc::channel(); + let (tx_c34, rx_c34) = mpsc::channel(); + let (tx_c56, rx_c56) = mpsc::channel(); + let (tx_c78, rx_c78) = mpsc::channel(); + + let sample_buffer_c1 = Arc::new(Mutex::new([0i16; 2*SPECTOGRAM_AREA])); + let sample_buffer_c2 = Arc::new(Mutex::new([0i16; 2*SPECTOGRAM_AREA])); + let sample_buffer_c3 = Arc::new(Mutex::new([0i16; 2*SPECTOGRAM_AREA])); + let sample_buffer_c4 = Arc::new(Mutex::new([0i16; 2*SPECTOGRAM_AREA])); + let sample_buffer_c5 = Arc::new(Mutex::new([0i16; 2*SPECTOGRAM_AREA])); + let sample_buffer_c6 = Arc::new(Mutex::new([0i16; 2*SPECTOGRAM_AREA])); + let sample_buffer_c7 = Arc::new(Mutex::new([0i16; 2*SPECTOGRAM_AREA])); + let sample_buffer_c8 = Arc::new(Mutex::new([0i16; 2*SPECTOGRAM_AREA])); + + let mut samples_c12 = SampleBuffer::new(sample_buffer_c1.clone(), sample_buffer_c2.clone(), tx_c12); + let mut samples_c34 = SampleBuffer::new(sample_buffer_c3.clone(), sample_buffer_c4.clone(), tx_c34); + let mut samples_c56 = SampleBuffer::new(sample_buffer_c5.clone(), sample_buffer_c6.clone(), tx_c56); + let mut samples_c78 = SampleBuffer::new(sample_buffer_c7.clone(), sample_buffer_c8.clone(), tx_c78); + + // resampler + let mut resampler = ResamplerFir::new( + 1, + ResamplerSampleRate::Hz22050, + ResamplerSampleRate::Hz48000, + Latency::Sample64, // could change to Sample8 + Attenuation::Db90, + ); + + // get the map to share it between the image arrays + let mapx_path = RelativePath::new(MAPX_PATH).as_str(); + let mapx_file = BufReader::new(File::open(mapx_path).unwrap()); + let mapx_npy = NpyFile::new(mapx_file).unwrap(); + let mapx: Vec = mapx_npy.into_vec().unwrap(); + + let mapy_path = RelativePath::new(MAPY_PATH).as_str(); + let mapy_file = BufReader::new(File::open(mapy_path).unwrap()); + let mapy_npy = NpyFile::new(mapy_file).unwrap(); + let mapy: Vec = mapy_npy.into_vec().unwrap(); // setup homography space and get ready for the calibration - let homography = [0f64; 9]; // homography is a 3x3 matrix of 64-bit floats - let mut image_array = ImageArray::new(homography); + let homography_a = [0f64; 9]; // homography is a 3x3 matrix of 64-bit floats + let homography_b = [0f64; 9]; // homography is a 3x3 matrix of 64-bit floats + let homography_c = [0f64; 9]; // homography is a 3x3 matrix of 64-bit floats + println!(" * Starting camera A"); + let mut image_array_a = ImageArray::new(homography_a, CAM_A_IDX, mapx.as_ptr() as usize, mapy.as_ptr() as usize, 190); + println!(" * Starting camera B"); + let mut image_array_b = ImageArray::new(homography_b, CAM_B_IDX, mapx.as_ptr() as usize, mapy.as_ptr() as usize, 172); + println!(" * Starting camera C"); + let mut image_array_c = ImageArray::new(homography_c, CAM_C_IDX, mapx.as_ptr() as usize, mapy.as_ptr() as usize, 236); // create the debug window - let debug_window = create_window("Debug", Default::default())?; + let window_options = WindowOptions{ + preserve_aspect_ratio: false, + background_color: Color::black(), + start_hidden: false, + size: Some([(WINDOW_SIZE * 3) as u32, CHUNK_SIZE as u32]), + resizable: true, + borderless: false, + fullscreen: false, + overlays_visible: false, + default_controls: false + }; + let debug_window = create_window("Debug", window_options)?; // get calibration image path let calibration_path = RelativePath::new(CALIBRATION_PATH).as_str(); // create window for displaying images and display calibration image - let display_window = create_window("Display", Default::default())?; + let window_options = WindowOptions{ + preserve_aspect_ratio: false, + background_color: Color::black(), + start_hidden: false, + size: Some([CANVAS_WIDTH as u32, CANVAS_HEIGHT as u32]), + resizable: true, + borderless: false, + fullscreen: false, + overlays_visible: false, + default_controls: false + }; + let display_window_a = create_window("Display A", window_options.clone())?; + let display_window_b = create_window("Display B", window_options.clone())?; + let display_window_c = create_window("Display C", window_options)?; + let calibration_image = ImageReader::open(calibration_path)?.decode()?; - display_window.set_image("Display", calibration_image)?; + display_window_a.set_image("Display A", calibration_image.clone())?; + display_window_b.set_image("Display B", calibration_image.clone())?; + display_window_c.set_image("Display C", calibration_image)?; - // wait for the user to press a key before continuing - for event in display_window.event_channel()? { - if let event::WindowEvent::KeyboardInput(event) = event { - if event.input.key_code == Some(event::VirtualKeyCode::Return) && event.input.state.is_pressed() { - break; + let mut arc_data_a: [u8; SPECTOGRAM_AREA * 3]; + let mut arc_image_a: ArcImage; + let mut arc_data_b: [u8; SPECTOGRAM_AREA * 3]; + let mut arc_image_b: ArcImage; + let mut arc_data_c: [u8; SPECTOGRAM_AREA * 3]; + let mut arc_image_c: ArcImage; + + // calibrate camera + if CALIBRATE { + println!(" * Calibrating Display A"); + // wait for the user to press a key before continuing + for event in display_window_a.event_channel()? { + if let event::WindowEvent::KeyboardInput(event) = event { + if event.input.key_code == Some(event::VirtualKeyCode::Return) && event.input.state.is_pressed() { + image_array_a.calibrate(); + break; + } + } + } + + println!(" * Calibrating Display B"); + for event in display_window_b.event_channel()? { + if let event::WindowEvent::KeyboardInput(event) = event { + if event.input.key_code == Some(event::VirtualKeyCode::Return) && event.input.state.is_pressed() { + image_array_b.calibrate(); + break; + } + } + } + + println!(" * Calibrating Display C"); + for event in display_window_c.event_channel()? { + if let event::WindowEvent::KeyboardInput(event) = event { + if event.input.key_code == Some(event::VirtualKeyCode::Return) && event.input.state.is_pressed() { + image_array_c.calibrate(); + break; + } } } } - // calibrate camera - image_array.calibrate(); - - // get audio path - let audio_path = RelativePath::new(AUDIO_PATH).as_str(); - - // open audio file - let mut reader = hound::WavReader::open(audio_path).unwrap(); - let file_rate = reader.spec().sample_rate; - - // setup the lowpass filters - let main_lowpass = LowpassFilter::new(file_rate, MAIN_LOWPASS); - let feedback_lowpass = LowpassFilter::new(file_rate, FEEDBACK_LOWPASS); - + // get audio path and open audio file + let audio_path_a = RelativePath::new(AUDIO_PATH_A).as_str(); + let audio_path_b = RelativePath::new(AUDIO_PATH_B).as_str(); + let audio_path_c = RelativePath::new(AUDIO_PATH_C).as_str(); + + println!(" * Opening audio files"); + + let mut reader_a = hound::WavReader::open(audio_path_a).unwrap(); + let mut reader_b = hound::WavReader::open(audio_path_b).unwrap(); + let mut reader_c = hound::WavReader::open(audio_path_c).unwrap(); + + let file_rate = reader_a.spec().sample_rate; + + // get inf iter of the samples in the wav file + let samples_a: Vec = reader_a.samples::().filter_map(Result::ok).collect::>(); + let mut infinite_a = samples_a.iter().copied().cycle(); + + let samples_b: Vec = reader_b.samples::().filter_map(Result::ok).collect::>(); + let mut infinite_b = samples_b.iter().copied().cycle(); + + let samples_c: Vec = reader_c.samples::().filter_map(Result::ok).collect::>(); + let mut infinite_c = samples_c.iter().copied().cycle(); + + println!(" * Itterators constructed"); + + let mut out_samples_a = [0f32; 11025]; // this is an arbitrary number sorry + let mut out_samples_b = [0f32; 11025]; + let mut out_samples_c = [0f32; 11025]; + // setup audio output and build output stream + println!(" * Output stream setup"); let host = cpal::default_host(); - let device = host.default_output_device().expect("No output device available"); + + if DEBUG { + for device in host.output_devices().unwrap() { + println!("{:?}", device.name().unwrap()); + } + //println!("{:?}", device.default_output_config()); + //let configs = device.supported_output_configs().unwrap(); + //for supported_config in configs { + // println!("{:?}", supported_config); + //} + } - let stream = device.build_output_stream( + let device_c12 = host.output_devices().unwrap().nth(DEV_C12_IDX).unwrap(); + let device_c34 = host.output_devices().unwrap().nth(DEV_C34_IDX).unwrap(); + let device_c56 = host.output_devices().unwrap().nth(DEV_C56_IDX).unwrap(); + let device_c78 = host.output_devices().unwrap().nth(DEV_C78_IDX).unwrap(); + + // CHANNELS 1-2 + let stream_c12 = device_c12.build_output_stream( + &StreamConfig{ + channels: 2, + sample_rate: SampleRate(OUTPUT_RATE as u32), + buffer_size: BufferSize::Fixed(WINDOW_SIZE as u32) + }, + move |data: &mut [i16], _: &cpal::OutputCallbackInfo| { + samples_c12.get_data(data); + }, + move |err| { + eprintln!("An error occurred on the output audio stream: {}", err); + }, + None + ).unwrap(); + println!(" * Starting stream"); + stream_c12.play().expect("Stream 1-2 play failed"); + + // CHANNELS 3-4 + let stream_c34 = device_c34.build_output_stream( + &StreamConfig{ + channels: 2, + sample_rate: SampleRate(OUTPUT_RATE as u32), + buffer_size: BufferSize::Fixed(WINDOW_SIZE as u32) + }, + move |data: &mut [i16], _: &cpal::OutputCallbackInfo| { + samples_c34.get_data(data); + }, + move |err| { + eprintln!("An error occurred on the output audio stream: {}", err); + }, + None + ).unwrap(); + println!(" * Starting stream"); + stream_c34.play().expect("Stream 3-4 play failed"); + + // CHANNELS 5-6 + let stream_c56 = device_c56.build_output_stream( + &StreamConfig{ + channels: 2, + sample_rate: SampleRate(OUTPUT_RATE as u32), + buffer_size: BufferSize::Fixed(WINDOW_SIZE as u32) + }, + move |data: &mut [i16], _: &cpal::OutputCallbackInfo| { + samples_c56.get_data(data); + }, + move |err| { + eprintln!("An error occurred on the output audio stream: {}", err); + }, + None + ).unwrap(); + println!(" * Starting stream"); + stream_c56.play().expect("Stream 5-6 play failed"); + + // CHANNELS 7-8 + let stream_c78 = device_c78.build_output_stream( &StreamConfig{ channels: 2, - sample_rate: SampleRate(file_rate), + sample_rate: SampleRate(OUTPUT_RATE as u32), buffer_size: BufferSize::Fixed(WINDOW_SIZE as u32) }, move |data: &mut [i16], _: &cpal::OutputCallbackInfo| { - samples.get_data(data); + samples_c78.get_data(data); }, move |err| { - eprintln!("an error occurred on the output audio stream: {}", err); + eprintln!("An error occurred on the output audio stream: {}", err); }, None ).unwrap(); - stream.play().expect("Stream play failed"); + println!(" * Starting stream"); + stream_c78.play().expect("Stream 7-8 play failed"); // begin looping though the samples until the buffer is full of complex audio with an imag element of 0 let mut i = 0; - for sample in reader.samples::() { + + let mut value_a: f32; + let mut value_b: f32; + let mut value_c: f32; + let mut now = SystemTime::now(); + + println!(" * Efficiency begins"); + println!(" * See you soon"); + + // EFFICIENCY BEGINS + + let mut imagenum = 0; + + loop { if i == SPECTOGRAM_AREA { // transform and do power scaling - forward_transform.process_with_scratch(&mut buffer, &mut scratch); - for x in buffer.iter_mut() { - *x *= 1f32 / WINDOW_SIZE as f32; - } - image_array.read_buffer(&buffer); + forward_transform.process_with_scratch(&mut buffer_a, &mut scratch); + buffer_a = buffer_a.par_iter_mut() + .map(|x| *x * (1f32 / WINDOW_SIZE as f32)) + .collect(); + image_array_a.read_buffer(&buffer_a); + + forward_transform.process_with_scratch(&mut buffer_b, &mut scratch); + buffer_b = buffer_b.par_iter_mut() + .map(|x| *x * (1f32 / WINDOW_SIZE as f32)) + .collect(); + image_array_b.read_buffer(&buffer_b); + + forward_transform.process_with_scratch(&mut buffer_c, &mut scratch); + buffer_c = buffer_c.par_iter_mut() + .map(|x| *x * (1f32 / WINDOW_SIZE as f32)) + .collect(); + image_array_c.read_buffer(&buffer_c); // show the image on screen - let image = ImageView::new(ImageInfo::rgb8(WINDOW_SIZE as u32, CHUNK_SIZE as u32), &image_array.data); - display_window.set_image ("image", image)?; + + arc_data_a = image_array_a.data.clone().try_into().unwrap(); + arc_image_a = ArcImage::new( + ImageInfo::rgb8(WINDOW_SIZE as u32, CHUNK_SIZE as u32), + Arc::new(arc_data_a) + ); + display_window_a.set_image("Display A", arc_image_a)?; + + arc_data_b = image_array_b.data.clone().try_into().unwrap(); + arc_image_b = ArcImage::new( + ImageInfo::rgb8(WINDOW_SIZE as u32, CHUNK_SIZE as u32), + Arc::new(arc_data_b) + ); + display_window_b.set_image("Display B", arc_image_b)?; + + arc_data_c = image_array_c.data.clone().try_into().unwrap(); + arc_image_c = ArcImage::new( + ImageInfo::rgb8(WINDOW_SIZE as u32, CHUNK_SIZE as u32), + Arc::new(arc_data_c) + ); + display_window_c.set_image("Display C", arc_image_c)?; // capture and transform camera view to image - image_array.read_camera(); + image_array_a.read_camera(); + image_array_b.read_camera(); + image_array_c.read_camera(); // make and display debug image - if DEBUG_MODE { - let debug_image = ImageView::new(ImageInfo::rgb8(WINDOW_SIZE as u32, CHUNK_SIZE as u32), &image_array.data); + if DEBUG { + let mut a_image = image_array_a.data.clone(); + let mut b_image = image_array_b.data.clone(); + let mut c_image = image_array_c.data.clone(); + + let a_slice: &mut [u8] = a_image.as_mut_slice(); + let b_slice: &mut [u8] = b_image.as_mut_slice(); + let c_slice: &mut [u8] = c_image.as_mut_slice(); + + let mut a_chunks = a_slice.chunks_mut(WINDOW_SIZE * 3); + let mut b_chunks = b_slice.chunks_mut(WINDOW_SIZE * 3); + let mut c_chunks = c_slice.chunks_mut(WINDOW_SIZE * 3); + + let mut image_data = vec![0u8;0]; + for _ in 0..CHUNK_SIZE { + let mut line = vec![0u8;0]; + + let a_line = a_chunks.next().unwrap(); + let b_line = b_chunks.next().unwrap(); + let c_line = c_chunks.next().unwrap(); + + line.extend_from_slice(a_line); + line.extend_from_slice(b_line); + line.extend_from_slice(c_line); + + + image_data.extend_from_slice(line.as_slice()); + } + + if false { + let save_image: ImageBuffer, Vec> = ImageBuffer::from_raw((WINDOW_SIZE * 4) as u32, CHUNK_SIZE as u32, image_data.clone()).unwrap(); + imagenum += 1; + save_image.save(format!("frames/frame-{:0>3}.png", imagenum)).unwrap(); + } + + let debug_image = ImageView::new(ImageInfo::rgb8((WINDOW_SIZE * 3) as u32, CHUNK_SIZE as u32), image_data.as_slice()); debug_window.set_image("Debug", debug_image)?; } // convert image to audio - image_array.write_buffer(&mut buffer); - inverse_transform.process_with_scratch(&mut buffer, &mut scratch); + image_array_a.write_buffer(&mut buffer_a); + image_array_b.write_buffer(&mut buffer_b); + image_array_c.write_buffer(&mut buffer_c); + inverse_transform.process_with_scratch(&mut buffer_a, &mut scratch); + inverse_transform.process_with_scratch(&mut buffer_b, &mut scratch); + inverse_transform.process_with_scratch(&mut buffer_c, &mut scratch); // when a "true" is receved by rx, get lock for sample buffer and fill the last half with the audio - if rx.recv().unwrap() { - let mut write_buffer = sample_buffer.lock().unwrap(); - for (i, x) in write_buffer[SPECTOGRAM_AREA..].iter_mut().enumerate() { - let value = main_lowpass.run(buffer[i].re / i16::MAX as f32); - *x = (value * i16::MAX) as i16; - } + if DEBUG { now = SystemTime::now(); } + + let _ = resampler.resample(&buffer_a.iter().rev().map(|x| x.re).collect::>(), &mut out_samples_a).unwrap(); + let _ = resampler.resample(&buffer_b.iter().rev().map(|x| x.re).collect::>(), &mut out_samples_b).unwrap(); + let _ = resampler.resample(&buffer_c.iter().rev().map(|x| x.re).collect::>(), &mut out_samples_c).unwrap(); + + + // CHANNELS 1-2 + if rx_c12.recv().unwrap() { + if DEBUG { println!("{:?}", now.elapsed().unwrap()); } + sample_buffer_c1.lock().unwrap()[SPECTOGRAM_AREA..] + .par_iter_mut() + .enumerate() + .for_each(|(i, x)| { + *x = ((out_samples_a[i] * AUDIO_A_C1) + (out_samples_b[i] * AUDIO_B_C1) + (out_samples_b[i] * AUDIO_C_C1)) as i16; + }); + sample_buffer_c2.lock().unwrap()[SPECTOGRAM_AREA..] + .par_iter_mut() + .enumerate() + .for_each(|(i, x)| { + *x = ((out_samples_a[i] * AUDIO_A_C2) + (out_samples_b[i] * AUDIO_B_C2) + (out_samples_b[i] * AUDIO_C_C2)) as i16; + }); + } + + // CHANNELS 3-4 + if rx_c34.recv().unwrap() { + sample_buffer_c3.lock().unwrap()[SPECTOGRAM_AREA..] + .par_iter_mut() + .enumerate() + .for_each(|(i, x)| { + *x = ((out_samples_a[i] * AUDIO_A_C3) + (out_samples_b[i] * AUDIO_B_C3) + (out_samples_b[i] * AUDIO_C_C3)) as i16; + }); + sample_buffer_c4.lock().unwrap()[SPECTOGRAM_AREA..] + .par_iter_mut() + .enumerate() + .for_each(|(i, x)| { + *x = ((out_samples_a[i] * AUDIO_A_C4) + (out_samples_b[i] * AUDIO_B_C4) + (out_samples_b[i] * AUDIO_C_C4)) as i16; + }); + } + + // CHANNELS 5-6 + if rx_c56.recv().unwrap() { + sample_buffer_c5.lock().unwrap()[SPECTOGRAM_AREA..] + .par_iter_mut() + .enumerate() + .for_each(|(i, x)| { + *x = ((out_samples_a[i] * AUDIO_A_C5) + (out_samples_b[i] * AUDIO_B_C5) + (out_samples_b[i] * AUDIO_C_C5)) as i16; + }); + sample_buffer_c6.lock().unwrap()[SPECTOGRAM_AREA..] + .par_iter_mut() + .enumerate() + .for_each(|(i, x)| { + *x = ((out_samples_a[i] * AUDIO_A_C6) + (out_samples_b[i] * AUDIO_B_C6) + (out_samples_b[i] * AUDIO_C_C6)) as i16; + }); + } + + // CHANNELS 7-8 + if rx_c78.recv().unwrap() { + sample_buffer_c7.lock().unwrap()[SPECTOGRAM_AREA..] + .par_iter_mut() + .enumerate() + .for_each(|(i, x)| { + *x = ((out_samples_a[i] * AUDIO_A_C7) + (out_samples_b[i] * AUDIO_B_C7) + (out_samples_b[i] * AUDIO_C_C7)) as i16; + }); + sample_buffer_c8.lock().unwrap()[SPECTOGRAM_AREA..] + .par_iter_mut() + .enumerate() + .for_each(|(i, x)| { + *x = ((out_samples_a[i] * AUDIO_A_C8) + (out_samples_b[i] * AUDIO_B_C8) + (out_samples_b[i] * AUDIO_C_C8)) as i16; + }); } i = 0; } + // if buffer is not full convert value and add to buffer - let mut value = sample.unwrap_or_default() as f32; - let feedback_value = feedback_lowpass.run(buffer[i].re / i16::MAX as f32); - value = (value * DRY) + (feedback_value * i16::MAX * WET); + value_a = (infinite_a.next().unwrap() as f32 * DRY) + (buffer_a[i].re * WET); + value_b = (infinite_b.next().unwrap() as f32 * DRY) + (buffer_b[i].re * WET); + value_c = (infinite_c.next().unwrap() as f32 * DRY) + (buffer_c[i].re * WET); + + buffer_a[i] = Complex{re: value_a, im: 0f32}; + buffer_b[i] = Complex{re: value_b, im: 0f32}; + buffer_c[i] = Complex{re: value_c, im: 0f32}; - buffer[i] = Complex{re: value, im: 0f32}; i += 1; } - - Ok(()) - } diff --git a/src/process.cpp b/src/process.cpp index 229981c..b72a65b 100644 --- a/src/process.cpp +++ b/src/process.cpp @@ -1,10 +1,13 @@ -#include "barrel.cpp" #include "homography.cpp" +#include "barrel.cpp" + +#ifdef USE_LUT #include "color.cpp" +#endif extern "C" { - void ProcessCapture(uint8_t *camera_ptr, uint8_t *buffer_ptr, double *homography_ptr, uint8_t *lut_ptr) + void ProcessCapture(uint8_t *camera_ptr, uint8_t *buffer_ptr, double *homography_ptr, uint8_t *lut_ptr, float* xmat_ptr, float* ymat_ptr) { /* * Heres the plan: @@ -22,6 +25,7 @@ extern "C" * even thinking about it in the rust. */ + //ApplyUndistort(camera_ptr, xmat_ptr, ymat_ptr); ApplyHomography(camera_ptr, buffer_ptr, homography_ptr); #ifdef USE_LUT ApplyCorrection(buffer_ptr, lut_ptr); @@ -29,8 +33,9 @@ extern "C" } // get homography function (see "homography.cpp") - void GetHomography(uint8_t *camera_ptr, double *homography_ptr) + void GetHomography(uint8_t *camera_ptr, double *homography_ptr, float* xmat_ptr, float* ymat_ptr) { + //ApplyUndistort(camera_ptr, xmat_ptr, ymat_ptr); FuncGetHomography(camera_ptr, homography_ptr); } } diff --git a/src/sample_buffer.rs b/src/sample_buffer.rs index d808f82..ae2d28b 100644 --- a/src/sample_buffer.rs +++ b/src/sample_buffer.rs @@ -4,32 +4,38 @@ use std::sync::{Arc, Mutex}; use crate::SPECTOGRAM_AREA; pub struct SampleBuffer { - buffer: Arc>, + right_buffer: Arc>, + left_buffer: Arc>, index: usize, tx: Sender } impl SampleBuffer { - pub fn new(buffer: Arc>, tx: Sender) -> Self { + pub fn new(right_buffer: Arc>, left_buffer: Arc>, tx: Sender) -> Self { + Self { - buffer, + right_buffer, + left_buffer, index: 0, tx } } pub fn get_data(&mut self, data: &mut [i16]) { - let mut buffer = self.buffer.lock().unwrap(); + let mut right_buffer = self.right_buffer.lock().unwrap(); + let mut left_buffer = self.left_buffer.lock().unwrap(); let length = data.len()/2; for i in 0..length { - data[i*2] = buffer[i + self.index]; + data[i*2] = right_buffer[i + self.index]; + data[i*2+1] = left_buffer[i + self.index]; } self.index += length; if self.index > SPECTOGRAM_AREA { for i in 0..SPECTOGRAM_AREA { - buffer[i] = buffer[i + SPECTOGRAM_AREA]; + right_buffer[i] = right_buffer[i + SPECTOGRAM_AREA]; + left_buffer[i] = left_buffer[i + SPECTOGRAM_AREA]; } self.index -= SPECTOGRAM_AREA; diff --git a/src/style_utils.rs b/src/style_utils.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/utils.rs b/src/utils.rs new file mode 100644 index 0000000..e69de29 diff --git a/todo b/todo index 52b5a35..39b9139 100644 --- a/todo +++ b/todo @@ -1,25 +1,19 @@ todo: - test the lut system in-situ, graph for optimal -- possibly see if a version can be made that takes mic input -- implement recording for testing - implement image display in unused channel - +- get temp guest list together +- ask R about headcounts and other event things - write cpp code for using cuFFT (not supported by rust-cuda) -- potentially write rust-cuda kernel for the color conversion +- add 3 to 2 reverse functions +- implement the video frame reader +- speed the whole thing up QUICKLY: -- make functional with windows - - some things that might not be windows compatible: - - show-image (YES but might need to mess with the backend) - - hound for reading the wav files (YES) - - cpal for the audio out (YES look into asio extra feature for lower latency) - - rscam for the camera (NO drop in for nokhwa) (IMPLEMENTED) - - the file paths (IMPLEMENTED) - evaluate if cuda is neccicary LIBRARIES: - FFTW (https://www.fftw.org/fftw3_doc/) for the c++ -- nokhwa (IMPLEMENTED) +- vid2img (https://github.com/rafaelcaricio/vid2img) - fon - rayon @@ -36,5 +30,31 @@ CAPTURE ISSUES: - reinstate the read loop AUDIO ISSUES: -- disable the feedback mix code -- disable the filtering code +- implement filtering + +CLICKING: +- check if messing with the itterators is possibly causing some kind of jump + +WARP ISSUES: +- surf.setExtended(True) // set surf to 128 keypoints if its only 64 right now + + + + + + // some code to turn the yuyv into rgb if we need it! + // let stride = (IMAGE_WIDTH * 3) as u32; + // let vuvy = YuvPackedImage{ + // yuy: frame.buffer(), + // yuy_stride: stride, + // width: IMAGE_WIDTH as u32, + // height: IMAGE_HEIGHT as u32 + // }; + // let mut rgb = [0u8; IMAGE_AREA]; + // yuyv422_to_rgb( + // &vuvy, + // &mut rgb, + // stride, + // YuvRange::Full, + // YuvStandardMatrix::Bt601 + // ).unwrap();W \ No newline at end of file