A multiplayer VR framework w/voice chat

audio working with kira. going to attempt a different audio backend

phaz.uk c73631e1 3d34f6e9

verified
Changed files
+279 -733
audio
client
+73 -413
Cargo.lock
··· 290 290 ] 291 291 292 292 [[package]] 293 + name = "atomic-arena" 294 + version = "0.1.2" 295 + source = "registry+https://github.com/rust-lang/crates.io-index" 296 + checksum = "73e8ed45f88ed32e6827a96b62d8fd4086d72defc754c5c6bd08470c1aaf648e" 297 + 298 + [[package]] 293 299 name = "atomic-waker" 294 300 version = "1.1.2" 295 301 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 306 312 dependencies = [ 307 313 "portable-atomic", 308 314 "portable-atomic-util", 309 - ] 310 - 311 - [[package]] 312 - name = "audionimbus-sys" 313 - version = "4.7.0" 314 - source = "registry+https://github.com/rust-lang/crates.io-index" 315 - checksum = "fb5d2e6b2a80ceca3ed697ddf6d11389a70a2186ae02e8038278469097d4ec44" 316 - dependencies = [ 317 - "bindgen 0.71.1", 318 315 ] 319 316 320 317 [[package]] ··· 936 933 "approx", 937 934 "bevy_reflect", 938 935 "derive_more", 939 - "glam 0.30.9", 936 + "glam", 940 937 "itertools 0.14.0", 941 938 "libm", 942 939 "rand 0.9.2", ··· 1111 1108 "downcast-rs 2.0.2", 1112 1109 "erased-serde", 1113 1110 "foldhash 0.2.0", 1114 - "glam 0.30.9", 1111 + "glam", 1115 1112 "inventory", 1116 1113 "petgraph", 1117 1114 "serde", ··· 1220 1217 ] 1221 1218 1222 1219 [[package]] 1223 - name = "bevy_seedling" 1224 - version = "0.6.1" 1225 - source = "registry+https://github.com/rust-lang/crates.io-index" 1226 - checksum = "cb0d2bb3af43e45ea318865e49cf2c33e32f32a986fcaf6d7a4e73a093ce1766" 1227 - dependencies = [ 1228 - "bevy_app", 1229 - "bevy_asset", 1230 - "bevy_ecs", 1231 - "bevy_log", 1232 - "bevy_math", 1233 - "bevy_platform", 1234 - "bevy_reflect", 1235 - "bevy_seedling_macros", 1236 - "bevy_time", 1237 - "bevy_transform", 1238 - "ebur128", 1239 - "firewheel", 1240 - "firewheel-ircam-hrtf", 1241 - "portable-atomic", 1242 - "rand 0.9.2", 1243 - "smallvec", 1244 - "symphonia", 1245 - "symphonium", 1246 - ] 1247 - 1248 - [[package]] 1249 - name = "bevy_seedling_macros" 1250 - version = "0.6.0" 1251 - source = "registry+https://github.com/rust-lang/crates.io-index" 1252 - checksum = "71af121c6c880413f48ce79a217312bb951d2b07cbd3f654dc93211c12bd7c05" 1253 - dependencies = [ 1254 - "bevy_macro_utils", 1255 - "proc-macro2", 1256 - "quote", 1257 - "syn", 1258 - ] 1259 - 1260 - [[package]] 1261 1220 name = "bevy_shader" 1262 1221 version = "0.17.3" 1263 1222 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1566 1525 1567 1526 [[package]] 1568 1527 name = "bindgen" 1569 - version = "0.71.1" 1570 - source = "registry+https://github.com/rust-lang/crates.io-index" 1571 - checksum = "5f58bf3d7db68cfbac37cfc485a8d711e87e064c3d0fe0435b92f7a407f9d6b3" 1572 - dependencies = [ 1573 - "bitflags 2.10.0", 1574 - "cexpr", 1575 - "clang-sys", 1576 - "itertools 0.13.0", 1577 - "log", 1578 - "prettyplease", 1579 - "proc-macro2", 1580 - "quote", 1581 - "regex", 1582 - "rustc-hash 2.1.1", 1583 - "shlex", 1584 - "syn", 1585 - ] 1586 - 1587 - [[package]] 1588 - name = "bindgen" 1589 1528 version = "0.72.1" 1590 1529 source = "registry+https://github.com/rust-lang/crates.io-index" 1591 1530 checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895" ··· 1981 1920 source = "registry+https://github.com/rust-lang/crates.io-index" 1982 1921 checksum = "ceec7a6067e62d6f931a2baf6f3a751f4a892595bcec1461a3c94ef9949864b6" 1983 1922 dependencies = [ 1984 - "bindgen 0.72.1", 1923 + "bindgen", 1985 1924 ] 1986 1925 1987 1926 [[package]] ··· 2119 2058 checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f" 2120 2059 2121 2060 [[package]] 2122 - name = "dasp_frame" 2123 - version = "0.11.0" 2124 - source = "registry+https://github.com/rust-lang/crates.io-index" 2125 - checksum = "b2a3937f5fe2135702897535c8d4a5553f8b116f76c1529088797f2eee7c5cd6" 2126 - dependencies = [ 2127 - "dasp_sample", 2128 - ] 2129 - 2130 - [[package]] 2131 2061 name = "dasp_sample" 2132 2062 version = "0.11.0" 2133 2063 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2229 2159 checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76" 2230 2160 2231 2161 [[package]] 2232 - name = "ebur128" 2233 - version = "0.1.10" 2234 - source = "registry+https://github.com/rust-lang/crates.io-index" 2235 - checksum = "e227cc62d64d6fe01abbef48134b9c1f17d470cef1e7a56337ad05b1f81df7f9" 2236 - dependencies = [ 2237 - "bitflags 1.3.2", 2238 - "dasp_frame", 2239 - "dasp_sample", 2240 - "smallvec", 2241 - ] 2242 - 2243 - [[package]] 2244 2162 name = "either" 2245 2163 version = "1.15.0" 2246 2164 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2254 2172 dependencies = [ 2255 2173 "const_panic", 2256 2174 "encase_derive", 2257 - "glam 0.30.9", 2175 + "glam", 2258 2176 "thiserror 2.0.17", 2259 2177 ] 2260 2178 ··· 2351 2269 checksum = "af9673d8203fcb076b19dfd17e38b3d4ae9f44959416ea532ce72415a6020365" 2352 2270 2353 2271 [[package]] 2354 - name = "fast-interleave" 2355 - version = "0.1.3" 2356 - source = "registry+https://github.com/rust-lang/crates.io-index" 2357 - checksum = "a0a5ab837f0983c0a9210d7847931f64e3be67fcb0ab93d625f7845a0132c825" 2358 - 2359 - [[package]] 2360 2272 name = "fastrand" 2361 2273 version = "2.3.0" 2362 2274 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2376 2288 version = "0.1.0" 2377 2289 dependencies = [ 2378 2290 "anyhow", 2379 - "audionimbus-sys", 2380 - "cpal 0.16.0", 2381 - "hound", 2291 + "bevy", 2292 + "kira", 2382 2293 ] 2383 2294 2384 2295 [[package]] ··· 2387 2298 dependencies = [ 2388 2299 "anyhow", 2389 2300 "bevy", 2390 - "bevy_seedling", 2391 2301 "cpal 0.16.0", 2392 2302 "dotenvy", 2303 + "felix-audio", 2393 2304 "felix-net", 2394 2305 "tokio", 2395 2306 ] ··· 2420 2331 checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" 2421 2332 2422 2333 [[package]] 2423 - name = "firewheel" 2424 - version = "0.9.2" 2425 - source = "registry+https://github.com/rust-lang/crates.io-index" 2426 - checksum = "b4a3247a4004d294962675375b2f539fb31990563261a385e7ef1353c1addd60" 2427 - dependencies = [ 2428 - "firewheel-core", 2429 - "firewheel-cpal", 2430 - "firewheel-graph", 2431 - "firewheel-nodes", 2432 - "firewheel-pool", 2433 - "thiserror 2.0.17", 2434 - ] 2435 - 2436 - [[package]] 2437 - name = "firewheel-core" 2438 - version = "0.9.2" 2439 - source = "registry+https://github.com/rust-lang/crates.io-index" 2440 - checksum = "9d57ae9ba24554846916e77affb2c9efea35f6d7f39ae2f56329db309f8396a9" 2441 - dependencies = [ 2442 - "arrayvec", 2443 - "bevy_ecs", 2444 - "bevy_platform", 2445 - "bevy_reflect", 2446 - "bitflags 2.10.0", 2447 - "firewheel-macros", 2448 - "fixed-resample", 2449 - "glam 0.29.3", 2450 - "glam 0.30.9", 2451 - "log", 2452 - "num-traits", 2453 - "portable-atomic", 2454 - "ringbuf", 2455 - "rtgc", 2456 - "smallvec", 2457 - "symphonium", 2458 - "thiserror 2.0.17", 2459 - "thunderdome", 2460 - "wmidi", 2461 - ] 2462 - 2463 - [[package]] 2464 - name = "firewheel-cpal" 2465 - version = "0.9.2" 2466 - source = "registry+https://github.com/rust-lang/crates.io-index" 2467 - checksum = "f561251f37171d143922c3b8e45c102f9d79fd9ce4bd6faaa62550af1c5b2b1d" 2468 - dependencies = [ 2469 - "bevy_platform", 2470 - "cpal 0.16.0", 2471 - "fast-interleave", 2472 - "firewheel-core", 2473 - "firewheel-graph", 2474 - "fixed-resample", 2475 - "log", 2476 - "ringbuf", 2477 - "thiserror 2.0.17", 2478 - ] 2479 - 2480 - [[package]] 2481 - name = "firewheel-graph" 2482 - version = "0.9.2" 2483 - source = "registry+https://github.com/rust-lang/crates.io-index" 2484 - checksum = "7730621467abd9aa6a945c6aa11447d5334d9427f0e51699c391e2648b8bc0c8" 2485 - dependencies = [ 2486 - "arrayvec", 2487 - "bevy_platform", 2488 - "bevy_reflect", 2489 - "firewheel-core", 2490 - "log", 2491 - "num-traits", 2492 - "ringbuf", 2493 - "smallvec", 2494 - "thiserror 2.0.17", 2495 - "thunderdome", 2496 - "triple_buffer", 2497 - ] 2498 - 2499 - [[package]] 2500 - name = "firewheel-ircam-hrtf" 2501 - version = "0.2.0" 2502 - source = "registry+https://github.com/rust-lang/crates.io-index" 2503 - checksum = "16ef3ba4e1f227a7247ddc94f5850324010ecf7ecf59ee3af5a2c9fcd326b744" 2504 - dependencies = [ 2505 - "bevy_ecs", 2506 - "bevy_reflect", 2507 - "firewheel", 2508 - "glam 0.30.9", 2509 - "hrtf", 2510 - ] 2511 - 2512 - [[package]] 2513 - name = "firewheel-macros" 2514 - version = "0.9.2" 2515 - source = "registry+https://github.com/rust-lang/crates.io-index" 2516 - checksum = "34833b22730fd510e34b07df943ce4e1495bc4f1d738a959cb31c0431f938b46" 2517 - dependencies = [ 2518 - "bevy_macro_utils", 2519 - "proc-macro2", 2520 - "quote", 2521 - "syn", 2522 - "toml_edit", 2523 - ] 2524 - 2525 - [[package]] 2526 - name = "firewheel-nodes" 2527 - version = "0.9.2" 2528 - source = "registry+https://github.com/rust-lang/crates.io-index" 2529 - checksum = "0513d8c83c24108b8dd8e28f572d5c90a87d085ca81929adb0cff2a62eff0863" 2530 - dependencies = [ 2531 - "bevy_ecs", 2532 - "bevy_platform", 2533 - "bevy_reflect", 2534 - "firewheel-core", 2535 - "fixed-resample", 2536 - "num-traits", 2537 - "smallvec", 2538 - ] 2539 - 2540 - [[package]] 2541 - name = "firewheel-pool" 2542 - version = "0.9.2" 2543 - source = "registry+https://github.com/rust-lang/crates.io-index" 2544 - checksum = "57b3f2122f632fcaff37d9c42e3b33d050199c180d8c13161f9f808a47b009f9" 2545 - dependencies = [ 2546 - "bevy_platform", 2547 - "firewheel-core", 2548 - "firewheel-graph", 2549 - "firewheel-nodes", 2550 - "smallvec", 2551 - "thiserror 2.0.17", 2552 - "thunderdome", 2553 - ] 2554 - 2555 - [[package]] 2556 - name = "fixed-resample" 2557 - version = "0.9.2" 2558 - source = "registry+https://github.com/rust-lang/crates.io-index" 2559 - checksum = "3e548b80c8a294b230847d73ae8e53d1b2d5b407a1a9ec51c9698a761c4610b1" 2560 - dependencies = [ 2561 - "arrayvec", 2562 - "fast-interleave", 2563 - "ringbuf", 2564 - "rubato 0.16.2", 2565 - ] 2566 - 2567 - [[package]] 2568 2334 name = "fixedbitset" 2569 2335 version = "0.5.7" 2570 2336 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2773 2539 2774 2540 [[package]] 2775 2541 name = "glam" 2776 - version = "0.29.3" 2777 - source = "registry+https://github.com/rust-lang/crates.io-index" 2778 - checksum = "8babf46d4c1c9d92deac9f7be466f76dfc4482b6452fc5024b5e8daf6ffeb3ee" 2779 - 2780 - [[package]] 2781 - name = "glam" 2782 2542 version = "0.30.9" 2783 2543 source = "registry+https://github.com/rust-lang/crates.io-index" 2784 2544 checksum = "bd47b05dddf0005d850e5644cae7f2b14ac3df487979dbfff3b56f20b1a6ae46" 2785 2545 dependencies = [ 2786 2546 "bytemuck", 2787 2547 "libm", 2548 + "mint", 2788 2549 "rand 0.9.2", 2789 2550 "serde_core", 2790 2551 ] ··· 2984 2745 checksum = "29a164ceff4500f2a72b1d21beaa8aa8ad83aec2b641844c659b190cb3ea2e0b" 2985 2746 dependencies = [ 2986 2747 "constgebra", 2987 - "glam 0.30.9", 2748 + "glam", 2988 2749 "tinyvec", 2989 2750 ] 2990 2751 ··· 2995 2756 checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" 2996 2757 2997 2758 [[package]] 2998 - name = "hound" 2999 - version = "3.5.1" 3000 - source = "registry+https://github.com/rust-lang/crates.io-index" 3001 - checksum = "62adaabb884c94955b19907d60019f4e145d091c75345379e70d1ee696f7854f" 3002 - 3003 - [[package]] 3004 - name = "hrtf" 3005 - version = "0.8.1" 3006 - source = "registry+https://github.com/rust-lang/crates.io-index" 3007 - checksum = "0f4de47a84fd55fa33aa5ef337016814fdc869fdad23e7898b5322fa290248e6" 3008 - dependencies = [ 3009 - "byteorder", 3010 - "rubato 0.14.1", 3011 - "rustfft", 3012 - ] 3013 - 3014 - [[package]] 3015 2759 name = "image" 3016 2760 version = "0.25.9" 3017 2761 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 3163 2907 version = "3.1.0" 3164 2908 source = "registry+https://github.com/rust-lang/crates.io-index" 3165 2909 checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" 2910 + 2911 + [[package]] 2912 + name = "kira" 2913 + version = "0.11.0" 2914 + source = "registry+https://github.com/rust-lang/crates.io-index" 2915 + checksum = "b8b2ed698ad54d270ee1d8b340604201bf538dacf8bf31e378da00690b9ea20a" 2916 + dependencies = [ 2917 + "atomic-arena", 2918 + "cpal 0.16.0", 2919 + "glam", 2920 + "mint", 2921 + "pastey", 2922 + "rtrb", 2923 + "send_wrapper", 2924 + "symphonia", 2925 + "triple_buffer", 2926 + ] 3166 2927 3167 2928 [[package]] 3168 2929 name = "ktx2" ··· 3340 3101 ] 3341 3102 3342 3103 [[package]] 3104 + name = "mint" 3105 + version = "0.5.9" 3106 + source = "registry+https://github.com/rust-lang/crates.io-index" 3107 + checksum = "e53debba6bda7a793e5f99b8dacf19e626084f525f7829104ba9898f367d85ff" 3108 + 3109 + [[package]] 3343 3110 name = "mio" 3344 3111 version = "1.1.1" 3345 3112 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 3513 3280 ] 3514 3281 3515 3282 [[package]] 3516 - name = "num-complex" 3517 - version = "0.4.6" 3518 - source = "registry+https://github.com/rust-lang/crates.io-index" 3519 - checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" 3520 - dependencies = [ 3521 - "num-traits", 3522 - ] 3523 - 3524 - [[package]] 3525 3283 name = "num-derive" 3526 3284 version = "0.4.2" 3527 3285 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 3530 3288 "proc-macro2", 3531 3289 "quote", 3532 3290 "syn", 3533 - ] 3534 - 3535 - [[package]] 3536 - name = "num-integer" 3537 - version = "0.1.46" 3538 - source = "registry+https://github.com/rust-lang/crates.io-index" 3539 - checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" 3540 - dependencies = [ 3541 - "num-traits", 3542 3291 ] 3543 3292 3544 3293 [[package]] ··· 3972 3721 checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" 3973 3722 3974 3723 [[package]] 3724 + name = "pastey" 3725 + version = "0.1.1" 3726 + source = "registry+https://github.com/rust-lang/crates.io-index" 3727 + checksum = "35fb2e5f958ec131621fdd531e9fc186ed768cbe395337403ae56c17a74c68ec" 3728 + 3729 + [[package]] 3975 3730 name = "percent-encoding" 3976 3731 version = "2.3.2" 3977 3732 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 4100 3855 checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa" 4101 3856 4102 3857 [[package]] 4103 - name = "prettyplease" 4104 - version = "0.2.37" 4105 - source = "registry+https://github.com/rust-lang/crates.io-index" 4106 - checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" 4107 - dependencies = [ 4108 - "proc-macro2", 4109 - "syn", 4110 - ] 4111 - 4112 - [[package]] 4113 - name = "primal-check" 4114 - version = "0.3.4" 4115 - source = "registry+https://github.com/rust-lang/crates.io-index" 4116 - checksum = "dc0d895b311e3af9902528fbb8f928688abbd95872819320517cc24ca6b2bd08" 4117 - dependencies = [ 4118 - "num-integer", 4119 - ] 4120 - 4121 - [[package]] 4122 3858 name = "proc-macro-crate" 4123 3859 version = "3.4.0" 4124 3860 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 4279 4015 ] 4280 4016 4281 4017 [[package]] 4282 - name = "realfft" 4283 - version = "3.5.0" 4284 - source = "registry+https://github.com/rust-lang/crates.io-index" 4285 - checksum = "f821338fddb99d089116342c46e9f1fbf3828dba077674613e734e01d6ea8677" 4286 - dependencies = [ 4287 - "rustfft", 4288 - ] 4289 - 4290 - [[package]] 4291 4018 name = "rectangle-pack" 4292 4019 version = "0.4.2" 4293 4020 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 4356 4083 checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" 4357 4084 4358 4085 [[package]] 4359 - name = "ringbuf" 4360 - version = "0.4.8" 4361 - source = "registry+https://github.com/rust-lang/crates.io-index" 4362 - checksum = "fe47b720588c8702e34b5979cb3271a8b1842c7cb6f57408efa70c779363488c" 4363 - dependencies = [ 4364 - "crossbeam-utils", 4365 - "portable-atomic", 4366 - "portable-atomic-util", 4367 - ] 4368 - 4369 - [[package]] 4370 4086 name = "rodio" 4371 4087 version = "0.20.1" 4372 4088 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 4396 4112 checksum = "6c20b6793b5c2fa6553b250154b78d6d0db37e72700ae35fad9387a46f487c97" 4397 4113 4398 4114 [[package]] 4399 - name = "rtgc" 4400 - version = "0.2.4" 4401 - source = "registry+https://github.com/rust-lang/crates.io-index" 4402 - checksum = "8ff37e188d26f62b595065458583a6a7101a52343b112c10a2b277e7a490247d" 4403 - dependencies = [ 4404 - "bevy_platform", 4405 - ] 4406 - 4407 - [[package]] 4408 - name = "rubato" 4409 - version = "0.14.1" 4410 - source = "registry+https://github.com/rust-lang/crates.io-index" 4411 - checksum = "e6dd52e80cfc21894deadf554a5673002938ae4625f7a283e536f9cf7c17b0d5" 4412 - dependencies = [ 4413 - "num-complex", 4414 - "num-integer", 4415 - "num-traits", 4416 - "realfft", 4417 - ] 4418 - 4419 - [[package]] 4420 - name = "rubato" 4421 - version = "0.16.2" 4115 + name = "rtrb" 4116 + version = "0.3.2" 4422 4117 source = "registry+https://github.com/rust-lang/crates.io-index" 4423 - checksum = "5258099699851cfd0082aeb645feb9c084d9a5e1f1b8d5372086b989fc5e56a1" 4424 - dependencies = [ 4425 - "num-complex", 4426 - "num-integer", 4427 - "num-traits", 4428 - "realfft", 4429 - ] 4118 + checksum = "ad8388ea1a9e0ea807e442e8263a699e7edcb320ecbcd21b4fa8ff859acce3ba" 4430 4119 4431 4120 [[package]] 4432 4121 name = "rustc-hash" ··· 4447 4136 checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" 4448 4137 dependencies = [ 4449 4138 "semver", 4450 - ] 4451 - 4452 - [[package]] 4453 - name = "rustfft" 4454 - version = "6.4.1" 4455 - source = "registry+https://github.com/rust-lang/crates.io-index" 4456 - checksum = "21db5f9893e91f41798c88680037dba611ca6674703c1a18601b01a72c8adb89" 4457 - dependencies = [ 4458 - "num-complex", 4459 - "num-integer", 4460 - "num-traits", 4461 - "primal-check", 4462 - "strength_reduce", 4463 - "transpose", 4464 4139 ] 4465 4140 4466 4141 [[package]] ··· 4767 4442 checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" 4768 4443 4769 4444 [[package]] 4770 - name = "strength_reduce" 4771 - version = "0.2.4" 4772 - source = "registry+https://github.com/rust-lang/crates.io-index" 4773 - checksum = "fe895eb47f22e2ddd4dabc02bce419d2e643c8e3b585c78158b349195bc24d82" 4774 - 4775 - [[package]] 4776 4445 name = "strict-num" 4777 4446 version = "0.1.1" 4778 4447 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 4802 4471 checksum = "5773a4c030a19d9bfaa090f49746ff35c75dfddfa700df7a5939d5e076a57039" 4803 4472 dependencies = [ 4804 4473 "lazy_static", 4474 + "symphonia-bundle-flac", 4475 + "symphonia-bundle-mp3", 4805 4476 "symphonia-codec-pcm", 4806 4477 "symphonia-codec-vorbis", 4807 4478 "symphonia-core", ··· 4811 4482 ] 4812 4483 4813 4484 [[package]] 4485 + name = "symphonia-bundle-flac" 4486 + version = "0.5.5" 4487 + source = "registry+https://github.com/rust-lang/crates.io-index" 4488 + checksum = "c91565e180aea25d9b80a910c546802526ffd0072d0b8974e3ebe59b686c9976" 4489 + dependencies = [ 4490 + "log", 4491 + "symphonia-core", 4492 + "symphonia-metadata", 4493 + "symphonia-utils-xiph", 4494 + ] 4495 + 4496 + [[package]] 4497 + name = "symphonia-bundle-mp3" 4498 + version = "0.5.5" 4499 + source = "registry+https://github.com/rust-lang/crates.io-index" 4500 + checksum = "4872dd6bb56bf5eac799e3e957aa1981086c3e613b27e0ac23b176054f7c57ed" 4501 + dependencies = [ 4502 + "lazy_static", 4503 + "log", 4504 + "symphonia-core", 4505 + "symphonia-metadata", 4506 + ] 4507 + 4508 + [[package]] 4814 4509 name = "symphonia-codec-pcm" 4815 4510 version = "0.5.5" 4816 4511 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 4842 4537 "bytemuck", 4843 4538 "lazy_static", 4844 4539 "log", 4845 - "rustfft", 4846 4540 ] 4847 4541 4848 4542 [[package]] ··· 4892 4586 ] 4893 4587 4894 4588 [[package]] 4895 - name = "symphonium" 4896 - version = "0.6.5" 4897 - source = "registry+https://github.com/rust-lang/crates.io-index" 4898 - checksum = "94700d892b055c7c25e2fc5319b43d59434119627a08a5096cdcd0fe5345914f" 4899 - dependencies = [ 4900 - "fast-interleave", 4901 - "fixed-resample", 4902 - "log", 4903 - "symphonia", 4904 - ] 4905 - 4906 - [[package]] 4907 4589 name = "syn" 4908 4590 version = "2.0.111" 4909 4591 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 5006 4688 dependencies = [ 5007 4689 "cfg-if", 5008 4690 ] 5009 - 5010 - [[package]] 5011 - name = "thunderdome" 5012 - version = "0.6.1" 5013 - source = "registry+https://github.com/rust-lang/crates.io-index" 5014 - checksum = "92e170f93360bf9ae6fe3c31116bbf27adb1d054cedd6bc3d7857e34f2d98d0b" 5015 4691 5016 4692 [[package]] 5017 4693 name = "tiny-skia" ··· 5193 4869 "tracing", 5194 4870 "tracing-subscriber", 5195 4871 "wasm-bindgen", 5196 - ] 5197 - 5198 - [[package]] 5199 - name = "transpose" 5200 - version = "0.2.3" 5201 - source = "registry+https://github.com/rust-lang/crates.io-index" 5202 - checksum = "1ad61aed86bc3faea4300c7aee358b4c6d0c8d6ccc36524c96e4c92ccf26e77e" 5203 - dependencies = [ 5204 - "num-integer", 5205 - "strength_reduce", 5206 4872 ] 5207 4873 5208 4874 [[package]] ··· 6330 5996 version = "0.46.0" 6331 5997 source = "registry+https://github.com/rust-lang/crates.io-index" 6332 5998 checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" 6333 - 6334 - [[package]] 6335 - name = "wmidi" 6336 - version = "4.0.10" 6337 - source = "registry+https://github.com/rust-lang/crates.io-index" 6338 - checksum = "4e55f35b40ad0178422d06e9ba845041baf2faf04627b91fde928d0f6a21c712" 6339 5999 6340 6000 [[package]] 6341 6001 name = "x11-dl"
+2 -3
audio/Cargo.toml
··· 5 5 6 6 [dependencies] 7 7 anyhow = "1.0.100" 8 - cpal = "0.16.0" 9 - hound = "3.5.1" 10 - audionimbus-sys = { version = "4.7.0", features = ["auto-install"] } 8 + bevy = "0.17.3" 9 + kira = "0.11.0"
-23
audio/examples/test.rs
··· 1 - use felix_audio::{AudioThread, source::AudioSource, utils::wav}; 2 - 3 - fn main(){ 4 - let audio = AudioThread::start(); 5 - 6 - let mut source = AudioSource::new(); 7 - 8 - let mut sample_index = 0; 9 - let samples = wav::load_wav_file("/home/phaze/Projects/Projects/felix/audio/out2.wav".into()); 10 - 11 - source.on_request_data(move | output, _ | { 12 - let length = output.len(); 13 - 14 - let input_stream = &samples[sample_index..(sample_index + length)]; 15 - sample_index += length; 16 - 17 - for i in 0..length{ output[i] = input_stream[i] } 18 - }); 19 - 20 - audio.add_source(source); 21 - 22 - loop {} 23 - }
+88 -185
audio/src/lib.rs
··· 1 - use std::{ptr::{null, null_mut}, sync::{Arc, Mutex, mpsc::{Sender, channel}}, thread, vec}; 1 + use std::{f32::consts::TAU, thread, time::Duration}; 2 2 3 - use audionimbus_sys::*; 4 - use cpal::{BufferSize, SampleRate, Stream, StreamConfig, traits::{DeviceTrait, HostTrait, StreamTrait}}; 3 + use bevy::{app::{App, Plugin, Startup, Update}, ecs::{component::Component, system::{Commands, Query}}, math::{Quat, Vec3}, transform::components::Transform}; 4 + use kira::{AudioManager, AudioManagerSettings, Decibels, DefaultBackend, Easing, Mapping, Tween, Value, effect::filter::FilterBuilder, listener::ListenerHandle, sound::static_sound::StaticSoundData, track::{SendTrackBuilder, SpatialTrackBuilder}}; 5 5 6 - use crate::source::AudioSource; 6 + use crate::source::FelixAudioSource; 7 7 8 8 pub mod source; 9 - mod voice; 10 - pub mod utils; 11 9 12 - const CHANNEL_COUNT: u16 = 2; 13 - const SAMPLE_RATE: u32 = 48_000; 14 - const BUFFER_SIZE: u32 = 512; 15 - const DISTANCE_FALLOFF: f32 = 1.0; 10 + fn update_listener_transform( 11 + mut audio_system: Query<&mut FelixAudioComponent>, 12 + listener: Query<(&FelixAudioListener, &Transform)> 13 + ){ 14 + let mut audio_system = audio_system.single_mut().expect("Cannot find FelixAudioComponent, has audio system been initialised?"); 15 + let ( _, listener_transform ) = listener.single().expect("Cannot find FelixAudioListener."); 16 16 17 - pub type Sample = f32; 18 - 19 - enum AudioThreadCommand{ 20 - AddSource(AudioSource) 17 + audio_system.main_listener.set_position(listener_transform.translation, Tween::default()); 18 + audio_system.main_listener.set_orientation(listener_transform.rotation, Tween::default()); 21 19 } 22 20 23 - pub struct AudioThread{ 24 - sender: Sender<AudioThreadCommand>, 25 - stream: Stream 26 - } 21 + fn update_audio_sources( 22 + mut audio_system: Query<&mut FelixAudioComponent>, 23 + sources: Query<(&mut FelixAudioSource, &Transform)>, 24 + ){ 25 + let mut audio_system = audio_system.single_mut().expect("Cannot find FelixAudioComponent, has audio system been initialised?"); 27 26 28 - fn build_context() -> IPLContext{ 29 - let mut context: IPLContext = IPLContext::default(); 30 - unsafe { 31 - iplContextCreate( 32 - &mut IPLContextSettings { 33 - version: STEAMAUDIO_VERSION, 34 - logCallback: None, 35 - allocateCallback: None, 36 - freeCallback: None, 37 - simdLevel: IPLSIMDLevel::IPL_SIMDLEVEL_AVX2, 38 - flags: IPLContextFlags::IPL_CONTEXTFLAGS_FORCE_32BIT 39 - }, 40 - &mut context 41 - ); 27 + for ( mut source, transform ) in sources{ 28 + if source.needs_init(){ 29 + source.init(&mut audio_system); 30 + } else { 31 + source.update(transform); 32 + } 42 33 } 43 - 44 - context 45 34 } 46 35 47 - impl AudioThread{ 48 - pub fn start() -> Self{ 49 - let ( sender, recv ) = channel(); 36 + #[derive(Component)] 37 + pub struct FelixAudioListener; 50 38 51 - let host = cpal::default_host(); 52 - let device = host.default_output_device().expect("No output available."); 39 + #[derive(Component)] 40 + pub struct FelixAudioComponent{ 41 + manager: AudioManager<DefaultBackend>, 42 + main_listener: ListenerHandle 43 + } 53 44 54 - let info = AudioThreadInfo { 55 - sample_rate: SAMPLE_RATE, 56 - buffer_size: BUFFER_SIZE, 57 - channel_count: CHANNEL_COUNT 58 - }; 45 + pub struct FelixAudio; 59 46 60 - let ( request_sender, request_recv ) = channel(); 61 - let ( response_sender, response_recv ) = channel(); 47 + impl Plugin for FelixAudio{ 48 + fn build(&self, app: &mut App) { 49 + app.add_systems(Startup, move | mut commands: Commands | { 50 + let mut manager = AudioManager::<DefaultBackend>::new(AudioManagerSettings::default()).unwrap(); 51 + let main_listener = manager.add_listener(Vec3::default(), Quat::default()).unwrap(); 62 52 63 - let stream = device.build_output_stream( 64 - &(&info).into(), 65 - move | output: &mut [ Sample ], _ |{ 66 - request_sender.send(output.len()).unwrap(); 67 - let dat: Vec<f32> = response_recv.recv().unwrap(); 53 + let handle = FelixAudioComponent { manager, main_listener }; 68 54 69 - for i in 0..output.len(){ output[i] = dat[i]; } 70 - }, 71 - |err| println!("{err:?}"), 72 - None 73 - ).unwrap(); 55 + commands.spawn(handle); 56 + }); 74 57 75 - thread::spawn(move || { 76 - // Audio thread. 77 - let mut audio_settings: IPLAudioSettings = (&info).into(); 58 + app.add_systems(Update, update_listener_transform); 59 + app.add_systems(Update, update_audio_sources); 60 + } 61 + } 78 62 79 - let mut sources: Vec<AudioSource> = vec![]; 80 - let context = build_context(); 63 + pub fn main(){ 64 + let mut manager = AudioManager::<DefaultBackend>::new(AudioManagerSettings::default()).unwrap(); 81 65 82 - let mut hrtf: IPLHRTF = IPLHRTF::default(); 83 - unsafe { 84 - iplHRTFCreate( 85 - &mut *context, 86 - &mut audio_settings, 87 - &mut IPLHRTFSettings { 88 - type_: IPLHRTFType::IPL_HRTFTYPE_DEFAULT, 89 - sofaFileName: null(), 90 - sofaData: null(), 91 - sofaDataSize: 0, 92 - volume: 1.0, 93 - normType: IPLHRTFNormType::IPL_HRTFNORMTYPE_RMS 94 - }, 95 - &mut hrtf 96 - ); 97 - } 66 + let listener = manager.add_listener( 67 + [ 0.0, 0.0, 0.0 ], 68 + Quat::default() 69 + ).unwrap(); 98 70 99 - let mut binaural_effect: IPLBinauralEffect = IPLBinauralEffect::default(); 100 - unsafe { 101 - iplBinauralEffectCreate( 102 - &mut *context, 103 - &mut audio_settings, 104 - &mut IPLBinauralEffectSettings { hrtf: &mut *hrtf }, 105 - &mut binaural_effect 106 - ); 107 - } 71 + let send = manager.add_send_track( 72 + SendTrackBuilder::new() 73 + ).unwrap(); 108 74 109 - while let Ok(length) = request_recv.recv(){ 110 - let mut output = vec![0.0; length]; 111 - 112 - if let Ok(ev) = recv.try_recv(){ 113 - match ev{ 114 - AudioThreadCommand::AddSource(mut source) => { 115 - source.setup(&info); 116 - sources.push(source); 117 - } 118 - } 119 - } 120 - 121 - output.fill(0.0); 122 - for source in &mut sources{ 123 - let input = source.render(output.len(), &info); 124 - 125 - let direction: ( f32, f32, f32 ) = ( 1.0, 0.2, 1.0 ); 126 - 127 - let dist = ( 128 - direction.0 * direction.0 + 129 - direction.1 * direction.1 + 130 - direction.2 * direction.2 131 - ).sqrt(); 132 - 133 - let dist_falloff = (1.0 / (1.0 + DISTANCE_FALLOFF * ( dist - 1.0 ) )).clamp(0.0, 1.0); 134 - 135 - if dist_falloff < 0.05{ return }; // If too far away, skip audio processing. 136 - 137 - let mut input_buffer = IPLAudioBuffer { 138 - numChannels: 1, 139 - numSamples: input.len() as i32, 140 - data: input.as_ptr() as *mut *mut Sample // NOTE: Technically this buffer is interleaved, but it *should* be mono, so we don't need to deinterleave it. 141 - }; 142 - 143 - let staging_container = vec![0.0; input.len() * 2 as usize]; 144 - let mut staging_buffer = IPLAudioBuffer { 145 - numChannels: info.channel_count as i32, 146 - numSamples: input.len() as i32, 147 - data: staging_container.as_slice().as_ptr() as *mut *mut Sample 148 - }; 149 - 150 - let mut binaural_effect_params = IPLBinauralEffectParams { 151 - direction: IPLVector3 { x: direction.0, y: direction.1, z: direction.2 }, 152 - interpolation: IPLHRTFInterpolation::IPL_HRTFINTERPOLATION_NEAREST, 153 - spatialBlend: 1.0, 154 - hrtf: hrtf, 155 - peakDelays: null_mut() 156 - }; 157 - 158 - unsafe { 159 - iplBinauralEffectApply( 160 - binaural_effect, 161 - &mut binaural_effect_params, 162 - &mut input_buffer, 163 - &mut staging_buffer 164 - ); 165 - } 166 - 167 - for i in 0..staging_container.len(){ 168 - output[i] = staging_container[i] * dist_falloff; 169 - } 170 - 171 - unsafe { iplAudioBufferFree(&mut *context, &mut staging_buffer); } 172 - } 173 - 174 - response_sender.send(output).unwrap(); 175 - } 176 - }); 75 + let radius = 50.0; 76 + let mut angle: f32 = 0.0; 177 77 178 - stream.play().unwrap(); 179 - 180 - Self { 181 - sender, 182 - stream 183 - } 184 - } 78 + let mut spatial_track = manager.add_spatial_sub_track( 79 + &listener, 80 + [ 81 + angle.sin() * radius, 82 + 0.0, 83 + angle.cos() * radius 84 + ], 85 + SpatialTrackBuilder::new() 86 + .with_effect( 87 + FilterBuilder::new().cutoff(Value::FromListenerDistance(Mapping { 88 + input_range: ( 0.0, 20.0 ), 89 + output_range: ( 18000.0, 2000.0 ), 90 + easing: Easing::Linear 91 + })) 92 + ).with_send(&send, Value::FromListenerDistance(Mapping { 93 + input_range: ( 0.0, 20.0 ), 94 + output_range: ( Decibels(24.0), Decibels(-60.0) ), 95 + easing: Easing::Linear 96 + })) 97 + ).unwrap(); 185 98 186 - pub fn add_source( &self, source: AudioSource ){ 187 - self.sender.send(AudioThreadCommand::AddSource(source)).unwrap(); 188 - } 189 - } 99 + let sound_data = StaticSoundData::from_file("out.wav").unwrap(); 100 + spatial_track.play(sound_data).unwrap(); 190 101 191 - pub struct AudioThreadInfo{ 192 - pub sample_rate: u32, 193 - pub buffer_size: u32, 194 - pub channel_count: u16 195 - } 102 + loop { 103 + thread::sleep(Duration::from_millis(50)); 196 104 197 - impl Into<IPLAudioSettings> for &AudioThreadInfo{ 198 - fn into(self) -> IPLAudioSettings { 199 - IPLAudioSettings { 200 - samplingRate: self.sample_rate as i32, 201 - frameSize: self.buffer_size as i32 202 - } 203 - } 204 - } 105 + angle += TAU * 0.01; 106 + dbg!(angle); 205 107 206 - impl Into<StreamConfig> for &AudioThreadInfo{ 207 - fn into(self) -> StreamConfig { 208 - StreamConfig { 209 - channels: self.channel_count, 210 - sample_rate: SampleRate(self.sample_rate), 211 - buffer_size: BufferSize::Fixed(self.buffer_size) 212 - } 108 + spatial_track.set_position( 109 + [ 110 + angle.sin() * radius, 111 + 0.0, 112 + angle.cos() * radius 113 + ], 114 + Tween::default() 115 + ); 213 116 } 214 117 }
+25 -37
audio/src/source.rs
··· 1 - use std::ptr::{null, null_mut}; 2 - 3 - use anyhow::bail; 4 - use audionimbus_sys::*; 1 + use bevy::{ecs::component::Component, transform::components::Transform}; 5 2 6 - use crate::{AudioThreadInfo, DISTANCE_FALLOFF, Sample}; 3 + use crate::FelixAudioComponent; 7 4 8 - pub struct AudioSource{ 9 - saturate_cb: Option<Box<dyn FnMut(&mut [ Sample ], &AudioThreadInfo) + Send>>, 5 + pub mod static_source; 10 6 11 - buffer: Vec<Sample> 7 + #[derive(Component)] 8 + pub struct FelixAudioSource{ 9 + inner: Box<dyn AudioSource + Send + Sync + 'static> 12 10 } 13 11 14 - unsafe impl Send for AudioSource {} 15 - 16 - impl AudioSource{ 17 - pub fn new() -> Self{ 18 - Self { 19 - saturate_cb: None, 20 - 21 - buffer: Vec::new() 22 - } 23 - } 24 - 25 - pub fn on_request_data<T>( &mut self, saturate_cb: T ) 26 - where 27 - T: FnMut(&mut [ Sample ], &AudioThreadInfo) + Send + 'static 28 - { 29 - self.saturate_cb = Some(Box::new(saturate_cb)); 12 + impl FelixAudioSource{ 13 + pub fn init( &mut self, audio_system: &mut FelixAudioComponent ){ 14 + self.inner.init(audio_system); 30 15 } 31 16 32 - pub fn handle( &self ) -> AudioSourceHandle{ 33 - AudioSourceHandle { } 17 + pub fn needs_init( &self ) -> bool{ 18 + self.inner.needs_init() 34 19 } 35 20 36 - // Internal stuff, called by audio thread. 37 - pub fn setup( &mut self, audio_settings: &AudioThreadInfo ){ 38 - self.buffer = vec![0.0; audio_settings.buffer_size as usize]; 21 + pub fn update( &mut self, transform: &Transform ){ 22 + self.inner.update(transform); 39 23 } 24 + } 40 25 41 - pub fn render( &mut self, length: usize, info: &AudioThreadInfo ) -> &mut [ Sample ]{ 42 - if let Some(saturate_cb) = &mut self.saturate_cb{ 43 - saturate_cb(&mut self.buffer[0..length], &info); 44 - &mut self.buffer[0..length] 45 - } else{ 46 - &mut self.buffer[0..length] 26 + impl<T> From<T> for FelixAudioSource 27 + where 28 + T: AudioSource + Send + Sync + 'static 29 + { 30 + fn from(value: T) -> Self { 31 + Self { 32 + inner: Box::new(value) 47 33 } 48 34 } 49 35 } 50 36 51 - pub struct AudioSourceHandle{ 52 - 37 + pub trait AudioSource{ 38 + fn init( &mut self, audio_system: &mut FelixAudioComponent ); 39 + fn needs_init( &self ) -> bool; 40 + fn update( &mut self, transform: &Transform ); 53 41 }
+84
audio/src/source/static_source.rs
··· 1 + use std::{sync::{Arc, Mutex}, thread}; 2 + 3 + use bevy::transform::components::Transform; 4 + use kira::{Decibels, Easing, Mapping, Mix, Tween, Value, effect::{filter::FilterBuilder, reverb::ReverbBuilder}, sound::static_sound::StaticSoundData, track::{SendTrackBuilder, SendTrackHandle, SpatialTrackBuilder, SpatialTrackHandle}}; 5 + 6 + use crate::{FelixAudioComponent, source::AudioSource}; 7 + 8 + pub struct StaticAudioSource{ 9 + loaded_sound_data: Arc<Mutex<Option<StaticSoundData>>>, 10 + send_track: Option<SendTrackHandle>, 11 + spatial_track: Option<SpatialTrackHandle> 12 + } 13 + 14 + impl StaticAudioSource{ 15 + pub fn new( path: &'static str ) -> Self{ 16 + let data = Arc::new(Mutex::new(None)); 17 + let data_1 = data.clone(); 18 + 19 + thread::spawn(move || { 20 + let sound_data = StaticSoundData::from_file(&path).unwrap(); 21 + let mut data_1 = data_1.lock().unwrap(); 22 + 23 + *data_1 = Some(sound_data); 24 + println!("Loaded: {}", path); 25 + }); 26 + 27 + Self { 28 + loaded_sound_data: data, 29 + 30 + send_track: None, 31 + spatial_track: None 32 + } 33 + } 34 + } 35 + 36 + impl AudioSource for StaticAudioSource{ 37 + fn init( &mut self, audio_system: &mut FelixAudioComponent ) { 38 + if let Ok(mut lock) = self.loaded_sound_data.try_lock(){ 39 + if lock.is_none(){ return } 40 + let sound_data = lock.take().unwrap(); 41 + 42 + let send_track = audio_system.manager.add_send_track(SendTrackBuilder::new()).unwrap(); 43 + 44 + let mut spatial_track = audio_system.manager.add_spatial_sub_track( 45 + &audio_system.main_listener, 46 + [ 47 + 0.0, 48 + 0.0, 49 + 0.0 50 + ], 51 + SpatialTrackBuilder::new() 52 + .with_effect(FilterBuilder::new().cutoff(Value::FromListenerDistance(Mapping { 53 + input_range: ( 0.0, 20.0 ), 54 + output_range: ( 18000.0, 2000.0 ), 55 + easing: Easing::Linear 56 + }))) 57 + .with_effect(ReverbBuilder::new().mix(Value::FromListenerDistance(Mapping { 58 + input_range: ( 0.0, 100.0 ), 59 + output_range: ( Mix::DRY, Mix::WET ), 60 + easing: Easing::Linear 61 + }))) 62 + .with_send(&send_track, Value::FromListenerDistance(Mapping { 63 + input_range: ( 0.0, 1.0 ), 64 + output_range: ( Decibels(12.0), Decibels(-100.0) ), 65 + easing: Easing::Linear 66 + })) 67 + ).unwrap(); 68 + 69 + spatial_track.play(sound_data.clone()).unwrap(); 70 + 71 + self.send_track = Some(send_track); 72 + self.spatial_track = Some(spatial_track); 73 + } 74 + } 75 + 76 + fn needs_init( &self ) -> bool { 77 + self.spatial_track.is_none() 78 + } 79 + 80 + fn update( &mut self, transform: &Transform ) { 81 + let track = self.spatial_track.as_mut().unwrap(); 82 + track.set_position(transform.translation, Tween::default()); 83 + } 84 + }
-1
audio/src/utils/mod.rs
··· 1 - pub mod wav;
-15
audio/src/utils/wav.rs
··· 1 - pub fn load_wav_file( path: String ) -> Vec<f32>{ 2 - let mut reader = hound::WavReader::open(path).unwrap(); 3 - let spec = reader.spec(); 4 - dbg!(&spec); 5 - 6 - let mut samples = vec![0.0; (reader.len() / spec.channels as u32) as usize]; 7 - let original_samples: Vec<_> = reader.samples::<i16>().map(|x| x.unwrap() as f32 / i16::MAX as f32).collect(); 8 - 9 - for i in 0..samples.len(){ 10 - let j = i * spec.channels as usize; 11 - samples[i] = original_samples[j]; 12 - } 13 - 14 - samples 15 - }
-51
audio/src/voice/mod.rs
··· 1 - use cpal::{BufferSize, SampleRate, SizedSample, Stream, StreamConfig, traits::{DeviceTrait, HostTrait}}; 2 - 3 - // Credits to: https://github.com/TapGhoul/vban_transceiver/blob/main/src/main.rs#L125 4 - // (thanks tap) 5 - 6 - const SAMPLE_RATE: SampleRate = SampleRate(44_100); 7 - const BUFFER_SIZE: BufferSize = BufferSize::Fixed(512); 8 - 9 - pub fn open_mic<T, K>( mut cb: T ) -> anyhow::Result<Stream> 10 - where 11 - T: FnMut(&[K]) + Send + 'static, 12 - K: SizedSample 13 - { 14 - let host = cpal::default_host(); 15 - let mic = host.default_input_device().unwrap(); 16 - 17 - let stream = mic.build_input_stream( 18 - &StreamConfig { 19 - channels: 1, 20 - buffer_size: BUFFER_SIZE, 21 - sample_rate: SAMPLE_RATE 22 - }, 23 - move | data, _ | cb(data), 24 - | err | panic!("{err}"), 25 - None 26 - ).unwrap(); 27 - 28 - Ok(stream) 29 - } 30 - 31 - pub fn open_output<T, K>( mut cb: T ) -> anyhow::Result<Stream> 32 - where 33 - T: FnMut(&mut [K]) + Send + 'static, 34 - K: SizedSample 35 - { 36 - let host = cpal::default_host(); 37 - let output = host.default_output_device().unwrap(); 38 - 39 - let stream = output.build_output_stream( 40 - &StreamConfig { 41 - channels: 1, 42 - sample_rate: SAMPLE_RATE, 43 - buffer_size: BUFFER_SIZE 44 - }, 45 - move | data, _ | cb(data), 46 - | err | panic!("{err}"), 47 - None 48 - ).unwrap(); 49 - 50 - Ok(stream) 51 - }
+1 -1
client/Cargo.toml
··· 6 6 [dependencies] 7 7 anyhow = "1.0.100" 8 8 bevy = "0.17.3" 9 - bevy_seedling = "0.6.1" 10 9 cpal = "0.16.0" 11 10 dotenvy = "0.15.7" 12 11 felix-net = { path = '../net' } 12 + felix-audio = { path = '../audio' } 13 13 tokio = { version = "1.48.0", features = ["full"] }
client/out.wav

This is a binary file and will not be displayed.

-1
client/src/components/network_interface.rs
··· 1 1 use std::collections::HashMap; 2 2 3 3 use bevy::prelude::*; 4 - use bevy_seedling::prelude::StreamWriterNode; 5 4 use felix_net::{packet::PacketTypes, packets::update_server_position::UpdateServerPositions}; 6 5 7 6 use crate::{debug_camera::DebugCamera, net::{NetClientCommand, connection::Connection}, remote_player::RemotePlayer};
+2 -2
client/src/main.rs
··· 1 1 use bevy::{DefaultPlugins, app::{App, FixedUpdate, Startup, Update}, ecs::system::Commands}; 2 - use bevy_seedling::prelude::*; 2 + use felix_audio::FelixAudio; 3 3 4 4 use crate::{components::{debug_camera, network_interface, remote_player}, setup::setup}; 5 5 ··· 13 13 App::new() 14 14 .add_plugins(( 15 15 DefaultPlugins, 16 - SeedlingPlugin::default() 16 + FelixAudio 17 17 )) 18 18 .add_systems(Startup, setup) 19 19 .add_systems(Startup, move | mut commands: Commands |{
+4 -1
client/src/setup.rs
··· 1 1 use bevy::prelude::*; 2 + use felix_audio::{FelixAudioListener, source::{FelixAudioSource, static_source::StaticAudioSource}}; 2 3 3 4 use crate::debug_camera; 4 5 ··· 10 11 commands.spawn(( 11 12 Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))), 12 13 MeshMaterial3d(materials.add(Color::WHITE)), 13 - Transform::from_xyz(5.0, 0.0, 0.0) 14 + Transform::from_xyz(5.0, 0.0, 0.0), 15 + FelixAudioSource::from(StaticAudioSource::new("out.wav")) 14 16 )); 15 17 16 18 commands.spawn(( ··· 35 37 debug_camera::DebugCamera::default(), 36 38 Camera3d::default(), 37 39 Transform::from_xyz(0.0, 0.0, 0.0).looking_at(Vec3::ZERO, Vec3::Y), 40 + FelixAudioListener 38 41 )); 39 42 }