Merge branch 'desttinghim/sound-effects' into 'master'

Sound Effects

Closes #163 and #97

See merge request veloren/veloren!473
This commit is contained in:
Joshua Barretto 2019-09-06 11:19:32 +00:00
commit f574b1748a
36 changed files with 758 additions and 557 deletions

106
Cargo.lock generated
View File

@ -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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

BIN
assets/voxygen/audio/footsteps/stepwood_2.wav (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -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"] }

View File

@ -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)
}
}

View 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 => {}
}
}
}

View 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
}
}

View File

@ -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)
}

View 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()
}
}

View File

@ -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));
}
}

View File

@ -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

View File

@ -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(

View File

@ -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) {

View File

@ -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`.

View 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();
}
}
}
}
}

View File

@ -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());