Compare commits
17
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2bf07d0fba | ||
|
|
e661022329 | ||
|
|
f4650ece00 | ||
|
|
01cc0feda2 | ||
|
|
234dcd08d0 | ||
|
|
9b05d32f27 | ||
|
|
5c79deec56 | ||
|
|
b8e3d870cb | ||
|
|
3ccc563c3d | ||
|
|
3cf7c279a8 | ||
|
|
a98be2f8e3 | ||
|
|
af2e7dc602 | ||
|
|
e2fee36cdb | ||
|
|
27821c1866 | ||
|
|
3d94df0b7a | ||
|
|
f6b6beda5e | ||
|
|
a9a49bef89 |
Generated
+765
-7
@@ -2,6 +2,176 @@
|
|||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 4
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "android_system_properties"
|
||||||
|
version = "0.1.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ae221649c9976a6f6c56ae1facf410f3ddb33cc661c4b7b61020a912d4237fbc"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "1.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "base64"
|
||||||
|
version = "0.23.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ac07cdecf99051d9a5238b80f35af32cdeba5b336e55d957b318b50137e18da5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "1.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bs58"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4"
|
||||||
|
dependencies = [
|
||||||
|
"tinyvec",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bumpalo"
|
||||||
|
version = "3.20.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cc"
|
||||||
|
version = "1.4.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "005ec2760ca554fae18df7a11195552ec576cd665632a881bc011d5bb2fd4d80"
|
||||||
|
dependencies = [
|
||||||
|
"find-msvc-tools",
|
||||||
|
"shlex",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "1.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "chacha20"
|
||||||
|
version = "0.10.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "65c35e4b699c7e15ccbe7ee35c005e4fc0a278d22238a2857e6ce2dadeda1b06"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cpufeatures",
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "chrono"
|
||||||
|
version = "0.4.45"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327"
|
||||||
|
dependencies = [
|
||||||
|
"iana-time-zone",
|
||||||
|
"num-traits",
|
||||||
|
"serde",
|
||||||
|
"windows-link",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "core-foundation-sys"
|
||||||
|
version = "0.8.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cpufeatures"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5ca28b0ae3115b884660db4118d803791fd6756b6e88f39c0f3f7859060d7566"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "darling"
|
||||||
|
version = "0.24.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ed17f5901b6630b993ca003def43f2f8ef4014fc13b047b57aad617ff32bc2ec"
|
||||||
|
dependencies = [
|
||||||
|
"darling_core",
|
||||||
|
"darling_macro",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "darling_core"
|
||||||
|
version = "0.24.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6837e2cf7485aaae18f86181d2f0e9a7ed297a025e220aeabf63fdebd3a2ddff"
|
||||||
|
dependencies = [
|
||||||
|
"ident_case",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"strsim",
|
||||||
|
"syn 3.0.6",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "darling_macro"
|
||||||
|
version = "0.24.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2ac7135c3ef02b2f7833bbeb1be5ba7f966dcde8a87c6b87f65a778d71a02785"
|
||||||
|
dependencies = [
|
||||||
|
"darling_core",
|
||||||
|
"quote",
|
||||||
|
"syn 3.0.6",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "defmt"
|
||||||
|
version = "1.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e2953bfe4f93bbd20cc71198842756f77d161884c99ebbabc41d80231ded88d1"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"defmt-macros",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "defmt-macros"
|
||||||
|
version = "1.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bad9c72e7ca2137e0dc3813245a0d282fd6daad32fd800af018306a9169b5fe8"
|
||||||
|
dependencies = [
|
||||||
|
"defmt-parser",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.119",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "defmt-parser"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "10d60334b3b2e7c9d91ef8150abfb6fa4c1c39ebbcf4a81c2e346aad939fee3e"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "deranged"
|
||||||
|
version = "0.5.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c"
|
||||||
|
dependencies = [
|
||||||
|
"serde_core",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dotenvy"
|
name = "dotenvy"
|
||||||
version = "0.15.7"
|
version = "0.15.7"
|
||||||
@@ -13,17 +183,283 @@ name = "dsp_thomann"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dotenvy",
|
"dotenvy",
|
||||||
|
"rand",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"serde_with",
|
||||||
"strum",
|
"strum",
|
||||||
"strum_macros",
|
"strum_macros",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dyn-clone"
|
||||||
|
version = "1.0.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "equivalent"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "find-msvc-tools"
|
||||||
|
version = "0.1.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3e0f1c7c3a72c66fd80abe965175f7523475c0489a87d3ff9d6e8c87d87a9d2d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-core"
|
||||||
|
version = "0.3.34"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-task"
|
||||||
|
version = "0.3.34"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cd417de3d1d015fc3bfd2b1ea46dfc7bab72ef86f1cc7cc9c78e728b34a6d1fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-util"
|
||||||
|
version = "0.3.34"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc"
|
||||||
|
dependencies = [
|
||||||
|
"futures-core",
|
||||||
|
"futures-task",
|
||||||
|
"pin-project-lite",
|
||||||
|
"slab",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getrandom"
|
||||||
|
version = "0.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"r-efi",
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.12.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.17.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "heck"
|
name = "heck"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hex"
|
||||||
|
version = "0.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "iana-time-zone"
|
||||||
|
version = "0.1.65"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470"
|
||||||
|
dependencies = [
|
||||||
|
"android_system_properties",
|
||||||
|
"core-foundation-sys",
|
||||||
|
"iana-time-zone-haiku",
|
||||||
|
"js-sys",
|
||||||
|
"log",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"windows-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "iana-time-zone-haiku"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ident_case"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "indexmap"
|
||||||
|
version = "1.9.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"hashbrown 0.12.3",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "indexmap"
|
||||||
|
version = "2.14.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cc4e190f5d26ca7051642629da2c52fc03bde85a03197c99408dcd291734c855"
|
||||||
|
dependencies = [
|
||||||
|
"equivalent",
|
||||||
|
"hashbrown 0.17.1",
|
||||||
|
"serde",
|
||||||
|
"serde_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itoa"
|
||||||
|
version = "1.0.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jiff"
|
||||||
|
version = "0.2.37"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0ab1baf72f08796de0260609515130699b890ac25f30e610ad894bc5856cafdb"
|
||||||
|
dependencies = [
|
||||||
|
"defmt",
|
||||||
|
"jiff-core",
|
||||||
|
"jiff-static",
|
||||||
|
"jiff-tzdb-platform",
|
||||||
|
"log",
|
||||||
|
"portable-atomic",
|
||||||
|
"portable-atomic-util",
|
||||||
|
"serde_core",
|
||||||
|
"windows-link",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jiff-core"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5e52fe76043ccecc9005d2305ebaadf7d7fc0cc89ca6baa10a94d6bc68c7128c"
|
||||||
|
dependencies = [
|
||||||
|
"defmt",
|
||||||
|
"log",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jiff-static"
|
||||||
|
version = "0.2.37"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "378268a1116ad67ae6228701118ac9f491d78fda38a40a1f1a9e1348de6f7212"
|
||||||
|
dependencies = [
|
||||||
|
"jiff-core",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.119",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jiff-tzdb"
|
||||||
|
version = "0.1.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "142bd39932ad231f10513df9ab62661fead8719872150b7ad02a2df79f4e141e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jiff-tzdb-platform"
|
||||||
|
version = "0.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "875a5a69ac2bab1a891711cf5eccbec1ce0341ea805560dcd90b7a2e925132e8"
|
||||||
|
dependencies = [
|
||||||
|
"jiff-tzdb",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "js-sys"
|
||||||
|
version = "0.3.105"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ce57d20d1ea864ce2ac172ab472d409214f4fd359f0b2a2775abdf522e2af99e"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"futures-util",
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.189"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "log"
|
||||||
|
version = "0.4.34"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.8.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-conv"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-traits"
|
||||||
|
version = "0.2.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "once_cell"
|
||||||
|
version = "1.21.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pin-project-lite"
|
||||||
|
version = "0.2.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "portable-atomic"
|
||||||
|
version = "1.15.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "05c8b63e8d9609db387f0324918f81d68fe27748f084ef092fb35954d0539a85"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "portable-atomic-util"
|
||||||
|
version = "0.2.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "10ab3eb7f3becc3a1cbc4f2c6f20267996cfc1a6467a873763411b136a122715"
|
||||||
|
dependencies = [
|
||||||
|
"portable-atomic",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "powerfmt"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.106"
|
version = "1.0.106"
|
||||||
@@ -42,6 +478,173 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "r-efi"
|
||||||
|
version = "6.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand"
|
||||||
|
version = "0.10.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "65c9fb96cbc91e3478eaae79a69fcd3f1ae4ad052e471fe6732fff548984b4af"
|
||||||
|
dependencies = [
|
||||||
|
"chacha20",
|
||||||
|
"getrandom",
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ref-cast"
|
||||||
|
version = "1.0.27"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7e440fb4e4b4147295338efb76001ab9e4efc0e5839df2c47fc5ac2381d365c3"
|
||||||
|
dependencies = [
|
||||||
|
"ref-cast-impl",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ref-cast-impl"
|
||||||
|
version = "1.0.27"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "92ecd8964f8453721699a1ed72037b0db49ce2f5a5138486ee89bed6f67cdf3a"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 3.0.6",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustversion"
|
||||||
|
version = "1.0.23"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "schemars"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f"
|
||||||
|
dependencies = [
|
||||||
|
"dyn-clone",
|
||||||
|
"ref-cast",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "schemars"
|
||||||
|
version = "1.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "687274d293b6cdc6e73e0fee520bf2049650090d7164f87672d212a3c530cf4a"
|
||||||
|
dependencies = [
|
||||||
|
"dyn-clone",
|
||||||
|
"ref-cast",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde"
|
||||||
|
version = "1.0.229"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba"
|
||||||
|
dependencies = [
|
||||||
|
"serde_core",
|
||||||
|
"serde_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_core"
|
||||||
|
version = "1.0.229"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48"
|
||||||
|
dependencies = [
|
||||||
|
"serde_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_derive"
|
||||||
|
version = "1.0.229"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 3.0.6",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_json"
|
||||||
|
version = "1.0.151"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14"
|
||||||
|
dependencies = [
|
||||||
|
"itoa",
|
||||||
|
"memchr",
|
||||||
|
"serde",
|
||||||
|
"serde_core",
|
||||||
|
"zmij",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_with"
|
||||||
|
version = "3.24.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "df9adc193c780ef8f159aee8b61e2d5801aaa555e6eb0947fe45530ec506296f"
|
||||||
|
dependencies = [
|
||||||
|
"base64",
|
||||||
|
"bs58",
|
||||||
|
"chrono",
|
||||||
|
"hex",
|
||||||
|
"indexmap 1.9.3",
|
||||||
|
"indexmap 2.14.2",
|
||||||
|
"jiff",
|
||||||
|
"schemars 0.9.0",
|
||||||
|
"schemars 1.2.2",
|
||||||
|
"serde_core",
|
||||||
|
"serde_json",
|
||||||
|
"serde_with_macros",
|
||||||
|
"time",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_with_macros"
|
||||||
|
version = "3.24.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3e17bbc68e28663bbbb90df47e058aa7eda4fb445b89fe70457bb94fbccf6e49"
|
||||||
|
dependencies = [
|
||||||
|
"darling",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 3.0.6",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "shlex"
|
||||||
|
version = "2.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "slab"
|
||||||
|
version = "0.4.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strsim"
|
||||||
|
version = "0.11.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strum"
|
name = "strum"
|
||||||
version = "0.28.0"
|
version = "0.28.0"
|
||||||
@@ -73,9 +676,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "3.0.2"
|
version = "3.0.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a207d6d6a2b7fc470b80443726053f18a2481b7e1eee970597051596567987a3"
|
checksum = "8593e8e72159ed2257d083c7a454a85cbf854f37a0966d8d483aff8c8a3ebcee"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -84,26 +687,181 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "2.0.19"
|
version = "2.0.21"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "09a43598840e33d5b0331f38c5e30d13bb11c11210a4b58f0d9b18a5a5eefcd9"
|
checksum = "09e52cb86a36cede5cb101bf8908837b3e4c6e5e59fe7fd85c23fb56200d189e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"thiserror-impl",
|
"thiserror-impl",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror-impl"
|
name = "thiserror-impl"
|
||||||
version = "2.0.19"
|
version = "2.0.21"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "43cbfe0cf76104d42a574802844187e84a305e531ed54455f11fbde0f10541cd"
|
checksum = "fe5197923287db20a58125f0bc85c062f7f2c892de97b18c356f9efb14b28524"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 3.0.2",
|
"syn 3.0.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "time"
|
||||||
|
version = "0.3.55"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cdb87b95ec50ddfa440816d227a17b2ccbdda963a316a727fda0fc4334f7d134"
|
||||||
|
dependencies = [
|
||||||
|
"deranged",
|
||||||
|
"num-conv",
|
||||||
|
"powerfmt",
|
||||||
|
"serde_core",
|
||||||
|
"time-core",
|
||||||
|
"time-macros",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "time-core"
|
||||||
|
version = "0.1.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "time-macros"
|
||||||
|
version = "0.2.32"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7e689342a48d2ea927c87ea50cabf8594854bf940e9310208848d680d668ed85"
|
||||||
|
dependencies = [
|
||||||
|
"num-conv",
|
||||||
|
"time-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tinyvec"
|
||||||
|
version = "1.13.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4cf0ded5c4e56918d8f8a339e1bb67d038d3bc6d144ac407904015ba2e4cde9b"
|
||||||
|
dependencies = [
|
||||||
|
"tinyvec_macros",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tinyvec_macros"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.24"
|
version = "1.0.24"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen"
|
||||||
|
version = "0.2.128"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "aecb87a33d3b0c5e3b7aa46336eaf486cffafbd281b195e4c8b80d50df2351bf"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"once_cell",
|
||||||
|
"rustversion",
|
||||||
|
"wasm-bindgen-macro",
|
||||||
|
"wasm-bindgen-shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-macro"
|
||||||
|
version = "0.2.128"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a690d511e3c1a8b3a55e33511e3c2c00c78415cd23650f32b808627f5696b9ed"
|
||||||
|
dependencies = [
|
||||||
|
"quote",
|
||||||
|
"wasm-bindgen-macro-support",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-macro-support"
|
||||||
|
version = "0.2.128"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "411e4887f0071ef2d2164a9d5fdf2d20efbef78fccd3a78b0c10a1dc5295e48a"
|
||||||
|
dependencies = [
|
||||||
|
"bumpalo",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 3.0.6",
|
||||||
|
"wasm-bindgen-shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-shared"
|
||||||
|
version = "0.2.128"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "81941cd78d0c92026c33e5e01312845a4cb1e9af3407f9134b100dd03144103e"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[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",
|
||||||
|
"windows-strings",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[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.119",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[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.119",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-link"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||||
|
|
||||||
|
[[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 = "zmij"
|
||||||
|
version = "1.0.23"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b"
|
||||||
|
|||||||
+7
-1
@@ -7,9 +7,13 @@ edition = "2024"
|
|||||||
dotenvy = "0.15"
|
dotenvy = "0.15"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
thiserror = "2.0.19"
|
thiserror = "2.0.21"
|
||||||
strum = "0.28.0"
|
strum = "0.28.0"
|
||||||
strum_macros = "0.28.0"
|
strum_macros = "0.28.0"
|
||||||
|
serde = { version = "1", features = ["derive"], optional = true }
|
||||||
|
serde_json = { version = "1", optional = true }
|
||||||
|
serde_with = "3.24.0"
|
||||||
|
rand = "0.10.3"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "dsp_thomann"
|
name = "dsp_thomann"
|
||||||
@@ -17,3 +21,5 @@ path = "src/lib.rs"
|
|||||||
|
|
||||||
[features]
|
[features]
|
||||||
hardware-tests = []
|
hardware-tests = []
|
||||||
|
default = []
|
||||||
|
serialization = ["dep:serde", "dep:serde_json"]
|
||||||
|
|||||||
+68
-13
@@ -617,26 +617,81 @@ delay = delay_min + (raw / 255) × (delay_max - delay_min)
|
|||||||
|
|
||||||
| Field | Value |
|
| Field | Value |
|
||||||
|---|---|
|
|---|---|
|
||||||
| **Purpose** | Per-channel level + peak metering |
|
| **Purpose** | Per-channel RMS + peak metering, with clip flags |
|
||||||
| **Size** | 3 bytes per channel |
|
| **Payload size** | 38 bytes (exactly; any other length is an error) |
|
||||||
| **Total** | 12 channels × 3 bytes = 36 bytes |
|
| **Layout** | 12 channels × 3 bytes = 36 bytes, followed by 2 clip-flag bytes |
|
||||||
|
| **Channel order** | Channels 0–3 are inputs, channels 4–11 are outputs, each mapped in enum order |
|
||||||
|
|
||||||
|
#### Channel record (3 bytes, at offset `i = channel × 3`)
|
||||||
|
|
||||||
| Byte offset | Field | Format |
|
| Byte offset | Field | Format |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| 0–1 | Level | IEEE754 float16, little-endian |
|
| `i + 0` | RMS low byte | Low byte of the RMS float16 |
|
||||||
| 2 | Peak | 1-byte peak value (format not specified in source) |
|
| `i + 1` | Shared high byte | High byte of **both** the RMS and Peak float16s |
|
||||||
|
| `i + 2` | Peak low byte | Low byte of the Peak float16 |
|
||||||
|
|
||||||
|
Both values are IEEE 754 half-precision floats (little-endian pairs). The peak is not a separate 1-byte value: it reuses byte `i + 1` as its high byte, so its byte order is reversed relative to the offset order.
|
||||||
|
|
||||||
**Encoding (value → raw):**
|
|
||||||
```text
|
```text
|
||||||
level_bytes = float16_encode(level) // 2 bytes, little-endian
|
rms_raw = float16_decode(lo = payload[i], hi = payload[i + 1])
|
||||||
peak_byte = peak_encode(peak) // format undefined — see note below
|
peak_raw = float16_decode(lo = payload[i + 2], hi = payload[i + 1])
|
||||||
raw = level_bytes + peak_byte
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**Decoding (raw → value):**
|
If a float16 fails to decode, the raw value defaults to `0.0`, which converts to `MIN_DB` (-60 dB).
|
||||||
|
|
||||||
|
#### Clip flags (bytes 36–37)
|
||||||
|
|
||||||
|
| Channel index | Flag location |
|
||||||
|
|---|---|
|
||||||
|
| 0–3 | `payload[36]`, bit `index` |
|
||||||
|
| 4–11 | `payload[37]`, bit `index - 4` |
|
||||||
|
|
||||||
```text
|
```text
|
||||||
level = float16_decode(raw[0:2]) // little-endian
|
clip = (flags_byte & (1 << bit)) != 0
|
||||||
peak = peak_decode(raw[2]) // format undefined — see note below
|
```
|
||||||
|
|
||||||
|
#### Raw → dB conversion
|
||||||
|
|
||||||
|
Raw values are converted with a piecewise-linear curve, then clamped.
|
||||||
|
|
||||||
|
| Constant | Value | Meaning |
|
||||||
|
|---|---|---|
|
||||||
|
| `X0` | -25.0 dB | Breakpoint |
|
||||||
|
| `Y0` | 1.0 | Raw value at the breakpoint |
|
||||||
|
| `K1` | 0.0104 | Raw units per dB below the breakpoint (`raw < Y0`) |
|
||||||
|
| `K2` | 0.0208 | Raw units per dB above the breakpoint (`raw >= Y0`) |
|
||||||
|
| `MIN_DB` | -60.0 dB | Lower clamp |
|
||||||
|
| `MAX_DB` | 12.0 dB | Upper clamp |
|
||||||
|
|
||||||
|
**Decoding (raw → dB):**
|
||||||
|
```text
|
||||||
|
if raw < Y0: db = X0 + (raw - Y0) / K1
|
||||||
|
else: db = X0 + (raw - Y0) / K2
|
||||||
|
db = clamp(db, MIN_DB, MAX_DB)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Encoding (dB → raw):** the inverse of the above. Values outside the clamp range are not recoverable.
|
||||||
|
```text
|
||||||
|
db = clamp(db, MIN_DB, MAX_DB)
|
||||||
|
if db < X0: raw = Y0 + (db - X0) * K1
|
||||||
|
else: raw = Y0 + (db - X0) * K2
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Full decode
|
||||||
|
|
||||||
|
```text
|
||||||
|
require len(payload) == 38
|
||||||
|
|
||||||
|
for index in 0..11:
|
||||||
|
i = index * 3
|
||||||
|
rms_db = raw_to_db(float16_decode(payload[i], payload[i + 1]))
|
||||||
|
peak_db = raw_to_db(float16_decode(payload[i + 2], payload[i + 1]))
|
||||||
|
clip = index < 4 ? payload[36] bit index
|
||||||
|
: payload[37] bit (index - 4)
|
||||||
|
meter[index] = { rms: rms_db, peak: peak_db, clip }
|
||||||
|
|
||||||
|
inputs = meter[0..3] → InputChannel enum order
|
||||||
|
outputs = meter[4..11] → OutputChannel enum order
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -1868,7 +1923,7 @@ Sine Wave:
|
|||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
| `Byte 1-36` | 12 meter channels | 3 bytes × 12 | [Enc §8.1 Meter Level](#81-meter-level) |
|
| `Byte 1-36` | 12 meter channels | 3 bytes × 12 | [Enc §8.1 Meter Level](#81-meter-level) |
|
||||||
| `Byte 37` | Input clip indicator | 1 byte bitmask | Same OR bitmask pattern as [Enc §4.1](#41-matrix-input-mask) |
|
| `Byte 37` | Input clip indicator | 1 byte bitmask | Same OR bitmask pattern as [Enc §4.1](#41-matrix-input-mask) |
|
||||||
| `Byte 38` | Output clip indicator | 1 byte bitmask | Same OR bitmask pattern as [Enc §4.1](#41-matrix-input-mask) |
|
| `Byte 38` | Output limit indicator | 1 byte bitmask | Same OR bitmask pattern as [Enc §4.1](#41-matrix-input-mask) |
|
||||||
|
|
||||||
**Example — Query**
|
**Example — Query**
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,8 @@
|
|||||||
- Figure out Meter level encoding
|
- Figure out Meter level encoding
|
||||||
- Full test of client (Improve existing one)
|
- Full test of client (Improve existing one)
|
||||||
- Write correct readme.md
|
- Write correct readme.md
|
||||||
|
- Make client dsp408 thread safe
|
||||||
|
- Absolutely, send command to avoid tcp keep alive, that make the dsp crash
|
||||||
|
|
||||||
Rust library for remote LAN control of Thomann DSP408 digital signal processors.
|
Rust library for remote LAN control of Thomann DSP408 digital signal processors.
|
||||||
|
|
||||||
|
|||||||
@@ -122,6 +122,12 @@ pub enum DSPError {
|
|||||||
#[error("operation failed: {0}")]
|
#[error("operation failed: {0}")]
|
||||||
OperationFailed(String),
|
OperationFailed(String),
|
||||||
|
|
||||||
|
#[error("internal error: {0}")]
|
||||||
|
InternalError(String),
|
||||||
|
|
||||||
|
#[error("mutex poisoned: {0}")]
|
||||||
|
MutexPoisoned(String),
|
||||||
|
|
||||||
#[error("I/O error: {0}")]
|
#[error("I/O error: {0}")]
|
||||||
Io(#[from] std::io::Error),
|
Io(#[from] std::io::Error),
|
||||||
|
|
||||||
@@ -134,3 +140,9 @@ pub enum DSPError {
|
|||||||
#[error("frame error: {0}")]
|
#[error("frame error: {0}")]
|
||||||
Frame(#[from] FrameError),
|
Frame(#[from] FrameError),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> From<std::sync::PoisonError<T>> for DSPError {
|
||||||
|
fn from(err: std::sync::PoisonError<T>) -> Self {
|
||||||
|
DSPError::MutexPoisoned(err.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,333 @@
|
|||||||
|
use rand::RngExt;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
|
use crate::dsp408::types::ConnectionStatus;
|
||||||
|
use crate::dsp408::types::{
|
||||||
|
Compressor, Crossover, CrossoverFilter, CrossoverFilters, DSPConfigState, DSPState, DelayUnit,
|
||||||
|
DeviceFlags, DiscreteFrequency, Gate, GraphicEQ, InputChannel, InputChannelState, InputMeters,
|
||||||
|
InputSource, InputType, Limiter, MatrixRoutes, Meter, OutputChannel, OutputChannelState,
|
||||||
|
OutputMeters, PEQ, PEQBand, PEQChain, PEQFilter, PresetBank, Ratio,
|
||||||
|
};
|
||||||
|
|
||||||
|
const FREQUENCY_MIN: f32 = 19.7;
|
||||||
|
const FREQUENCY_MAX: f32 = 20160.0;
|
||||||
|
|
||||||
|
const PRESET_COUNT: usize = 20;
|
||||||
|
|
||||||
|
pub fn default_dsp_state() -> DSPState {
|
||||||
|
DSPState {
|
||||||
|
name: "Default".to_string(),
|
||||||
|
|
||||||
|
flags: DeviceFlags { is_locked: true },
|
||||||
|
|
||||||
|
presets: default_preset_bank(),
|
||||||
|
|
||||||
|
current_config: default_config(),
|
||||||
|
|
||||||
|
connection: ConnectionStatus::Disconnected,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn default_input_meters() -> InputMeters {
|
||||||
|
InputMeters {
|
||||||
|
meters: InputChannel::iter().map(|c| (c, default_meter())).collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn default_output_meters() -> OutputMeters {
|
||||||
|
OutputMeters {
|
||||||
|
meters: OutputChannel::iter()
|
||||||
|
.map(|c| (c, default_meter()))
|
||||||
|
.collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// Presets
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
fn default_preset_bank() -> PresetBank {
|
||||||
|
PresetBank {
|
||||||
|
current_index: 0,
|
||||||
|
names: vec!["Default".to_string(); PRESET_COUNT],
|
||||||
|
modified: vec![false; PRESET_COUNT],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// DSP config
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
fn default_config() -> DSPConfigState {
|
||||||
|
DSPConfigState {
|
||||||
|
input_source: InputSource {
|
||||||
|
r#type: InputType::Analog,
|
||||||
|
frequency: DiscreteFrequency::F20000,
|
||||||
|
},
|
||||||
|
|
||||||
|
delay_unit: DelayUnit::Millisecond,
|
||||||
|
|
||||||
|
input_states: default_input_states(),
|
||||||
|
output_states: default_output_states(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// Input channels
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
fn default_input_states() -> HashMap<InputChannel, InputChannelState> {
|
||||||
|
[
|
||||||
|
(
|
||||||
|
InputChannel::InA,
|
||||||
|
default_input_channel_state("In A", false),
|
||||||
|
),
|
||||||
|
(InputChannel::InB, default_input_channel_state("In B", true)),
|
||||||
|
(
|
||||||
|
InputChannel::InC,
|
||||||
|
default_input_channel_state("In C", false),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
InputChannel::InD,
|
||||||
|
default_input_channel_state("In D", false),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
.into_iter()
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_input_channel_state(name: &str, a: bool) -> InputChannelState {
|
||||||
|
if a {
|
||||||
|
return InputChannelState {
|
||||||
|
name: name.to_string(),
|
||||||
|
|
||||||
|
gain: 0.0,
|
||||||
|
phase_inverted: false,
|
||||||
|
delay: 0.0,
|
||||||
|
|
||||||
|
gate: default_gate(),
|
||||||
|
geq: default_graphic_eq(),
|
||||||
|
peq_chain: default_peq_chain(),
|
||||||
|
crossover: default_crossover_filters(),
|
||||||
|
|
||||||
|
linked_channels: vec![InputChannel::InA],
|
||||||
|
// linked_channels: Vec::new(),
|
||||||
|
mute: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
InputChannelState {
|
||||||
|
name: name.to_string(),
|
||||||
|
|
||||||
|
gain: 0.0,
|
||||||
|
phase_inverted: false,
|
||||||
|
delay: 0.0,
|
||||||
|
|
||||||
|
gate: default_gate(),
|
||||||
|
geq: default_graphic_eq(),
|
||||||
|
peq_chain: default_peq_chain(),
|
||||||
|
crossover: default_crossover_filters(),
|
||||||
|
|
||||||
|
linked_channels: Vec::new(),
|
||||||
|
|
||||||
|
mute: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// Output channels
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
fn default_output_states() -> HashMap<OutputChannel, OutputChannelState> {
|
||||||
|
[
|
||||||
|
(OutputChannel::Out1, default_output_channel_state("Out 1")),
|
||||||
|
(OutputChannel::Out2, default_output_channel_state("Out 2")),
|
||||||
|
(OutputChannel::Out3, default_output_channel_state("Out 3")),
|
||||||
|
(OutputChannel::Out4, default_output_channel_state("Out 4")),
|
||||||
|
(OutputChannel::Out5, default_output_channel_state("Out 5")),
|
||||||
|
(OutputChannel::Out6, default_output_channel_state("Out 6")),
|
||||||
|
(OutputChannel::Out7, default_output_channel_state("Out 7")),
|
||||||
|
(OutputChannel::Out8, default_output_channel_state("Out 8")),
|
||||||
|
]
|
||||||
|
.into_iter()
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_output_channel_state(name: &str) -> OutputChannelState {
|
||||||
|
OutputChannelState {
|
||||||
|
name: name.to_string(),
|
||||||
|
|
||||||
|
matrix_routes: default_matrix_routes(),
|
||||||
|
|
||||||
|
crossover: default_crossover_filters(),
|
||||||
|
peq_chain: default_peq_chain(),
|
||||||
|
|
||||||
|
compressor: default_compressor(),
|
||||||
|
limiter: default_limiter(),
|
||||||
|
|
||||||
|
gain: 0.0,
|
||||||
|
phase_inverted: false,
|
||||||
|
delay: 0.0,
|
||||||
|
|
||||||
|
linked_channels: Vec::new(),
|
||||||
|
|
||||||
|
mute: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// Gate
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
fn default_gate() -> Gate {
|
||||||
|
Gate {
|
||||||
|
attack: 10,
|
||||||
|
release: 10,
|
||||||
|
hold: 10,
|
||||||
|
threshold: 0.0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// Graphic EQ
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
fn default_graphic_eq() -> GraphicEQ {
|
||||||
|
let gains = DiscreteFrequency::iter()
|
||||||
|
.map(|frequency| (frequency, 0.0))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
GraphicEQ {
|
||||||
|
gains,
|
||||||
|
bypass: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// PEQ
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
fn default_peq() -> PEQ {
|
||||||
|
PEQ {
|
||||||
|
gain: 0.0,
|
||||||
|
frequency: 1000.0,
|
||||||
|
q: 1.0,
|
||||||
|
filter_type: PEQFilter::Peak,
|
||||||
|
bypass: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_peq_chain() -> PEQChain {
|
||||||
|
let bands = PEQBand::iter().map(|band| (band, default_peq())).collect();
|
||||||
|
|
||||||
|
PEQChain {
|
||||||
|
bands,
|
||||||
|
bypass: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// Crossover
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
fn default_crossover(frequency: f32) -> Crossover {
|
||||||
|
Crossover {
|
||||||
|
frequency,
|
||||||
|
slope: CrossoverFilter::Bypass,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_crossover_filters() -> CrossoverFilters {
|
||||||
|
CrossoverFilters {
|
||||||
|
high_pass: default_crossover(FREQUENCY_MIN),
|
||||||
|
low_pass: default_crossover(FREQUENCY_MAX),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// Matrix
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
fn default_matrix_routes() -> MatrixRoutes {
|
||||||
|
let gains = [
|
||||||
|
(InputChannel::InA, 0.0),
|
||||||
|
(InputChannel::InB, 0.0),
|
||||||
|
(InputChannel::InC, 0.0),
|
||||||
|
(InputChannel::InD, 0.0),
|
||||||
|
]
|
||||||
|
.into_iter()
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
MatrixRoutes {
|
||||||
|
connected: vec![InputChannel::InA],
|
||||||
|
gains,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// Compressor
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
fn default_compressor() -> Compressor {
|
||||||
|
Compressor {
|
||||||
|
threshold: -90.0,
|
||||||
|
ratio: Ratio::Ratio1_1,
|
||||||
|
attack: 1,
|
||||||
|
release: 10,
|
||||||
|
knee: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// Limiter
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
fn default_limiter() -> Limiter {
|
||||||
|
Limiter {
|
||||||
|
threshold: -90.0,
|
||||||
|
attack: 1,
|
||||||
|
release: 10,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// Meters
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
fn default_meter() -> Meter {
|
||||||
|
Meter {
|
||||||
|
rms: -60.0,
|
||||||
|
peak: -60.0,
|
||||||
|
clip: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn random_meter() -> Meter {
|
||||||
|
let mut rng = rand::rng();
|
||||||
|
|
||||||
|
let rms = rng.random_range(-60.0..=0.0);
|
||||||
|
let peak = (rms + rng.random_range(0.0..=12.0) as f32).min(12.0);
|
||||||
|
|
||||||
|
Meter {
|
||||||
|
rms,
|
||||||
|
peak,
|
||||||
|
clip: peak > 0.0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn random_input_meters() -> InputMeters {
|
||||||
|
InputMeters {
|
||||||
|
meters: InputChannel::iter()
|
||||||
|
.map(|channel| (channel, random_meter()))
|
||||||
|
.collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn random_output_meters() -> OutputMeters {
|
||||||
|
OutputMeters {
|
||||||
|
meters: OutputChannel::iter()
|
||||||
|
.map(|channel| (channel, random_meter()))
|
||||||
|
.collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
+932
-341
File diff suppressed because it is too large
Load Diff
@@ -1,2 +1,4 @@
|
|||||||
|
mod default;
|
||||||
mod dsp408;
|
mod dsp408;
|
||||||
|
|
||||||
pub use dsp408::DSP408;
|
pub use dsp408::DSP408;
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
common::errors::ProtocolError,
|
common::errors::ProtocolError,
|
||||||
dsp408::{
|
dsp408::{
|
||||||
protocol::{
|
protocol::frame::Frame,
|
||||||
constants::{METERS_HIGH_STEP, METERS_LOW_STEP, METERS_SPLIT, METERS_SPLIT_LEVEL_DB},
|
|
||||||
frame::Frame,
|
|
||||||
},
|
|
||||||
types::{
|
types::{
|
||||||
Acknowledgement, AuthenticationResult, ConfigChunk, CurrentPreset, DeviceFlags,
|
Acknowledgement, AuthenticationResult, ConfigChunk, CurrentPreset, DeviceFlags,
|
||||||
DeviceInfo, DeviceResponseType, HandshakeAck, Meters, ModifiedPreset, NotImplemented,
|
DeviceInfo, DeviceResponseType, HandshakeAck, InputChannel, InputMeters, Meter,
|
||||||
PresetName, UnknownResponse,
|
ModifiedPreset, NotImplemented, OutputChannel, OutputMeters, PresetName,
|
||||||
|
UnknownResponse,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -88,10 +90,6 @@ pub fn map_response(frame: &Frame) -> Result<DeviceResponseType, ProtocolError>
|
|||||||
|
|
||||||
// Command `0x24` (Get Config Chunk)
|
// Command `0x24` (Get Config Chunk)
|
||||||
if cmd == 0x24 {
|
if cmd == 0x24 {
|
||||||
// Mirrors Python's `int.from_bytes(payload[:1], "little")`, which
|
|
||||||
// is `0` for an empty payload rather than an error — Python slices
|
|
||||||
// never panic. `payload.get(1..)` below mirrors the same
|
|
||||||
// forgiving-slice behavior for the remainder.
|
|
||||||
let index = payload.first().copied().unwrap_or(0);
|
let index = payload.first().copied().unwrap_or(0);
|
||||||
|
|
||||||
if index > 0x1c {
|
if index > 0x1c {
|
||||||
@@ -166,27 +164,75 @@ pub fn map_response(frame: &Frame) -> Result<DeviceResponseType, ProtocolError>
|
|||||||
|
|
||||||
// Command `0x40` (Get Level Meters)
|
// Command `0x40` (Get Level Meters)
|
||||||
if cmd == 0x40 {
|
if cmd == 0x40 {
|
||||||
|
const X0: f32 = -25.0; // breakpoint, in dB
|
||||||
|
const Y0: f32 = 1.0; // raw value at the breakpoint
|
||||||
|
const K1: f32 = 0.0104; // slope below breakpoint (raw < Y0)
|
||||||
|
const K2: f32 = 0.0208; // slope above breakpoint (raw >= Y0)
|
||||||
|
|
||||||
|
const MIN_DB: f32 = -60.0;
|
||||||
|
const MAX_DB: f32 = 12.0;
|
||||||
|
|
||||||
|
fn float_to_db(raw: f32) -> f32 {
|
||||||
|
let db = if raw < Y0 {
|
||||||
|
X0 + (raw - Y0) / K1
|
||||||
|
} else {
|
||||||
|
X0 + (raw - Y0) / K2
|
||||||
|
};
|
||||||
|
db.clamp(MIN_DB, MAX_DB)
|
||||||
|
}
|
||||||
|
|
||||||
if payload.len() != 38 {
|
if payload.len() != 38 {
|
||||||
return Err(ProtocolError::new("Not enough bytes for meter levels"));
|
return Err(ProtocolError::new("Not enough bytes for meter levels"));
|
||||||
}
|
}
|
||||||
|
|
||||||
let floats: Vec<f32> = (0..36)
|
let raw_meters: Vec<Meter> = (0..36)
|
||||||
.step_by(3)
|
.step_by(3)
|
||||||
.map(|i| decode_float16(payload[i], payload[i + 1]).unwrap_or_default())
|
.enumerate()
|
||||||
.collect();
|
.map(|(index, i)| {
|
||||||
|
let rms = decode_float16(payload[i], payload[i + 1]).unwrap_or_default();
|
||||||
|
let peak = decode_float16(payload[i + 2], payload[i + 1]).unwrap_or_default();
|
||||||
|
|
||||||
let meters: Vec<f32> = floats
|
let rms_db = float_to_db(rms);
|
||||||
.into_iter()
|
let peak_db = float_to_db(peak);
|
||||||
.map(|f| {
|
|
||||||
if f < METERS_SPLIT {
|
let clip = if index < 4 {
|
||||||
METERS_SPLIT_LEVEL_DB + (f - METERS_SPLIT) / METERS_LOW_STEP
|
payload[36] & (1 << index) != 0
|
||||||
} else {
|
} else {
|
||||||
METERS_SPLIT_LEVEL_DB + (f - METERS_SPLIT) / METERS_HIGH_STEP
|
payload[37] & (1 << (index - 4)) != 0
|
||||||
|
};
|
||||||
|
|
||||||
|
Meter {
|
||||||
|
rms: rms_db,
|
||||||
|
peak: peak_db,
|
||||||
|
clip,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
return Ok(DeviceResponseType::Meters(Meters { levels: meters }));
|
let mut input_iter = InputChannel::iter();
|
||||||
|
let mut output_iter = OutputChannel::iter();
|
||||||
|
|
||||||
|
let mut input_meters = HashMap::new();
|
||||||
|
let mut output_meters = HashMap::new();
|
||||||
|
|
||||||
|
for (index, meter) in raw_meters.into_iter().enumerate() {
|
||||||
|
if index < 4 {
|
||||||
|
if let Some(channel) = input_iter.next() {
|
||||||
|
input_meters.insert(channel, meter);
|
||||||
|
}
|
||||||
|
} else if let Some(channel) = output_iter.next() {
|
||||||
|
output_meters.insert(channel, meter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(DeviceResponseType::Meters(
|
||||||
|
InputMeters {
|
||||||
|
meters: input_meters,
|
||||||
|
},
|
||||||
|
OutputMeters {
|
||||||
|
meters: output_meters,
|
||||||
|
},
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(DeviceResponseType::UnknownResponse(UnknownResponse {
|
Ok(DeviceResponseType::UnknownResponse(UnknownResponse {
|
||||||
@@ -401,8 +447,6 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn meters_decode() {
|
fn meters_decode() {
|
||||||
// 38 bytes required.
|
|
||||||
// First 36 bytes are meter values, remaining 2 bytes ignored.
|
|
||||||
let mut payload = vec![0; 38];
|
let mut payload = vec![0; 38];
|
||||||
|
|
||||||
// half float 1.0 = 0x3c00
|
// half float 1.0 = 0x3c00
|
||||||
@@ -414,11 +458,12 @@ mod tests {
|
|||||||
let result = map_response(&frame(0x40, payload)).unwrap();
|
let result = map_response(&frame(0x40, payload)).unwrap();
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
DeviceResponseType::Meters(m) => {
|
DeviceResponseType::Meters(inputs, outputs) => {
|
||||||
assert_eq!(m.levels.len(), 12);
|
assert_eq!(inputs.meters.len(), 4);
|
||||||
|
assert_eq!(outputs.meters.len(), 8);
|
||||||
|
|
||||||
for level in m.levels {
|
for meter in inputs.meters.values().chain(outputs.meters.values()) {
|
||||||
assert!(level.is_finite());
|
assert!(meter.rms.is_finite());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
other => panic!("unexpected {:?}", other),
|
other => panic!("unexpected {:?}", other),
|
||||||
|
|||||||
@@ -35,12 +35,14 @@ fn read_gate(r: &mut BinaryReader) -> Result<types::Gate, DSPError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn read_geq(r: &mut BinaryReader) -> Result<types::GraphicEQ, DSPError> {
|
fn read_geq(r: &mut BinaryReader) -> Result<types::GraphicEQ, DSPError> {
|
||||||
let gains = types::DiscreteFrequency::iter()
|
let mut gains = std::collections::HashMap::new();
|
||||||
.map(|_| {
|
|
||||||
|
for frequency in types::DiscreteFrequency::iter() {
|
||||||
let raw = r.read_u16()?;
|
let raw = r.read_u16()?;
|
||||||
Ok(mapper::raw_to_eq_gain(raw)?)
|
let gain = mapper::raw_to_eq_gain(raw)?;
|
||||||
})
|
|
||||||
.collect::<Result<Vec<_>, DSPError>>()?;
|
gains.insert(frequency, gain);
|
||||||
|
}
|
||||||
|
|
||||||
Ok(types::GraphicEQ {
|
Ok(types::GraphicEQ {
|
||||||
gains,
|
gains,
|
||||||
@@ -49,17 +51,20 @@ fn read_geq(r: &mut BinaryReader) -> Result<types::GraphicEQ, DSPError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn read_peq_chain(r: &mut BinaryReader, band_count: usize) -> Result<types::PEQChain, DSPError> {
|
fn read_peq_chain(r: &mut BinaryReader, band_count: usize) -> Result<types::PEQChain, DSPError> {
|
||||||
let bands = (0..band_count)
|
let bands = types::PEQBand::iter()
|
||||||
.map(|_| {
|
.take(band_count)
|
||||||
Ok(types::PEQ {
|
.map(|band| {
|
||||||
|
let peq = types::PEQ {
|
||||||
gain: mapper::raw_to_eq_gain(r.read_u16()?)?,
|
gain: mapper::raw_to_eq_gain(r.read_u16()?)?,
|
||||||
frequency: mapper::raw_to_frequency_hz(r.read_u16()?)?,
|
frequency: mapper::raw_to_frequency_hz(r.read_u16()?)?,
|
||||||
q: mapper::raw_to_peq_q(r.read_u8()?)?,
|
q: mapper::raw_to_peq_q(r.read_u8()?)?,
|
||||||
filter_type: mapper::raw_to_peq_filter(r.read_u8()?)?,
|
filter_type: mapper::raw_to_peq_filter(r.read_u8()?)?,
|
||||||
bypass: false,
|
bypass: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok((band, peq))
|
||||||
})
|
})
|
||||||
})
|
.collect::<Result<HashMap<_, _>, DSPError>>()?;
|
||||||
.collect::<Result<Vec<_>, DSPError>>()?;
|
|
||||||
|
|
||||||
Ok(types::PEQChain {
|
Ok(types::PEQChain {
|
||||||
bands,
|
bands,
|
||||||
@@ -67,6 +72,21 @@ fn read_peq_chain(r: &mut BinaryReader, band_count: usize) -> Result<types::PEQC
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn apply_peq_bypass(
|
||||||
|
r: &mut BinaryReader,
|
||||||
|
bands: &mut HashMap<types::PEQBand, types::PEQ>,
|
||||||
|
) -> Result<(), DSPError> {
|
||||||
|
let bitmap = r.read_u16()?;
|
||||||
|
|
||||||
|
for (index, band) in types::PEQBand::iter().enumerate() {
|
||||||
|
if let Some(peq) = bands.get_mut(&band) {
|
||||||
|
peq.bypass = bitmap & (1 << index) != 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn read_crossover(r: &mut BinaryReader) -> Result<types::CrossoverFilters, DSPError> {
|
fn read_crossover(r: &mut BinaryReader) -> Result<types::CrossoverFilters, DSPError> {
|
||||||
let hp_freq = r.read_u16()?;
|
let hp_freq = r.read_u16()?;
|
||||||
let lp_freq = r.read_u16()?;
|
let lp_freq = r.read_u16()?;
|
||||||
@@ -152,7 +172,13 @@ pub fn decode_config(payload: &[u8]) -> Result<types::DSPConfigState, DSPError>
|
|||||||
inp.linked_channels = mapper::raw_to_link_channels(
|
inp.linked_channels = mapper::raw_to_link_channels(
|
||||||
mapper::channel_to_raw(types::Channel::Input(channel))?,
|
mapper::channel_to_raw(types::Channel::Input(channel))?,
|
||||||
r.read_u8()?,
|
r.read_u8()?,
|
||||||
)?;
|
)?
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|link| match link {
|
||||||
|
types::Channel::Input(input) => Some(input),
|
||||||
|
types::Channel::Output(_) => None,
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================
|
// ============================
|
||||||
@@ -162,17 +188,26 @@ pub fn decode_config(payload: &[u8]) -> Result<types::DSPConfigState, DSPError>
|
|||||||
for (channel, out) in types::OutputChannel::iter().zip(output_channels.iter_mut()) {
|
for (channel, out) in types::OutputChannel::iter().zip(output_channels.iter_mut()) {
|
||||||
out.name = mapper::raw_to_channel_name(r.pop(constants::CHANNEL_NAME_LENGTH)?)?;
|
out.name = mapper::raw_to_channel_name(r.pop(constants::CHANNEL_NAME_LENGTH)?)?;
|
||||||
|
|
||||||
r.skip(1)?;
|
|
||||||
|
|
||||||
out.matrix_routes = types::MatrixRoutes {
|
out.matrix_routes = types::MatrixRoutes {
|
||||||
connected: mapper::raw_to_matrix(r.read_u8()?)?,
|
connected: mapper::raw_to_matrix(r.read_u8()?)?,
|
||||||
|
|
||||||
gains: (0..4)
|
gains: {
|
||||||
.map(|_| {
|
r.skip(1)?;
|
||||||
|
|
||||||
|
[
|
||||||
|
types::InputChannel::InA,
|
||||||
|
types::InputChannel::InB,
|
||||||
|
types::InputChannel::InC,
|
||||||
|
types::InputChannel::InD,
|
||||||
|
]
|
||||||
|
.into_iter()
|
||||||
|
.map(|input| {
|
||||||
let raw = r.read_u16()?;
|
let raw = r.read_u16()?;
|
||||||
Ok::<f32, DSPError>(mapper::raw_to_matrix_gain(raw)?)
|
let gain = mapper::raw_to_matrix_gain(raw)?;
|
||||||
|
Ok::<(types::InputChannel, f32), DSPError>((input, gain))
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<_>, _>>()?,
|
.collect::<Result<HashMap<_, _>, _>>()?
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
out.crossover = read_crossover(&mut r)?;
|
out.crossover = read_crossover(&mut r)?;
|
||||||
@@ -196,7 +231,13 @@ pub fn decode_config(payload: &[u8]) -> Result<types::DSPConfigState, DSPError>
|
|||||||
out.linked_channels = mapper::raw_to_link_channels(
|
out.linked_channels = mapper::raw_to_link_channels(
|
||||||
mapper::channel_to_raw(types::Channel::Output(channel))?,
|
mapper::channel_to_raw(types::Channel::Output(channel))?,
|
||||||
r.read_u8()?,
|
r.read_u8()?,
|
||||||
)?;
|
)?
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|link| match link {
|
||||||
|
types::Channel::Output(output) => Some(output),
|
||||||
|
types::Channel::Input(_) => None,
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================
|
// ============================
|
||||||
@@ -212,15 +253,11 @@ pub fn decode_config(payload: &[u8]) -> Result<types::DSPConfigState, DSPError>
|
|||||||
// ============================
|
// ============================
|
||||||
|
|
||||||
for inp in &mut input_channels {
|
for inp in &mut input_channels {
|
||||||
apply_flag(&mut r, inp.peq_chain.bands.as_mut_slice(), |band, value| {
|
apply_peq_bypass(&mut r, &mut inp.peq_chain.bands)?;
|
||||||
band.bypass = value
|
|
||||||
})?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for out in &mut output_channels {
|
for out in &mut output_channels {
|
||||||
apply_flag(&mut r, out.peq_chain.bands.as_mut_slice(), |band, value| {
|
apply_peq_bypass(&mut r, &mut out.peq_chain.bands)?;
|
||||||
band.bypass = value
|
|
||||||
})?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================
|
// ============================
|
||||||
@@ -260,9 +297,7 @@ pub fn decode_config(payload: &[u8]) -> Result<types::DSPConfigState, DSPError>
|
|||||||
for (index, inp) in input_channels.iter_mut().enumerate() {
|
for (index, inp) in input_channels.iter_mut().enumerate() {
|
||||||
let bypass = input_peq_bitmap & (1 << index) != 0;
|
let bypass = input_peq_bitmap & (1 << index) != 0;
|
||||||
|
|
||||||
for peq in inp.peq_chain.bands.iter_mut() {
|
inp.peq_chain.bypass = bypass;
|
||||||
peq.bypass = bypass;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let output_peq_bitmap = r.read_u16()?;
|
let output_peq_bitmap = r.read_u16()?;
|
||||||
@@ -270,9 +305,7 @@ pub fn decode_config(payload: &[u8]) -> Result<types::DSPConfigState, DSPError>
|
|||||||
for (index, out) in output_channels.iter_mut().enumerate() {
|
for (index, out) in output_channels.iter_mut().enumerate() {
|
||||||
let bypass = output_peq_bitmap & (1 << index) != 0;
|
let bypass = output_peq_bitmap & (1 << index) != 0;
|
||||||
|
|
||||||
for peq in out.peq_chain.bands.iter_mut() {
|
out.peq_chain.bypass = bypass;
|
||||||
peq.bypass = bypass;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let bitmap = r.read_u16()?;
|
let bitmap = r.read_u16()?;
|
||||||
|
|||||||
@@ -77,8 +77,3 @@ pub fn output_link_mask(channel: u8) -> Option<u8> {
|
|||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const METERS_SPLIT: f32 = 1.0;
|
|
||||||
pub const METERS_SPLIT_LEVEL_DB: f32 = -18.0;
|
|
||||||
pub const METERS_LOW_STEP: f32 = 0.0104;
|
|
||||||
pub const METERS_HIGH_STEP: f32 = 0.0208;
|
|
||||||
|
|||||||
+69
-11
@@ -1,8 +1,12 @@
|
|||||||
use std::{collections::HashMap, net::IpAddr};
|
use std::{collections::HashMap, net::IpAddr};
|
||||||
use strum_macros::{EnumCount, EnumIter};
|
use strum_macros::{EnumCount, EnumIter};
|
||||||
|
|
||||||
|
#[cfg(feature = "serialization")]
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
// ------ Enums ------
|
// ------ Enums ------
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub enum DelayUnit {
|
pub enum DelayUnit {
|
||||||
Millisecond,
|
Millisecond,
|
||||||
@@ -10,6 +14,7 @@ pub enum DelayUnit {
|
|||||||
Feet,
|
Feet,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, EnumIter, EnumCount, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, EnumIter, EnumCount, PartialOrd, Ord)]
|
||||||
pub enum InputChannel {
|
pub enum InputChannel {
|
||||||
InA,
|
InA,
|
||||||
@@ -18,6 +23,7 @@ pub enum InputChannel {
|
|||||||
InD,
|
InD,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, EnumIter, EnumCount, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, EnumIter, EnumCount, PartialOrd, Ord)]
|
||||||
pub enum OutputChannel {
|
pub enum OutputChannel {
|
||||||
Out1,
|
Out1,
|
||||||
@@ -30,12 +36,14 @@ pub enum OutputChannel {
|
|||||||
Out8,
|
Out8,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||||
pub enum Channel {
|
pub enum Channel {
|
||||||
Input(InputChannel),
|
Input(InputChannel),
|
||||||
Output(OutputChannel),
|
Output(OutputChannel),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
|
||||||
pub enum Ratio {
|
pub enum Ratio {
|
||||||
#[default]
|
#[default]
|
||||||
@@ -57,6 +65,7 @@ pub enum Ratio {
|
|||||||
Limit,
|
Limit,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
|
||||||
pub enum CrossoverFilter {
|
pub enum CrossoverFilter {
|
||||||
#[default]
|
#[default]
|
||||||
@@ -83,6 +92,7 @@ pub enum CrossoverFilter {
|
|||||||
Bl48,
|
Bl48,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, EnumIter)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, EnumIter)]
|
||||||
pub enum PEQBand {
|
pub enum PEQBand {
|
||||||
B1 = 1,
|
B1 = 1,
|
||||||
@@ -96,6 +106,7 @@ pub enum PEQBand {
|
|||||||
B9,
|
B9,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub enum PEQFilter {
|
pub enum PEQFilter {
|
||||||
Peak,
|
Peak,
|
||||||
@@ -109,6 +120,7 @@ pub enum PEQFilter {
|
|||||||
AllPass2,
|
AllPass2,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, EnumIter)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, EnumIter)]
|
||||||
pub enum DiscreteFrequency {
|
pub enum DiscreteFrequency {
|
||||||
F20,
|
F20,
|
||||||
@@ -144,6 +156,7 @@ pub enum DiscreteFrequency {
|
|||||||
F20000,
|
F20000,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub enum InputType {
|
pub enum InputType {
|
||||||
Analog,
|
Analog,
|
||||||
@@ -152,6 +165,7 @@ pub enum InputType {
|
|||||||
SineWave,
|
SineWave,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
pub struct InputSource {
|
pub struct InputSource {
|
||||||
pub r#type: InputType,
|
pub r#type: InputType,
|
||||||
@@ -194,6 +208,7 @@ pub struct PresetName {
|
|||||||
pub name: String,
|
pub name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub struct DeviceFlags {
|
pub struct DeviceFlags {
|
||||||
pub is_locked: bool,
|
pub is_locked: bool,
|
||||||
@@ -204,9 +219,12 @@ pub struct AuthenticationResult {
|
|||||||
pub success: bool,
|
pub success: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
|
||||||
pub struct Meters {
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
pub levels: Vec<f32>,
|
pub struct Meter {
|
||||||
|
pub rms: f32,
|
||||||
|
pub peak: f32,
|
||||||
|
pub clip: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
@@ -230,7 +248,7 @@ pub enum DeviceResponseType {
|
|||||||
PresetName(PresetName),
|
PresetName(PresetName),
|
||||||
DeviceFlags(DeviceFlags),
|
DeviceFlags(DeviceFlags),
|
||||||
AuthenticationResult(AuthenticationResult),
|
AuthenticationResult(AuthenticationResult),
|
||||||
Meters(Meters),
|
Meters(InputMeters, OutputMeters),
|
||||||
CurrentPreset(CurrentPreset),
|
CurrentPreset(CurrentPreset),
|
||||||
ModifiedPreset(ModifiedPreset),
|
ModifiedPreset(ModifiedPreset),
|
||||||
ConfigChunk(ConfigChunk),
|
ConfigChunk(ConfigChunk),
|
||||||
@@ -238,7 +256,7 @@ pub enum DeviceResponseType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ------ State ------
|
// ------ State ------
|
||||||
|
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Default)]
|
#[derive(Debug, Clone, Copy, PartialEq, Default)]
|
||||||
pub struct Gate {
|
pub struct Gate {
|
||||||
pub attack: u16,
|
pub attack: u16,
|
||||||
@@ -247,6 +265,7 @@ pub struct Gate {
|
|||||||
pub threshold: f32,
|
pub threshold: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Default)]
|
#[derive(Debug, Clone, Copy, PartialEq, Default)]
|
||||||
pub struct Compressor {
|
pub struct Compressor {
|
||||||
pub threshold: f32,
|
pub threshold: f32,
|
||||||
@@ -256,6 +275,7 @@ pub struct Compressor {
|
|||||||
pub knee: u16,
|
pub knee: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Default)]
|
#[derive(Debug, Clone, Copy, PartialEq, Default)]
|
||||||
pub struct Limiter {
|
pub struct Limiter {
|
||||||
pub threshold: f32,
|
pub threshold: f32,
|
||||||
@@ -263,12 +283,14 @@ pub struct Limiter {
|
|||||||
pub release: u16,
|
pub release: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
|
||||||
#[derive(Debug, Clone, PartialEq, Default)]
|
#[derive(Debug, Clone, PartialEq, Default)]
|
||||||
pub struct GraphicEQ {
|
pub struct GraphicEQ {
|
||||||
pub gains: Vec<f32>,
|
pub gains: HashMap<DiscreteFrequency, f32>,
|
||||||
pub bypass: bool,
|
pub bypass: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
pub struct PEQ {
|
pub struct PEQ {
|
||||||
pub gain: f32,
|
pub gain: f32,
|
||||||
@@ -278,30 +300,35 @@ pub struct PEQ {
|
|||||||
pub bypass: bool,
|
pub bypass: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Default)]
|
#[derive(Debug, Clone, Copy, PartialEq, Default)]
|
||||||
pub struct CrossoverFilters {
|
pub struct CrossoverFilters {
|
||||||
pub high_pass: Crossover,
|
pub high_pass: Crossover,
|
||||||
pub low_pass: Crossover,
|
pub low_pass: Crossover,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Default)]
|
#[derive(Debug, Clone, Copy, PartialEq, Default)]
|
||||||
pub struct Crossover {
|
pub struct Crossover {
|
||||||
pub frequency: f32,
|
pub frequency: f32,
|
||||||
pub slope: CrossoverFilter,
|
pub slope: CrossoverFilter,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
|
||||||
#[derive(Debug, Clone, PartialEq, Default)]
|
#[derive(Debug, Clone, PartialEq, Default)]
|
||||||
pub struct MatrixRoutes {
|
pub struct MatrixRoutes {
|
||||||
pub connected: Vec<InputChannel>,
|
pub connected: Vec<InputChannel>,
|
||||||
pub gains: Vec<f32>,
|
pub gains: HashMap<InputChannel, f32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
|
||||||
#[derive(Debug, Clone, PartialEq, Default)]
|
#[derive(Debug, Clone, PartialEq, Default)]
|
||||||
pub struct PEQChain {
|
pub struct PEQChain {
|
||||||
pub bands: Vec<PEQ>,
|
pub bands: HashMap<PEQBand, PEQ>,
|
||||||
pub bypass: bool,
|
pub bypass: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct PresetBank {
|
pub struct PresetBank {
|
||||||
pub current_index: usize,
|
pub current_index: usize,
|
||||||
@@ -309,6 +336,7 @@ pub struct PresetBank {
|
|||||||
pub modified: Vec<bool>,
|
pub modified: Vec<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct DeviceConnection {
|
pub struct DeviceConnection {
|
||||||
pub host: IpAddr,
|
pub host: IpAddr,
|
||||||
@@ -316,6 +344,7 @@ pub struct DeviceConnection {
|
|||||||
pub device_id: u8,
|
pub device_id: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
|
||||||
#[derive(Debug, Clone, PartialEq, Default)]
|
#[derive(Debug, Clone, PartialEq, Default)]
|
||||||
pub struct InputChannelState {
|
pub struct InputChannelState {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
@@ -326,10 +355,11 @@ pub struct InputChannelState {
|
|||||||
pub geq: GraphicEQ,
|
pub geq: GraphicEQ,
|
||||||
pub peq_chain: PEQChain,
|
pub peq_chain: PEQChain,
|
||||||
pub crossover: CrossoverFilters,
|
pub crossover: CrossoverFilters,
|
||||||
pub linked_channels: Vec<Channel>,
|
pub linked_channels: Vec<InputChannel>,
|
||||||
pub mute: bool,
|
pub mute: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
|
||||||
#[derive(Debug, Clone, Default, PartialEq)]
|
#[derive(Debug, Clone, Default, PartialEq)]
|
||||||
pub struct OutputChannelState {
|
pub struct OutputChannelState {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
@@ -341,10 +371,11 @@ pub struct OutputChannelState {
|
|||||||
pub gain: f32,
|
pub gain: f32,
|
||||||
pub phase_inverted: bool,
|
pub phase_inverted: bool,
|
||||||
pub delay: f32,
|
pub delay: f32,
|
||||||
pub linked_channels: Vec<Channel>,
|
pub linked_channels: Vec<OutputChannel>,
|
||||||
pub mute: bool,
|
pub mute: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct DSPConfigState {
|
pub struct DSPConfigState {
|
||||||
pub(crate) input_states: HashMap<InputChannel, InputChannelState>,
|
pub(crate) input_states: HashMap<InputChannel, InputChannelState>,
|
||||||
@@ -367,11 +398,38 @@ impl DSPConfigState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub enum DSPMode {
|
||||||
|
Demo,
|
||||||
|
Normal,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub enum ConnectionStatus {
|
||||||
|
Connected,
|
||||||
|
Disconnected,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct DSPState {
|
pub struct DSPState {
|
||||||
pub(crate) name: String,
|
pub(crate) name: String,
|
||||||
pub(crate) flags: DeviceFlags,
|
pub(crate) flags: DeviceFlags,
|
||||||
pub(crate) presets: PresetBank,
|
pub(crate) presets: PresetBank,
|
||||||
|
|
||||||
pub(crate) current_config: DSPConfigState,
|
pub(crate) current_config: DSPConfigState,
|
||||||
|
pub(crate) connection: ConnectionStatus,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
|
||||||
|
#[derive(Debug, Clone, PartialEq, Default)]
|
||||||
|
pub struct InputMeters {
|
||||||
|
pub meters: HashMap<InputChannel, Meter>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
|
||||||
|
#[derive(Debug, Clone, PartialEq, Default)]
|
||||||
|
pub struct OutputMeters {
|
||||||
|
pub meters: HashMap<OutputChannel, Meter>,
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-4
@@ -2,7 +2,6 @@ use std::net::IpAddr;
|
|||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use dsp_thomann::dsp408::DSP408;
|
use dsp_thomann::dsp408::DSP408;
|
||||||
use dsp_thomann::dsp408::types;
|
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let host = IpAddr::from_str("192.168.49.30")?;
|
let host = IpAddr::from_str("192.168.49.30")?;
|
||||||
@@ -22,13 +21,29 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
}
|
}
|
||||||
println!("DSP connected.");
|
println!("DSP connected.");
|
||||||
|
|
||||||
dsp.set_mute(types::Channel::Input(types::InputChannel::InA), true)?;
|
// dsp.set_mute(types::Channel::Input(types::InputChannel::InA), true)?;
|
||||||
|
|
||||||
dbg!(dsp.state()?);
|
// let r = dsp.set_peq_band(
|
||||||
|
// types::Channel::Input(InA),
|
||||||
|
// types::PEQBand::B1,
|
||||||
|
// 3.0,
|
||||||
|
// 1400.0,
|
||||||
|
// 2.1,
|
||||||
|
// types::PEQFilter::LowShelf,
|
||||||
|
// false,
|
||||||
|
// )?;
|
||||||
|
// dbg!(r);
|
||||||
|
|
||||||
|
dbg!(&dsp.state());
|
||||||
|
|
||||||
|
// let s = &dsp.state()?.current_config.input_states[&InputChannel::InA].peq_chain;
|
||||||
|
// dbg!(s)
|
||||||
|
|
||||||
println!("Disconnecting...");
|
println!("Disconnecting...");
|
||||||
dsp.disconnect();
|
dsp.disconnect()?;
|
||||||
println!("Disconnected");
|
println!("Disconnected");
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 10020100 27 40 263df7 263dfd 263dfd 263dfd 063d8d 063d63 263dcf 263dfd 263df6 263dcf 263dcf 263dcf 0300 10038b
|
||||||
|
|||||||
Reference in New Issue
Block a user