mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'desttinghim/sound-effects' into 'master'
Sound Effects Closes #163 and #97 See merge request veloren/veloren!473
This commit is contained in:
commit
f574b1748a
106
Cargo.lock
generated
106
Cargo.lock
generated
@ -21,10 +21,21 @@ dependencies = [
|
||||
"memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "alga"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"approx 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libm 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-complex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "alsa-sys"
|
||||
version = "0.1.1"
|
||||
source = "git+https://github.com/desttinghim/cpal?rev=e7c086d0afc368a888ad133c3b1d928b16986130#e7c086d0afc368a888ad133c3b1d928b16986130"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -311,16 +322,6 @@ dependencies = [
|
||||
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cgmath"
|
||||
version = "0.14.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"approx 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "chashmap"
|
||||
version = "2.2.2"
|
||||
@ -378,7 +379,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "claxon"
|
||||
version = "0.3.3"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
@ -535,9 +536,9 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "cpal"
|
||||
version = "0.8.2"
|
||||
source = "git+https://github.com/desttinghim/cpal?rev=e7c086d0afc368a888ad133c3b1d928b16986130#e7c086d0afc368a888ad133c3b1d928b16986130"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"alsa-sys 0.1.1 (git+https://github.com/desttinghim/cpal?rev=e7c086d0afc368a888ad133c3b1d928b16986130)",
|
||||
"alsa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"coreaudio-rs 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1023,6 +1024,14 @@ dependencies = [
|
||||
"pkg-config 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.1.11"
|
||||
@ -1512,6 +1521,11 @@ dependencies = [
|
||||
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libm"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "line_drawing"
|
||||
version = "0.7.0"
|
||||
@ -1596,6 +1610,14 @@ dependencies = [
|
||||
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "matrixmultiply"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"rawpointer 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "maybe-uninit"
|
||||
version = "2.0.0"
|
||||
@ -1722,6 +1744,22 @@ dependencies = [
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nalgebra"
|
||||
version = "0.18.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"alga 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"approx 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"matrixmultiply 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-complex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "net2"
|
||||
version = "0.2.33"
|
||||
@ -2439,6 +2477,11 @@ dependencies = [
|
||||
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rawpointer"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.1.0"
|
||||
@ -2524,16 +2567,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "rodio"
|
||||
version = "0.8.1"
|
||||
source = "git+https://github.com/desttinghim/rodio.git?rev=dd93f905c1afefaac03c496a666ecab27d3e391b#dd93f905c1afefaac03c496a666ecab27d3e391b"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cgmath 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"claxon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cpal 0.8.2 (git+https://github.com/desttinghim/cpal?rev=e7c086d0afc368a888ad133c3b1d928b16986130)",
|
||||
"claxon 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cpal 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hound 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lewton 0.9.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"minimp3 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"nalgebra 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3000,6 +3043,11 @@ name = "tuple_utils"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "ucd-util"
|
||||
version = "0.1.5"
|
||||
@ -3181,7 +3229,7 @@ dependencies = [
|
||||
"parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"portpicker 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rodio 0.8.1 (git+https://github.com/desttinghim/rodio.git?rev=dd93f905c1afefaac03c496a666ecab27d3e391b)",
|
||||
"rodio 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -3419,7 +3467,8 @@ dependencies = [
|
||||
"checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c"
|
||||
"checksum aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5"
|
||||
"checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d"
|
||||
"checksum alsa-sys 0.1.1 (git+https://github.com/desttinghim/cpal?rev=e7c086d0afc368a888ad133c3b1d928b16986130)" = "<none>"
|
||||
"checksum alga 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d708cb68c7106ed1844de68f50f0157a7788c2909a6926fad5a87546ef6a4ff8"
|
||||
"checksum alsa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b0edcbbf9ef68f15ae1b620f722180b82a98b6f0628d30baa6b8d2a5abc87d58"
|
||||
"checksum andrew 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9b7f09f89872c2b6b29e319377b1fbe91c6f5947df19a25596e121cf19a7b35e"
|
||||
"checksum android_glue 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "000444226fcff248f2bc4c7625be32c63caccfecc2723a2b9f78a7487a49c407"
|
||||
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
|
||||
@ -3455,13 +3504,12 @@ dependencies = [
|
||||
"checksum cexpr 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "42aac45e9567d97474a834efdee3081b3c942b2205be932092f53354ce503d6c"
|
||||
"checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33"
|
||||
"checksum cgl 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "55e7ec0b74fe5897894cbc207092c577e87c52f8a59e8ca8d97ef37551f60a49"
|
||||
"checksum cgmath 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "87f025a17ad3f30d49015c787903976d5f9cd6115ece1eb7f4d6ffe06b8c4080"
|
||||
"checksum chashmap 2.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ff41a3c2c1e39921b9003de14bf0439c7b63a9039637c291e1a64925d8ddfa45"
|
||||
"checksum chrono 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "77d81f58b7301084de3b958691458a53c3f7e0b1d702f77e550b6a88e3a88abe"
|
||||
"checksum clang-sys 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "611ec2e3a7623afd8a8c0d027887b6b55759d894abbf5fe11b9dc11b50d5b49a"
|
||||
"checksum clang-sys 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e414af9726e1d11660801e73ccc7fb81803fb5f49e5903a25b348b2b3b480d2e"
|
||||
"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
|
||||
"checksum claxon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "35193597ff846c905e135b66b7a88876a8b684d269a24fa0f6086988fc2197c8"
|
||||
"checksum claxon 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f86c952727a495bda7abaf09bafdee1a939194dd793d9a8e26281df55ac43b00"
|
||||
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
|
||||
"checksum cmake 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "3c84c596dcf125d6781f58e3f4254677ec2a6d8aa56e8501ac277100990b3229"
|
||||
"checksum cocoa 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b0c23085dde1ef4429df6e5896b89356d35cdd321fb43afe3e378d010bb5adc6"
|
||||
@ -3479,7 +3527,7 @@ dependencies = [
|
||||
"checksum core-graphics 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)" = "56790968ab1c8a1202a102e6de05fc6e1ec87da99e4e93e9a7d13efbfc1e95a9"
|
||||
"checksum coreaudio-rs 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f229761965dad3e9b11081668a6ea00f1def7aa46062321b5ec245b834f6e491"
|
||||
"checksum coreaudio-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "78fdbabf58d5b1f461e31b94a571c109284f384cec619a3d96e66ec55b4de82b"
|
||||
"checksum cpal 0.8.2 (git+https://github.com/desttinghim/cpal?rev=e7c086d0afc368a888ad133c3b1d928b16986130)" = "<none>"
|
||||
"checksum cpal 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d58ae1ed6536b1b233f5e3aeb6997a046ddb4d05e3f61701b58a92eb254a829e"
|
||||
"checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1"
|
||||
"checksum crossbeam 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d7408247b1b87f480890f28b670c5f8d9a8a4274833433fe74dc0dfd46d33650"
|
||||
"checksum crossbeam 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2d818a4990769aac0c7ff1360e233ef3a41adcb009ebb2036bf6915eb0f6b23c"
|
||||
@ -3532,6 +3580,7 @@ dependencies = [
|
||||
"checksum gdk-pixbuf 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c2d2199eba47ebcb9977ce28179649bdd59305ef465c4e6f9b65aaa41c24e6b5"
|
||||
"checksum gdk-pixbuf-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df6a3b73e04fafc07f5ebc083f1096a773412e627828e1103a55e921f81187d8"
|
||||
"checksum gdk-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3162ff940526ddff71bf1f630facee6b5e05d282d125ba0c4c803842819b80c3"
|
||||
"checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec"
|
||||
"checksum getrandom 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "fc344b02d3868feb131e8b5fe2b9b0a1cc42942679af493061fc13b853243872"
|
||||
"checksum gfx 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)" = "619e38a31e275efaf92c6a94f977db8aac396e3cb6998c176cfde32ce3239b69"
|
||||
"checksum gfx_core 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4e1127b02a9d4fcc880091d8a0f4419efd598de4f1649edcd005c76e5792176f"
|
||||
@ -3583,6 +3632,7 @@ dependencies = [
|
||||
"checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba"
|
||||
"checksum libloading 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fd38073de8f7965d0c17d30546d4bb6da311ab428d1c7a3fc71dff7f9d4979b9"
|
||||
"checksum libloading 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2b111a074963af1d37a139918ac6d49ad1d0d5e47f72fd55388619691a7d753"
|
||||
"checksum libm 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a"
|
||||
"checksum line_drawing 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5cc7ad3d82c845bdb5dde34ffdcc7a5fb4d2996e1e1ee0f19c33bc80e15196b9"
|
||||
"checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83"
|
||||
"checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c"
|
||||
@ -3594,6 +3644,7 @@ dependencies = [
|
||||
"checksum lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d947cbb889ed21c2a84be6ffbaebf5b4e0f4340638cba0444907e38b56be084"
|
||||
"checksum mach 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "86dd2487cdfea56def77b88438a2c915fb45113c5319bfe7e14306ca4cd0b0e1"
|
||||
"checksum malloc_buf 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb"
|
||||
"checksum matrixmultiply 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dcfed72d871629daa12b25af198f110e8095d7650f5f4c61c5bac28364604f9b"
|
||||
"checksum maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
|
||||
"checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a"
|
||||
"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e"
|
||||
@ -3608,6 +3659,7 @@ dependencies = [
|
||||
"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
|
||||
"checksum mopa 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a785740271256c230f57462d3b83e52f998433a7062fc18f96d5999474a9f915"
|
||||
"checksum msgbox 0.1.1 (git+https://github.com/bekker/msgbox-rs.git)" = "<none>"
|
||||
"checksum nalgebra 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aaa9fddbc34c8c35dd2108515587b8ce0cab396f17977b8c738568e4edb521a2"
|
||||
"checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88"
|
||||
"checksum nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6c722bee1037d430d0f8e687bbdbf222f27cc6e4e68d5caf630857bb2b6dbdce"
|
||||
"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945"
|
||||
@ -3685,6 +3737,7 @@ dependencies = [
|
||||
"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
|
||||
"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44"
|
||||
"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
|
||||
"checksum rawpointer 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ebac11a9d2e11f2af219b8b8d833b76b1ea0e054aa0e8d8e9e4cbde353bdf019"
|
||||
"checksum rayon 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a4b0186e22767d5b9738a05eab7c6ac90b15db17e5b5f9bd87976dd7d89a10a4"
|
||||
"checksum rayon-core 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbe0df8435ac0c397d467b6cad6d25543d06e8a019ef3f6af3c384597515bd2"
|
||||
"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
|
||||
@ -3694,7 +3747,7 @@ dependencies = [
|
||||
"checksum regex 1.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "d9d8297cc20bbb6184f8b45ff61c8ee6a9ac56c156cec8e38c3e5084773c44ad"
|
||||
"checksum regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7"
|
||||
"checksum regex-syntax 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b143cceb2ca5e56d5671988ef8b15615733e7ee16cd348e064333b251b89343f"
|
||||
"checksum rodio 0.8.1 (git+https://github.com/desttinghim/rodio.git?rev=dd93f905c1afefaac03c496a666ecab27d3e391b)" = "<none>"
|
||||
"checksum rodio 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d0f961b254e66d147a7b550c78b01308934c97d807a34b417fd0f5a0a0f3a2d"
|
||||
"checksum ron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2ece421e0c4129b90e4a35b6f625e472e96c552136f5093a2f4fa2bbb75a62d5"
|
||||
"checksum rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ca4eaef519b494d1f2848fc602d18816fed808a981aedf4f1f00ceb7c9d32cf"
|
||||
"checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783"
|
||||
@ -3749,6 +3802,7 @@ dependencies = [
|
||||
"checksum tiff 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d7b7c2cfc4742bd8a32f2e614339dd8ce30dbcf676bb262bd63a2327bc5df57d"
|
||||
"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
|
||||
"checksum tuple_utils 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cbfecd7bb8f0a3e96b3b31c46af2677a55a588767c0091f484601424fcb20e7e"
|
||||
"checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9"
|
||||
"checksum ucd-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa9b3b49edd3468c0e6565d85783f51af95212b6fa3986a5500954f00b460874"
|
||||
"checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20"
|
||||
"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
|
||||
|
BIN
assets/voxygen/audio/footsteps/stepdirt_1.wav
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/audio/footsteps/stepdirt_1.wav
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/audio/footsteps/stepdirt_2.wav
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/audio/footsteps/stepdirt_2.wav
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/audio/footsteps/stepdirt_3.wav
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/audio/footsteps/stepdirt_3.wav
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/audio/footsteps/stepdirt_4.wav
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/audio/footsteps/stepdirt_4.wav
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/audio/footsteps/stepdirt_5.wav
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/audio/footsteps/stepdirt_5.wav
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/audio/footsteps/stepdirt_6.wav
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/audio/footsteps/stepdirt_6.wav
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/audio/footsteps/stepdirt_7.wav
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/audio/footsteps/stepdirt_7.wav
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/audio/footsteps/stepdirt_8.wav
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/audio/footsteps/stepdirt_8.wav
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/audio/footsteps/stepsnow_1.wav
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/audio/footsteps/stepsnow_1.wav
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/audio/footsteps/stepsnow_2.wav
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/audio/footsteps/stepsnow_2.wav
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/audio/footsteps/stepstone_1.wav
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/audio/footsteps/stepstone_1.wav
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/audio/footsteps/stepstone_2.wav
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/audio/footsteps/stepstone_2.wav
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/audio/footsteps/stepstone_3.wav
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/audio/footsteps/stepstone_3.wav
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/audio/footsteps/stepstone_4.wav
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/audio/footsteps/stepstone_4.wav
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/audio/footsteps/stepstone_5.wav
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/audio/footsteps/stepstone_5.wav
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/audio/footsteps/stepstone_6.wav
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/audio/footsteps/stepstone_6.wav
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/audio/footsteps/stepstone_7.wav
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/audio/footsteps/stepstone_7.wav
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/audio/footsteps/stepstone_8.wav
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/audio/footsteps/stepstone_8.wav
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/audio/footsteps/stepwater_1.wav
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/audio/footsteps/stepwater_1.wav
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/audio/footsteps/stepwater_2.wav
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/audio/footsteps/stepwater_2.wav
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/audio/footsteps/stepwood_1.wav
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/audio/footsteps/stepwood_1.wav
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/audio/footsteps/stepwood_2.wav
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/audio/footsteps/stepwood_2.wav
(Stored with Git LFS)
Normal file
Binary file not shown.
@ -54,7 +54,7 @@ num = "0.2.0"
|
||||
backtrace = "0.3.33"
|
||||
rand = "0.7.0"
|
||||
frustum_query = "0.1.2"
|
||||
rodio = { git = "https://github.com/desttinghim/rodio.git", rev = "dd93f905c1afefaac03c496a666ecab27d3e391b" }
|
||||
rodio = "0.9.0"
|
||||
crossbeam = "0.7.2"
|
||||
heaptrack = "0.3.0"
|
||||
hashbrown = { version = "0.5.0", features = ["serde", "nightly"] }
|
||||
|
@ -1,424 +0,0 @@
|
||||
use crate::settings::{AudioSettings, Settings};
|
||||
use common::assets::read_dir;
|
||||
use crossbeam::{
|
||||
atomic::AtomicCell,
|
||||
channel::{unbounded, Sender},
|
||||
queue::SegQueue,
|
||||
sync::ShardedLock,
|
||||
};
|
||||
use parking_lot::{Condvar, Mutex};
|
||||
use rodio::{Decoder, Device, Sink};
|
||||
use std::fs::File;
|
||||
use std::io::BufReader;
|
||||
use std::sync::Arc;
|
||||
use std::thread;
|
||||
|
||||
trait AudioConfig {
|
||||
fn set_volume(&mut self, volume: f32);
|
||||
fn set_device(&mut self, name: String);
|
||||
}
|
||||
|
||||
trait MonoMode {
|
||||
fn set_mono(tx: Sender<AudioPlayerMsg>) -> Self;
|
||||
}
|
||||
|
||||
trait StereoMode {
|
||||
fn set_stereo(tx: Sender<AudioPlayerMsg>) -> Self;
|
||||
}
|
||||
|
||||
trait DebugMode {
|
||||
fn set_no_audio(tx: Sender<AudioPlayerMsg>) -> Self;
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum SinkError {
|
||||
SinkNotMatch,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||
pub enum Genre {
|
||||
Bgm,
|
||||
Sfx,
|
||||
None,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum AudioPlayerMsg {
|
||||
AudioPlay,
|
||||
AudioStop,
|
||||
AudioTime(f64),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Action {
|
||||
Load(String),
|
||||
Stop,
|
||||
AdjustVolume(f32),
|
||||
ChangeDevice(String),
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct EventLoop {
|
||||
condvar: Arc<(Mutex<bool>, Condvar)>,
|
||||
queue: Arc<SegQueue<Action>>,
|
||||
playing: Arc<ShardedLock<bool>>,
|
||||
}
|
||||
|
||||
impl EventLoop {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
condvar: Arc::new((Mutex::new(false), Condvar::new())),
|
||||
queue: Arc::new(SegQueue::new()),
|
||||
playing: Arc::new(ShardedLock::new(false)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The `AudioPlayer` handles exactly what player does by playing audio from emitter.
|
||||
pub struct AudioPlayer {
|
||||
event_loop: EventLoop,
|
||||
paused: AtomicCell<bool>,
|
||||
tx: Sender<AudioPlayerMsg>,
|
||||
}
|
||||
|
||||
impl AudioPlayer {
|
||||
pub(crate) fn new(genre: Genre, tx: Sender<AudioPlayerMsg>) -> Self {
|
||||
match genre {
|
||||
Genre::Bgm => AudioPlayer::set_mono(tx),
|
||||
Genre::Sfx => unimplemented!(),
|
||||
Genre::None => AudioPlayer::set_no_audio(tx),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn load(&self, path: &str) {
|
||||
self.emit(Action::Load(path.to_string()));
|
||||
self.set_playing(true);
|
||||
}
|
||||
|
||||
// pub(crate) fn pause(&mut self) {
|
||||
// self.paused.store(true);
|
||||
// self.send(AudioPlayerMsg::AudioStop);
|
||||
// self.set_playing(false);
|
||||
// }
|
||||
|
||||
pub(crate) fn resume(&mut self) {
|
||||
self.paused.store(false);
|
||||
self.send(AudioPlayerMsg::AudioPlay);
|
||||
self.set_playing(true);
|
||||
}
|
||||
|
||||
// pub(crate) fn stop(&mut self) {
|
||||
// self.paused.store(false);
|
||||
// self.send(AudioPlayerMsg::AudioStop);
|
||||
// self.emit(Action::Stop);
|
||||
// self.set_playing(false);
|
||||
// }
|
||||
|
||||
pub(crate) fn is_paused(&self) -> bool {
|
||||
self.paused.load()
|
||||
}
|
||||
|
||||
pub(crate) fn set_volume(&self, value: f32) {
|
||||
self.emit(Action::AdjustVolume(value));
|
||||
}
|
||||
|
||||
pub(crate) fn set_device(&self, device: &str) {
|
||||
self.emit(Action::ChangeDevice(device.to_string()));
|
||||
}
|
||||
|
||||
fn emit(&self, action: Action) {
|
||||
self.event_loop.queue.push(action);
|
||||
}
|
||||
|
||||
fn send(&mut self, msg: AudioPlayerMsg) {
|
||||
send_msg(&mut self.tx, msg);
|
||||
}
|
||||
|
||||
fn set_playing(&self, playing: bool) {
|
||||
*self.event_loop.playing.write().unwrap() = playing;
|
||||
let &(ref lock, ref condvar) = &*self.event_loop.condvar;
|
||||
let mut started = lock.lock();
|
||||
*started = playing;
|
||||
if playing {
|
||||
condvar.notify_one();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MonoMode for AudioPlayer {
|
||||
/// Playing audio until a receive operation appears on the other side.
|
||||
fn set_mono(tx: Sender<AudioPlayerMsg>) -> Self {
|
||||
let event_loop = EventLoop::new();
|
||||
|
||||
{
|
||||
//let mut tx = tx.clone();
|
||||
let event_loop = event_loop.clone();
|
||||
let condition = event_loop.condvar.clone();
|
||||
|
||||
thread::spawn(move || {
|
||||
let block = || {
|
||||
let (ref lock, ref condvar) = *condition;
|
||||
let mut started = lock.lock();
|
||||
*started = false;
|
||||
while !*started {
|
||||
condvar.wait(&mut started);
|
||||
}
|
||||
};
|
||||
let mut playback = MonoEmitter::new(&Settings::load().audio);
|
||||
|
||||
// Start the thread if set_playing(true).
|
||||
loop {
|
||||
if let Ok(action) = event_loop.queue.pop() {
|
||||
match action {
|
||||
Action::Load(path) => {
|
||||
if playback.stream.empty() {
|
||||
playback.play_from(&path);
|
||||
//send_msg(&mut tx, AudioPlayerMsg::AudioPlay);
|
||||
}
|
||||
}
|
||||
Action::Stop => playback.stream.stop(),
|
||||
Action::AdjustVolume(value) => playback.set_volume(value),
|
||||
Action::ChangeDevice(device) => playback.set_device(device),
|
||||
}
|
||||
} else {
|
||||
block();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Self {
|
||||
event_loop,
|
||||
paused: AtomicCell::new(false),
|
||||
tx,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DebugMode for AudioPlayer {
|
||||
/// Don't load `rodio` for `no-audio` feature.
|
||||
fn set_no_audio(tx: Sender<AudioPlayerMsg>) -> Self {
|
||||
Self {
|
||||
event_loop: EventLoop::new(),
|
||||
paused: AtomicCell::new(true),
|
||||
tx,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// TODO: Implement treeview and modellist widgets for GUI design.
|
||||
pub struct Jukebox {
|
||||
genre: AtomicCell<Genre>,
|
||||
pub(crate) player: AudioPlayer,
|
||||
}
|
||||
|
||||
impl Jukebox {
|
||||
pub(crate) fn new(genre: Genre) -> Self {
|
||||
let (tx, _rx) = unbounded();
|
||||
Self {
|
||||
genre: AtomicCell::new(genre),
|
||||
player: AudioPlayer::new(genre, tx),
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: The `update` function should associate with `conrod` to visualise the audio playlist
|
||||
// and settings.
|
||||
// pub(crate) fn update(&mut self, _msg: AudioPlayerMsg) {
|
||||
// unimplemented!()
|
||||
// }
|
||||
|
||||
/// Display the current genre.
|
||||
pub(crate) fn get_genre(&self) -> Genre {
|
||||
self.genre.load()
|
||||
}
|
||||
}
|
||||
|
||||
struct MonoEmitter {
|
||||
device: Device,
|
||||
stream: Sink,
|
||||
}
|
||||
|
||||
// struct StereoEmitter {
|
||||
// device: Device,
|
||||
// stream: SpatialSink,
|
||||
// }
|
||||
|
||||
impl MonoEmitter {
|
||||
fn new(settings: &AudioSettings) -> Self {
|
||||
let device = match &settings.audio_device {
|
||||
Some(dev) => rodio::output_devices()
|
||||
.find(|x| &x.name() == dev)
|
||||
.or_else(rodio::default_output_device)
|
||||
.expect("No Audio devices found!"),
|
||||
None => rodio::default_output_device().expect("No Audio devices found!"),
|
||||
};
|
||||
let sink = Sink::new(&device);
|
||||
sink.set_volume(settings.music_volume);
|
||||
|
||||
Self {
|
||||
device,
|
||||
stream: sink,
|
||||
}
|
||||
}
|
||||
|
||||
// /// Returns the name of the current audio device.
|
||||
// /// Does not return rodio Device struct in case our audio backend changes.
|
||||
// fn get_device(&self) -> String {
|
||||
// self.device.name()
|
||||
// }
|
||||
|
||||
fn play_from(&mut self, path: &str) {
|
||||
let bufreader = BufReader::new(File::open(path).unwrap());
|
||||
let src = Decoder::new(bufreader).unwrap();
|
||||
self.stream.append(src);
|
||||
}
|
||||
}
|
||||
|
||||
impl AudioConfig for MonoEmitter {
|
||||
fn set_volume(&mut self, volume: f32) {
|
||||
self.stream.set_volume(volume.min(1.0).max(0.0))
|
||||
}
|
||||
|
||||
/// Sets the current audio device from a string.
|
||||
/// Does not use the rodio Device struct in case that detail changes.
|
||||
/// If the string is an invalid audio device, then no change is made.
|
||||
fn set_device(&mut self, name: String) {
|
||||
if let Some(dev) = rodio::output_devices().find(|x| x.name() == name) {
|
||||
self.device = dev;
|
||||
self.stream = Sink::new(&self.device);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// impl StereoEmitter {
|
||||
// fn new(settings: &AudioSettings) -> Self {
|
||||
// let device = match &settings.audio_device {
|
||||
// Some(dev) => rodio::output_devices()
|
||||
// .find(|x| &x.name() == dev)
|
||||
// .or_else(rodio::default_output_device)
|
||||
// .expect("No Audio devices found!"),
|
||||
// None => rodio::default_output_device().expect("No Audio devices found!"),
|
||||
// };
|
||||
// let sink = SpatialSink::new(
|
||||
// &device.device,
|
||||
// [0.0, 0.0, 0.0],
|
||||
// [1.0, 0.0, 0.0],
|
||||
// [-1.0, 0.0, 0.0],
|
||||
// );
|
||||
// sink.set_volume(settings.music_volume);
|
||||
|
||||
// Self {
|
||||
// device,
|
||||
// stream: sink,
|
||||
// }
|
||||
// }
|
||||
|
||||
// fn play_from(&mut self, path: &str) {
|
||||
// let bufreader = load_from_path(path).unwrap();
|
||||
// let src = Decoder::new(bufreader).unwrap();
|
||||
// self.stream.append(src);
|
||||
// }
|
||||
// }
|
||||
|
||||
// impl AudioConfig for StereoEmitter {
|
||||
// fn set_volume(&mut self, volume: f32) {
|
||||
// self.stream.set_volume(volume.min(1.0).max(0.0))
|
||||
// }
|
||||
|
||||
// /// Sets the current audio device from a string.
|
||||
// /// Does not use the rodio Device struct in case that detail changes.
|
||||
// /// If the string is an invalid audio device, then no change is made.
|
||||
// fn set_device(&mut self, name: String) {
|
||||
// if let Some(dev) = rodio::output_devices().find(|x| x.name() == name) {
|
||||
// self.device = dev;
|
||||
// self.stream = SpatialSink::new(
|
||||
// &self.device,
|
||||
// [0.0, 0.0, 0.0],
|
||||
// [1.0, 0.0, 0.0],
|
||||
// [-1.0, 0.0, 0.0],
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
/// Returns the default audio device.
|
||||
/// Does not return rodio Device struct in case our audio backend changes.
|
||||
pub(crate) fn get_default_device() -> String {
|
||||
rodio::default_output_device()
|
||||
.expect("No audio output devices detected.")
|
||||
.name()
|
||||
}
|
||||
|
||||
/// Load the audio file directory selected by genre.
|
||||
pub(crate) fn load_soundtracks(genre: &Genre) -> Vec<String> {
|
||||
match *genre {
|
||||
Genre::Bgm => {
|
||||
let assets = read_dir("voxygen.audio.soundtrack").unwrap();
|
||||
let soundtracks = assets
|
||||
.filter_map(|entry| {
|
||||
entry.ok().map(|f| {
|
||||
let path = f.path();
|
||||
path.to_string_lossy().into_owned()
|
||||
})
|
||||
})
|
||||
.collect::<Vec<String>>();
|
||||
|
||||
soundtracks
|
||||
}
|
||||
Genre::Sfx => {
|
||||
let assets = read_dir("voxygen.audio.soundtrack").unwrap();
|
||||
let soundtracks = assets
|
||||
//.filter_map(|entry| {
|
||||
// entry.ok().and_then(|f| {
|
||||
// f.path()
|
||||
// .file_name()
|
||||
// .and_then(|n| n.to_str().map(|s| String::from(s)))
|
||||
// })
|
||||
//})
|
||||
//.collect::<Vec<String>>();
|
||||
.filter_map(|entry| {
|
||||
entry.ok().map(|f| {
|
||||
let path = f.path();
|
||||
(*path.into_os_string().to_string_lossy()).to_owned()
|
||||
})
|
||||
})
|
||||
.collect::<Vec<String>>();
|
||||
|
||||
soundtracks
|
||||
}
|
||||
Genre::None => {
|
||||
let empty_list = Vec::new();
|
||||
empty_list
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn select_random_music(genre: &Genre) -> String {
|
||||
let soundtracks = load_soundtracks(genre);
|
||||
let index = rand::random::<usize>() % soundtracks.len();
|
||||
soundtracks[index].clone()
|
||||
}
|
||||
|
||||
/// Returns a vec of the audio devices available.
|
||||
/// Does not return rodio Device struct in case our audio backend changes.
|
||||
pub(crate) fn list_devices() -> Vec<String> {
|
||||
list_devices_raw().iter().map(|x| x.name()).collect()
|
||||
}
|
||||
|
||||
/// Returns vec of devices
|
||||
fn list_devices_raw() -> Vec<Device> {
|
||||
rodio::output_devices().collect()
|
||||
}
|
||||
|
||||
fn send_msg(tx: &mut Sender<AudioPlayerMsg>, msg: AudioPlayerMsg) {
|
||||
tx.send(msg)
|
||||
.expect("Failed on attempting to send a message into audio channel.");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_load_soundtracks() {
|
||||
use crate::audio::base::{load_soundtracks, Genre};
|
||||
for entry in load_soundtracks(&Genre::Bgm).iter() {
|
||||
println!("{}", entry)
|
||||
}
|
||||
}
|
137
voxygen/src/audio/channel.rs
Normal file
137
voxygen/src/audio/channel.rs
Normal file
@ -0,0 +1,137 @@
|
||||
use crate::audio::fader::Fader;
|
||||
use rodio::{Decoder, Device, Sample, Source, SpatialSink};
|
||||
use std::fs::File;
|
||||
use std::io::BufReader;
|
||||
use vek::*;
|
||||
|
||||
#[derive(PartialEq, Clone, Copy)]
|
||||
pub enum AudioType {
|
||||
Sfx,
|
||||
Music,
|
||||
None,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Clone, Copy)]
|
||||
enum ChannelState {
|
||||
// Init,
|
||||
// ToPlay,
|
||||
// Loading,
|
||||
Playing,
|
||||
Stopping,
|
||||
Stopped,
|
||||
}
|
||||
|
||||
pub struct Channel {
|
||||
id: usize,
|
||||
sink: SpatialSink,
|
||||
audio_type: AudioType,
|
||||
state: ChannelState,
|
||||
fader: Fader,
|
||||
pub pos: Vec3<f32>,
|
||||
}
|
||||
|
||||
// TODO: Implement asynchronous loading
|
||||
impl Channel {
|
||||
/// Create an empty channel for future use
|
||||
pub fn new(device: &Device) -> Self {
|
||||
Self {
|
||||
id: 0,
|
||||
sink: SpatialSink::new(device, [0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [-1.0, 0.0, 0.0]),
|
||||
audio_type: AudioType::None,
|
||||
state: ChannelState::Stopped,
|
||||
fader: Fader::fade_in(0.0),
|
||||
pos: Vec3::zero(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn music(id: usize, device: &Device, bufr: BufReader<File>) -> Self {
|
||||
let sink = SpatialSink::new(device, [0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [-1.0, 0.0, 0.0]);
|
||||
let sound = Decoder::new(bufr).unwrap();
|
||||
|
||||
sink.append(sound);
|
||||
|
||||
Self {
|
||||
id,
|
||||
sink,
|
||||
audio_type: AudioType::Music,
|
||||
state: ChannelState::Playing,
|
||||
fader: Fader::fade_in(0.0),
|
||||
pos: Vec3::zero(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sfx(id: usize, sink: SpatialSink, pos: Vec3<f32>) -> Self {
|
||||
Self {
|
||||
id,
|
||||
sink,
|
||||
audio_type: AudioType::Sfx,
|
||||
state: ChannelState::Playing,
|
||||
fader: Fader::fade_in(0.0),
|
||||
pos,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn play<S>(&mut self, source: S)
|
||||
where
|
||||
S: Source + Send + 'static,
|
||||
S::Item: Sample,
|
||||
S::Item: Send,
|
||||
<S as std::iter::Iterator>::Item: std::fmt::Debug,
|
||||
{
|
||||
self.state = ChannelState::Playing;
|
||||
self.sink.append(source);
|
||||
}
|
||||
|
||||
pub fn is_done(&self) -> bool {
|
||||
self.sink.empty() || self.state == ChannelState::Stopped
|
||||
}
|
||||
|
||||
pub fn stop(&mut self, fader: Fader) {
|
||||
self.state = ChannelState::Stopping;
|
||||
self.fader = fader;
|
||||
}
|
||||
|
||||
pub fn get_id(&self) -> usize {
|
||||
self.id
|
||||
}
|
||||
|
||||
pub fn set_id(&mut self, new_id: usize) {
|
||||
self.id = new_id;
|
||||
}
|
||||
|
||||
pub fn get_audio_type(&self) -> AudioType {
|
||||
self.audio_type
|
||||
}
|
||||
|
||||
pub fn set_volume(&mut self, volume: f32) {
|
||||
self.sink.set_volume(volume);
|
||||
}
|
||||
|
||||
pub fn set_emitter_position(&mut self, pos: [f32; 3]) {
|
||||
self.sink.set_emitter_position(pos);
|
||||
}
|
||||
|
||||
pub fn set_left_ear_position(&mut self, pos: [f32; 3]) {
|
||||
self.sink.set_left_ear_position(pos);
|
||||
}
|
||||
|
||||
pub fn set_right_ear_position(&mut self, pos: [f32; 3]) {
|
||||
self.sink.set_right_ear_position(pos);
|
||||
}
|
||||
|
||||
pub fn update(&mut self, dt: f32) {
|
||||
match self.state {
|
||||
// ChannelState::Init | ChannelState::ToPlay | ChannelState::Loading => {}
|
||||
ChannelState::Playing => {}
|
||||
ChannelState::Stopping => {
|
||||
self.fader.update(dt);
|
||||
self.sink.set_volume(self.fader.get_volume());
|
||||
|
||||
if self.fader.is_finished() {
|
||||
self.state = ChannelState::Stopped;
|
||||
}
|
||||
}
|
||||
ChannelState::Stopped => {}
|
||||
}
|
||||
}
|
||||
}
|
66
voxygen/src/audio/fader.rs
Normal file
66
voxygen/src/audio/fader.rs
Normal file
@ -0,0 +1,66 @@
|
||||
#[derive(PartialEq, Clone, Copy)]
|
||||
pub struct Fader {
|
||||
length: f32,
|
||||
running_time: f32,
|
||||
volume_from: f32,
|
||||
volume_to: f32,
|
||||
is_running: bool,
|
||||
}
|
||||
|
||||
fn lerp(t: f32, a: f32, b: f32) -> f32 {
|
||||
(1.0 - t) * a + t * b
|
||||
}
|
||||
|
||||
impl Fader {
|
||||
pub fn fade(time: f32, volume_from: f32, volume_to: f32) -> Self {
|
||||
Self {
|
||||
length: time,
|
||||
running_time: 0.0,
|
||||
volume_from,
|
||||
volume_to,
|
||||
is_running: true,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fade_in(time: f32) -> Self {
|
||||
Self {
|
||||
length: time,
|
||||
running_time: 0.0,
|
||||
volume_from: 0.0,
|
||||
volume_to: 1.0,
|
||||
is_running: true,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fade_out(time: f32) -> Self {
|
||||
Self {
|
||||
length: time,
|
||||
running_time: 0.0,
|
||||
volume_from: 1.0,
|
||||
volume_to: 0.0,
|
||||
is_running: true,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(&mut self, dt: f32) {
|
||||
if self.is_running {
|
||||
self.running_time = self.running_time + dt;
|
||||
if self.running_time >= self.length {
|
||||
self.running_time = self.length;
|
||||
self.is_running = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_volume(&self) -> f32 {
|
||||
lerp(
|
||||
self.running_time / self.length,
|
||||
self.volume_from,
|
||||
self.volume_to,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn is_finished(&self) -> bool {
|
||||
self.running_time >= self.length || !self.is_running
|
||||
}
|
||||
}
|
@ -1,41 +1,242 @@
|
||||
pub mod base;
|
||||
use base::{Genre, Jukebox};
|
||||
pub mod channel;
|
||||
pub mod fader;
|
||||
pub mod soundcache;
|
||||
use channel::{AudioType, Channel};
|
||||
use fader::Fader;
|
||||
use soundcache::SoundCache;
|
||||
|
||||
use common::assets;
|
||||
use rodio::{Decoder, Device};
|
||||
use vek::*;
|
||||
|
||||
const FALLOFF: f32 = 0.13;
|
||||
|
||||
pub struct AudioFrontend {
|
||||
pub(crate) model: Jukebox,
|
||||
pub(crate) default_device: String,
|
||||
pub(crate) device_list: Vec<String>,
|
||||
pub device: String,
|
||||
pub device_list: Vec<String>,
|
||||
audio_device: Option<Device>,
|
||||
sound_cache: SoundCache,
|
||||
|
||||
channels: Vec<Channel>,
|
||||
next_channel_id: usize,
|
||||
|
||||
sfx_volume: f32,
|
||||
music_volume: f32,
|
||||
|
||||
listener_pos: Vec3<f32>,
|
||||
listener_ori: Vec3<f32>,
|
||||
|
||||
listener_ear_left: Vec3<f32>,
|
||||
listener_ear_right: Vec3<f32>,
|
||||
}
|
||||
|
||||
impl AudioFrontend {
|
||||
pub(crate) fn new() -> Self {
|
||||
/// Construct with given device
|
||||
pub fn new(device: String, channel_num: usize) -> Self {
|
||||
let mut channels = Vec::with_capacity(channel_num);
|
||||
let audio_device = get_device_raw(&device);
|
||||
if let Some(audio_device) = &audio_device {
|
||||
for _i in 0..channel_num {
|
||||
channels.push(Channel::new(&audio_device));
|
||||
}
|
||||
}
|
||||
Self {
|
||||
model: Jukebox::new(Genre::Bgm),
|
||||
default_device: base::get_default_device(),
|
||||
device_list: base::list_devices(),
|
||||
device: device.clone(),
|
||||
device_list: list_devices(),
|
||||
audio_device,
|
||||
sound_cache: SoundCache::new(),
|
||||
channels: channels,
|
||||
next_channel_id: 1,
|
||||
sfx_volume: 1.0,
|
||||
music_volume: 1.0,
|
||||
listener_pos: Vec3::zero(),
|
||||
listener_ori: Vec3::zero(),
|
||||
listener_ear_left: Vec3::zero(),
|
||||
listener_ear_right: Vec3::zero(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Play audio.
|
||||
pub(crate) fn play(&mut self) {
|
||||
let path = base::select_random_music(&Genre::Bgm);
|
||||
|
||||
match self.model.player.is_paused() {
|
||||
true => match self.model.get_genre() {
|
||||
Genre::Bgm => self.model.player.resume(),
|
||||
Genre::Sfx => unimplemented!(), // TODO: add support for sound effects.
|
||||
Genre::None => (),
|
||||
},
|
||||
false => self.model.player.load(&path),
|
||||
/// Construct in `no-audio` mode for debugging
|
||||
pub fn no_audio() -> Self {
|
||||
Self {
|
||||
device: "none".to_string(),
|
||||
device_list: list_devices(),
|
||||
audio_device: None,
|
||||
sound_cache: SoundCache::new(),
|
||||
channels: Vec::new(),
|
||||
next_channel_id: 1,
|
||||
sfx_volume: 1.0,
|
||||
music_volume: 1.0,
|
||||
listener_pos: Vec3::zero(),
|
||||
listener_ori: Vec3::zero(),
|
||||
listener_ear_left: Vec3::zero(),
|
||||
listener_ear_right: Vec3::zero(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct in `no-audio` mode for debugging.
|
||||
pub(crate) fn no_audio() -> Self {
|
||||
Self {
|
||||
model: Jukebox::new(Genre::None),
|
||||
default_device: "None".to_owned(),
|
||||
device_list: Vec::new(),
|
||||
/// Maintain audio
|
||||
pub fn maintain(&mut self, dt: f32) {
|
||||
for channel in self.channels.iter_mut() {
|
||||
channel.update(dt);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_channel(&mut self) -> Option<&mut Channel> {
|
||||
self.channels.iter_mut().find(|c| c.is_done())
|
||||
}
|
||||
|
||||
/// Play specfied sound file.
|
||||
///```ignore
|
||||
///audio.play_sound("voxygen.audio.sfx.step");
|
||||
///```
|
||||
pub fn play_sound(&mut self, sound: &str, pos: Vec3<f32>) -> usize {
|
||||
let id = self.next_channel_id;
|
||||
self.next_channel_id += 1;
|
||||
|
||||
if let Some(_) = &self.audio_device {
|
||||
let calc_pos = ((pos - self.listener_pos) * FALLOFF).into_array();
|
||||
|
||||
let sound = self.sound_cache.load_sound(sound);
|
||||
|
||||
let left_ear = self.listener_ear_left.into_array();
|
||||
let right_ear = self.listener_ear_right.into_array();
|
||||
|
||||
if let Some(channel) = self.get_channel() {
|
||||
channel.set_id(id);
|
||||
channel.set_emitter_position(calc_pos);
|
||||
channel.set_left_ear_position(left_ear);
|
||||
channel.set_right_ear_position(right_ear);
|
||||
channel.play(sound);
|
||||
} else {
|
||||
log::warn!("No available channels!");
|
||||
}
|
||||
}
|
||||
|
||||
id
|
||||
}
|
||||
|
||||
pub fn set_listener_pos(&mut self, pos: &Vec3<f32>, ori: &Vec3<f32>) {
|
||||
self.listener_pos = pos.clone();
|
||||
self.listener_ori = ori.normalized();
|
||||
|
||||
let up = Vec3::new(0.0, 0.0, 1.0);
|
||||
|
||||
let pos_left = up.cross(self.listener_ori.clone()).normalized();
|
||||
let pos_right = self.listener_ori.cross(up.clone()).normalized();
|
||||
|
||||
self.listener_ear_left = pos_left;
|
||||
self.listener_ear_right = pos_right;
|
||||
|
||||
for channel in self.channels.iter_mut() {
|
||||
if channel.get_audio_type() == AudioType::Sfx {
|
||||
channel.set_emitter_position(
|
||||
((channel.pos - self.listener_pos) * FALLOFF).into_array(),
|
||||
);
|
||||
channel.set_left_ear_position(pos_left.into_array());
|
||||
channel.set_right_ear_position(pos_right.into_array());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn play_music(&mut self, sound: &str) -> usize {
|
||||
let id = self.next_channel_id;
|
||||
self.next_channel_id += 1;
|
||||
|
||||
if let Some(_) = &self.audio_device {
|
||||
let file = assets::load_file(&sound, &["ogg"]).unwrap();
|
||||
let sound = Decoder::new(file).unwrap();
|
||||
|
||||
if let Some(channel) = self.get_channel() {
|
||||
channel.set_id(id);
|
||||
channel.play(sound);
|
||||
}
|
||||
}
|
||||
|
||||
id
|
||||
}
|
||||
|
||||
pub fn stop_channel(&mut self, channel_id: usize, fader: Fader) {
|
||||
let index = self.channels.iter().position(|c| c.get_id() == channel_id);
|
||||
if let Some(index) = index {
|
||||
self.channels[index].stop(fader);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_sfx_volume(&self) -> f32 {
|
||||
self.sfx_volume
|
||||
}
|
||||
|
||||
pub fn get_music_volume(&self) -> f32 {
|
||||
self.music_volume
|
||||
}
|
||||
|
||||
pub fn set_sfx_volume(&mut self, volume: f32) {
|
||||
self.sfx_volume = volume;
|
||||
|
||||
for channel in self.channels.iter_mut() {
|
||||
if channel.get_audio_type() == AudioType::Sfx {
|
||||
channel.set_volume(volume);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_music_volume(&mut self, volume: f32) {
|
||||
self.music_volume = volume;
|
||||
|
||||
for channel in self.channels.iter_mut() {
|
||||
if channel.get_audio_type() == AudioType::Music {
|
||||
channel.set_volume(volume);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: figure out how badly this will break things when it is called
|
||||
pub fn set_device(&mut self, name: String) {
|
||||
self.device = name.clone();
|
||||
self.audio_device = get_device_raw(&name);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn select_random_music() -> String {
|
||||
let soundtracks = load_soundtracks();
|
||||
let index = rand::random::<usize>() % soundtracks.len();
|
||||
soundtracks[index].clone()
|
||||
}
|
||||
|
||||
/// Returns the default audio device.
|
||||
/// Does not return rodio Device struct in case our audio backend changes.
|
||||
pub fn get_default_device() -> String {
|
||||
rodio::default_output_device()
|
||||
.expect("No audio output devices detected.")
|
||||
.name()
|
||||
}
|
||||
|
||||
/// Load the audio file directory selected by genre.
|
||||
pub fn load_soundtracks() -> Vec<String> {
|
||||
let assets = assets::read_dir("voxygen.audio.soundtrack").unwrap();
|
||||
let soundtracks = assets
|
||||
.filter_map(|entry| {
|
||||
entry.ok().map(|f| {
|
||||
let path = f.path();
|
||||
path.to_string_lossy().into_owned()
|
||||
})
|
||||
})
|
||||
.collect::<Vec<String>>();
|
||||
|
||||
soundtracks
|
||||
}
|
||||
|
||||
/// Returns a vec of the audio devices available.
|
||||
/// Does not return rodio Device struct in case our audio backend changes.
|
||||
pub fn list_devices() -> Vec<String> {
|
||||
list_devices_raw().iter().map(|x| x.name()).collect()
|
||||
}
|
||||
|
||||
/// Returns vec of devices
|
||||
fn list_devices_raw() -> Vec<Device> {
|
||||
rodio::output_devices().collect()
|
||||
}
|
||||
|
||||
fn get_device_raw(device: &str) -> Option<Device> {
|
||||
rodio::output_devices().find(|d| d.name() == device)
|
||||
}
|
||||
|
53
voxygen/src/audio/soundcache.rs
Normal file
53
voxygen/src/audio/soundcache.rs
Normal file
@ -0,0 +1,53 @@
|
||||
use common::assets;
|
||||
use hashbrown::HashMap;
|
||||
use rodio;
|
||||
use std::convert::AsRef;
|
||||
use std::io;
|
||||
use std::io::Read;
|
||||
use std::sync::Arc;
|
||||
|
||||
// Implementation of sound taken from this github issue:
|
||||
// https://github.com/RustAudio/rodio/issues/141
|
||||
pub struct Sound(Arc<Vec<u8>>);
|
||||
|
||||
impl AsRef<[u8]> for Sound {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Sound {
|
||||
pub fn load(filename: &str) -> Result<Sound, assets::Error> {
|
||||
let mut file = assets::load_file(filename, &["wav"])?;
|
||||
let mut buf = Vec::new();
|
||||
file.read_to_end(&mut buf)?;
|
||||
Ok(Sound(Arc::new(buf)))
|
||||
}
|
||||
|
||||
pub fn cursor(&self) -> io::Cursor<Sound> {
|
||||
io::Cursor::new(Sound(self.0.clone()))
|
||||
}
|
||||
|
||||
pub fn decoder(&self) -> rodio::Decoder<io::Cursor<Sound>> {
|
||||
rodio::Decoder::new(self.cursor()).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SoundCache {
|
||||
sounds: HashMap<String, Sound>,
|
||||
}
|
||||
|
||||
impl SoundCache {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
sounds: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load_sound(&mut self, name: &str) -> rodio::Decoder<io::Cursor<Sound>> {
|
||||
self.sounds
|
||||
.entry(name.to_string())
|
||||
.or_insert(Sound::load(name).unwrap())
|
||||
.decoder()
|
||||
}
|
||||
}
|
@ -2,7 +2,6 @@ use super::{
|
||||
img_ids::Imgs, BarNumbers, CrosshairType, Fonts, ShortcutNumbers, Show, XpBar, TEXT_COLOR,
|
||||
};
|
||||
use crate::{
|
||||
audio::base::Genre,
|
||||
ui::{ImageSlider, ScaleMode, ToggleButton},
|
||||
GlobalState,
|
||||
};
|
||||
@ -1251,39 +1250,26 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
}
|
||||
|
||||
// Audio Device Selector --------------------------------------------
|
||||
match self.global_state.audio.model.get_genre() {
|
||||
Genre::Bgm => {
|
||||
let device = &self.global_state.audio.default_device;
|
||||
let device_list = &self.global_state.audio.device_list;
|
||||
Text::new("Volume")
|
||||
.down_from(state.ids.audio_volume_slider, 10.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.opensans)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.audio_device_text, ui);
|
||||
let device = &self.global_state.audio.device;
|
||||
let device_list = &self.global_state.audio.device_list;
|
||||
Text::new("Volume")
|
||||
.down_from(state.ids.audio_volume_slider, 10.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.opensans)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.audio_device_text, ui);
|
||||
|
||||
// Get which device is currently selected
|
||||
let selected = device_list.iter().position(|x| x.contains(device));
|
||||
// Get which device is currently selected
|
||||
let selected = device_list.iter().position(|x| x.contains(device));
|
||||
|
||||
if let Some(clicked) = DropDownList::new(&device_list, selected)
|
||||
.w_h(400.0, 22.0)
|
||||
.down_from(state.ids.audio_device_text, 10.0)
|
||||
.label_font_id(self.fonts.opensans)
|
||||
.set(state.ids.audio_device_list, ui)
|
||||
{
|
||||
let new_val = device_list[clicked].clone();
|
||||
events.push(Event::ChangeAudioDevice(new_val));
|
||||
}
|
||||
}
|
||||
Genre::Sfx => unimplemented!(),
|
||||
Genre::None => {
|
||||
Text::new("Volume")
|
||||
.down_from(state.ids.audio_volume_slider, 10.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.opensans)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.audio_device_text, ui);
|
||||
}
|
||||
if let Some(clicked) = DropDownList::new(&device_list, selected)
|
||||
.w_h(400.0, 22.0)
|
||||
.down_from(state.ids.audio_device_text, 10.0)
|
||||
.label_font_id(self.fonts.opensans)
|
||||
.set(state.ids.audio_device_list, ui)
|
||||
{
|
||||
let new_val = device_list[clicked].clone();
|
||||
events.push(Event::ChangeAudioDevice(new_val));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,10 +31,7 @@ pub mod window;
|
||||
// Reexports
|
||||
pub use crate::error::Error;
|
||||
|
||||
use crate::{
|
||||
audio::base::Genre, audio::AudioFrontend, menu::main::MainMenuState, settings::Settings,
|
||||
window::Window,
|
||||
};
|
||||
use crate::{audio::AudioFrontend, menu::main::MainMenuState, settings::Settings, window::Window};
|
||||
use heaptrack::track_mem;
|
||||
use log::{self, debug, error, info};
|
||||
|
||||
@ -58,9 +55,8 @@ impl GlobalState {
|
||||
self.window.needs_refresh_resize();
|
||||
}
|
||||
|
||||
pub fn maintain(&mut self) {
|
||||
// TODO: Maintain both `Bgm` and `Sfx` audio threads.
|
||||
self.audio.play();
|
||||
pub fn maintain(&mut self, dt: f32) {
|
||||
self.audio.maintain(dt);
|
||||
}
|
||||
}
|
||||
|
||||
@ -108,6 +104,22 @@ fn main() {
|
||||
if let Err(err) = settings.save_to_file() {
|
||||
panic!("Failed to save settings: {:?}", err);
|
||||
}
|
||||
let audio_device = match &settings.audio.audio_device {
|
||||
Some(d) => d.to_string(),
|
||||
None => audio::get_default_device(),
|
||||
};
|
||||
let audio = if settings.audio.audio_on {
|
||||
AudioFrontend::new(audio_device, 16)
|
||||
} else {
|
||||
AudioFrontend::no_audio()
|
||||
};
|
||||
|
||||
let mut global_state = GlobalState {
|
||||
audio,
|
||||
window: Window::new(&settings).expect("Failed to create window!"),
|
||||
settings,
|
||||
};
|
||||
let settings = &global_state.settings;
|
||||
|
||||
// Initialize logging.
|
||||
let term_log_level = std::env::var_os("VOXYGEN_LOG")
|
||||
@ -186,39 +198,6 @@ fn main() {
|
||||
default_hook(panic_info);
|
||||
}));
|
||||
|
||||
// Set up the global state.
|
||||
let audio = if settings.audio.audio_on {
|
||||
AudioFrontend::new()
|
||||
} else {
|
||||
AudioFrontend::no_audio()
|
||||
};
|
||||
|
||||
let mut global_state = GlobalState {
|
||||
audio,
|
||||
window: Window::new(&settings).expect("Failed to create window!"),
|
||||
settings,
|
||||
};
|
||||
|
||||
// Initialize discord. (lazy_static initalise lazily...)
|
||||
#[cfg(feature = "discord")]
|
||||
{
|
||||
match DISCORD_INSTANCE.lock() {
|
||||
Ok(_disc) => {
|
||||
//great
|
||||
}
|
||||
Err(e) => log::error!("Couldn't init discord: {}", e),
|
||||
}
|
||||
}
|
||||
|
||||
match global_state.audio.model.get_genre() {
|
||||
Genre::Bgm => {
|
||||
global_state.settings.audio.audio_device =
|
||||
Some(crate::audio::base::get_default_device())
|
||||
}
|
||||
Genre::Sfx => unimplemented!(),
|
||||
Genre::None => global_state.settings.audio.audio_device = None,
|
||||
}
|
||||
|
||||
// Set up the initial play state.
|
||||
let mut states: Vec<Box<dyn PlayState>> = vec![Box::new(MainMenuState::new(&mut global_state))];
|
||||
states
|
||||
|
@ -78,7 +78,7 @@ impl PlayState for CharSelectionState {
|
||||
}
|
||||
|
||||
// Maintain global state.
|
||||
global_state.maintain();
|
||||
global_state.maintain(clock.get_last_delta().as_secs_f32());
|
||||
|
||||
// Maintain the scene.
|
||||
self.scene.maintain(
|
||||
|
@ -76,7 +76,7 @@ impl PlayState for MainMenuState {
|
||||
}
|
||||
|
||||
// Maintain global_state
|
||||
global_state.maintain();
|
||||
global_state.maintain(clock.get_last_delta().as_secs_f32());
|
||||
|
||||
// Maintain the UI.
|
||||
for event in self.main_menu_ui.maintain(global_state) {
|
||||
|
@ -1,13 +1,16 @@
|
||||
pub mod camera;
|
||||
pub mod figure;
|
||||
pub mod sound;
|
||||
pub mod terrain;
|
||||
|
||||
use self::{
|
||||
camera::{Camera, CameraMode},
|
||||
figure::FigureMgr,
|
||||
sound::SoundMgr,
|
||||
terrain::Terrain,
|
||||
};
|
||||
use crate::{
|
||||
audio::AudioFrontend,
|
||||
render::{
|
||||
create_pp_mesh, create_skybox_mesh, Consts, Globals, Light, Model, PostProcessLocals,
|
||||
PostProcessPipeline, Renderer, SkyboxLocals, SkyboxPipeline,
|
||||
@ -46,6 +49,7 @@ pub struct Scene {
|
||||
loaded_distance: f32,
|
||||
|
||||
figure_mgr: FigureMgr,
|
||||
sound_mgr: SoundMgr,
|
||||
}
|
||||
|
||||
impl Scene {
|
||||
@ -71,6 +75,7 @@ impl Scene {
|
||||
terrain: Terrain::new(renderer),
|
||||
loaded_distance: 0.0,
|
||||
figure_mgr: FigureMgr::new(),
|
||||
sound_mgr: SoundMgr::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -115,7 +120,12 @@ impl Scene {
|
||||
}
|
||||
|
||||
/// Maintain data such as GPU constant buffers, models, etc. To be called once per tick.
|
||||
pub fn maintain(&mut self, renderer: &mut Renderer, client: &Client) {
|
||||
pub fn maintain(
|
||||
&mut self,
|
||||
renderer: &mut Renderer,
|
||||
audio: &mut AudioFrontend,
|
||||
client: &Client,
|
||||
) {
|
||||
// Get player position.
|
||||
let player_pos = client
|
||||
.state()
|
||||
@ -219,6 +229,9 @@ impl Scene {
|
||||
|
||||
// Remove unused figures.
|
||||
self.figure_mgr.clean(client.get_tick());
|
||||
|
||||
// Maintain audio
|
||||
self.sound_mgr.maintain(audio, client);
|
||||
}
|
||||
|
||||
/// Render the scene using the provided `Renderer`.
|
||||
|
67
voxygen/src/scene/sound.rs
Normal file
67
voxygen/src/scene/sound.rs
Normal file
@ -0,0 +1,67 @@
|
||||
use crate::audio::AudioFrontend;
|
||||
use client::Client;
|
||||
use common::comp::{Body, CharacterState, MovementState::*, Ori, Pos};
|
||||
use hashbrown::HashMap;
|
||||
use specs::{Entity as EcsEntity, Join};
|
||||
use std::time::Instant;
|
||||
use vek::*;
|
||||
|
||||
pub struct AnimState {
|
||||
last_step_sound: Instant,
|
||||
}
|
||||
|
||||
pub struct SoundMgr {
|
||||
character_states: HashMap<EcsEntity, AnimState>,
|
||||
}
|
||||
|
||||
impl SoundMgr {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
character_states: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn maintain(&mut self, audio: &mut AudioFrontend, client: &Client) {
|
||||
let ecs = client.state().ecs();
|
||||
// Get player position.
|
||||
let player_pos = ecs
|
||||
.read_storage::<Pos>()
|
||||
.get(client.entity())
|
||||
.map_or(Vec3::zero(), |pos| pos.0);
|
||||
|
||||
let player_ori = ecs
|
||||
.read_storage::<Ori>()
|
||||
.get(client.entity())
|
||||
.map_or(Vec3::zero(), |pos| pos.0);
|
||||
|
||||
audio.set_listener_pos(&player_pos, &player_ori);
|
||||
|
||||
for (entity, pos, body, character) in (
|
||||
&ecs.entities(),
|
||||
&ecs.read_storage::<Pos>(),
|
||||
&ecs.read_storage::<Body>(),
|
||||
ecs.read_storage::<CharacterState>().maybe(),
|
||||
)
|
||||
.join()
|
||||
{
|
||||
if let (Body::Humanoid(_), Some(character)) = (body, character) {
|
||||
let state = self
|
||||
.character_states
|
||||
.entry(entity)
|
||||
.or_insert_with(|| AnimState {
|
||||
last_step_sound: Instant::now(),
|
||||
});
|
||||
|
||||
if character.movement == Run && state.last_step_sound.elapsed().as_secs_f64() > 0.25
|
||||
{
|
||||
let rand_step = (rand::random::<usize>() % 7) + 1;
|
||||
audio.play_sound(
|
||||
&format!("voxygen.audio.footsteps.stepdirt_{}", rand_step),
|
||||
pos.0,
|
||||
);
|
||||
state.last_step_sound = Instant::now();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -271,7 +271,7 @@ impl PlayState for SessionState {
|
||||
}
|
||||
|
||||
// Maintain global state.
|
||||
global_state.maintain();
|
||||
global_state.maintain(clock.get_last_delta().as_secs_f32());
|
||||
|
||||
// Extract HUD events ensuring the client borrow gets dropped.
|
||||
let hud_events = self.hud.maintain(
|
||||
@ -357,13 +357,13 @@ impl PlayState for SessionState {
|
||||
}
|
||||
|
||||
HudEvent::AdjustVolume(volume) => {
|
||||
global_state.audio.model.player.set_volume(volume);
|
||||
global_state.audio.set_music_volume(volume);
|
||||
|
||||
global_state.settings.audio.music_volume = volume;
|
||||
global_state.settings.save_to_file_warn();
|
||||
}
|
||||
HudEvent::ChangeAudioDevice(name) => {
|
||||
global_state.audio.model.player.set_device(&name.clone());
|
||||
global_state.audio.set_device(name.clone());
|
||||
|
||||
global_state.settings.audio.audio_device = Some(name);
|
||||
global_state.settings.save_to_file_warn();
|
||||
@ -388,8 +388,11 @@ impl PlayState for SessionState {
|
||||
}
|
||||
|
||||
// Maintain the scene.
|
||||
self.scene
|
||||
.maintain(global_state.window.renderer_mut(), &self.client.borrow());
|
||||
self.scene.maintain(
|
||||
global_state.window.renderer_mut(),
|
||||
&mut global_state.audio,
|
||||
&self.client.borrow(),
|
||||
);
|
||||
|
||||
// Render the session.
|
||||
self.render(global_state.window.renderer_mut());
|
||||
|
Loading…
Reference in New Issue
Block a user