mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'shandley/audio-channel-types' into 'master'
Use non-spatial audio sinks for music Closes #463 See merge request veloren/veloren!794
This commit is contained in:
commit
a08fc287ae
55
Cargo.lock
generated
55
Cargo.lock
generated
@ -391,11 +391,6 @@ dependencies = [
|
|||||||
"unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "claxon"
|
|
||||||
version = "0.4.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clipboard-win"
|
name = "clipboard-win"
|
||||||
version = "2.2.0"
|
version = "2.2.0"
|
||||||
@ -1583,14 +1578,6 @@ name = "lzw"
|
|||||||
version = "0.10.0"
|
version = "0.10.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "mach"
|
|
||||||
version = "0.2.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "malloc_buf"
|
name = "malloc_buf"
|
||||||
version = "0.0.6"
|
version = "0.0.6"
|
||||||
@ -1666,23 +1653,6 @@ dependencies = [
|
|||||||
"x11-dl 2.18.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"x11-dl 2.18.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "minimp3"
|
|
||||||
version = "0.3.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"minimp3-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"slice-deque 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "minimp3-sys"
|
|
||||||
version = "0.3.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mio"
|
name = "mio"
|
||||||
version = "0.6.21"
|
version = "0.6.21"
|
||||||
@ -2555,15 +2525,13 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rodio"
|
name = "rodio"
|
||||||
version = "0.9.0"
|
version = "0.10.0"
|
||||||
source = "git+https://github.com/RustAudio/rodio?rev=e5474a2#e5474a2ef15f2d0a3bae2538de159b6d3e5bdf79"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"claxon 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"cpal 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cpal 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"hound 3.4.0 (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)",
|
"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)",
|
"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)",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -2816,16 +2784,6 @@ name = "slab"
|
|||||||
version = "0.4.2"
|
version = "0.4.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "slice-deque"
|
|
||||||
version = "0.2.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"mach 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smallvec"
|
name = "smallvec"
|
||||||
version = "0.6.13"
|
version = "0.6.13"
|
||||||
@ -3300,7 +3258,7 @@ dependencies = [
|
|||||||
"msgbox 0.4.0 (git+https://github.com/bekker/msgbox-rs.git?rev=68fe39a)",
|
"msgbox 0.4.0 (git+https://github.com/bekker/msgbox-rs.git?rev=68fe39a)",
|
||||||
"num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rodio 0.9.0 (git+https://github.com/RustAudio/rodio?rev=e5474a2)",
|
"rodio 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -3654,7 +3612,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
"checksum chunked_transfer 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "498d20a7aaf62625b9bf26e637cf7736417cde1d0c99f1d04d1170229a85cf87"
|
"checksum chunked_transfer 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "498d20a7aaf62625b9bf26e637cf7736417cde1d0c99f1d04d1170229a85cf87"
|
||||||
"checksum clang-sys 0.28.1 (registry+https://github.com/rust-lang/crates.io-index)" = "81de550971c976f176130da4b2978d3b524eaa0fd9ac31f3ceb5ae1231fb4853"
|
"checksum clang-sys 0.28.1 (registry+https://github.com/rust-lang/crates.io-index)" = "81de550971c976f176130da4b2978d3b524eaa0fd9ac31f3ceb5ae1231fb4853"
|
||||||
"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
|
"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
|
||||||
"checksum claxon 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f86c952727a495bda7abaf09bafdee1a939194dd793d9a8e26281df55ac43b00"
|
|
||||||
"checksum clipboard-win 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3a093d6fed558e5fe24c3dfc85a68bb68f1c824f440d3ba5aca189e2998786b"
|
"checksum clipboard-win 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3a093d6fed558e5fe24c3dfc85a68bb68f1c824f440d3ba5aca189e2998786b"
|
||||||
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
|
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
|
||||||
"checksum cocoa 0.18.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1706996401131526e36b3b49f0c4d912639ce110996f3ca144d78946727bce54"
|
"checksum cocoa 0.18.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1706996401131526e36b3b49f0c4d912639ce110996f3ca144d78946727bce54"
|
||||||
@ -3782,7 +3739,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
|
"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
|
||||||
"checksum lz4-compress 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f966533a922a9bba9e95e594c1fdb3b9bf5fdcdb11e37e51ad84cd76e468b91"
|
"checksum lz4-compress 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f966533a922a9bba9e95e594c1fdb3b9bf5fdcdb11e37e51ad84cd76e468b91"
|
||||||
"checksum lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d947cbb889ed21c2a84be6ffbaebf5b4e0f4340638cba0444907e38b56be084"
|
"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 malloc_buf 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb"
|
||||||
"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
|
"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
|
||||||
"checksum maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
|
"checksum maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
|
||||||
@ -3792,8 +3748,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
"checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0"
|
"checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0"
|
||||||
"checksum mime_guess 1.8.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0d977de9ee851a0b16e932979515c0f3da82403183879811bc97d50bd9cc50f7"
|
"checksum mime_guess 1.8.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0d977de9ee851a0b16e932979515c0f3da82403183879811bc97d50bd9cc50f7"
|
||||||
"checksum minifb 0.13.0 (git+https://github.com/emoon/rust_minifb.git)" = "<none>"
|
"checksum minifb 0.13.0 (git+https://github.com/emoon/rust_minifb.git)" = "<none>"
|
||||||
"checksum minimp3 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "542e9bed56860c5070a09939eee0e2df6f8f73f60304ddf56d620947e7017239"
|
|
||||||
"checksum minimp3-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c109ae05c00ad6e3a53fab101e2f234545bdd010f0fffd399355efaf70817817"
|
|
||||||
"checksum mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)" = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f"
|
"checksum mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)" = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f"
|
||||||
"checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40"
|
"checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40"
|
||||||
"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
|
"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
|
||||||
@ -3888,7 +3842,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
"checksum regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "92b73c2a1770c255c240eaa4ee600df1704a38dc3feaa6e949e7fcd4f8dc09f9"
|
"checksum regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "92b73c2a1770c255c240eaa4ee600df1704a38dc3feaa6e949e7fcd4f8dc09f9"
|
||||||
"checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716"
|
"checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716"
|
||||||
"checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e"
|
"checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e"
|
||||||
"checksum rodio 0.9.0 (git+https://github.com/RustAudio/rodio?rev=e5474a2)" = "<none>"
|
"checksum rodio 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1e0e0dfa7c8b17c6428f6e992a22ea595922cc86f946191b6b59e7ce96b77262"
|
||||||
"checksum ron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2ece421e0c4129b90e4a35b6f625e472e96c552136f5093a2f4fa2bbb75a62d5"
|
"checksum ron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2ece421e0c4129b90e4a35b6f625e472e96c552136f5093a2f4fa2bbb75a62d5"
|
||||||
"checksum roots 0.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e4c67c712ab62be58b24ab8960e2b95dd4ee00aac115c76f2709657821fe376d"
|
"checksum roots 0.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e4c67c712ab62be58b24ab8960e2b95dd4ee00aac115c76f2709657821fe376d"
|
||||||
"checksum rouille 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "112568052ec17fa26c6c11c40acbb30d3ad244bf3d6da0be181f5e7e42e5004f"
|
"checksum rouille 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "112568052ec17fa26c6c11c40acbb30d3ad244bf3d6da0be181f5e7e42e5004f"
|
||||||
@ -3919,7 +3873,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
"checksum shrev 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b5752e017e03af9d735b4b069f53b7a7fd90fefafa04d8bd0c25581b0bff437f"
|
"checksum shrev 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b5752e017e03af9d735b4b069f53b7a7fd90fefafa04d8bd0c25581b0bff437f"
|
||||||
"checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac"
|
"checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac"
|
||||||
"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
|
"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
|
||||||
"checksum slice-deque 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ffddf594f5f597f63533d897427a570dbaa9feabaaa06595b74b71b7014507d7"
|
|
||||||
"checksum smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6"
|
"checksum smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6"
|
||||||
"checksum smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ecf3b85f68e8abaa7555aa5abdb1153079387e60b718283d732f03897fcfc86"
|
"checksum smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ecf3b85f68e8abaa7555aa5abdb1153079387e60b718283d732f03897fcfc86"
|
||||||
"checksum smithay-client-toolkit 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2ccb8c57049b2a34d2cc2b203fa785020ba0129d31920ef0d317430adaf748fa"
|
"checksum smithay-client-toolkit 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2ccb8c57049b2a34d2cc2b203fa785020ba0129d31920ef0d317430adaf748fa"
|
||||||
|
@ -55,8 +55,7 @@ num = "0.2.0"
|
|||||||
backtrace = "0.3.40"
|
backtrace = "0.3.40"
|
||||||
rand = "0.7.2"
|
rand = "0.7.2"
|
||||||
treeculler = { git = "https://gitlab.com/yusdacra/treeculler.git" }
|
treeculler = { git = "https://gitlab.com/yusdacra/treeculler.git" }
|
||||||
# context for pinning to commit: https://gitlab.com/veloren/veloren/issues/280
|
rodio = { version = "0.10", default-features = false, features = ["wav", "vorbis"] }
|
||||||
rodio = { git = "https://github.com/RustAudio/rodio", rev = "e5474a2"}
|
|
||||||
cpal = "0.10"
|
cpal = "0.10"
|
||||||
crossbeam = "=0.7.2"
|
crossbeam = "=0.7.2"
|
||||||
hashbrown = { version = "0.6.2", features = ["rayon", "serde", "nightly"] }
|
hashbrown = { version = "0.6.2", features = ["rayon", "serde", "nightly"] }
|
||||||
|
@ -1,51 +1,125 @@
|
|||||||
use crate::audio::fader::Fader;
|
use crate::audio::fader::{FadeDirection, Fader};
|
||||||
use rodio::{Device, Sample, Source, SpatialSink};
|
use rodio::{Device, Sample, Sink, Source, SpatialSink};
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Copy)]
|
|
||||||
pub enum AudioType {
|
|
||||||
Sfx,
|
|
||||||
Music,
|
|
||||||
None,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Copy)]
|
#[derive(PartialEq, Clone, Copy)]
|
||||||
enum ChannelState {
|
enum ChannelState {
|
||||||
// Init,
|
|
||||||
// ToPlay,
|
|
||||||
// Loading,
|
|
||||||
Playing,
|
Playing,
|
||||||
Stopping,
|
Fading,
|
||||||
Stopped,
|
Stopped,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Each MusicChannel has a MusicChannelTag which help us determine how we
|
||||||
|
/// should transition between music types
|
||||||
#[derive(PartialEq, Clone, Copy)]
|
#[derive(PartialEq, Clone, Copy)]
|
||||||
pub enum ChannelTag {
|
pub enum MusicChannelTag {
|
||||||
TitleMusic,
|
TitleMusic,
|
||||||
Soundtrack,
|
Exploration,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Channel {
|
/// A MusicChannel uses a non-positional audio sink designed to play music which
|
||||||
id: usize,
|
/// is always heard at the player's position
|
||||||
sink: SpatialSink,
|
pub struct MusicChannel {
|
||||||
audio_type: AudioType,
|
tag: MusicChannelTag,
|
||||||
|
sink: Sink,
|
||||||
state: ChannelState,
|
state: ChannelState,
|
||||||
fader: Fader,
|
fader: Fader,
|
||||||
tag: Option<ChannelTag>,
|
}
|
||||||
|
|
||||||
|
impl MusicChannel {
|
||||||
|
pub fn new(device: &Device) -> Self {
|
||||||
|
Self {
|
||||||
|
sink: Sink::new(device),
|
||||||
|
tag: MusicChannelTag::TitleMusic,
|
||||||
|
state: ChannelState::Stopped,
|
||||||
|
fader: Fader::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Play a music track item on this channel. If the channel has an existing track
|
||||||
|
// playing, the new sounds will be appended and played once they complete.
|
||||||
|
// Otherwise it will begin playing immediately.
|
||||||
|
pub fn play<S>(&mut self, source: S, tag: MusicChannelTag)
|
||||||
|
where
|
||||||
|
S: Source + Send + 'static,
|
||||||
|
S::Item: Sample,
|
||||||
|
S::Item: Send,
|
||||||
|
<S as std::iter::Iterator>::Item: std::fmt::Debug,
|
||||||
|
{
|
||||||
|
self.tag = tag;
|
||||||
|
self.sink.append(source);
|
||||||
|
|
||||||
|
self.state = if !self.fader.is_finished() {
|
||||||
|
ChannelState::Fading
|
||||||
|
} else {
|
||||||
|
ChannelState::Playing
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the volume of the current channel. If the channel is currently
|
||||||
|
/// fading, the volume of the fader is updated to this value.
|
||||||
|
pub fn set_volume(&mut self, volume: f32) {
|
||||||
|
if !self.fader.is_finished() {
|
||||||
|
self.fader.update_target_volume(volume);
|
||||||
|
} else {
|
||||||
|
self.sink.set_volume(volume);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set a fader for the channel. If a fader exists already, it is replaced.
|
||||||
|
/// If the channel has not begun playing, and the fader is set to fade in,
|
||||||
|
/// we set the volume of the channel to the initial volume of the fader so
|
||||||
|
/// that the volumes match when playing begins.
|
||||||
|
pub fn set_fader(&mut self, fader: Fader) {
|
||||||
|
self.fader = fader;
|
||||||
|
self.state = ChannelState::Fading;
|
||||||
|
|
||||||
|
if self.state == ChannelState::Stopped && fader.direction() == FadeDirection::In {
|
||||||
|
self.sink.set_volume(fader.get_volume());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns true if either the channels sink reports itself as empty (no
|
||||||
|
/// more sounds in the queue) or we have forcibly set the channels state to
|
||||||
|
/// the 'Stopped' state
|
||||||
|
pub fn is_done(&self) -> bool { self.sink.empty() || self.state == ChannelState::Stopped }
|
||||||
|
|
||||||
|
pub fn get_tag(&self) -> MusicChannelTag { self.tag }
|
||||||
|
|
||||||
|
/// Maintain the fader attached to this channel. If the channel is not
|
||||||
|
/// fading, no action is taken.
|
||||||
|
pub fn maintain(&mut self, dt: f32) {
|
||||||
|
if self.state == ChannelState::Fading {
|
||||||
|
self.fader.update(dt);
|
||||||
|
self.sink.set_volume(self.fader.get_volume());
|
||||||
|
|
||||||
|
if self.fader.is_finished() {
|
||||||
|
match self.fader.direction() {
|
||||||
|
FadeDirection::Out => {
|
||||||
|
self.state = ChannelState::Stopped;
|
||||||
|
self.sink.stop();
|
||||||
|
},
|
||||||
|
FadeDirection::In => {
|
||||||
|
self.state = ChannelState::Playing;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An SfxChannel uses a positional audio sink, and is designed for short-lived
|
||||||
|
/// audio which can be spatially controlled, but does not need control over
|
||||||
|
/// playback or fading/transitions
|
||||||
|
pub struct SfxChannel {
|
||||||
|
sink: SpatialSink,
|
||||||
pub pos: Vec3<f32>,
|
pub pos: Vec3<f32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Implement asynchronous loading
|
impl SfxChannel {
|
||||||
impl Channel {
|
|
||||||
/// Create an empty channel for future use
|
|
||||||
pub fn new(device: &Device) -> Self {
|
pub fn new(device: &Device) -> Self {
|
||||||
Self {
|
Self {
|
||||||
id: 0,
|
|
||||||
sink: SpatialSink::new(device, [0.0; 3], [1.0, 0.0, 0.0], [-1.0, 0.0, 0.0]),
|
sink: SpatialSink::new(device, [0.0; 3], [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),
|
|
||||||
tag: None,
|
|
||||||
pos: Vec3::zero(),
|
pos: Vec3::zero(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -57,31 +131,13 @@ impl Channel {
|
|||||||
S::Item: Send,
|
S::Item: Send,
|
||||||
<S as std::iter::Iterator>::Item: std::fmt::Debug,
|
<S as std::iter::Iterator>::Item: std::fmt::Debug,
|
||||||
{
|
{
|
||||||
self.state = ChannelState::Playing;
|
|
||||||
self.sink.append(source);
|
self.sink.append(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_done(&self) -> bool { self.sink.empty() || self.state == ChannelState::Stopped }
|
|
||||||
|
|
||||||
pub fn set_tag(&mut self, tag: Option<ChannelTag>) { self.tag = tag; }
|
|
||||||
|
|
||||||
pub fn get_tag(&self) -> Option<ChannelTag> { self.tag }
|
|
||||||
|
|
||||||
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_audio_type(&mut self, audio_type: AudioType) { self.audio_type = audio_type; }
|
|
||||||
|
|
||||||
pub fn set_volume(&mut self, volume: f32) { self.sink.set_volume(volume); }
|
pub fn set_volume(&mut self, volume: f32) { self.sink.set_volume(volume); }
|
||||||
|
|
||||||
|
pub fn is_done(&self) -> bool { self.sink.empty() }
|
||||||
|
|
||||||
pub fn set_emitter_position(&mut self, pos: [f32; 3]) { self.sink.set_emitter_position(pos); }
|
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_left_ear_position(&mut self, pos: [f32; 3]) { self.sink.set_left_ear_position(pos); }
|
||||||
@ -89,20 +145,4 @@ impl Channel {
|
|||||||
pub fn set_right_ear_position(&mut self, pos: [f32; 3]) {
|
pub fn set_right_ear_position(&mut self, pos: [f32; 3]) {
|
||||||
self.sink.set_right_ear_position(pos);
|
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 => {},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -6,13 +6,18 @@ pub struct Fader {
|
|||||||
volume_to: f32,
|
volume_to: f32,
|
||||||
is_running: bool,
|
is_running: bool,
|
||||||
}
|
}
|
||||||
|
#[derive(Debug, PartialEq, Clone, Copy)]
|
||||||
|
pub enum FadeDirection {
|
||||||
|
In,
|
||||||
|
Out,
|
||||||
|
}
|
||||||
|
|
||||||
fn lerp(t: f32, a: f32, b: f32) -> f32 { (1.0 - t) * a + t * b }
|
fn lerp(t: f32, a: f32, b: f32) -> f32 { (1.0 - t) * a + t * b }
|
||||||
|
|
||||||
impl Fader {
|
impl Fader {
|
||||||
pub fn fade(time: f32, volume_from: f32, volume_to: f32) -> Self {
|
pub fn fade(length: f32, volume_from: f32, volume_to: f32) -> Self {
|
||||||
Self {
|
Self {
|
||||||
length: time,
|
length,
|
||||||
running_time: 0.0,
|
running_time: 0.0,
|
||||||
volume_from,
|
volume_from,
|
||||||
volume_to,
|
volume_to,
|
||||||
@ -20,23 +25,28 @@ impl Fader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fade_in(time: f32) -> Self {
|
pub fn fade_in(time: f32, volume_to: f32) -> Self { Self::fade(time, 0.0, volume_to) }
|
||||||
Self {
|
|
||||||
length: time,
|
pub fn fade_out(time: f32, volume_from: f32) -> Self { Self::fade(time, volume_from, 0.0) }
|
||||||
running_time: 0.0,
|
|
||||||
volume_from: 0.0,
|
pub fn update_target_volume(&mut self, volume: f32) {
|
||||||
volume_to: 1.0,
|
match self.direction() {
|
||||||
is_running: true,
|
FadeDirection::In => {
|
||||||
|
self.volume_to = volume;
|
||||||
|
},
|
||||||
|
FadeDirection::Out => {
|
||||||
|
if self.get_volume() > volume {
|
||||||
|
self.volume_from = volume;
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fade_out(time: f32, volume_from: f32) -> Self {
|
pub fn direction(&self) -> FadeDirection {
|
||||||
Self {
|
if self.volume_to < self.volume_from {
|
||||||
length: time,
|
FadeDirection::Out
|
||||||
running_time: 0.0,
|
} else {
|
||||||
volume_from,
|
FadeDirection::In
|
||||||
volume_to: 0.0,
|
|
||||||
is_running: true,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,3 +70,107 @@ impl Fader {
|
|||||||
|
|
||||||
pub fn is_finished(&self) -> bool { self.running_time >= self.length || !self.is_running }
|
pub fn is_finished(&self) -> bool { self.running_time >= self.length || !self.is_running }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a stopped fader with no running duration
|
||||||
|
impl Default for Fader {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
length: 0.0,
|
||||||
|
running_time: 0.0,
|
||||||
|
volume_from: 0.0,
|
||||||
|
volume_to: 1.0,
|
||||||
|
is_running: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn fade_direction_in() {
|
||||||
|
let fader = Fader::fade_in(10.0, 0.0);
|
||||||
|
|
||||||
|
assert_eq!(fader.direction(), FadeDirection::In);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn fade_direction_out() {
|
||||||
|
let fader = Fader::fade_out(10.0, 1.0);
|
||||||
|
|
||||||
|
assert_eq!(fader.direction(), FadeDirection::Out);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn fade_out_completes() {
|
||||||
|
let mut fader = Fader::fade_out(10.0, 1.0);
|
||||||
|
|
||||||
|
// Run for the full duration
|
||||||
|
fader.update(10.0);
|
||||||
|
|
||||||
|
assert_eq!(fader.get_volume(), 0.0);
|
||||||
|
assert!(fader.is_finished());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn update_target_volume_fading_out_when_currently_above() {
|
||||||
|
let mut fader = Fader::fade_out(20.0, 1.0);
|
||||||
|
|
||||||
|
// After 0.1s, the fader should still be close to 1.0
|
||||||
|
fader.update(0.1);
|
||||||
|
|
||||||
|
// Reduce volume to 0.4. We are currently above that.
|
||||||
|
fader.update_target_volume(0.4);
|
||||||
|
|
||||||
|
// The volume should immediately reduce to < 0.4 on the next update
|
||||||
|
fader.update(0.1);
|
||||||
|
|
||||||
|
assert!(fader.get_volume() < 0.4)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn update_target_volume_fading_out_when_currently_below() {
|
||||||
|
let mut fader = Fader::fade_out(10.0, 0.8);
|
||||||
|
|
||||||
|
// After 9s, the fader should be close to 0
|
||||||
|
fader.update(9.0);
|
||||||
|
|
||||||
|
// Notify of a volume increase to 1.0. We are already far below that.
|
||||||
|
fader.update_target_volume(1.0);
|
||||||
|
|
||||||
|
// The fader should be unaffected by the new value, and continue dropping
|
||||||
|
fader.update(0.1);
|
||||||
|
|
||||||
|
assert!(fader.get_volume() < 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn update_target_volume_fading_in_when_currently_above() {
|
||||||
|
let mut fader = Fader::fade_in(10.0, 1.0);
|
||||||
|
|
||||||
|
// After 9s, the fader should be close to 1.0
|
||||||
|
fader.update(9.0);
|
||||||
|
|
||||||
|
// Reduce volume to 0.4. We are currently above that.
|
||||||
|
fader.update_target_volume(0.4);
|
||||||
|
|
||||||
|
// Run out the fader. It's volume should be 0.4
|
||||||
|
fader.update(1.0);
|
||||||
|
|
||||||
|
assert_eq!(fader.get_volume(), 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn update_target_volume_fading_in_when_currently_below() {
|
||||||
|
let mut fader = Fader::fade_in(20.0, 1.0);
|
||||||
|
|
||||||
|
// After 0.1s, the fader should still be close to 0.0
|
||||||
|
fader.update(0.1);
|
||||||
|
|
||||||
|
// Reduce volume to 0.4. The volume_to should be reduced accordingly.
|
||||||
|
fader.update_target_volume(0.4);
|
||||||
|
|
||||||
|
assert_eq!(fader.volume_to, 0.4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -4,7 +4,7 @@ pub mod music;
|
|||||||
pub mod sfx;
|
pub mod sfx;
|
||||||
pub mod soundcache;
|
pub mod soundcache;
|
||||||
|
|
||||||
use channel::{AudioType, Channel, ChannelTag};
|
use channel::{MusicChannel, MusicChannelTag, SfxChannel};
|
||||||
use fader::Fader;
|
use fader::Fader;
|
||||||
use soundcache::SoundCache;
|
use soundcache::SoundCache;
|
||||||
|
|
||||||
@ -21,8 +21,8 @@ pub struct AudioFrontend {
|
|||||||
audio_device: Option<Device>,
|
audio_device: Option<Device>,
|
||||||
sound_cache: SoundCache,
|
sound_cache: SoundCache,
|
||||||
|
|
||||||
channels: Vec<Channel>,
|
music_channels: Vec<MusicChannel>,
|
||||||
next_channel_id: usize,
|
sfx_channels: Vec<SfxChannel>,
|
||||||
|
|
||||||
sfx_volume: f32,
|
sfx_volume: f32,
|
||||||
music_volume: f32,
|
music_volume: f32,
|
||||||
@ -36,21 +36,23 @@ pub struct AudioFrontend {
|
|||||||
|
|
||||||
impl AudioFrontend {
|
impl AudioFrontend {
|
||||||
/// Construct with given device
|
/// Construct with given device
|
||||||
pub fn new(device: String, channel_num: usize) -> Self {
|
pub fn new(device: String, max_sfx_channels: usize) -> Self {
|
||||||
let mut channels = Vec::with_capacity(channel_num);
|
let mut sfx_channels = Vec::with_capacity(max_sfx_channels);
|
||||||
let audio_device = get_device_raw(&device);
|
let audio_device = get_device_raw(&device);
|
||||||
|
|
||||||
if let Some(audio_device) = &audio_device {
|
if let Some(audio_device) = &audio_device {
|
||||||
for _i in 0..channel_num {
|
for _ in 0..max_sfx_channels {
|
||||||
channels.push(Channel::new(&audio_device));
|
sfx_channels.push(SfxChannel::new(&audio_device));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
device: device.clone(),
|
device: device.clone(),
|
||||||
device_list: list_devices(),
|
device_list: list_devices(),
|
||||||
audio_device,
|
audio_device,
|
||||||
sound_cache: SoundCache::new(),
|
sound_cache: SoundCache::new(),
|
||||||
channels,
|
music_channels: Vec::new(),
|
||||||
next_channel_id: 1,
|
sfx_channels,
|
||||||
sfx_volume: 1.0,
|
sfx_volume: 1.0,
|
||||||
music_volume: 1.0,
|
music_volume: 1.0,
|
||||||
listener_pos: Vec3::zero(),
|
listener_pos: Vec3::zero(),
|
||||||
@ -67,8 +69,8 @@ impl AudioFrontend {
|
|||||||
device_list: Vec::new(),
|
device_list: Vec::new(),
|
||||||
audio_device: None,
|
audio_device: None,
|
||||||
sound_cache: SoundCache::new(),
|
sound_cache: SoundCache::new(),
|
||||||
channels: Vec::new(),
|
music_channels: Vec::new(),
|
||||||
next_channel_id: 1,
|
sfx_channels: Vec::new(),
|
||||||
sfx_volume: 1.0,
|
sfx_volume: 1.0,
|
||||||
music_volume: 1.0,
|
music_volume: 1.0,
|
||||||
listener_pos: Vec3::zero(),
|
listener_pos: Vec3::zero(),
|
||||||
@ -78,40 +80,62 @@ impl AudioFrontend {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Maintain audio
|
/// Drop any unused music channels, and update their faders
|
||||||
pub fn maintain(&mut self, dt: f32) {
|
pub fn maintain(&mut self, dt: f32) {
|
||||||
for channel in self.channels.iter_mut() {
|
self.music_channels.retain(|c| !c.is_done());
|
||||||
channel.update(dt);
|
|
||||||
|
for channel in self.music_channels.iter_mut() {
|
||||||
|
channel.maintain(dt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_channel(
|
fn get_sfx_channel(&mut self) -> Option<&mut SfxChannel> {
|
||||||
|
if self.audio_device.is_some() {
|
||||||
|
if let Some(channel) = self.sfx_channels.iter_mut().find(|c| c.is_done()) {
|
||||||
|
channel.set_volume(self.sfx_volume);
|
||||||
|
|
||||||
|
return Some(channel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Retrieve a music channel from the channel list. This inspects the
|
||||||
|
/// MusicChannelTag to determine whether we are transitioning between
|
||||||
|
/// music types and acts accordingly. For example transitioning between
|
||||||
|
/// `TitleMusic` and `Exploration` should fade out the title channel and
|
||||||
|
/// fade in a new `Exploration` channel.
|
||||||
|
fn get_music_channel(
|
||||||
&mut self,
|
&mut self,
|
||||||
audio_type: AudioType,
|
next_channel_tag: MusicChannelTag,
|
||||||
channel_tag: Option<ChannelTag>,
|
) -> Option<&mut MusicChannel> {
|
||||||
) -> Option<&mut Channel> {
|
if let Some(audio_device) = &self.audio_device {
|
||||||
if let Some(channel) = self.channels.iter_mut().find(|c| c.is_done()) {
|
if self.music_channels.is_empty() {
|
||||||
let id = self.next_channel_id;
|
let mut next_music_channel = MusicChannel::new(&audio_device);
|
||||||
self.next_channel_id += 1;
|
next_music_channel.set_volume(self.music_volume);
|
||||||
|
|
||||||
let volume = match audio_type {
|
self.music_channels.push(next_music_channel);
|
||||||
AudioType::Music => self.music_volume,
|
} else {
|
||||||
_ => self.sfx_volume,
|
let existing_channel = self.music_channels.last_mut()?;
|
||||||
};
|
|
||||||
|
|
||||||
channel.set_id(id);
|
if existing_channel.get_tag() != next_channel_tag {
|
||||||
channel.set_tag(channel_tag);
|
// Fade the existing channel out. It will be removed when the fade completes.
|
||||||
channel.set_audio_type(audio_type);
|
existing_channel.set_fader(Fader::fade_out(2.0, self.music_volume));
|
||||||
channel.set_volume(volume);
|
|
||||||
|
|
||||||
Some(channel)
|
let mut next_music_channel = MusicChannel::new(&audio_device);
|
||||||
} else {
|
|
||||||
None
|
next_music_channel.set_fader(Fader::fade_in(12.0, self.music_volume));
|
||||||
|
|
||||||
|
self.music_channels.push(next_music_channel);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.music_channels.last_mut()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Play specfied sound file.
|
pub fn play_sfx(&mut self, sound: &str, pos: Vec3<f32>) {
|
||||||
pub fn play_sound(&mut self, sound: &str, pos: Vec3<f32>) -> Option<usize> {
|
|
||||||
if self.audio_device.is_some() {
|
if self.audio_device.is_some() {
|
||||||
let calc_pos = ((pos - self.listener_pos) * FALLOFF).into_array();
|
let calc_pos = ((pos - self.listener_pos) * FALLOFF).into_array();
|
||||||
|
|
||||||
@ -120,33 +144,22 @@ impl AudioFrontend {
|
|||||||
let left_ear = self.listener_ear_left.into_array();
|
let left_ear = self.listener_ear_left.into_array();
|
||||||
let right_ear = self.listener_ear_right.into_array();
|
let right_ear = self.listener_ear_right.into_array();
|
||||||
|
|
||||||
if let Some(channel) = self.get_channel(AudioType::Sfx, None) {
|
if let Some(channel) = self.get_sfx_channel() {
|
||||||
channel.set_emitter_position(calc_pos);
|
channel.set_emitter_position(calc_pos);
|
||||||
channel.set_left_ear_position(left_ear);
|
channel.set_left_ear_position(left_ear);
|
||||||
channel.set_right_ear_position(right_ear);
|
channel.set_right_ear_position(right_ear);
|
||||||
channel.play(sound);
|
channel.play(sound);
|
||||||
|
|
||||||
return Some(channel.get_id());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn play_music(&mut self, sound: &str, channel_tag: Option<ChannelTag>) -> Option<usize> {
|
fn play_music(&mut self, sound: &str, channel_tag: MusicChannelTag) {
|
||||||
if self.audio_device.is_some() {
|
if let Some(channel) = self.get_music_channel(channel_tag) {
|
||||||
if let Some(channel) = self.get_channel(AudioType::Music, channel_tag) {
|
let file = assets::load_file(&sound, &["ogg"]).expect("Failed to load sound");
|
||||||
let file = assets::load_file(&sound, &["ogg"]).expect("Failed to load sound");
|
let sound = Decoder::new(file).expect("Failed to decode sound");
|
||||||
let sound = Decoder::new(file).expect("Failed to decode sound");
|
|
||||||
|
|
||||||
channel.set_emitter_position([0.0; 3]);
|
channel.play(sound, channel_tag);
|
||||||
channel.play(sound);
|
|
||||||
|
|
||||||
return Some(channel.get_id());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_listener_pos(&mut self, pos: &Vec3<f32>, ori: &Vec3<f32>) {
|
pub fn set_listener_pos(&mut self, pos: &Vec3<f32>, ori: &Vec3<f32>) {
|
||||||
@ -161,8 +174,8 @@ impl AudioFrontend {
|
|||||||
self.listener_ear_left = pos_left;
|
self.listener_ear_left = pos_left;
|
||||||
self.listener_ear_right = pos_right;
|
self.listener_ear_right = pos_right;
|
||||||
|
|
||||||
for channel in self.channels.iter_mut() {
|
for channel in self.sfx_channels.iter_mut() {
|
||||||
if !channel.is_done() && channel.get_audio_type() == AudioType::Sfx {
|
if !channel.is_done() {
|
||||||
// TODO: Update this to correctly determine the updated relative position of
|
// TODO: Update this to correctly determine the updated relative position of
|
||||||
// the SFX emitter when the player (listener) moves
|
// the SFX emitter when the player (listener) moves
|
||||||
// channel.set_emitter_position(
|
// channel.set_emitter_position(
|
||||||
@ -174,32 +187,18 @@ impl AudioFrontend {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn play_title_music(&mut self) -> Option<usize> {
|
pub fn play_title_music(&mut self) {
|
||||||
if self.music_enabled() {
|
if self.music_enabled() {
|
||||||
self.play_music(
|
self.play_music(
|
||||||
"voxygen.audio.soundtrack.veloren_title_tune",
|
"voxygen.audio.soundtrack.veloren_title_tune",
|
||||||
Some(ChannelTag::TitleMusic),
|
MusicChannelTag::TitleMusic,
|
||||||
)
|
)
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stop_title_music(&mut self) {
|
pub fn play_exploration_music(&mut self, item: &str) {
|
||||||
let index = self.channels.iter().position(|c| {
|
if self.music_enabled() {
|
||||||
!c.is_done() && c.get_tag().is_some() && c.get_tag().unwrap() == ChannelTag::TitleMusic
|
self.play_music(item, MusicChannelTag::Exploration)
|
||||||
});
|
|
||||||
|
|
||||||
if let Some(index) = index {
|
|
||||||
self.channels[index].stop(Fader::fade_out(1.5, self.music_volume));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,24 +213,16 @@ impl AudioFrontend {
|
|||||||
pub fn set_sfx_volume(&mut self, sfx_volume: f32) {
|
pub fn set_sfx_volume(&mut self, sfx_volume: f32) {
|
||||||
self.sfx_volume = sfx_volume;
|
self.sfx_volume = sfx_volume;
|
||||||
|
|
||||||
for channel in self.channels.iter_mut() {
|
for channel in self.sfx_channels.iter_mut() {
|
||||||
if channel.get_audio_type() == AudioType::Sfx {
|
channel.set_volume(sfx_volume);
|
||||||
channel.set_volume(sfx_volume);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_music_volume(&mut self, music_volume: f32) {
|
pub fn set_music_volume(&mut self, music_volume: f32) {
|
||||||
self.music_volume = music_volume;
|
self.music_volume = music_volume;
|
||||||
|
|
||||||
for channel in self.channels.iter_mut() {
|
for channel in self.music_channels.iter_mut() {
|
||||||
if channel.get_audio_type() == AudioType::Music {
|
channel.set_volume(music_volume);
|
||||||
if music_volume > 0.0 {
|
|
||||||
channel.set_volume(music_volume);
|
|
||||||
} else {
|
|
||||||
channel.stop(Fader::fade_out(0.0, 0.0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::audio::{channel::ChannelTag, AudioFrontend};
|
use crate::audio::AudioFrontend;
|
||||||
use client::Client;
|
use client::Client;
|
||||||
use common::assets;
|
use common::assets;
|
||||||
use rand::{seq::IteratorRandom, thread_rng};
|
use rand::{seq::IteratorRandom, thread_rng};
|
||||||
@ -31,7 +31,6 @@ pub struct MusicMgr {
|
|||||||
soundtrack: SoundtrackCollection,
|
soundtrack: SoundtrackCollection,
|
||||||
began_playing: Instant,
|
began_playing: Instant,
|
||||||
next_track_change: f64,
|
next_track_change: f64,
|
||||||
current_music: Option<usize>,
|
|
||||||
last_track: String,
|
last_track: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,7 +40,6 @@ impl MusicMgr {
|
|||||||
soundtrack: Self::load_soundtrack_items(),
|
soundtrack: Self::load_soundtrack_items(),
|
||||||
began_playing: Instant::now(),
|
began_playing: Instant::now(),
|
||||||
next_track_change: 0.0,
|
next_track_change: 0.0,
|
||||||
current_music: None,
|
|
||||||
last_track: String::from("None"),
|
last_track: String::from("None"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -50,15 +48,15 @@ impl MusicMgr {
|
|||||||
if audio.music_enabled()
|
if audio.music_enabled()
|
||||||
&& self.began_playing.elapsed().as_secs_f64() > self.next_track_change
|
&& self.began_playing.elapsed().as_secs_f64() > self.next_track_change
|
||||||
{
|
{
|
||||||
self.current_music = self.play_random_track(audio, client);
|
self.play_random_track(audio, client);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn play_random_track(&mut self, audio: &mut AudioFrontend, client: &Client) -> Option<usize> {
|
fn play_random_track(&mut self, audio: &mut AudioFrontend, client: &Client) {
|
||||||
const SILENCE_BETWEEN_TRACKS_SECONDS: f64 = 45.0;
|
const SILENCE_BETWEEN_TRACKS_SECONDS: f64 = 45.0;
|
||||||
|
|
||||||
let game_time = (client.state().get_time_of_day() as u64 % 86400) as u32;
|
let game_time = (client.state().get_time_of_day() as u64 % 86400) as u32;
|
||||||
let current_period_of_day = self.get_current_day_period(game_time);
|
let current_period_of_day = Self::get_current_day_period(game_time);
|
||||||
let mut rng = thread_rng();
|
let mut rng = thread_rng();
|
||||||
|
|
||||||
let track = self
|
let track = self
|
||||||
@ -79,10 +77,10 @@ impl MusicMgr {
|
|||||||
self.began_playing = Instant::now();
|
self.began_playing = Instant::now();
|
||||||
self.next_track_change = track.length + SILENCE_BETWEEN_TRACKS_SECONDS;
|
self.next_track_change = track.length + SILENCE_BETWEEN_TRACKS_SECONDS;
|
||||||
|
|
||||||
audio.play_music(&track.path, Some(ChannelTag::Soundtrack))
|
audio.play_exploration_music(&track.path);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_current_day_period(&self, game_time: u32) -> DayPeriod {
|
fn get_current_day_period(game_time: u32) -> DayPeriod {
|
||||||
if game_time > DAY_START_SECONDS && game_time < DAY_END_SECONDS {
|
if game_time > DAY_START_SECONDS && game_time < DAY_END_SECONDS {
|
||||||
DayPeriod::Day
|
DayPeriod::Day
|
||||||
} else {
|
} else {
|
||||||
|
@ -91,7 +91,7 @@ impl SfxMgr {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
audio.play_sound(sfx_file, position);
|
audio.play_sfx(sfx_file, position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -121,7 +121,7 @@ fn main() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let mut audio = if settings.audio.audio_on {
|
let mut audio = if settings.audio.audio_on {
|
||||||
AudioFrontend::new(audio_device(), 16)
|
AudioFrontend::new(audio_device(), settings.audio.max_sfx_channels)
|
||||||
} else {
|
} else {
|
||||||
AudioFrontend::no_audio()
|
AudioFrontend::no_audio()
|
||||||
};
|
};
|
||||||
|
@ -18,7 +18,6 @@ use ui::{Event as MainMenuEvent, MainMenuUi};
|
|||||||
|
|
||||||
pub struct MainMenuState {
|
pub struct MainMenuState {
|
||||||
main_menu_ui: MainMenuUi,
|
main_menu_ui: MainMenuUi,
|
||||||
title_music_channel: Option<usize>,
|
|
||||||
singleplayer: Option<Singleplayer>,
|
singleplayer: Option<Singleplayer>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,7 +26,6 @@ impl MainMenuState {
|
|||||||
pub fn new(global_state: &mut GlobalState) -> Self {
|
pub fn new(global_state: &mut GlobalState) -> Self {
|
||||||
Self {
|
Self {
|
||||||
main_menu_ui: MainMenuUi::new(global_state),
|
main_menu_ui: MainMenuUi::new(global_state),
|
||||||
title_music_channel: None,
|
|
||||||
singleplayer: None,
|
singleplayer: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -44,11 +42,8 @@ impl PlayState for MainMenuState {
|
|||||||
let mut client_init: Option<ClientInit> = None;
|
let mut client_init: Option<ClientInit> = None;
|
||||||
|
|
||||||
// Kick off title music
|
// Kick off title music
|
||||||
if self.title_music_channel.is_none()
|
if global_state.settings.audio.audio_on && global_state.audio.music_enabled() {
|
||||||
&& global_state.settings.audio.audio_on
|
global_state.audio.play_title_music();
|
||||||
&& global_state.audio.music_enabled()
|
|
||||||
{
|
|
||||||
self.title_music_channel = global_state.audio.play_title_music();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset singleplayer server if it was running already
|
// Reset singleplayer server if it was running already
|
||||||
|
@ -126,9 +126,6 @@ impl PlayState for SessionState {
|
|||||||
let mut clock = Clock::start();
|
let mut clock = Clock::start();
|
||||||
self.client.borrow_mut().clear_terrain();
|
self.client.borrow_mut().clear_terrain();
|
||||||
|
|
||||||
// Kill the title music if it is still playing
|
|
||||||
global_state.audio.stop_title_music();
|
|
||||||
|
|
||||||
// Send startup commands to the server
|
// Send startup commands to the server
|
||||||
if global_state.settings.send_logon_commands {
|
if global_state.settings.send_logon_commands {
|
||||||
for cmd in &global_state.settings.logon_commands {
|
for cmd in &global_state.settings.logon_commands {
|
||||||
|
@ -221,6 +221,7 @@ pub struct AudioSettings {
|
|||||||
pub master_volume: f32,
|
pub master_volume: f32,
|
||||||
pub music_volume: f32,
|
pub music_volume: f32,
|
||||||
pub sfx_volume: f32,
|
pub sfx_volume: f32,
|
||||||
|
pub max_sfx_channels: usize,
|
||||||
|
|
||||||
/// Audio Device that Voxygen will use to play audio.
|
/// Audio Device that Voxygen will use to play audio.
|
||||||
pub audio_device: Option<String>,
|
pub audio_device: Option<String>,
|
||||||
@ -233,6 +234,7 @@ impl Default for AudioSettings {
|
|||||||
master_volume: 1.0,
|
master_volume: 1.0,
|
||||||
music_volume: 0.4,
|
music_volume: 0.4,
|
||||||
sfx_volume: 0.6,
|
sfx_volume: 0.6,
|
||||||
|
max_sfx_channels: 10,
|
||||||
audio_device: None,
|
audio_device: None,
|
||||||
audio_on: true,
|
audio_on: true,
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user