diff options
Diffstat (limited to '')
28 files changed, 1719 insertions, 1227 deletions
diff --git a/linden/indra/llaudio/CMakeLists.txt b/linden/indra/llaudio/CMakeLists.txt index 0a668f9..1a0527c 100644 --- a/linden/indra/llaudio/CMakeLists.txt +++ b/linden/indra/llaudio/CMakeLists.txt | |||
@@ -4,6 +4,7 @@ project(llaudio) | |||
4 | 4 | ||
5 | # Current starting point for CMake. Seems rather arbitrary - MC | 5 | # Current starting point for CMake. Seems rather arbitrary - MC |
6 | include(00-Common) | 6 | include(00-Common) |
7 | include(LLAudio) | ||
7 | include(Audio) | 8 | include(Audio) |
8 | include(OPENAL) | 9 | include(OPENAL) |
9 | include(FMOD) | 10 | include(FMOD) |
@@ -12,9 +13,9 @@ include(LLCommon) | |||
12 | include(LLMath) | 13 | include(LLMath) |
13 | include(LLMessage) | 14 | include(LLMessage) |
14 | include(LLVFS) | 15 | include(LLVFS) |
15 | include(LLMedia) | ||
16 | 16 | ||
17 | include_directories( | 17 | include_directories( |
18 | ${LLAUDIO_INCLUDE_DIRS} | ||
18 | ${FMOD_INCLUDE_DIR} | 19 | ${FMOD_INCLUDE_DIR} |
19 | ${LLCOMMON_INCLUDE_DIRS} | 20 | ${LLCOMMON_INCLUDE_DIRS} |
20 | ${LLMATH_INCLUDE_DIRS} | 21 | ${LLMATH_INCLUDE_DIRS} |
@@ -26,43 +27,43 @@ include_directories( | |||
26 | ${VORBIS_INCLUDE_DIRS} | 27 | ${VORBIS_INCLUDE_DIRS} |
27 | ${OPENAL_LIB_INCLUDE_DIRS} | 28 | ${OPENAL_LIB_INCLUDE_DIRS} |
28 | ${FREEAULT_LIB_INCLUDE_DIRS} | 29 | ${FREEAULT_LIB_INCLUDE_DIRS} |
29 | ${LLMEDIA_INCLUDE_DIRS} | ||
30 | ${GSTREAMER_INCLUDE_DIRS} | ||
31 | ) | 30 | ) |
32 | 31 | ||
33 | set(llaudio_SOURCE_FILES | 32 | set(llaudio_SOURCE_FILES |
34 | audioengine.cpp | 33 | llaudioengine.cpp |
35 | listener.cpp | 34 | lllistener.cpp |
36 | llaudiodecodemgr.cpp | 35 | llaudiodecodemgr.cpp |
37 | vorbisdecode.cpp | 36 | llvorbisdecode.cpp |
38 | vorbisencode.cpp | 37 | llvorbisencode.cpp |
39 | ) | 38 | ) |
40 | 39 | ||
41 | set(llaudio_HEADER_FILES | 40 | set(llaudio_HEADER_FILES |
42 | CMakeLists.txt | 41 | CMakeLists.txt |
43 | 42 | ||
44 | audioengine.h | 43 | llaudioengine.h |
45 | listener.h | 44 | lllistener.h |
46 | llaudiodecodemgr.h | 45 | llaudiodecodemgr.h |
47 | vorbisdecode.h | 46 | llvorbisdecode.h |
48 | vorbisencode.h | 47 | llvorbisencode.h |
49 | windgen.h | 48 | llwindgen.h |
50 | ) | 49 | ) |
51 | 50 | ||
52 | if (FMOD) | 51 | if (FMOD) |
53 | list(APPEND llaudio_SOURCE_FILES | 52 | list(APPEND llaudio_SOURCE_FILES |
54 | audioengine_fmod.cpp | 53 | llaudioengine_fmod.cpp |
55 | listener_fmod.cpp | 54 | lllistener_fmod.cpp |
55 | llstreamingaudio_fmod.cpp | ||
56 | ) | 56 | ) |
57 | 57 | ||
58 | list(APPEND llaudio_HEADER_FILES | 58 | list(APPEND llaudio_HEADER_FILES |
59 | audioengine_fmod.h | 59 | llaudioengine_fmod.h |
60 | listener_fmod.h | 60 | lllistener_fmod.h |
61 | llstreamingaudio_fmod.h | ||
61 | ) | 62 | ) |
62 | 63 | ||
63 | if (LINUX) | 64 | if (LINUX) |
64 | if (${CXX_VERSION} MATCHES "4.[23]") | 65 | if (${CXX_VERSION} MATCHES "4.[23]") |
65 | set_source_files_properties(audioengine_fmod.cpp | 66 | set_source_files_properties(llaudioengine_fmod.cpp |
66 | COMPILE_FLAGS -Wno-error=write-strings) | 67 | COMPILE_FLAGS -Wno-error=write-strings) |
67 | endif (${CXX_VERSION} MATCHES "4.[23]") | 68 | endif (${CXX_VERSION} MATCHES "4.[23]") |
68 | endif (LINUX) | 69 | endif (LINUX) |
@@ -70,13 +71,13 @@ endif (FMOD) | |||
70 | 71 | ||
71 | if (OPENAL) | 72 | if (OPENAL) |
72 | list(APPEND llaudio_SOURCE_FILES | 73 | list(APPEND llaudio_SOURCE_FILES |
73 | audioengine_openal.cpp | 74 | llaudioengine_openal.cpp |
74 | listener_openal.cpp | 75 | lllistener_openal.cpp |
75 | ) | 76 | ) |
76 | 77 | ||
77 | list(APPEND llaudio_HEADER_FILES | 78 | list(APPEND llaudio_HEADER_FILES |
78 | audioengine_openal.h | 79 | llaudioengine_openal.h |
79 | listener_openal.h | 80 | lllistener_openal.h |
80 | ) | 81 | ) |
81 | endif (OPENAL) | 82 | endif (OPENAL) |
82 | 83 | ||
diff --git a/linden/indra/llaudio/listener.cpp b/linden/indra/llaudio/listener.cpp index e2dc30e..e69de29 100644 --- a/linden/indra/llaudio/listener.cpp +++ b/linden/indra/llaudio/listener.cpp | |||
@@ -1,153 +0,0 @@ | |||
1 | /** | ||
2 | * @file listener.cpp | ||
3 | * @brief Implementation of LISTENER class abstracting the audio support | ||
4 | * | ||
5 | * $LicenseInfo:firstyear=2000&license=viewergpl$ | ||
6 | * | ||
7 | * Copyright (c) 2000-2009, Linden Research, Inc. | ||
8 | * | ||
9 | * Second Life Viewer Source Code | ||
10 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
11 | * to you under the terms of the GNU General Public License, version 2.0 | ||
12 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
13 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
14 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
15 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
16 | * | ||
17 | * There are special exceptions to the terms and conditions of the GPL as | ||
18 | * it is applied to this Source Code. View the full text of the exception | ||
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
20 | * online at | ||
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
22 | * | ||
23 | * By copying, modifying or distributing this software, you acknowledge | ||
24 | * that you have read and understood your obligations described above, | ||
25 | * and agree to abide by those obligations. | ||
26 | * | ||
27 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
28 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
29 | * COMPLETENESS OR PERFORMANCE. | ||
30 | * $/LicenseInfo$ | ||
31 | */ | ||
32 | |||
33 | #include "linden_common.h" | ||
34 | |||
35 | #include "listener.h" | ||
36 | |||
37 | #define DEFAULT_AT 0.0f,0.0f,-1.0f | ||
38 | #define DEFAULT_UP 0.0f,1.0f,0.0f | ||
39 | |||
40 | //----------------------------------------------------------------------- | ||
41 | // constructor | ||
42 | //----------------------------------------------------------------------- | ||
43 | LLListener::LLListener() | ||
44 | { | ||
45 | init(); | ||
46 | } | ||
47 | |||
48 | //----------------------------------------------------------------------- | ||
49 | LLListener::~LLListener() | ||
50 | { | ||
51 | } | ||
52 | |||
53 | //----------------------------------------------------------------------- | ||
54 | void LLListener::init(void) | ||
55 | { | ||
56 | mPosition.zeroVec(); | ||
57 | mListenAt.setVec(DEFAULT_AT); | ||
58 | mListenUp.setVec(DEFAULT_UP); | ||
59 | mVelocity.zeroVec(); | ||
60 | } | ||
61 | |||
62 | //----------------------------------------------------------------------- | ||
63 | void LLListener::translate(LLVector3 offset) | ||
64 | { | ||
65 | mPosition += offset; | ||
66 | } | ||
67 | |||
68 | //----------------------------------------------------------------------- | ||
69 | void LLListener::setPosition(LLVector3 pos) | ||
70 | { | ||
71 | mPosition = pos; | ||
72 | } | ||
73 | |||
74 | //----------------------------------------------------------------------- | ||
75 | LLVector3 LLListener::getPosition(void) | ||
76 | { | ||
77 | return(mPosition); | ||
78 | } | ||
79 | |||
80 | //----------------------------------------------------------------------- | ||
81 | LLVector3 LLListener::getAt(void) | ||
82 | { | ||
83 | return(mListenAt); | ||
84 | } | ||
85 | |||
86 | //----------------------------------------------------------------------- | ||
87 | LLVector3 LLListener::getUp(void) | ||
88 | { | ||
89 | return(mListenUp); | ||
90 | } | ||
91 | |||
92 | //----------------------------------------------------------------------- | ||
93 | void LLListener::setVelocity(LLVector3 vel) | ||
94 | { | ||
95 | mVelocity = vel; | ||
96 | } | ||
97 | |||
98 | //----------------------------------------------------------------------- | ||
99 | void LLListener::orient(LLVector3 up, LLVector3 at) | ||
100 | { | ||
101 | mListenUp = up; | ||
102 | mListenAt = at; | ||
103 | } | ||
104 | |||
105 | //----------------------------------------------------------------------- | ||
106 | void LLListener::set(LLVector3 pos, LLVector3 vel, LLVector3 up, LLVector3 at) | ||
107 | { | ||
108 | mPosition = pos; | ||
109 | mVelocity = vel; | ||
110 | |||
111 | setPosition(pos); | ||
112 | setVelocity(vel); | ||
113 | orient(up,at); | ||
114 | } | ||
115 | |||
116 | //----------------------------------------------------------------------- | ||
117 | void LLListener::setDopplerFactor(F32 factor) | ||
118 | { | ||
119 | } | ||
120 | |||
121 | //----------------------------------------------------------------------- | ||
122 | F32 LLListener::getDopplerFactor() | ||
123 | { | ||
124 | return (1.f); | ||
125 | } | ||
126 | |||
127 | //----------------------------------------------------------------------- | ||
128 | void LLListener::setDistanceFactor(F32 factor) | ||
129 | { | ||
130 | } | ||
131 | |||
132 | //----------------------------------------------------------------------- | ||
133 | F32 LLListener::getDistanceFactor() | ||
134 | { | ||
135 | return (1.f); | ||
136 | } | ||
137 | |||
138 | //----------------------------------------------------------------------- | ||
139 | void LLListener::setRolloffFactor(F32 factor) | ||
140 | { | ||
141 | } | ||
142 | |||
143 | //----------------------------------------------------------------------- | ||
144 | F32 LLListener::getRolloffFactor() | ||
145 | { | ||
146 | return (1.f); | ||
147 | } | ||
148 | |||
149 | //----------------------------------------------------------------------- | ||
150 | void LLListener::commitDeferredChanges() | ||
151 | { | ||
152 | } | ||
153 | |||
diff --git a/linden/indra/llaudio/listener.h b/linden/indra/llaudio/listener.h index 4137304..e69de29 100644 --- a/linden/indra/llaudio/listener.h +++ b/linden/indra/llaudio/listener.h | |||
@@ -1,80 +0,0 @@ | |||
1 | /** | ||
2 | * @file listener.h | ||
3 | * @brief Description of LISTENER base class abstracting the audio support. | ||
4 | * | ||
5 | * $LicenseInfo:firstyear=2000&license=viewergpl$ | ||
6 | * | ||
7 | * Copyright (c) 2000-2009, Linden Research, Inc. | ||
8 | * | ||
9 | * Second Life Viewer Source Code | ||
10 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
11 | * to you under the terms of the GNU General Public License, version 2.0 | ||
12 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
13 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
14 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
15 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
16 | * | ||
17 | * There are special exceptions to the terms and conditions of the GPL as | ||
18 | * it is applied to this Source Code. View the full text of the exception | ||
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
20 | * online at | ||
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
22 | * | ||
23 | * By copying, modifying or distributing this software, you acknowledge | ||
24 | * that you have read and understood your obligations described above, | ||
25 | * and agree to abide by those obligations. | ||
26 | * | ||
27 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
28 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
29 | * COMPLETENESS OR PERFORMANCE. | ||
30 | * $/LicenseInfo$ | ||
31 | */ | ||
32 | |||
33 | #ifndef LL_LISTENER_H | ||
34 | #define LL_LISTENER_H | ||
35 | |||
36 | #include "v3math.h" | ||
37 | |||
38 | class LLListener | ||
39 | { | ||
40 | private: | ||
41 | protected: | ||
42 | LLVector3 mPosition; | ||
43 | LLVector3 mVelocity; | ||
44 | LLVector3 mListenAt; | ||
45 | LLVector3 mListenUp; | ||
46 | |||
47 | public: | ||
48 | |||
49 | private: | ||
50 | protected: | ||
51 | public: | ||
52 | LLListener(); | ||
53 | virtual ~LLListener(); | ||
54 | virtual void init(); | ||
55 | |||
56 | virtual void set(LLVector3 pos, LLVector3 vel, LLVector3 up, LLVector3 at); | ||
57 | |||
58 | virtual void setPosition(LLVector3 pos); | ||
59 | virtual void setVelocity(LLVector3 vel); | ||
60 | |||
61 | virtual void orient(LLVector3 up, LLVector3 at); | ||
62 | virtual void translate(LLVector3 offset); | ||
63 | |||
64 | virtual void setDopplerFactor(F32 factor); | ||
65 | virtual void setDistanceFactor(F32 factor); | ||
66 | virtual void setRolloffFactor(F32 factor); | ||
67 | |||
68 | virtual LLVector3 getPosition(); | ||
69 | virtual LLVector3 getAt(); | ||
70 | virtual LLVector3 getUp(); | ||
71 | |||
72 | virtual F32 getDopplerFactor(); | ||
73 | virtual F32 getDistanceFactor(); | ||
74 | virtual F32 getRolloffFactor(); | ||
75 | |||
76 | virtual void commitDeferredChanges(); | ||
77 | }; | ||
78 | |||
79 | #endif | ||
80 | |||
diff --git a/linden/indra/llaudio/listener_ds3d.h b/linden/indra/llaudio/listener_ds3d.h index 3121e12..e69de29 100644 --- a/linden/indra/llaudio/listener_ds3d.h +++ b/linden/indra/llaudio/listener_ds3d.h | |||
@@ -1,76 +0,0 @@ | |||
1 | /** | ||
2 | * @file listener_ds3d.h | ||
3 | * @brief Description of LISTENER class abstracting the audio support | ||
4 | * as a DirectSound 3D implementation (windows only) | ||
5 | * | ||
6 | * $LicenseInfo:firstyear=2000&license=viewergpl$ | ||
7 | * | ||
8 | * Copyright (c) 2000-2009, Linden Research, Inc. | ||
9 | * | ||
10 | * Second Life Viewer Source Code | ||
11 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
12 | * to you under the terms of the GNU General Public License, version 2.0 | ||
13 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
14 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
15 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
16 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
17 | * | ||
18 | * There are special exceptions to the terms and conditions of the GPL as | ||
19 | * it is applied to this Source Code. View the full text of the exception | ||
20 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
21 | * online at | ||
22 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
23 | * | ||
24 | * By copying, modifying or distributing this software, you acknowledge | ||
25 | * that you have read and understood your obligations described above, | ||
26 | * and agree to abide by those obligations. | ||
27 | * | ||
28 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
29 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
30 | * COMPLETENESS OR PERFORMANCE. | ||
31 | * $/LicenseInfo$ | ||
32 | */ | ||
33 | |||
34 | #ifndef LL_LISTENER_DS3D_H | ||
35 | #define LL_LISTENER_DS3D_H | ||
36 | |||
37 | #include "listener.h" | ||
38 | |||
39 | #include <dmusici.h> | ||
40 | #include <dsound.h> | ||
41 | #include <ks.h> | ||
42 | |||
43 | class LLListener_DS3D : public LLListener | ||
44 | { | ||
45 | private: | ||
46 | protected: | ||
47 | IDirectSound3DListener8 *m3DListener; | ||
48 | public: | ||
49 | |||
50 | private: | ||
51 | protected: | ||
52 | public: | ||
53 | LLListener_DS3D(); | ||
54 | virtual ~LLListener_DS3D(); | ||
55 | virtual void init(); | ||
56 | |||
57 | virtual void setDS3DLPtr (IDirectSound3DListener8 *listener_p); | ||
58 | |||
59 | virtual void translate(LLVector3 offset); | ||
60 | virtual void setPosition(LLVector3 pos); | ||
61 | virtual void setVelocity(LLVector3 vel); | ||
62 | virtual void orient(LLVector3 up, LLVector3 at); | ||
63 | |||
64 | virtual void setDopplerFactor(F32 factor); | ||
65 | virtual F32 getDopplerFactor(); | ||
66 | virtual void setDistanceFactor(F32 factor); | ||
67 | virtual F32 getDistanceFactor(); | ||
68 | virtual void setRolloffFactor(F32 factor); | ||
69 | virtual F32 getRolloffFactor(); | ||
70 | |||
71 | virtual void commitDeferredChanges(); | ||
72 | }; | ||
73 | |||
74 | #endif | ||
75 | |||
76 | |||
diff --git a/linden/indra/llaudio/listener_fmod.cpp b/linden/indra/llaudio/listener_fmod.cpp index 4bbb3d9..e69de29 100644 --- a/linden/indra/llaudio/listener_fmod.cpp +++ b/linden/indra/llaudio/listener_fmod.cpp | |||
@@ -1,143 +0,0 @@ | |||
1 | /** | ||
2 | * @file listener_fmod.cpp | ||
3 | * @brief implementation of LISTENER class abstracting the audio | ||
4 | * support as a FMOD 3D implementation (windows only) | ||
5 | * | ||
6 | * $LicenseInfo:firstyear=2002&license=viewergpl$ | ||
7 | * | ||
8 | * Copyright (c) 2002-2009, Linden Research, Inc. | ||
9 | * | ||
10 | * Second Life Viewer Source Code | ||
11 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
12 | * to you under the terms of the GNU General Public License, version 2.0 | ||
13 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
14 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
15 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
16 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
17 | * | ||
18 | * There are special exceptions to the terms and conditions of the GPL as | ||
19 | * it is applied to this Source Code. View the full text of the exception | ||
20 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
21 | * online at | ||
22 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
23 | * | ||
24 | * By copying, modifying or distributing this software, you acknowledge | ||
25 | * that you have read and understood your obligations described above, | ||
26 | * and agree to abide by those obligations. | ||
27 | * | ||
28 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
29 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
30 | * COMPLETENESS OR PERFORMANCE. | ||
31 | * $/LicenseInfo$ | ||
32 | */ | ||
33 | |||
34 | #include "linden_common.h" | ||
35 | #include "audioengine.h" | ||
36 | #include "listener_fmod.h" | ||
37 | #include "fmod.h" | ||
38 | |||
39 | //----------------------------------------------------------------------- | ||
40 | // constructor | ||
41 | //----------------------------------------------------------------------- | ||
42 | LLListener_FMOD::LLListener_FMOD() | ||
43 | { | ||
44 | init(); | ||
45 | } | ||
46 | |||
47 | //----------------------------------------------------------------------- | ||
48 | LLListener_FMOD::~LLListener_FMOD() | ||
49 | { | ||
50 | } | ||
51 | |||
52 | //----------------------------------------------------------------------- | ||
53 | void LLListener_FMOD::init(void) | ||
54 | { | ||
55 | // do inherited | ||
56 | LLListener::init(); | ||
57 | mDopplerFactor = 1.0f; | ||
58 | mDistanceFactor = 1.0f; | ||
59 | mRolloffFactor = 1.0f; | ||
60 | } | ||
61 | |||
62 | //----------------------------------------------------------------------- | ||
63 | void LLListener_FMOD::translate(LLVector3 offset) | ||
64 | { | ||
65 | LLListener::translate(offset); | ||
66 | |||
67 | 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]); | ||
68 | } | ||
69 | |||
70 | //----------------------------------------------------------------------- | ||
71 | void LLListener_FMOD::setPosition(LLVector3 pos) | ||
72 | { | ||
73 | LLListener::setPosition(pos); | ||
74 | |||
75 | 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]); | ||
76 | } | ||
77 | |||
78 | //----------------------------------------------------------------------- | ||
79 | void LLListener_FMOD::setVelocity(LLVector3 vel) | ||
80 | { | ||
81 | LLListener::setVelocity(vel); | ||
82 | |||
83 | 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]); | ||
84 | } | ||
85 | |||
86 | //----------------------------------------------------------------------- | ||
87 | void LLListener_FMOD::orient(LLVector3 up, LLVector3 at) | ||
88 | { | ||
89 | LLListener::orient(up, at); | ||
90 | |||
91 | // Welcome to the transition between right and left | ||
92 | // (coordinate systems, that is) | ||
93 | // Leaving the at vector alone results in a L/R reversal | ||
94 | // since DX is left-handed and we (LL, OpenGL, OpenAL) are right-handed | ||
95 | at = -at; | ||
96 | |||
97 | FSOUND_3D_Listener_SetAttributes(NULL, NULL, at.mV[0],at.mV[1],at.mV[2], up.mV[0],up.mV[1],up.mV[2]); | ||
98 | } | ||
99 | |||
100 | //----------------------------------------------------------------------- | ||
101 | void LLListener_FMOD::commitDeferredChanges() | ||
102 | { | ||
103 | FSOUND_Update(); | ||
104 | } | ||
105 | |||
106 | |||
107 | void LLListener_FMOD::setRolloffFactor(F32 factor) | ||
108 | { | ||
109 | mRolloffFactor = factor; | ||
110 | FSOUND_3D_SetRolloffFactor(factor); | ||
111 | } | ||
112 | |||
113 | |||
114 | F32 LLListener_FMOD::getRolloffFactor() | ||
115 | { | ||
116 | return mRolloffFactor; | ||
117 | } | ||
118 | |||
119 | |||
120 | void LLListener_FMOD::setDopplerFactor(F32 factor) | ||
121 | { | ||
122 | mDopplerFactor = factor; | ||
123 | FSOUND_3D_SetDopplerFactor(factor); | ||
124 | } | ||
125 | |||
126 | |||
127 | F32 LLListener_FMOD::getDopplerFactor() | ||
128 | { | ||
129 | return mDopplerFactor; | ||
130 | } | ||
131 | |||
132 | |||
133 | void LLListener_FMOD::setDistanceFactor(F32 factor) | ||
134 | { | ||
135 | mDistanceFactor = factor; | ||
136 | FSOUND_3D_SetDistanceFactor(factor); | ||
137 | } | ||
138 | |||
139 | |||
140 | F32 LLListener_FMOD::getDistanceFactor() | ||
141 | { | ||
142 | return mDistanceFactor; | ||
143 | } | ||
diff --git a/linden/indra/llaudio/listener_fmod.h b/linden/indra/llaudio/listener_fmod.h index 5f372ab..e69de29 100644 --- a/linden/indra/llaudio/listener_fmod.h +++ b/linden/indra/llaudio/listener_fmod.h | |||
@@ -1,67 +0,0 @@ | |||
1 | /** | ||
2 | * @file listener_fmod.h | ||
3 | * @brief Description of LISTENER class abstracting the audio support | ||
4 | * as an FMOD 3D implementation (windows and Linux) | ||
5 | * | ||
6 | * $LicenseInfo:firstyear=2002&license=viewergpl$ | ||
7 | * | ||
8 | * Copyright (c) 2002-2009, Linden Research, Inc. | ||
9 | * | ||
10 | * Second Life Viewer Source Code | ||
11 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
12 | * to you under the terms of the GNU General Public License, version 2.0 | ||
13 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
14 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
15 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
16 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
17 | * | ||
18 | * There are special exceptions to the terms and conditions of the GPL as | ||
19 | * it is applied to this Source Code. View the full text of the exception | ||
20 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
21 | * online at | ||
22 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
23 | * | ||
24 | * By copying, modifying or distributing this software, you acknowledge | ||
25 | * that you have read and understood your obligations described above, | ||
26 | * and agree to abide by those obligations. | ||
27 | * | ||
28 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
29 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
30 | * COMPLETENESS OR PERFORMANCE. | ||
31 | * $/LicenseInfo$ | ||
32 | */ | ||
33 | |||
34 | #ifndef LL_LISTENER_FMOD_H | ||
35 | #define LL_LISTENER_FMOD_H | ||
36 | |||
37 | #include "listener.h" | ||
38 | |||
39 | class LLListener_FMOD : public LLListener | ||
40 | { | ||
41 | public: | ||
42 | LLListener_FMOD(); | ||
43 | virtual ~LLListener_FMOD(); | ||
44 | virtual void init(); | ||
45 | |||
46 | virtual void translate(LLVector3 offset); | ||
47 | virtual void setPosition(LLVector3 pos); | ||
48 | virtual void setVelocity(LLVector3 vel); | ||
49 | virtual void orient(LLVector3 up, LLVector3 at); | ||
50 | virtual void commitDeferredChanges(); | ||
51 | |||
52 | virtual void setDopplerFactor(F32 factor); | ||
53 | virtual F32 getDopplerFactor(); | ||
54 | virtual void setDistanceFactor(F32 factor); | ||
55 | virtual F32 getDistanceFactor(); | ||
56 | virtual void setRolloffFactor(F32 factor); | ||
57 | virtual F32 getRolloffFactor(); | ||
58 | |||
59 | protected: | ||
60 | F32 mDopplerFactor; | ||
61 | F32 mDistanceFactor; | ||
62 | F32 mRolloffFactor; | ||
63 | }; | ||
64 | |||
65 | #endif | ||
66 | |||
67 | |||
diff --git a/linden/indra/llaudio/llaudiodecodemgr.cpp b/linden/indra/llaudio/llaudiodecodemgr.cpp index afb3c33..a14d4ec 100644 --- a/linden/indra/llaudio/llaudiodecodemgr.cpp +++ b/linden/indra/llaudio/llaudiodecodemgr.cpp | |||
@@ -33,18 +33,18 @@ | |||
33 | 33 | ||
34 | #include "llaudiodecodemgr.h" | 34 | #include "llaudiodecodemgr.h" |
35 | 35 | ||
36 | #include "vorbisdecode.h" | 36 | #include "llvorbisdecode.h" |
37 | #include "audioengine.h" | 37 | #include "llaudioengine.h" |
38 | #include "lllfsthread.h" | 38 | #include "lllfsthread.h" |
39 | #include "llvfile.h" | 39 | #include "llvfile.h" |
40 | #include "llstring.h" | 40 | #include "llstring.h" |
41 | #include "lldir.h" | 41 | #include "lldir.h" |
42 | #include "llendianswizzle.h" | 42 | #include "llendianswizzle.h" |
43 | #include "audioengine.h" | ||
44 | #include "llassetstorage.h" | 43 | #include "llassetstorage.h" |
45 | 44 | ||
46 | #include "vorbis/codec.h" | 45 | #include "vorbis/codec.h" |
47 | #include "vorbis/vorbisfile.h" | 46 | #include "vorbis/vorbisfile.h" |
47 | #include "llvorbisencode.h" | ||
48 | 48 | ||
49 | extern LLAudioEngine *gAudiop; | 49 | extern LLAudioEngine *gAudiop; |
50 | 50 | ||
@@ -218,11 +218,42 @@ BOOL LLVorbisDecodeState::initDecode() | |||
218 | return(FALSE); | 218 | return(FALSE); |
219 | } | 219 | } |
220 | 220 | ||
221 | size_t size_guess = (size_t)ov_pcm_total(&mVF, -1); | 221 | S32 sample_count = ov_pcm_total(&mVF, -1); |
222 | size_t size_guess = (size_t)sample_count; | ||
222 | vorbis_info* vi = ov_info(&mVF, -1); | 223 | vorbis_info* vi = ov_info(&mVF, -1); |
223 | size_guess *= vi->channels; | 224 | size_guess *= vi->channels; |
224 | size_guess *= 2; | 225 | size_guess *= 2; |
225 | size_guess += 2048; | 226 | size_guess += 2048; |
227 | |||
228 | bool abort_decode = false; | ||
229 | |||
230 | if( vi->channels < 1 || vi->channels > LLVORBIS_CLIP_MAX_CHANNELS ) | ||
231 | { | ||
232 | abort_decode = true; | ||
233 | llwarns << "Bad channel count: " << vi->channels << llendl; | ||
234 | } | ||
235 | |||
236 | if( (size_t)sample_count > LLVORBIS_CLIP_REJECT_SAMPLES ) | ||
237 | { | ||
238 | abort_decode = true; | ||
239 | llwarns << "Illegal sample count: " << sample_count << llendl; | ||
240 | } | ||
241 | |||
242 | if( size_guess > LLVORBIS_CLIP_REJECT_SIZE ) | ||
243 | { | ||
244 | abort_decode = true; | ||
245 | llwarns << "Illegal sample size: " << size_guess << llendl; | ||
246 | } | ||
247 | |||
248 | if( abort_decode ) | ||
249 | { | ||
250 | llwarns << "Canceling initDecode. Bad asset: " << mUUID << llendl; | ||
251 | llwarns << "Bad asset encoded by: " << ov_comment(&mVF,-1)->vendor << llendl; | ||
252 | delete mInFilep; | ||
253 | mInFilep = NULL; | ||
254 | return FALSE; | ||
255 | } | ||
256 | |||
226 | mWAVBuffer.reserve(size_guess); | 257 | mWAVBuffer.reserve(size_guess); |
227 | mWAVBuffer.resize(WAV_HEADER_SIZE); | 258 | mWAVBuffer.resize(WAV_HEADER_SIZE); |
228 | 259 | ||
@@ -375,16 +406,16 @@ BOOL LLVorbisDecodeState::finishDecode() | |||
375 | 406 | ||
376 | // write "data" chunk length, in little-endian format | 407 | // write "data" chunk length, in little-endian format |
377 | S32 data_length = mWAVBuffer.size() - WAV_HEADER_SIZE; | 408 | S32 data_length = mWAVBuffer.size() - WAV_HEADER_SIZE; |
378 | mWAVBuffer[40] = (data_length - 8) & 0x000000FF; | 409 | mWAVBuffer[40] = (data_length) & 0x000000FF; |
379 | mWAVBuffer[41] = ((data_length - 8)>> 8) & 0x000000FF; | 410 | mWAVBuffer[41] = (data_length >> 8) & 0x000000FF; |
380 | mWAVBuffer[42] = ((data_length - 8)>> 16) & 0x000000FF; | 411 | mWAVBuffer[42] = (data_length >> 16) & 0x000000FF; |
381 | mWAVBuffer[43] = ((data_length - 8)>> 24) & 0x000000FF; | 412 | mWAVBuffer[43] = (data_length >> 24) & 0x000000FF; |
382 | |||
383 | // write overall "RIFF" length, in little-endian format | 413 | // write overall "RIFF" length, in little-endian format |
384 | mWAVBuffer[4] = (data_length + 28) & 0x000000FF; | 414 | data_length += 36; |
385 | mWAVBuffer[5] = ((data_length + 28) >> 8) & 0x000000FF; | 415 | mWAVBuffer[4] = (data_length) & 0x000000FF; |
386 | mWAVBuffer[6] = ((data_length + 28) >> 16) & 0x000000FF; | 416 | mWAVBuffer[5] = (data_length >> 8) & 0x000000FF; |
387 | mWAVBuffer[7] = ((data_length + 28) >> 24) & 0x000000FF; | 417 | mWAVBuffer[6] = (data_length >> 16) & 0x000000FF; |
418 | mWAVBuffer[7] = (data_length >> 24) & 0x000000FF; | ||
388 | 419 | ||
389 | // | 420 | // |
390 | // FUDGECAKES!!! Vorbis encode/decode messes up loop point transitions (pop) | 421 | // FUDGECAKES!!! Vorbis encode/decode messes up loop point transitions (pop) |
@@ -396,8 +427,7 @@ BOOL LLVorbisDecodeState::finishDecode() | |||
396 | S32 fade_length; | 427 | S32 fade_length; |
397 | char pcmout[4096]; /*Flawfinder: ignore*/ | 428 | char pcmout[4096]; /*Flawfinder: ignore*/ |
398 | 429 | ||
399 | fade_length = llmin((S32)128,(S32)(data_length)/8); | 430 | fade_length = llmin((S32)128,(S32)(data_length-36)/8); |
400 | |||
401 | if((S32)mWAVBuffer.size() >= (WAV_HEADER_SIZE + 2* fade_length)) | 431 | if((S32)mWAVBuffer.size() >= (WAV_HEADER_SIZE + 2* fade_length)) |
402 | { | 432 | { |
403 | memcpy(pcmout, &mWAVBuffer[WAV_HEADER_SIZE], (2 * fade_length)); /*Flawfinder: ignore*/ | 433 | memcpy(pcmout, &mWAVBuffer[WAV_HEADER_SIZE], (2 * fade_length)); /*Flawfinder: ignore*/ |
@@ -437,7 +467,7 @@ BOOL LLVorbisDecodeState::finishDecode() | |||
437 | } | 467 | } |
438 | } | 468 | } |
439 | 469 | ||
440 | if (0 == data_length) | 470 | if (36 == data_length) |
441 | { | 471 | { |
442 | llwarns << "BAD Vorbis decode in finishDecode!" << llendl; | 472 | llwarns << "BAD Vorbis decode in finishDecode!" << llendl; |
443 | mValid = FALSE; | 473 | mValid = FALSE; |
diff --git a/linden/indra/llaudio/audioengine.cpp b/linden/indra/llaudio/llaudioengine.cpp index 1900c38..bed791a 100644 --- a/linden/indra/llaudio/audioengine.cpp +++ b/linden/indra/llaudio/llaudioengine.cpp | |||
@@ -35,7 +35,8 @@ | |||
35 | 35 | ||
36 | #include "linden_common.h" | 36 | #include "linden_common.h" |
37 | 37 | ||
38 | #include "audioengine.h" | 38 | #include "llaudioengine.h" |
39 | #include "llstreamingaudio.h" | ||
39 | 40 | ||
40 | #include "llerror.h" | 41 | #include "llerror.h" |
41 | #include "llmath.h" | 42 | #include "llmath.h" |
@@ -47,9 +48,6 @@ | |||
47 | #include "llaudiodecodemgr.h" | 48 | #include "llaudiodecodemgr.h" |
48 | #include "llassetstorage.h" | 49 | #include "llassetstorage.h" |
49 | 50 | ||
50 | #include "llmediamanager.h" | ||
51 | #include "llmediabase.h" | ||
52 | #include "llmediaimplcommon.h" | ||
53 | 51 | ||
54 | // necessary for grabbing sounds from sim (implemented in viewer) | 52 | // necessary for grabbing sounds from sim (implemented in viewer) |
55 | extern void request_sound(const LLUUID &sound_guid); | 53 | extern void request_sound(const LLUUID &sound_guid); |
@@ -72,6 +70,15 @@ LLAudioEngine::~LLAudioEngine() | |||
72 | { | 70 | { |
73 | } | 71 | } |
74 | 72 | ||
73 | LLStreamingAudioInterface* LLAudioEngine::getStreamingAudioImpl() | ||
74 | { | ||
75 | return mStreamingAudioImpl; | ||
76 | } | ||
77 | |||
78 | void LLAudioEngine::setStreamingAudioImpl(LLStreamingAudioInterface *impl) | ||
79 | { | ||
80 | mStreamingAudioImpl = impl; | ||
81 | } | ||
75 | 82 | ||
76 | void LLAudioEngine::setDefaults() | 83 | void LLAudioEngine::setDefaults() |
77 | { | 84 | { |
@@ -98,13 +105,10 @@ void LLAudioEngine::setDefaults() | |||
98 | } | 105 | } |
99 | 106 | ||
100 | mMasterGain = 1.f; | 107 | mMasterGain = 1.f; |
101 | mInternetStreamGain = 0.125f; | 108 | mInternalGain = 0.f; |
102 | mNextWindUpdate = 0.f; | 109 | mNextWindUpdate = 0.f; |
103 | 110 | ||
104 | mInternetStreamMedia = NULL; | 111 | mStreamingAudioImpl = NULL; |
105 | mInternetStreamURL.clear(); | ||
106 | |||
107 | mStatus = LLMediaBase::STATUS_UNKNOWN; | ||
108 | 112 | ||
109 | for (U32 i = 0; i < LLAudioEngine::AUDIO_TYPE_COUNT; i++) | 113 | for (U32 i = 0; i < LLAudioEngine::AUDIO_TYPE_COUNT; i++) |
110 | mSecondaryGain[i] = 1.0f; | 114 | mSecondaryGain[i] = 1.0f; |
@@ -168,163 +172,61 @@ void LLAudioEngine::shutdown() | |||
168 | delete mBuffers[i]; | 172 | delete mBuffers[i]; |
169 | mBuffers[i] = NULL; | 173 | mBuffers[i] = NULL; |
170 | } | 174 | } |
171 | |||
172 | delete mInternetStreamMedia; | ||
173 | mInternetStreamMedia = NULL; | ||
174 | mInternetStreamURL.clear(); | ||
175 | } | ||
176 | |||
177 | |||
178 | //////////////////////////////////////////////////////////////////////////////// | ||
179 | // virtual (derives from LLMediaBase) | ||
180 | LLMediaBase::EStatus LLAudioEngine::getStatus() | ||
181 | { | ||
182 | return mStatus; | ||
183 | } | 175 | } |
184 | 176 | ||
185 | 177 | ||
186 | // virtual | 178 | // virtual |
187 | void LLAudioEngine::startInternetStream(const std::string& url) | 179 | void LLAudioEngine::startInternetStream(const std::string& url) |
188 | { | 180 | { |
189 | llinfos << "entered startInternetStream()" << llendl; | 181 | if (mStreamingAudioImpl) |
190 | 182 | mStreamingAudioImpl->start(url); | |
191 | if (!mInternetStreamMedia) | ||
192 | { | ||
193 | LLMediaManager* mgr = LLMediaManager::getInstance(); | ||
194 | if (mgr) | ||
195 | { | ||
196 | mInternetStreamMedia = mgr->createSourceFromMimeType(LLURI(url).scheme(), "audio/mpeg"); // assumes that whatever media implementation supports mp3 also supports vorbis. | ||
197 | llinfos << "mInternetStreamMedia is now " << mInternetStreamMedia << llendl; | ||
198 | } | ||
199 | } | ||
200 | |||
201 | if(!mInternetStreamMedia) | ||
202 | { | ||
203 | return; | ||
204 | } | ||
205 | // Check for a dead stream from gstreamer, just in case | ||
206 | else if(getStatus() == LLMediaBase::STATUS_DEAD) | ||
207 | { | ||
208 | llinfos << "don't play dead stream urls"<< llendl; | ||
209 | mInternetStreamURL.clear(); | ||
210 | mInternetStreamMedia->addCommand(LLMediaBase::COMMAND_STOP); | ||
211 | mInternetStreamMedia->updateMedia(); | ||
212 | stopInternetStream(); | ||
213 | } | ||
214 | else if (url.empty()) | ||
215 | { | ||
216 | llinfos << "url is emptly. Setting stream to NULL"<< llendl; | ||
217 | mInternetStreamURL.clear(); | ||
218 | mInternetStreamMedia->addCommand(LLMediaBase::COMMAND_STOP); | ||
219 | mInternetStreamMedia->updateMedia(); | ||
220 | } | ||
221 | // Stream appears to be good, attempting to play | ||
222 | else | ||
223 | { | ||
224 | // stop any other stream first | ||
225 | stopInternetStream(); | ||
226 | |||
227 | llinfos << "Starting internet stream: " << url << llendl; | ||
228 | mInternetStreamURL = url; | ||
229 | mInternetStreamMedia->navigateTo(url); | ||
230 | //llinfos << "Playing....." << llendl; | ||
231 | mInternetStreamMedia->addCommand(LLMediaBase::COMMAND_START); | ||
232 | mInternetStreamMedia->updateMedia(); | ||
233 | mStatus = LLMediaBase::STATUS_STARTED; | ||
234 | } | ||
235 | } | 183 | } |
236 | 184 | ||
185 | |||
237 | // virtual | 186 | // virtual |
238 | void LLAudioEngine::stopInternetStream() | 187 | void LLAudioEngine::stopInternetStream() |
239 | { | 188 | { |
240 | llinfos << "entered stopInternetStream()" << llendl; | 189 | if (mStreamingAudioImpl) |
241 | mInternetStreamURL.clear(); | 190 | mStreamingAudioImpl->stop(); |
242 | |||
243 | if(mInternetStreamMedia) | ||
244 | { | ||
245 | if(!mInternetStreamMedia->addCommand(LLMediaBase::COMMAND_STOP)) | ||
246 | { | ||
247 | llinfos << "attempting to stop stream failed!" << llendl; | ||
248 | } | ||
249 | mInternetStreamMedia->updateMedia(); | ||
250 | } | ||
251 | |||
252 | mInternetStreamURL.clear(); | ||
253 | } | 191 | } |
254 | 192 | ||
255 | // virtual | 193 | // virtual |
256 | void LLAudioEngine::pauseInternetStream(int pause) | 194 | void LLAudioEngine::pauseInternetStream(int pause) |
257 | { | 195 | { |
258 | llinfos << "entered pauseInternetStream()" << llendl; | 196 | if (mStreamingAudioImpl) |
259 | 197 | mStreamingAudioImpl->pause(pause); | |
260 | if(!mInternetStreamMedia) | ||
261 | return; | ||
262 | |||
263 | if(pause) | ||
264 | { | ||
265 | if(! mInternetStreamMedia->addCommand(LLMediaBase::COMMAND_PAUSE)) | ||
266 | { | ||
267 | llinfos << "attempting to pause stream failed!" << llendl; | ||
268 | } | ||
269 | } else { | ||
270 | if(! mInternetStreamMedia->addCommand(LLMediaBase::COMMAND_START)) | ||
271 | { | ||
272 | llinfos << "attempting to unpause stream failed!" << llendl; | ||
273 | } | ||
274 | } | ||
275 | mInternetStreamMedia->updateMedia(); | ||
276 | } | 198 | } |
277 | 199 | ||
278 | // virtual | 200 | // virtual |
279 | void LLAudioEngine::updateInternetStream() | 201 | void LLAudioEngine::updateInternetStream() |
280 | { | 202 | { |
281 | if (mInternetStreamMedia) | 203 | if (mStreamingAudioImpl) |
282 | mInternetStreamMedia->updateMedia(); | 204 | mStreamingAudioImpl->update(); |
283 | } | 205 | } |
284 | 206 | ||
285 | // virtual | 207 | // virtual |
286 | int LLAudioEngine::isInternetStreamPlaying() | 208 | int LLAudioEngine::isInternetStreamPlaying() |
287 | { | 209 | { |
288 | if (!mInternetStreamMedia) | 210 | if (mStreamingAudioImpl) |
289 | return 0; | 211 | return mStreamingAudioImpl->isPlaying(); |
290 | |||
291 | if (mInternetStreamMedia->getStatus() == LLMediaBase::STATUS_STARTED) | ||
292 | { | ||
293 | return 1; // Active and playing | ||
294 | } | ||
295 | |||
296 | if (mInternetStreamMedia->getStatus() == LLMediaBase::STATUS_PAUSED) | ||
297 | { | ||
298 | return 2; // paused | ||
299 | } | ||
300 | 212 | ||
301 | return 0; // Stopped | 213 | return 0; // Stopped |
302 | } | 214 | } |
303 | 215 | ||
304 | // virtual | ||
305 | void LLAudioEngine::getInternetStreamInfo(char* artist, char* title) | ||
306 | { | ||
307 | artist[0] = 0; | ||
308 | title[0] = 0; | ||
309 | } | ||
310 | 216 | ||
311 | // virtual | 217 | // virtual |
312 | void LLAudioEngine::setInternetStreamGain(F32 vol) | 218 | void LLAudioEngine::setInternetStreamGain(F32 vol) |
313 | { | 219 | { |
314 | mInternetStreamGain = vol; | 220 | if (mStreamingAudioImpl) |
315 | 221 | mStreamingAudioImpl->setGain(vol); | |
316 | if(!mInternetStreamMedia) | ||
317 | return; | ||
318 | |||
319 | vol = llclamp(vol, 0.f, 1.f); | ||
320 | mInternetStreamMedia->setVolume(vol); | ||
321 | mInternetStreamMedia->updateMedia(); | ||
322 | } | 222 | } |
323 | 223 | ||
324 | // virtual | 224 | // virtual |
325 | const std::string& LLAudioEngine::getInternetStreamURL() | 225 | std::string LLAudioEngine::getInternetStreamURL() |
326 | { | 226 | { |
327 | return mInternetStreamURL; | 227 | if (mStreamingAudioImpl) |
228 | return mStreamingAudioImpl->getURL(); | ||
229 | else return std::string(); | ||
328 | } | 230 | } |
329 | 231 | ||
330 | 232 | ||
@@ -335,13 +237,6 @@ void LLAudioEngine::updateChannels() | |||
335 | { | 237 | { |
336 | if (mChannels[i]) | 238 | if (mChannels[i]) |
337 | { | 239 | { |
338 | // set secondary gain if type is available | ||
339 | LLAudioSource* source = mChannels[i]->getSource(); | ||
340 | if (source) | ||
341 | { | ||
342 | mChannels[i]->setSecondaryGain(mSecondaryGain[source->getType()]); | ||
343 | } | ||
344 | |||
345 | mChannels[i]->updateBuffer(); | 240 | mChannels[i]->updateBuffer(); |
346 | mChannels[i]->update3DPosition(); | 241 | mChannels[i]->update3DPosition(); |
347 | mChannels[i]->updateLoop(); | 242 | mChannels[i]->updateLoop(); |
@@ -361,15 +256,6 @@ void LLAudioEngine::idle(F32 max_decode_time) | |||
361 | // Primarily does position updating, cleanup of unused audio sources. | 256 | // Primarily does position updating, cleanup of unused audio sources. |
362 | // Also does regeneration of the current priority of each audio source. | 257 | // Also does regeneration of the current priority of each audio source. |
363 | 258 | ||
364 | if (getMuted()) | ||
365 | { | ||
366 | setInternalGain(0.f); | ||
367 | } | ||
368 | else | ||
369 | { | ||
370 | setInternalGain(getMasterGain()); | ||
371 | } | ||
372 | |||
373 | S32 i; | 259 | S32 i; |
374 | for (i = 0; i < MAX_BUFFERS; i++) | 260 | for (i = 0; i < MAX_BUFFERS; i++) |
375 | { | 261 | { |
@@ -398,6 +284,12 @@ void LLAudioEngine::idle(F32 max_decode_time) | |||
398 | continue; | 284 | continue; |
399 | } | 285 | } |
400 | 286 | ||
287 | if (sourcep->isMuted()) | ||
288 | { | ||
289 | ++iter; | ||
290 | continue; | ||
291 | } | ||
292 | |||
401 | if (!sourcep->getChannel() && sourcep->getCurrentBuffer()) | 293 | if (!sourcep->getChannel() && sourcep->getCurrentBuffer()) |
402 | { | 294 | { |
403 | // We could potentially play this sound if its priority is high enough. | 295 | // We could potentially play this sound if its priority is high enough. |
@@ -420,7 +312,7 @@ void LLAudioEngine::idle(F32 max_decode_time) | |||
420 | LLAudioChannel *channelp = getFreeChannel(max_priority); | 312 | LLAudioChannel *channelp = getFreeChannel(max_priority); |
421 | if (channelp) | 313 | if (channelp) |
422 | { | 314 | { |
423 | //LL_INFOS("AudioEngine") << "Replacing source in channel due to priority!" << llendl; | 315 | //llinfos << "Replacing source in channel due to priority!" << llendl; |
424 | max_sourcep->setChannel(channelp); | 316 | max_sourcep->setChannel(channelp); |
425 | channelp->setSource(max_sourcep); | 317 | channelp->setSource(max_sourcep); |
426 | if (max_sourcep->isSyncSlave()) | 318 | if (max_sourcep->isSyncSlave()) |
@@ -453,9 +345,9 @@ void LLAudioEngine::idle(F32 max_decode_time) | |||
453 | // attached to each channel, since only those with active channels | 345 | // attached to each channel, since only those with active channels |
454 | // can have anything interesting happen with their queue? (Maybe not true) | 346 | // can have anything interesting happen with their queue? (Maybe not true) |
455 | LLAudioSource *sourcep = iter->second; | 347 | LLAudioSource *sourcep = iter->second; |
456 | if (!sourcep->mQueuedDatap) | 348 | if (!sourcep->mQueuedDatap || sourcep->isMuted()) |
457 | { | 349 | { |
458 | // Nothing queued, so we don't care. | 350 | // Muted, or nothing queued, so we don't care. |
459 | continue; | 351 | continue; |
460 | } | 352 | } |
461 | 353 | ||
@@ -535,6 +427,10 @@ void LLAudioEngine::idle(F32 max_decode_time) | |||
535 | for (iter = mAllSources.begin(); iter != mAllSources.end(); ++iter) | 427 | for (iter = mAllSources.begin(); iter != mAllSources.end(); ++iter) |
536 | { | 428 | { |
537 | LLAudioSource *sourcep = iter->second; | 429 | LLAudioSource *sourcep = iter->second; |
430 | if (sourcep->isMuted()) | ||
431 | { | ||
432 | continue; | ||
433 | } | ||
538 | if (sourcep->isSyncMaster()) | 434 | if (sourcep->isSyncMaster()) |
539 | { | 435 | { |
540 | if (sourcep->getPriority() > max_sm_priority) | 436 | if (sourcep->getPriority() > max_sm_priority) |
@@ -590,7 +486,7 @@ void LLAudioEngine::idle(F32 max_decode_time) | |||
590 | { | 486 | { |
591 | if (!mBuffers[i]->mInUse && mBuffers[i]->mLastUseTimer.getElapsedTimeF32() > 30.f) | 487 | if (!mBuffers[i]->mInUse && mBuffers[i]->mLastUseTimer.getElapsedTimeF32() > 30.f) |
592 | { | 488 | { |
593 | //LL_INFOS("AudioEngine") << "Flushing unused buffer!" << llendl; | 489 | //llinfos << "Flushing unused buffer!" << llendl; |
594 | mBuffers[i]->mAudioDatap->mBufferp = NULL; | 490 | mBuffers[i]->mAudioDatap->mBufferp = NULL; |
595 | delete mBuffers[i]; | 491 | delete mBuffers[i]; |
596 | mBuffers[i] = NULL; | 492 | mBuffers[i] = NULL; |
@@ -670,7 +566,7 @@ void LLAudioEngine::enableWind(bool enable) | |||
670 | } | 566 | } |
671 | 567 | ||
672 | 568 | ||
673 | LLAudioBuffer *LLAudioEngine::getFreeBuffer() | 569 | LLAudioBuffer * LLAudioEngine::getFreeBuffer() |
674 | { | 570 | { |
675 | static clock_t last_info = 0; | 571 | static clock_t last_info = 0; |
676 | static bool spamming = FALSE; | 572 | static bool spamming = FALSE; |
@@ -822,15 +718,23 @@ bool LLAudioEngine::isWindEnabled() | |||
822 | 718 | ||
823 | void LLAudioEngine::setMuted(bool muted) | 719 | void LLAudioEngine::setMuted(bool muted) |
824 | { | 720 | { |
825 | mMuted = muted; | 721 | if (muted != mMuted) |
722 | { | ||
723 | mMuted = muted; | ||
724 | setMasterGain(mMasterGain); | ||
725 | } | ||
826 | enableWind(!mMuted); | 726 | enableWind(!mMuted); |
827 | } | 727 | } |
828 | 728 | ||
829 | |||
830 | void LLAudioEngine::setMasterGain(const F32 gain) | 729 | void LLAudioEngine::setMasterGain(const F32 gain) |
831 | { | 730 | { |
832 | mMasterGain = gain; | 731 | mMasterGain = gain; |
833 | setInternalGain(gain); | 732 | F32 internal_gain = getMuted() ? 0.f : gain; |
733 | if (internal_gain != mInternalGain) | ||
734 | { | ||
735 | mInternalGain = internal_gain; | ||
736 | setInternalGain(mInternalGain); | ||
737 | } | ||
834 | } | 738 | } |
835 | 739 | ||
836 | F32 LLAudioEngine::getMasterGain() | 740 | F32 LLAudioEngine::getMasterGain() |
@@ -852,7 +756,10 @@ F32 LLAudioEngine::getSecondaryGain(S32 type) | |||
852 | 756 | ||
853 | F32 LLAudioEngine::getInternetStreamGain() | 757 | F32 LLAudioEngine::getInternetStreamGain() |
854 | { | 758 | { |
855 | return mInternetStreamGain; | 759 | if (mStreamingAudioImpl) |
760 | return mStreamingAudioImpl->getGain(); | ||
761 | else | ||
762 | return 1.0f; | ||
856 | } | 763 | } |
857 | 764 | ||
858 | void LLAudioEngine::setMaxWindGain(F32 gain) | 765 | void LLAudioEngine::setMaxWindGain(F32 gain) |
@@ -929,10 +836,9 @@ void LLAudioEngine::triggerSound(const LLUUID &audio_uuid, const LLUUID& owner_i | |||
929 | const S32 type, const LLVector3d &pos_global) | 836 | const S32 type, const LLVector3d &pos_global) |
930 | { | 837 | { |
931 | // Create a new source (since this can't be associated with an existing source. | 838 | // Create a new source (since this can't be associated with an existing source. |
932 | //LL_INFOS("AudioEngine") << "Localized: " << audio_uuid << llendl; | 839 | //llinfos << "Localized: " << audio_uuid << llendl; |
933 | 840 | ||
934 | //If we cannot hear it, dont even try to load the sound. | 841 | if (mMuted) |
935 | if (mMuted || gain == 0.0) | ||
936 | { | 842 | { |
937 | return; | 843 | return; |
938 | } | 844 | } |
@@ -1020,28 +926,6 @@ F32 LLAudioEngine::getDopplerFactor() | |||
1020 | } | 926 | } |
1021 | 927 | ||
1022 | 928 | ||
1023 | void LLAudioEngine::setDistanceFactor(F32 factor) | ||
1024 | { | ||
1025 | if (mListenerp) | ||
1026 | { | ||
1027 | mListenerp->setDistanceFactor(factor); | ||
1028 | } | ||
1029 | } | ||
1030 | |||
1031 | |||
1032 | F32 LLAudioEngine::getDistanceFactor() | ||
1033 | { | ||
1034 | if (mListenerp) | ||
1035 | { | ||
1036 | return mListenerp->getDistanceFactor(); | ||
1037 | } | ||
1038 | else | ||
1039 | { | ||
1040 | return 0.f; | ||
1041 | } | ||
1042 | } | ||
1043 | |||
1044 | |||
1045 | void LLAudioEngine::setRolloffFactor(F32 factor) | 929 | void LLAudioEngine::setRolloffFactor(F32 factor) |
1046 | { | 930 | { |
1047 | if (mListenerp) | 931 | if (mListenerp) |
@@ -1070,7 +954,7 @@ void LLAudioEngine::commitDeferredChanges() | |||
1070 | } | 954 | } |
1071 | 955 | ||
1072 | 956 | ||
1073 | LLAudioSource *LLAudioEngine::findAudioSource(const LLUUID &source_id) | 957 | LLAudioSource * LLAudioEngine::findAudioSource(const LLUUID &source_id) |
1074 | { | 958 | { |
1075 | source_map::iterator iter; | 959 | source_map::iterator iter; |
1076 | iter = mAllSources.find(source_id); | 960 | iter = mAllSources.find(source_id); |
@@ -1086,7 +970,7 @@ LLAudioSource *LLAudioEngine::findAudioSource(const LLUUID &source_id) | |||
1086 | } | 970 | } |
1087 | 971 | ||
1088 | 972 | ||
1089 | LLAudioData *LLAudioEngine::getAudioData(const LLUUID &audio_uuid) | 973 | LLAudioData * LLAudioEngine::getAudioData(const LLUUID &audio_uuid) |
1090 | { | 974 | { |
1091 | data_map::iterator iter; | 975 | data_map::iterator iter; |
1092 | iter = mAllData.find(audio_uuid); | 976 | iter = mAllData.find(audio_uuid); |
@@ -1152,10 +1036,10 @@ bool LLAudioEngine::hasLocalFile(const LLUUID &uuid) | |||
1152 | 1036 | ||
1153 | void LLAudioEngine::startNextTransfer() | 1037 | void LLAudioEngine::startNextTransfer() |
1154 | { | 1038 | { |
1155 | //LL_INFOS("AudioEngine") << "LLAudioEngine::startNextTransfer()" << llendl; | 1039 | //llinfos << "LLAudioEngine::startNextTransfer()" << llendl; |
1156 | if (mCurrentTransfer.notNull() || getMuted()) | 1040 | if (mCurrentTransfer.notNull() || getMuted()) |
1157 | { | 1041 | { |
1158 | //LL_INFOS("AudioEngine") << "Transfer in progress, aborting" << llendl; | 1042 | //llinfos << "Transfer in progress, aborting" << llendl; |
1159 | return; | 1043 | return; |
1160 | } | 1044 | } |
1161 | 1045 | ||
@@ -1336,7 +1220,7 @@ void LLAudioEngine::startNextTransfer() | |||
1336 | 1220 | ||
1337 | if (asset_id.notNull()) | 1221 | if (asset_id.notNull()) |
1338 | { | 1222 | { |
1339 | LL_INFOS("AudioEngine") << "Getting asset data for: " << asset_id << llendl; | 1223 | llinfos << "Getting asset data for: " << asset_id << llendl; |
1340 | gAudiop->mCurrentTransfer = asset_id; | 1224 | gAudiop->mCurrentTransfer = asset_id; |
1341 | gAudiop->mCurrentTransferTimer.reset(); | 1225 | gAudiop->mCurrentTransferTimer.reset(); |
1342 | gAssetStorage->getAssetData(asset_id, LLAssetType::AT_SOUND, | 1226 | gAssetStorage->getAssetData(asset_id, LLAssetType::AT_SOUND, |
@@ -1344,7 +1228,7 @@ void LLAudioEngine::startNextTransfer() | |||
1344 | } | 1228 | } |
1345 | else | 1229 | else |
1346 | { | 1230 | { |
1347 | //LL_INFOS("AudioEngine") << "No pending transfers?" << llendl; | 1231 | //llinfos << "No pending transfers?" << llendl; |
1348 | } | 1232 | } |
1349 | } | 1233 | } |
1350 | 1234 | ||
@@ -1354,7 +1238,7 @@ void LLAudioEngine::assetCallback(LLVFS *vfs, const LLUUID &uuid, LLAssetType::E | |||
1354 | { | 1238 | { |
1355 | if (result_code) | 1239 | if (result_code) |
1356 | { | 1240 | { |
1357 | LL_INFOS("AudioEngine") << "Boom, error in audio file transfer: " << LLAssetStorage::getErrorString( result_code ) << " (" << result_code << ")" << llendl; | 1241 | llinfos << "Boom, error in audio file transfer: " << LLAssetStorage::getErrorString( result_code ) << " (" << result_code << ")" << llendl; |
1358 | // Need to mark data as bad to avoid constant rerequests. | 1242 | // Need to mark data as bad to avoid constant rerequests. |
1359 | LLAudioData *adp = gAudiop->getAudioData(uuid); | 1243 | LLAudioData *adp = gAudiop->getAudioData(uuid); |
1360 | if (adp) | 1244 | if (adp) |
@@ -1394,13 +1278,14 @@ LLAudioSource::LLAudioSource(const LLUUID& id, const LLUUID& owner_id, const F32 | |||
1394 | mOwnerID(owner_id), | 1278 | mOwnerID(owner_id), |
1395 | mPriority(0.f), | 1279 | mPriority(0.f), |
1396 | mGain(gain), | 1280 | mGain(gain), |
1397 | mType(type), | 1281 | mSourceMuted(false), |
1398 | mAmbient(false), | 1282 | mAmbient(false), |
1399 | mLoop(false), | 1283 | mLoop(false), |
1400 | mSyncMaster(false), | 1284 | mSyncMaster(false), |
1401 | mSyncSlave(false), | 1285 | mSyncSlave(false), |
1402 | mQueueSounds(false), | 1286 | mQueueSounds(false), |
1403 | mPlayedOnce(false), | 1287 | mPlayedOnce(false), |
1288 | mType(type), | ||
1404 | mChannelp(NULL), | 1289 | mChannelp(NULL), |
1405 | mCurrentDatap(NULL), | 1290 | mCurrentDatap(NULL), |
1406 | mQueuedDatap(NULL) | 1291 | mQueuedDatap(NULL) |
@@ -1452,6 +1337,10 @@ void LLAudioSource::updatePriority() | |||
1452 | { | 1337 | { |
1453 | mPriority = 1.f; | 1338 | mPriority = 1.f; |
1454 | } | 1339 | } |
1340 | else if (isMuted()) | ||
1341 | { | ||
1342 | mPriority = 0.f; | ||
1343 | } | ||
1455 | else | 1344 | else |
1456 | { | 1345 | { |
1457 | // Priority is based on distance | 1346 | // Priority is based on distance |
@@ -1500,25 +1389,33 @@ bool LLAudioSource::setupChannel() | |||
1500 | 1389 | ||
1501 | bool LLAudioSource::play(const LLUUID &audio_uuid) | 1390 | bool LLAudioSource::play(const LLUUID &audio_uuid) |
1502 | { | 1391 | { |
1392 | // Special abuse of play(); don't play a sound, but kill it. | ||
1503 | if (audio_uuid.isNull()) | 1393 | if (audio_uuid.isNull()) |
1504 | { | 1394 | { |
1505 | if (getChannel()) | 1395 | if (getChannel()) |
1506 | { | 1396 | { |
1507 | getChannel()->setSource(NULL); | 1397 | getChannel()->setSource(NULL); |
1508 | setChannel(NULL); | 1398 | setChannel(NULL); |
1509 | addAudioData(NULL, true); | 1399 | if (!isMuted()) |
1400 | { | ||
1401 | mCurrentDatap = NULL; | ||
1402 | } | ||
1510 | } | 1403 | } |
1404 | return false; | ||
1511 | } | 1405 | } |
1406 | |||
1512 | // Reset our age timeout if someone attempts to play the source. | 1407 | // Reset our age timeout if someone attempts to play the source. |
1513 | mAgeTimer.reset(); | 1408 | mAgeTimer.reset(); |
1514 | 1409 | ||
1515 | LLAudioData *adp = gAudiop->getAudioData(audio_uuid); | 1410 | LLAudioData *adp = gAudiop->getAudioData(audio_uuid); |
1516 | |||
1517 | bool has_buffer = gAudiop->updateBufferForData(adp, audio_uuid); | ||
1518 | |||
1519 | |||
1520 | addAudioData(adp); | 1411 | addAudioData(adp); |
1521 | 1412 | ||
1413 | if (isMuted()) | ||
1414 | { | ||
1415 | return false; | ||
1416 | } | ||
1417 | |||
1418 | bool has_buffer = gAudiop->updateBufferForData(adp, audio_uuid); | ||
1522 | if (!has_buffer) | 1419 | if (!has_buffer) |
1523 | { | 1420 | { |
1524 | // Don't bother trying to set up a channel or anything, we don't have an audio buffer. | 1421 | // Don't bother trying to set up a channel or anything, we don't have an audio buffer. |
@@ -1543,10 +1440,11 @@ bool LLAudioSource::play(const LLUUID &audio_uuid) | |||
1543 | } | 1440 | } |
1544 | 1441 | ||
1545 | 1442 | ||
1546 | bool LLAudioSource::isDone() | 1443 | bool LLAudioSource::isDone() const |
1547 | { | 1444 | { |
1548 | const F32 MAX_AGE = 60.f; | 1445 | const F32 MAX_AGE = 60.f; |
1549 | const F32 MAX_UNPLAYED_AGE = 15.f; | 1446 | const F32 MAX_UNPLAYED_AGE = 15.f; |
1447 | const F32 MAX_MUTED_AGE = 11.f; | ||
1550 | 1448 | ||
1551 | if (isLoop()) | 1449 | if (isLoop()) |
1552 | { | 1450 | { |
@@ -1554,7 +1452,6 @@ bool LLAudioSource::isDone() | |||
1554 | return false; | 1452 | return false; |
1555 | } | 1453 | } |
1556 | 1454 | ||
1557 | |||
1558 | if (hasPendingPreloads()) | 1455 | if (hasPendingPreloads()) |
1559 | { | 1456 | { |
1560 | return false; | 1457 | return false; |
@@ -1571,10 +1468,10 @@ bool LLAudioSource::isDone() | |||
1571 | // This is a single-play source | 1468 | // This is a single-play source |
1572 | if (!mChannelp) | 1469 | if (!mChannelp) |
1573 | { | 1470 | { |
1574 | if ((elapsed > MAX_UNPLAYED_AGE) || mPlayedOnce) | 1471 | if ((elapsed > (mSourceMuted ? MAX_MUTED_AGE : MAX_UNPLAYED_AGE)) || mPlayedOnce) |
1575 | { | 1472 | { |
1576 | // We don't have a channel assigned, and it's been | 1473 | // We don't have a channel assigned, and it's been |
1577 | // over 5 seconds since we tried to play it. Don't bother. | 1474 | // over 15 seconds since we tried to play it. Don't bother. |
1578 | //llinfos << "No channel assigned, source is done" << llendl; | 1475 | //llinfos << "No channel assigned, source is done" << llendl; |
1579 | return true; | 1476 | return true; |
1580 | } | 1477 | } |
@@ -1600,7 +1497,7 @@ bool LLAudioSource::isDone() | |||
1600 | 1497 | ||
1601 | if ((elapsed > MAX_UNPLAYED_AGE) || mPlayedOnce) | 1498 | if ((elapsed > MAX_UNPLAYED_AGE) || mPlayedOnce) |
1602 | { | 1499 | { |
1603 | // The sound isn't playing back after 5 seconds or we're already done playing it, kill it. | 1500 | // The sound isn't playing back after 15 seconds or we're already done playing it, kill it. |
1604 | return true; | 1501 | return true; |
1605 | } | 1502 | } |
1606 | 1503 | ||
@@ -1696,17 +1593,17 @@ bool LLAudioSource::hasPendingPreloads() const | |||
1696 | } | 1593 | } |
1697 | 1594 | ||
1698 | 1595 | ||
1699 | LLAudioData *LLAudioSource::getCurrentData() | 1596 | LLAudioData * LLAudioSource::getCurrentData() |
1700 | { | 1597 | { |
1701 | return mCurrentDatap; | 1598 | return mCurrentDatap; |
1702 | } | 1599 | } |
1703 | 1600 | ||
1704 | LLAudioData *LLAudioSource::getQueuedData() | 1601 | LLAudioData * LLAudioSource::getQueuedData() |
1705 | { | 1602 | { |
1706 | return mQueuedDatap; | 1603 | return mQueuedDatap; |
1707 | } | 1604 | } |
1708 | 1605 | ||
1709 | LLAudioBuffer *LLAudioSource::getCurrentBuffer() | 1606 | LLAudioBuffer * LLAudioSource::getCurrentBuffer() |
1710 | { | 1607 | { |
1711 | if (!mCurrentDatap) | 1608 | if (!mCurrentDatap) |
1712 | { | 1609 | { |
@@ -1737,7 +1634,7 @@ LLAudioChannel::LLAudioChannel() : | |||
1737 | LLAudioChannel::~LLAudioChannel() | 1634 | LLAudioChannel::~LLAudioChannel() |
1738 | { | 1635 | { |
1739 | // Need to disconnect any sources which are using this channel. | 1636 | // Need to disconnect any sources which are using this channel. |
1740 | //LL_INFOS("AudioEngine") << "Cleaning up audio channel" << llendl; | 1637 | //llinfos << "Cleaning up audio channel" << llendl; |
1741 | if (mCurrentSourcep) | 1638 | if (mCurrentSourcep) |
1742 | { | 1639 | { |
1743 | mCurrentSourcep->setChannel(NULL); | 1640 | mCurrentSourcep->setChannel(NULL); |
@@ -1748,12 +1645,12 @@ LLAudioChannel::~LLAudioChannel() | |||
1748 | 1645 | ||
1749 | void LLAudioChannel::setSource(LLAudioSource *sourcep) | 1646 | void LLAudioChannel::setSource(LLAudioSource *sourcep) |
1750 | { | 1647 | { |
1751 | //LL_INFOS("AudioEngine") << this << ": setSource(" << sourcep << ")" << llendl; | 1648 | //llinfos << this << ": setSource(" << sourcep << ")" << llendl; |
1752 | 1649 | ||
1753 | if (!sourcep) | 1650 | if (!sourcep) |
1754 | { | 1651 | { |
1755 | // Clearing the source for this channel, don't need to do anything. | 1652 | // Clearing the source for this channel, don't need to do anything. |
1756 | //LL_INFOS("AudioEngine") << "Clearing source for channel" << llendl; | 1653 | //llinfos << "Clearing source for channel" << llendl; |
1757 | cleanup(); | 1654 | cleanup(); |
1758 | mCurrentSourcep = NULL; | 1655 | mCurrentSourcep = NULL; |
1759 | mWaiting = false; | 1656 | mWaiting = false; |
@@ -1763,7 +1660,7 @@ void LLAudioChannel::setSource(LLAudioSource *sourcep) | |||
1763 | if (sourcep == mCurrentSourcep) | 1660 | if (sourcep == mCurrentSourcep) |
1764 | { | 1661 | { |
1765 | // Don't reallocate the channel, this will make FMOD goofy. | 1662 | // Don't reallocate the channel, this will make FMOD goofy. |
1766 | //LL_INFOS("AudioEngine") << "Calling setSource with same source!" << llendl; | 1663 | //llinfos << "Calling setSource with same source!" << llendl; |
1767 | } | 1664 | } |
1768 | 1665 | ||
1769 | mCurrentSourcep = sourcep; | 1666 | mCurrentSourcep = sourcep; |
diff --git a/linden/indra/llaudio/audioengine.h b/linden/indra/llaudio/llaudioengine.h index e46091c..a1b240e 100644 --- a/linden/indra/llaudio/audioengine.h +++ b/linden/indra/llaudio/llaudioengine.h | |||
@@ -37,18 +37,14 @@ | |||
37 | #include <list> | 37 | #include <list> |
38 | #include <map> | 38 | #include <map> |
39 | 39 | ||
40 | #include "listener.h" | ||
41 | #include "v3math.h" | 40 | #include "v3math.h" |
42 | #include "v3dmath.h" | 41 | #include "v3dmath.h" |
43 | #include "listener.h" | ||
44 | #include "lltimer.h" | 42 | #include "lltimer.h" |
45 | #include "lluuid.h" | 43 | #include "lluuid.h" |
46 | #include "llframetimer.h" | 44 | #include "llframetimer.h" |
47 | #include "llassettype.h" | 45 | #include "llassettype.h" |
48 | 46 | ||
49 | #include "llmediabase.h" | 47 | #include "lllistener.h" |
50 | |||
51 | class LLMediaBase; | ||
52 | 48 | ||
53 | const F32 LL_WIND_UPDATE_INTERVAL = 0.1f; | 49 | const F32 LL_WIND_UPDATE_INTERVAL = 0.1f; |
54 | const F32 LL_ROLLOFF_MULTIPLIER_UNDER_WATER = 5.f; // How much sounds are weaker under water | 50 | const F32 LL_ROLLOFF_MULTIPLIER_UNDER_WATER = 5.f; // How much sounds are weaker under water |
@@ -75,7 +71,7 @@ class LLAudioData; | |||
75 | class LLAudioChannel; | 71 | class LLAudioChannel; |
76 | class LLAudioChannelOpenAL; | 72 | class LLAudioChannelOpenAL; |
77 | class LLAudioBuffer; | 73 | class LLAudioBuffer; |
78 | 74 | class LLStreamingAudioInterface; | |
79 | 75 | ||
80 | 76 | ||
81 | // | 77 | // |
@@ -121,9 +117,11 @@ public: | |||
121 | // Use these for temporarily muting the audio system. | 117 | // Use these for temporarily muting the audio system. |
122 | // Does not change buffers, initialization, etc. but | 118 | // Does not change buffers, initialization, etc. but |
123 | // stops playing new sounds. | 119 | // stops playing new sounds. |
124 | virtual void setMuted(bool muted); | 120 | void setMuted(bool muted); |
125 | virtual bool getMuted() const { return mMuted; } | 121 | bool getMuted() const { return mMuted; } |
126 | 122 | #ifdef USE_PLUGIN_MEDIA | |
123 | LLPluginClassMedia* initializeMedia(const std::string& media_type); | ||
124 | #endif | ||
127 | F32 getMasterGain(); | 125 | F32 getMasterGain(); |
128 | void setMasterGain(F32 gain); | 126 | void setMasterGain(F32 gain); |
129 | 127 | ||
@@ -134,8 +132,6 @@ public: | |||
134 | 132 | ||
135 | virtual void setDopplerFactor(F32 factor); | 133 | virtual void setDopplerFactor(F32 factor); |
136 | virtual F32 getDopplerFactor(); | 134 | virtual F32 getDopplerFactor(); |
137 | virtual void setDistanceFactor(F32 factor); | ||
138 | virtual F32 getDistanceFactor(); | ||
139 | virtual void setRolloffFactor(F32 factor); | 135 | virtual void setRolloffFactor(F32 factor); |
140 | virtual F32 getRolloffFactor(); | 136 | virtual F32 getRolloffFactor(); |
141 | virtual void setMaxWindGain(F32 gain); | 137 | virtual void setMaxWindGain(F32 gain); |
@@ -154,19 +150,19 @@ public: | |||
154 | LLAudioSource *findAudioSource(const LLUUID &source_id); | 150 | LLAudioSource *findAudioSource(const LLUUID &source_id); |
155 | LLAudioData *getAudioData(const LLUUID &audio_uuid); | 151 | LLAudioData *getAudioData(const LLUUID &audio_uuid); |
156 | 152 | ||
157 | 153 | // Internet stream implementation manipulation | |
158 | // Internet stream methods | 154 | LLStreamingAudioInterface *getStreamingAudioImpl(); |
159 | virtual void startInternetStream(const std::string& url); | 155 | void setStreamingAudioImpl(LLStreamingAudioInterface *impl); |
160 | virtual void stopInternetStream(); | 156 | // Internet stream methods - these will call down into the *mStreamingAudioImpl if it exists |
161 | virtual void pauseInternetStream(int pause); | 157 | void startInternetStream(const std::string& url); |
162 | virtual void updateInternetStream(); | 158 | void stopInternetStream(); |
163 | virtual int isInternetStreamPlaying(); | 159 | void pauseInternetStream(int pause); |
164 | virtual void getInternetStreamInfo(char* artist, char* title); | 160 | void updateInternetStream(); // expected to be called often |
161 | int isInternetStreamPlaying(); | ||
165 | // use a value from 0.0 to 1.0, inclusive | 162 | // use a value from 0.0 to 1.0, inclusive |
166 | virtual void setInternetStreamGain(F32 vol); | 163 | void setInternetStreamGain(F32 vol); |
167 | virtual const std::string& getInternetStreamURL(); | 164 | std::string getInternetStreamURL(); |
168 | virtual LLMediaBase::EStatus getStatus(); | 165 | |
169 | |||
170 | // For debugging usage | 166 | // For debugging usage |
171 | virtual LLVector3 getListenerPos(); | 167 | virtual LLVector3 getListenerPos(); |
172 | 168 | ||
@@ -185,8 +181,6 @@ public: | |||
185 | static void assetCallback(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type, void *user_data, S32 result_code, LLExtStat ext_status); | 181 | static void assetCallback(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type, void *user_data, S32 result_code, LLExtStat ext_status); |
186 | 182 | ||
187 | friend class LLPipeline; // For debugging | 183 | friend class LLPipeline; // For debugging |
188 | |||
189 | LLMediaBase * getStreamMedia() { return mInternetStreamMedia; } | ||
190 | public: | 184 | public: |
191 | F32 mMaxWindGain; // Hack. Public to set before fade in? | 185 | F32 mMaxWindGain; // Hack. Public to set before fade in? |
192 | 186 | ||
@@ -244,21 +238,16 @@ protected: | |||
244 | LLAudioBuffer *mBuffers[MAX_BUFFERS]; | 238 | LLAudioBuffer *mBuffers[MAX_BUFFERS]; |
245 | 239 | ||
246 | F32 mMasterGain; | 240 | F32 mMasterGain; |
241 | F32 mInternalGain; // Actual gain set; either mMasterGain or 0 when mMuted is true. | ||
247 | F32 mSecondaryGain[AUDIO_TYPE_COUNT]; | 242 | F32 mSecondaryGain[AUDIO_TYPE_COUNT]; |
248 | 243 | ||
249 | // Hack! Internet streams are treated differently from other sources! | ||
250 | F32 mInternetStreamGain; | ||
251 | std::string mInternetStreamURL; | ||
252 | |||
253 | F32 mNextWindUpdate; | 244 | F32 mNextWindUpdate; |
254 | 245 | ||
255 | LLFrameTimer mWindUpdateTimer; | 246 | LLFrameTimer mWindUpdateTimer; |
256 | 247 | ||
257 | LLMediaBase::EStatus mStatus; | ||
258 | |||
259 | private: | 248 | private: |
260 | void setDefaults(); | 249 | void setDefaults(); |
261 | LLMediaBase *mInternetStreamMedia; | 250 | LLStreamingAudioInterface *mStreamingAudioImpl; |
262 | }; | 251 | }; |
263 | 252 | ||
264 | 253 | ||
@@ -314,7 +303,8 @@ public: | |||
314 | virtual void setGain(const F32 gain) { mGain = llclamp(gain, 0.f, 1.f); } | 303 | virtual void setGain(const F32 gain) { mGain = llclamp(gain, 0.f, 1.f); } |
315 | 304 | ||
316 | const LLUUID &getID() const { return mID; } | 305 | const LLUUID &getID() const { return mID; } |
317 | bool isDone(); | 306 | bool isDone() const; |
307 | bool isMuted() const { return mSourceMuted; } | ||
318 | 308 | ||
319 | LLAudioData *getCurrentData(); | 309 | LLAudioData *getCurrentData(); |
320 | LLAudioData *getQueuedData(); | 310 | LLAudioData *getQueuedData(); |
@@ -336,6 +326,7 @@ protected: | |||
336 | LLUUID mOwnerID; // owner of the object playing the sound | 326 | LLUUID mOwnerID; // owner of the object playing the sound |
337 | F32 mPriority; | 327 | F32 mPriority; |
338 | F32 mGain; | 328 | F32 mGain; |
329 | bool mSourceMuted; | ||
339 | bool mAmbient; | 330 | bool mAmbient; |
340 | bool mLoop; | 331 | bool mLoop; |
341 | bool mSyncMaster; | 332 | bool mSyncMaster; |
diff --git a/linden/indra/llaudio/audioengine_fmod.cpp b/linden/indra/llaudio/llaudioengine_fmod.cpp index 938c2aa..85ae863 100644 --- a/linden/indra/llaudio/audioengine_fmod.cpp +++ b/linden/indra/llaudio/llaudioengine_fmod.cpp | |||
@@ -32,8 +32,11 @@ | |||
32 | 32 | ||
33 | #include "linden_common.h" | 33 | #include "linden_common.h" |
34 | 34 | ||
35 | #include "audioengine_fmod.h" | 35 | #include "llstreamingaudio.h" |
36 | #include "listener_fmod.h" | 36 | #include "llstreamingaudio_fmod.h" |
37 | |||
38 | #include "llaudioengine_fmod.h" | ||
39 | #include "lllistener_fmod.h" | ||
37 | 40 | ||
38 | #include "llerror.h" | 41 | #include "llerror.h" |
39 | #include "llmath.h" | 42 | #include "llmath.h" |
@@ -46,6 +49,7 @@ | |||
46 | 49 | ||
47 | #include "sound_ids.h" | 50 | #include "sound_ids.h" |
48 | 51 | ||
52 | |||
49 | extern "C" { | 53 | extern "C" { |
50 | void * F_CALLBACKAPI windCallback(void *originalbuffer, void *newbuffer, int length, void* userdata); | 54 | void * F_CALLBACKAPI windCallback(void *originalbuffer, void *newbuffer, int length, void* userdata); |
51 | } | 55 | } |
@@ -53,35 +57,9 @@ extern "C" { | |||
53 | FSOUND_DSPUNIT *gWindDSP = NULL; | 57 | FSOUND_DSPUNIT *gWindDSP = NULL; |
54 | 58 | ||
55 | 59 | ||
56 | // Safe strcpy | ||
57 | #if 0 //(unused) //LL_WINDOWS || LL_LINUX | ||
58 | static size_t strlcpy( char* dest, const char* src, size_t dst_size ) | ||
59 | { | ||
60 | size_t source_len = 0; | ||
61 | size_t min_len = 0; | ||
62 | if( dst_size > 0 ) | ||
63 | { | ||
64 | if( src ) | ||
65 | { | ||
66 | source_len = strlen(src); /*Flawfinder: ignore*/ | ||
67 | min_len = llmin( dst_size - 1, source_len ); | ||
68 | memcpy(dest, src, min_len); /*Flawfinder: ignore*/ | ||
69 | } | ||
70 | dest[min_len] = '\0'; | ||
71 | } | ||
72 | return source_len; | ||
73 | } | ||
74 | #else | ||
75 | // apple ships with the non-standard strlcpy in /usr/include/string.h: | ||
76 | // size_t strlcpy(char *, const char *, size_t); | ||
77 | #endif | ||
78 | |||
79 | |||
80 | LLAudioEngine_FMOD::LLAudioEngine_FMOD() | 60 | LLAudioEngine_FMOD::LLAudioEngine_FMOD() |
81 | { | 61 | { |
82 | mInited = false; | 62 | mInited = false; |
83 | mCurrentInternetStreamp = NULL; | ||
84 | mInternetStreamChannel = -1; | ||
85 | mWindGen = NULL; | 63 | mWindGen = NULL; |
86 | } | 64 | } |
87 | 65 | ||
@@ -93,8 +71,6 @@ LLAudioEngine_FMOD::~LLAudioEngine_FMOD() | |||
93 | 71 | ||
94 | bool LLAudioEngine_FMOD::init(const S32 num_channels, void* userdata) | 72 | bool LLAudioEngine_FMOD::init(const S32 num_channels, void* userdata) |
95 | { | 73 | { |
96 | mFadeIn = -10000; | ||
97 | |||
98 | LLAudioEngine::init(num_channels, userdata); | 74 | LLAudioEngine::init(num_channels, userdata); |
99 | 75 | ||
100 | // Reserve one extra channel for the http stream. | 76 | // Reserve one extra channel for the http stream. |
@@ -241,7 +217,9 @@ bool LLAudioEngine_FMOD::init(const S32 num_channels, void* userdata) | |||
241 | 217 | ||
242 | #endif | 218 | #endif |
243 | 219 | ||
244 | initInternetStream(); | 220 | // set up our favourite FMOD-native streaming audio implementation if none has already been added |
221 | if (!getStreamingAudioImpl()) // no existing implementation added | ||
222 | setStreamingAudioImpl(new LLStreamingAudio_FMOD()); | ||
245 | 223 | ||
246 | LL_DEBUGS("AppInit") << "LLAudioEngine_FMOD::init() FMOD initialized correctly" << LL_ENDL; | 224 | LL_DEBUGS("AppInit") << "LLAudioEngine_FMOD::init() FMOD initialized correctly" << LL_ENDL; |
247 | 225 | ||
@@ -296,13 +274,13 @@ void LLAudioEngine_FMOD::shutdown() | |||
296 | } | 274 | } |
297 | 275 | ||
298 | 276 | ||
299 | LLAudioBuffer *LLAudioEngine_FMOD::createBuffer() | 277 | LLAudioBuffer * LLAudioEngine_FMOD::createBuffer() |
300 | { | 278 | { |
301 | return new LLAudioBufferFMOD(); | 279 | return new LLAudioBufferFMOD(); |
302 | } | 280 | } |
303 | 281 | ||
304 | 282 | ||
305 | LLAudioChannel *LLAudioEngine_FMOD::createChannel() | 283 | LLAudioChannel * LLAudioEngine_FMOD::createChannel() |
306 | { | 284 | { |
307 | return new LLAudioChannelFMOD(); | 285 | return new LLAudioChannelFMOD(); |
308 | } | 286 | } |
@@ -432,10 +410,12 @@ void LLAudioEngine_FMOD::setInternalGain(F32 gain) | |||
432 | gain = llclamp( gain, 0.0f, 1.0f ); | 410 | gain = llclamp( gain, 0.0f, 1.0f ); |
433 | FSOUND_SetSFXMasterVolume( llround( 255.0f * gain ) ); | 411 | FSOUND_SetSFXMasterVolume( llround( 255.0f * gain ) ); |
434 | 412 | ||
435 | if ( mInternetStreamChannel != -1 ) | 413 | LLStreamingAudioInterface *saimpl = getStreamingAudioImpl(); |
414 | if ( saimpl ) | ||
436 | { | 415 | { |
437 | F32 clamp_internet_stream_gain = llclamp( mInternetStreamGain, 0.0f, 1.0f ); | 416 | // fmod likes its streaming audio channel gain re-asserted after |
438 | FSOUND_SetVolumeAbsolute( mInternetStreamChannel, llround( 255.0f * clamp_internet_stream_gain ) ); | 417 | // master volume change. |
418 | saimpl->setGain(saimpl->getGain()); | ||
439 | } | 419 | } |
440 | } | 420 | } |
441 | 421 | ||
@@ -660,7 +640,7 @@ bool LLAudioBufferFMOD::loadWAV(const std::string& filename) | |||
660 | return false; | 640 | return false; |
661 | } | 641 | } |
662 | 642 | ||
663 | if (!LLAPRFile::isExist(filename, NULL, LL_APR_RPB)) | 643 | if (!LLAPRFile::isExist(filename, LL_APR_RPB)) |
664 | { | 644 | { |
665 | // File not found, abort. | 645 | // File not found, abort. |
666 | return false; | 646 | return false; |
@@ -752,313 +732,6 @@ void LLAudioBufferFMOD::set3DMode(bool use3d) | |||
752 | } | 732 | } |
753 | 733 | ||
754 | 734 | ||
755 | |||
756 | //--------------------------------------------------------------------------- | ||
757 | // Internet Streaming | ||
758 | //--------------------------------------------------------------------------- | ||
759 | void LLAudioEngine_FMOD::initInternetStream() | ||
760 | { | ||
761 | // Number of milliseconds of audio to buffer for the audio card. | ||
762 | // Must be larger than the usual Second Life frame stutter time. | ||
763 | FSOUND_Stream_SetBufferSize(200); | ||
764 | |||
765 | // Here's where we set the size of the network buffer and some buffering | ||
766 | // parameters. In this case we want a network buffer of 16k, we want it | ||
767 | // to prebuffer 40% of that when we first connect, and we want it | ||
768 | // to rebuffer 80% of that whenever we encounter a buffer underrun. | ||
769 | |||
770 | // Leave the net buffer properties at the default. | ||
771 | //FSOUND_Stream_Net_SetBufferProperties(20000, 40, 80); | ||
772 | mInternetStreamURL.clear(); | ||
773 | } | ||
774 | |||
775 | |||
776 | void LLAudioEngine_FMOD::startInternetStream(const std::string& url) | ||
777 | { | ||
778 | if (!mInited) | ||
779 | { | ||
780 | llwarns << "startInternetStream before audio initialized" << llendl; | ||
781 | return; | ||
782 | } | ||
783 | |||
784 | // "stop" stream but don't clear url, etc. in calse url == mInternetStreamURL | ||
785 | stopInternetStream(); | ||
786 | if (!url.empty()) | ||
787 | { | ||
788 | llinfos << "Starting internet stream: " << url << llendl; | ||
789 | mCurrentInternetStreamp = new LLAudioStreamFMOD(url); | ||
790 | mInternetStreamURL = url; | ||
791 | } | ||
792 | else | ||
793 | { | ||
794 | llinfos << "Set internet stream to null" << llendl; | ||
795 | mInternetStreamURL.clear(); | ||
796 | } | ||
797 | } | ||
798 | |||
799 | |||
800 | signed char F_CALLBACKAPI LLAudioEngine_FMOD::callbackMetaData(char *name, char *value, void *userdata) | ||
801 | { | ||
802 | /* | ||
803 | LLAudioEngine_FMOD* self = (LLAudioEngine_FMOD*)userdata; | ||
804 | |||
805 | if (!strcmp("ARTIST", name)) | ||
806 | { | ||
807 | strlcpy(self->mInternetStreamArtist, value, 256); | ||
808 | self->mInternetStreamNewMetaData = true; | ||
809 | return true; | ||
810 | } | ||
811 | |||
812 | if (!strcmp("TITLE", name)) | ||
813 | { | ||
814 | strlcpy(self->mInternetStreamTitle, value, 256); | ||
815 | self->mInternetStreamNewMetaData = true; | ||
816 | return true; | ||
817 | } | ||
818 | */ | ||
819 | |||
820 | return true; | ||
821 | } | ||
822 | |||
823 | |||
824 | void LLAudioEngine_FMOD::updateInternetStream() | ||
825 | { | ||
826 | // Kill dead internet streams, if possible | ||
827 | std::list<LLAudioStreamFMOD *>::iterator iter; | ||
828 | for (iter = mDeadStreams.begin(); iter != mDeadStreams.end();) | ||
829 | { | ||
830 | LLAudioStreamFMOD *streamp = *iter; | ||
831 | if (streamp->stopStream()) | ||
832 | { | ||
833 | llinfos << "Closed dead stream" << llendl; | ||
834 | delete streamp; | ||
835 | mDeadStreams.erase(iter++); | ||
836 | } | ||
837 | else | ||
838 | { | ||
839 | iter++; | ||
840 | } | ||
841 | } | ||
842 | |||
843 | // Don't do anything if there are no streams playing | ||
844 | if (!mCurrentInternetStreamp) | ||
845 | { | ||
846 | return; | ||
847 | } | ||
848 | |||
849 | int open_state = mCurrentInternetStreamp->getOpenState(); | ||
850 | |||
851 | if (!open_state) | ||
852 | { | ||
853 | // Stream is live | ||
854 | |||
855 | |||
856 | // start the stream if it's ready | ||
857 | if (mInternetStreamChannel < 0) | ||
858 | { | ||
859 | mInternetStreamChannel = mCurrentInternetStreamp->startStream(); | ||
860 | |||
861 | if (mInternetStreamChannel != -1) | ||
862 | { | ||
863 | // Reset volume to previously set volume | ||
864 | setInternetStreamGain(mInternetStreamGain); | ||
865 | FSOUND_SetPaused(mInternetStreamChannel, false); | ||
866 | //FSOUND_Stream_Net_SetMetadataCallback(mInternetStream, callbackMetaData, this); | ||
867 | } | ||
868 | } | ||
869 | } | ||
870 | |||
871 | switch(open_state) | ||
872 | { | ||
873 | default: | ||
874 | case 0: | ||
875 | // success | ||
876 | break; | ||
877 | case -1: | ||
878 | // stream handle is invalid | ||
879 | llwarns << "InternetStream - invalid handle" << llendl; | ||
880 | stopInternetStream(); | ||
881 | return; | ||
882 | case -2: | ||
883 | // opening | ||
884 | //strlcpy(mInternetStreamArtist, "Opening", 256); | ||
885 | break; | ||
886 | case -3: | ||
887 | // failed to open, file not found, perhaps | ||
888 | llwarns << "InternetSteam - failed to open" << llendl; | ||
889 | stopInternetStream(); | ||
890 | return; | ||
891 | case -4: | ||
892 | // connecting | ||
893 | //strlcpy(mInternetStreamArtist, "Connecting", 256); | ||
894 | break; | ||
895 | case -5: | ||
896 | // buffering | ||
897 | //strlcpy(mInternetStreamArtist, "Buffering", 256); | ||
898 | break; | ||
899 | } | ||
900 | |||
901 | } | ||
902 | |||
903 | void LLAudioEngine_FMOD::stopInternetStream() | ||
904 | { | ||
905 | if (mInternetStreamChannel != -1) | ||
906 | { | ||
907 | FSOUND_SetPaused(mInternetStreamChannel, true); | ||
908 | FSOUND_SetPriority(mInternetStreamChannel, 0); | ||
909 | mInternetStreamChannel = -1; | ||
910 | } | ||
911 | |||
912 | if (mCurrentInternetStreamp) | ||
913 | { | ||
914 | llinfos << "Stopping internet stream: " << mCurrentInternetStreamp->getURL() << llendl; | ||
915 | if (mCurrentInternetStreamp->stopStream()) | ||
916 | { | ||
917 | delete mCurrentInternetStreamp; | ||
918 | } | ||
919 | else | ||
920 | { | ||
921 | llwarns << "Pushing stream to dead list: " << mCurrentInternetStreamp->getURL() << llendl; | ||
922 | mDeadStreams.push_back(mCurrentInternetStreamp); | ||
923 | } | ||
924 | mCurrentInternetStreamp = NULL; | ||
925 | //mInternetStreamURL.clear(); | ||
926 | } | ||
927 | } | ||
928 | |||
929 | void LLAudioEngine_FMOD::pauseInternetStream(int pause) | ||
930 | { | ||
931 | if (pause < 0) | ||
932 | { | ||
933 | pause = mCurrentInternetStreamp ? 1 : 0; | ||
934 | } | ||
935 | |||
936 | if (pause) | ||
937 | { | ||
938 | if (mCurrentInternetStreamp) | ||
939 | { | ||
940 | stopInternetStream(); | ||
941 | } | ||
942 | } | ||
943 | else | ||
944 | { | ||
945 | startInternetStream(mInternetStreamURL); | ||
946 | } | ||
947 | } | ||
948 | |||
949 | |||
950 | // A stream is "playing" if it has been requested to start. That | ||
951 | // doesn't necessarily mean audio is coming out of the speakers. | ||
952 | int LLAudioEngine_FMOD::isInternetStreamPlaying() | ||
953 | { | ||
954 | if (mCurrentInternetStreamp) | ||
955 | { | ||
956 | return 1; // Active and playing | ||
957 | } | ||
958 | else if (!mInternetStreamURL.empty()) | ||
959 | { | ||
960 | return 2; // "Paused" | ||
961 | } | ||
962 | else | ||
963 | { | ||
964 | return 0; | ||
965 | } | ||
966 | } | ||
967 | |||
968 | |||
969 | void LLAudioEngine_FMOD::setInternetStreamGain(F32 vol) | ||
970 | { | ||
971 | mInternetStreamGain = vol; | ||
972 | |||
973 | if (mInternetStreamChannel != -1) | ||
974 | { | ||
975 | vol = llclamp(vol, 0.f, 1.f); | ||
976 | int vol_int = llround(vol * 255.f); | ||
977 | FSOUND_SetVolumeAbsolute(mInternetStreamChannel, vol_int); | ||
978 | } | ||
979 | } | ||
980 | |||
981 | |||
982 | LLAudioStreamFMOD::LLAudioStreamFMOD(const std::string& url) : | ||
983 | mInternetStream(NULL), | ||
984 | mReady(false) | ||
985 | { | ||
986 | mInternetStreamURL = url; | ||
987 | mInternetStream = FSOUND_Stream_Open(url.c_str(), FSOUND_NORMAL | FSOUND_NONBLOCKING, 0, 0); | ||
988 | if (!mInternetStream) | ||
989 | { | ||
990 | llwarns << "Couldn't open fmod stream, error " | ||
991 | << FMOD_ErrorString(FSOUND_GetError()) | ||
992 | << llendl; | ||
993 | mReady = false; | ||
994 | return; | ||
995 | } | ||
996 | |||
997 | mReady = true; | ||
998 | } | ||
999 | |||
1000 | int LLAudioStreamFMOD::startStream() | ||
1001 | { | ||
1002 | // We need a live and opened stream before we try and play it. | ||
1003 | if (!mInternetStream || getOpenState()) | ||
1004 | { | ||
1005 | llwarns << "No internet stream to start playing!" << llendl; | ||
1006 | return -1; | ||
1007 | } | ||
1008 | |||
1009 | // Make sure the stream is set to 2D mode. | ||
1010 | FSOUND_Stream_SetMode(mInternetStream, FSOUND_2D); | ||
1011 | |||
1012 | return FSOUND_Stream_PlayEx(FSOUND_FREE, mInternetStream, NULL, true); | ||
1013 | } | ||
1014 | |||
1015 | bool LLAudioStreamFMOD::stopStream() | ||
1016 | { | ||
1017 | if (mInternetStream) | ||
1018 | { | ||
1019 | int read_percent = 0; | ||
1020 | int status = 0; | ||
1021 | int bitrate = 0; | ||
1022 | unsigned int flags = 0x0; | ||
1023 | FSOUND_Stream_Net_GetStatus(mInternetStream, &status, &read_percent, &bitrate, &flags); | ||
1024 | |||
1025 | bool close = true; | ||
1026 | switch (status) | ||
1027 | { | ||
1028 | case FSOUND_STREAM_NET_CONNECTING: | ||
1029 | close = false; | ||
1030 | break; | ||
1031 | case FSOUND_STREAM_NET_NOTCONNECTED: | ||
1032 | case FSOUND_STREAM_NET_BUFFERING: | ||
1033 | case FSOUND_STREAM_NET_READY: | ||
1034 | case FSOUND_STREAM_NET_ERROR: | ||
1035 | default: | ||
1036 | close = true; | ||
1037 | } | ||
1038 | |||
1039 | if (close) | ||
1040 | { | ||
1041 | FSOUND_Stream_Close(mInternetStream); | ||
1042 | mInternetStream = NULL; | ||
1043 | return true; | ||
1044 | } | ||
1045 | else | ||
1046 | { | ||
1047 | return false; | ||
1048 | } | ||
1049 | } | ||
1050 | else | ||
1051 | { | ||
1052 | return true; | ||
1053 | } | ||
1054 | } | ||
1055 | |||
1056 | int LLAudioStreamFMOD::getOpenState() | ||
1057 | { | ||
1058 | int open_state = FSOUND_Stream_GetOpenState(mInternetStream); | ||
1059 | return open_state; | ||
1060 | } | ||
1061 | |||
1062 | void * F_CALLBACKAPI windCallback(void *originalbuffer, void *newbuffer, int length, void* userdata) | 735 | void * F_CALLBACKAPI windCallback(void *originalbuffer, void *newbuffer, int length, void* userdata) |
1063 | { | 736 | { |
1064 | // originalbuffer = fmod's original mixbuffer. | 737 | // originalbuffer = fmod's original mixbuffer. |
diff --git a/linden/indra/llaudio/audioengine_fmod.h b/linden/indra/llaudio/llaudioengine_fmod.h index d0d2e1b..3968657 100644 --- a/linden/indra/llaudio/audioengine_fmod.h +++ b/linden/indra/llaudio/llaudioengine_fmod.h | |||
@@ -34,13 +34,13 @@ | |||
34 | #ifndef LL_AUDIOENGINE_FMOD_H | 34 | #ifndef LL_AUDIOENGINE_FMOD_H |
35 | #define LL_AUDIOENGINE_FMOD_H | 35 | #define LL_AUDIOENGINE_FMOD_H |
36 | 36 | ||
37 | #include "audioengine.h" | 37 | #include "llaudioengine.h" |
38 | #include "listener_fmod.h" | 38 | #include "lllistener_fmod.h" |
39 | #include "windgen.h" | 39 | #include "llwindgen.h" |
40 | 40 | ||
41 | #include "fmod.h" | 41 | #include "fmod.h" |
42 | 42 | ||
43 | class LLAudioStreamFMOD; | 43 | class LLAudioStreamManagerFMOD; |
44 | 44 | ||
45 | class LLAudioEngine_FMOD : public LLAudioEngine | 45 | class LLAudioEngine_FMOD : public LLAudioEngine |
46 | { | 46 | { |
@@ -50,20 +50,11 @@ public: | |||
50 | 50 | ||
51 | // initialization/startup/shutdown | 51 | // initialization/startup/shutdown |
52 | virtual bool init(const S32 num_channels, void *user_data); | 52 | virtual bool init(const S32 num_channels, void *user_data); |
53 | virtual std::string getDriverName(bool verbose); | 53 | virtual std::string getDriverName(bool verbose); |
54 | virtual void allocateListener(); | 54 | virtual void allocateListener(); |
55 | 55 | ||
56 | virtual void shutdown(); | 56 | virtual void shutdown(); |
57 | 57 | ||
58 | // Internet stream methods | ||
59 | virtual void initInternetStream(); | ||
60 | virtual void startInternetStream(const std::string& url); | ||
61 | virtual void updateInternetStream(); | ||
62 | virtual void stopInternetStream(); | ||
63 | virtual void pauseInternetStream(int pause); | ||
64 | virtual int isInternetStreamPlaying(); | ||
65 | virtual void setInternetStreamGain(F32 vol); | ||
66 | |||
67 | /*virtual*/ void initWind(); | 58 | /*virtual*/ void initWind(); |
68 | /*virtual*/ void cleanupWind(); | 59 | /*virtual*/ void cleanupWind(); |
69 | 60 | ||
@@ -83,15 +74,9 @@ protected: | |||
83 | protected: | 74 | protected: |
84 | static signed char F_CALLBACKAPI callbackMetaData(char* name, char* value, void* userdata); | 75 | static signed char F_CALLBACKAPI callbackMetaData(char* name, char* value, void* userdata); |
85 | 76 | ||
86 | LLAudioStreamFMOD *mCurrentInternetStreamp; | ||
87 | int mInternetStreamChannel; | ||
88 | |||
89 | std::list<LLAudioStreamFMOD *> mDeadStreams; | ||
90 | |||
91 | //F32 mMinDistance[MAX_BUFFERS]; | 77 | //F32 mMinDistance[MAX_BUFFERS]; |
92 | //F32 mMaxDistance[MAX_BUFFERS]; | 78 | //F32 mMaxDistance[MAX_BUFFERS]; |
93 | 79 | ||
94 | S32 mFadeIn; | ||
95 | bool mInited; | 80 | bool mInited; |
96 | 81 | ||
97 | // On Windows, userdata is the HWND of the application window. | 82 | // On Windows, userdata is the HWND of the application window. |
@@ -140,22 +125,5 @@ protected: | |||
140 | FSOUND_SAMPLE *mSamplep; | 125 | FSOUND_SAMPLE *mSamplep; |
141 | }; | 126 | }; |
142 | 127 | ||
143 | class LLAudioStreamFMOD | ||
144 | { | ||
145 | public: | ||
146 | LLAudioStreamFMOD(const std::string& url); | ||
147 | int startStream(); | ||
148 | bool stopStream(); // Returns true if the stream was successfully stopped. | ||
149 | bool ready(); | ||
150 | |||
151 | const std::string& getURL() { return mInternetStreamURL; } | ||
152 | |||
153 | int getOpenState(); | ||
154 | protected: | ||
155 | FSOUND_STREAM* mInternetStream; | ||
156 | bool mReady; | ||
157 | |||
158 | std::string mInternetStreamURL; | ||
159 | }; | ||
160 | 128 | ||
161 | #endif // LL_AUDIOENGINE_FMOD_H | 129 | #endif // LL_AUDIOENGINE_FMOD_H |
diff --git a/linden/indra/llaudio/audioengine_openal.cpp b/linden/indra/llaudio/llaudioengine_openal.cpp index 84305f0..93bc42b 100644 --- a/linden/indra/llaudio/audioengine_openal.cpp +++ b/linden/indra/llaudio/llaudioengine_openal.cpp | |||
@@ -34,10 +34,12 @@ | |||
34 | #include "linden_common.h" | 34 | #include "linden_common.h" |
35 | #include "lldir.h" | 35 | #include "lldir.h" |
36 | 36 | ||
37 | #include "audioengine_openal.h" | 37 | #include "llaudioengine_openal.h" |
38 | #include "listener_openal.h" | 38 | #include "lllistener_openal.h" |
39 | 39 | ||
40 | 40 | ||
41 | static const float WIND_BUFFER_SIZE_SEC = 0.05f; // 1/20th sec | ||
42 | |||
41 | LLAudioEngine_OpenAL::LLAudioEngine_OpenAL() | 43 | LLAudioEngine_OpenAL::LLAudioEngine_OpenAL() |
42 | : | 44 | : |
43 | mWindGen(NULL), | 45 | mWindGen(NULL), |
@@ -55,41 +57,15 @@ LLAudioEngine_OpenAL::~LLAudioEngine_OpenAL() | |||
55 | { | 57 | { |
56 | } | 58 | } |
57 | 59 | ||
58 | static ALboolean alutInitHelp(const char **errorstring) | ||
59 | { | ||
60 | ALboolean result = AL_FALSE; | ||
61 | ALenum err = AL_NO_ERROR; | ||
62 | #if LL_WINDOWS | ||
63 | __try { | ||
64 | result = alutInit(NULL, NULL); | ||
65 | err = alutGetError(); | ||
66 | alGetError(); // hit loading of wrap_oal.dll | ||
67 | if(!result) *errorstring = alutGetErrorString(err); | ||
68 | } __except( EXCEPTION_EXECUTE_HANDLER ) { | ||
69 | *errorstring = "[Exception]"; | ||
70 | result = AL_FALSE; | ||
71 | } | ||
72 | return result; | ||
73 | #else | ||
74 | result = alutInit(NULL, NULL); | ||
75 | if(!result) { | ||
76 | err = alutGetError(); | ||
77 | *errorstring = alutGetErrorString(err); | ||
78 | } | ||
79 | return result; | ||
80 | #endif | ||
81 | } | ||
82 | |||
83 | // virtual | 60 | // virtual |
84 | bool LLAudioEngine_OpenAL::init(const S32 num_channels, void* userdata) | 61 | bool LLAudioEngine_OpenAL::init(const S32 num_channels, void* userdata) |
85 | { | 62 | { |
86 | const char *errorstring = "(null)"; | ||
87 | mWindGen = NULL; | 63 | mWindGen = NULL; |
88 | LLAudioEngine::init(num_channels, userdata); | 64 | LLAudioEngine::init(num_channels, userdata); |
89 | 65 | ||
90 | if(!alutInitHelp(&errorstring)) | 66 | if(!alutInit(NULL, NULL)) |
91 | { | 67 | { |
92 | llwarns << "LLAudioEngine_OpenAL::init() ALUT initialization failed: " << errorstring << llendl; | 68 | llwarns << "LLAudioEngine_OpenAL::init() ALUT initialization failed: " << alutGetErrorString (alutGetError ()) << llendl; |
93 | return false; | 69 | return false; |
94 | } | 70 | } |
95 | 71 | ||
@@ -287,8 +263,6 @@ bool LLAudioChannelOpenAL::updateBuffer() | |||
287 | mCurrentSourcep->isLoop() ? AL_TRUE : AL_FALSE); | 263 | mCurrentSourcep->isLoop() ? AL_TRUE : AL_FALSE); |
288 | alSourcef(mALSource, AL_ROLLOFF_FACTOR, | 264 | alSourcef(mALSource, AL_ROLLOFF_FACTOR, |
289 | gAudiop->mListenerp->getRolloffFactor()); | 265 | gAudiop->mListenerp->getRolloffFactor()); |
290 | alSourcef(mALSource, AL_REFERENCE_DISTANCE, | ||
291 | gAudiop->mListenerp->getDistanceFactor()); | ||
292 | } | 266 | } |
293 | 267 | ||
294 | return true; | 268 | return true; |
@@ -417,7 +391,7 @@ void LLAudioEngine_OpenAL::initWind() | |||
417 | mWindGen = new LLWindGen<WIND_SAMPLE_T>; | 391 | mWindGen = new LLWindGen<WIND_SAMPLE_T>; |
418 | 392 | ||
419 | mWindBufFreq = mWindGen->getInputSamplingRate(); | 393 | mWindBufFreq = mWindGen->getInputSamplingRate(); |
420 | mWindBufSamples = llceil(mWindBufFreq * 0.05f); // 1/20th sec - WIND_BUFFER_SIZE_SEC | 394 | mWindBufSamples = llceil(mWindBufFreq * WIND_BUFFER_SIZE_SEC); |
421 | mWindBufBytes = mWindBufSamples * 2 /*stereo*/ * sizeof(WIND_SAMPLE_T); | 395 | mWindBufBytes = mWindBufSamples * 2 /*stereo*/ * sizeof(WIND_SAMPLE_T); |
422 | 396 | ||
423 | mWindBuf = new WIND_SAMPLE_T [mWindBufSamples * 2 /*stereo*/]; | 397 | mWindBuf = new WIND_SAMPLE_T [mWindBufSamples * 2 /*stereo*/]; |
diff --git a/linden/indra/llaudio/audioengine_openal.h b/linden/indra/llaudio/llaudioengine_openal.h index 8c8bfd9..900bcb3 100644 --- a/linden/indra/llaudio/audioengine_openal.h +++ b/linden/indra/llaudio/llaudioengine_openal.h | |||
@@ -36,10 +36,9 @@ | |||
36 | #ifndef LL_AUDIOENGINE_OPENAL_H | 36 | #ifndef LL_AUDIOENGINE_OPENAL_H |
37 | #define LL_AUDIOENGINE_OPENAL_H | 37 | #define LL_AUDIOENGINE_OPENAL_H |
38 | 38 | ||
39 | #include "audioengine.h" | 39 | #include "llaudioengine.h" |
40 | #include "listener_openal.h" | 40 | #include "lllistener_openal.h" |
41 | #include "windgen.h" | 41 | #include "llwindgen.h" |
42 | |||
43 | 42 | ||
44 | class LLAudioEngine_OpenAL : public LLAudioEngine | 43 | class LLAudioEngine_OpenAL : public LLAudioEngine |
45 | { | 44 | { |
diff --git a/linden/indra/llaudio/lllistener.cpp b/linden/indra/llaudio/lllistener.cpp new file mode 100644 index 0000000..846c6bc --- /dev/null +++ b/linden/indra/llaudio/lllistener.cpp | |||
@@ -0,0 +1,142 @@ | |||
1 | /** | ||
2 | * @file listener.cpp | ||
3 | * @brief Implementation of LISTENER class abstracting the audio support | ||
4 | * | ||
5 | * $LicenseInfo:firstyear=2000&license=viewergpl$ | ||
6 | * | ||
7 | * Copyright (c) 2000-2009, Linden Research, Inc. | ||
8 | * | ||
9 | * Second Life Viewer Source Code | ||
10 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
11 | * to you under the terms of the GNU General Public License, version 2.0 | ||
12 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
13 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
14 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
15 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
16 | * | ||
17 | * There are special exceptions to the terms and conditions of the GPL as | ||
18 | * it is applied to this Source Code. View the full text of the exception | ||
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
20 | * online at | ||
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
22 | * | ||
23 | * By copying, modifying or distributing this software, you acknowledge | ||
24 | * that you have read and understood your obligations described above, | ||
25 | * and agree to abide by those obligations. | ||
26 | * | ||
27 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
28 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
29 | * COMPLETENESS OR PERFORMANCE. | ||
30 | * $/LicenseInfo$ | ||
31 | */ | ||
32 | |||
33 | #include "linden_common.h" | ||
34 | |||
35 | #include "lllistener.h" | ||
36 | |||
37 | #define DEFAULT_AT 0.0f,0.0f,-1.0f | ||
38 | #define DEFAULT_UP 0.0f,1.0f,0.0f | ||
39 | |||
40 | //----------------------------------------------------------------------- | ||
41 | // constructor | ||
42 | //----------------------------------------------------------------------- | ||
43 | LLListener::LLListener() | ||
44 | { | ||
45 | init(); | ||
46 | } | ||
47 | |||
48 | //----------------------------------------------------------------------- | ||
49 | LLListener::~LLListener() | ||
50 | { | ||
51 | } | ||
52 | |||
53 | //----------------------------------------------------------------------- | ||
54 | void LLListener::init(void) | ||
55 | { | ||
56 | mPosition.zeroVec(); | ||
57 | mListenAt.setVec(DEFAULT_AT); | ||
58 | mListenUp.setVec(DEFAULT_UP); | ||
59 | mVelocity.zeroVec(); | ||
60 | } | ||
61 | |||
62 | //----------------------------------------------------------------------- | ||
63 | void LLListener::translate(LLVector3 offset) | ||
64 | { | ||
65 | mPosition += offset; | ||
66 | } | ||
67 | |||
68 | //----------------------------------------------------------------------- | ||
69 | void LLListener::setPosition(LLVector3 pos) | ||
70 | { | ||
71 | mPosition = pos; | ||
72 | } | ||
73 | |||
74 | //----------------------------------------------------------------------- | ||
75 | LLVector3 LLListener::getPosition(void) | ||
76 | { | ||
77 | return(mPosition); | ||
78 | } | ||
79 | |||
80 | //----------------------------------------------------------------------- | ||
81 | LLVector3 LLListener::getAt(void) | ||
82 | { | ||
83 | return(mListenAt); | ||
84 | } | ||
85 | |||
86 | //----------------------------------------------------------------------- | ||
87 | LLVector3 LLListener::getUp(void) | ||
88 | { | ||
89 | return(mListenUp); | ||
90 | } | ||
91 | |||
92 | //----------------------------------------------------------------------- | ||
93 | void LLListener::setVelocity(LLVector3 vel) | ||
94 | { | ||
95 | mVelocity = vel; | ||
96 | } | ||
97 | |||
98 | //----------------------------------------------------------------------- | ||
99 | void LLListener::orient(LLVector3 up, LLVector3 at) | ||
100 | { | ||
101 | mListenUp = up; | ||
102 | mListenAt = at; | ||
103 | } | ||
104 | |||
105 | //----------------------------------------------------------------------- | ||
106 | void LLListener::set(LLVector3 pos, LLVector3 vel, LLVector3 up, LLVector3 at) | ||
107 | { | ||
108 | mPosition = pos; | ||
109 | mVelocity = vel; | ||
110 | |||
111 | setPosition(pos); | ||
112 | setVelocity(vel); | ||
113 | orient(up,at); | ||
114 | } | ||
115 | |||
116 | //----------------------------------------------------------------------- | ||
117 | void LLListener::setDopplerFactor(F32 factor) | ||
118 | { | ||
119 | } | ||
120 | |||
121 | //----------------------------------------------------------------------- | ||
122 | F32 LLListener::getDopplerFactor() | ||
123 | { | ||
124 | return (1.f); | ||
125 | } | ||
126 | |||
127 | //----------------------------------------------------------------------- | ||
128 | void LLListener::setRolloffFactor(F32 factor) | ||
129 | { | ||
130 | } | ||
131 | |||
132 | //----------------------------------------------------------------------- | ||
133 | F32 LLListener::getRolloffFactor() | ||
134 | { | ||
135 | return (1.f); | ||
136 | } | ||
137 | |||
138 | //----------------------------------------------------------------------- | ||
139 | void LLListener::commitDeferredChanges() | ||
140 | { | ||
141 | } | ||
142 | |||
diff --git a/linden/indra/llaudio/lllistener.h b/linden/indra/llaudio/lllistener.h new file mode 100644 index 0000000..e94fbe8 --- /dev/null +++ b/linden/indra/llaudio/lllistener.h | |||
@@ -0,0 +1,78 @@ | |||
1 | /** | ||
2 | * @file listener.h | ||
3 | * @brief Description of LISTENER base class abstracting the audio support. | ||
4 | * | ||
5 | * $LicenseInfo:firstyear=2000&license=viewergpl$ | ||
6 | * | ||
7 | * Copyright (c) 2000-2009, Linden Research, Inc. | ||
8 | * | ||
9 | * Second Life Viewer Source Code | ||
10 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
11 | * to you under the terms of the GNU General Public License, version 2.0 | ||
12 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
13 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
14 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
15 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
16 | * | ||
17 | * There are special exceptions to the terms and conditions of the GPL as | ||
18 | * it is applied to this Source Code. View the full text of the exception | ||
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
20 | * online at | ||
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
22 | * | ||
23 | * By copying, modifying or distributing this software, you acknowledge | ||
24 | * that you have read and understood your obligations described above, | ||
25 | * and agree to abide by those obligations. | ||
26 | * | ||
27 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
28 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
29 | * COMPLETENESS OR PERFORMANCE. | ||
30 | * $/LicenseInfo$ | ||
31 | */ | ||
32 | |||
33 | #ifndef LL_LISTENER_H | ||
34 | #define LL_LISTENER_H | ||
35 | |||
36 | #include "v3math.h" | ||
37 | |||
38 | class LLListener | ||
39 | { | ||
40 | private: | ||
41 | protected: | ||
42 | LLVector3 mPosition; | ||
43 | LLVector3 mVelocity; | ||
44 | LLVector3 mListenAt; | ||
45 | LLVector3 mListenUp; | ||
46 | |||
47 | public: | ||
48 | |||
49 | private: | ||
50 | protected: | ||
51 | public: | ||
52 | LLListener(); | ||
53 | virtual ~LLListener(); | ||
54 | virtual void init(); | ||
55 | |||
56 | virtual void set(LLVector3 pos, LLVector3 vel, LLVector3 up, LLVector3 at); | ||
57 | |||
58 | virtual void setPosition(LLVector3 pos); | ||
59 | virtual void setVelocity(LLVector3 vel); | ||
60 | |||
61 | virtual void orient(LLVector3 up, LLVector3 at); | ||
62 | virtual void translate(LLVector3 offset); | ||
63 | |||
64 | virtual void setDopplerFactor(F32 factor); | ||
65 | virtual void setRolloffFactor(F32 factor); | ||
66 | |||
67 | virtual LLVector3 getPosition(); | ||
68 | virtual LLVector3 getAt(); | ||
69 | virtual LLVector3 getUp(); | ||
70 | |||
71 | virtual F32 getDopplerFactor(); | ||
72 | virtual F32 getRolloffFactor(); | ||
73 | |||
74 | virtual void commitDeferredChanges(); | ||
75 | }; | ||
76 | |||
77 | #endif | ||
78 | |||
diff --git a/linden/indra/llaudio/lllistener_ds3d.h b/linden/indra/llaudio/lllistener_ds3d.h new file mode 100644 index 0000000..1ff9c17 --- /dev/null +++ b/linden/indra/llaudio/lllistener_ds3d.h | |||
@@ -0,0 +1,74 @@ | |||
1 | /** | ||
2 | * @file listener_ds3d.h | ||
3 | * @brief Description of LISTENER class abstracting the audio support | ||
4 | * as a DirectSound 3D implementation (windows only) | ||
5 | * | ||
6 | * $LicenseInfo:firstyear=2000&license=viewergpl$ | ||
7 | * | ||
8 | * Copyright (c) 2000-2009, Linden Research, Inc. | ||
9 | * | ||
10 | * Second Life Viewer Source Code | ||
11 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
12 | * to you under the terms of the GNU General Public License, version 2.0 | ||
13 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
14 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
15 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
16 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
17 | * | ||
18 | * There are special exceptions to the terms and conditions of the GPL as | ||
19 | * it is applied to this Source Code. View the full text of the exception | ||
20 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
21 | * online at | ||
22 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
23 | * | ||
24 | * By copying, modifying or distributing this software, you acknowledge | ||
25 | * that you have read and understood your obligations described above, | ||
26 | * and agree to abide by those obligations. | ||
27 | * | ||
28 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
29 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
30 | * COMPLETENESS OR PERFORMANCE. | ||
31 | * $/LicenseInfo$ | ||
32 | */ | ||
33 | |||
34 | #ifndef LL_LISTENER_DS3D_H | ||
35 | #define LL_LISTENER_DS3D_H | ||
36 | |||
37 | #include "lllistener.h" | ||
38 | |||
39 | #include <dmusici.h> | ||
40 | #include <dsound.h> | ||
41 | #include <ks.h> | ||
42 | |||
43 | class LLListener_DS3D : public LLListener | ||
44 | { | ||
45 | private: | ||
46 | protected: | ||
47 | IDirectSound3DListener8 *m3DListener; | ||
48 | public: | ||
49 | |||
50 | private: | ||
51 | protected: | ||
52 | public: | ||
53 | LLListener_DS3D(); | ||
54 | virtual ~LLListener_DS3D(); | ||
55 | virtual void init(); | ||
56 | |||
57 | virtual void setDS3DLPtr (IDirectSound3DListener8 *listener_p); | ||
58 | |||
59 | virtual void translate(LLVector3 offset); | ||
60 | virtual void setPosition(LLVector3 pos); | ||
61 | virtual void setVelocity(LLVector3 vel); | ||
62 | virtual void orient(LLVector3 up, LLVector3 at); | ||
63 | |||
64 | virtual void setDopplerFactor(F32 factor); | ||
65 | virtual F32 getDopplerFactor(); | ||
66 | virtual void setRolloffFactor(F32 factor); | ||
67 | virtual F32 getRolloffFactor(); | ||
68 | |||
69 | virtual void commitDeferredChanges(); | ||
70 | }; | ||
71 | |||
72 | #endif | ||
73 | |||
74 | |||
diff --git a/linden/indra/llaudio/lllistener_fmod.cpp b/linden/indra/llaudio/lllistener_fmod.cpp new file mode 100644 index 0000000..57ad461 --- /dev/null +++ b/linden/indra/llaudio/lllistener_fmod.cpp | |||
@@ -0,0 +1,131 @@ | |||
1 | /** | ||
2 | * @file listener_fmod.cpp | ||
3 | * @brief implementation of LISTENER class abstracting the audio | ||
4 | * support as a FMOD 3D implementation (windows only) | ||
5 | * | ||
6 | * $LicenseInfo:firstyear=2002&license=viewergpl$ | ||
7 | * | ||
8 | * Copyright (c) 2002-2009, Linden Research, Inc. | ||
9 | * | ||
10 | * Second Life Viewer Source Code | ||
11 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
12 | * to you under the terms of the GNU General Public License, version 2.0 | ||
13 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
14 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
15 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
16 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
17 | * | ||
18 | * There are special exceptions to the terms and conditions of the GPL as | ||
19 | * it is applied to this Source Code. View the full text of the exception | ||
20 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
21 | * online at | ||
22 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
23 | * | ||
24 | * By copying, modifying or distributing this software, you acknowledge | ||
25 | * that you have read and understood your obligations described above, | ||
26 | * and agree to abide by those obligations. | ||
27 | * | ||
28 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
29 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
30 | * COMPLETENESS OR PERFORMANCE. | ||
31 | * $/LicenseInfo$ | ||
32 | */ | ||
33 | |||
34 | #include "linden_common.h" | ||
35 | #include "llaudioengine.h" | ||
36 | #include "lllistener_fmod.h" | ||
37 | #include "fmod.h" | ||
38 | |||
39 | //----------------------------------------------------------------------- | ||
40 | // constructor | ||
41 | //----------------------------------------------------------------------- | ||
42 | LLListener_FMOD::LLListener_FMOD() | ||
43 | { | ||
44 | init(); | ||
45 | } | ||
46 | |||
47 | //----------------------------------------------------------------------- | ||
48 | LLListener_FMOD::~LLListener_FMOD() | ||
49 | { | ||
50 | } | ||
51 | |||
52 | //----------------------------------------------------------------------- | ||
53 | void LLListener_FMOD::init(void) | ||
54 | { | ||
55 | // do inherited | ||
56 | LLListener::init(); | ||
57 | mDopplerFactor = 1.0f; | ||
58 | mRolloffFactor = 1.0f; | ||
59 | } | ||
60 | |||
61 | //----------------------------------------------------------------------- | ||
62 | void LLListener_FMOD::translate(LLVector3 offset) | ||
63 | { | ||
64 | LLListener::translate(offset); | ||
65 | |||
66 | 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]); | ||
67 | } | ||
68 | |||
69 | //----------------------------------------------------------------------- | ||
70 | void LLListener_FMOD::setPosition(LLVector3 pos) | ||
71 | { | ||
72 | LLListener::setPosition(pos); | ||
73 | |||
74 | 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]); | ||
75 | } | ||
76 | |||
77 | //----------------------------------------------------------------------- | ||
78 | void LLListener_FMOD::setVelocity(LLVector3 vel) | ||
79 | { | ||
80 | LLListener::setVelocity(vel); | ||
81 | |||
82 | 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]); | ||
83 | } | ||
84 | |||
85 | //----------------------------------------------------------------------- | ||
86 | void LLListener_FMOD::orient(LLVector3 up, LLVector3 at) | ||
87 | { | ||
88 | LLListener::orient(up, at); | ||
89 | |||
90 | // Welcome to the transition between right and left | ||
91 | // (coordinate systems, that is) | ||
92 | // Leaving the at vector alone results in a L/R reversal | ||
93 | // since DX is left-handed and we (LL, OpenGL, OpenAL) are right-handed | ||
94 | at = -at; | ||
95 | |||
96 | FSOUND_3D_Listener_SetAttributes(NULL, NULL, at.mV[0],at.mV[1],at.mV[2], up.mV[0],up.mV[1],up.mV[2]); | ||
97 | } | ||
98 | |||
99 | //----------------------------------------------------------------------- | ||
100 | void LLListener_FMOD::commitDeferredChanges() | ||
101 | { | ||
102 | FSOUND_Update(); | ||
103 | } | ||
104 | |||
105 | |||
106 | void LLListener_FMOD::setRolloffFactor(F32 factor) | ||
107 | { | ||
108 | mRolloffFactor = factor; | ||
109 | FSOUND_3D_SetRolloffFactor(factor); | ||
110 | } | ||
111 | |||
112 | |||
113 | F32 LLListener_FMOD::getRolloffFactor() | ||
114 | { | ||
115 | return mRolloffFactor; | ||
116 | } | ||
117 | |||
118 | |||
119 | void LLListener_FMOD::setDopplerFactor(F32 factor) | ||
120 | { | ||
121 | mDopplerFactor = factor; | ||
122 | FSOUND_3D_SetDopplerFactor(factor); | ||
123 | } | ||
124 | |||
125 | |||
126 | F32 LLListener_FMOD::getDopplerFactor() | ||
127 | { | ||
128 | return mDopplerFactor; | ||
129 | } | ||
130 | |||
131 | |||
diff --git a/linden/indra/llaudio/lllistener_fmod.h b/linden/indra/llaudio/lllistener_fmod.h new file mode 100644 index 0000000..5a48ec8 --- /dev/null +++ b/linden/indra/llaudio/lllistener_fmod.h | |||
@@ -0,0 +1,64 @@ | |||
1 | /** | ||
2 | * @file listener_fmod.h | ||
3 | * @brief Description of LISTENER class abstracting the audio support | ||
4 | * as an FMOD 3D implementation (windows and Linux) | ||
5 | * | ||
6 | * $LicenseInfo:firstyear=2002&license=viewergpl$ | ||
7 | * | ||
8 | * Copyright (c) 2002-2009, Linden Research, Inc. | ||
9 | * | ||
10 | * Second Life Viewer Source Code | ||
11 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
12 | * to you under the terms of the GNU General Public License, version 2.0 | ||
13 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
14 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
15 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
16 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
17 | * | ||
18 | * There are special exceptions to the terms and conditions of the GPL as | ||
19 | * it is applied to this Source Code. View the full text of the exception | ||
20 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
21 | * online at | ||
22 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
23 | * | ||
24 | * By copying, modifying or distributing this software, you acknowledge | ||
25 | * that you have read and understood your obligations described above, | ||
26 | * and agree to abide by those obligations. | ||
27 | * | ||
28 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
29 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
30 | * COMPLETENESS OR PERFORMANCE. | ||
31 | * $/LicenseInfo$ | ||
32 | */ | ||
33 | |||
34 | #ifndef LL_LISTENER_FMOD_H | ||
35 | #define LL_LISTENER_FMOD_H | ||
36 | |||
37 | #include "lllistener.h" | ||
38 | |||
39 | class LLListener_FMOD : public LLListener | ||
40 | { | ||
41 | public: | ||
42 | LLListener_FMOD(); | ||
43 | virtual ~LLListener_FMOD(); | ||
44 | virtual void init(); | ||
45 | |||
46 | virtual void translate(LLVector3 offset); | ||
47 | virtual void setPosition(LLVector3 pos); | ||
48 | virtual void setVelocity(LLVector3 vel); | ||
49 | virtual void orient(LLVector3 up, LLVector3 at); | ||
50 | virtual void commitDeferredChanges(); | ||
51 | |||
52 | virtual void setDopplerFactor(F32 factor); | ||
53 | virtual F32 getDopplerFactor(); | ||
54 | virtual void setRolloffFactor(F32 factor); | ||
55 | virtual F32 getRolloffFactor(); | ||
56 | |||
57 | protected: | ||
58 | F32 mDopplerFactor; | ||
59 | F32 mRolloffFactor; | ||
60 | }; | ||
61 | |||
62 | #endif | ||
63 | |||
64 | |||
diff --git a/linden/indra/llaudio/listener_openal.cpp b/linden/indra/llaudio/lllistener_openal.cpp index d0ef9b2..a96ebd5 100644 --- a/linden/indra/llaudio/listener_openal.cpp +++ b/linden/indra/llaudio/lllistener_openal.cpp | |||
@@ -32,9 +32,9 @@ | |||
32 | */ | 32 | */ |
33 | 33 | ||
34 | #include "linden_common.h" | 34 | #include "linden_common.h" |
35 | #include "audioengine.h" | 35 | #include "llaudioengine.h" |
36 | 36 | ||
37 | #include "listener_openal.h" | 37 | #include "lllistener_openal.h" |
38 | 38 | ||
39 | LLListener_OpenAL::LLListener_OpenAL() | 39 | LLListener_OpenAL::LLListener_OpenAL() |
40 | { | 40 | { |
@@ -114,12 +114,3 @@ F32 LLListener_OpenAL::getRolloffFactor() | |||
114 | } | 114 | } |
115 | 115 | ||
116 | 116 | ||
117 | void LLListener_OpenAL::setDistanceFactor(F32 factor) | ||
118 | { | ||
119 | mDistanceFactor = factor; | ||
120 | } | ||
121 | |||
122 | F32 LLListener_OpenAL::getDistanceFactor() | ||
123 | { | ||
124 | return mDistanceFactor; | ||
125 | } | ||
diff --git a/linden/indra/llaudio/listener_openal.h b/linden/indra/llaudio/lllistener_openal.h index 2b79ada..0dfeea5 100644 --- a/linden/indra/llaudio/listener_openal.h +++ b/linden/indra/llaudio/lllistener_openal.h | |||
@@ -34,10 +34,9 @@ | |||
34 | #ifndef LL_LISTENER_OPENAL_H | 34 | #ifndef LL_LISTENER_OPENAL_H |
35 | #define LL_LISTENER_OPENAL_H | 35 | #define LL_LISTENER_OPENAL_H |
36 | 36 | ||
37 | #include "listener.h" | 37 | #include "lllistener.h" |
38 | 38 | ||
39 | 39 | #include "AL/al.h" | |
40 | //#include "AL/al.h" | ||
41 | #include "AL/alut.h" | 40 | #include "AL/alut.h" |
42 | 41 | ||
43 | class LLListener_OpenAL : public LLListener | 42 | class LLListener_OpenAL : public LLListener |
@@ -54,13 +53,10 @@ class LLListener_OpenAL : public LLListener | |||
54 | 53 | ||
55 | virtual void setDopplerFactor(F32 factor); | 54 | virtual void setDopplerFactor(F32 factor); |
56 | virtual F32 getDopplerFactor(); | 55 | virtual F32 getDopplerFactor(); |
57 | virtual void setDistanceFactor(F32 factor); | ||
58 | virtual F32 getDistanceFactor(); | ||
59 | virtual void setRolloffFactor(F32 factor); | 56 | virtual void setRolloffFactor(F32 factor); |
60 | virtual F32 getRolloffFactor(); | 57 | virtual F32 getRolloffFactor(); |
61 | 58 | ||
62 | protected: | 59 | protected: |
63 | F32 mDistanceFactor; | ||
64 | F32 mRolloffFactor; | 60 | F32 mRolloffFactor; |
65 | }; | 61 | }; |
66 | 62 | ||
diff --git a/linden/indra/llaudio/llstreamingaudio.h b/linden/indra/llaudio/llstreamingaudio.h new file mode 100644 index 0000000..aa89e6a --- /dev/null +++ b/linden/indra/llaudio/llstreamingaudio.h | |||
@@ -0,0 +1,56 @@ | |||
1 | /** | ||
2 | * @file streamingaudio.h | ||
3 | * @author Tofu Linden | ||
4 | * @brief Definition of LLStreamingAudioInterface base class abstracting the streaming audio interface | ||
5 | * | ||
6 | * $LicenseInfo:firstyear=2009&license=viewergpl$ | ||
7 | * | ||
8 | * Copyright (c) 2009, Linden Research, Inc. | ||
9 | * | ||
10 | * Second Life Viewer Source Code | ||
11 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
12 | * to you under the terms of the GNU General Public License, version 2.0 | ||
13 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
14 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
15 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
16 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
17 | * | ||
18 | * There are special exceptions to the terms and conditions of the GPL as | ||
19 | * it is applied to this Source Code. View the full text of the exception | ||
20 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
21 | * online at | ||
22 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
23 | * | ||
24 | * By copying, modifying or distributing this software, you acknowledge | ||
25 | * that you have read and understood your obligations described above, | ||
26 | * and agree to abide by those obligations. | ||
27 | * | ||
28 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
29 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
30 | * COMPLETENESS OR PERFORMANCE. | ||
31 | * $/LicenseInfo$ | ||
32 | */ | ||
33 | |||
34 | #ifndef LL_STREAMINGAUDIO_H | ||
35 | #define LL_STREAMINGAUDIO_H | ||
36 | |||
37 | #include "stdtypes.h" // from llcommon | ||
38 | |||
39 | // Entirely abstract. Based exactly on the historic API. | ||
40 | class LLStreamingAudioInterface | ||
41 | { | ||
42 | public: | ||
43 | virtual ~LLStreamingAudioInterface() {} | ||
44 | |||
45 | virtual void start(const std::string& url) = 0; | ||
46 | virtual void stop() = 0; | ||
47 | virtual void pause(int pause) = 0; | ||
48 | virtual void update() = 0; | ||
49 | virtual int isPlaying() = 0; | ||
50 | // use a value from 0.0 to 1.0, inclusive | ||
51 | virtual void setGain(F32 vol) = 0; | ||
52 | virtual F32 getGain() = 0; | ||
53 | virtual std::string getURL() = 0; | ||
54 | }; | ||
55 | |||
56 | #endif // LL_STREAMINGAUDIO_H | ||
diff --git a/linden/indra/llaudio/llstreamingaudio_fmod.cpp b/linden/indra/llaudio/llstreamingaudio_fmod.cpp new file mode 100644 index 0000000..a71a872 --- /dev/null +++ b/linden/indra/llaudio/llstreamingaudio_fmod.cpp | |||
@@ -0,0 +1,362 @@ | |||
1 | /** | ||
2 | * @file streamingaudio_fmod.cpp | ||
3 | * @brief LLStreamingAudio_FMOD implementation | ||
4 | * | ||
5 | * $LicenseInfo:firstyear=2009&license=viewergpl$ | ||
6 | * | ||
7 | * Copyright (c) 2009, Linden Research, Inc. | ||
8 | * | ||
9 | * Second Life Viewer Source Code | ||
10 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
11 | * to you under the terms of the GNU General Public License, version 2.0 | ||
12 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
13 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
14 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
15 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
16 | * | ||
17 | * There are special exceptions to the terms and conditions of the GPL as | ||
18 | * it is applied to this Source Code. View the full text of the exception | ||
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
20 | * online at | ||
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
22 | * | ||
23 | * By copying, modifying or distributing this software, you acknowledge | ||
24 | * that you have read and understood your obligations described above, | ||
25 | * and agree to abide by those obligations. | ||
26 | * | ||
27 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
28 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
29 | * COMPLETENESS OR PERFORMANCE. | ||
30 | * $/LicenseInfo$ | ||
31 | */ | ||
32 | |||
33 | #include "linden_common.h" | ||
34 | |||
35 | #include "llmath.h" | ||
36 | |||
37 | #include "fmod.h" | ||
38 | #include "fmod_errors.h" | ||
39 | |||
40 | #include "llstreamingaudio_fmod.h" | ||
41 | |||
42 | |||
43 | class LLAudioStreamManagerFMOD | ||
44 | { | ||
45 | public: | ||
46 | LLAudioStreamManagerFMOD(const std::string& url); | ||
47 | int startStream(); | ||
48 | bool stopStream(); // Returns true if the stream was successfully stopped. | ||
49 | bool ready(); | ||
50 | |||
51 | const std::string& getURL() { return mInternetStreamURL; } | ||
52 | |||
53 | int getOpenState(); | ||
54 | protected: | ||
55 | FSOUND_STREAM* mInternetStream; | ||
56 | bool mReady; | ||
57 | |||
58 | std::string mInternetStreamURL; | ||
59 | }; | ||
60 | |||
61 | |||
62 | |||
63 | //--------------------------------------------------------------------------- | ||
64 | // Internet Streaming | ||
65 | //--------------------------------------------------------------------------- | ||
66 | LLStreamingAudio_FMOD::LLStreamingAudio_FMOD() : | ||
67 | mCurrentInternetStreamp(NULL), | ||
68 | mFMODInternetStreamChannel(-1), | ||
69 | mGain(1.0f) | ||
70 | { | ||
71 | // Number of milliseconds of audio to buffer for the audio card. | ||
72 | // Must be larger than the usual Second Life frame stutter time. | ||
73 | FSOUND_Stream_SetBufferSize(200); | ||
74 | |||
75 | // Here's where we set the size of the network buffer and some buffering | ||
76 | // parameters. In this case we want a network buffer of 16k, we want it | ||
77 | // to prebuffer 40% of that when we first connect, and we want it | ||
78 | // to rebuffer 80% of that whenever we encounter a buffer underrun. | ||
79 | |||
80 | // Leave the net buffer properties at the default. | ||
81 | //FSOUND_Stream_Net_SetBufferProperties(20000, 40, 80); | ||
82 | } | ||
83 | |||
84 | |||
85 | LLStreamingAudio_FMOD::~LLStreamingAudio_FMOD() | ||
86 | { | ||
87 | // nothing interesting/safe to do. | ||
88 | } | ||
89 | |||
90 | |||
91 | void LLStreamingAudio_FMOD::start(const std::string& url) | ||
92 | { | ||
93 | //if (!mInited) | ||
94 | //{ | ||
95 | // llwarns << "startInternetStream before audio initialized" << llendl; | ||
96 | // return; | ||
97 | //} | ||
98 | |||
99 | // "stop" stream but don't clear url, etc. in case url == mInternetStreamURL | ||
100 | stop(); | ||
101 | |||
102 | if (!url.empty()) | ||
103 | { | ||
104 | llinfos << "Starting internet stream: " << url << llendl; | ||
105 | mCurrentInternetStreamp = new LLAudioStreamManagerFMOD(url); | ||
106 | mURL = url; | ||
107 | } | ||
108 | else | ||
109 | { | ||
110 | llinfos << "Set internet stream to null" << llendl; | ||
111 | mURL.clear(); | ||
112 | } | ||
113 | } | ||
114 | |||
115 | |||
116 | void LLStreamingAudio_FMOD::update() | ||
117 | { | ||
118 | // Kill dead internet streams, if possible | ||
119 | std::list<LLAudioStreamManagerFMOD *>::iterator iter; | ||
120 | for (iter = mDeadStreams.begin(); iter != mDeadStreams.end();) | ||
121 | { | ||
122 | LLAudioStreamManagerFMOD *streamp = *iter; | ||
123 | if (streamp->stopStream()) | ||
124 | { | ||
125 | llinfos << "Closed dead stream" << llendl; | ||
126 | delete streamp; | ||
127 | mDeadStreams.erase(iter++); | ||
128 | } | ||
129 | else | ||
130 | { | ||
131 | iter++; | ||
132 | } | ||
133 | } | ||
134 | |||
135 | // Don't do anything if there are no streams playing | ||
136 | if (!mCurrentInternetStreamp) | ||
137 | { | ||
138 | return; | ||
139 | } | ||
140 | |||
141 | int open_state = mCurrentInternetStreamp->getOpenState(); | ||
142 | |||
143 | if (!open_state) | ||
144 | { | ||
145 | // Stream is live | ||
146 | |||
147 | // start the stream if it's ready | ||
148 | if (mFMODInternetStreamChannel < 0) | ||
149 | { | ||
150 | mFMODInternetStreamChannel = mCurrentInternetStreamp->startStream(); | ||
151 | |||
152 | if (mFMODInternetStreamChannel != -1) | ||
153 | { | ||
154 | // Reset volume to previously set volume | ||
155 | setGain(getGain()); | ||
156 | FSOUND_SetPaused(mFMODInternetStreamChannel, false); | ||
157 | } | ||
158 | } | ||
159 | } | ||
160 | |||
161 | switch(open_state) | ||
162 | { | ||
163 | default: | ||
164 | case 0: | ||
165 | // success | ||
166 | break; | ||
167 | case -1: | ||
168 | // stream handle is invalid | ||
169 | llwarns << "InternetStream - invalid handle" << llendl; | ||
170 | stop(); | ||
171 | return; | ||
172 | case -2: | ||
173 | // opening | ||
174 | break; | ||
175 | case -3: | ||
176 | // failed to open, file not found, perhaps | ||
177 | llwarns << "InternetSteam - failed to open" << llendl; | ||
178 | stop(); | ||
179 | return; | ||
180 | case -4: | ||
181 | // connecting | ||
182 | break; | ||
183 | case -5: | ||
184 | // buffering | ||
185 | break; | ||
186 | } | ||
187 | |||
188 | } | ||
189 | |||
190 | void LLStreamingAudio_FMOD::stop() | ||
191 | { | ||
192 | if (mFMODInternetStreamChannel != -1) | ||
193 | { | ||
194 | FSOUND_SetPaused(mFMODInternetStreamChannel, true); | ||
195 | FSOUND_SetPriority(mFMODInternetStreamChannel, 0); | ||
196 | mFMODInternetStreamChannel = -1; | ||
197 | } | ||
198 | |||
199 | if (mCurrentInternetStreamp) | ||
200 | { | ||
201 | llinfos << "Stopping internet stream: " << mCurrentInternetStreamp->getURL() << llendl; | ||
202 | if (mCurrentInternetStreamp->stopStream()) | ||
203 | { | ||
204 | delete mCurrentInternetStreamp; | ||
205 | } | ||
206 | else | ||
207 | { | ||
208 | llwarns << "Pushing stream to dead list: " << mCurrentInternetStreamp->getURL() << llendl; | ||
209 | mDeadStreams.push_back(mCurrentInternetStreamp); | ||
210 | } | ||
211 | mCurrentInternetStreamp = NULL; | ||
212 | //mURL.clear(); | ||
213 | } | ||
214 | } | ||
215 | |||
216 | void LLStreamingAudio_FMOD::pause(int pauseopt) | ||
217 | { | ||
218 | if (pauseopt < 0) | ||
219 | { | ||
220 | pauseopt = mCurrentInternetStreamp ? 1 : 0; | ||
221 | } | ||
222 | |||
223 | if (pauseopt) | ||
224 | { | ||
225 | if (mCurrentInternetStreamp) | ||
226 | { | ||
227 | stop(); | ||
228 | } | ||
229 | } | ||
230 | else | ||
231 | { | ||
232 | start(getURL()); | ||
233 | } | ||
234 | } | ||
235 | |||
236 | |||
237 | // A stream is "playing" if it has been requested to start. That | ||
238 | // doesn't necessarily mean audio is coming out of the speakers. | ||
239 | int LLStreamingAudio_FMOD::isPlaying() | ||
240 | { | ||
241 | if (mCurrentInternetStreamp) | ||
242 | { | ||
243 | return 1; // Active and playing | ||
244 | } | ||
245 | else if (!mURL.empty()) | ||
246 | { | ||
247 | return 2; // "Paused" | ||
248 | } | ||
249 | else | ||
250 | { | ||
251 | return 0; | ||
252 | } | ||
253 | } | ||
254 | |||
255 | |||
256 | F32 LLStreamingAudio_FMOD::getGain() | ||
257 | { | ||
258 | return mGain; | ||
259 | } | ||
260 | |||
261 | |||
262 | std::string LLStreamingAudio_FMOD::getURL() | ||
263 | { | ||
264 | return mURL; | ||
265 | } | ||
266 | |||
267 | |||
268 | void LLStreamingAudio_FMOD::setGain(F32 vol) | ||
269 | { | ||
270 | mGain = vol; | ||
271 | |||
272 | if (mFMODInternetStreamChannel != -1) | ||
273 | { | ||
274 | vol = llclamp(vol, 0.f, 1.f); | ||
275 | int vol_int = llround(vol * 255.f); | ||
276 | FSOUND_SetVolumeAbsolute(mFMODInternetStreamChannel, vol_int); | ||
277 | } | ||
278 | } | ||
279 | |||
280 | |||
281 | /////////////////////////////////////////////////////// | ||
282 | // manager of possibly-multiple internet audio streams | ||
283 | |||
284 | LLAudioStreamManagerFMOD::LLAudioStreamManagerFMOD(const std::string& url) : | ||
285 | mInternetStream(NULL), | ||
286 | mReady(false) | ||
287 | { | ||
288 | mInternetStreamURL = url; | ||
289 | mInternetStream = FSOUND_Stream_Open(url.c_str(), FSOUND_NORMAL | FSOUND_NONBLOCKING, 0, 0); | ||
290 | if (!mInternetStream) | ||
291 | { | ||
292 | llwarns << "Couldn't open fmod stream, error " | ||
293 | << FMOD_ErrorString(FSOUND_GetError()) | ||
294 | << llendl; | ||
295 | mReady = false; | ||
296 | return; | ||
297 | } | ||
298 | |||
299 | mReady = true; | ||
300 | } | ||
301 | |||
302 | int LLAudioStreamManagerFMOD::startStream() | ||
303 | { | ||
304 | // We need a live and opened stream before we try and play it. | ||
305 | if (!mInternetStream || getOpenState()) | ||
306 | { | ||
307 | llwarns << "No internet stream to start playing!" << llendl; | ||
308 | return -1; | ||
309 | } | ||
310 | |||
311 | // Make sure the stream is set to 2D mode. | ||
312 | FSOUND_Stream_SetMode(mInternetStream, FSOUND_2D); | ||
313 | |||
314 | return FSOUND_Stream_PlayEx(FSOUND_FREE, mInternetStream, NULL, true); | ||
315 | } | ||
316 | |||
317 | bool LLAudioStreamManagerFMOD::stopStream() | ||
318 | { | ||
319 | if (mInternetStream) | ||
320 | { | ||
321 | int read_percent = 0; | ||
322 | int status = 0; | ||
323 | int bitrate = 0; | ||
324 | unsigned int flags = 0x0; | ||
325 | FSOUND_Stream_Net_GetStatus(mInternetStream, &status, &read_percent, &bitrate, &flags); | ||
326 | |||
327 | bool close = true; | ||
328 | switch (status) | ||
329 | { | ||
330 | case FSOUND_STREAM_NET_CONNECTING: | ||
331 | close = false; | ||
332 | break; | ||
333 | case FSOUND_STREAM_NET_NOTCONNECTED: | ||
334 | case FSOUND_STREAM_NET_BUFFERING: | ||
335 | case FSOUND_STREAM_NET_READY: | ||
336 | case FSOUND_STREAM_NET_ERROR: | ||
337 | default: | ||
338 | close = true; | ||
339 | } | ||
340 | |||
341 | if (close) | ||
342 | { | ||
343 | FSOUND_Stream_Close(mInternetStream); | ||
344 | mInternetStream = NULL; | ||
345 | return true; | ||
346 | } | ||
347 | else | ||
348 | { | ||
349 | return false; | ||
350 | } | ||
351 | } | ||
352 | else | ||
353 | { | ||
354 | return true; | ||
355 | } | ||
356 | } | ||
357 | |||
358 | int LLAudioStreamManagerFMOD::getOpenState() | ||
359 | { | ||
360 | int open_state = FSOUND_Stream_GetOpenState(mInternetStream); | ||
361 | return open_state; | ||
362 | } | ||
diff --git a/linden/indra/llaudio/llstreamingaudio_fmod.h b/linden/indra/llaudio/llstreamingaudio_fmod.h new file mode 100644 index 0000000..968ab53 --- /dev/null +++ b/linden/indra/llaudio/llstreamingaudio_fmod.h | |||
@@ -0,0 +1,68 @@ | |||
1 | /** | ||
2 | * @file streamingaudio_fmod.h | ||
3 | * @author Tofu Linden | ||
4 | * @brief Definition of LLStreamingAudio_FMOD implementation | ||
5 | * | ||
6 | * $LicenseInfo:firstyear=2009&license=viewergpl$ | ||
7 | * | ||
8 | * Copyright (c) 2009, Linden Research, Inc. | ||
9 | * | ||
10 | * Second Life Viewer Source Code | ||
11 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
12 | * to you under the terms of the GNU General Public License, version 2.0 | ||
13 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
14 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
15 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
16 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
17 | * | ||
18 | * There are special exceptions to the terms and conditions of the GPL as | ||
19 | * it is applied to this Source Code. View the full text of the exception | ||
20 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
21 | * online at | ||
22 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
23 | * | ||
24 | * By copying, modifying or distributing this software, you acknowledge | ||
25 | * that you have read and understood your obligations described above, | ||
26 | * and agree to abide by those obligations. | ||
27 | * | ||
28 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
29 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
30 | * COMPLETENESS OR PERFORMANCE. | ||
31 | * $/LicenseInfo$ | ||
32 | */ | ||
33 | |||
34 | #ifndef LL_STREAMINGAUDIO_FMOD_H | ||
35 | #define LL_STREAMINGAUDIO_FMOD_H | ||
36 | |||
37 | #include "stdtypes.h" // from llcommon | ||
38 | |||
39 | #include "llstreamingaudio.h" | ||
40 | |||
41 | class LLAudioStreamManagerFMOD; | ||
42 | |||
43 | class LLStreamingAudio_FMOD : public LLStreamingAudioInterface | ||
44 | { | ||
45 | public: | ||
46 | LLStreamingAudio_FMOD(); | ||
47 | /*virtual*/ ~LLStreamingAudio_FMOD(); | ||
48 | |||
49 | /*virtual*/ void start(const std::string& url); | ||
50 | /*virtual*/ void stop(); | ||
51 | /*virtual*/ void pause(int pause); | ||
52 | /*virtual*/ void update(); | ||
53 | /*virtual*/ int isPlaying(); | ||
54 | /*virtual*/ void setGain(F32 vol); | ||
55 | /*virtual*/ F32 getGain(); | ||
56 | /*virtual*/ std::string getURL(); | ||
57 | |||
58 | private: | ||
59 | LLAudioStreamManagerFMOD *mCurrentInternetStreamp; | ||
60 | int mFMODInternetStreamChannel; | ||
61 | std::list<LLAudioStreamManagerFMOD *> mDeadStreams; | ||
62 | |||
63 | std::string mURL; | ||
64 | F32 mGain; | ||
65 | }; | ||
66 | |||
67 | |||
68 | #endif // LL_STREAMINGAUDIO_FMOD_H | ||
diff --git a/linden/indra/llaudio/vorbisdecode.cpp b/linden/indra/llaudio/llvorbisdecode.cpp index 4bf70f4..4bf70f4 100644 --- a/linden/indra/llaudio/vorbisdecode.cpp +++ b/linden/indra/llaudio/llvorbisdecode.cpp | |||
diff --git a/linden/indra/llaudio/vorbisdecode.h b/linden/indra/llaudio/llvorbisdecode.h index cb67c99..cb67c99 100644 --- a/linden/indra/llaudio/vorbisdecode.h +++ b/linden/indra/llaudio/llvorbisdecode.h | |||
diff --git a/linden/indra/llaudio/llvorbisencode.cpp b/linden/indra/llaudio/llvorbisencode.cpp new file mode 100644 index 0000000..a24394d --- /dev/null +++ b/linden/indra/llaudio/llvorbisencode.cpp | |||
@@ -0,0 +1,505 @@ | |||
1 | /** | ||
2 | * @file vorbisencode.cpp | ||
3 | * @brief Vorbis encoding routine routine for Indra. | ||
4 | * | ||
5 | * $LicenseInfo:firstyear=2000&license=viewergpl$ | ||
6 | * | ||
7 | * Copyright (c) 2000-2009, Linden Research, Inc. | ||
8 | * | ||
9 | * Second Life Viewer Source Code | ||
10 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
11 | * to you under the terms of the GNU General Public License, version 2.0 | ||
12 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
13 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
14 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
15 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
16 | * | ||
17 | * There are special exceptions to the terms and conditions of the GPL as | ||
18 | * it is applied to this Source Code. View the full text of the exception | ||
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
20 | * online at | ||
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
22 | * | ||
23 | * By copying, modifying or distributing this software, you acknowledge | ||
24 | * that you have read and understood your obligations described above, | ||
25 | * and agree to abide by those obligations. | ||
26 | * | ||
27 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
28 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
29 | * COMPLETENESS OR PERFORMANCE. | ||
30 | * $/LicenseInfo$ | ||
31 | */ | ||
32 | |||
33 | #include "linden_common.h" | ||
34 | |||
35 | #include "vorbis/vorbisenc.h" | ||
36 | |||
37 | #include "llvorbisencode.h" | ||
38 | #include "llerror.h" | ||
39 | #include "llrand.h" | ||
40 | #include "llmath.h" | ||
41 | #include "llapr.h" | ||
42 | |||
43 | //#if LL_DARWIN | ||
44 | // MBW -- XXX -- Getting rid of SecondLifeVorbis for now -- no fmod means no name collisions. | ||
45 | #if 0 | ||
46 | #include "VorbisFramework.h" | ||
47 | |||
48 | #define vorbis_analysis mac_vorbis_analysis | ||
49 | #define vorbis_analysis_headerout mac_vorbis_analysis_headerout | ||
50 | #define vorbis_analysis_init mac_vorbis_analysis_init | ||
51 | #define vorbis_encode_ctl mac_vorbis_encode_ctl | ||
52 | #define vorbis_encode_setup_init mac_vorbis_encode_setup_init | ||
53 | #define vorbis_encode_setup_managed mac_vorbis_encode_setup_managed | ||
54 | |||
55 | #define vorbis_info_init mac_vorbis_info_init | ||
56 | #define vorbis_info_clear mac_vorbis_info_clear | ||
57 | #define vorbis_comment_init mac_vorbis_comment_init | ||
58 | #define vorbis_comment_clear mac_vorbis_comment_clear | ||
59 | #define vorbis_block_init mac_vorbis_block_init | ||
60 | #define vorbis_block_clear mac_vorbis_block_clear | ||
61 | #define vorbis_dsp_clear mac_vorbis_dsp_clear | ||
62 | #define vorbis_analysis_buffer mac_vorbis_analysis_buffer | ||
63 | #define vorbis_analysis_wrote mac_vorbis_analysis_wrote | ||
64 | #define vorbis_analysis_blockout mac_vorbis_analysis_blockout | ||
65 | |||
66 | #define ogg_stream_packetin mac_ogg_stream_packetin | ||
67 | #define ogg_stream_init mac_ogg_stream_init | ||
68 | #define ogg_stream_flush mac_ogg_stream_flush | ||
69 | #define ogg_stream_pageout mac_ogg_stream_pageout | ||
70 | #define ogg_page_eos mac_ogg_page_eos | ||
71 | #define ogg_stream_clear mac_ogg_stream_clear | ||
72 | |||
73 | #endif | ||
74 | |||
75 | S32 check_for_invalid_wav_formats(const std::string& in_fname, std::string& error_msg) | ||
76 | { | ||
77 | U16 num_channels = 0; | ||
78 | U32 sample_rate = 0; | ||
79 | U32 bits_per_sample = 0; | ||
80 | U32 physical_file_size = 0; | ||
81 | U32 chunk_length = 0; | ||
82 | U32 raw_data_length = 0; | ||
83 | U32 bytes_per_sec = 0; | ||
84 | BOOL uncompressed_pcm = FALSE; | ||
85 | |||
86 | unsigned char wav_header[44]; /*Flawfinder: ignore*/ | ||
87 | |||
88 | error_msg.clear(); | ||
89 | |||
90 | //******************************** | ||
91 | LLAPRFile infile ; | ||
92 | infile.open(in_fname,LL_APR_RB, LLAPRFile::global); | ||
93 | //******************************** | ||
94 | if (!infile.getFileHandle()) | ||
95 | { | ||
96 | error_msg = "CannotUploadSoundFile"; | ||
97 | return(LLVORBISENC_SOURCE_OPEN_ERR); | ||
98 | } | ||
99 | |||
100 | infile.read(wav_header, 44); | ||
101 | physical_file_size = infile.seek(APR_END,0); | ||
102 | |||
103 | if (strncmp((char *)&(wav_header[0]),"RIFF",4)) | ||
104 | { | ||
105 | error_msg = "SoundFileNotRIFF"; | ||
106 | return(LLVORBISENC_WAV_FORMAT_ERR); | ||
107 | } | ||
108 | |||
109 | if (strncmp((char *)&(wav_header[8]),"WAVE",4)) | ||
110 | { | ||
111 | error_msg = "SoundFileNotRIFF"; | ||
112 | return(LLVORBISENC_WAV_FORMAT_ERR); | ||
113 | } | ||
114 | |||
115 | // parse the chunks | ||
116 | |||
117 | U32 file_pos = 12; // start at the first chunk (usually fmt but not always) | ||
118 | |||
119 | while ((file_pos + 8)< physical_file_size) | ||
120 | { | ||
121 | infile.seek(APR_SET,file_pos); | ||
122 | infile.read(wav_header, 44); | ||
123 | |||
124 | chunk_length = ((U32) wav_header[7] << 24) | ||
125 | + ((U32) wav_header[6] << 16) | ||
126 | + ((U32) wav_header[5] << 8) | ||
127 | + wav_header[4]; | ||
128 | |||
129 | // llinfos << "chunk found: '" << wav_header[0] << wav_header[1] << wav_header[2] << wav_header[3] << "'" << llendl; | ||
130 | |||
131 | if (!(strncmp((char *)&(wav_header[0]),"fmt ",4))) | ||
132 | { | ||
133 | if ((wav_header[8] == 0x01) && (wav_header[9] == 0x00)) | ||
134 | { | ||
135 | uncompressed_pcm = TRUE; | ||
136 | } | ||
137 | num_channels = ((U16) wav_header[11] << 8) + wav_header[10]; | ||
138 | sample_rate = ((U32) wav_header[15] << 24) | ||
139 | + ((U32) wav_header[14] << 16) | ||
140 | + ((U32) wav_header[13] << 8) | ||
141 | + wav_header[12]; | ||
142 | bits_per_sample = ((U16) wav_header[23] << 8) + wav_header[22]; | ||
143 | bytes_per_sec = ((U32) wav_header[19] << 24) | ||
144 | + ((U32) wav_header[18] << 16) | ||
145 | + ((U32) wav_header[17] << 8) | ||
146 | + wav_header[16]; | ||
147 | } | ||
148 | else if (!(strncmp((char *)&(wav_header[0]),"data",4))) | ||
149 | { | ||
150 | raw_data_length = chunk_length; | ||
151 | } | ||
152 | file_pos += (chunk_length + 8); | ||
153 | chunk_length = 0; | ||
154 | } | ||
155 | //**************** | ||
156 | infile.close(); | ||
157 | //**************** | ||
158 | |||
159 | if (!uncompressed_pcm) | ||
160 | { | ||
161 | error_msg = "SoundFileNotPCM"; | ||
162 | return(LLVORBISENC_PCM_FORMAT_ERR); | ||
163 | } | ||
164 | |||
165 | if ((num_channels < 1) || (num_channels > LLVORBIS_CLIP_MAX_CHANNELS)) | ||
166 | { | ||
167 | error_msg = "SoundFileInvalidChannelCount"; | ||
168 | return(LLVORBISENC_MULTICHANNEL_ERR); | ||
169 | } | ||
170 | |||
171 | if (sample_rate != LLVORBIS_CLIP_SAMPLE_RATE) | ||
172 | { | ||
173 | error_msg = "SoundFileInvalidSampleRate"; | ||
174 | return(LLVORBISENC_UNSUPPORTED_SAMPLE_RATE); | ||
175 | } | ||
176 | |||
177 | if ((bits_per_sample != 16) && (bits_per_sample != 8)) | ||
178 | { | ||
179 | error_msg = "SoundFileInvalidWordSize"; | ||
180 | return(LLVORBISENC_UNSUPPORTED_WORD_SIZE); | ||
181 | } | ||
182 | |||
183 | if (!raw_data_length) | ||
184 | { | ||
185 | error_msg = "SoundFileInvalidHeader"; | ||
186 | return(LLVORBISENC_CLIP_TOO_LONG); | ||
187 | } | ||
188 | |||
189 | F32 clip_length = (F32)raw_data_length/(F32)bytes_per_sec; | ||
190 | |||
191 | if (clip_length > LLVORBIS_CLIP_MAX_TIME) | ||
192 | { | ||
193 | error_msg = "SoundFileInvalidTooLong"; | ||
194 | return(LLVORBISENC_CLIP_TOO_LONG); | ||
195 | } | ||
196 | |||
197 | return(LLVORBISENC_NOERR); | ||
198 | } | ||
199 | |||
200 | S32 encode_vorbis_file(const std::string& in_fname, const std::string& out_fname) | ||
201 | { | ||
202 | #define READ_BUFFER 1024 | ||
203 | unsigned char readbuffer[READ_BUFFER*4+44]; /* out of the data segment, not the stack */ /*Flawfinder: ignore*/ | ||
204 | |||
205 | ogg_stream_state os; /* take physical pages, weld into a logical stream of packets */ | ||
206 | ogg_page og; /* one Ogg bitstream page. Vorbis packets are inside */ | ||
207 | ogg_packet op; /* one raw packet of data for decode */ | ||
208 | |||
209 | vorbis_info vi; /* struct that stores all the static vorbis bitstream settings */ | ||
210 | vorbis_comment vc; /* struct that stores all the user comments */ | ||
211 | |||
212 | vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */ | ||
213 | vorbis_block vb; /* local working space for packet->PCM decode */ | ||
214 | |||
215 | int eos=0; | ||
216 | int result; | ||
217 | |||
218 | U16 num_channels = 0; | ||
219 | U32 sample_rate = 0; | ||
220 | U32 bits_per_sample = 0; | ||
221 | |||
222 | S32 format_error = 0; | ||
223 | std::string error_msg; | ||
224 | if ((format_error = check_for_invalid_wav_formats(in_fname, error_msg))) | ||
225 | { | ||
226 | llwarns << error_msg << ": " << in_fname << llendl; | ||
227 | return(format_error); | ||
228 | } | ||
229 | |||
230 | #if 1 | ||
231 | unsigned char wav_header[44]; /*Flawfinder: ignore*/ | ||
232 | |||
233 | S32 data_left = 0; | ||
234 | |||
235 | LLAPRFile infile ; | ||
236 | infile.open(in_fname,LL_APR_RB, LLAPRFile::global); | ||
237 | if (!infile.getFileHandle()) | ||
238 | { | ||
239 | llwarns << "Couldn't open temporary ogg file for writing: " << in_fname | ||
240 | << llendl; | ||
241 | return(LLVORBISENC_SOURCE_OPEN_ERR); | ||
242 | } | ||
243 | |||
244 | LLAPRFile outfile ; | ||
245 | outfile.open(out_fname,LL_APR_WPB, LLAPRFile::global); | ||
246 | if (!outfile.getFileHandle()) | ||
247 | { | ||
248 | llwarns << "Couldn't open upload sound file for reading: " << in_fname | ||
249 | << llendl; | ||
250 | return(LLVORBISENC_DEST_OPEN_ERR); | ||
251 | } | ||
252 | |||
253 | // parse the chunks | ||
254 | U32 chunk_length = 0; | ||
255 | U32 file_pos = 12; // start at the first chunk (usually fmt but not always) | ||
256 | |||
257 | while (infile.eof() != APR_EOF) | ||
258 | { | ||
259 | infile.seek(APR_SET,file_pos); | ||
260 | infile.read(wav_header, 44); | ||
261 | |||
262 | chunk_length = ((U32) wav_header[7] << 24) | ||
263 | + ((U32) wav_header[6] << 16) | ||
264 | + ((U32) wav_header[5] << 8) | ||
265 | + wav_header[4]; | ||
266 | |||
267 | // llinfos << "chunk found: '" << wav_header[0] << wav_header[1] << wav_header[2] << wav_header[3] << "'" << llendl; | ||
268 | |||
269 | if (!(strncmp((char *)&(wav_header[0]),"fmt ",4))) | ||
270 | { | ||
271 | num_channels = ((U16) wav_header[11] << 8) + wav_header[10]; | ||
272 | sample_rate = ((U32) wav_header[15] << 24) | ||
273 | + ((U32) wav_header[14] << 16) | ||
274 | + ((U32) wav_header[13] << 8) | ||
275 | + wav_header[12]; | ||
276 | bits_per_sample = ((U16) wav_header[23] << 8) + wav_header[22]; | ||
277 | } | ||
278 | else if (!(strncmp((char *)&(wav_header[0]),"data",4))) | ||
279 | { | ||
280 | infile.seek(APR_SET,file_pos+8); | ||
281 | // leave the file pointer at the beginning of the data chunk data | ||
282 | data_left = chunk_length; | ||
283 | break; | ||
284 | } | ||
285 | file_pos += (chunk_length + 8); | ||
286 | chunk_length = 0; | ||
287 | } | ||
288 | |||
289 | |||
290 | /********** Encode setup ************/ | ||
291 | |||
292 | /* choose an encoding mode */ | ||
293 | /* (mode 0: 44kHz stereo uncoupled, roughly 128kbps VBR) */ | ||
294 | vorbis_info_init(&vi); | ||
295 | |||
296 | // always encode to mono | ||
297 | |||
298 | // SL-52913 & SL-53779 determined this quality level to be our 'good | ||
299 | // enough' general-purpose quality level with a nice low bitrate. | ||
300 | // Equivalent to oggenc -q0.5 | ||
301 | F32 quality = 0.05f; | ||
302 | // quality = (bitrate==128000 ? 0.4f : 0.1); | ||
303 | |||
304 | // if (vorbis_encode_init(&vi, /* num_channels */ 1 ,sample_rate, -1, bitrate, -1)) | ||
305 | if (vorbis_encode_init_vbr(&vi, /* num_channels */ 1 ,sample_rate, quality)) | ||
306 | // if (vorbis_encode_setup_managed(&vi,1,sample_rate,-1,bitrate,-1) || | ||
307 | // vorbis_encode_ctl(&vi,OV_ECTL_RATEMANAGE_AVG,NULL) || | ||
308 | // vorbis_encode_setup_init(&vi)) | ||
309 | { | ||
310 | llwarns << "unable to initialize vorbis codec at quality " << quality << llendl; | ||
311 | // llwarns << "unable to initialize vorbis codec at bitrate " << bitrate << llendl; | ||
312 | return(LLVORBISENC_DEST_OPEN_ERR); | ||
313 | } | ||
314 | |||
315 | /* add a comment */ | ||
316 | vorbis_comment_init(&vc); | ||
317 | // vorbis_comment_add(&vc,"Linden"); | ||
318 | |||
319 | /* set up the analysis state and auxiliary encoding storage */ | ||
320 | vorbis_analysis_init(&vd,&vi); | ||
321 | vorbis_block_init(&vd,&vb); | ||
322 | |||
323 | /* set up our packet->stream encoder */ | ||
324 | /* pick a random serial number; that way we can more likely build | ||
325 | chained streams just by concatenation */ | ||
326 | ogg_stream_init(&os, ll_rand()); | ||
327 | |||
328 | /* Vorbis streams begin with three headers; the initial header (with | ||
329 | most of the codec setup parameters) which is mandated by the Ogg | ||
330 | bitstream spec. The second header holds any comment fields. The | ||
331 | third header holds the bitstream codebook. We merely need to | ||
332 | make the headers, then pass them to libvorbis one at a time; | ||
333 | libvorbis handles the additional Ogg bitstream constraints */ | ||
334 | |||
335 | { | ||
336 | ogg_packet header; | ||
337 | ogg_packet header_comm; | ||
338 | ogg_packet header_code; | ||
339 | |||
340 | vorbis_analysis_headerout(&vd,&vc,&header,&header_comm,&header_code); | ||
341 | ogg_stream_packetin(&os,&header); /* automatically placed in its own | ||
342 | page */ | ||
343 | ogg_stream_packetin(&os,&header_comm); | ||
344 | ogg_stream_packetin(&os,&header_code); | ||
345 | |||
346 | /* We don't have to write out here, but doing so makes streaming | ||
347 | * much easier, so we do, flushing ALL pages. This ensures the actual | ||
348 | * audio data will start on a new page | ||
349 | */ | ||
350 | while(!eos){ | ||
351 | int result=ogg_stream_flush(&os,&og); | ||
352 | if(result==0)break; | ||
353 | outfile.write(og.header, og.header_len); | ||
354 | outfile.write(og.body, og.body_len); | ||
355 | } | ||
356 | |||
357 | } | ||
358 | |||
359 | |||
360 | while(!eos) | ||
361 | { | ||
362 | long bytes_per_sample = bits_per_sample/8; | ||
363 | |||
364 | long bytes=(long)infile.read(readbuffer,llclamp((S32)(READ_BUFFER*num_channels*bytes_per_sample),0,data_left)); /* stereo hardwired here */ | ||
365 | |||
366 | if (bytes==0) | ||
367 | { | ||
368 | /* end of file. this can be done implicitly in the mainline, | ||
369 | but it's easier to see here in non-clever fashion. | ||
370 | Tell the library we're at end of stream so that it can handle | ||
371 | the last frame and mark end of stream in the output properly */ | ||
372 | |||
373 | vorbis_analysis_wrote(&vd,0); | ||
374 | // eos = 1; | ||
375 | |||
376 | } | ||
377 | else | ||
378 | { | ||
379 | long i; | ||
380 | long samples; | ||
381 | int temp; | ||
382 | |||
383 | data_left -= bytes; | ||
384 | /* data to encode */ | ||
385 | |||
386 | /* expose the buffer to submit data */ | ||
387 | float **buffer=vorbis_analysis_buffer(&vd,READ_BUFFER); | ||
388 | |||
389 | i = 0; | ||
390 | samples = bytes / (num_channels * bytes_per_sample); | ||
391 | |||
392 | if (num_channels == 2) | ||
393 | { | ||
394 | if (bytes_per_sample == 2) | ||
395 | { | ||
396 | /* uninterleave samples */ | ||
397 | for(i=0; i<samples ;i++) | ||
398 | { | ||
399 | temp = ((signed char *)readbuffer)[i*4+1]; /*Flawfinder: ignore*/ | ||
400 | temp += ((signed char *)readbuffer)[i*4+3]; /*Flawfinder: ignore*/ | ||
401 | temp <<= 8; | ||
402 | temp += readbuffer[i*4]; | ||
403 | temp += readbuffer[i*4+2]; | ||
404 | |||
405 | buffer[0][i] = ((float)temp) / 65536.f; | ||
406 | } | ||
407 | } | ||
408 | else // presume it's 1 byte per which is unsigned (F#@%ing wav "standard") | ||
409 | { | ||
410 | /* uninterleave samples */ | ||
411 | for(i=0; i<samples ;i++) | ||
412 | { | ||
413 | temp = readbuffer[i*2+0]; | ||
414 | temp += readbuffer[i*2+1]; | ||
415 | temp -= 256; | ||
416 | buffer[0][i] = ((float)temp) / 256.f; | ||
417 | } | ||
418 | } | ||
419 | } | ||
420 | else if (num_channels == 1) | ||
421 | { | ||
422 | if (bytes_per_sample == 2) | ||
423 | { | ||
424 | for(i=0; i < samples ;i++) | ||
425 | { | ||
426 | temp = ((signed char*)readbuffer)[i*2+1]; | ||
427 | temp <<= 8; | ||
428 | temp += readbuffer[i*2]; | ||
429 | buffer[0][i] = ((float)temp) / 32768.f; | ||
430 | } | ||
431 | } | ||
432 | else // presume it's 1 byte per which is unsigned (F#@%ing wav "standard") | ||
433 | { | ||
434 | for(i=0; i < samples ;i++) | ||
435 | { | ||
436 | temp = readbuffer[i]; | ||
437 | temp -= 128; | ||
438 | buffer[0][i] = ((float)temp) / 128.f; | ||
439 | } | ||
440 | } | ||
441 | } | ||
442 | |||
443 | /* tell the library how much we actually submitted */ | ||
444 | vorbis_analysis_wrote(&vd,i); | ||
445 | } | ||
446 | |||
447 | /* vorbis does some data preanalysis, then divvies up blocks for | ||
448 | more involved (potentially parallel) processing. Get a single | ||
449 | block for encoding now */ | ||
450 | while(vorbis_analysis_blockout(&vd,&vb)==1) | ||
451 | { | ||
452 | |||
453 | /* analysis */ | ||
454 | /* Do the main analysis, creating a packet */ | ||
455 | vorbis_analysis(&vb, NULL); | ||
456 | vorbis_bitrate_addblock(&vb); | ||
457 | |||
458 | while(vorbis_bitrate_flushpacket(&vd, &op)) | ||
459 | { | ||
460 | |||
461 | /* weld the packet into the bitstream */ | ||
462 | ogg_stream_packetin(&os,&op); | ||
463 | |||
464 | /* write out pages (if any) */ | ||
465 | while(!eos) | ||
466 | { | ||
467 | result = ogg_stream_pageout(&os,&og); | ||
468 | |||
469 | if(result==0) | ||
470 | break; | ||
471 | |||
472 | outfile.write(og.header, og.header_len); | ||
473 | outfile.write(og.body, og.body_len); | ||
474 | |||
475 | /* this could be set above, but for illustrative purposes, I do | ||
476 | it here (to show that vorbis does know where the stream ends) */ | ||
477 | |||
478 | if(ogg_page_eos(&og)) | ||
479 | eos=1; | ||
480 | |||
481 | } | ||
482 | } | ||
483 | } | ||
484 | } | ||
485 | |||
486 | |||
487 | |||
488 | /* clean up and exit. vorbis_info_clear() must be called last */ | ||
489 | |||
490 | ogg_stream_clear(&os); | ||
491 | vorbis_block_clear(&vb); | ||
492 | vorbis_dsp_clear(&vd); | ||
493 | vorbis_comment_clear(&vc); | ||
494 | vorbis_info_clear(&vi); | ||
495 | |||
496 | /* ogg_page and ogg_packet structs always point to storage in | ||
497 | libvorbis. They're never freed or manipulated directly */ | ||
498 | |||
499 | // fprintf(stderr,"Vorbis encoding: Done.\n"); | ||
500 | llinfos << "Vorbis encoding: Done." << llendl; | ||
501 | |||
502 | #endif | ||
503 | return(LLVORBISENC_NOERR); | ||
504 | |||
505 | } | ||
diff --git a/linden/indra/llaudio/vorbisencode.h b/linden/indra/llaudio/llvorbisencode.h index ff5ce3a..2825a30 100644 --- a/linden/indra/llaudio/vorbisencode.h +++ b/linden/indra/llaudio/llvorbisencode.h | |||
@@ -45,6 +45,17 @@ const S32 LLVORBISENC_UNSUPPORTED_SAMPLE_RATE = 8; // unsupported sample ra | |||
45 | const S32 LLVORBISENC_UNSUPPORTED_WORD_SIZE = 9; // unsupported word size | 45 | const S32 LLVORBISENC_UNSUPPORTED_WORD_SIZE = 9; // unsupported word size |
46 | const S32 LLVORBISENC_CLIP_TOO_LONG = 10; // source file is too long | 46 | const S32 LLVORBISENC_CLIP_TOO_LONG = 10; // source file is too long |
47 | 47 | ||
48 | const F32 LLVORBIS_CLIP_MAX_TIME = 10.0f; | ||
49 | const U8 LLVORBIS_CLIP_MAX_CHANNELS = 2; | ||
50 | const U32 LLVORBIS_CLIP_SAMPLE_RATE = 44100; | ||
51 | const U32 LLVORBIS_CLIP_MAX_SAMPLES_PER_CHANNEL = (U32)(LLVORBIS_CLIP_MAX_TIME * LLVORBIS_CLIP_SAMPLE_RATE); | ||
52 | const U32 LLVORBIS_CLIP_MAX_SAMPLES = LLVORBIS_CLIP_MAX_SAMPLES_PER_CHANNEL * LLVORBIS_CLIP_MAX_CHANNELS; | ||
53 | const size_t LLVORBIS_CLIP_MAX_SAMPLE_DATA = LLVORBIS_CLIP_MAX_SAMPLES * 2; // 2 = 16-bit | ||
54 | |||
55 | // Treat anything this long as a bad asset. A little fudge factor at the end: | ||
56 | // Make that a lot of fudge factor. We're allowing 30 sec for now - 3x legal upload | ||
57 | const size_t LLVORBIS_CLIP_REJECT_SAMPLES = LLVORBIS_CLIP_MAX_SAMPLES * 3; | ||
58 | const size_t LLVORBIS_CLIP_REJECT_SIZE = LLVORBIS_CLIP_MAX_SAMPLE_DATA * 3; | ||
48 | 59 | ||
49 | S32 check_for_invalid_wav_formats(const std::string& in_fname, std::string& error_msg); | 60 | S32 check_for_invalid_wav_formats(const std::string& in_fname, std::string& error_msg); |
50 | S32 encode_vorbis_file(const std::string& in_fname, const std::string& out_fname); | 61 | S32 encode_vorbis_file(const std::string& in_fname, const std::string& out_fname); |
diff --git a/linden/indra/llaudio/windgen.h b/linden/indra/llaudio/llwindgen.h index 847bfa6..847bfa6 100644 --- a/linden/indra/llaudio/windgen.h +++ b/linden/indra/llaudio/llwindgen.h | |||