Add audio, fix timing
This commit is contained in:
parent
8bba7b9e1b
commit
70373647fb
|
@ -31,12 +31,43 @@ dependencies = [
|
|||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "allocator-api2"
|
||||
version = "0.2.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f"
|
||||
|
||||
[[package]]
|
||||
name = "alsa"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed7572b7ba83a31e20d1b48970ee402d2e3e0537dcfe0a3ff4d6eb7508617d43"
|
||||
dependencies = [
|
||||
"alsa-sys",
|
||||
"bitflags 2.6.0",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "alsa-sys"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db8fee663d06c4e303404ef5f40488a53e062f89ba8bfed81f42325aafad1527"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "android-activity"
|
||||
version = "0.6.0"
|
||||
|
@ -51,7 +82,7 @@ dependencies = [
|
|||
"jni-sys",
|
||||
"libc",
|
||||
"log",
|
||||
"ndk",
|
||||
"ndk 0.9.0",
|
||||
"ndk-context",
|
||||
"ndk-sys 0.6.0+11769913",
|
||||
"num_enum",
|
||||
|
@ -167,6 +198,24 @@ version = "1.4.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
|
||||
|
||||
[[package]]
|
||||
name = "bindgen"
|
||||
version = "0.70.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"cexpr",
|
||||
"clang-sys",
|
||||
"itertools",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"regex",
|
||||
"rustc-hash",
|
||||
"shlex",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bit-set"
|
||||
version = "0.6.0"
|
||||
|
@ -284,6 +333,15 @@ version = "1.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c"
|
||||
|
||||
[[package]]
|
||||
name = "cexpr"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
|
||||
dependencies = [
|
||||
"nom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
|
@ -308,6 +366,17 @@ version = "1.0.12"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e10e7569f6ca78ef7664d7d651115172d4875c4410c050306bccde856a99a49"
|
||||
|
||||
[[package]]
|
||||
name = "clang-sys"
|
||||
version = "1.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4"
|
||||
dependencies = [
|
||||
"glob",
|
||||
"libc",
|
||||
"libloading",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.20"
|
||||
|
@ -454,6 +523,49 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "coreaudio-rs"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "321077172d79c662f64f5071a03120748d5bb652f5231570141be24cfcd2bace"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"core-foundation-sys",
|
||||
"coreaudio-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "coreaudio-sys"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2ce857aa0b77d77287acc1ac3e37a05a8c95a2af3647d23b15f263bdaeb7562b"
|
||||
dependencies = [
|
||||
"bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cpal"
|
||||
version = "0.15.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "873dab07c8f743075e57f524c583985fbaf745602acbe916a01539364369a779"
|
||||
dependencies = [
|
||||
"alsa",
|
||||
"core-foundation-sys",
|
||||
"coreaudio-rs",
|
||||
"dasp_sample",
|
||||
"jni",
|
||||
"js-sys",
|
||||
"libc",
|
||||
"mach2",
|
||||
"ndk 0.8.0",
|
||||
"ndk-context",
|
||||
"oboe",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"web-sys",
|
||||
"windows 0.54.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.20"
|
||||
|
@ -477,6 +589,12 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dasp_sample"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f"
|
||||
|
||||
[[package]]
|
||||
name = "dispatch"
|
||||
version = "0.2.0"
|
||||
|
@ -513,6 +631,12 @@ version = "0.1.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f25c0e292a7ca6d6498557ff1df68f32c99850012b6ea401cf8daf771f22ff53"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.1"
|
||||
|
@ -588,6 +712,12 @@ dependencies = [
|
|||
"xml-rs",
|
||||
]
|
||||
|
||||
[[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"
|
||||
|
@ -638,7 +768,7 @@ dependencies = [
|
|||
"presser",
|
||||
"thiserror",
|
||||
"winapi",
|
||||
"windows",
|
||||
"windows 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -773,6 +903,15 @@ version = "1.70.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jni"
|
||||
version = "0.21.1"
|
||||
|
@ -885,6 +1024,15 @@ version = "0.4.22"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
|
||||
|
||||
[[package]]
|
||||
name = "mach2"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "malloc_buf"
|
||||
version = "0.0.6"
|
||||
|
@ -924,6 +1072,12 @@ dependencies = [
|
|||
"paste",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "minimal-lexical"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||
|
||||
[[package]]
|
||||
name = "mint"
|
||||
version = "0.5.9"
|
||||
|
@ -951,6 +1105,20 @@ dependencies = [
|
|||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ndk"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2076a31b7010b17a38c01907c45b945e8f11495ee4dd588309718901b1f7a5b7"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"jni-sys",
|
||||
"log",
|
||||
"ndk-sys 0.5.0+25.2.9519653",
|
||||
"num_enum",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ndk"
|
||||
version = "0.9.0"
|
||||
|
@ -990,6 +1158,54 @@ dependencies = [
|
|||
"jni-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "7.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"minimal-lexical",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-complex"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-derive"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.46"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_enum"
|
||||
version = "0.7.3"
|
||||
|
@ -1223,6 +1439,29 @@ dependencies = [
|
|||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "oboe"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e8b61bebd49e5d43f5f8cc7ee2891c16e0f41ec7954d36bcb6c14c5e0de867fb"
|
||||
dependencies = [
|
||||
"jni",
|
||||
"ndk 0.8.0",
|
||||
"ndk-context",
|
||||
"num-derive",
|
||||
"num-traits",
|
||||
"oboe-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "oboe-sys"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c8bb09a4a2b1d668170cfe0a7d5bc103f8999fb316c98099b6a9939c9f2e79d"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.20.2"
|
||||
|
@ -1341,6 +1580,15 @@ version = "0.3.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa"
|
||||
|
||||
[[package]]
|
||||
name = "primal-check"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc0d895b311e3af9902528fbb8f928688abbd95872819320517cc24ca6b2bd08"
|
||||
dependencies = [
|
||||
"num-integer",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-crate"
|
||||
version = "3.2.0"
|
||||
|
@ -1395,6 +1643,15 @@ version = "0.6.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539"
|
||||
|
||||
[[package]]
|
||||
name = "realfft"
|
||||
version = "3.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "390252372b7f2aac8360fc5e72eba10136b166d6faeed97e6d0c8324eb99b2b1"
|
||||
dependencies = [
|
||||
"rustfft",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.4.1"
|
||||
|
@ -1413,18 +1670,80 @@ dependencies = [
|
|||
"bitflags 2.6.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
||||
|
||||
[[package]]
|
||||
name = "renderdoc-sys"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832"
|
||||
|
||||
[[package]]
|
||||
name = "rtrb"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3f94e84c073f3b85d4012b44722fa8842b9986d741590d4f2636ad0a5b14143"
|
||||
|
||||
[[package]]
|
||||
name = "rubato"
|
||||
version = "0.16.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdd96992d7e24b3d7f35fdfe02af037a356ac90d41b466945cf3333525a86eea"
|
||||
dependencies = [
|
||||
"num-complex",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
"realfft",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||
|
||||
[[package]]
|
||||
name = "rustfft"
|
||||
version = "6.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43806561bc506d0c5d160643ad742e3161049ac01027b5e6d7524091fd401d86"
|
||||
dependencies = [
|
||||
"num-complex",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
"primal-check",
|
||||
"strength_reduce",
|
||||
"transpose",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.38.38"
|
||||
|
@ -1506,10 +1825,16 @@ dependencies = [
|
|||
"bytemuck",
|
||||
"cc",
|
||||
"clap",
|
||||
"cpal",
|
||||
"imgui",
|
||||
"imgui-wgpu",
|
||||
"imgui-winit-support",
|
||||
"itertools",
|
||||
"num-derive",
|
||||
"num-traits",
|
||||
"pollster",
|
||||
"rtrb",
|
||||
"rubato",
|
||||
"wgpu",
|
||||
"winit",
|
||||
]
|
||||
|
@ -1587,6 +1912,12 @@ version = "1.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||
|
||||
[[package]]
|
||||
name = "strength_reduce"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fe895eb47f22e2ddd4dabc02bce419d2e643c8e3b585c78158b349195bc24d82"
|
||||
|
||||
[[package]]
|
||||
name = "strict-num"
|
||||
version = "0.1.1"
|
||||
|
@ -1708,6 +2039,16 @@ version = "0.1.32"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
|
||||
|
||||
[[package]]
|
||||
name = "transpose"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ad61aed86bc3faea4300c7aee358b4c6d0c8d6ccc36524c96e4c92ccf26e77e"
|
||||
dependencies = [
|
||||
"num-integer",
|
||||
"strength_reduce",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ttf-parser"
|
||||
version = "0.25.0"
|
||||
|
@ -2111,7 +2452,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",
|
||||
]
|
||||
|
||||
|
@ -2124,6 +2475,25 @@ dependencies = [
|
|||
"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"
|
||||
|
@ -2351,7 +2721,7 @@ dependencies = [
|
|||
"js-sys",
|
||||
"libc",
|
||||
"memmap2",
|
||||
"ndk",
|
||||
"ndk 0.9.0",
|
||||
"objc2",
|
||||
"objc2-app-kit",
|
||||
"objc2-foundation",
|
||||
|
|
|
@ -7,10 +7,16 @@ edition = "2021"
|
|||
anyhow = "1"
|
||||
bytemuck = { version = "1", features = ["derive"] }
|
||||
clap = { version = "4", features = ["derive"] }
|
||||
cpal = "0.15"
|
||||
imgui = "0.12"
|
||||
imgui-wgpu = { git = "https://github.com/Yatekii/imgui-wgpu-rs", rev = "2edd348" }
|
||||
imgui-winit-support = "0.13"
|
||||
itertools = "0.13"
|
||||
num-derive = "0.4"
|
||||
num-traits = "0.2"
|
||||
pollster = "0.4"
|
||||
rtrb = "0.3"
|
||||
rubato = "0.16"
|
||||
wgpu = "22.1"
|
||||
winit = "0.30"
|
||||
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
use anyhow::{bail, Result};
|
||||
use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
|
||||
use itertools::Itertools;
|
||||
use rubato::{FftFixedInOut, Resampler};
|
||||
|
||||
pub struct Audio {
|
||||
#[allow(unused)]
|
||||
stream: cpal::Stream,
|
||||
sampler: FftFixedInOut<f32>,
|
||||
input_buffer: Vec<Vec<f32>>,
|
||||
output_buffer: Vec<Vec<f32>>,
|
||||
sample_sink: rtrb::Producer<f32>,
|
||||
}
|
||||
|
||||
impl Audio {
|
||||
pub fn init() -> Result<Self> {
|
||||
let host = cpal::default_host();
|
||||
let Some(device) = host.default_output_device() else {
|
||||
bail!("No output device available");
|
||||
};
|
||||
let Some(config) = device
|
||||
.supported_output_configs()?
|
||||
.find(|c| c.channels() == 2 && c.sample_format().is_float())
|
||||
else {
|
||||
bail!("No suitable output config available");
|
||||
};
|
||||
let mut config = config.with_max_sample_rate().config();
|
||||
let sampler = FftFixedInOut::new(41700, config.sample_rate.0 as usize, 834, 2)?;
|
||||
config.buffer_size = cpal::BufferSize::Fixed(sampler.output_frames_max() as u32);
|
||||
|
||||
let input_buffer = sampler.input_buffer_allocate(true);
|
||||
let output_buffer = sampler.output_buffer_allocate(true);
|
||||
let (sample_sink, mut sample_source) =
|
||||
rtrb::RingBuffer::new(sampler.output_frames_max() * 4);
|
||||
|
||||
let stream = device.build_output_stream(
|
||||
&config,
|
||||
move |data: &mut [f32], _| {
|
||||
let requested = data.len();
|
||||
let chunk = match sample_source.read_chunk(data.len()) {
|
||||
Ok(c) => c,
|
||||
Err(rtrb::chunks::ChunkError::TooFewSlots(n)) => {
|
||||
sample_source.read_chunk(n).unwrap()
|
||||
}
|
||||
};
|
||||
let len = chunk.len();
|
||||
let (first, second) = chunk.as_slices();
|
||||
data[0..first.len()].copy_from_slice(first);
|
||||
data[first.len()..len].copy_from_slice(second);
|
||||
for rest in &mut data[len..requested] {
|
||||
*rest = 0.0;
|
||||
}
|
||||
chunk.commit_all();
|
||||
},
|
||||
move |err| eprintln!("stream error: {err}"),
|
||||
None,
|
||||
)?;
|
||||
stream.play()?;
|
||||
Ok(Self {
|
||||
stream,
|
||||
sampler,
|
||||
input_buffer,
|
||||
output_buffer,
|
||||
sample_sink,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn update(&mut self, samples: &[f32]) {
|
||||
for sample in samples.chunks_exact(2) {
|
||||
for (channel, value) in self.input_buffer.iter_mut().zip(sample) {
|
||||
channel.push(*value);
|
||||
}
|
||||
if self.input_buffer[0].len() >= self.sampler.input_frames_next() {
|
||||
let (_, output_samples) = self
|
||||
.sampler
|
||||
.process_into_buffer(&self.input_buffer, &mut self.output_buffer, None)
|
||||
.unwrap();
|
||||
|
||||
let chunk = match self.sample_sink.write_chunk_uninit(output_samples * 2) {
|
||||
Ok(c) => c,
|
||||
Err(rtrb::chunks::ChunkError::TooFewSlots(n)) => {
|
||||
self.sample_sink.write_chunk_uninit(n).unwrap()
|
||||
}
|
||||
};
|
||||
let interleaved = self.output_buffer[0]
|
||||
.iter()
|
||||
.interleave(self.output_buffer[1].iter())
|
||||
.cloned();
|
||||
chunk.fill_from_iter(interleaved);
|
||||
|
||||
for channel in &mut self.input_buffer {
|
||||
channel.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while self.sample_sink.slots() < self.sampler.output_frames_max() * 2 {
|
||||
std::hint::spin_loop();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,29 +1,60 @@
|
|||
use std::{
|
||||
fs,
|
||||
path::Path,
|
||||
path::{Path, PathBuf},
|
||||
sync::mpsc::{self, TryRecvError},
|
||||
};
|
||||
|
||||
use anyhow::Result;
|
||||
|
||||
use crate::{renderer::GameRenderer, shrooms_vb_core::CoreVB};
|
||||
use crate::{audio::Audio, renderer::GameRenderer, shrooms_vb_core::CoreVB};
|
||||
|
||||
pub struct EmulatorBuilder {
|
||||
rom: Option<PathBuf>,
|
||||
commands: mpsc::Receiver<EmulatorCommand>,
|
||||
}
|
||||
|
||||
impl EmulatorBuilder {
|
||||
pub fn new() -> (Self, EmulatorClient) {
|
||||
let (queue, commands) = mpsc::channel();
|
||||
let builder = Self {
|
||||
rom: None,
|
||||
commands,
|
||||
};
|
||||
let client = EmulatorClient { queue };
|
||||
(builder, client)
|
||||
}
|
||||
|
||||
pub fn with_rom(self, path: &Path) -> Self {
|
||||
Self {
|
||||
rom: Some(path.into()),
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build(self) -> Result<Emulator> {
|
||||
let mut emulator = Emulator::new(self.commands)?;
|
||||
if let Some(path) = self.rom {
|
||||
emulator.load_rom(&path)?;
|
||||
}
|
||||
Ok(emulator)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Emulator {
|
||||
sim: CoreVB,
|
||||
audio: Audio,
|
||||
commands: mpsc::Receiver<EmulatorCommand>,
|
||||
renderer: Option<GameRenderer>,
|
||||
}
|
||||
|
||||
impl Emulator {
|
||||
pub fn new() -> (Self, EmulatorClient) {
|
||||
let (sink, source) = mpsc::channel();
|
||||
let emu = Emulator {
|
||||
fn new(commands: mpsc::Receiver<EmulatorCommand>) -> Result<Self> {
|
||||
Ok(Self {
|
||||
sim: CoreVB::new(),
|
||||
commands: source,
|
||||
audio: Audio::init()?,
|
||||
commands,
|
||||
renderer: None,
|
||||
};
|
||||
let queue = EmulatorClient { queue: sink };
|
||||
(emu, queue)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn load_rom(&mut self, path: &Path) -> Result<()> {
|
||||
|
@ -34,6 +65,7 @@ impl Emulator {
|
|||
|
||||
pub fn run(&mut self) {
|
||||
let mut eye_contents = vec![0u8; 384 * 224 * 2];
|
||||
let mut audio_samples = vec![];
|
||||
loop {
|
||||
self.sim.emulate_frame();
|
||||
if let Some(renderer) = &mut self.renderer {
|
||||
|
@ -41,6 +73,11 @@ impl Emulator {
|
|||
renderer.render(&eye_contents);
|
||||
}
|
||||
}
|
||||
self.sim.read_samples(&mut audio_samples);
|
||||
if !audio_samples.is_empty() {
|
||||
self.audio.update(&audio_samples);
|
||||
audio_samples.clear();
|
||||
}
|
||||
loop {
|
||||
match self.commands.try_recv() {
|
||||
Ok(command) => self.handle_command(command),
|
||||
|
|
|
@ -3,10 +3,11 @@ use std::{path::PathBuf, thread};
|
|||
use anyhow::Result;
|
||||
use app::App;
|
||||
use clap::Parser;
|
||||
use emulator::Emulator;
|
||||
use emulator::EmulatorBuilder;
|
||||
use winit::event_loop::{ControlFlow, EventLoop};
|
||||
|
||||
mod app;
|
||||
mod audio;
|
||||
mod emulator;
|
||||
mod renderer;
|
||||
mod shrooms_vb_core;
|
||||
|
@ -19,9 +20,10 @@ struct Args {
|
|||
fn main() -> Result<()> {
|
||||
let args = Args::parse();
|
||||
|
||||
let (mut emulator, client) = Emulator::new();
|
||||
emulator.load_rom(&args.rom)?;
|
||||
let (builder, client) = EmulatorBuilder::new();
|
||||
let builder = builder.with_rom(&args.rom);
|
||||
thread::spawn(move || {
|
||||
let mut emulator = builder.build().unwrap();
|
||||
emulator.run();
|
||||
});
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use std::{ffi::c_void, ptr};
|
||||
use std::{ffi::c_void, ptr, slice};
|
||||
|
||||
use anyhow::{anyhow, Result};
|
||||
use num_derive::{FromPrimitive, ToPrimitive};
|
||||
|
||||
#[repr(C)]
|
||||
struct VB {
|
||||
|
@ -9,6 +10,20 @@ struct VB {
|
|||
|
||||
#[allow(non_camel_case_types)]
|
||||
type c_int = i32;
|
||||
#[allow(non_camel_case_types)]
|
||||
type c_uint = u32;
|
||||
|
||||
#[repr(u32)]
|
||||
#[derive(FromPrimitive, ToPrimitive)]
|
||||
enum VBDataType {
|
||||
S8 = 0,
|
||||
U8 = 1,
|
||||
S16 = 2,
|
||||
U16 = 3,
|
||||
S32 = 4,
|
||||
F32 = 5,
|
||||
}
|
||||
|
||||
type OnFrame = extern "C" fn(sim: *mut VB) -> c_int;
|
||||
|
||||
#[link(name = "vb")]
|
||||
|
@ -27,6 +42,13 @@ extern "C" {
|
|||
right_stride_x: c_int,
|
||||
right_stride_y: c_int,
|
||||
);
|
||||
#[link_name = "vbGetSamples"]
|
||||
fn vb_get_samples(
|
||||
sim: *mut VB,
|
||||
typ_: *mut VBDataType,
|
||||
capacity: *mut c_uint,
|
||||
position: *mut c_uint,
|
||||
) -> *mut c_void;
|
||||
#[link_name = "vbGetUserData"]
|
||||
fn vb_get_user_data(sim: *mut VB) -> *mut c_void;
|
||||
#[link_name = "vbInit"]
|
||||
|
@ -39,6 +61,13 @@ extern "C" {
|
|||
fn vb_set_keys(sim: *mut VB, keys: u16) -> u16;
|
||||
#[link_name = "vbSetFrameCallback"]
|
||||
fn vb_set_frame_callback(sim: *mut VB, on_frame: OnFrame);
|
||||
#[link_name = "vbSetSamples"]
|
||||
fn vb_set_samples(
|
||||
sim: *mut VB,
|
||||
samples: *mut c_void,
|
||||
typ_: VBDataType,
|
||||
capacity: c_uint,
|
||||
) -> c_int;
|
||||
#[link_name = "vbSetUserData"]
|
||||
fn vb_set_user_data(sim: *mut VB, tag: *mut c_void);
|
||||
#[link_name = "vbSizeOf"]
|
||||
|
@ -53,6 +82,9 @@ extern "C" fn on_frame(sim: *mut VB) -> i32 {
|
|||
1
|
||||
}
|
||||
|
||||
const AUDIO_CAPACITY_SAMPLES: usize = 834 * 4;
|
||||
const AUDIO_CAPACITY_FLOATS: usize = AUDIO_CAPACITY_SAMPLES * 2;
|
||||
|
||||
struct VBState {
|
||||
frame_seen: bool,
|
||||
}
|
||||
|
@ -79,6 +111,11 @@ impl CoreVB {
|
|||
unsafe { vb_set_user_data(sim, Box::into_raw(Box::new(state)).cast()) };
|
||||
unsafe { vb_set_frame_callback(sim, on_frame) };
|
||||
|
||||
// set up audio buffer
|
||||
let audio_buffer = vec![0.0f32; AUDIO_CAPACITY_FLOATS];
|
||||
let samples: *mut c_void = Box::into_raw(audio_buffer.into_boxed_slice()).cast();
|
||||
unsafe { vb_set_samples(sim, samples, VBDataType::F32, AUDIO_CAPACITY_SAMPLES as u32) };
|
||||
|
||||
CoreVB { sim }
|
||||
}
|
||||
|
||||
|
@ -138,6 +175,25 @@ impl CoreVB {
|
|||
true
|
||||
}
|
||||
|
||||
pub fn read_samples(&mut self, samples: &mut Vec<f32>) {
|
||||
let mut position = 0;
|
||||
let ptr =
|
||||
unsafe { vb_get_samples(self.sim, ptr::null_mut(), ptr::null_mut(), &mut position) };
|
||||
// SAFETY: position is an offset in a buffer of (f32, f32). so, position * 2 is an offset in a buffer of f32.
|
||||
let read_samples: &mut [f32] =
|
||||
unsafe { slice::from_raw_parts_mut(ptr.cast(), position as usize * 2) };
|
||||
samples.extend_from_slice(read_samples);
|
||||
|
||||
unsafe {
|
||||
vb_set_samples(
|
||||
self.sim,
|
||||
ptr,
|
||||
VBDataType::F32,
|
||||
AUDIO_CAPACITY_SAMPLES as u32,
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
pub fn set_keys(&mut self, keys: u16) {
|
||||
unsafe { vb_set_keys(self.sim, keys) };
|
||||
}
|
||||
|
@ -145,6 +201,14 @@ impl CoreVB {
|
|||
|
||||
impl Drop for CoreVB {
|
||||
fn drop(&mut self) {
|
||||
let ptr =
|
||||
unsafe { vb_get_samples(self.sim, ptr::null_mut(), ptr::null_mut(), ptr::null_mut()) };
|
||||
// SAFETY: the audio buffer originally came from a Vec<u32>
|
||||
let floats: Vec<f32> = unsafe {
|
||||
Vec::from_raw_parts(ptr.cast(), AUDIO_CAPACITY_FLOATS, AUDIO_CAPACITY_FLOATS)
|
||||
};
|
||||
drop(floats);
|
||||
|
||||
// SAFETY: the *mut VB owns its userdata.
|
||||
// There is no way for the userdata to be null or otherwise invalid.
|
||||
let ptr: *mut VBState = unsafe { vb_get_user_data(self.sim).cast() };
|
||||
|
|
Loading…
Reference in New Issue