diff --git a/Cargo.lock b/Cargo.lock index 00bf5ea..8c96528 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,103 +1,203 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "alsa" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed7572b7ba83a31e20d1b48970ee402d2e3e0537dcfe0a3ff4d6eb7508617d43" +dependencies = [ + "alsa-sys", + "bitflags 2.9.1", + "cfg-if", + "libc", +] [[package]] name = "alsa-sys" -version = "0.1.2" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0edcbbf9ef68f15ae1b620f722180b82a98b6f0628d30baa6b8d2a5abc87d58" +checksum = "db8fee663d06c4e303404ef5f40488a53e062f89ba8bfed81f42325aafad1527" dependencies = [ "libc", "pkg-config", ] [[package]] -name = "atty" -version = "0.2.14" +name = "anstream" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ - "hermit-abi", - "libc", - "winapi", + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" + +[[package]] +name = "anstyle-parse" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6680de5231bd6ee4c6191b8a1325daa282b415391ec9d3a37bd34f2060dc73fa" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.59.0", ] +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + [[package]] name = "autocfg" -version = "1.0.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "bindgen" -version = "0.53.3" +version = "0.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c72a978d268b1d70b0e963217e60fdabd9523a941457a6c42a7315d15c7e89e5" +checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f" dependencies = [ - "bitflags", + "bitflags 2.9.1", "cexpr", - "cfg-if", "clang-sys", - "lazy_static", - "lazycell", - "peeking_take_while", + "itertools", "proc-macro2", "quote", "regex", "rustc-hash", "shlex", + "syn", ] [[package]] name = "bitflags" -version = "1.2.1" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" [[package]] name = "bitvec" -version = "0.18.1" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c1f0df4bb4c441080e98d6ea2dc3281fc19bb440e69ce03075e3d705894f1cb" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" dependencies = [ "funty", "radium", + "tap", "wyz", ] +[[package]] +name = "bumpalo" +version = "3.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" + +[[package]] +name = "bytemuck" +version = "1.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9134a6ef01ce4b366b50689c94f82c14bc72bc5d0386829828a2e2752ef7958c" + [[package]] name = "byteorder" -version = "1.3.4" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" [[package]] name = "cc" -version = "1.0.59" +version = "1.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66120af515773fb005778dc07c261bd201ec8ce50bd6e7144c927753fe013381" +checksum = "16595d3be041c03b09d08d0858631facccee9221e579704070e6e9e4915d3bc7" +dependencies = [ + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" [[package]] name = "cexpr" -version = "0.4.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4aedb84272dbe89af497cf81375129abda4fc0a9e7c5d317498c15cc30c0d27" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" dependencies = [ - "nom 5.1.2", + "nom", ] [[package]] name = "cfg-if" -version = "0.1.10" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clang-sys" -version = "0.29.3" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe6837df1d5cba2397b835c8530f51723267e16abbf83892e9e5af4f0e5dd10a" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" dependencies = [ "glob", "libc", @@ -106,152 +206,262 @@ dependencies = [ [[package]] name = "clap" -version = "3.0.0-beta.5" +version = "4.5.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "feff3878564edb93745d58cf63e17b63f24142506e7a20c87a5521ed7bfb1d63" +checksum = "ed93b9805f8ba930df42c2590f05453d5ec36cbb85d018868a5b24d31f6ac000" dependencies = [ - "atty", - "bitflags", + "clap_builder", "clap_derive", - "indexmap", - "lazy_static", - "os_str_bytes", +] + +[[package]] +name = "clap_builder" +version = "4.5.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "379026ff283facf611b0ea629334361c4211d1b12ee01024eec1591133b04120" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", "strsim", - "termcolor", - "textwrap", - "unicase", ] [[package]] name = "clap_derive" -version = "3.0.0-beta.5" +version = "4.5.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b15c6b4f786ffb6192ffe65a36855bc1fc2444bcd0945ae16748dcd6ed7d0d3" +checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7" dependencies = [ "heck", - "proc-macro-error", "proc-macro2", "quote", "syn", ] +[[package]] +name = "clap_lex" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" + [[package]] name = "claxon" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4bfbf56724aa9eca8afa4fcfadeb479e722935bb2a0900c2d37e0cc477af0688" +[[package]] +name = "colorchoice" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" + +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + [[package]] name = "core-foundation-sys" -version = "0.6.2" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "coreaudio-rs" -version = "0.9.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f229761965dad3e9b11081668a6ea00f1def7aa46062321b5ec245b834f6e491" +checksum = "321077172d79c662f64f5071a03120748d5bb652f5231570141be24cfcd2bace" dependencies = [ - "bitflags", + "bitflags 1.3.2", + "core-foundation-sys", "coreaudio-sys", ] [[package]] name = "coreaudio-sys" -version = "0.2.5" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6570ee6e089131e928d5ec9236db9e818aa3cf850f48b0eec6ef700571271d4" +checksum = "2ce857aa0b77d77287acc1ac3e37a05a8c95a2af3647d23b15f263bdaeb7562b" dependencies = [ "bindgen", ] [[package]] name = "cpal" -version = "0.11.0" +version = "0.15.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b55d55d69f403f62a95bd3c04b431e0aedf5120c70f15d07a8edd234443dd59" +checksum = "873dab07c8f743075e57f524c583985fbaf745602acbe916a01539364369a779" dependencies = [ - "alsa-sys", + "alsa", "core-foundation-sys", "coreaudio-rs", - "lazy_static", + "dasp_sample", + "jni", + "js-sys", "libc", - "num-traits", - "stdweb", - "thiserror", - "winapi", + "mach2", + "ndk", + "ndk-context", + "oboe", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows", ] +[[package]] +name = "dasp_sample" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f" + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + [[package]] name = "funty" -version = "1.0.1" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ba62103ce691c2fd80fbae2213dfdda9ce60804973ac6b6e97de818ea7f52c8" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "getrandom" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi", +] [[package]] name = "glob" -version = "0.3.0" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" +checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" [[package]] name = "hashbrown" -version = "0.11.2" +version = "0.15.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3" [[package]] name = "heck" -version = "0.3.1" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hound" +version = "3.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" +checksum = "62adaabb884c94955b19907d60019f4e145d091c75345379e70d1ee696f7854f" + +[[package]] +name = "indexmap" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" dependencies = [ - "unicode-segmentation", + "equivalent", + "hashbrown", ] [[package]] -name = "hermit-abi" -version = "0.1.15" +name = "is_terminal_polyfill" +version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3deed196b6e7f9e44a2ae8d94225d80302d81208b1bb673fd21fe634645c85a9" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" dependencies = [ - "libc", + "either", ] [[package]] -name = "hound" -version = "3.4.0" +name = "jni" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a164bb2ceaeff4f42542bdb847c41517c78a60f5649671b2a07312b6e117549" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +dependencies = [ + "cesu8", + "cfg-if", + "combine", + "jni-sys", + "log", + "thiserror", + "walkdir", + "windows-sys 0.45.0", +] [[package]] -name = "indexmap" -version = "1.7.0" +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + +[[package]] +name = "jobserver" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" +checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" dependencies = [ - "autocfg", - "hashbrown", + "getrandom", + "libc", ] [[package]] -name = "lazy_static" -version = "1.4.0" +name = "js-sys" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +dependencies = [ + "once_cell", + "wasm-bindgen", +] [[package]] -name = "lazycell" -version = "1.3.0" +name = "lazy_static" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "lewton" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be42bea7971f4ba0ea1e215730c29bc1ff9bd2a9c10013912f42a8dcf8d77c0d" +checksum = "777b48df9aaab155475a83a7df3070395ea1ac6902f5cd062b8f2b028075c030" dependencies = [ "byteorder", "ogg", @@ -260,34 +470,40 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.76" +version = "0.2.172" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "755456fae044e6fa1ebbbd1b3e902ae19e73097ed4ed87bb79934a867c007bc3" +checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" [[package]] name = "libloading" -version = "0.5.2" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2b111a074963af1d37a139918ac6d49ad1d0d5e47f72fd55388619691a7d753" +checksum = "6a793df0d7afeac54f95b471d3af7f0d4fb975699f972341a4b76988d49cdf0c" dependencies = [ - "cc", - "winapi", + "cfg-if", + "windows-targets 0.52.6", ] [[package]] -name = "mach" -version = "0.3.2" +name = "log" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + +[[package]] +name = "mach2" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" dependencies = [ "libc", ] [[package]] name = "memchr" -version = "2.4.1" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "minimal-lexical" @@ -296,159 +512,214 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] -name = "minimp3" -version = "0.3.5" +name = "ndk" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dce0cff6a0bfd3f8b6b2350819bbddd63bc65cc45e53888bdd0ff49dde16d2d5" +checksum = "2076a31b7010b17a38c01907c45b945e8f11495ee4dd588309718901b1f7a5b7" dependencies = [ - "minimp3-sys", - "slice-deque", + "bitflags 2.9.1", + "jni-sys", + "log", + "ndk-sys", + "num_enum", + "thiserror", ] [[package]] -name = "minimp3-sys" -version = "0.3.2" +name = "ndk-context" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e21c73734c69dc95696c9ed8926a2b393171d98b3f5f5935686a26a487ab9b90" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" + +[[package]] +name = "ndk-sys" +version = "0.5.0+25.2.9519653" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c196769dd60fd4f363e11d948139556a344e79d451aeb2fa2fd040738ef7691" dependencies = [ - "cc", + "jni-sys", ] [[package]] name = "nom" -version = "5.1.2" +version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" dependencies = [ "memchr", - "version_check", + "minimal-lexical", ] [[package]] -name = "nom" -version = "7.1.0" +name = "num-derive" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1d11e1ef389c76fe5b81bcaf2ea32cf88b62bc494e19f493d0b30e7a930109" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ - "memchr", - "minimal-lexical", - "version_check", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "num-traits" -version = "0.2.12" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] [[package]] -name = "ogg" -version = "0.7.0" +name = "num_enum" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d79f1db9148be9d0e174bb3ac890f6030fcb1ed947267c5a91ee4c91b5a91e15" +checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" dependencies = [ - "byteorder", + "num_enum_derive", ] [[package]] -name = "os_str_bytes" -version = "4.2.0" +name = "num_enum_derive" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "addaa943333a514159c80c97ff4a93306530d965d27e139188283cd13e06a799" +checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" dependencies = [ - "memchr", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "peeking_take_while" -version = "0.1.2" +name = "oboe" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" +checksum = "e8b61bebd49e5d43f5f8cc7ee2891c16e0f41ec7954d36bcb6c14c5e0de867fb" +dependencies = [ + "jni", + "ndk", + "ndk-context", + "num-derive", + "num-traits", + "oboe-sys", +] [[package]] -name = "pkg-config" -version = "0.3.18" +name = "oboe-sys" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d36492546b6af1463394d46f0c834346f31548646f6ba10849802c9c9a27ac33" +checksum = "6c8bb09a4a2b1d668170cfe0a7d5bc103f8999fb316c98099b6a9939c9f2e79d" +dependencies = [ + "cc", +] [[package]] -name = "proc-macro-error" -version = "1.0.4" +name = "ogg" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +checksum = "6951b4e8bf21c8193da321bcce9c9dd2e13c858fe078bf9054a288b419ae5d6e" dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn", - "version_check", + "byteorder", ] [[package]] -name = "proc-macro-error-attr" -version = "1.0.4" +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" + +[[package]] +name = "pkg-config" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "proc-macro-crate" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" dependencies = [ - "proc-macro2", - "quote", - "version_check", + "toml_edit", ] [[package]] name = "proc-macro2" -version = "1.0.32" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba508cc11742c0dc5c1659771673afbab7a0efab23aa17e854cbab0837ed0b43" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" dependencies = [ - "unicode-xid", + "unicode-ident", ] [[package]] name = "quote" -version = "1.0.10" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" + [[package]] name = "radium" -version = "0.3.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "def50a86306165861203e7f84ecffbbdfdea79f0e51039b33de1e952358c47ac" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" [[package]] name = "regex" -version = "1.3.9" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", "regex-syntax", ] [[package]] name = "regex-syntax" -version = "0.6.18" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "rodio" -version = "0.11.0" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73bbf260262fd5501b7a17d6827e0d25c1127e921eb177150a060faf6e217a70" +checksum = "e7ceb6607dd738c99bc8cb28eff249b7cd5c8ec88b9db96c0608c1480d140fb1" dependencies = [ "claxon", "cpal", "hound", - "lazy_static", "lewton", - "minimp3", + "symphonia", ] [[package]] @@ -458,7 +729,7 @@ dependencies = [ "bitvec", "clap", "hound", - "nom 7.1.0", + "nom", "rodio", "thiserror", ] @@ -470,77 +741,112 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] -name = "shlex" -version = "0.1.1" +name = "rustversion" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" +checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" [[package]] -name = "slice-deque" -version = "0.3.0" +name = "same-file" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31ef6ee280cdefba6d2d0b4b78a84a1c1a3f3a4cec98c2d4231c8bc225de0f25" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" dependencies = [ - "libc", - "mach", - "winapi", + "winapi-util", ] [[package]] -name = "stdweb" -version = "0.1.3" +name = "shlex" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef5430c8e36b713e13b48a9f709cc21e046723fe44ce34587b73a830203b533e" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "strsim" -version = "0.10.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] -name = "syn" -version = "1.0.81" +name = "symphonia" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2afee18b8beb5a596ecb4a2dce128c719b4ba399d34126b9e4396e3f9860966" +checksum = "815c942ae7ee74737bb00f965fa5b5a2ac2ce7b6c01c0cc169bbeaf7abd5f5a9" dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", + "lazy_static", + "symphonia-bundle-mp3", + "symphonia-core", + "symphonia-metadata", ] [[package]] -name = "termcolor" -version = "1.1.0" +name = "symphonia-bundle-mp3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f" +checksum = "c01c2aae70f0f1fb096b6f0ff112a930b1fb3626178fba3ae68b09dce71706d4" dependencies = [ - "winapi-util", + "lazy_static", + "log", + "symphonia-core", + "symphonia-metadata", ] [[package]] -name = "textwrap" -version = "0.14.2" +name = "symphonia-core" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "798306779e3dc7d5231bd5691f5a813496dc79d3f56bf82e25789f2094e022c3" +dependencies = [ + "arrayvec", + "bitflags 1.3.2", + "bytemuck", + "lazy_static", + "log", +] + +[[package]] +name = "symphonia-metadata" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc622b9841a10089c5b18e99eb904f4341615d5aa55bbf4eedde1be721a4023c" +dependencies = [ + "encoding_rs", + "lazy_static", + "log", + "symphonia-core", +] + +[[package]] +name = "syn" +version = "2.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80" +checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" dependencies = [ - "unicode-width", + "proc-macro2", + "quote", + "unicode-ident", ] +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + [[package]] name = "thiserror" -version = "1.0.20" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dfdd070ccd8ccb78f4ad66bf1982dc37f620ef696c6b5028fe2ed83dd3d0d08" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.20" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd80fc12f73063ac132ac92aceea36734f04a1d93c1240c6944e23a3b8841793" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", @@ -549,76 +855,348 @@ dependencies = [ [[package]] name = "tinyvec" -version = "0.3.4" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "238ce071d267c5710f9d31451efec16c5ee22de34df17cc05e56cbc92e967117" +checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] -name = "unicase" -version = "2.6.0" +name = "toml_datetime" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +checksum = "3da5db5a963e24bc68be8b17b6fa82814bb22ee8660f192bb182771d498f09a3" + +[[package]] +name = "toml_edit" +version = "0.22.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "310068873db2c5b3e7659d2cc35d21855dbafa50d1ce336397c666e3cb08137e" dependencies = [ - "version_check", + "indexmap", + "toml_datetime", + "winnow", ] [[package]] -name = "unicode-segmentation" -version = "1.6.0" +name = "unicode-ident" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" [[package]] -name = "unicode-width" -version = "0.1.8" +name = "utf8parse" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] -name = "unicode-xid" -version = "0.2.1" +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", +] [[package]] -name = "version_check" -version = "0.9.2" +name = "wasm-bindgen-backend" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] [[package]] -name = "winapi" -version = "0.3.9" +name = "wasm-bindgen-futures" +version = "0.4.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", + "cfg-if", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", ] [[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" +name = "wasm-bindgen-macro" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "web-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +dependencies = [ + "js-sys", + "wasm-bindgen", +] [[package]] name = "winapi-util" -version = "0.1.5" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "windows" +version = "0.54.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9252e5725dbed82865af151df558e754e4a3c2c30818359eb17465f1346a1b49" +dependencies = [ + "windows-core", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.54.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12661b9c89351d684a50a8a643ce5f608e20243b9fb84687800163429f161d65" +dependencies = [ + "windows-result", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" dependencies = [ - "winapi", + "windows-targets 0.42.2", ] [[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06928c8748d81b05c9be96aad92e1b6ff01833332f281e8cfca3be4b35fc9ec" +dependencies = [ + "memchr", +] + +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags 2.9.1", +] [[package]] name = "wyz" -version = "0.2.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] diff --git a/Cargo.toml b/Cargo.toml index 84d28b9..aaf0ab9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,9 +13,9 @@ documentation = "http://docs.rs/rudiments" edition = "2018" [dependencies] -bitvec = "0.18.1" -clap = "3.0.0-beta.5" +bitvec = "1.0.1" +clap = { version = "4.5.38", features = ["derive"] } hound = "3.4.0" nom = "7" -rodio = "0.11.0" +rodio = "0.20.1" thiserror = "1.0" diff --git a/assets/instrumentations/linndrum b/assets/instrumentations/linndrum index 21a1670..b901131 100644 --- a/assets/instrumentations/linndrum +++ b/assets/instrumentations/linndrum @@ -24,4 +24,5 @@ tambourine tamb.wav tom tom.wav tom-high tomh.wav tom-vhigh tomhh.wav -tom-low toml.wav \ No newline at end of file +tom-low toml.wav +sine [internal sound] diff --git a/assets/patterns/standard b/assets/patterns/standard index 78a9dd3..fca9934 100644 --- a/assets/patterns/standard +++ b/assets/patterns/standard @@ -1,3 +1,4 @@ -hi-hat |x-x-|x-x-|x-x-|x-x-| 0.25 -snare |----|x---|----|x---| -kick |x---|----|x---|----| \ No newline at end of file +hi-hat |x-x-|x-x-|x-x-|x-x-|x-x-|x-x-|x-x-|xxx-| 0.25 +snare |----|x---|----|x---|----|x---|----|x---| +kick |x---|----|x---|----|x---|----| +sine |-A-B|-C-D| diff --git a/src/audio.rs b/src/audio.rs index 214e3d3..353e6f1 100644 --- a/src/audio.rs +++ b/src/audio.rs @@ -1,10 +1,11 @@ -use rodio::{self, dynamic_mixer, Source}; -use std::{collections::HashMap, fmt, io::BufReader, path::Path, thread, time::Duration}; +use rodio::{OutputStream, dynamic_mixer, source::Source}; +use std::{collections::HashMap, fmt, path::Path, thread, time::Duration}; use crate::{ error::{Error::*, Result}, - instrumentation::{Instrumentation, SampleFile}, - pattern::{Amplitude, Pattern, Steps, BEATS_PER_MEASURE, STEPS_PER_MEASURE}, + instrumentation::{SampleFile, SampleSource}, + pattern::Amplitude, + steps::Steps, }; /// Number of playback channels. @@ -30,148 +31,113 @@ impl fmt::Display for Tempo { } } -/// A type that represents the fully bound and reduced tracks of a pattern. -type Tracks = HashMap; - -/// Plays a pattern either once or repeatedly at the tempo given using samples -/// found in the given path. -pub fn play( - pattern: Pattern, - instrumentation: Instrumentation, - samples_path: &Path, - tempo: Tempo, - repeat: bool, -) -> Result<()> { - let (tracks, aggregate_steps) = bind_tracks(pattern, instrumentation); - let mix = mix_tracks(&tempo, tracks, samples_path)?; - - if repeat { - play_repeat(&tempo, mix, aggregate_steps) - } else { - play_once(&tempo, mix) +impl Tempo { + /// Computes the duration of a step. + pub fn step_duration(&self, beats: usize) -> Duration { + Duration::from_secs_f32((beats as f32) * 15.0 / (self.0 as f32)) } -} -/// Binds a pattern's step sequences to audio files. -/// An sequences bound to the same audio file will be unioned. -/// The smallest amplitude for instruments bound to the same audio file will be used. -fn bind_tracks(pattern: Pattern, instrumentation: Instrumentation) -> (Tracks, Steps) { - let mut aggregate_steps = Steps::zeros(); - let tracks = instrumentation - .into_iter() - .map(|(sample_file, instruments)| { - let simplified_steps = instruments.iter().fold( - (Steps::zeros(), Amplitude::max()), - |mut acc, instrument| { - if let Some((steps, amplitude)) = pattern.get(instrument) { - // update the aggregate step sequence - aggregate_steps.union(steps); - - // update the track's step sequence and amplitude - acc.0.union(steps); - acc.1 = acc.1.min(amplitude); - } - - acc - }, - ); - - (sample_file, simplified_steps) - }) - .collect(); + /// Computes the duration to delay a mix with trailing silence when played on repeat. + /// This is necessary so that playback of the next iteration begins at the end + /// of the current iteration's measure instead of after its final non-silent step. + fn delay_pad_duration(&self) -> Duration { + self.step_duration(1).mul_f32(self.delay_factor()) * 1 as u32 + } - (tracks, aggregate_steps) + /// Computes a factor necessary for delay-padding a mix played on repeat. + fn delay_factor(&self) -> f32 { + -1.0 / 120.0 * self.0 as f32 + 2.0 + } } -/// Mixes the tracks together using audio files found in the path given. -fn mix_tracks( - tempo: &Tempo, - tracks: Tracks, - samples_path: &Path, -) -> Result + Send>> { - let (controller, mixer) = dynamic_mixer::mixer(CHANNELS, SAMPLE_RATE); - - for (sample_file, (steps, amplitude)) in tracks.iter() { - let sample_file_path = sample_file.with_parent(samples_path)?; - let file = std::fs::File::open(sample_file_path.path())?; - let source = rodio::Decoder::new(BufReader::new(file))?.buffered(); - - for (i, step) in steps.iter().enumerate() { - if !step { - continue; +pub struct Sources(HashMap); + +impl Sources { + /// Mixes the sources together using audio files found in the path given. + pub fn mix( + &self, + tempo: &Tempo, + ) -> Result + Send>> { + let (controller, mixer) = dynamic_mixer::mixer(CHANNELS, SAMPLE_RATE); + for (sample_source, (steps, amplitude)) in self.0.iter() { + for (i, (step_vel, step_freq)) in steps.iter().enumerate() { + if 0 == *step_vel { + continue; + } + let amp_vel = *step_vel as f32 / 256.0 * amplitude.value(); + let delay = tempo.step_duration(1) * (i as u32); + controller.add(sample_source.source(*step_freq).amplify(amp_vel).delay(delay)); } - let delay = step_duration(tempo) * (i as u32); - controller.add(source.clone().amplify(amplitude.value()).delay(delay)); } + Ok(Box::new(mixer)) } +} - Ok(Box::new(mixer)) +/// A type that represents the fully bound and reduced tracks of a pattern. +pub struct Tracks(HashMap); + +impl Tracks { + /// Creates sources using audio files found in the path given. + pub fn sources(&self, samples_path: &Path) -> Result { + let mut sample_map = HashMap::new(); + for (sample_file, (steps, amplitude)) in self.0.iter() { + sample_map.insert( + SampleSource::from(samples_path, sample_file)?, + (steps.clone(), amplitude.clone()) + ); + } + Ok(Sources(sample_map)) + } + + pub fn from(hash_map: HashMap) -> Tracks { + Tracks(hash_map) + } } /// Plays a mixed pattern repeatedly. -fn play_repeat( +pub fn play_repeat( tempo: &Tempo, source: Box + Send>, - aggregate_steps: Steps, + beats: usize, ) -> Result<()> { - if let Some(device) = rodio::default_output_device() { - // compute the amount of trailing silence - let trailing_silence = aggregate_steps.trailing_silent_steps(); - + if let Ok((_stream, stream_handle)) = OutputStream::try_default() { // play the pattern - rodio::play_raw( - &device, + if let Ok(()) = stream_handle.play_raw( source // forward pad with trailing silence - .delay(delay_pad_duration(&tempo, trailing_silence)) + .delay(tempo.delay_pad_duration()) // trim to measure length - .take_duration(measure_duration(&tempo)) + .take_duration(tempo.step_duration(beats)) .repeat_infinite() .convert_samples(), - ); - - // sleep forever - thread::park(); - - Ok(()) + ) { + // sleep forever + thread::park(); + Ok(()) + } else { + Err(AudioDeviceError()) + } } else { Err(AudioDeviceError()) } } /// Plays a mixed pattern once. -fn play_once(tempo: &Tempo, source: Box + Send>) -> Result<()> { - if let Some(device) = rodio::default_output_device() { +pub fn play_once( + tempo: &Tempo, + source: Box + Send>, + beats: usize +) -> Result<()> { + if let Ok((_stream, stream_handle)) = OutputStream::try_default() { // play the pattern - rodio::play_raw(&device, source.convert_samples()); - - // sleep for the duration of a single measure - thread::sleep(measure_duration(tempo)); - - Ok(()) + if let Ok(_) = stream_handle.play_raw(source.convert_samples()) { + // sleep for the duration of a single measure + thread::sleep(tempo.step_duration(beats)); + Ok(()) + } else { + Err(AudioDeviceError()) + } } else { Err(AudioDeviceError()) } } - -/// Computes the duration of a measure. -fn measure_duration(tempo: &Tempo) -> Duration { - Duration::from_secs_f32(1.0 / (tempo.0 as f32 / 60.0 / BEATS_PER_MEASURE as f32)) -} - -/// Computes the duration of a step. -fn step_duration(tempo: &Tempo) -> Duration { - measure_duration(tempo) / STEPS_PER_MEASURE as u32 -} - -/// Computes the duration to delay a mix with trailing silence when played on repeat. -/// This is necessary so that playback of the next iteration begins at the end -/// of the current iteration's measure instead of after its final non-silent step. -fn delay_pad_duration(tempo: &Tempo, trailing_silent_steps: usize) -> Duration { - step_duration(tempo).mul_f32(delay_factor(tempo)) * trailing_silent_steps as u32 -} - -/// Computes a factor necessary for delay-padding a mix played on repeat. -fn delay_factor(tempo: &Tempo) -> f32 { - -1.0 / 120.0 * tempo.0 as f32 + 2.0 -} diff --git a/src/instrumentation.rs b/src/instrumentation.rs index 47bf29a..67678ff 100644 --- a/src/instrumentation.rs +++ b/src/instrumentation.rs @@ -6,12 +6,7 @@ use nom::{ IResult, }; use std::{ - collections::hash_map::IntoIter, - collections::{HashMap, HashSet}, - fmt, - fs::File, - io::{BufRead, BufReader}, - path::{Path, PathBuf}, + collections::{hash_map::IntoIter, HashMap, HashSet}, convert::TryInto, fmt, fs::File, hash::{Hash, Hasher}, io::{BufRead, BufReader}, path::{Path, PathBuf}, time::Duration }; use crate::{ @@ -19,6 +14,17 @@ use crate::{ pattern::Instrument, }; +use rodio::{ + Decoder, + Source, + source::{ + SineWave, + SamplesConverter, + FadeOut, + Buffered + } +}; + /// Represents the contents of an instrumentation file. /// /// An instrumentation file binds the instruments from a pattern file to audio @@ -95,7 +101,94 @@ impl fmt::Display for Instrumentation { /// Represents the location of an audio sample file. #[derive(Debug, Eq, Hash, PartialEq)] -pub struct SampleFile(pub PathBuf); +pub struct SampleFile(PathBuf); + +pub enum SampleSource { + Sample { + file_path: SampleFile, + source: Buffered>> + }, + Synth { + file_path: SampleFile, + source: HashMap, i16>> + }, +} + +impl SampleSource { + pub fn from(samples_path: &Path, sample_file: &SampleFile) -> Result { + if let Ok(sample_file_path) = sample_file.with_parent(samples_path) { + let file = std::fs::File::open(sample_file_path.path())?; + Ok(SampleSource::Sample { + file_path: sample_file_path, + source: rodio::Decoder::new(BufReader::new(file))?.buffered(), + }) + } else { + Ok(SampleSource::Synth { + file_path: SampleFile(samples_path.to_path_buf()), + source: HashMap::from([ + (44000, SineWave::new(440.00).fade_out(Duration::from_millis(50)).convert_samples()), + (49388, SineWave::new(493.88).fade_out(Duration::from_millis(50)).convert_samples()), + (52325, SineWave::new(523.25).fade_out(Duration::from_millis(50)).convert_samples()), + (58733, SineWave::new(587.33).fade_out(Duration::from_millis(50)).convert_samples()), + ]), + }) + } + } + + pub fn source(&self, freq: f32) -> Box + Send + 'static> { + match self { + Self::Sample { file_path: _, source } => Box::new(source.clone()), + Self::Synth { file_path: _, source } => { + let ifreq: u16 = (freq * 100.0).round() as u16; + if let Some(src) = source.get(&ifreq) { + Box::new(src.clone()) + } else { + Box::new(SineWave::new(440.0).fade_out(Duration::from_millis(50)).convert_samples()) + } + }, + } + } +} + +impl PartialEq for SampleSource { + fn eq(&self, other: &Self) -> bool { + match self { + SampleSource::Sample { file_path, source: _ } => { + let file_path0 = file_path; + match other { + SampleSource::Sample { file_path, source: _ } => { + file_path == file_path0 + }, + SampleSource::Synth { file_path, source: _ } => { + file_path == file_path0 + } + } + }, + SampleSource::Synth { file_path, source: _ } => { + let file_path0 = file_path; + match other { + SampleSource::Sample { file_path, source: _ } => { + file_path == file_path0 + }, + SampleSource::Synth { file_path, source: _ } => { + file_path == file_path0 + } + } + } + } + } +} + +impl Eq for SampleSource {} + +impl Hash for SampleSource { + fn hash(&self, state: &mut H) { + match self { + SampleSource::Sample { file_path, source: _ } => file_path.hash(state), + SampleSource::Synth { file_path, source: _ } => file_path.hash(state), + } + } +} impl SampleFile { /// Returns the path of the sample file. diff --git a/src/main.rs b/src/main.rs index 16cc2d2..79ce291 100644 --- a/src/main.rs +++ b/src/main.rs @@ -161,9 +161,11 @@ use std::path::Path; use crate::{error::Result, instrumentation::Instrumentation, pattern::Pattern}; mod audio; +use audio::{play_once, play_repeat, Tempo}; mod error; mod instrumentation; mod pattern; +mod steps; /// A step-sequencing drum machine #[derive(Parser, Debug)] @@ -193,15 +195,23 @@ struct Opts { fn main() -> Result<()> { let opts: Opts = Opts::parse(); let pattern = Pattern::parse(Path::new(&opts.pattern))?; - let instrumentation = Instrumentation::parse(Path::new(&opts.instrumentation))?; - audio::play( - pattern, - instrumentation, - Path::new(&opts.samples), - audio::Tempo::from(opts.tempo), - opts.repeat, + let play = if opts.repeat { + play_repeat + } else { + play_once + }; + + // Plays a pattern either once or repeatedly at the tempo given using samples + // found in the given path. + play( + &Tempo::from(opts.tempo), + pattern + .bind(Instrumentation::parse(Path::new(&opts.instrumentation))?) + .sources(Path::new(&opts.samples))? + .mix(&Tempo::from(opts.tempo))?, + pattern.len() )?; Ok(()) -} +} \ No newline at end of file diff --git a/src/pattern.rs b/src/pattern.rs index f409883..b13814a 100644 --- a/src/pattern.rs +++ b/src/pattern.rs @@ -1,6 +1,5 @@ extern crate nom; -use bitvec::{prelude::*, slice::Iter}; use nom::{ branch::alt, bytes::complete::{is_not, tag}, @@ -18,13 +17,15 @@ use std::{ path::Path, }; -use crate::error::{Error::*, Result}; - -/// The number of steps in a measure. -pub const STEPS_PER_MEASURE: usize = 16; - -/// The number of beats in a measure. -pub const BEATS_PER_MEASURE: usize = 4; +use crate::{ + error::{ + Error::*, + Result + }, + audio::Tracks, + Instrumentation, + steps::Steps, +}; /// Indicates a *play* step. const STEP_PLAY: &str = "x"; @@ -35,6 +36,25 @@ const STEP_SILENT: &str = "-"; /// The beat separator in a step sequence. const SEPARATOR: &str = "|"; +/// The notes +const NOTE_A: &str = "A"; +const NOTE_AS: &str = "A#"; +const NOTE_BF: &str = "Bb"; +const NOTE_B: &str = "B"; +const NOTE_C: &str = "C"; +const NOTE_CS: &str = "C#"; +const NOTE_DF: &str = "Db"; +const NOTE_D: &str = "D"; +const NOTE_DS: &str = "D#"; +const NOTE_EF: &str = "Eb"; +const NOTE_E: &str = "E"; +const NOTE_F: &str = "F"; +const NOTE_FS: &str = "F#"; +const NOTE_GF: &str = "Gb"; +const NOTE_G: &str = "G"; +const NOTE_GS: &str = "G#"; +const NOTE_AF: &str = "Ab"; + /// Reperesents the contents of a pattern file. /// /// Each line of a pattern file represents a track. There is no limit to the number @@ -86,6 +106,47 @@ impl Pattern { pub fn get(&self, i: &Instrument) -> Option<&(Steps, Amplitude)> { self.0.get(i) } + + pub fn len(&self) -> usize { + let mut max_len: usize = 0; + for (_, (s, _)) in self.0.iter() { + if s.len() > max_len { + max_len = s.len(); + } + } + max_len + } + + /// Binds a pattern's step sequences to audio files. + /// Any sequences bound to the same audio file will be unioned. + /// The smallest amplitude for instruments bound to the same audio file will be used. + pub fn bind(&self, instrumentation: Instrumentation) -> Tracks { + let mut aggregate_steps = Steps::zeros(self.len()); + Tracks::from( + instrumentation + .into_iter() + .map(|(sample_file, instruments)| { + let simplified_steps = instruments.iter().fold( + (Steps::zeros(self.len()), Amplitude::max()), + |mut acc, instrument| { + if let Some((steps, amplitude)) = self.get(instrument) { + // update the aggregate step sequence + aggregate_steps = aggregate_steps.union(steps); + + // update the track's step sequence and amplitude + acc.0 = acc.0.union(steps); + acc.1 = acc.1.min(amplitude); + } + + acc + }, + ); + + (sample_file, simplified_steps) + }) + .collect() + ) + } } impl fmt::Display for Pattern { @@ -115,50 +176,8 @@ impl fmt::Display for Instrument { } } -/// The step sequence of a track. -#[derive(Debug, PartialEq)] -pub struct Steps(BitVec); - -impl Steps { - /// Returns a seqence of all zeros. - pub fn zeros() -> Steps { - Steps(bitvec![0; STEPS_PER_MEASURE]) - } - - /// Performs an in-place stepwise union of this sequence and the one given. - pub fn union(&mut self, other: &Steps) { - self.0 |= other.0.clone(); - } - - /// Returns an immutable iterator over the step values. - pub fn iter(&self) -> Iter { - self.0.iter() - } - - /// Returns the number of silent steps at the end of this sequence. - pub fn trailing_silent_steps(&self) -> usize { - match self.0.iter().rposition(|s| *s) { - Some(n) => STEPS_PER_MEASURE - (n + 1), - None => 0, - } - } -} - -impl From for Steps { - #[inline] - fn from(bs: BitVec) -> Steps { - Steps(bs) - } -} - -impl fmt::Display for Steps { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.0) - } -} - /// Represents a track's amplitude in the range of [0,1] inclusive. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct Amplitude(f32); impl Amplitude { @@ -205,7 +224,7 @@ fn parse_track(s: &str) -> IResult<&str, Track> { s, ( Instrument::from(instrument), - Steps(steps), + steps, Amplitude::defaulting(amplitude), ), )) @@ -217,21 +236,25 @@ fn parse_instrument(s: &str) -> IResult<&str, &str> { } /// Parses the steps from a track line. -fn parse_steps(s: &str) -> IResult<&str, BitVec> { +fn parse_steps(s: &str) -> IResult<&str, Steps> { let p = fold_many1( - alt((tag(STEP_PLAY), tag(STEP_SILENT), tag(SEPARATOR))), - || BitVec::with_capacity(STEPS_PER_MEASURE), - |mut acc: BitVec, i| { + alt((tag(STEP_PLAY), tag(STEP_SILENT), tag(SEPARATOR), tag(NOTE_A), tag(NOTE_B), tag(NOTE_C), tag(NOTE_D))), + || Steps::new(), + |mut acc: Steps, i| { match i { - STEP_PLAY => acc.push(true), - STEP_SILENT => acc.push(false), + STEP_PLAY => acc.push(255, 440.0), + STEP_SILENT => acc.push(0, 0.0), + NOTE_A => acc.push(255, 440.0), + NOTE_B => acc.push(255, 493.88), + NOTE_C => acc.push(255, 523.25), + NOTE_D => acc.push(0x3f, 587.33), _ => (), } acc }, ); - verify(p, |v: &BitVec| v.len() == STEPS_PER_MEASURE)(s) + verify(p, |v: &Steps| v.len() > 0)(s) } /// Parses the amplitude from a track line. @@ -245,6 +268,7 @@ fn parse_amplitude(s: &str) -> IResult<&str, Option> { #[cfg(test)] mod tests { use super::*; + use bitvec::{bitvec, prelude::Lsb0}; #[test] fn test_parse_track() { @@ -255,7 +279,7 @@ mod tests { assert_eq!(r, ""); assert_eq!(l.0, Instrument::from("a")); - assert_eq!(l.1, Steps(bitvec![0; STEPS_PER_MEASURE])); + assert_eq!(l.1, Steps::from(bitvec![0; 16])); } #[test] @@ -285,19 +309,25 @@ mod tests { let s6 = "|x-x-|x-x-|x-x-|x-x-|"; assert!(parse_steps(s1).is_err()); - assert!(parse_steps(s2).is_err()); - assert!(parse_steps(s3).is_err()); + assert_eq!( + parse_steps(s2).unwrap(), + ("", Steps::from(bitvec![0; 4])) + ); + assert_eq!( + parse_steps(s3).unwrap(), + ("", Steps::from(bitvec![0; 17])) + ); assert_eq!( parse_steps(s4).unwrap(), - ("", bitvec![0; STEPS_PER_MEASURE]) + ("", Steps::from(bitvec![0; 16])) ); assert_eq!( parse_steps(s5).unwrap(), - ("", bitvec![1; STEPS_PER_MEASURE]) + ("", Steps::from(bitvec![1; 16])) ); assert_eq!( parse_steps(s6).unwrap(), - ("", bitvec![1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]) + ("", Steps::from(bitvec![1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0])) ); } diff --git a/src/steps.rs b/src/steps.rs new file mode 100644 index 0000000..b133377 --- /dev/null +++ b/src/steps.rs @@ -0,0 +1,57 @@ +use std::{ + fmt, +}; + +#[derive(Debug, PartialEq, Clone)] +pub struct Steps(Vec<(u8, f32)>); // MIDI velocity, frequency + +impl Steps { + pub fn new() -> Steps { + Steps(Vec::new()) + } + + pub fn push(&mut self, vel: u8, freq: f32) { + self.0.push((vel, freq)) + } + + pub fn zeros(steps: usize) -> Steps { + Steps(vec![(0, 0.0); steps]) + } + + pub fn union(&mut self, other: &Steps) -> Steps { + Steps( + self + .iter() + .zip(other.iter()) + .map(|((v1, f1), (v2, f2))| { if *v1 > *v2 { (*v1, *f1) } else { (*v2, *f2) } }) + .collect() + ) + } + + pub fn iter(&self) -> std::slice::Iter<(u8, f32)> { + self.0.iter() + } + + pub fn len(&self) -> usize { + self.0.len() + } +} + +impl fmt::Display for Steps { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.0.len()) + } +} + +use bitvec::prelude::BitVec; +impl From for Steps { + #[inline] + fn from(bs: BitVec) -> Steps { + Steps( + bs + .iter() + .map(|b| { if *b { (255, 440.0) } else { (0, 0.0) }}) + .collect() + ) + } +}