diff options
author | Astatin <[email protected]> | 2025-08-06 15:59:22 +0200 |
---|---|---|
committer | Astatin <[email protected]> | 2025-08-06 15:59:22 +0200 |
commit | 70b95279579146bf46910257f8e0ecb1ff62b24f (patch) | |
tree | 0152abe0e1899fd3dd246571456c2713a7735170 | |
parent | a5b89a18526a5b56b74f3ced3d0ebe6ad35a4551 (diff) |
Dynamically adapt audio speed to keep latency low
-rw-r--r-- | Cargo.lock | 512 | ||||
-rw-r--r-- | Cargo.toml | 3 | ||||
-rw-r--r-- | src/consts.rs | 4 | ||||
-rw-r--r-- | src/desktop/audio.rs | 85 | ||||
-rw-r--r-- | src/io.rs | 22 | ||||
-rw-r--r-- | src/logs.rs | 4 | ||||
-rw-r--r-- | src/main.rs | 2 |
7 files changed, 319 insertions, 313 deletions
@@ -32,15 +32,6 @@ dependencies = [ ] [[package]] -name = "aho-corasick" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" -dependencies = [ - "memchr", -] - -[[package]] name = "allocator-api2" version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -48,14 +39,14 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "alsa" -version = "0.7.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8512c9117059663fb5606788fbca3619e2a91dac0e3fe516242eab1fa6be5e44" +checksum = "ed7572b7ba83a31e20d1b48970ee402d2e3e0537dcfe0a3ff4d6eb7508617d43" dependencies = [ "alsa-sys", - "bitflags 1.3.2", + "bitflags 2.9.1", + "cfg-if", "libc", - "nix 0.24.3", ] [[package]] @@ -75,17 +66,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee91c0c2905bae44f84bfa4e044536541df26b7703fd0888deeb9060fcc44289" dependencies = [ "android-properties", - "bitflags 2.4.0", + "bitflags 2.9.1", "cc", "cesu8", - "jni 0.21.1", + "jni", "jni-sys", "libc", "log", "ndk 0.8.0", "ndk-context", "ndk-sys 0.5.0+25.2.9519653", - "num_enum 0.7.3", + "num_enum", "thiserror", ] @@ -193,26 +184,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] -name = "bindgen" -version = "0.64.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4243e6031260db77ede97ad86c27e501d646a27ab57b59a574f725d98ab1fb4" -dependencies = [ - "bitflags 1.3.2", - "cexpr", - "clang-sys", - "lazy_static", - "lazycell", - "peeking_take_while", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex", - "syn 1.0.109", -] - -[[package]] name = "bit-set" version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -235,9 +206,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.0" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" [[package]] name = "block" @@ -261,7 +232,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "15b55663a85f33501257357e6421bb33e769d5c9ffb5ba0921c975a123e35e68" dependencies = [ "block-sys", - "objc2", + "objc2 0.4.1", ] [[package]] @@ -288,7 +259,7 @@ version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fba7adb4dd5aa98e5553510223000e7148f621165ec5f9acd7113f6ca4995298" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.9.1", "log", "polling", "rustix", @@ -324,15 +295,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" [[package]] -name = "cexpr" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" -dependencies = [ - "nom", -] - -[[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -345,17 +307,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" [[package]] -name = "clang-sys" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f" -dependencies = [ - "glob", - "libc", - "libloading 0.7.4", -] - -[[package]] name = "clap" version = "4.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -468,18 +419,12 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ - "core-foundation-sys 0.8.7", + "core-foundation-sys", "libc", ] [[package]] name = "core-foundation-sys" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" - -[[package]] -name = "core-foundation-sys" version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" @@ -510,47 +455,42 @@ dependencies = [ [[package]] name = "coreaudio-rs" -version = "0.11.2" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb17e2d1795b1996419648915df94bc7103c28f7b48062d7acf4652fc371b2ff" +checksum = "1aae284fbaf7d27aa0e292f7677dfbe26503b0d555026f702940805a630eac17" dependencies = [ "bitflags 1.3.2", - "core-foundation-sys 0.6.2", - "coreaudio-sys", -] - -[[package]] -name = "coreaudio-sys" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f034b2258e6c4ade2f73bf87b21047567fb913ee9550837c2316d139b0262b24" -dependencies = [ - "bindgen", + "libc", + "objc2-audio-toolbox", + "objc2-core-audio", + "objc2-core-audio-types", + "objc2-core-foundation", ] [[package]] name = "cpal" -version = "0.15.2" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d959d90e938c5493000514b446987c07aed46c668faaa7d34d6c7a67b1a578c" +checksum = "cbd307f43cc2a697e2d1f8bc7a1d824b5269e052209e28883e5bc04d095aaa3f" dependencies = [ "alsa", - "core-foundation-sys 0.8.7", "coreaudio-rs", "dasp_sample", - "jni 0.19.0", + "jni", "js-sys", "libc", "mach2", - "ndk 0.7.0", + "ndk 0.9.0", "ndk-context", - "oboe", - "once_cell", - "parking_lot", + "num-derive", + "num-traits", + "objc2-audio-toolbox", + "objc2-core-audio", + "objc2-core-audio-types", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "windows 0.46.0", + "windows 0.54.0", ] [[package]] @@ -571,7 +511,7 @@ version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e3d747f100290a1ca24b752186f61f6637e1deffe3bf6320de6fcb29510a307" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.9.1", "libloading 0.8.6", "winapi", ] @@ -589,6 +529,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" [[package]] +name = "dispatch2" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" +dependencies = [ + "bitflags 2.9.1", + "objc2 0.6.1", +] + +[[package]] name = "dlib" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -608,6 +558,7 @@ name = "emulator" version = "0.1.0" dependencies = [ "clap", + "cpal", "gilrs", "pixels", "rodio", @@ -710,7 +661,7 @@ dependencies = [ "libc", "libudev-sys", "log", - "nix 0.26.2", + "nix", "uuid", "vec_map", "wasm-bindgen", @@ -730,12 +681,6 @@ dependencies = [ ] [[package]] -name = "glob" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" - -[[package]] name = "glow" version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -762,7 +707,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.9.1", "gpu-alloc-types", ] @@ -772,7 +717,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98ff03b468aa837d70984d55f5d3f846f6ec31fe34bbb97c4f85219caeee1ca4" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.9.1", ] [[package]] @@ -794,7 +739,7 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc11df1ace8e7e564511f53af41f3e42ddc95b56fd07b3f4445d2a6048bc682c" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.9.1", "gpu-descriptor-types", "hashbrown", ] @@ -805,7 +750,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6bf0b36e6f090b7e1d8a4b49c0cb81c1f8376f72198c65dd3ad9ff3556b8b78c" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.9.1", ] [[package]] @@ -824,7 +769,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af2a7e73e1f34c48da31fb668a907f250794837e08faa144fd24f0b8b741e890" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.9.1", "com", "libc", "libloading 0.8.6", @@ -865,7 +810,7 @@ checksum = "99d3aaff8a54577104bafdf686ff18565c3b6903ca5782a2026ef06e2c7aa319" dependencies = [ "block2", "dispatch", - "objc2", + "objc2 0.4.1", ] [[package]] @@ -884,7 +829,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b2d4429acc1deff0fbdece0325b4997bdb02b2c245ab7023fd5deca0f6348de" dependencies = [ - "core-foundation-sys 0.8.7", + "core-foundation-sys", "mach2", ] @@ -901,34 +846,6 @@ dependencies = [ [[package]] name = "jni" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6df18c2e3db7e453d3c6ac5b3e9d5182664d28788126d39b91f2d1e22b017ec" -dependencies = [ - "cesu8", - "combine", - "jni-sys", - "log", - "thiserror", - "walkdir", -] - -[[package]] -name = "jni" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "039022cdf4d7b1cf548d31f60ae783138e5fd42013f6271049d7df7afadef96c" -dependencies = [ - "cesu8", - "combine", - "jni-sys", - "log", - "thiserror", - "walkdir", -] - -[[package]] -name = "jni" version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" @@ -986,18 +903,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" [[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - -[[package]] name = "libc" version = "0.2.171" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1029,7 +934,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.9.1", "libc", "redox_syscall 0.5.10", ] @@ -1105,7 +1010,7 @@ version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c43f73953f8cbe511f021b58f18c3ce1c3d1ae13fe953293e13345bf83217f25" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.9.1", "block", "core-graphics-types", "foreign-types", @@ -1115,19 +1020,13 @@ dependencies = [ ] [[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] name = "naga" version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50e3524642f53d9af419ab5e8dd29d3ba155708267667c2f3f06c88c9e130843" dependencies = [ "bit-set", - "bitflags 2.4.0", + "bitflags 2.9.1", "codespan-reporting", "hexf-parse", "indexmap", @@ -1142,30 +1041,30 @@ dependencies = [ [[package]] name = "ndk" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "451422b7e4718271c8b5b3aadf5adedba43dc76312454b387e98fae0fc951aa0" +checksum = "2076a31b7010b17a38c01907c45b945e8f11495ee4dd588309718901b1f7a5b7" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.9.1", "jni-sys", - "ndk-sys 0.4.1+23.1.7779620", - "num_enum 0.5.11", - "raw-window-handle 0.5.2", + "log", + "ndk-sys 0.5.0+25.2.9519653", + "num_enum", + "raw-window-handle", "thiserror", ] [[package]] name = "ndk" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2076a31b7010b17a38c01907c45b945e8f11495ee4dd588309718901b1f7a5b7" +checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.9.1", "jni-sys", "log", - "ndk-sys 0.5.0+25.2.9519653", - "num_enum 0.7.3", - "raw-window-handle 0.6.2", + "ndk-sys 0.6.0+11769913", + "num_enum", "thiserror", ] @@ -1177,15 +1076,6 @@ checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" [[package]] name = "ndk-sys" -version = "0.4.1+23.1.7779620" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cf2aae958bd232cac5069850591667ad422d263686d75b52a065f9badeee5a3" -dependencies = [ - "jni-sys", -] - -[[package]] -name = "ndk-sys" version = "0.5.0+25.2.9519653" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c196769dd60fd4f363e11d948139556a344e79d451aeb2fa2fd040738ef7691" @@ -1194,14 +1084,12 @@ dependencies = [ ] [[package]] -name = "nix" -version = "0.24.3" +name = "ndk-sys" +version = "0.6.0+11769913" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" +checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" dependencies = [ - "bitflags 1.3.2", - "cfg-if", - "libc", + "jni-sys", ] [[package]] @@ -1217,63 +1105,62 @@ dependencies = [ ] [[package]] -name = "nom" -version = "7.1.3" +name = "num-bigint" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ - "memchr", - "minimal-lexical", + "num-integer", + "num-traits", ] [[package]] name = "num-derive" -version = "0.3.3" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.100", ] [[package]] -name = "num-traits" -version = "0.2.15" +name = "num-integer" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", + "num-traits", ] [[package]] -name = "num_enum" -version = "0.5.11" +name = "num-rational" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" dependencies = [ - "num_enum_derive 0.5.11", + "num-bigint", + "num-integer", + "num-traits", ] [[package]] -name = "num_enum" -version = "0.7.3" +name = "num-traits" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ - "num_enum_derive 0.7.3", + "autocfg", ] [[package]] -name = "num_enum_derive" -version = "0.5.11" +name = "num_enum" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" +checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn 1.0.109", + "num_enum_derive", ] [[package]] @@ -1311,7 +1198,64 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "559c5a40fdd30eb5e344fbceacf7595a81e242529fb4e21cf5f43fb4f11ff98d" dependencies = [ "objc-sys", - "objc2-encode", + "objc2-encode 3.0.0", +] + +[[package]] +name = "objc2" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88c6597e14493ab2e44ce58f2fdecf095a51f12ca57bec060a11c57332520551" +dependencies = [ + "objc2-encode 4.1.0", +] + +[[package]] +name = "objc2-audio-toolbox" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10cbe18d879e20a4aea544f8befe38bcf52255eb63d3f23eca2842f3319e4c07" +dependencies = [ + "bitflags 2.9.1", + "libc", + "objc2 0.6.1", + "objc2-core-audio", + "objc2-core-audio-types", + "objc2-core-foundation", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-audio" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca44961e888e19313b808f23497073e3f6b3c22bb485056674c8b49f3b025c82" +dependencies = [ + "dispatch2", + "objc2 0.6.1", + "objc2-core-audio-types", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-core-audio-types" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0f1cc99bb07ad2ddb6527ddf83db6a15271bb036b3eb94b801cd44fdc666ee1" +dependencies = [ + "bitflags 2.9.1", + "objc2 0.6.1", +] + +[[package]] +name = "objc2-core-foundation" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c10c2894a6fed806ade6027bcd50662746363a9589d3ec9d9bef30a4e4bc166" +dependencies = [ + "bitflags 2.9.1", + "dispatch2", + "objc2 0.6.1", ] [[package]] @@ -1321,33 +1265,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d079845b37af429bfe5dfa76e6d087d788031045b25cfc6fd898486fd9847666" [[package]] -name = "objc_exception" -version = "0.1.2" +name = "objc2-encode" +version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad970fb455818ad6cba4c122ad012fae53ae8b4795f86378bce65e4f6bab2ca4" -dependencies = [ - "cc", -] +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" [[package]] -name = "oboe" -version = "0.5.0" +name = "objc2-foundation" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8868cc237ee02e2d9618539a23a8d228b9bb3fc2e7a5b11eed3831de77c395d0" +checksum = "900831247d2fe1a09a683278e5384cfb8c80c79fe6b166f9d14bfdde0ea1b03c" dependencies = [ - "jni 0.20.0", - "ndk 0.7.0", - "ndk-context", - "num-derive", - "num-traits", - "oboe-sys", + "objc2 0.6.1", ] [[package]] -name = "oboe-sys" -version = "0.5.0" +name = "objc_exception" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f44155e7fb718d3cfddcf70690b2b51ac4412f347cd9e4fbe511abe9cd7b5f2" +checksum = "ad970fb455818ad6cba4c122ad012fae53ae8b4795f86378bce65e4f6bab2ca4" dependencies = [ "cc", ] @@ -1406,12 +1342,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] -name = "peeking_take_while" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" - -[[package]] name = "percent-encoding" version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1431,7 +1361,7 @@ checksum = "518d43cd70c5381d4c7bd4bf47ee344beee99b58b0587adcb198cc713ff0dfb5" dependencies = [ "bytemuck", "pollster", - "raw-window-handle 0.6.2", + "raw-window-handle", "thiserror", "ultraviolet", "wgpu", @@ -1521,12 +1451,6 @@ checksum = "c3d6831663a5098ea164f89cff59c6284e95f4e3c76ce9848d4529f5ccca9bde" [[package]] name = "raw-window-handle" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" - -[[package]] -name = "raw-window-handle" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" @@ -1546,39 +1470,10 @@ version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1" dependencies = [ - "bitflags 2.4.0", -] - -[[package]] -name = "regex" -version = "1.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", + "bitflags 2.9.1", ] [[package]] -name = "regex-automata" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83d3daa6976cffb758ec878f108ba0e062a45b2d6ca3a2cca965338855476caf" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab07dc67230e4a4718e70fd5c20055a4334b121f1f9db8fe63ef39ce9b8c846" - -[[package]] name = "renderdoc-sys" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1586,11 +1481,13 @@ checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" [[package]] name = "rodio" -version = "0.17.1" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdf1d4dea18dff2e9eb6dca123724f8b60ef44ad74a9ad283cdfe025df7e73fa" +checksum = "e40ecf59e742e03336be6a3d53755e789fd05a059fa22dfa0ed624722319e183" dependencies = [ "cpal", + "dasp_sample", + "num-rational", ] [[package]] @@ -1605,7 +1502,7 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.9.1", "errno", "libc", "linux-raw-sys", @@ -1682,12 +1579,6 @@ dependencies = [ ] [[package]] -name = "shlex" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" - -[[package]] name = "slab" version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1717,7 +1608,7 @@ version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "922fd3eeab3bd820d76537ce8f582b1cf951eceb5475c28500c7457d9d17f53a" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.9.1", "calloop", "calloop-wayland-source", "cursor-icon", @@ -1751,7 +1642,7 @@ version = "0.3.0+sdk-1.3.268.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.9.1", ] [[package]] @@ -2051,7 +1942,7 @@ version = "0.31.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2120de3d33638aaef5b9f4472bff75f07c56379cf76ea320bd3a3d65ecaf73f" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.9.1", "rustix", "wayland-backend", "wayland-scanner", @@ -2063,7 +1954,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.9.1", "cursor-icon", "wayland-backend", ] @@ -2085,7 +1976,7 @@ version = "0.31.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f81f365b8b4a97f422ac0e8737c438024b5951734506b0e1d775c73030561f4" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.9.1", "wayland-backend", "wayland-client", "wayland-scanner", @@ -2097,7 +1988,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23803551115ff9ea9bce586860c5c5a971e360825a0309264102a9495a5ff479" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.9.1", "wayland-backend", "wayland-client", "wayland-protocols", @@ -2110,7 +2001,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad1f61b76b6c2d8742e10f9ba5c3737f6530b4c243132c2a2ccc8aa96fe25cd6" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.9.1", "wayland-backend", "wayland-client", "wayland-protocols", @@ -2184,7 +2075,7 @@ dependencies = [ "naga", "parking_lot", "profiling", - "raw-window-handle 0.6.2", + "raw-window-handle", "smallvec", "static_assertions", "wasm-bindgen", @@ -2203,7 +2094,7 @@ checksum = "28b94525fc99ba9e5c9a9e24764f2bc29bad0911a7446c12f446a8277369bf3a" dependencies = [ "arrayvec", "bit-vec", - "bitflags 2.4.0", + "bitflags 2.9.1", "cfg_aliases", "codespan-reporting", "indexmap", @@ -2212,7 +2103,7 @@ dependencies = [ "once_cell", "parking_lot", "profiling", - "raw-window-handle 0.6.2", + "raw-window-handle", "rustc-hash", "smallvec", "thiserror", @@ -2231,7 +2122,7 @@ dependencies = [ "arrayvec", "ash", "bit-set", - "bitflags 2.4.0", + "bitflags 2.9.1", "block", "cfg_aliases", "core-graphics-types", @@ -2255,7 +2146,7 @@ dependencies = [ "parking_lot", "profiling", "range-alloc", - "raw-window-handle 0.6.2", + "raw-window-handle", "renderdoc-sys", "rustc-hash", "smallvec", @@ -2272,7 +2163,7 @@ version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b671ff9fb03f78b46ff176494ee1ebe7d603393f42664be55b64dc8d53969805" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.9.1", "js-sys", "web-sys", ] @@ -2339,7 +2230,17 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" dependencies = [ - "windows-core", + "windows-core 0.52.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows" +version = "0.54.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9252e5725dbed82865af151df558e754e4a3c2c30818359eb17465f1346a1b49" +dependencies = [ + "windows-core 0.54.0", "windows-targets 0.52.6", ] @@ -2353,6 +2254,25 @@ dependencies = [ ] [[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" @@ -2566,7 +2486,7 @@ dependencies = [ "ahash", "android-activity", "atomic-waker", - "bitflags 2.4.0", + "bitflags 2.9.1", "bytemuck", "calloop", "cfg_aliases", @@ -2580,11 +2500,11 @@ dependencies = [ "memmap2", "ndk 0.8.0", "ndk-sys 0.5.0+25.2.9519653", - "objc2", + "objc2 0.4.1", "once_cell", "orbclient", "percent-encoding", - "raw-window-handle 0.6.2", + "raw-window-handle", "redox_syscall 0.3.5", "rustix", "sctk-adwaita", @@ -2668,7 +2588,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.9.1", "dlib", "log", "once_cell", @@ -7,7 +7,8 @@ authors = ["Astatin <astatin@redacted>"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -rodio = { version = "0.17", default-features = false, features = [] } +rodio = { version = "0.21", default-features = false, features = ["playback"] } +cpal = "0.16" gilrs = "0.10.2" clap = { version = "4.3.21", features = ["derive"] } pixels = "0.15" diff --git a/src/consts.rs b/src/consts.rs index 2b93133..3e464e3 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -8,5 +8,5 @@ pub const DISPLAY_UPDATE_SLEEP_TIME_MICROS: u64 = ((1000000 / DISPLAY_UPDATE_RATE) as f64 / SPEEDUP_FACTOR) as u64; pub const CPU_CLOCK_SPEED: u64 = 4_194_304; -pub const CPU_CYCLE_LENGTH_NANOS: u64 = - ((1_000_000_000 / CPU_CLOCK_SPEED) as f64 / SPEEDUP_FACTOR) as u64; +pub const CPU_CYCLE_LENGTH_NANOS: f64 = + ((1_000_000_000. / CPU_CLOCK_SPEED as f64) / SPEEDUP_FACTOR) as f64; diff --git a/src/desktop/audio.rs b/src/desktop/audio.rs index a6905f8..42dc129 100644 --- a/src/desktop/audio.rs +++ b/src/desktop/audio.rs @@ -1,15 +1,63 @@ -use rodio::{OutputStream, Sink, Source}; +use rodio::{Sink, Source}; +use rodio::stream::{OutputStreamBuilder, OutputStream}; +use cpal::BufferSize; use crate::audio::{MutableWave, SAMPLE_RATE}; use crate::io::{Audio, Wave}; +use crate::logs::{log, LogLevel}; use std::mem; -use std::time::Duration; +use std::time::{SystemTime, Duration}; + +const BUFFER_SIZE: usize = 256; +const RODIO_BUFFER_SIZE: usize = 1024; +const RODIO_BUFFER_SINK_LATE_EXPECTED: f32 = 0.; +const LATE_SPEEDUP_INTENSITY_INV: f32 = 2048.0; +const SPEEDUP_SKIP_LIMIT: f32 = 1.008; + +const TIME_RING_BUFFER_SIZE: usize = (SAMPLE_RATE as usize / BUFFER_SIZE) * 10; +struct SpeedFinder { + buf: [SystemTime; TIME_RING_BUFFER_SIZE], + i: usize, + has_circled: bool, +} + +impl SpeedFinder { + fn new() -> Self { + Self { + buf: [SystemTime::now(); TIME_RING_BUFFER_SIZE], + i: 0, + has_circled: false, + } + } + + fn tick(&mut self) -> Option<f32> { + if self.i >= TIME_RING_BUFFER_SIZE { + self.i = 0; + self.has_circled = true; + } -const BUFFER_SIZE: usize = 1024; + let previous = self.buf[self.i]; + let now = SystemTime::now(); + + self.buf[self.i] = now; + self.i += 1; + if !self.has_circled { + if self.i == 1 { + return None; + } else { + return Some(now.duration_since(self.buf[0]).unwrap().as_secs_f32() / (self.i - 1) as f32); + } + } else { + return Some(now.duration_since(previous).unwrap().as_secs_f32() / TIME_RING_BUFFER_SIZE as f32); + } + } +} pub struct RodioAudio { - _stream: OutputStream, sink: Sink, + stream: OutputStream, + + speed_finder: SpeedFinder, wave: RodioWave<MutableWave>, buffer: Box<[f32; BUFFER_SIZE]>, buffer_i: usize, @@ -40,7 +88,7 @@ impl<I: Iterator<Item = f32>> Iterator for RodioBuffer<I> { } impl<I: Iterator<Item = f32>> Source for RodioBuffer<I> { - fn current_frame_len(&self) -> Option<usize> { + fn current_span_len(&self) -> Option<usize> { None } @@ -59,17 +107,18 @@ impl<I: Iterator<Item = f32>> Source for RodioBuffer<I> { impl Audio for RodioAudio { fn new(wave: MutableWave) -> Self { - let (stream, stream_handle) = OutputStream::try_default().unwrap(); + let stream = OutputStreamBuilder::from_default_device().unwrap().with_sample_rate(SAMPLE_RATE).with_buffer_size(BufferSize::Fixed(RODIO_BUFFER_SIZE as u32)).open_stream().unwrap(); - let sink = Sink::try_new(&stream_handle).unwrap(); + let sink = Sink::connect_new(stream.mixer()); let wave = RodioWave(wave, 0); RodioAudio { - _stream: stream, + speed_finder: SpeedFinder::new(), sink: sink, wave, buffer: Box::new([0.0; BUFFER_SIZE]), buffer_i: 0, + stream, } } @@ -82,6 +131,26 @@ impl Audio for RodioAudio { self.buffer_i = 0; let mut buffer = Box::new([0.0; BUFFER_SIZE]); mem::swap(&mut self.buffer, &mut buffer); + if let Some(speed) = self.speed_finder.tick() { + let mut late_speedup: f32; + let rodio_buffers_sink_late = self.sink.len() as f32 / (RODIO_BUFFER_SIZE / BUFFER_SIZE) as f32; + late_speedup = ((rodio_buffers_sink_late - RODIO_BUFFER_SINK_LATE_EXPECTED).powi(3) / LATE_SPEEDUP_INTENSITY_INV) + 1.; + + if late_speedup > SPEEDUP_SKIP_LIMIT { + while late_speedup > 1.0 { + let rodio_buffers_sink_late = self.sink.len() as f32 / (RODIO_BUFFER_SIZE / BUFFER_SIZE) as f32; + late_speedup = ((rodio_buffers_sink_late - RODIO_BUFFER_SINK_LATE_EXPECTED).powi(3) / LATE_SPEEDUP_INTENSITY_INV) + 1.; + + self.sink.skip_one(); + } + late_speedup = 1.; + } + let average_speed = (1./speed) / (2 * SAMPLE_RATE / BUFFER_SIZE as u32) as f32; + let rodio_buffers_sink_late = self.sink.len() as f32 / (RODIO_BUFFER_SIZE / BUFFER_SIZE) as f32; + log(LogLevel::AudioLatency, format!("audio sink latency: {}ms", (1000. * rodio_buffers_sink_late / ((2*SAMPLE_RATE) as f32 / RODIO_BUFFER_SIZE as f32)))); + + self.sink.set_speed(late_speedup * average_speed); + } self.sink.append(RodioBuffer(buffer.into_iter())); } } @@ -164,11 +164,21 @@ impl<I: Input, W: Window, S: Serial, A: Audio, LS: LoadSave> Gameboy<I, W, S, A, let mut last_ram_bank_enabled = false; let mut now = SystemTime::now(); + let mut last_halt_cycle = now; + let mut last_halt_cycle_counter: u128 = 0; let mut next_precise_gamepad_update: Option<u128> = None; while !state.is_stopped { if was_previously_halted && !state.mem.halt { - log(LogLevel::HaltCycles, format!("Halt cycles {}", halt_time)); + let n = SystemTime::now(); + log( + LogLevel::HaltCycles, + format!( + "Halt cycles {} (system average speed: {}Hz)", + halt_time, + last_halt_cycle_counter as f32 / n.duration_since(last_halt_cycle).unwrap().as_secs_f32(), + ) + ); halt_time = 0; } was_previously_halted = state.mem.halt; @@ -179,6 +189,7 @@ impl<I: Input, W: Window, S: Serial, A: Audio, LS: LoadSave> Gameboy<I, W, S, A, 4 }; + last_halt_cycle_counter += c as u128; state.cpu.dbg_cycle_counter += c; total_cycle_counter += c as u128; audio_counter += c; @@ -194,7 +205,7 @@ impl<I: Input, W: Window, S: Serial, A: Audio, LS: LoadSave> Gameboy<I, W, S, A, state.check_interrupts(); state.mem.update_serial(total_cycle_counter); - nanos_sleep += c as f64 * (consts::CPU_CYCLE_LENGTH_NANOS as f64 / *speed) as f64; + nanos_sleep += c as f64 * (consts::CPU_CYCLE_LENGTH_NANOS / *speed) as f64; if nanos_sleep >= 0.0 || next_precise_gamepad_update.map_or(false, |c| (c >= total_cycle_counter)) @@ -233,11 +244,12 @@ impl<I: Input, W: Window, S: Serial, A: Audio, LS: LoadSave> Gameboy<I, W, S, A, } } - thread::sleep(time::Duration::from_nanos(nanos_sleep as u64 / 10)); + thread::sleep(time::Duration::from_nanos(1)); //nanos_sleep as u64)); + let new_now = SystemTime::now(); nanos_sleep = - nanos_sleep - SystemTime::now().duration_since(now).unwrap().as_nanos() as f64; - now = SystemTime::now(); + nanos_sleep - new_now.duration_since(now).unwrap().as_nanos() as f64; + now = new_now; if last_ram_bank_enabled && !state.mem.ram_bank_enabled { if let Err(err) = load_save.save_external_ram(state.mem.external_ram.as_ref()) { diff --git a/src/logs.rs b/src/logs.rs index 4eefc3e..cf00cae 100644 --- a/src/logs.rs +++ b/src/logs.rs @@ -7,6 +7,7 @@ pub enum LogLevel { Debug, OpcodeDump, HaltCycles, + AudioLatency, Error, } @@ -31,6 +32,9 @@ pub fn set_log_level(verbosity: String) { "errors" => { set.insert(LogLevel::Error); } + "audio_latency" => { + set.insert(LogLevel::AudioLatency); + } "none" => {} _ => panic!("Unknown log level \"{}\"", level), } diff --git a/src/main.rs b/src/main.rs index ee815f8..3f71987 100644 --- a/src/main.rs +++ b/src/main.rs @@ -84,7 +84,7 @@ struct Cli { #[arg(long, default_value_t = false)] no_response: bool, - /// Verbosity. Coma separated values (possible values: infos,debug,opcode_dump,halt_cycles,errors,none) + /// Verbosity. Coma separated values (possible values: infos,debug,opcode_dump,halt_cycles,audio_latency,errors,none) #[arg(short, long, default_value = "infos,errors")] verbosity: String, } |