summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOz Linden <oz@lindenlab.com>2013-04-18 14:55:28 -0400
committerOz Linden <oz@lindenlab.com>2013-04-18 14:55:28 -0400
commited2b5da8f1eb51e747f6d9f5a4fc535cbf7e69d9 (patch)
tree1971a71e793087d45501a4f291931725bb4e1753
parentf16472976ec4fe0908753e2708df26f8d7a92348 (diff)
parentadfa7d49de6d58671bc7121483e306a9f6d705ed (diff)
merge changes for DRTVWR-298
-rw-r--r--.hgtags127
-rw-r--r--autobuild.xml23
-rw-r--r--doc/contributions.txt5
-rw-r--r--indra/cmake/CMakeLists.txt4
-rw-r--r--indra/cmake/Copy3rdPartyLibs.cmake45
-rw-r--r--indra/cmake/FMOD.cmake39
-rw-r--r--indra/cmake/FMODEX.cmake46
-rw-r--r--indra/cmake/FindFMOD.cmake44
-rw-r--r--indra/cmake/FindFMODEX.cmake65
-rw-r--r--indra/llaudio/CMakeLists.txt28
-rw-r--r--indra/llaudio/llaudioengine.h1
-rw-r--r--indra/llaudio/llaudioengine_fmod.cpp781
-rw-r--r--indra/llaudio/llaudioengine_fmodex.cpp746
-rw-r--r--indra/llaudio/llaudioengine_fmodex.h (renamed from indra/llaudio/llaudioengine_fmod.h)88
-rw-r--r--indra/llaudio/lllistener_fmodex.cpp (renamed from indra/llaudio/lllistener_fmod.cpp)58
-rw-r--r--indra/llaudio/lllistener_fmodex.h (renamed from indra/llaudio/lllistener_fmod.h)21
-rw-r--r--indra/llaudio/llstreamingaudio.h2
-rw-r--r--indra/llaudio/llstreamingaudio_fmodex.cpp (renamed from indra/llaudio/llstreamingaudio_fmod.cpp)205
-rw-r--r--indra/llaudio/llstreamingaudio_fmodex.h (renamed from indra/llaudio/llstreamingaudio_fmod.h)41
-rw-r--r--indra/llaudio/llvorbisencode.cpp2
-rw-r--r--indra/llaudio/llwindgen.h34
-rw-r--r--indra/newview/CMakeLists.txt45
-rwxr-xr-xindra/newview/app_settings/settings.xml56
-rw-r--r--indra/newview/fmod_hidden_symbols.exp240
-rw-r--r--indra/newview/fmodwrapper.cpp37
-rwxr-xr-xindra/newview/linux_tools/wrapper.sh14
-rw-r--r--indra/newview/llappviewer.cpp14
-rw-r--r--indra/newview/llstartup.cpp20
-rw-r--r--indra/newview/llvieweraudio.cpp70
-rw-r--r--indra/newview/llviewercontrol.cpp1
-rw-r--r--indra/newview/viewer_manifest.py25
31 files changed, 1346 insertions, 1581 deletions
diff --git a/.hgtags b/.hgtags
index ed123d3440..9d495cfc6b 100644
--- a/.hgtags
+++ b/.hgtags
@@ -72,35 +72,35 @@ b53a0576eec80614d7767ed72b40ed67aeff27c9 DRTVWR-38_2.5.2-release
461c8c65b5c799ddfe365422f9be9c0095d91e7d 2.6.0-beta1-tip
9e4641f4a7870c0f565a25a2971368d5a29516a1 2.6.0-beta2
9e4641f4a7870c0f565a25a2971368d5a29516a1 DRTVWR-41_2.6.0-beta2
+42f32494bac475d0737799346f6831558ae8bf5d 2.6.0-release
+42f32494bac475d0737799346f6831558ae8bf5d DRTVWR-39_2.6.0-release
c5bdef3aaa2744626aef3c217ce29e1900d357b3 2.6.1-beta1
c5bdef3aaa2744626aef3c217ce29e1900d357b3 2.6.1-start
c5bdef3aaa2744626aef3c217ce29e1900d357b3 DRTVWR-43_2.6.1-beta1
+c9182ed77d427c759cfacf49a7b71a2e20d522aa 2.6.1-release
+c9182ed77d427c759cfacf49a7b71a2e20d522aa DRTVWR-42_2.6.1-release
56b2778c743c2a964d82e1caf11084d76a87de2c 2.6.2-start
d1203046bb653b763f835b04d184646949d8dd5c 2.6.2-beta1
d1203046bb653b763f835b04d184646949d8dd5c DRTVWR-45_2.6.2-beta1
-42f32494bac475d0737799346f6831558ae8bf5d 2.6.0-release
-42f32494bac475d0737799346f6831558ae8bf5d DRTVWR-39_2.6.0-release
-c9182ed77d427c759cfacf49a7b71a2e20d522aa 2.6.1-release
-c9182ed77d427c759cfacf49a7b71a2e20d522aa DRTVWR-42_2.6.1-release
+214180ad5714ce8392b82bbebcc92f4babd98300 2.6.2-release
+214180ad5714ce8392b82bbebcc92f4babd98300 DRTVWR-44_2.6.2-release
52b2263ab28f0976c689fd0b76c55a9eb027cdbf end-of-develop.py
ec32f1045e7c2644015245df3a9933620aa194b8 2.6.3-start
d7fcefabdf32bb61a9ea6d6037c1bb26190a85bc 2.6.3-beta1
d7fcefabdf32bb61a9ea6d6037c1bb26190a85bc DRTVWR-47_2.6.3-beta1
0630e977504af5ea320c58d33cae4e1ddee793e9 2.6.3-beta2
0630e977504af5ea320c58d33cae4e1ddee793e9 DRTVWR-48_2.6.3-beta2
+8f2da1701c81a62352df2b8d413d27fb2cade9a6 2.6.3-release
+8f2da1701c81a62352df2b8d413d27fb2cade9a6 DRTVWR-46_2.6.3-release
3178e311da3a8739a85363665006ea3c4610cad4 dons-headless-hackathon-work
-214180ad5714ce8392b82bbebcc92f4babd98300 2.6.2-release
-214180ad5714ce8392b82bbebcc92f4babd98300 DRTVWR-44_2.6.2-release
7db558aaa7c176f2022b3e9cfe38ac72f6d1fccd 2.6.5-beta1
7db558aaa7c176f2022b3e9cfe38ac72f6d1fccd DRTVWR-50_2.6.5-beta1
-8f2da1701c81a62352df2b8d413d27fb2cade9a6 2.6.3-release
-8f2da1701c81a62352df2b8d413d27fb2cade9a6 DRTVWR-46_2.6.3-release
800cefce8d364ffdd2f383cbecb91294da3ea424 2.6.6-start
bb1075286b3b147b1dae2e3d6b2d56f04ff03f35 2.6.6-beta1
bb1075286b3b147b1dae2e3d6b2d56f04ff03f35 DRTVWR-52_2.6.6-beta1
-5e349dbe9cc84ea5795af8aeb6d473a0af9d4953 2.6.8-start
dac76a711da5f1489a01c1fa62ec97d99c25736d 2.6.6-release
dac76a711da5f1489a01c1fa62ec97d99c25736d DRTVWR-51_2.6.6-release
+5e349dbe9cc84ea5795af8aeb6d473a0af9d4953 2.6.8-start
beafa8a9bd1d1b670b7523d865204dc4a4b38eef 2.6.8-beta1
beafa8a9bd1d1b670b7523d865204dc4a4b38eef DRTVWR-55_2.6.8-beta1
be2000b946f8cb3de5f44b2d419287d4c48ec4eb 2.6.8-release
@@ -119,50 +119,50 @@ e67da2c6e3125966dd49eef98b36317afac1fcfe 2.6.9-start
9f79a6ed8fdcd2f3dac33ea6b3236eeb278dccfe 2.7.2-start
e0dc8b741eaa27dcdfbc9e956bb2579b954d15eb 2.7.2-beta1
e0dc8b741eaa27dcdfbc9e956bb2579b954d15eb DRTVWR-63_2.7.2-beta1
-6a3e7e403bd19e45fdfc2fcc716867af3ab80861 2.7.3-start
fe3a8e7973072ea62043c08b19b66626c1a720eb 2.7.1-release
fe3a8e7973072ea62043c08b19b66626c1a720eb 2.7.2-release
fe3a8e7973072ea62043c08b19b66626c1a720eb DRTVWR-60_2.7.1-release
fe3a8e7973072ea62043c08b19b66626c1a720eb DRTVWR-62_2.7.2-release
+6a3e7e403bd19e45fdfc2fcc716867af3ab80861 2.7.3-start
6af10678de4736222b2c3f7e010e984fb5b327de 2.7.4-start
be963a4eef635542f9617d7f5fd22ba48fb71958 2.7.4-beta1
be963a4eef635542f9617d7f5fd22ba48fb71958 DRTVWR-67_2.7.4-beta1
+057f319dd8eccdf63a54d99686c68cdcb31b6abc 2.7.4-release
+057f319dd8eccdf63a54d99686c68cdcb31b6abc DRTVWR-66_2.7.4-release
19a498fa62570f352d7d246f17e3c81cc1d82d8b 2.7.5-start
09984bfa6cae17e0f72d02b75c1b7393c65eecfc 2.7.5-beta1
09984bfa6cae17e0f72d02b75c1b7393c65eecfc DRTVWR-69_2.7.5-beta1
+6866d9df6efbd441c66451debd376d21211de39c 2.7.5-release
+6866d9df6efbd441c66451debd376d21211de39c DRTVWR-68_2.7.5-release
e1ed60913230dd64269a7f7fc52cbc6004f6d52c 2.8.0-beta1
e1ed60913230dd64269a7f7fc52cbc6004f6d52c 2.8.0-start
e1ed60913230dd64269a7f7fc52cbc6004f6d52c DRTVWR-71_2.8.0-beta1
-057f319dd8eccdf63a54d99686c68cdcb31b6abc 2.7.4-release
-057f319dd8eccdf63a54d99686c68cdcb31b6abc DRTVWR-66_2.7.4-release
-6866d9df6efbd441c66451debd376d21211de39c 2.7.5-release
-6866d9df6efbd441c66451debd376d21211de39c DRTVWR-68_2.7.5-release
+493d9127ee50e84ba08a736a65a23ca86f7a5b01 2.8.0-release
+493d9127ee50e84ba08a736a65a23ca86f7a5b01 DRTVWR-70_2.8.0-release
502f6a5deca9365ddae57db4f1e30172668e171e 2.8.1-start
2c7e459e0c883f8e406b932e41e60097e9ee077e 2.8.1-beta1
2c7e459e0c883f8e406b932e41e60097e9ee077e DRTVWR-73_2.8.1-beta1
-493d9127ee50e84ba08a736a65a23ca86f7a5b01 2.8.0-release
-493d9127ee50e84ba08a736a65a23ca86f7a5b01 DRTVWR-70_2.8.0-release
-54bc7823ad4e3a436fef79710f685a7372bbf795 2.8.2-start
-ac0f1a132d35c02a58861d37cca75b0429ac9137 2.8.3-start
29e93d7e19991011bd12b5748142b11a5dcb4370 2.8.1-release
29e93d7e19991011bd12b5748142b11a5dcb4370 DRTVWR-72_2.8.1-release
4780e3bd2b3042f91be3426151f28c30d199bb3b 2.8.1-hotfix
4780e3bd2b3042f91be3426151f28c30d199bb3b DRTVWR-76_2.8.1-hotfix
+54bc7823ad4e3a436fef79710f685a7372bbf795 2.8.2-start
+ac0f1a132d35c02a58861d37cca75b0429ac9137 2.8.3-start
599677276b227357140dda35bea4a2c18e2e67b5 2.8.3-beta1
599677276b227357140dda35bea4a2c18e2e67b5 DRTVWR-75_2.8.3-beta1
+fb85792b84bf28428889c4cc966469d92e5dac4c 2.8.3-release
+fb85792b84bf28428889c4cc966469d92e5dac4c DRTVWR-74_2.8.3-release
6b678ea52f90d5c14181661dcd2546e25bde483e 3.0.0-start
b0be6ce3adfef3a014a2389d360539f8a86c5439 3.0.0-beta1
b0be6ce3adfef3a014a2389d360539f8a86c5439 DRTVWR-78_3.0.0-beta1
-fb85792b84bf28428889c4cc966469d92e5dac4c 2.8.3-release
-fb85792b84bf28428889c4cc966469d92e5dac4c DRTVWR-74_2.8.3-release
+1778f26b6d0ae762dec3ca37140f66620f2485d9 3.0.0-release
+1778f26b6d0ae762dec3ca37140f66620f2485d9 DRTVWR-77_3.0.0-release
82a2079ffcb57ecb1b3849cb41376b443e1eb912 3.0.1-start
364fd63517fbacbbcb9129d096187171ba8c9e48 3.0.1-beta1
364fd63517fbacbbcb9129d096187171ba8c9e48 DRTVWR-81_3.0.1-beta1
f2412ecd6740803ea9452f1d17fd872e263a0df7 3.0.2-start
42784bf50fa01974bada2a1af3892ee09c93fcda 3.0.2-beta1
42784bf50fa01974bada2a1af3892ee09c93fcda DRTVWR-83_3.0.2-beta1
-1778f26b6d0ae762dec3ca37140f66620f2485d9 3.0.0-release
-1778f26b6d0ae762dec3ca37140f66620f2485d9 DRTVWR-77_3.0.0-release
e5c9af2d7980a99a71650be3a0cf7b2b3c3b897e 3.0.2-beta2
e5c9af2d7980a99a71650be3a0cf7b2b3c3b897e DRTVWR-86_3.0.2-beta2
b95ddac176ac944efdc85cbee94ac2e1eab44c79 3.0.3-start
@@ -170,9 +170,9 @@ b95ddac176ac944efdc85cbee94ac2e1eab44c79 3.0.3-start
6694f3f062aa45f64ab391d25a3eb3d5eb1b0871 DRTVWR-85_3.0.3-beta1
61aa7974df089e8621fe9a4c69bcdefdb3cc208a 3.0.3-beta2
61aa7974df089e8621fe9a4c69bcdefdb3cc208a DRTVWR-89_3.0.3-beta2
-586907287be581817b2422b5137971b22d54ea48 3.0.4-start
0496d2f74043cf4e6058e76ac3db03d44cff42ce 3.0.3-release
0496d2f74043cf4e6058e76ac3db03d44cff42ce DRTVWR-84_3.0.3-release
+586907287be581817b2422b5137971b22d54ea48 3.0.4-start
92a3aa04775438226399b19deee12ac3b5a62838 3.0.5-start
c7282e59f374ee904bd793c3c444455e3399b0c5 3.1.0-start
2657fa785bbfac115852c41bd0adaff74c2ad5da 3.1.0-beta1
@@ -193,11 +193,11 @@ e440cd1dfbd128d7d5467019e497f7f803640ad6 DRTVWR-95_3.2.0-beta1
c4911ec8cd81e676dfd2af438b3e065407a94a7a 3.2.1-start
9e390d76807fa70d356b8716fb83b8ce42a629ef 3.2.1-beta1
9e390d76807fa70d356b8716fb83b8ce42a629ef DRTVWR-100_3.2.1-beta1
+a8c7030d6845186fac7c188be4323a0e887b4184 3.2.1-release
+a8c7030d6845186fac7c188be4323a0e887b4184 DRTVWR-99_3.2.1-release
40b46edba007d15d0059c80864b708b99c1da368 3.2.2-start
523df3e67378541498d516d52af4402176a26bac 3.2.2-beta1
523df3e67378541498d516d52af4402176a26bac DRTVWR-102_3.2.2-beta1
-a8c7030d6845186fac7c188be4323a0e887b4184 3.2.1-release
-a8c7030d6845186fac7c188be4323a0e887b4184 DRTVWR-99_3.2.1-release
80f3e30d8aa4d8f674a48bd742aaa6d8e9eae0b5 3.2.3-start
3fe994349fae64fc40874bb59db387131eb35a41 3.2.4-beta1
3fe994349fae64fc40874bb59db387131eb35a41 3.2.4-start
@@ -248,57 +248,67 @@ bb9932a7a5fd00edf52d95f354e3b37ae6a942db DRTVWR-156
6414ecdabc5d89515b08d1f872cf923ed3a5523a DRTVWR-148
2a3965b3ad202df7ea25d2be689291bb14a1280e DRTVWR-155
24a7281bef42bd4430ceb25db8b195449c2c7de3 DRTVWR-153
+a716684aa7c07c440b1de5815b8a1f3dd3fd8bfb DRTVWR-159
+9a78ac13f047056f788c4734dd91aebfe30970e3 DRTVWR-157
5910f8063a7e1ddddf504c2f35ca831cc5e8f469 DRTVWR-160
f0a174c2adb4bc39b16722a61d7eeb4f2a1d4843 3.3.3-beta1
f0a174c2adb4bc39b16722a61d7eeb4f2a1d4843 DRTVWR-144
-2d6c0634b11e6f3df11002b8510a72a0433da00a DRTVWR-164
+089e5c84b2dece68f2b016c842ef9b5de4786842 DRTVWR-161
600f3b3920d94de805ac6dc8bb6def9c069dd360 DRTVWR-162
+c08e2ac17a99973b2a94477659220b99b8847ae2 DRTVWR-163
+2d6c0634b11e6f3df11002b8510a72a0433da00a DRTVWR-164
80b5e5e9775966d3839331ffa7a16a60f9d7c930 DRTVWR-165
fdcc08a4f20ae9bb060f4693c8980d216534efdf 3.3.3-beta2
af5f3e43e6e4424b1da19d9e16f6b853a7b822ed DRTVWR-169
4b3c68199a86cabaa5d9466d7b0f7e141e901d7a 3.3.3-beta3
6428242e124b523813bfaf4c45b3d422f0298c81 3.3.3-release
-a716684aa7c07c440b1de5815b8a1f3dd3fd8bfb DRTVWR-159
-9a78ac13f047056f788c4734dd91aebfe30970e3 DRTVWR-157
-089e5c84b2dece68f2b016c842ef9b5de4786842 DRTVWR-161
-c08e2ac17a99973b2a94477659220b99b8847ae2 DRTVWR-163
b9d0170b62eb1c7c3adaa37a0b13a833e5e659f9 DRTVWR-171
050e48759337249130f684b4a21080b683f61732 DRTVWR-168
09ef7fd1b0781f33b8a3a9af6236b7bcb4831910 DRTVWR-170
f87bfbe0b62d26f451d02a47c80ebef6b9168fc2 DRTVWR-158
f91d003091a61937a044652c4c674447f7dcbb7a 3.3.4-beta1
+005dfe5c4c377207d065fb27858d2eb0b53b143a DRTVWR-167
bce218b2b45b730b22cc51e4807aa8b571cadef3 DRTVWR-173
cbea6356ce9cb0c313b6777f10c5c14783264fcc DRTVWR-174
82b5330bc8b17d0d4b598832e9c5a92e90075682 3.3.4-beta2
57d221de3df94f90b55204313c2cef044a3c0ae2 DRTVWR-176
eb539c65e6ee26eea2bf373af2d0f4b52dc91289 DRTVWR-177
a8057e1b9a1246b434a27405be35e030f7d28b0c 3.3.4-beta3
+888768f162d2c0a8de1dcc5fb9a08bd8bd120a6b DRTVWR-175
4281aa899fb2cedb7a9ca7ce91c5c29d4aa69594 DRTVWR-180
5c08e1d8edd871807153603b690e3ee9dbb548aa DRTVWR-183
6c75f220b103db1420919c8b635fe53e2177f318 3.3.4-beta4
9cd174d3a54d93d409a7c346a15b8bfb40fc58f4 DRTVWR-184
ab2ffc547c8a8950ff187c4f6c95e5334fab597b 3.3.4-beta5
28e100d0379a2b0710c57647a28fc5239d3d7b99 3.3.4-release
-005dfe5c4c377207d065fb27858d2eb0b53b143a DRTVWR-167
-888768f162d2c0a8de1dcc5fb9a08bd8bd120a6b DRTVWR-175
a8b3eca451a9eaab59987efb0ab1c4217e3f2dcc DRTVWR-182
1f27cdfdc54246484f8afbbe42ce48e954175cbd 3.4.0-beta1
-9ee9387789701d597130f879d9011a4958753862 DRTVWR-189
+81f6b745ef27f5915fd07f988fdec9944f2bb73e DRTVWR-186
47f0d08ba7ade0a3905074009067c6d3df7e16ae DRTVWR-190
+cc953f00956be52cc64c30637bbeec310eea603f DRTVWR-181
+c04e68e1b0034fd0a20815ae24c77e5f8428e822 DRTVWR-188
+9ee9387789701d597130f879d9011a4958753862 DRTVWR-189
421126293dcbde918e0da027ca0ab9deb5b4fbf2 DRTVWR-192
+4b2c52aecb7a75de31dbb12d9f5b9a251d8707be DRTVWR-191
33a2fc7a910ae29ff8b4850316ed7fbff9f64d33 DRTVWR-195
e9732c739c8a72a590216951505ea9c76a526a84 DRTVWR-193
+78ca0bbf43a92e8914d4cfa87d69a6717ef7d4cf DRTVWR-194
7602f61c804a512764e349c034c02ddabeefebc4 DRTVWR-196
ae5c83dd61d2d37c45f1d5b8bf2b036d87599f1b DRTVWR-198
507bdfbd6bf844a511c1ffeda4baa80016ed1346 DRTVWR-197
b1dbb1a83f48f93f6f878cff9e52d2cb635e145c 3.4.0-beta2
37402e2b19af970d51b0a814d79892cc5647532b DRTVWR-200
182a9bf30e81070361bb020a78003b1cf398e79c 3.4.0-beta3
+248f4acd92a706c79e842bc83d80baa7369c0c2e DRTVWR-203
6dfb0fba782c9233dd95f24ec48146db0d3f210b DRTVWR-199
7c9102fb998885621919f2474a002c35b583539b 3.3.4-release2
7649a3dff5ec22d3727377e5f02efd0f421e4cb5 DRTVWR-201
84fb70dfe3444e75a44fb4bee43e2fc8221cebdd 3.4.0-beta4
+de3be913f68813a9bac7d1c671fef96d1159bcd6 DRTVWR-202
573e863be2f26d3687161def4b9fea9b7038dda8 3.4.0-beta5
+34dbbe2b00afe90352d3acf8290eb10ab90d1c8b oz-build-test-tag
+6ee71714935ffcd159db3d4f5800c1929aac54e1 DRTVWR-205
+7b22c612fc756e0ea63b10b163e81d107f85dbf8 DRTVWR-206
8c9085066c78ed5f6c9379dc054c82a6fcdb1851 DRTVWR-207
351eea5f9dc192fc5ddea3b02958de97677a0a12 3.3.4-release3
af7b28e75bd5a629cd9e0dc46fb3f1757626f493 DRTVWR-212
@@ -309,6 +319,7 @@ ceed0b65a69f1eac20d523e0203320a32f9a3f3c DRTVWR-215
97977c67245f52db20eb15f1918cc0f24778cabc 3.4.0-release
5adb2b8f96c3cac88ad7c7d996d707f1b29df336 3.4.1-beta1
b3f74858a1c8720c82d0978f3877a3fc8ba459ec 3.4.1-beta1a
+b61afe175b829c149d369524a4e974dfda99facf DRTVWR-219
2b779f233ee6f38c89cb921650c773a96e63da92 DRTVWR-220
0b9d95f4bfb6867cbf56eaec51633b0da2f1262d DRTVWR-221
e6e553761829dc0270eaaa712b7cb0622535b076 3.4.1-beta3
@@ -333,36 +344,31 @@ baf97f06ae17223614c5e31aa42e71d87cff07fe DRTVWR-236
b2f21e3442542283a80e7eaebae9f833e5a927b6 DRTVWR-237
3f9be82de642d468c5fc272cb9d96b46b5498402 3.4.1-beta12
e59ffd3fe0838ae6b09b242a6e9df71761b88f41 3.4.1-release
-81f6b745ef27f5915fd07f988fdec9944f2bb73e DRTVWR-186
-cc953f00956be52cc64c30637bbeec310eea603f DRTVWR-181
-c04e68e1b0034fd0a20815ae24c77e5f8428e822 DRTVWR-188
-4b2c52aecb7a75de31dbb12d9f5b9a251d8707be DRTVWR-191
-78ca0bbf43a92e8914d4cfa87d69a6717ef7d4cf DRTVWR-194
-248f4acd92a706c79e842bc83d80baa7369c0c2e DRTVWR-203
-de3be913f68813a9bac7d1c671fef96d1159bcd6 DRTVWR-202
-34dbbe2b00afe90352d3acf8290eb10ab90d1c8b oz-build-test-tag
-6ee71714935ffcd159db3d4f5800c1929aac54e1 DRTVWR-205
-7b22c612fc756e0ea63b10b163e81d107f85dbf8 DRTVWR-206
-b61afe175b829c149d369524a4e974dfda99facf DRTVWR-219
32896d5e920ca9a29256ff3b747c2e99752aa5ae DRTVWR-217
704bbae7b182a1f2811a47a054e680522966f54a 3.4.2-beta1
+d799593b53ed733862e9a13871e318e886469377 DRTVWR-208
+e497dcde7a3653e384eb223a8a460030e89c294c DRTVWR-223
288539fc0408ed4b69a99665de33bbbc2c3c08fe DRTVWR-216
e664473c16df1d82ffaff382e7b3e023da202d52 3.4.2-beta2
+93ab02d83f51e30a3cabad98aff89601befd9413 DRTVWR-240
0891d7a773a31397dcad48be3fa66531d567a821 DRTVWR-242
710785535362b3cb801b6a3dc4703be3373bd0cd 3.4.2-beta3
-e9a5886052433d5db9e504ffaca10890f9932979 DRTVWR-243
-73b84b9864dc650fe7c8fc9f52361450f0849004 3.4.2-beta4
-16310aabccf315870f7cc9bf966926c0ad6954fa 3.4.2-release
-d799593b53ed733862e9a13871e318e886469377 DRTVWR-208
-e497dcde7a3653e384eb223a8a460030e89c294c DRTVWR-223
-93ab02d83f51e30a3cabad98aff89601befd9413 DRTVWR-240
2aa72e3372a83dece4df9cf72fb1e7c34f90b5e3 DRTVWR-209
f7bedce18ad52283e6072814db23318907261487 DRTVWR-238
7b64c96fbcadf360bd2feaae19d330166b70877c DRTVWR-210
+e9a5886052433d5db9e504ffaca10890f9932979 DRTVWR-243
+73b84b9864dc650fe7c8fc9f52361450f0849004 3.4.2-beta4
+16310aabccf315870f7cc9bf966926c0ad6954fa 3.4.2-release
5e4e4128b256525bafc07a62e35ae8527aaa9c9d DRTVWR-241
f1d3b3fcab28ed9ea532bf50db0ba96f5c8cc8e9 DRTVWR-232
4918b150e75df6b516fb6c2616d32043fa6b4cac DRTVWR-245
94ab2b49458ab372a95d2d6949fdf574f413068d 3.4.3-beta1
+4c3460cb1fb7c6da9965e09c734d282a8e9c81f0 DRTVWR-229
+f4481df42f9a4a92bf475a80f0c51d1a4bbdfd59 DRTVWR-246
+39c5204b6e800983a41ccac8ad6dc993120197c6 DRTVWR-247
+7c7d57d393e8ae7b61623279de06eb4a62ccae6a DRTVWR-249
+f72b50ef168c159d6e79e97aa2bcafaf8577ab99 DRTVWR-230
+b418be80903520c492e1173f3afbc4021cad5d07 DRTVWR-255
965b9a35e260c0f53be1a25f0db7abc8a67eaf47 DRTVWR-252
bb10adc4f76cf0067fca7075146f00cdc0740e9d DRTVWR-251
ab0aa2f6ba22b52fed30a2337197f589156edc75 DRTVWR-253
@@ -371,31 +377,25 @@ ab0aa2f6ba22b52fed30a2337197f589156edc75 DRTVWR-253
44e764a6ac9e672a4f3bce821a4b6a218590c374 DRTVWR-258
c23d734065ed593b2413385aecd8366d8e0ee96b DRTVWR-257
452ce96d4046dc05a3ecaecc203e2cc8ddd72e76 DRTVWR-259
+9aa1aa9f1fe13c194695a0b8f0af298296241dc2 DRTVWR-260
daca610d840625b5bebb966a57cb49581852c417 DRTVWR-265
9afbdc4e24cc04feacfb2b7a10b78a64f780901a DRTVWR-266
73280db02501f5ad041fc18b1eba68e73a81996c DRTVWR-267
870e2d79e0063fda87187f17bbc2747766733194 3.4.3-beta3
0a2ca6546b499239afeb66d17b2fadbcdbe36ab1 3.4.3-release
-4c3460cb1fb7c6da9965e09c734d282a8e9c81f0 DRTVWR-229
-f4481df42f9a4a92bf475a80f0c51d1a4bbdfd59 DRTVWR-246
-39c5204b6e800983a41ccac8ad6dc993120197c6 DRTVWR-247
-7c7d57d393e8ae7b61623279de06eb4a62ccae6a DRTVWR-249
-f72b50ef168c159d6e79e97aa2bcafaf8577ab99 DRTVWR-230
-b418be80903520c492e1173f3afbc4021cad5d07 DRTVWR-255
-9aa1aa9f1fe13c194695a0b8f0af298296241dc2 DRTVWR-260
84fbaf2d4141bd161731430e760949dc787ca206 DRTVWR-244
083d2d36b5bb1c54fc3dd7caac0e7ac381a9cef0 3.4.4-beta1
+391a8c74cec7275c5d26c85ad108d4782a3e3dd9 DRTVWR-268
b634dec987c16e8c9c938e11e52591d9ead8fa9b DRTVWR-270
cd39255bd23330fd30c04105f2811e941d8524fe 3.4.4-beta2
2c4011bbc2b15b82198fd8b51f3a9fe765a08c4d DRTVWR-271
2f8a3ef687bc55828abcb17ac1ad7cde70536d7e 3.4.4-beta3
35cfd4cf5b895fa776592f2e630e330be7f0604e DRTVWR-273
+a36f1f354b02aa6e448ca13685de167d0a0a3d03 DRTVWR-272
+37dba00ad820de3a808d4039396b162a9c275b3e DRTVWR-269
c374035d459af3c03dea2dd90880dfc25de64706 DRTVWR-275
05d9f1dd7a954069af2a33abedb7713fa36a04cb 3.4.4-beta4
e1bb1ae7d8b12faeb37933a737c199cc9b9f89cc 3.4.4-release
-391a8c74cec7275c5d26c85ad108d4782a3e3dd9 DRTVWR-268
-a36f1f354b02aa6e448ca13685de167d0a0a3d03 DRTVWR-272
-37dba00ad820de3a808d4039396b162a9c275b3e DRTVWR-269
7c6dfdc1b7a2ce0d8e3a8f3ce3058547ea065c0f DRTVWR-250
b9ff9730daa53a541925300cbd02bb14575a5705 DRTVWR-277
af6b711a97073431953b55ee808aaa09900c27e5 DRTVWR-276
@@ -405,6 +405,8 @@ c296133849d1f103c0e2abc41e6599daed00b67b DRTVWR-280
5df4802bec93c8d0a509946d826bb4c50c5442ec DRTVWR-281
7c1c33ba4cfd2d15ca51cc1ac440eca551331a4a DRTVWR-283
6b9c7dbebef793230d64e1b452577c8b142d4143 3.4.5-beta2
+37947e4f771f001b551581bf7cd0051c3153beed DRTVWR-282
+6482cceb91cda68b799f3e6cdc66d33bf123547a DRTVWR-284
ccf991e02dc2f63fb646324230d54832683f4a9b DRTVWR-286
2d849850558a5a0324b398d1c102d30bcbdfb88f DRTVWR-287
e06898df8644fe567bee94f817d03abc1c380993 3.4.5-beta3
@@ -417,8 +419,6 @@ b23419a2748483c98f3b84b630468a21c88feba5 DRTVWR-292
0a5d409161ef2a89b28c9a741051dd2dedc707d6 DRTVWR-297
852b69ef0b5fe6b13b69cc2217282cc64de6afab 3.4.5-beta5
a49c715243a36a8a380504d14cb7416b3039c956 3.4.5-release
-37947e4f771f001b551581bf7cd0051c3153beed DRTVWR-282
-6482cceb91cda68b799f3e6cdc66d33bf123547a DRTVWR-284
092a9effbedd1a0276fa5ced520992ce00f96fbf CHUI-PV-0
279ef1dfc9b749a6cc499cf190fec0c090b6d682 DRTVWR-288
9b19edaf1d8ddf435f60fbbb444dd25db8f63953 3.5.0-beta1
@@ -434,9 +434,8 @@ fd6b510e83f56830e45670c428653134899d3e25 DRTVWR-305
902caf2b9fdbdbc5c399c4d5ebcecaf9cb97bab8 DRTVWR-306
5c6098fd17d40ee3a38ca6b64f6be9db7f61f0a8 3.5.0-beta7
adc360e6bf21390d2665380951d85937cd29a604 3.5.0-release
-0ca3910763cec967703e45bc6208a325dccb9f95 3.5.1-beta1
1ada73295ed0eaa4a772ef079c29f57069342c32 DRTVWR-310
-0ca3910763cec967703e45bc6208a325dccb9f95 3.5.1-beta1
20cdf370f5c8be6193bef6fb3a81cc3f81275191 3.5.1-beta1
2319904200de367646b9a9442239a38d52c1eeb5 DRTVWR-313
9d8726eca785acad694564516f16dd639faf45c0 3.5.1-beta2
+78a8fe6abf331944d6b6bb1ce1024a6bc08141f4 DRTVWR-298
diff --git a/autobuild.xml b/autobuild.xml
index 80a44ec75d..ba6b76e7b2 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -483,14 +483,14 @@
</map>
</map>
</map>
- <key>fmod</key>
+ <key>fmodex</key>
<map>
<key>license</key>
- <string>fmod</string>
+ <string>fmodex</string>
<key>license_file</key>
- <string>LICENSES/fmod.txt</string>
+ <string>LICENSES/fmodex.txt</string>
<key>name</key>
- <string>fmod</string>
+ <string>fmodex</string>
<key>platforms</key>
<map>
<key>darwin</key>
@@ -498,9 +498,9 @@
<key>archive</key>
<map>
<key>hash</key>
- <string>61ead113e6479452e6b690c84b4e9d30</string>
+ <string>89a3df89da75444877cf3197416fed67</string>
<key>url</key>
- <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-fmod-private/rev/221852/arch/Darwin/installer/fmod-3.75-darwin-20110222.tar.bz2</string>
+ <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-fmodex-private/rev/270029/arch/Darwin/installer/fmodex-4.44-darwin-20130205.tar.bz2</string>
</map>
<key>name</key>
<string>darwin</string>
@@ -510,9 +510,9 @@
<key>archive</key>
<map>
<key>hash</key>
- <string>0c61d643db54d2e5999be8254569d8b3</string>
+ <string>fd787931f49ece9bf99f4d1d1596f04b</string>
<key>url</key>
- <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-fmod-private/rev/221852/arch/Linux/installer/fmod-3.75-linux-20110223.tar.bz2</string>
+ <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-fmodex-private/rev/269984/arch/Linux/installer/fmodex-4.44-linux-20130205.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
@@ -522,9 +522,9 @@
<key>archive</key>
<map>
<key>hash</key>
- <string>d9a9a6ad86895353bcd63374a4c1a91d</string>
+ <string>9e0f62be63e74af18f670f864cac93da</string>
<key>url</key>
- <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-fmod-private/rev/221852/arch/CYGWIN/installer/fmod-3.75-windows-20110222.tar.bz2</string>
+ <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-fmodex-private/rev/270026/arch/CYGWIN/installer/fmodex-4.44-windows-20130205.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
@@ -2531,7 +2531,6 @@
<string>"Visual Studio 10"</string>
<string>-DUNATTENDED:BOOL=ON</string>
<string>-DUSE_KDU=FALSE</string>
- <string>-DFMOD=FALSE</string>
</array>
</map>
<key>name</key>
@@ -2620,7 +2619,6 @@
<string>-DUNATTENDED:BOOL=ON</string>
<string>-DINSTALL_PROPRIETARY=FALSE</string>
<string>-DUSE_KDU=FALSE</string>
- <string>-DFMOD=FALSE</string>
</array>
</map>
<key>name</key>
@@ -2708,7 +2706,6 @@
<string>-DUNATTENDED:BOOL=ON</string>
<string>-DINSTALL_PROPRIETARY=FALSE</string>
<string>-DUSE_KDU=FALSE</string>
- <string>-DFMOD=FALSE</string>
</array>
</map>
<key>name</key>
diff --git a/doc/contributions.txt b/doc/contributions.txt
index a63e3a22b0..9f2f51f248 100644
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -1068,10 +1068,12 @@ Sheet Spotter
Shnurui Troughton
Shyotl Kuhr
MAINT-1138
+ MAINT-2334
Siana Gearz
STORM-960
STORM-1088
MAINT-1138
+ MAINT-2334
sicarius Thorne
Sicarius Toxx
SignpostMarv Martin
@@ -1089,6 +1091,8 @@ SLB Wirefly
Slee Mayo
SEC-1075
snowy Sidran
+Sovereign Engineer
+ MAINT-2334
SpacedOut Frye
VWR-34
VWR-45
@@ -1342,3 +1346,4 @@ Zoex Flanagan
+
diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt
index a21fa90950..10a23ea068 100644
--- a/indra/cmake/CMakeLists.txt
+++ b/indra/cmake/CMakeLists.txt
@@ -24,12 +24,11 @@ set(cmake_SOURCE_FILES
DragDrop.cmake
EXPAT.cmake
ExamplePlugin.cmake
- FMOD.cmake
FindAPR.cmake
FindAutobuild.cmake
FindBerkeleyDB.cmake
FindCARes.cmake
- FindFMOD.cmake
+ FindFMODEX.cmake
FindGLH.cmake
FindGoogleBreakpad.cmake
FindGooglePerfTools.cmake
@@ -40,6 +39,7 @@ set(cmake_SOURCE_FILES
FindSCP.cmake
FindXmlRpcEpi.cmake
FindZLIB.cmake
+ FMODEX.cmake
FreeType.cmake
GLEXT.cmake
GLH.cmake
diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake
index 338da4743e..ef529c32d3 100644
--- a/indra/cmake/Copy3rdPartyLibs.cmake
+++ b/indra/cmake/Copy3rdPartyLibs.cmake
@@ -62,10 +62,9 @@ if(WINDOWS)
set(release_files ${release_files} libtcmalloc_minimal.dll)
endif(USE_TCMALLOC)
- if (FMOD)
- set(debug_files ${debug_files} fmod.dll)
- set(release_files ${release_files} fmod.dll)
- endif (FMOD)
+ if (FMODEX)
+ set(release_files ${release_files} fmodex.dll)
+ endif (FMODEX)
#*******************************
# Copy MS C runtime dlls, required for packaging.
@@ -222,8 +221,10 @@ elseif(DARWIN)
libcollada14dom.dylib
)
- # fmod is statically linked on darwin
- set(fmod_files "")
+ if (FMODEX)
+ set(debug_files ${debug_files} libfmodexL.dylib)
+ set(release_files ${release_files} libfmodex.dylib)
+ endif (FMODEX)
elseif(LINUX)
# linux is weird, multiple side by side configurations aren't supported
@@ -288,9 +289,9 @@ elseif(LINUX)
set(release_files ${release_files} "libtcmalloc_minimal.so")
endif (USE_TCMALLOC)
- if (FMOD)
- set(release_files ${release_files} "libfmod-3.75.so")
- endif (FMOD)
+ if (FMODEX)
+ set(release_file ${release_files} "libfmodex.so")
+ endif (FMODEX)
else(WINDOWS)
message(STATUS "WARNING: unrecognized platform for staging 3rd party libs, skipping...")
@@ -305,8 +306,6 @@ else(WINDOWS)
set(release_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-linux/lib/release")
set(release_files "")
- set(fmod_files "")
-
set(debug_llkdu_src "")
set(debug_llkdu_dst "")
set(release_llkdu_src "")
@@ -369,30 +368,6 @@ copy_if_different(
)
set(third_party_targets ${third_party_targets} ${out_targets})
-if (FMOD_SDK_DIR)
- copy_if_different(
- ${FMOD_SDK_DIR}
- "${CMAKE_CURRENT_BINARY_DIR}/Debug"
- out_targets
- ${fmod_files}
- )
- set(all_targets ${all_targets} ${out_targets})
- copy_if_different(
- ${FMOD_SDK_DIR}
- "${CMAKE_CURRENT_BINARY_DIR}/Release"
- out_targets
- ${fmod_files}
- )
- set(all_targets ${all_targets} ${out_targets})
- copy_if_different(
- ${FMOD_SDK_DIR}
- "${CMAKE_CURRENT_BINARY_DIR}/RelWithDbgInfo"
- out_targets
- ${fmod_files}
- )
- set(all_targets ${all_targets} ${out_targets})
-endif (FMOD_SDK_DIR)
-
if(NOT STANDALONE)
add_custom_target(
stage_third_party_libs ALL
diff --git a/indra/cmake/FMOD.cmake b/indra/cmake/FMOD.cmake
deleted file mode 100644
index 3586c1160a..0000000000
--- a/indra/cmake/FMOD.cmake
+++ /dev/null
@@ -1,39 +0,0 @@
-# -*- cmake -*-
-
-# FMOD can be set when launching the make using the argument -DFMOD:BOOL=ON
-# When building using proprietary binaries though (i.e. having access to LL private servers),
-# we always build with FMOD.
-# Open source devs should use the -DFMOD:BOOL=ON then if they want to build with FMOD, whether
-# they are using STANDALONE or not.
-if (INSTALL_PROPRIETARY)
- set(FMOD ON CACHE BOOL "Use FMOD sound library.")
-endif (INSTALL_PROPRIETARY)
-
-if (FMOD)
- if (STANDALONE)
- # In that case, we use the version of the library installed on the system
- set(FMOD_FIND_REQUIRED ON)
- include(FindFMOD)
- else (STANDALONE)
- if (FMOD_LIBRARY AND FMOD_INCLUDE_DIR)
- # If the path have been specified in the arguments, use that
- set(FMOD_LIBRARIES ${FMOD_LIBRARY})
- MESSAGE(STATUS "Using FMOD path: ${FMOD_LIBRARIES}, ${FMOD_INCLUDE_DIR}")
- else (FMOD_LIBRARY AND FMOD_INCLUDE_DIR)
- # If not, we're going to try to get the package listed in autobuild.xml
- # Note: if you're not using INSTALL_PROPRIETARY, the package URL should be local (file:/// URL)
- # as accessing the private LL location will fail if you don't have the credential
- include(Prebuilt)
- use_prebuilt_binary(fmod)
- if (WINDOWS)
- set(FMOD_LIBRARY fmod)
- elseif (DARWIN)
- set(FMOD_LIBRARY fmod)
- elseif (LINUX)
- set(FMOD_LIBRARY fmod-3.75)
- endif (WINDOWS)
- set(FMOD_LIBRARIES ${FMOD_LIBRARY})
- set(FMOD_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include)
- endif (FMOD_LIBRARY AND FMOD_INCLUDE_DIR)
- endif (STANDALONE)
-endif (FMOD)
diff --git a/indra/cmake/FMODEX.cmake b/indra/cmake/FMODEX.cmake
new file mode 100644
index 0000000000..65bc1cabeb
--- /dev/null
+++ b/indra/cmake/FMODEX.cmake
@@ -0,0 +1,46 @@
+# -*- cmake -*-
+
+# FMOD can be set when launching the make using the argument -DFMOD:BOOL=ON
+# When building using proprietary binaries though (i.e. having access to LL private servers),
+# we always build with FMODEX.
+# Open source devs should use the -DFMODEX:BOOL=ON then if they want to build with FMOD, whether
+# they are using STANDALONE or not.
+if (INSTALL_PROPRIETARY)
+ set(FMODEX ON CACHE BOOL "Using FMOD Ex sound library.")
+endif (INSTALL_PROPRIETARY)
+
+if (FMODEX)
+ if (STANDALONE)
+ # In that case, we use the version of the library installed on the system
+ set(FMODEX_FIND_REQUIRED ON)
+ include(FindFMODEX)
+ else (STANDALONE)
+ if (FMODEX_LIBRARY AND FMODEX_INCLUDE_DIR)
+ # If the path have been specified in the arguments, use that
+ set(FMODEX_LIBRARIES ${FMODEX_LIBRARY})
+ MESSAGE(STATUS "Using FMODEX path: ${FMODEX_LIBRARIES}, ${FMODEX_INCLUDE_DIR}")
+ else (FMODEX_LIBRARY AND FMODEX_INCLUDE_DIR)
+ # If not, we're going to try to get the package listed in autobuild.xml
+ # Note: if you're not using INSTALL_PROPRIETARY, the package URL should be local (file:/// URL)
+ # as accessing the private LL location will fail if you don't have the credential
+ include(Prebuilt)
+ use_prebuilt_binary(fmodex)
+ if (WINDOWS)
+ set(FMODEX_LIBRARY
+ debug fmodexL_vc
+ optimized fmodex_vc)
+ elseif (DARWIN)
+ set(FMODEX_LIBRARY
+ debug fmodexL
+ optimized fmodex)
+ elseif (LINUX)
+ set(FMODEX_LIBRARY
+ debug fmodexL
+ optimized fmodex)
+ endif (WINDOWS)
+ set(FMODEX_LIBRARIES ${FMODEX_LIBRARY})
+ set(FMODEX_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/fmodex)
+ endif (FMODEX_LIBRARY AND FMODEX_INCLUDE_DIR)
+ endif (STANDALONE)
+endif (FMODEX)
+
diff --git a/indra/cmake/FindFMOD.cmake b/indra/cmake/FindFMOD.cmake
deleted file mode 100644
index 1ebbc8c96e..0000000000
--- a/indra/cmake/FindFMOD.cmake
+++ /dev/null
@@ -1,44 +0,0 @@
-# -*- cmake -*-
-
-# - Find FMOD
-# Find the FMOD includes and library
-# This module defines
-# FMOD_INCLUDE_DIR, where to find fmod.h and fmod_errors.h
-# FMOD_LIBRARIES, the libraries needed to use FMOD.
-# FMOD, If false, do not try to use FMOD.
-# also defined, but not for general use are
-# FMOD_LIBRARY, where to find the FMOD library.
-
-FIND_PATH(FMOD_INCLUDE_DIR fmod.h PATH_SUFFIXES fmod)
-
-SET(FMOD_NAMES ${FMOD_NAMES} fmod fmodvc fmodex fmod-3.75)
-FIND_LIBRARY(FMOD_LIBRARY
- NAMES ${FMOD_NAMES}
- PATH_SUFFIXES fmod
- )
-
-IF (FMOD_LIBRARY AND FMOD_INCLUDE_DIR)
- SET(FMOD_LIBRARIES ${FMOD_LIBRARY})
- SET(FMOD_FOUND "YES")
-ELSE (FMOD_LIBRARY AND FMOD_INCLUDE_DIR)
- SET(FMOD_FOUND "NO")
-ENDIF (FMOD_LIBRARY AND FMOD_INCLUDE_DIR)
-
-IF (FMOD_FOUND)
- IF (NOT FMOD_FIND_QUIETLY)
- MESSAGE(STATUS "Found FMOD: ${FMOD_LIBRARIES}")
- ENDIF (NOT FMOD_FIND_QUIETLY)
-ELSE (FMOD_FOUND)
- IF (FMOD_FIND_REQUIRED)
- MESSAGE(FATAL_ERROR "Could not find FMOD library")
- ENDIF (FMOD_FIND_REQUIRED)
-ENDIF (FMOD_FOUND)
-
-# Deprecated declarations.
-SET (NATIVE_FMOD_INCLUDE_PATH ${FMOD_INCLUDE_DIR} )
-GET_FILENAME_COMPONENT (NATIVE_FMOD_LIB_PATH ${FMOD_LIBRARY} PATH)
-
-MARK_AS_ADVANCED(
- FMOD_LIBRARY
- FMOD_INCLUDE_DIR
- )
diff --git a/indra/cmake/FindFMODEX.cmake b/indra/cmake/FindFMODEX.cmake
new file mode 100644
index 0000000000..b621727c0e
--- /dev/null
+++ b/indra/cmake/FindFMODEX.cmake
@@ -0,0 +1,65 @@
+# -*- cmake -*-
+
+# - Find FMODEX
+# Find the FMODEX includes and library
+# This module defines
+# FMODEX_INCLUDE_DIR, where to find fmod.h and fmod_errors.h
+# FMODEX_LIBRARIES, the libraries needed to use FMODEX.
+# FMODEX, If false, do not try to use FMODEX.
+# also defined, but not for general use are
+# FMODEX_LIBRARY, where to find the FMODEX library.
+
+FIND_PATH(FMODEX_INCLUDE_DIR fmod.h PATH_SUFFIXES fmod)
+
+SET(FMODEX_NAMES ${FMODEX_NAMES} fmodex fmodvc fmodexL_vc)
+FIND_LIBRARY(FMODEX_LIBRARY
+ NAMES ${FMODEX_NAMES}
+ PATH_SUFFIXES fmodex
+ )
+
+IF (FMODEX_SDK_DIR OR WINDOWS)
+ if(WINDOWS)
+ set(FMODEX_SDK_DIR "$ENV{PROGRAMFILES}/FMOD SoundSystem/FMOD Programmers API Windows" CACHE PATH "Path to FMODEX")
+ STRING(REGEX REPLACE "\\\\" "/" FMODEX_SDK_DIR ${FMODEX_SDK_DIR})
+ endif(WINDOWS)
+ find_library(FMODEX_LIBRARY
+ fmodex_vc fmodexL_vc
+ PATHS
+ ${FMODEX_SDK_DIR}/api/lib
+ ${FMODEX_SDK_DIR}/api
+ ${FMODEX_SDK_DIR}
+ )
+ find_path(FMODEX_INCLUDE_DIR fmod.h
+ ${FMODEX_SDK_DIR}/api/inc
+ ${FMODEX_SDK_DIR}/api
+ ${FMODEX_SDK_DIR}
+ )
+ find_path(FMODEX_INCLUDE_DIR fmod.h
+ ${FMODEX_SDK_DIR}/api/inc
+ ${FMODEX_SDK_DIR}/api
+ ${FMODEX_SDK_DIR}
+ )
+ IF (FMODEX_LIBRARY AND FMODEX_INCLUDE_DIR)
+ SET(FMODEX_LIBRARIES ${FMODEX_LIBRARY})
+ SET(FMODEX_FOUND "YES")
+ endif (FMODEX_LIBRARY AND FMODEX_INCLUDE_DIR)
+ENDIF (FMODEX_SDK_DIR OR WINDOWS)
+
+IF (FMODEX_FOUND)
+ IF (NOT FMODEX_FIND_QUIETLY)
+ MESSAGE(STATUS "Found FMODEX: ${FMODEX_LIBRARIES}")
+ ENDIF (NOT FMODEX_FIND_QUIETLY)
+ELSE (FMODEX_FOUND)
+ IF (FMODEX_FIND_REQUIRED)
+ MESSAGE(FATAL_ERROR "Could not find FMODEX library")
+ ENDIF (FMODEX_FIND_REQUIRED)
+ENDIF (FMODEX_FOUND)
+
+# Deprecated declarations.
+SET (NATIVE_FMODEX_INCLUDE_PATH ${FMODEX_INCLUDE_DIR} )
+GET_FILENAME_COMPONENT (NATIVE_FMODEX_LIB_PATH ${FMODEX_LIBRARY} PATH)
+
+MARK_AS_ADVANCED(
+ FMODEX_LIBRARY
+ FMODEX_INCLUDE_DIR
+ )
diff --git a/indra/llaudio/CMakeLists.txt b/indra/llaudio/CMakeLists.txt
index 24d2531106..1b2bdb9888 100644
--- a/indra/llaudio/CMakeLists.txt
+++ b/indra/llaudio/CMakeLists.txt
@@ -5,7 +5,7 @@ project(llaudio)
include(00-Common)
include(Audio)
include(LLAudio)
-include(FMOD)
+include(FMODEX)
include(OPENAL)
include(LLCommon)
include(LLMath)
@@ -24,7 +24,6 @@ include_directories(
${VORBIS_INCLUDE_DIRS}
${OPENAL_LIB_INCLUDE_DIRS}
${FREEAULT_LIB_INCLUDE_DIRS}
- ${FMOD_INCLUDE_DIR}
)
set(llaudio_SOURCE_FILES
@@ -44,29 +43,22 @@ set(llaudio_HEADER_FILES
llwindgen.h
)
-if (FMOD)
+if (FMODEX)
include_directories(
- ${FMOD_INCLUDE_DIR}
+ ${FMODEX_INCLUDE_DIR}
)
-
list(APPEND llaudio_SOURCE_FILES
- llaudioengine_fmod.cpp
- lllistener_fmod.cpp
- llstreamingaudio_fmod.cpp
+ llaudioengine_fmodex.cpp
+ lllistener_fmodex.cpp
+ llstreamingaudio_fmodex.cpp
)
list(APPEND llaudio_HEADER_FILES
- llaudioengine_fmod.h
- lllistener_fmod.h
- llstreamingaudio_fmod.h
+ llaudioengine_fmodex.h
+ lllistener_fmodex.h
+ llstreamingaudio_fmodex.h
)
-
- if (LINUX OR DARWIN)
- set_source_files_properties(llaudioengine_fmod.cpp
- llstreamingaudio_fmod.cpp
- COMPILE_FLAGS -Wno-write-strings)
- endif (LINUX OR DARWIN)
-endif (FMOD)
+endif (FMODEX)
if (OPENAL)
list(APPEND llaudio_SOURCE_FILES
diff --git a/indra/llaudio/llaudioengine.h b/indra/llaudio/llaudioengine.h
index 99b96c3c38..da1629a1db 100644
--- a/indra/llaudio/llaudioengine.h
+++ b/indra/llaudio/llaudioengine.h
@@ -42,7 +42,6 @@
#include "lllistener.h"
const F32 LL_WIND_UPDATE_INTERVAL = 0.1f;
-const F32 LL_ROLLOFF_MULTIPLIER_UNDER_WATER = 5.f; // How much sounds are weaker under water
const F32 LL_WIND_UNDERWATER_CENTER_FREQ = 20.f;
const F32 ATTACHED_OBJECT_TIMEOUT = 5.0f;
diff --git a/indra/llaudio/llaudioengine_fmod.cpp b/indra/llaudio/llaudioengine_fmod.cpp
deleted file mode 100644
index a40de9fa68..0000000000
--- a/indra/llaudio/llaudioengine_fmod.cpp
+++ /dev/null
@@ -1,781 +0,0 @@
-/**
- * @file audioengine_fmod.cpp
- * @brief Implementation of LLAudioEngine class abstracting the audio support as a FMOD 3D implementation
- *
- * $LicenseInfo:firstyear=2002&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "llstreamingaudio.h"
-#include "llstreamingaudio_fmod.h"
-
-#include "llaudioengine_fmod.h"
-#include "lllistener_fmod.h"
-
-#include "llerror.h"
-#include "llmath.h"
-#include "llrand.h"
-
-#include "fmod.h"
-#include "fmod_errors.h"
-#include "lldir.h"
-#include "llapr.h"
-
-#include "sound_ids.h"
-
-
-extern "C" {
- void * F_CALLBACKAPI windCallback(void *originalbuffer, void *newbuffer, int length, void* userdata);
-}
-
-
-LLAudioEngine_FMOD::LLAudioEngine_FMOD()
-{
- mInited = false;
- mWindGen = NULL;
- mWindDSP = NULL;
-}
-
-
-LLAudioEngine_FMOD::~LLAudioEngine_FMOD()
-{
-}
-
-
-bool LLAudioEngine_FMOD::init(const S32 num_channels, void* userdata)
-{
- LLAudioEngine::init(num_channels, userdata);
-
- // Reserve one extra channel for the http stream.
- if (!FSOUND_SetMinHardwareChannels(num_channels + 1))
- {
- LL_WARNS("AppInit") << "FMOD::init[0](), error: " << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL;
- }
-
- LL_DEBUGS("AppInit") << "LLAudioEngine_FMOD::init() initializing FMOD" << LL_ENDL;
-
- F32 version = FSOUND_GetVersion();
- if (version < FMOD_VERSION)
- {
- LL_WARNS("AppInit") << "Error : You are using the wrong FMOD version (" << version
- << ")! You should be using FMOD " << FMOD_VERSION << LL_ENDL;
- //return false;
- }
-
- U32 fmod_flags = 0x0;
-
-#if LL_WINDOWS
- // Windows needs to know which window is frontmost.
- // This must be called before FSOUND_Init() per the FMOD docs.
- // This could be used to let FMOD handle muting when we lose focus,
- // but we don't actually want to do that because we want to distinguish
- // between minimized and not-focused states.
- if (!FSOUND_SetHWND(userdata))
- {
- LL_WARNS("AppInit") << "Error setting FMOD window: "
- << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL;
- return false;
- }
- // Play audio when we don't have focus.
- // (For example, IM client on top of us.)
- // This means we also try to play audio when minimized,
- // so we manually handle muting in that case. JC
- fmod_flags |= FSOUND_INIT_GLOBALFOCUS;
-#endif
-
-#if LL_LINUX
- // initialize the FMOD engine
-
- // This is a hack to use only FMOD's basic FPU mixer
- // when the LL_VALGRIND environmental variable is set,
- // otherwise valgrind will fall over on FMOD's MMX detection
- if (getenv("LL_VALGRIND")) /*Flawfinder: ignore*/
- {
- LL_INFOS("AppInit") << "Pacifying valgrind in FMOD init." << LL_ENDL;
- FSOUND_SetMixer(FSOUND_MIXER_QUALITY_FPU);
- }
-
- // If we don't set an output method, Linux FMOD always
- // decides on OSS and fails otherwise. So we'll manually
- // try ESD, then OSS, then ALSA.
- // Why this order? See SL-13250, but in short, OSS emulated
- // on top of ALSA is ironically more reliable than raw ALSA.
- // Ack, and ESD has more reliable failure modes - but has worse
- // latency - than all of them, so wins for now.
- bool audio_ok = false;
-
- if (!audio_ok)
- {
- if (NULL == getenv("LL_BAD_FMOD_ESD")) /*Flawfinder: ignore*/
- {
- LL_DEBUGS("AppInit") << "Trying ESD audio output..." << LL_ENDL;
- if(FSOUND_SetOutput(FSOUND_OUTPUT_ESD) &&
- FSOUND_Init(44100, num_channels, fmod_flags))
- {
- LL_DEBUGS("AppInit") << "ESD audio output initialized OKAY"
- << LL_ENDL;
- audio_ok = true;
- } else {
- LL_WARNS("AppInit") << "ESD audio output FAILED to initialize: "
- << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL;
- }
- } else {
- LL_DEBUGS("AppInit") << "ESD audio output SKIPPED" << LL_ENDL;
- }
- }
- if (!audio_ok)
- {
- if (NULL == getenv("LL_BAD_FMOD_OSS")) /*Flawfinder: ignore*/
- {
- LL_DEBUGS("AppInit") << "Trying OSS audio output..." << LL_ENDL;
- if(FSOUND_SetOutput(FSOUND_OUTPUT_OSS) &&
- FSOUND_Init(44100, num_channels, fmod_flags))
- {
- LL_DEBUGS("AppInit") << "OSS audio output initialized OKAY" << LL_ENDL;
- audio_ok = true;
- } else {
- LL_WARNS("AppInit") << "OSS audio output FAILED to initialize: "
- << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL;
- }
- } else {
- LL_DEBUGS("AppInit") << "OSS audio output SKIPPED" << LL_ENDL;
- }
- }
- if (!audio_ok)
- {
- if (NULL == getenv("LL_BAD_FMOD_ALSA")) /*Flawfinder: ignore*/
- {
- LL_DEBUGS("AppInit") << "Trying ALSA audio output..." << LL_ENDL;
- if(FSOUND_SetOutput(FSOUND_OUTPUT_ALSA) &&
- FSOUND_Init(44100, num_channels, fmod_flags))
- {
- LL_DEBUGS("AppInit") << "ALSA audio output initialized OKAY" << LL_ENDL;
- audio_ok = true;
- } else {
- LL_WARNS("AppInit") << "ALSA audio output FAILED to initialize: "
- << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL;
- }
- } else {
- LL_DEBUGS("AppInit") << "OSS audio output SKIPPED" << LL_ENDL;
- }
- }
- if (!audio_ok)
- {
- LL_WARNS("AppInit") << "Overall audio init failure." << LL_ENDL;
- return false;
- }
-
- // On Linux, FMOD causes a SIGPIPE for some netstream error
- // conditions (an FMOD bug); ignore SIGPIPE so it doesn't crash us.
- // NOW FIXED in FMOD 3.x since 2006-10-01.
- //signal(SIGPIPE, SIG_IGN);
-
- // We're interested in logging which output method we
- // ended up with, for QA purposes.
- switch (FSOUND_GetOutput())
- {
- case FSOUND_OUTPUT_NOSOUND: LL_DEBUGS("AppInit") << "Audio output: NoSound" << LL_ENDL; break;
- case FSOUND_OUTPUT_OSS: LL_DEBUGS("AppInit") << "Audio output: OSS" << LL_ENDL; break;
- case FSOUND_OUTPUT_ESD: LL_DEBUGS("AppInit") << "Audio output: ESD" << LL_ENDL; break;
- case FSOUND_OUTPUT_ALSA: LL_DEBUGS("AppInit") << "Audio output: ALSA" << LL_ENDL; break;
- default: LL_INFOS("AppInit") << "Audio output: Unknown!" << LL_ENDL; break;
- };
-
-#else // LL_LINUX
-
- // initialize the FMOD engine
- if (!FSOUND_Init(44100, num_channels, fmod_flags))
- {
- LL_WARNS("AppInit") << "Error initializing FMOD: "
- << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL;
- return false;
- }
-
-#endif
-
- // set up our favourite FMOD-native streaming audio implementation if none has already been added
- if (!getStreamingAudioImpl()) // no existing implementation added
- setStreamingAudioImpl(new LLStreamingAudio_FMOD());
-
- LL_DEBUGS("AppInit") << "LLAudioEngine_FMOD::init() FMOD initialized correctly" << LL_ENDL;
-
- mInited = true;
-
- return true;
-}
-
-
-std::string LLAudioEngine_FMOD::getDriverName(bool verbose)
-{
- if (verbose)
- {
- F32 version = FSOUND_GetVersion();
- return llformat("FMOD version %f", version);
- }
- else
- {
- return "FMOD";
- }
-}
-
-
-void LLAudioEngine_FMOD::allocateListener(void)
-{
- mListenerp = (LLListener *) new LLListener_FMOD();
- if (!mListenerp)
- {
- llwarns << "Listener creation failed" << llendl;
- }
-}
-
-
-void LLAudioEngine_FMOD::shutdown()
-{
- if (mWindDSP)
- {
- FSOUND_DSP_SetActive(mWindDSP,false);
- FSOUND_DSP_Free(mWindDSP);
- }
-
- stopInternetStream();
-
- LLAudioEngine::shutdown();
-
- llinfos << "LLAudioEngine_FMOD::shutdown() closing FMOD" << llendl;
- FSOUND_Close();
- llinfos << "LLAudioEngine_FMOD::shutdown() done closing FMOD" << llendl;
-
- delete mListenerp;
- mListenerp = NULL;
-}
-
-
-LLAudioBuffer * LLAudioEngine_FMOD::createBuffer()
-{
- return new LLAudioBufferFMOD();
-}
-
-
-LLAudioChannel * LLAudioEngine_FMOD::createChannel()
-{
- return new LLAudioChannelFMOD();
-}
-
-
-bool LLAudioEngine_FMOD::initWind()
-{
- if (!mWindGen)
- {
- bool enable;
-
- switch (FSOUND_GetMixer())
- {
- case FSOUND_MIXER_MMXP5:
- case FSOUND_MIXER_MMXP6:
- case FSOUND_MIXER_QUALITY_MMXP5:
- case FSOUND_MIXER_QUALITY_MMXP6:
- enable = (typeid(MIXBUFFERFORMAT) == typeid(S16));
- break;
- case FSOUND_MIXER_BLENDMODE:
- enable = (typeid(MIXBUFFERFORMAT) == typeid(S32));
- break;
- case FSOUND_MIXER_QUALITY_FPU:
- enable = (typeid(MIXBUFFERFORMAT) == typeid(F32));
- break;
- default:
- // FSOUND_GetMixer() does not return a valid mixer type on Darwin
- LL_INFOS("AppInit") << "Unknown FMOD mixer type, assuming default" << LL_ENDL;
- enable = true;
- break;
- }
-
- if (enable)
- {
- mWindGen = new LLWindGen<MIXBUFFERFORMAT>(FSOUND_GetOutputRate());
- }
- else
- {
- LL_WARNS("AppInit") << "Incompatible FMOD mixer type, wind noise disabled" << LL_ENDL;
- }
- }
-
- mNextWindUpdate = 0.0;
-
- if (mWindGen && !mWindDSP)
- {
- mWindDSP = FSOUND_DSP_Create(&windCallback, FSOUND_DSP_DEFAULTPRIORITY_CLEARUNIT + 20, mWindGen);
- }
- if (mWindDSP)
- {
- FSOUND_DSP_SetActive(mWindDSP, true);
- return true;
- }
-
- return false;
-}
-
-
-void LLAudioEngine_FMOD::cleanupWind()
-{
- if (mWindDSP)
- {
- FSOUND_DSP_SetActive(mWindDSP, false);
- FSOUND_DSP_Free(mWindDSP);
- mWindDSP = NULL;
- }
-
- delete mWindGen;
- mWindGen = NULL;
-}
-
-
-//-----------------------------------------------------------------------
-void LLAudioEngine_FMOD::updateWind(LLVector3 wind_vec, F32 camera_height_above_water)
-{
- LLVector3 wind_pos;
- F64 pitch;
- F64 center_freq;
-
- if (!mEnableWind)
- {
- return;
- }
-
- if (mWindUpdateTimer.checkExpirationAndReset(LL_WIND_UPDATE_INTERVAL))
- {
-
- // wind comes in as Linden coordinate (+X = forward, +Y = left, +Z = up)
- // need to convert this to the conventional orientation DS3D and OpenAL use
- // where +X = right, +Y = up, +Z = backwards
-
- wind_vec.setVec(-wind_vec.mV[1], wind_vec.mV[2], -wind_vec.mV[0]);
-
- // cerr << "Wind update" << endl;
-
- pitch = 1.0 + mapWindVecToPitch(wind_vec);
- center_freq = 80.0 * pow(pitch,2.5*(mapWindVecToGain(wind_vec)+1.0));
-
- mWindGen->mTargetFreq = (F32)center_freq;
- mWindGen->mTargetGain = (F32)mapWindVecToGain(wind_vec) * mMaxWindGain;
- mWindGen->mTargetPanGainR = (F32)mapWindVecToPan(wind_vec);
- }
-}
-
-/*
-//-----------------------------------------------------------------------
-void LLAudioEngine_FMOD::setSourceMinDistance(U16 source_num, F64 distance)
-{
- if (!mInited)
- {
- return;
- }
- if (mBuffer[source_num])
- {
- mMinDistance[source_num] = (F32) distance;
- if (!FSOUND_Sample_SetMinMaxDistance(mBuffer[source_num],mMinDistance[source_num], mMaxDistance[source_num]))
- {
- llwarns << "FMOD::setSourceMinDistance(" << source_num << "), error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl;
- }
- }
-}
-
-//-----------------------------------------------------------------------
-void LLAudioEngine_FMOD::setSourceMaxDistance(U16 source_num, F64 distance)
-{
- if (!mInited)
- {
- return;
- }
- if (mBuffer[source_num])
- {
- mMaxDistance[source_num] = (F32) distance;
- if (!FSOUND_Sample_SetMinMaxDistance(mBuffer[source_num],mMinDistance[source_num], mMaxDistance[source_num]))
- {
- llwarns << "FMOD::setSourceMaxDistance(" << source_num << "), error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl;
- }
- }
-}
-
-//-----------------------------------------------------------------------
-void LLAudioEngine_FMOD::get3DParams(S32 source_num, S32 *volume, S32 *freq, S32 *inside, S32 *outside, LLVector3 *orient, S32 *out_volume, F32 *min_dist, F32 *max_dist)
-{
- *volume = 0;
- *freq = 0;
- *inside = 0;
- *outside = 0;
- *orient = LLVector3::zero;
- *out_volume = 0;
- *min_dist = 0.f;
- *max_dist = 0.f;
-}
-
-*/
-
-
-//-----------------------------------------------------------------------
-void LLAudioEngine_FMOD::setInternalGain(F32 gain)
-{
- if (!mInited)
- {
- return;
- }
-
- gain = llclamp( gain, 0.0f, 1.0f );
- FSOUND_SetSFXMasterVolume( llround( 255.0f * gain ) );
-
- LLStreamingAudioInterface *saimpl = getStreamingAudioImpl();
- if ( saimpl )
- {
- // fmod likes its streaming audio channel gain re-asserted after
- // master volume change.
- saimpl->setGain(saimpl->getGain());
- }
-}
-
-//
-// LLAudioChannelFMOD implementation
-//
-
-LLAudioChannelFMOD::LLAudioChannelFMOD() : LLAudioChannel(), mChannelID(0), mLastSamplePos(0)
-{
-}
-
-
-LLAudioChannelFMOD::~LLAudioChannelFMOD()
-{
- cleanup();
-}
-
-
-bool LLAudioChannelFMOD::updateBuffer()
-{
- if (LLAudioChannel::updateBuffer())
- {
- // Base class update returned true, which means that we need to actually
- // set up the channel for a different buffer.
-
- LLAudioBufferFMOD *bufferp = (LLAudioBufferFMOD *)mCurrentSourcep->getCurrentBuffer();
-
- // Grab the FMOD sample associated with the buffer
- FSOUND_SAMPLE *samplep = bufferp->getSample();
- if (!samplep)
- {
- // This is bad, there should ALWAYS be a sample associated with a legit
- // buffer.
- llerrs << "No FMOD sample!" << llendl;
- return false;
- }
-
-
- // Actually play the sound. Start it off paused so we can do all the necessary
- // setup.
- mChannelID = FSOUND_PlaySoundEx(FSOUND_FREE, samplep, FSOUND_DSP_GetSFXUnit(), true);
-
- //llinfos << "Setting up channel " << std::hex << mChannelID << std::dec << llendl;
- }
-
- // If we have a source for the channel, we need to update its gain.
- if (mCurrentSourcep)
- {
- // SJB: warnings can spam and hurt framerate, disabling
- if (!FSOUND_SetVolume(mChannelID, llround(getSecondaryGain() * mCurrentSourcep->getGain() * 255.0f)))
- {
-// llwarns << "LLAudioChannelFMOD::updateBuffer error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl;
- }
-
- if (!FSOUND_SetLoopMode(mChannelID, mCurrentSourcep->isLoop() ? FSOUND_LOOP_NORMAL : FSOUND_LOOP_OFF))
- {
-// llwarns << "Channel " << mChannelID << "Source ID: " << mCurrentSourcep->getID()
-// << " at " << mCurrentSourcep->getPositionGlobal() << llendl;
-// llwarns << "LLAudioChannelFMOD::updateBuffer error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl;
- }
- }
-
- return true;
-}
-
-
-void LLAudioChannelFMOD::update3DPosition()
-{
- if (!mChannelID)
- {
- // We're not actually a live channel (i.e., we're not playing back anything)
- return;
- }
-
- LLAudioBufferFMOD *bufferp = (LLAudioBufferFMOD *)mCurrentBufferp;
- if (!bufferp)
- {
- // We don't have a buffer associated with us (should really have been picked up
- // by the above if.
- return;
- }
-
- if (mCurrentSourcep->isAmbient())
- {
- // Ambient sound, don't need to do any positional updates.
- bufferp->set3DMode(false);
- }
- else
- {
- // Localized sound. Update the position and velocity of the sound.
- bufferp->set3DMode(true);
-
- LLVector3 float_pos;
- float_pos.setVec(mCurrentSourcep->getPositionGlobal());
- if (!FSOUND_3D_SetAttributes(mChannelID, float_pos.mV, mCurrentSourcep->getVelocity().mV))
- {
- LL_DEBUGS("FMOD") << "LLAudioChannelFMOD::update3DPosition error: " << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL;
- }
- }
-}
-
-
-void LLAudioChannelFMOD::updateLoop()
-{
- if (!mChannelID)
- {
- // May want to clear up the loop/sample counters.
- return;
- }
-
- //
- // Hack: We keep track of whether we looped or not by seeing when the
- // sample position looks like it's going backwards. Not reliable; may
- // yield false negatives.
- //
- U32 cur_pos = FSOUND_GetCurrentPosition(mChannelID);
- if (cur_pos < (U32)mLastSamplePos)
- {
- mLoopedThisFrame = true;
- }
- mLastSamplePos = cur_pos;
-}
-
-
-void LLAudioChannelFMOD::cleanup()
-{
- if (!mChannelID)
- {
- //llinfos << "Aborting cleanup with no channelID." << llendl;
- return;
- }
-
- //llinfos << "Cleaning up channel: " << mChannelID << llendl;
- if (!FSOUND_StopSound(mChannelID))
- {
- LL_DEBUGS("FMOD") << "LLAudioChannelFMOD::cleanup error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl;
- }
-
- mCurrentBufferp = NULL;
- mChannelID = 0;
-}
-
-
-void LLAudioChannelFMOD::play()
-{
- if (!mChannelID)
- {
- llwarns << "Playing without a channelID, aborting" << llendl;
- return;
- }
-
- if (!FSOUND_SetPaused(mChannelID, false))
- {
- llwarns << "LLAudioChannelFMOD::play error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl;
- }
- getSource()->setPlayedOnce(true);
-}
-
-
-void LLAudioChannelFMOD::playSynced(LLAudioChannel *channelp)
-{
- LLAudioChannelFMOD *fmod_channelp = (LLAudioChannelFMOD*)channelp;
- if (!(fmod_channelp->mChannelID && mChannelID))
- {
- // Don't have channels allocated to both the master and the slave
- return;
- }
-
- U32 position = FSOUND_GetCurrentPosition(fmod_channelp->mChannelID) % mCurrentBufferp->getLength();
- // Try to match the position of our sync master
- if (!FSOUND_SetCurrentPosition(mChannelID, position))
- {
- llwarns << "LLAudioChannelFMOD::playSynced unable to set current position" << llendl;
- }
-
- // Start us playing
- play();
-}
-
-
-bool LLAudioChannelFMOD::isPlaying()
-{
- if (!mChannelID)
- {
- return false;
- }
-
- return FSOUND_IsPlaying(mChannelID) && (!FSOUND_GetPaused(mChannelID));
-}
-
-
-
-//
-// LLAudioBufferFMOD implementation
-//
-
-
-LLAudioBufferFMOD::LLAudioBufferFMOD()
-{
- mSamplep = NULL;
-}
-
-
-LLAudioBufferFMOD::~LLAudioBufferFMOD()
-{
- if (mSamplep)
- {
- // Clean up the associated FMOD sample if it exists.
- FSOUND_Sample_Free(mSamplep);
- mSamplep = NULL;
- }
-}
-
-
-bool LLAudioBufferFMOD::loadWAV(const std::string& filename)
-{
- // Try to open a wav file from disk. This will eventually go away, as we don't
- // really want to block doing this.
- if (filename.empty())
- {
- // invalid filename, abort.
- return false;
- }
-
- if (!LLAPRFile::isExist(filename, NULL, LL_APR_RPB))
- {
- // File not found, abort.
- return false;
- }
-
- if (mSamplep)
- {
- // If there's already something loaded in this buffer, clean it up.
- FSOUND_Sample_Free(mSamplep);
- mSamplep = NULL;
- }
-
- // Load up the wav file into an fmod sample
-#if LL_WINDOWS
- // MikeS. - Loading the sound file manually and then handing it over to FMOD,
- // since FMOD uses posix IO internally,
- // which doesn't work with unicode file paths.
- LLFILE* sound_file = LLFile::fopen(filename,"rb"); /* Flawfinder: ignore */
- if (sound_file)
- {
- fseek(sound_file,0,SEEK_END);
- U32 file_length = ftell(sound_file); //Find the length of the file by seeking to the end and getting the offset
- size_t read_count;
- fseek(sound_file,0,SEEK_SET); //Seek back to the beginning
- char* buffer = new char[file_length];
- llassert(buffer);
- read_count = fread((void*)buffer,file_length,1,sound_file);//Load it..
- if(ferror(sound_file)==0 && (read_count == 1)){//No read error, and we got 1 chunk of our size...
- unsigned int mode_flags = FSOUND_LOOP_NORMAL | FSOUND_LOADMEMORY;
- //FSOUND_16BITS | FSOUND_MONO | FSOUND_LOADMEMORY | FSOUND_LOOP_NORMAL;
- mSamplep = FSOUND_Sample_Load(FSOUND_UNMANAGED, buffer, mode_flags , 0, file_length);
- }
- delete[] buffer;
- fclose(sound_file);
- }
-#else
- mSamplep = FSOUND_Sample_Load(FSOUND_UNMANAGED, filename.c_str(), FSOUND_LOOP_NORMAL, 0, 0);
-#endif
-
- if (!mSamplep)
- {
- // We failed to load the file for some reason.
- llwarns << "Could not load data '" << filename << "': "
- << FMOD_ErrorString(FSOUND_GetError()) << llendl;
-
- //
- // If we EVER want to load wav files provided by end users, we need
- // to rethink this!
- //
- // file is probably corrupt - remove it.
- LLFile::remove(filename);
- return false;
- }
-
- // Everything went well, return true
- return true;
-}
-
-
-U32 LLAudioBufferFMOD::getLength()
-{
- if (!mSamplep)
- {
- return 0;
- }
-
- return FSOUND_Sample_GetLength(mSamplep);
-}
-
-
-void LLAudioBufferFMOD::set3DMode(bool use3d)
-{
- U16 current_mode = FSOUND_Sample_GetMode(mSamplep);
-
- if (use3d)
- {
- if (!FSOUND_Sample_SetMode(mSamplep, (current_mode & (~FSOUND_2D))))
- {
- llwarns << "LLAudioBufferFMOD::set3DMode error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl;
- }
- }
- else
- {
- if (!FSOUND_Sample_SetMode(mSamplep, current_mode | FSOUND_2D))
- {
- llwarns << "LLAudioBufferFMOD::set3DMode error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl;
- }
- }
-}
-
-
-void * F_CALLBACKAPI windCallback(void *originalbuffer, void *newbuffer, int length, void* userdata)
-{
- // originalbuffer = fmod's original mixbuffer.
- // newbuffer = the buffer passed from the previous DSP unit.
- // length = length in samples at this mix time.
- // userdata = user parameter passed through in FSOUND_DSP_Create.
-
- LLWindGen<LLAudioEngine_FMOD::MIXBUFFERFORMAT> *windgen =
- (LLWindGen<LLAudioEngine_FMOD::MIXBUFFERFORMAT> *)userdata;
-
- newbuffer = windgen->windGenerate((LLAudioEngine_FMOD::MIXBUFFERFORMAT *)newbuffer, length);
-
- return newbuffer;
-}
diff --git a/indra/llaudio/llaudioengine_fmodex.cpp b/indra/llaudio/llaudioengine_fmodex.cpp
new file mode 100644
index 0000000000..5ec30c7d1d
--- /dev/null
+++ b/indra/llaudio/llaudioengine_fmodex.cpp
@@ -0,0 +1,746 @@
+/**
+ * @file audioengine_fmodex.cpp
+ * @brief Implementation of LLAudioEngine class abstracting the audio
+ * support as a FMODEX implementation
+ *
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llstreamingaudio.h"
+#include "llstreamingaudio_fmodex.h"
+
+#include "llaudioengine_fmodex.h"
+#include "lllistener_fmodex.h"
+
+#include "llerror.h"
+#include "llmath.h"
+#include "llrand.h"
+
+#include "fmod.hpp"
+#include "fmod_errors.h"
+#include "lldir.h"
+#include "llapr.h"
+
+#include "sound_ids.h"
+
+FMOD_RESULT F_CALLBACK windCallback(FMOD_DSP_STATE *dsp_state, float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int outchannels);
+
+FMOD::ChannelGroup *LLAudioEngine_FMODEX::mChannelGroups[LLAudioEngine::AUDIO_TYPE_COUNT] = {0};
+
+LLAudioEngine_FMODEX::LLAudioEngine_FMODEX(bool enable_profiler)
+{
+ mInited = false;
+ mWindGen = NULL;
+ mWindDSP = NULL;
+ mSystem = NULL;
+ mEnableProfiler = enable_profiler;
+}
+
+
+LLAudioEngine_FMODEX::~LLAudioEngine_FMODEX()
+{
+}
+
+
+inline bool Check_FMOD_Error(FMOD_RESULT result, const char *string)
+{
+ if(result == FMOD_OK)
+ return false;
+ llwarns << string << " Error: " << FMOD_ErrorString(result) << llendl;
+ return true;
+}
+
+void* F_STDCALL decode_alloc(unsigned int size, FMOD_MEMORY_TYPE type, const char *sourcestr)
+{
+ if(type & FMOD_MEMORY_STREAM_DECODE)
+ {
+ llinfos << "Decode buffer size: " << size << llendl;
+ }
+ else if(type & FMOD_MEMORY_STREAM_FILE)
+ {
+ llinfos << "Strean buffer size: " << size << llendl;
+ }
+ return new char[size];
+}
+void* F_STDCALL decode_realloc(void *ptr, unsigned int size, FMOD_MEMORY_TYPE type, const char *sourcestr)
+{
+ memset(ptr,0,size);
+ return ptr;
+}
+void F_STDCALL decode_dealloc(void *ptr, FMOD_MEMORY_TYPE type, const char *sourcestr)
+{
+ delete[] (char*)ptr;
+}
+
+bool LLAudioEngine_FMODEX::init(const S32 num_channels, void* userdata)
+{
+ U32 version;
+ FMOD_RESULT result;
+
+ LL_DEBUGS("AppInit") << "LLAudioEngine_FMODEX::init() initializing FMOD" << LL_ENDL;
+
+ //result = FMOD::Memory_Initialize(NULL, 0, &decode_alloc, &decode_realloc, &decode_dealloc, FMOD_MEMORY_STREAM_DECODE | FMOD_MEMORY_STREAM_FILE);
+ //if(Check_FMOD_Error(result, "FMOD::Memory_Initialize"))
+ // return false;
+
+ result = FMOD::System_Create(&mSystem);
+ if(Check_FMOD_Error(result, "FMOD::System_Create"))
+ return false;
+
+ //will call LLAudioEngine_FMODEX::allocateListener, which needs a valid mSystem pointer.
+ LLAudioEngine::init(num_channels, userdata);
+
+ result = mSystem->getVersion(&version);
+ Check_FMOD_Error(result, "FMOD::System::getVersion");
+
+ if (version < FMOD_VERSION)
+ {
+ LL_WARNS("AppInit") << "Error : You are using the wrong FMOD Ex version (" << version
+ << ")! You should be using FMOD Ex" << FMOD_VERSION << LL_ENDL;
+ }
+
+ result = mSystem->setSoftwareFormat(44100, FMOD_SOUND_FORMAT_PCM16, 0, 0, FMOD_DSP_RESAMPLER_LINEAR);
+ Check_FMOD_Error(result,"FMOD::System::setSoftwareFormat");
+
+ // In this case, all sounds, PLUS wind and stream will be software.
+ result = mSystem->setSoftwareChannels(num_channels + 2);
+ Check_FMOD_Error(result,"FMOD::System::setSoftwareChannels");
+
+ U32 fmod_flags = FMOD_INIT_NORMAL;
+ if(mEnableProfiler)
+ {
+ fmod_flags |= FMOD_INIT_ENABLE_PROFILE;
+ mSystem->createChannelGroup("None", &mChannelGroups[AUDIO_TYPE_NONE]);
+ mSystem->createChannelGroup("SFX", &mChannelGroups[AUDIO_TYPE_SFX]);
+ mSystem->createChannelGroup("UI", &mChannelGroups[AUDIO_TYPE_UI]);
+ mSystem->createChannelGroup("Ambient", &mChannelGroups[AUDIO_TYPE_AMBIENT]);
+ }
+
+#if LL_LINUX
+ bool audio_ok = false;
+
+ if (!audio_ok)
+ {
+ if (NULL == getenv("LL_BAD_FMOD_PULSEAUDIO")) /*Flawfinder: ignore*/
+ {
+ LL_DEBUGS("AppInit") << "Trying PulseAudio audio output..." << LL_ENDL;
+ if(mSystem->setOutput(FMOD_OUTPUTTYPE_PULSEAUDIO) == FMOD_OK &&
+ (result = mSystem->init(num_channels + 2, fmod_flags, 0)) == FMOD_OK)
+ {
+ LL_DEBUGS("AppInit") << "PulseAudio output initialized OKAY" << LL_ENDL;
+ audio_ok = true;
+ }
+ else
+ {
+ Check_FMOD_Error(result, "PulseAudio audio output FAILED to initialize");
+ }
+ }
+ else
+ {
+ LL_DEBUGS("AppInit") << "PulseAudio audio output SKIPPED" << LL_ENDL;
+ }
+ }
+ if (!audio_ok)
+ {
+ if (NULL == getenv("LL_BAD_FMOD_ALSA")) /*Flawfinder: ignore*/
+ {
+ LL_DEBUGS("AppInit") << "Trying ALSA audio output..." << LL_ENDL;
+ if(mSystem->setOutput(FMOD_OUTPUTTYPE_ALSA) == FMOD_OK &&
+ (result = mSystem->init(num_channels + 2, fmod_flags, 0)) == FMOD_OK)
+ {
+ LL_DEBUGS("AppInit") << "ALSA audio output initialized OKAY" << LL_ENDL;
+ audio_ok = true;
+ }
+ else
+ {
+ Check_FMOD_Error(result, "ALSA audio output FAILED to initialize");
+ }
+ }
+ else
+ {
+ LL_DEBUGS("AppInit") << "ALSA audio output SKIPPED" << LL_ENDL;
+ }
+ }
+ if (!audio_ok)
+ {
+ if (NULL == getenv("LL_BAD_FMOD_OSS")) /*Flawfinder: ignore*/
+ {
+ LL_DEBUGS("AppInit") << "Trying OSS audio output..." << LL_ENDL;
+ if(mSystem->setOutput(FMOD_OUTPUTTYPE_OSS) == FMOD_OK &&
+ (result = mSystem->init(num_channels + 2, fmod_flags, 0)) == FMOD_OK)
+ {
+ LL_DEBUGS("AppInit") << "OSS audio output initialized OKAY" << LL_ENDL;
+ audio_ok = true;
+ }
+ else
+ {
+ Check_FMOD_Error(result, "OSS audio output FAILED to initialize");
+ }
+ }
+ else
+ {
+ LL_DEBUGS("AppInit") << "OSS audio output SKIPPED" << LL_ENDL;
+ }
+ }
+ if (!audio_ok)
+ {
+ LL_WARNS("AppInit") << "Overall audio init failure." << LL_ENDL;
+ return false;
+ }
+
+ // We're interested in logging which output method we
+ // ended up with, for QA purposes.
+ FMOD_OUTPUTTYPE output_type;
+ mSystem->getOutput(&output_type);
+ switch (output_type)
+ {
+ case FMOD_OUTPUTTYPE_NOSOUND:
+ LL_INFOS("AppInit") << "Audio output: NoSound" << LL_ENDL; break;
+ case FMOD_OUTPUTTYPE_PULSEAUDIO:
+ LL_INFOS("AppInit") << "Audio output: PulseAudio" << LL_ENDL; break;
+ case FMOD_OUTPUTTYPE_ALSA:
+ LL_INFOS("AppInit") << "Audio output: ALSA" << LL_ENDL; break;
+ case FMOD_OUTPUTTYPE_OSS:
+ LL_INFOS("AppInit") << "Audio output: OSS" << LL_ENDL; break;
+ default:
+ LL_INFOS("AppInit") << "Audio output: Unknown!" << LL_ENDL; break;
+ };
+#else // LL_LINUX
+
+ // initialize the FMOD engine
+ result = mSystem->init( num_channels + 2, fmod_flags, 0);
+ if (result == FMOD_ERR_OUTPUT_CREATEBUFFER)
+ {
+ /*
+ Ok, the speaker mode selected isn't supported by this soundcard. Switch it
+ back to stereo...
+ */
+ result = mSystem->setSpeakerMode(FMOD_SPEAKERMODE_STEREO);
+ Check_FMOD_Error(result,"Error falling back to stereo mode");
+ /*
+ ... and re-init.
+ */
+ result = mSystem->init( num_channels + 2, fmod_flags, 0);
+ }
+ if(Check_FMOD_Error(result, "Error initializing FMOD Ex"))
+ return false;
+#endif
+
+ // set up our favourite FMOD-native streaming audio implementation if none has already been added
+ if (!getStreamingAudioImpl()) // no existing implementation added
+ setStreamingAudioImpl(new LLStreamingAudio_FMODEX(mSystem));
+
+ LL_INFOS("AppInit") << "LLAudioEngine_FMODEX::init() FMOD Ex initialized correctly" << LL_ENDL;
+
+ int r_numbuffers, r_samplerate, r_channels, r_bits;
+ unsigned int r_bufferlength;
+ char r_name[256];
+ mSystem->getDSPBufferSize(&r_bufferlength, &r_numbuffers);
+ mSystem->getSoftwareFormat(&r_samplerate, NULL, &r_channels, NULL, NULL, &r_bits);
+ mSystem->getDriverInfo(0, r_name, 255, 0);
+ r_name[255] = '\0';
+ int latency = (int)(1000.0f * r_bufferlength * r_numbuffers / r_samplerate);
+
+ LL_INFOS("AppInit") << "FMOD device: "<< r_name << "\n"
+ << "FMOD Ex parameters: " << r_samplerate << " Hz * " << r_channels << " * " <<r_bits <<" bit\n"
+ << "\tbuffer " << r_bufferlength << " * " << r_numbuffers << " (" << latency <<"ms)" << LL_ENDL;
+
+ mInited = true;
+
+ return true;
+}
+
+
+std::string LLAudioEngine_FMODEX::getDriverName(bool verbose)
+{
+ llassert_always(mSystem);
+ if (verbose)
+ {
+ U32 version;
+ if(!Check_FMOD_Error(mSystem->getVersion(&version), "FMOD::System::getVersion"))
+ {
+ return llformat("FMOD Ex %1x.%02x.%02x", version >> 16, version >> 8 & 0x000000FF, version & 0x000000FF);
+ }
+ }
+ return "FMODEx";
+}
+
+
+void LLAudioEngine_FMODEX::allocateListener(void)
+{
+ mListenerp = (LLListener *) new LLListener_FMODEX(mSystem);
+ if (!mListenerp)
+ {
+ llwarns << "Listener creation failed" << llendl;
+ }
+}
+
+
+void LLAudioEngine_FMODEX::shutdown()
+{
+ stopInternetStream();
+
+ llinfos << "About to LLAudioEngine::shutdown()" << llendl;
+ LLAudioEngine::shutdown();
+
+ llinfos << "LLAudioEngine_FMODEX::shutdown() closing FMOD Ex" << llendl;
+ mSystem->close();
+ mSystem->release();
+ llinfos << "LLAudioEngine_FMODEX::shutdown() done closing FMOD Ex" << llendl;
+
+ delete mListenerp;
+ mListenerp = NULL;
+}
+
+
+LLAudioBuffer * LLAudioEngine_FMODEX::createBuffer()
+{
+ return new LLAudioBufferFMODEX(mSystem);
+}
+
+
+LLAudioChannel * LLAudioEngine_FMODEX::createChannel()
+{
+ return new LLAudioChannelFMODEX(mSystem);
+}
+
+bool LLAudioEngine_FMODEX::initWind()
+{
+ mNextWindUpdate = 0.0;
+
+ if (!mWindDSP)
+ {
+ FMOD_DSP_DESCRIPTION dspdesc;
+ memset(&dspdesc, 0, sizeof(FMOD_DSP_DESCRIPTION)); //Set everything to zero
+ strncpy(dspdesc.name,"Wind Unit", sizeof(dspdesc.name)); //Set name to "Wind Unit"
+ dspdesc.channels=2;
+ dspdesc.read = &windCallback; //Assign callback.
+ if(Check_FMOD_Error(mSystem->createDSP(&dspdesc, &mWindDSP), "FMOD::createDSP"))
+ return false;
+
+ if(mWindGen)
+ delete mWindGen;
+
+ float frequency = 44100;
+ mWindDSP->getDefaults(&frequency,0,0,0);
+ mWindGen = new LLWindGen<MIXBUFFERFORMAT>((U32)frequency);
+ mWindDSP->setUserData((void*)mWindGen);
+ }
+
+ if (mWindDSP)
+ {
+ mSystem->playDSP(FMOD_CHANNEL_FREE, mWindDSP, false, 0);
+ return true;
+ }
+ return false;
+}
+
+
+void LLAudioEngine_FMODEX::cleanupWind()
+{
+ if (mWindDSP)
+ {
+ mWindDSP->remove();
+ mWindDSP->release();
+ mWindDSP = NULL;
+ }
+
+ delete mWindGen;
+ mWindGen = NULL;
+}
+
+
+//-----------------------------------------------------------------------
+void LLAudioEngine_FMODEX::updateWind(LLVector3 wind_vec, F32 camera_height_above_water)
+{
+ LLVector3 wind_pos;
+ F64 pitch;
+ F64 center_freq;
+
+ if (!mEnableWind)
+ {
+ return;
+ }
+
+ if (mWindUpdateTimer.checkExpirationAndReset(LL_WIND_UPDATE_INTERVAL))
+ {
+
+ // wind comes in as Linden coordinate (+X = forward, +Y = left, +Z = up)
+ // need to convert this to the conventional orientation DS3D and OpenAL use
+ // where +X = right, +Y = up, +Z = backwards
+
+ wind_vec.setVec(-wind_vec.mV[1], wind_vec.mV[2], -wind_vec.mV[0]);
+
+ // cerr << "Wind update" << endl;
+
+ pitch = 1.0 + mapWindVecToPitch(wind_vec);
+ center_freq = 80.0 * pow(pitch,2.5*(mapWindVecToGain(wind_vec)+1.0));
+
+ mWindGen->mTargetFreq = (F32)center_freq;
+ mWindGen->mTargetGain = (F32)mapWindVecToGain(wind_vec) * mMaxWindGain;
+ mWindGen->mTargetPanGainR = (F32)mapWindVecToPan(wind_vec);
+ }
+}
+
+//-----------------------------------------------------------------------
+void LLAudioEngine_FMODEX::setInternalGain(F32 gain)
+{
+ if (!mInited)
+ {
+ return;
+ }
+
+ gain = llclamp( gain, 0.0f, 1.0f );
+
+ FMOD::ChannelGroup *master_group;
+ mSystem->getMasterChannelGroup(&master_group);
+
+ master_group->setVolume(gain);
+
+ LLStreamingAudioInterface *saimpl = getStreamingAudioImpl();
+ if ( saimpl )
+ {
+ // fmod likes its streaming audio channel gain re-asserted after
+ // master volume change.
+ saimpl->setGain(saimpl->getGain());
+ }
+}
+
+//
+// LLAudioChannelFMODEX implementation
+//
+
+LLAudioChannelFMODEX::LLAudioChannelFMODEX(FMOD::System *system) : LLAudioChannel(), mSystemp(system), mChannelp(NULL), mLastSamplePos(0)
+{
+}
+
+
+LLAudioChannelFMODEX::~LLAudioChannelFMODEX()
+{
+ cleanup();
+}
+
+bool LLAudioChannelFMODEX::updateBuffer()
+{
+ if (LLAudioChannel::updateBuffer())
+ {
+ // Base class update returned true, which means that we need to actually
+ // set up the channel for a different buffer.
+
+ LLAudioBufferFMODEX *bufferp = (LLAudioBufferFMODEX *)mCurrentSourcep->getCurrentBuffer();
+
+ // Grab the FMOD sample associated with the buffer
+ FMOD::Sound *soundp = bufferp->getSound();
+ if (!soundp)
+ {
+ // This is bad, there should ALWAYS be a sound associated with a legit
+ // buffer.
+ llerrs << "No FMOD sound!" << llendl;
+ return false;
+ }
+
+
+ // Actually play the sound. Start it off paused so we can do all the necessary
+ // setup.
+ if(!mChannelp)
+ {
+ FMOD_RESULT result = getSystem()->playSound(FMOD_CHANNEL_FREE, soundp, true, &mChannelp);
+ Check_FMOD_Error(result, "FMOD::System::playSound");
+ }
+
+ //llinfos << "Setting up channel " << std::hex << mChannelID << std::dec << llendl;
+ }
+
+ // If we have a source for the channel, we need to update its gain.
+ if (mCurrentSourcep)
+ {
+ // SJB: warnings can spam and hurt framerate, disabling
+ //FMOD_RESULT result;
+
+ mChannelp->setVolume(getSecondaryGain() * mCurrentSourcep->getGain());
+ //Check_FMOD_Error(result, "FMOD::Channel::setVolume");
+
+ mChannelp->setMode(mCurrentSourcep->isLoop() ? FMOD_LOOP_NORMAL : FMOD_LOOP_OFF);
+ /*if(Check_FMOD_Error(result, "FMOD::Channel::setMode"))
+ {
+ S32 index;
+ mChannelp->getIndex(&index);
+ llwarns << "Channel " << index << "Source ID: " << mCurrentSourcep->getID()
+ << " at " << mCurrentSourcep->getPositionGlobal() << llendl;
+ }*/
+ }
+
+ return true;
+}
+
+
+void LLAudioChannelFMODEX::update3DPosition()
+{
+ if (!mChannelp)
+ {
+ // We're not actually a live channel (i.e., we're not playing back anything)
+ return;
+ }
+
+ LLAudioBufferFMODEX *bufferp = (LLAudioBufferFMODEX *)mCurrentBufferp;
+ if (!bufferp)
+ {
+ // We don't have a buffer associated with us (should really have been picked up
+ // by the above if.
+ return;
+ }
+
+ if (mCurrentSourcep->isAmbient())
+ {
+ // Ambient sound, don't need to do any positional updates.
+ set3DMode(false);
+ }
+ else
+ {
+ // Localized sound. Update the position and velocity of the sound.
+ set3DMode(true);
+
+ LLVector3 float_pos;
+ float_pos.setVec(mCurrentSourcep->getPositionGlobal());
+ FMOD_RESULT result = mChannelp->set3DAttributes((FMOD_VECTOR*)float_pos.mV, (FMOD_VECTOR*)mCurrentSourcep->getVelocity().mV);
+ Check_FMOD_Error(result, "FMOD::Channel::set3DAttributes");
+ }
+}
+
+
+void LLAudioChannelFMODEX::updateLoop()
+{
+ if (!mChannelp)
+ {
+ // May want to clear up the loop/sample counters.
+ return;
+ }
+
+ //
+ // Hack: We keep track of whether we looped or not by seeing when the
+ // sample position looks like it's going backwards. Not reliable; may
+ // yield false negatives.
+ //
+ U32 cur_pos;
+ mChannelp->getPosition(&cur_pos,FMOD_TIMEUNIT_PCMBYTES);
+
+ if (cur_pos < (U32)mLastSamplePos)
+ {
+ mLoopedThisFrame = true;
+ }
+ mLastSamplePos = cur_pos;
+}
+
+
+void LLAudioChannelFMODEX::cleanup()
+{
+ if (!mChannelp)
+ {
+ //llinfos << "Aborting cleanup with no channel handle." << llendl;
+ return;
+ }
+
+ //llinfos << "Cleaning up channel: " << mChannelID << llendl;
+ Check_FMOD_Error(mChannelp->stop(),"FMOD::Channel::stop");
+
+ mCurrentBufferp = NULL;
+ mChannelp = NULL;
+}
+
+
+void LLAudioChannelFMODEX::play()
+{
+ if (!mChannelp)
+ {
+ llwarns << "Playing without a channel handle, aborting" << llendl;
+ return;
+ }
+
+ Check_FMOD_Error(mChannelp->setPaused(false), "FMOD::Channel::pause");
+
+ getSource()->setPlayedOnce(true);
+
+ if(LLAudioEngine_FMODEX::mChannelGroups[getSource()->getType()])
+ mChannelp->setChannelGroup(LLAudioEngine_FMODEX::mChannelGroups[getSource()->getType()]);
+}
+
+
+void LLAudioChannelFMODEX::playSynced(LLAudioChannel *channelp)
+{
+ LLAudioChannelFMODEX *fmod_channelp = (LLAudioChannelFMODEX*)channelp;
+ if (!(fmod_channelp->mChannelp && mChannelp))
+ {
+ // Don't have channels allocated to both the master and the slave
+ return;
+ }
+
+ U32 cur_pos;
+ if(Check_FMOD_Error(mChannelp->getPosition(&cur_pos,FMOD_TIMEUNIT_PCMBYTES), "Unable to retrieve current position"))
+ return;
+
+ cur_pos %= mCurrentBufferp->getLength();
+
+ // Try to match the position of our sync master
+ Check_FMOD_Error(mChannelp->setPosition(cur_pos,FMOD_TIMEUNIT_PCMBYTES),"Unable to set current position");
+
+ // Start us playing
+ play();
+}
+
+
+bool LLAudioChannelFMODEX::isPlaying()
+{
+ if (!mChannelp)
+ {
+ return false;
+ }
+
+ bool paused, playing;
+ mChannelp->getPaused(&paused);
+ mChannelp->isPlaying(&playing);
+ return !paused && playing;
+}
+
+
+//
+// LLAudioChannelFMODEX implementation
+//
+
+
+LLAudioBufferFMODEX::LLAudioBufferFMODEX(FMOD::System *system) : mSystemp(system), mSoundp(NULL)
+{
+}
+
+
+LLAudioBufferFMODEX::~LLAudioBufferFMODEX()
+{
+ if(mSoundp)
+ {
+ mSoundp->release();
+ mSoundp = NULL;
+ }
+}
+
+
+bool LLAudioBufferFMODEX::loadWAV(const std::string& filename)
+{
+ // Try to open a wav file from disk. This will eventually go away, as we don't
+ // really want to block doing this.
+ if (filename.empty())
+ {
+ // invalid filename, abort.
+ return false;
+ }
+
+ if (!LLAPRFile::isExist(filename, NULL, LL_APR_RPB))
+ {
+ // File not found, abort.
+ return false;
+ }
+
+ if (mSoundp)
+ {
+ // If there's already something loaded in this buffer, clean it up.
+ mSoundp->release();
+ mSoundp = NULL;
+ }
+
+ FMOD_MODE base_mode = FMOD_LOOP_NORMAL | FMOD_SOFTWARE;
+ FMOD_CREATESOUNDEXINFO exinfo;
+ memset(&exinfo,0,sizeof(exinfo));
+ exinfo.cbsize = sizeof(exinfo);
+ exinfo.suggestedsoundtype = FMOD_SOUND_TYPE_WAV; //Hint to speed up loading.
+ // Load up the wav file into an fmod sample
+#if LL_WINDOWS
+ FMOD_RESULT result = getSystem()->createSound((const char*)utf8str_to_utf16str(filename).c_str(), base_mode | FMOD_UNICODE, &exinfo, &mSoundp);
+#else
+ FMOD_RESULT result = getSystem()->createSound(filename.c_str(), base_mode, &exinfo, &mSoundp);
+#endif
+
+ if (result != FMOD_OK)
+ {
+ // We failed to load the file for some reason.
+ llwarns << "Could not load data '" << filename << "': " << FMOD_ErrorString(result) << llendl;
+
+ //
+ // If we EVER want to load wav files provided by end users, we need
+ // to rethink this!
+ //
+ // file is probably corrupt - remove it.
+ LLFile::remove(filename);
+ return false;
+ }
+
+ // Everything went well, return true
+ return true;
+}
+
+
+U32 LLAudioBufferFMODEX::getLength()
+{
+ if (!mSoundp)
+ {
+ return 0;
+ }
+
+ U32 length;
+ mSoundp->getLength(&length, FMOD_TIMEUNIT_PCMBYTES);
+ return length;
+}
+
+
+void LLAudioChannelFMODEX::set3DMode(bool use3d)
+{
+ FMOD_MODE current_mode;
+ if(mChannelp->getMode(&current_mode) != FMOD_OK)
+ return;
+ FMOD_MODE new_mode = current_mode;
+ new_mode &= ~(use3d ? FMOD_2D : FMOD_3D);
+ new_mode |= use3d ? FMOD_3D : FMOD_2D;
+
+ if(current_mode != new_mode)
+ {
+ mChannelp->setMode(new_mode);
+ }
+}
+
+
+FMOD_RESULT F_CALLBACK windCallback(FMOD_DSP_STATE *dsp_state, float *originalbuffer, float *newbuffer, unsigned int length, int inchannels, int outchannels)
+{
+ // originalbuffer = fmod's original mixbuffer.
+ // newbuffer = the buffer passed from the previous DSP unit.
+ // length = length in samples at this mix time.
+ // userdata = user parameter passed through in FSOUND_DSP_Create.
+
+ LLWindGen<LLAudioEngine_FMODEX::MIXBUFFERFORMAT> *windgen;
+ FMOD::DSP *thisdsp = (FMOD::DSP *)dsp_state->instance;
+
+ thisdsp->getUserData((void **)&windgen);
+ S32 channels, configwidth, configheight;
+ thisdsp->getInfo(0, 0, &channels, &configwidth, &configheight);
+
+ windgen->windGenerate((LLAudioEngine_FMODEX::MIXBUFFERFORMAT *)newbuffer, length);
+
+ return FMOD_OK;
+}
diff --git a/indra/llaudio/llaudioengine_fmod.h b/indra/llaudio/llaudioengine_fmodex.h
index 4582a5d57e..415a9ed0ef 100644
--- a/indra/llaudio/llaudioengine_fmod.h
+++ b/indra/llaudio/llaudioengine_fmodex.h
@@ -1,7 +1,7 @@
/**
- * @file audioengine_fmod.h
- * @brief Definition of LLAudioEngine class abstracting the audio
- * support as a FMOD 3D implementation
+ * @file audioengine_fmodex.h
+ * @brief Definition of LLAudioEngine class abstracting the audio
+ * support as a FMODEX implementation
*
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
* Second Life Viewer Source Code
@@ -25,26 +25,33 @@
* $/LicenseInfo$
*/
-#ifndef LL_AUDIOENGINE_FMOD_H
-#define LL_AUDIOENGINE_FMOD_H
+#ifndef LL_AUDIOENGINE_FMODEX_H
+#define LL_AUDIOENGINE_FMODEX_H
#include "llaudioengine.h"
-#include "lllistener_fmod.h"
#include "llwindgen.h"
-#include "fmod.h"
-
-class LLAudioStreamManagerFMOD;
-
-class LLAudioEngine_FMOD : public LLAudioEngine
+//Stubs
+class LLAudioStreamManagerFMODEX;
+namespace FMOD
+{
+ class System;
+ class Channel;
+ class ChannelGroup;
+ class Sound;
+ class DSP;
+}
+
+//Interfaces
+class LLAudioEngine_FMODEX : public LLAudioEngine
{
public:
- LLAudioEngine_FMOD();
- virtual ~LLAudioEngine_FMOD();
+ LLAudioEngine_FMODEX(bool enable_profiler);
+ virtual ~LLAudioEngine_FMODEX();
// initialization/startup/shutdown
virtual bool init(const S32 num_channels, void *user_data);
- virtual std::string getDriverName(bool verbose);
+ virtual std::string getDriverName(bool verbose);
virtual void allocateListener();
virtual void shutdown();
@@ -54,38 +61,33 @@ public:
/*virtual*/void updateWind(LLVector3 direction, F32 camera_height_above_water);
-#if LL_DARWIN
- typedef S32 MIXBUFFERFORMAT;
-#else
- typedef S16 MIXBUFFERFORMAT;
-#endif
+ typedef F32 MIXBUFFERFORMAT;
+ FMOD::System *getSystem() const {return mSystem;}
protected:
/*virtual*/ LLAudioBuffer *createBuffer(); // Get a free buffer, or flush an existing one if you have to.
/*virtual*/ LLAudioChannel *createChannel(); // Create a new audio channel.
/*virtual*/ void setInternalGain(F32 gain);
-protected:
- static signed char F_CALLBACKAPI callbackMetaData(char* name, char* value, void* userdata);
-
- //F32 mMinDistance[MAX_BUFFERS];
- //F32 mMaxDistance[MAX_BUFFERS];
bool mInited;
- // On Windows, userdata is the HWND of the application window.
- void* mUserData;
-
LLWindGen<MIXBUFFERFORMAT> *mWindGen;
- FSOUND_DSPUNIT *mWindDSP;
+
+ FMOD::DSP *mWindDSP;
+ FMOD::System *mSystem;
+ bool mEnableProfiler;
+
+public:
+ static FMOD::ChannelGroup *mChannelGroups[LLAudioEngine::AUDIO_TYPE_COUNT];
};
-class LLAudioChannelFMOD : public LLAudioChannel
+class LLAudioChannelFMODEX : public LLAudioChannel
{
public:
- LLAudioChannelFMOD();
- virtual ~LLAudioChannelFMOD();
+ LLAudioChannelFMODEX(FMOD::System *audioengine);
+ virtual ~LLAudioChannelFMODEX();
protected:
/*virtual*/ void play();
@@ -97,28 +99,30 @@ protected:
/*virtual*/ void update3DPosition();
/*virtual*/ void updateLoop();
+ void set3DMode(bool use3d);
protected:
- int mChannelID;
+ FMOD::System *getSystem() const {return mSystemp;}
+ FMOD::System *mSystemp;
+ FMOD::Channel *mChannelp;
S32 mLastSamplePos;
};
-class LLAudioBufferFMOD : public LLAudioBuffer
+class LLAudioBufferFMODEX : public LLAudioBuffer
{
public:
- LLAudioBufferFMOD();
- virtual ~LLAudioBufferFMOD();
+ LLAudioBufferFMODEX(FMOD::System *audioengine);
+ virtual ~LLAudioBufferFMODEX();
/*virtual*/ bool loadWAV(const std::string& filename);
/*virtual*/ U32 getLength();
- friend class LLAudioChannelFMOD;
-
- void set3DMode(bool use3d);
-protected:
- FSOUND_SAMPLE *getSample() { return mSamplep; }
+ friend class LLAudioChannelFMODEX;
protected:
- FSOUND_SAMPLE *mSamplep;
+ FMOD::System *getSystem() const {return mSystemp;}
+ FMOD::System *mSystemp;
+ FMOD::Sound *getSound() const{ return mSoundp; }
+ FMOD::Sound *mSoundp;
};
-#endif // LL_AUDIOENGINE_FMOD_H
+#endif // LL_AUDIOENGINE_FMODEX_H
diff --git a/indra/llaudio/lllistener_fmod.cpp b/indra/llaudio/lllistener_fmodex.cpp
index 0138f4345e..2509a7aebc 100644
--- a/indra/llaudio/lllistener_fmod.cpp
+++ b/indra/llaudio/lllistener_fmodex.cpp
@@ -1,7 +1,7 @@
/**
- * @file listener_fmod.cpp
- * @brief implementation of LISTENER class abstracting the audio
- * support as a FMOD 3D implementation (windows only)
+ * @file listener_fmodex.cpp
+ * @brief Implementation of LISTENER class abstracting the audio
+ * support as a FMODEX implementation
*
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
* Second Life Viewer Source Code
@@ -27,24 +27,25 @@
#include "linden_common.h"
#include "llaudioengine.h"
-#include "lllistener_fmod.h"
-#include "fmod.h"
+#include "lllistener_fmodex.h"
+#include "fmod.hpp"
//-----------------------------------------------------------------------
// constructor
//-----------------------------------------------------------------------
-LLListener_FMOD::LLListener_FMOD()
+LLListener_FMODEX::LLListener_FMODEX(FMOD::System *system)
{
+ mSystem = system;
init();
}
//-----------------------------------------------------------------------
-LLListener_FMOD::~LLListener_FMOD()
+LLListener_FMODEX::~LLListener_FMODEX()
{
}
//-----------------------------------------------------------------------
-void LLListener_FMOD::init(void)
+void LLListener_FMODEX::init(void)
{
// do inherited
LLListener::init();
@@ -53,31 +54,31 @@ void LLListener_FMOD::init(void)
}
//-----------------------------------------------------------------------
-void LLListener_FMOD::translate(LLVector3 offset)
+void LLListener_FMODEX::translate(LLVector3 offset)
{
LLListener::translate(offset);
- FSOUND_3D_Listener_SetAttributes(mPosition.mV, NULL, mListenAt.mV[0],mListenAt.mV[1],mListenAt.mV[2], mListenUp.mV[0],mListenUp.mV[1],mListenUp.mV[2]);
+ mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV);
}
//-----------------------------------------------------------------------
-void LLListener_FMOD::setPosition(LLVector3 pos)
+void LLListener_FMODEX::setPosition(LLVector3 pos)
{
LLListener::setPosition(pos);
- FSOUND_3D_Listener_SetAttributes(pos.mV, NULL, mListenAt.mV[0],mListenAt.mV[1],mListenAt.mV[2], mListenUp.mV[0],mListenUp.mV[1],mListenUp.mV[2]);
+ mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV);
}
//-----------------------------------------------------------------------
-void LLListener_FMOD::setVelocity(LLVector3 vel)
+void LLListener_FMODEX::setVelocity(LLVector3 vel)
{
LLListener::setVelocity(vel);
- FSOUND_3D_Listener_SetAttributes(NULL, vel.mV, mListenAt.mV[0],mListenAt.mV[1],mListenAt.mV[2], mListenUp.mV[0],mListenUp.mV[1],mListenUp.mV[2]);
+ mSystem->set3DListenerAttributes(0, NULL, (FMOD_VECTOR*)mVelocity.mV, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV);
}
//-----------------------------------------------------------------------
-void LLListener_FMOD::orient(LLVector3 up, LLVector3 at)
+void LLListener_FMODEX::orient(LLVector3 up, LLVector3 at)
{
LLListener::orient(up, at);
@@ -87,37 +88,46 @@ void LLListener_FMOD::orient(LLVector3 up, LLVector3 at)
// since DX is left-handed and we (LL, OpenGL, OpenAL) are right-handed
at = -at;
- FSOUND_3D_Listener_SetAttributes(NULL, NULL, at.mV[0],at.mV[1],at.mV[2], up.mV[0],up.mV[1],up.mV[2]);
+ mSystem->set3DListenerAttributes(0, NULL, NULL, (FMOD_VECTOR*)at.mV, (FMOD_VECTOR*)up.mV);
}
//-----------------------------------------------------------------------
-void LLListener_FMOD::commitDeferredChanges()
+void LLListener_FMODEX::commitDeferredChanges()
{
- FSOUND_Update();
+ mSystem->update();
}
-void LLListener_FMOD::setRolloffFactor(F32 factor)
+void LLListener_FMODEX::setRolloffFactor(F32 factor)
{
+ //An internal FMODEx optimization skips 3D updates if there have not been changes to the 3D sound environment.
+ //Sadly, a change in rolloff is not accounted for, thus we must touch the listener properties as well.
+ //In short: Changing the position ticks a dirtyflag inside fmodex, which makes it not skip 3D processing next update call.
+ if(mRolloffFactor != factor)
+ {
+ LLVector3 pos = mVelocity - LLVector3(0.f,0.f,.1f);
+ mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)pos.mV, NULL, NULL, NULL);
+ mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mVelocity.mV, NULL, NULL, NULL);
+ }
mRolloffFactor = factor;
- FSOUND_3D_SetRolloffFactor(factor);
+ mSystem->set3DSettings(mDopplerFactor, 1.f, mRolloffFactor);
}
-F32 LLListener_FMOD::getRolloffFactor()
+F32 LLListener_FMODEX::getRolloffFactor()
{
return mRolloffFactor;
}
-void LLListener_FMOD::setDopplerFactor(F32 factor)
+void LLListener_FMODEX::setDopplerFactor(F32 factor)
{
mDopplerFactor = factor;
- FSOUND_3D_SetDopplerFactor(factor);
+ mSystem->set3DSettings(mDopplerFactor, 1.f, mRolloffFactor);
}
-F32 LLListener_FMOD::getDopplerFactor()
+F32 LLListener_FMODEX::getDopplerFactor()
{
return mDopplerFactor;
}
diff --git a/indra/llaudio/lllistener_fmod.h b/indra/llaudio/lllistener_fmodex.h
index 818da05d51..073b65d53a 100644
--- a/indra/llaudio/lllistener_fmod.h
+++ b/indra/llaudio/lllistener_fmodex.h
@@ -1,5 +1,5 @@
/**
- * @file listener_fmod.h
+ * @file listener_fmodex.h
* @brief Description of LISTENER class abstracting the audio support
* as an FMOD 3D implementation (windows and Linux)
*
@@ -25,16 +25,23 @@
* $/LicenseInfo$
*/
-#ifndef LL_LISTENER_FMOD_H
-#define LL_LISTENER_FMOD_H
+#ifndef LL_LISTENER_FMODEX_H
+#define LL_LISTENER_FMODEX_H
#include "lllistener.h"
-class LLListener_FMOD : public LLListener
+//Stubs
+namespace FMOD
+{
+ class System;
+}
+
+//Interfaces
+class LLListener_FMODEX : public LLListener
{
public:
- LLListener_FMOD();
- virtual ~LLListener_FMOD();
+ LLListener_FMODEX(FMOD::System *system);
+ virtual ~LLListener_FMODEX();
virtual void init();
virtual void translate(LLVector3 offset);
@@ -47,8 +54,8 @@ class LLListener_FMOD : public LLListener
virtual F32 getDopplerFactor();
virtual void setRolloffFactor(F32 factor);
virtual F32 getRolloffFactor();
-
protected:
+ FMOD::System *mSystem;
F32 mDopplerFactor;
F32 mRolloffFactor;
};
diff --git a/indra/llaudio/llstreamingaudio.h b/indra/llaudio/llstreamingaudio.h
index 20104af744..93479f9d59 100644
--- a/indra/llaudio/llstreamingaudio.h
+++ b/indra/llaudio/llstreamingaudio.h
@@ -45,6 +45,8 @@ class LLStreamingAudioInterface
virtual void setGain(F32 vol) = 0;
virtual F32 getGain() = 0;
virtual std::string getURL() = 0;
+ virtual bool supportsAdjustableBufferSizes(){return false;}
+ virtual void setBufferSizes(U32 streambuffertime, U32 decodebuffertime){};
};
#endif // LL_STREAMINGAUDIO_H
diff --git a/indra/llaudio/llstreamingaudio_fmod.cpp b/indra/llaudio/llstreamingaudio_fmodex.cpp
index bcdea771a7..4a74267650 100644
--- a/indra/llaudio/llstreamingaudio_fmod.cpp
+++ b/indra/llaudio/llstreamingaudio_fmodex.cpp
@@ -1,8 +1,8 @@
/**
- * @file streamingaudio_fmod.cpp
- * @brief LLStreamingAudio_FMOD implementation
+ * @file streamingaudio_fmodex.cpp
+ * @brief LLStreamingAudio_FMODEX implementation
*
- * $LicenseInfo:firstyear=2009&license=viewerlgpl$
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
@@ -28,25 +28,27 @@
#include "llmath.h"
-#include "fmod.h"
+#include "fmod.hpp"
#include "fmod_errors.h"
-#include "llstreamingaudio_fmod.h"
+#include "llstreamingaudio_fmodex.h"
-class LLAudioStreamManagerFMOD
+class LLAudioStreamManagerFMODEX
{
public:
- LLAudioStreamManagerFMOD(const std::string& url);
- int startStream();
+ LLAudioStreamManagerFMODEX(FMOD::System *system, const std::string& url);
+ FMOD::Channel* startStream();
bool stopStream(); // Returns true if the stream was successfully stopped.
bool ready();
const std::string& getURL() { return mInternetStreamURL; }
- int getOpenState();
+ FMOD_OPENSTATE getOpenState(unsigned int* percentbuffered=NULL, bool* starving=NULL, bool* diskbusy=NULL);
protected:
- FSOUND_STREAM* mInternetStream;
+ FMOD::System* mSystem;
+ FMOD::Channel* mStreamChannel;
+ FMOD::Sound* mInternetStream;
bool mReady;
std::string mInternetStreamURL;
@@ -57,14 +59,17 @@ protected:
//---------------------------------------------------------------------------
// Internet Streaming
//---------------------------------------------------------------------------
-LLStreamingAudio_FMOD::LLStreamingAudio_FMOD() :
+LLStreamingAudio_FMODEX::LLStreamingAudio_FMODEX(FMOD::System *system) :
+ mSystem(system),
mCurrentInternetStreamp(NULL),
- mFMODInternetStreamChannel(-1),
+ mFMODInternetStreamChannelp(NULL),
mGain(1.0f)
{
// Number of milliseconds of audio to buffer for the audio card.
// Must be larger than the usual Second Life frame stutter time.
- FSOUND_Stream_SetBufferSize(200);
+ const U32 buffer_seconds = 10; //sec
+ const U32 estimated_bitrate = 128; //kbit/sec
+ mSystem->setStreamBufferSize(estimated_bitrate * buffer_seconds * 128/*bytes/kbit*/, FMOD_TIMEUNIT_RAWBYTES);
// Here's where we set the size of the network buffer and some buffering
// parameters. In this case we want a network buffer of 16k, we want it
@@ -76,13 +81,13 @@ LLStreamingAudio_FMOD::LLStreamingAudio_FMOD() :
}
-LLStreamingAudio_FMOD::~LLStreamingAudio_FMOD()
+LLStreamingAudio_FMODEX::~LLStreamingAudio_FMODEX()
{
// nothing interesting/safe to do.
}
-void LLStreamingAudio_FMOD::start(const std::string& url)
+void LLStreamingAudio_FMODEX::start(const std::string& url)
{
//if (!mInited)
//{
@@ -96,7 +101,7 @@ void LLStreamingAudio_FMOD::start(const std::string& url)
if (!url.empty())
{
llinfos << "Starting internet stream: " << url << llendl;
- mCurrentInternetStreamp = new LLAudioStreamManagerFMOD(url);
+ mCurrentInternetStreamp = new LLAudioStreamManagerFMODEX(mSystem,url);
mURL = url;
}
else
@@ -107,13 +112,13 @@ void LLStreamingAudio_FMOD::start(const std::string& url)
}
-void LLStreamingAudio_FMOD::update()
+void LLStreamingAudio_FMODEX::update()
{
// Kill dead internet streams, if possible
- std::list<LLAudioStreamManagerFMOD *>::iterator iter;
+ std::list<LLAudioStreamManagerFMODEX *>::iterator iter;
for (iter = mDeadStreams.begin(); iter != mDeadStreams.end();)
{
- LLAudioStreamManagerFMOD *streamp = *iter;
+ LLAudioStreamManagerFMODEX *streamp = *iter;
if (streamp->stopStream())
{
llinfos << "Closed dead stream" << llendl;
@@ -132,62 +137,66 @@ void LLStreamingAudio_FMOD::update()
return;
}
- int open_state = mCurrentInternetStreamp->getOpenState();
+ unsigned int progress;
+ bool starving;
+ bool diskbusy;
+ FMOD_OPENSTATE open_state = mCurrentInternetStreamp->getOpenState(&progress, &starving, &diskbusy);
- if (!open_state)
+ if (open_state == FMOD_OPENSTATE_READY)
{
// Stream is live
// start the stream if it's ready
- if (mFMODInternetStreamChannel < 0)
+ if (!mFMODInternetStreamChannelp &&
+ (mFMODInternetStreamChannelp = mCurrentInternetStreamp->startStream()))
{
- mFMODInternetStreamChannel = mCurrentInternetStreamp->startStream();
-
- if (mFMODInternetStreamChannel != -1)
- {
- // Reset volume to previously set volume
- setGain(getGain());
- FSOUND_SetPaused(mFMODInternetStreamChannel, false);
- }
+ // Reset volume to previously set volume
+ setGain(getGain());
+ mFMODInternetStreamChannelp->setPaused(false);
+ mLastStarved.stop();
}
}
-
- switch(open_state)
+ else if(open_state == FMOD_OPENSTATE_ERROR)
{
- default:
- case 0:
- // success
- break;
- case -1:
- // stream handle is invalid
- llwarns << "InternetStream - invalid handle" << llendl;
stop();
return;
- case -2:
- // opening
- break;
- case -3:
- // failed to open, file not found, perhaps
- llwarns << "InternetStream - failed to open" << llendl;
- stop();
- return;
- case -4:
- // connecting
- break;
- case -5:
- // buffering
- break;
}
+ if(mFMODInternetStreamChannelp)
+ {
+ FMOD::Sound *sound = NULL;
+
+ if(mFMODInternetStreamChannelp->getCurrentSound(&sound) == FMOD_OK && sound)
+ {
+ if(starving)
+ {
+ if(!mLastStarved.getStarted())
+ {
+ llinfos << "Stream starvation detected! Muting stream audio until it clears." << llendl;
+ llinfos << " (diskbusy="<<diskbusy<<")" << llendl;
+ llinfos << " (progress="<<progress<<")" << llendl;
+ mFMODInternetStreamChannelp->setMute(true);
+ }
+ mLastStarved.start();
+ }
+ else if(mLastStarved.getStarted() && mLastStarved.getElapsedTimeF32() > 1.f)
+ {
+ mLastStarved.stop();
+ mFMODInternetStreamChannelp->setMute(false);
+ }
+ }
+ }
}
-void LLStreamingAudio_FMOD::stop()
+void LLStreamingAudio_FMODEX::stop()
{
- if (mFMODInternetStreamChannel != -1)
+ mLastStarved.stop();
+
+ if (mFMODInternetStreamChannelp)
{
- FSOUND_SetPaused(mFMODInternetStreamChannel, true);
- FSOUND_SetPriority(mFMODInternetStreamChannel, 0);
- mFMODInternetStreamChannel = -1;
+ mFMODInternetStreamChannelp->setPaused(true);
+ mFMODInternetStreamChannelp->setPriority(0);
+ mFMODInternetStreamChannelp = NULL;
}
if (mCurrentInternetStreamp)
@@ -207,7 +216,7 @@ void LLStreamingAudio_FMOD::stop()
}
}
-void LLStreamingAudio_FMOD::pause(int pauseopt)
+void LLStreamingAudio_FMODEX::pause(int pauseopt)
{
if (pauseopt < 0)
{
@@ -230,7 +239,7 @@ void LLStreamingAudio_FMOD::pause(int pauseopt)
// A stream is "playing" if it has been requested to start. That
// doesn't necessarily mean audio is coming out of the speakers.
-int LLStreamingAudio_FMOD::isPlaying()
+int LLStreamingAudio_FMODEX::isPlaying()
{
if (mCurrentInternetStreamp)
{
@@ -247,44 +256,47 @@ int LLStreamingAudio_FMOD::isPlaying()
}
-F32 LLStreamingAudio_FMOD::getGain()
+F32 LLStreamingAudio_FMODEX::getGain()
{
return mGain;
}
-std::string LLStreamingAudio_FMOD::getURL()
+std::string LLStreamingAudio_FMODEX::getURL()
{
return mURL;
}
-void LLStreamingAudio_FMOD::setGain(F32 vol)
+void LLStreamingAudio_FMODEX::setGain(F32 vol)
{
mGain = vol;
- if (mFMODInternetStreamChannel != -1)
+ if (mFMODInternetStreamChannelp)
{
- vol = llclamp(vol * vol, 0.f, 1.f);
- int vol_int = llround(vol * 255.f);
- FSOUND_SetVolumeAbsolute(mFMODInternetStreamChannel, vol_int);
+ vol = llclamp(vol * vol, 0.f, 1.f); //should vol be squared here?
+
+ mFMODInternetStreamChannelp->setVolume(vol);
}
}
-
///////////////////////////////////////////////////////
// manager of possibly-multiple internet audio streams
-LLAudioStreamManagerFMOD::LLAudioStreamManagerFMOD(const std::string& url) :
+LLAudioStreamManagerFMODEX::LLAudioStreamManagerFMODEX(FMOD::System *system, const std::string& url) :
+ mSystem(system),
+ mStreamChannel(NULL),
mInternetStream(NULL),
mReady(false)
{
mInternetStreamURL = url;
- mInternetStream = FSOUND_Stream_Open(url.c_str(), FSOUND_NORMAL | FSOUND_NONBLOCKING, 0, 0);
- if (!mInternetStream)
+
+ FMOD_RESULT result = mSystem->createStream(url.c_str(), FMOD_2D | FMOD_NONBLOCKING | FMOD_MPEGSEARCH | FMOD_IGNORETAGS, 0, &mInternetStream);
+
+ if (result!= FMOD_OK)
{
llwarns << "Couldn't open fmod stream, error "
- << FMOD_ErrorString(FSOUND_GetError())
+ << FMOD_ErrorString(result)
<< llendl;
mReady = false;
return;
@@ -293,48 +305,42 @@ LLAudioStreamManagerFMOD::LLAudioStreamManagerFMOD(const std::string& url) :
mReady = true;
}
-int LLAudioStreamManagerFMOD::startStream()
+FMOD::Channel *LLAudioStreamManagerFMODEX::startStream()
{
// We need a live and opened stream before we try and play it.
- if (!mInternetStream || getOpenState())
+ if (!mInternetStream || getOpenState() != FMOD_OPENSTATE_READY)
{
llwarns << "No internet stream to start playing!" << llendl;
- return -1;
+ return NULL;
}
- // Make sure the stream is set to 2D mode.
- FSOUND_Stream_SetMode(mInternetStream, FSOUND_2D);
+ if(mStreamChannel)
+ return mStreamChannel; //Already have a channel for this stream.
- return FSOUND_Stream_PlayEx(FSOUND_FREE, mInternetStream, NULL, true);
+ mSystem->playSound(FMOD_CHANNEL_FREE, mInternetStream, true, &mStreamChannel);
+ return mStreamChannel;
}
-bool LLAudioStreamManagerFMOD::stopStream()
+bool LLAudioStreamManagerFMODEX::stopStream()
{
if (mInternetStream)
{
- int read_percent = 0;
- int status = 0;
- int bitrate = 0;
- unsigned int flags = 0x0;
- FSOUND_Stream_Net_GetStatus(mInternetStream, &status, &read_percent, &bitrate, &flags);
+
bool close = true;
- switch (status)
+ switch (getOpenState())
{
- case FSOUND_STREAM_NET_CONNECTING:
+ case FMOD_OPENSTATE_CONNECTING:
close = false;
break;
- case FSOUND_STREAM_NET_NOTCONNECTED:
- case FSOUND_STREAM_NET_BUFFERING:
- case FSOUND_STREAM_NET_READY:
- case FSOUND_STREAM_NET_ERROR:
default:
close = true;
}
if (close)
{
- FSOUND_Stream_Close(mInternetStream);
+ mInternetStream->release();
+ mStreamChannel = NULL;
mInternetStream = NULL;
return true;
}
@@ -349,8 +355,19 @@ bool LLAudioStreamManagerFMOD::stopStream()
}
}
-int LLAudioStreamManagerFMOD::getOpenState()
+FMOD_OPENSTATE LLAudioStreamManagerFMODEX::getOpenState(unsigned int* percentbuffered, bool* starving, bool* diskbusy)
+{
+ FMOD_OPENSTATE state;
+ mInternetStream->getOpenState(&state, percentbuffered, starving, diskbusy);
+ return state;
+}
+
+void LLStreamingAudio_FMODEX::setBufferSizes(U32 streambuffertime, U32 decodebuffertime)
{
- int open_state = FSOUND_Stream_GetOpenState(mInternetStream);
- return open_state;
+ mSystem->setStreamBufferSize(streambuffertime/1000*128*128, FMOD_TIMEUNIT_RAWBYTES);
+ FMOD_ADVANCEDSETTINGS settings;
+ memset(&settings,0,sizeof(settings));
+ settings.cbsize=sizeof(settings);
+ settings.defaultDecodeBufferSize = decodebuffertime;//ms
+ mSystem->setAdvancedSettings(&settings);
}
diff --git a/indra/llaudio/llstreamingaudio_fmod.h b/indra/llaudio/llstreamingaudio_fmodex.h
index 9970f0d03b..42b6b3aaa8 100644
--- a/indra/llaudio/llstreamingaudio_fmod.h
+++ b/indra/llaudio/llstreamingaudio_fmodex.h
@@ -1,9 +1,8 @@
/**
- * @file streamingaudio_fmod.h
- * @author Tofu Linden
- * @brief Definition of LLStreamingAudio_FMOD implementation
+ * @file streamingaudio_fmodex.h
+ * @brief Definition of LLStreamingAudio_FMODEX implementation
*
- * $LicenseInfo:firstyear=2009&license=viewerlgpl$
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
@@ -25,20 +24,28 @@
* $/LicenseInfo$
*/
-#ifndef LL_STREAMINGAUDIO_FMOD_H
-#define LL_STREAMINGAUDIO_FMOD_H
+#ifndef LL_STREAMINGAUDIO_FMODEX_H
+#define LL_STREAMINGAUDIO_FMODEX_H
#include "stdtypes.h" // from llcommon
#include "llstreamingaudio.h"
+#include "lltimer.h"
-class LLAudioStreamManagerFMOD;
+//Stubs
+class LLAudioStreamManagerFMODEX;
+namespace FMOD
+{
+ class System;
+ class Channel;
+}
-class LLStreamingAudio_FMOD : public LLStreamingAudioInterface
+//Interfaces
+class LLStreamingAudio_FMODEX : public LLStreamingAudioInterface
{
public:
- LLStreamingAudio_FMOD();
- /*virtual*/ ~LLStreamingAudio_FMOD();
+ LLStreamingAudio_FMODEX(FMOD::System *system);
+ /*virtual*/ ~LLStreamingAudio_FMODEX();
/*virtual*/ void start(const std::string& url);
/*virtual*/ void stop();
@@ -49,14 +56,20 @@ class LLStreamingAudio_FMOD : public LLStreamingAudioInterface
/*virtual*/ F32 getGain();
/*virtual*/ std::string getURL();
+ /*virtual*/ bool supportsAdjustableBufferSizes(){return true;}
+ /*virtual*/ void setBufferSizes(U32 streambuffertime, U32 decodebuffertime);
private:
- LLAudioStreamManagerFMOD *mCurrentInternetStreamp;
- int mFMODInternetStreamChannel;
- std::list<LLAudioStreamManagerFMOD *> mDeadStreams;
+ FMOD::System *mSystem;
+
+ LLAudioStreamManagerFMODEX *mCurrentInternetStreamp;
+ FMOD::Channel *mFMODInternetStreamChannelp;
+ std::list<LLAudioStreamManagerFMODEX *> mDeadStreams;
std::string mURL;
F32 mGain;
+
+ LLTimer mLastStarved;
};
-#endif // LL_STREAMINGAUDIO_FMOD_H
+#endif // LL_STREAMINGAUDIO_FMODEX_H
diff --git a/indra/llaudio/llvorbisencode.cpp b/indra/llaudio/llvorbisencode.cpp
index 0e0c80a456..dfd5da12b3 100644
--- a/indra/llaudio/llvorbisencode.cpp
+++ b/indra/llaudio/llvorbisencode.cpp
@@ -35,7 +35,7 @@
#include "llapr.h"
//#if LL_DARWIN
-// MBW -- XXX -- Getting rid of SecondLifeVorbis for now -- no fmod means no name collisions.
+// MBW -- XXX -- Getting rid of SecondLifeVorbis for now
#if 0
#include "VorbisFramework.h"
diff --git a/indra/llaudio/llwindgen.h b/indra/llaudio/llwindgen.h
index b9cecb60a1..719b0ecbf2 100644
--- a/indra/llaudio/llwindgen.h
+++ b/indra/llaudio/llwindgen.h
@@ -27,6 +27,7 @@
#define WINDGEN_H
#include "llcommon.h"
+#include "llrand.h"
template <class MIXBUFFERFORMAT_T>
class LLWindGen
@@ -54,7 +55,9 @@ public:
}
const U32 getInputSamplingRate() { return mInputSamplingRate; }
-
+ const F32 getNextSample();
+ const F32 getClampedSample(bool clamp, F32 sample);
+
// newbuffer = the buffer passed from the previous DSP unit.
// numsamples = length in samples-per-channel at this mix time.
// NOTE: generates L/R interleaved stereo
@@ -89,7 +92,7 @@ public:
// Start with white noise
// This expression is fragile, rearrange it and it will break!
- next_sample = (F32)rand() * (1.0f / (F32)(RAND_MAX / (U16_MAX / 8))) + (F32)(S16_MIN / 8);
+ next_sample = getNextSample();
// Apply a pinking filter
// Magic numbers taken from PKE method at http://www.firstpr.com.au/dsp/pink-noise/
@@ -126,23 +129,13 @@ public:
for (U8 i=mSubSamples; i && numsamples; --i, --numsamples)
{
mLastSample = mLastSample + delta;
- S32 sample_right = (S32)(mLastSample * mCurrentPanGainR);
- S32 sample_left = (S32)mLastSample - sample_right;
+ MIXBUFFERFORMAT_T sample_right = (MIXBUFFERFORMAT_T)getClampedSample(clip, mLastSample * mCurrentPanGainR);
+ MIXBUFFERFORMAT_T sample_left = (MIXBUFFERFORMAT_T)getClampedSample(clip, mLastSample - (F32)sample_right);
- if (!clip)
- {
- *cursamplep = (MIXBUFFERFORMAT_T)sample_left;
- ++cursamplep;
- *cursamplep = (MIXBUFFERFORMAT_T)sample_right;
- ++cursamplep;
- }
- else
- {
- *cursamplep = (MIXBUFFERFORMAT_T)llclamp(sample_left, (S32)S16_MIN, (S32)S16_MAX);
- ++cursamplep;
- *cursamplep = (MIXBUFFERFORMAT_T)llclamp(sample_right, (S32)S16_MIN, (S32)S16_MAX);
- ++cursamplep;
- }
+ *cursamplep = sample_left;
+ ++cursamplep;
+ *cursamplep = sample_right;
+ ++cursamplep;
}
}
@@ -173,4 +166,9 @@ private:
F32 mLastSample;
};
+template<class T> inline const F32 LLWindGen<T>::getNextSample() { return (F32)rand() * (1.0f / (F32)(RAND_MAX / (U16_MAX / 8))) + (F32)(S16_MIN / 8); }
+template<> inline const F32 LLWindGen<F32>::getNextSample() { return ll_frand()-.5f; }
+template<class T> inline const F32 LLWindGen<T>::getClampedSample(bool clamp, F32 sample) { return clamp ? (F32)llclamp((S32)sample,(S32)S16_MIN,(S32)S16_MAX) : sample; }
+template<> inline const F32 LLWindGen<F32>::getClampedSample(bool clamp, F32 sample) { return sample; }
+
#endif
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 4f7ce88165..fae02c0b30 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -10,7 +10,7 @@ include(DirectX)
include(OpenSSL)
include(DragDrop)
include(EXPAT)
-include(FMOD)
+include(FMODEX)
include(OPENAL)
include(OpenGL)
include(Hunspell)
@@ -53,6 +53,10 @@ if (NOT HAVOK_TPV)
add_subdirectory(${LLPHYSICSEXTENSIONS_SRC_DIR} llphysicsextensions)
endif (NOT HAVOK_TPV)
+if(FMODEX)
+ include_directories(${FMODEX_INCLUDE_DIR})
+endif(FMODEX)
+
include_directories(
${DBUSGLIB_INCLUDE_DIRS}
${JSONCPP_INCLUDE_DIR}
@@ -62,7 +66,6 @@ include_directories(
${LLCOMMON_INCLUDE_DIRS}
${LLCOREHTTP_INCLUDE_DIRS}
${LLPHYSICS_INCLUDE_DIRS}
- ${FMOD_INCLUDE_DIR}
${LLIMAGE_INCLUDE_DIRS}
${LLKDU_INCLUDE_DIRS}
${LLINVENTORY_INCLUDE_DIRS}
@@ -1533,29 +1536,12 @@ endif (WINDOWS)
if (OPENAL)
set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DLL_OPENAL")
-endif (OPENAL)
-
-if (FMOD)
- set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DLL_FMOD")
+endif (OPENAL)
- if (DARWIN)
- set(fmodwrapper_SOURCE_FILES fmodwrapper.cpp)
- add_library(fmodwrapper SHARED ${fmodwrapper_SOURCE_FILES})
- set(fmodwrapper_needed_LIBRARIES ${FMOD_LIBRARY} ${CARBON_LIBRARY})
- set_target_properties(
- fmodwrapper
- PROPERTIES
- BUILD_WITH_INSTALL_RPATH 1
- INSTALL_NAME_DIR "@executable_path/../Resources"
- LINK_FLAGS "-unexported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/fmod_hidden_symbols.exp"
- )
- set(FMODWRAPPER_LIBRARY fmodwrapper)
- target_link_libraries(fmodwrapper ${fmodwrapper_needed_LIBRARIES})
- else (DARWIN)
- # fmodwrapper unnecessary on linux or windows
- set(FMODWRAPPER_LIBRARY ${FMOD_LIBRARY})
- endif (DARWIN)
-endif (FMOD)
+if (FMODEX)
+ set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DLL_FMODEX")
+ set(FMODWRAPPER_LIBRARY ${FMODEX_LIBRARY})
+endif (FMODEX)
set_source_files_properties(llstartup.cpp PROPERTIES COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS}")
@@ -1636,9 +1622,6 @@ if (WINDOWS)
${SHARED_LIB_STAGING_DIR}/Release/openjpeg.dll
${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/openjpeg.dll
${SHARED_LIB_STAGING_DIR}/Debug/openjpegd.dll
- ${SHARED_LIB_STAGING_DIR}/Release/fmod.dll
- ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/fmod.dll
- ${SHARED_LIB_STAGING_DIR}/Debug/fmod.dll
${SHARED_LIB_STAGING_DIR}/Release/msvcr100.dll
${SHARED_LIB_STAGING_DIR}/Release/msvcp100.dll
${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/msvcr100.dll
@@ -1703,6 +1686,14 @@ if (WINDOWS)
windows-updater
)
+ if (FMODEX)
+ list(APPEND COPY_INPUT_DEPENDENCIES
+ ${SHARED_LIB_STAGING_DIR}/Release/fmodex.dll
+ ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/fmodex.dll
+ ${SHARED_LIB_STAGING_DIR}/Debug/fmodexL.dll
+ )
+ endif (FMODEX)
+
add_custom_command(
OUTPUT ${CMAKE_CFG_INTDIR}/copy_touched.bat
COMMAND ${PYTHON_EXECUTABLE}
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index f66d8fca5b..3281d347a7 100755
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -291,6 +291,17 @@
<key>Value</key>
<real>1.0</real>
</map>
+ <key>AudioLevelUnderwaterRolloff</key>
+ <map>
+ <key>Comment</key>
+ <string>Controls the distance-based dropoff of audio volume underwater(fraction or multiple of default audio rolloff)</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>5.0</real>
+ </map>
<key>AudioLevelSFX</key>
<map>
<key>Comment</key>
@@ -14446,7 +14457,50 @@
<key>Value</key>
<integer>0</integer>
</map>
-
+ <key>DisablePrecacheDelayAfterTeleporting</key>
+ <map>
+ <key>Comment</key>
+ <string>Disables the artificial delay in the viewer that precaches some incoming assets</string>
+ <key>Persist</key>
+ <integer>0</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>FMODExProfilerEnable</key>
+ <map>
+ <key>Comment</key>
+ <string>Enable profiler tool if using FMOD Ex</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>FMODExDecodeBufferSize</key>
+ <map>
+ <key>Comment</key>
+ <string>Sets the streaming decode buffer size (in milliseconds)</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>U32</string>
+ <key>Value</key>
+ <integer>1000</integer>
+ </map>
+ <key>FMODExStreamBufferSize</key>
+ <map>
+ <key>Comment</key>
+ <string>Sets the streaming buffer size (in milliseconds)</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>U32</string>
+ <key>Value</key>
+ <integer>7000</integer>
+ </map>
<key>DisablePrecacheDelayAfterTeleporting</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/fmod_hidden_symbols.exp b/indra/newview/fmod_hidden_symbols.exp
deleted file mode 100644
index 1e790255bc..0000000000
--- a/indra/newview/fmod_hidden_symbols.exp
+++ /dev/null
@@ -1,240 +0,0 @@
-_CarbonSndPlayDoubleBuffer
-_ConvertFromIeeeExtended
-__book_maptype1_quantvals
-__book_unquantize
-__float32_pack
-__float32_unpack
-__ilog
-__make_words
-_lpc_clear
-_lpc_init
-__vorbis_block_alloc
-__vorbis_block_ripcord
-__vorbis_apply_window
-__vorbis_window_get
-_vorbis_analysis_blockout
-_vorbis_analysis_buffer
-_vorbis_analysis_wrote
-_vorbis_block_clear
-_vorbis_block_init
-_vorbis_dsp_clear
-_vorbis_synthesis_blockin
-_vorbis_synthesis_init
-_vorbis_synthesis_pcmout
-_vorbis_synthesis_read
-_vorbis_packet_blocksize
-_vorbis_synthesis
-_vorbis_book_clear
-_vorbis_book_decode
-_vorbis_book_decodev_add
-_vorbis_book_decodev_set
-_vorbis_book_decodevs_add
-_vorbis_book_decodevv_add
-_vorbis_book_init_decode
-_vorbis_comment_add
-_vorbis_comment_add_tag
-_vorbis_comment_clear
-_vorbis_comment_init
-_vorbis_comment_query
-_vorbis_comment_query_count
-_vorbis_coslook
-_vorbis_fromdBlook
-_vorbis_info_blocksize
-_vorbis_info_clear
-_vorbis_info_init
-_vorbis_invsq2explook
-_vorbis_invsqlook
-_vorbis_lpc_from_curve
-_vorbis_lpc_from_data
-_vorbis_lpc_predict
-_vorbis_lsp_to_curve
-_vorbis_staticbook_clear
-_vorbis_staticbook_destroy
-_vorbis_staticbook_unpack
-_vorbis_synthesis_headerin
-_vorbis_synthesis_lapout
-_vorbis_synthesis_restart
-_vorbis_synthesis_trackonly
-_vorbis_window
-_ogg_packet_clear
-_ogg_page_bos
-_ogg_page_checksum_set
-_ogg_page_continued
-_ogg_page_eos
-_ogg_page_granulepos
-_ogg_page_packets
-_ogg_page_pageno
-_ogg_page_serialno
-_ogg_page_version
-_ogg_stream_reset_serialno
-_ogg_stream_clear
-_ogg_stream_destroy
-_ogg_stream_eos
-_ogg_stream_flush
-_ogg_stream_init
-_ogg_stream_packetout
-_ogg_stream_packetpeek
-_ogg_stream_pagein
-_ogg_stream_pageout
-_ogg_stream_reset
-_ogg_sync_buffer
-_ogg_sync_clear
-_ogg_sync_destroy
-_ogg_sync_init
-_ogg_sync_pageout
-_ogg_sync_pageseek
-_ogg_sync_reset
-_ogg_sync_wrote
-_ov_bitrate
-_ov_bitrate_instant
-_ov_clear
-_ov_comment
-_ov_info
-_ov_open
-_ov_open_callbacks
-_ov_pcm_seek
-_ov_pcm_seek_page
-_ov_pcm_tell
-_ov_pcm_total
-_ov_raw_seek
-_ov_raw_tell
-_ov_raw_total
-_ov_read
-_ov_read_float
-_ov_seekable
-_ov_serialnumber
-_ov_streams
-_ov_test
-_ov_test_callbacks
-_ov_test_open
-_ov_time_seek
-_ov_time_seek_page
-_ov_time_tell
-_ov_time_total
-_ogg_toupper
-_oggpackB_adv
-_oggpackB_adv1
-_oggpackB_bits
-_oggpackB_bytes
-_oggpackB_get_buffer
-_oggpackB_look
-_oggpackB_look1
-_oggpackB_read
-_oggpackB_read1
-_oggpackB_readinit
-_oggpackB_reset
-_oggpack_adv
-_oggpack_adv1
-_oggpack_bits
-_oggpack_bytes
-_oggpack_get_buffer
-_oggpack_look
-_oggpack_look1
-_oggpack_read
-_oggpack_read1
-_oggpack_readinit
-_oggpack_reset
-_ov_crosslap
-_ov_pcm_seek_lap
-_ov_pcm_seek_page_lap
-_ov_raw_seek_lap
-_ov_time_seek_lap
-_ov_time_seek_page_lap
-_II_step_one
-_II_step_two
-_MyRecComp
-_SampleRates
-_Sinfo
-_ValidStepIndex
-__Z11fmodwrapperv
-__Z11fmodwrapperv.eh
-__floor_P
-__mapping_P
-__residue_P
-__ve_envelope_clear
-__ve_envelope_init
-__ve_envelope_mark
-__ve_envelope_search
-__ve_envelope_shift
-__vi_gpsy_free
-__vi_psy_free
-__vorbis_window_init
-__vp_ampmax_decay
-__vp_couple
-__vp_global_free
-__vp_global_look
-__vp_noise_normalize
-__vp_noise_normalize_sort
-__vp_noisemask
-__vp_offset_and_mix
-__vp_psy_clear
-__vp_psy_init
-__vp_quantize_couple_memo
-__vp_quantize_couple_sort
-__vp_remove_floor
-__vp_tonemask
-_alloc_0
-_alloc_1
-_alloc_2
-_alloc_3
-_alloc_4
-_bandInfo
-_cdcallback
-_cdchannel
-_cdmode
-_cdnumtracks
-_cdstream
-_cdtrack
-_drft_backward
-_drft_clear
-_drft_forward
-_drft_init
-_eatwhite
-_floor0_exportbundle
-_floor1_exportbundle
-_gFreeList
-_gNMRecBusy
-_gNMRecPtr
-_gSilenceOnes
-_gSilenceTwos
-_longLimit
-_mapping0_exportbundle
-_mdct_backward
-_mdct_clear
-_mdct_forward
-_mdct_init
-_muls
-_mystrdup
-_res0_free_info
-_res0_free_look
-_res0_inverse
-_res0_look
-_res0_unpack
-_res1_class
-_res1_inverse
-_res2_inverse
-_residue0_exportbundle
-_residue1_exportbundle
-_residue2_exportbundle
-_scale
-_shortLimit
-_tabsel_123
-_F_Free
-_F_Malloc
-_F_ReAlloc
-_F_memcmp
-_F_memmove
-_F_strcat
-_F_strchr
-_F_strcmp
-_F_strcpy
-_F_stricmp
-_F_strlen
-_F_strncat
-_F_strncmp
-_F_strncpy
-_F_strnicmp
-_F_strstr
-_F_strupr
-_F_tolower
-_F_toupper
diff --git a/indra/newview/fmodwrapper.cpp b/indra/newview/fmodwrapper.cpp
deleted file mode 100644
index 16f1d19a78..0000000000
--- a/indra/newview/fmodwrapper.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-/**
- * @file fmodwrapper.cpp
- * @brief dummy source file for building a shared library to wrap libfmod.a
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-extern "C"
-{
- void FSOUND_Init(void);
-}
-
-void* fmodwrapper(void)
-{
- // When building the fmodwrapper library, the linker doesn't seem to want to bring in libfmod.a unless I explicitly
- // reference at least one symbol in the library. This seemed like the simplest way.
- return (void*)&FSOUND_Init;
-}
diff --git a/indra/newview/linux_tools/wrapper.sh b/indra/newview/linux_tools/wrapper.sh
index 1381e49c62..48b883e999 100755
--- a/indra/newview/linux_tools/wrapper.sh
+++ b/indra/newview/linux_tools/wrapper.sh
@@ -4,17 +4,17 @@
## These options are for self-assisted troubleshooting during this beta
## testing phase; you should not usually need to touch them.
+## - Avoids using any FMOD Ex audio driver.
+#export LL_BAD_FMODEX_DRIVER=x
## - Avoids using any OpenAL audio driver.
#export LL_BAD_OPENAL_DRIVER=x
-## - Avoids using any FMOD audio driver.
-#export LL_BAD_FMOD_DRIVER=x
-## - Avoids using the FMOD ESD audio driver.
-#export LL_BAD_FMOD_ESD=x
-## - Avoids using the FMOD OSS audio driver.
-#export LL_BAD_FMOD_OSS=x
-## - Avoids using the FMOD ALSA audio driver.
+## - Avoids using the FMOD Ex PulseAudio audio driver.
+#export LL_BAD_FMOD_PULSEAUDIO=x
+## - Avoids using the FMOD or FMOD Ex ALSA audio driver.
#export LL_BAD_FMOD_ALSA=x
+## - Avoids using the FMOD or FMOD Ex OSS audio driver.
+#export LL_BAD_FMOD_OSS=x
## - Avoids the optional OpenGL extensions which have proven most problematic
## on some hardware. Disabling this option may cause BETTER PERFORMANCE but
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 3adf956ae3..97962b8705 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -1707,19 +1707,7 @@ bool LLAppViewer::cleanup()
gAudiop->setStreamingAudioImpl(NULL);
// shut down the audio subsystem
-
- bool want_longname = false;
- if (gAudiop->getDriverName(want_longname) == "FMOD")
- {
- // This hack exists because fmod likes to occasionally
- // crash or hang forever when shutting down, for no
- // apparent reason.
- llwarns << "Hack, skipping FMOD audio engine cleanup" << llendflush;
- }
- else
- {
- gAudiop->shutdown();
- }
+ gAudiop->shutdown();
delete gAudiop;
gAudiop = NULL;
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 8b71f1067f..9d5fd46a1d 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -37,8 +37,8 @@
#include "llviewermedia_streamingaudio.h"
#include "llaudioengine.h"
-#ifdef LL_FMOD
-# include "llaudioengine_fmod.h"
+#ifdef LL_FMODEX
+# include "llaudioengine_fmodex.h"
#endif
#ifdef LL_OPENAL
@@ -623,32 +623,32 @@ bool idle_startup()
{
gAudiop = NULL;
-#ifdef LL_OPENAL
+#ifdef LL_FMODEX
if (!gAudiop
#if !LL_WINDOWS
- && NULL == getenv("LL_BAD_OPENAL_DRIVER")
+ && NULL == getenv("LL_BAD_FMODEX_DRIVER")
#endif // !LL_WINDOWS
)
{
- gAudiop = (LLAudioEngine *) new LLAudioEngine_OpenAL();
+ gAudiop = (LLAudioEngine *) new LLAudioEngine_FMODEX(gSavedSettings.getBOOL("FMODExProfilerEnable"));
}
#endif
-#ifdef LL_FMOD
+#ifdef LL_OPENAL
if (!gAudiop
#if !LL_WINDOWS
- && NULL == getenv("LL_BAD_FMOD_DRIVER")
+ && NULL == getenv("LL_BAD_OPENAL_DRIVER")
#endif // !LL_WINDOWS
)
{
- gAudiop = (LLAudioEngine *) new LLAudioEngine_FMOD();
+ gAudiop = (LLAudioEngine *) new LLAudioEngine_OpenAL();
}
#endif
-
+
if (gAudiop)
{
#if LL_WINDOWS
- // FMOD on Windows needs the window handle to stop playing audio
+ // FMOD Ex on Windows needs the window handle to stop playing audio
// when window is minimized. JC
void* window_handle = (HWND)gViewerWindow->getPlatformWindow();
#else
diff --git a/indra/newview/llvieweraudio.cpp b/indra/newview/llvieweraudio.cpp
index 564bf7997a..094694dc06 100644
--- a/indra/newview/llvieweraudio.cpp
+++ b/indra/newview/llvieweraudio.cpp
@@ -44,6 +44,8 @@
#include "llparcel.h"
#include "llviewermessage.h"
+#include "llstreamingaudio.h"
+
/////////////////////////////////////////////////////////
LLViewerAudio::LLViewerAudio() :
@@ -102,6 +104,11 @@ void LLViewerAudio::startInternetStreamWithAutoFade(std::string streamURI)
else
{
mFadeState = FADE_IN;
+
+ LLStreamingAudioInterface *stream = gAudiop->getStreamingAudioImpl();
+ if(stream && stream->supportsAdjustableBufferSizes())
+ stream->setBufferSizes(gSavedSettings.getU32("FMODExStreamBufferSize"),gSavedSettings.getU32("FMODExDecodeBufferSize"));
+
gAudiop->startInternetStream(mNextStreamURI);
startFading();
registerIdleListener();
@@ -157,6 +164,11 @@ bool LLViewerAudio::onIdleUpdate()
if (!mNextStreamURI.empty())
{
mFadeState = FADE_IN;
+
+ LLStreamingAudioInterface *stream = gAudiop->getStreamingAudioImpl();
+ if(stream && stream->supportsAdjustableBufferSizes())
+ stream->setBufferSizes(gSavedSettings.getU32("FMODExStreamBufferSize"),gSavedSettings.getU32("FMODExDecodeBufferSize"));
+
gAudiop->startInternetStream(mNextStreamURI);
startFading();
}
@@ -386,7 +398,12 @@ void audio_update_volume(bool force_update)
gAudiop->setMasterGain ( master_volume );
gAudiop->setDopplerFactor(gSavedSettings.getF32("AudioLevelDoppler"));
- gAudiop->setRolloffFactor(gSavedSettings.getF32("AudioLevelRolloff"));
+
+ if(!LLViewerCamera::getInstance()->cameraUnderWater())
+ gAudiop->setRolloffFactor(gSavedSettings.getF32("AudioLevelRolloff"));
+ else
+ gAudiop->setRolloffFactor(gSavedSettings.getF32("AudioLevelUnderwaterRolloff"));
+
gAudiop->setMuted(mute_audio || progress_view_visible);
//Play any deferred sounds when unmuted
@@ -473,44 +490,22 @@ void audio_update_listener()
void audio_update_wind(bool force_update)
{
#ifdef kAUDIO_ENABLE_WIND
- //
- // Extract height above water to modulate filter by whether above/below water
- //
+
LLViewerRegion* region = gAgent.getRegion();
if (region)
{
- static F32 last_camera_water_height = -1000.f;
- LLVector3 camera_pos = gAgentCamera.getCameraPositionAgent();
- F32 camera_water_height = camera_pos.mV[VZ] - region->getWaterHeight();
-
- //
- // Don't update rolloff factor unless water surface has been crossed
- //
- if (force_update || (last_camera_water_height * camera_water_height) < 0.f)
- {
- static LLUICachedControl<F32> rolloff("AudioLevelRolloff", 1.0f);
- if (camera_water_height < 0.f)
- {
- gAudiop->setRolloffFactor(rolloff * LL_ROLLOFF_MULTIPLIER_UNDER_WATER);
- }
- else
- {
- gAudiop->setRolloffFactor(rolloff);
- }
- }
-
- // Scale down the contribution of weather-simulation wind to the
- // ambient wind noise. Wind velocity averages 3.5 m/s, with gusts to 7 m/s
- // whereas steady-state avatar walk velocity is only 3.2 m/s.
- // Without this the world feels desolate on first login when you are
- // standing still.
- static LLUICachedControl<F32> wind_level("AudioLevelWind", 0.5f);
- LLVector3 scaled_wind_vec = gWindVec * wind_level;
-
- // Mix in the avatar's motion, subtract because when you walk north,
- // the apparent wind moves south.
- LLVector3 final_wind_vec = scaled_wind_vec - gAgent.getVelocity();
-
+ // Scale down the contribution of weather-simulation wind to the
+ // ambient wind noise. Wind velocity averages 3.5 m/s, with gusts to 7 m/s
+ // whereas steady-state avatar walk velocity is only 3.2 m/s.
+ // Without this the world feels desolate on first login when you are
+ // standing still.
+ static LLUICachedControl<F32> wind_level("AudioLevelWind", 0.5f);
+ LLVector3 scaled_wind_vec = gWindVec * wind_level;
+
+ // Mix in the avatar's motion, subtract because when you walk north,
+ // the apparent wind moves south.
+ LLVector3 final_wind_vec = scaled_wind_vec - gAgent.getVelocity();
+
// rotate the wind vector to be listener (agent) relative
gRelativeWindVec = gAgent.getFrameAgent().rotateToLocal( final_wind_vec );
@@ -543,8 +538,7 @@ void audio_update_wind(bool force_update)
gAudiop->mMaxWindGain = llmax(gAudiop->mMaxWindGain - volume_delta, 0.f);
}
- last_camera_water_height = camera_water_height;
- gAudiop->updateWind(gRelativeWindVec, camera_water_height);
+ gAudiop->updateWind(gRelativeWindVec, gAgentCamera.getCameraPositionAgent()[VZ] - gAgent.getRegion()->getWaterHeight());
}
#endif
}
diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp
index 051f5f4485..a62f73deef 100644
--- a/indra/newview/llviewercontrol.cpp
+++ b/indra/newview/llviewercontrol.cpp
@@ -655,6 +655,7 @@ void settings_setup_listeners()
gSavedSettings.getControl("AudioLevelVoice")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2));
gSavedSettings.getControl("AudioLevelDoppler")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2));
gSavedSettings.getControl("AudioLevelRolloff")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2));
+ gSavedSettings.getControl("AudioLevelUnderwaterRolloff")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2));
gSavedSettings.getControl("MuteAudio")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2));
gSavedSettings.getControl("MuteMusic")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2));
gSavedSettings.getControl("MuteMedia")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2));
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index 69248e26bc..e2b914aae8 100644
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -367,10 +367,14 @@ class WindowsManifest(ViewerManifest):
print err.message
print "Skipping COLLADA and GLOD libraries (assumming linked statically)"
-
- # Get fmod dll, continue if missing
- if not self.path("fmod.dll"):
- print "Skipping fmod.dll"
+ # Get fmodex dll, continue if missing
+ try:
+ if self.args['configuration'].lower() == 'debug':
+ self.path("fmodexL.dll")
+ else:
+ self.path("fmodex.dll")
+ except:
+ print "Skipping fmodex audio library(assuming other audio engine)"
# For textures
if self.args['configuration'].lower() == 'debug':
@@ -743,6 +747,7 @@ class DarwinManifest(ViewerManifest):
"libcollada14dom.dylib",
"libexpat.1.5.2.dylib",
"libexception_handler.dylib",
+ "libfmodex.dylib",
"libGLOD.dylib",
):
dylibs += path_optional(os.path.join(libdir, libfile), libfile)
@@ -757,11 +762,7 @@ class DarwinManifest(ViewerManifest):
'SLVoice',
):
self.path2basename(libdir, libfile)
-
- # FMOD for sound
- libfile = "libfmodwrapper.dylib"
- path_optional(os.path.join(self.args['configuration'], libfile), libfile)
-
+
# our apps
for app_bld_dir, app in (("mac_crash_logger", "mac-crash-logger.app"),
("mac_updater", "mac-updater.app"),
@@ -1122,11 +1123,13 @@ class Linux_i686Manifest(LinuxManifest):
pass
try:
- self.path("libfmod-3.75.so")
+ self.path("libfmodex-*.so")
+ self.path("libfmodex.so")
pass
except:
- print "Skipping libfmod-3.75.so - not found"
+ print "Skipping libfmodex.so - not found"
pass
+
self.end_prefix("lib")
# Vivox runtimes