aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llaudio
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--linden/indra/llaudio/CMakeLists.txt43
-rw-r--r--linden/indra/llaudio/listener.cpp153
-rw-r--r--linden/indra/llaudio/listener.h80
-rw-r--r--linden/indra/llaudio/listener_ds3d.h76
-rw-r--r--linden/indra/llaudio/listener_fmod.cpp143
-rw-r--r--linden/indra/llaudio/listener_fmod.h67
-rw-r--r--linden/indra/llaudio/llaudiodecodemgr.cpp62
-rw-r--r--linden/indra/llaudio/llaudioengine.cpp (renamed from linden/indra/llaudio/audioengine.cpp)303
-rw-r--r--linden/indra/llaudio/llaudioengine.h (renamed from linden/indra/llaudio/audioengine.h)57
-rw-r--r--linden/indra/llaudio/llaudioengine_fmod.cpp (renamed from linden/indra/llaudio/audioengine_fmod.cpp)361
-rw-r--r--linden/indra/llaudio/llaudioengine_fmod.h (renamed from linden/indra/llaudio/audioengine_fmod.h)42
-rw-r--r--linden/indra/llaudio/llaudioengine_openal.cpp (renamed from linden/indra/llaudio/audioengine_openal.cpp)40
-rw-r--r--linden/indra/llaudio/llaudioengine_openal.h (renamed from linden/indra/llaudio/audioengine_openal.h)7
-rw-r--r--linden/indra/llaudio/lllistener.cpp142
-rw-r--r--linden/indra/llaudio/lllistener.h78
-rw-r--r--linden/indra/llaudio/lllistener_ds3d.h74
-rw-r--r--linden/indra/llaudio/lllistener_fmod.cpp131
-rw-r--r--linden/indra/llaudio/lllistener_fmod.h64
-rw-r--r--linden/indra/llaudio/lllistener_openal.cpp (renamed from linden/indra/llaudio/listener_openal.cpp)13
-rw-r--r--linden/indra/llaudio/lllistener_openal.h (renamed from linden/indra/llaudio/listener_openal.h)8
-rw-r--r--linden/indra/llaudio/llstreamingaudio.h56
-rw-r--r--linden/indra/llaudio/llstreamingaudio_fmod.cpp362
-rw-r--r--linden/indra/llaudio/llstreamingaudio_fmod.h68
-rw-r--r--linden/indra/llaudio/llvorbisdecode.cpp (renamed from linden/indra/llaudio/vorbisdecode.cpp)0
-rw-r--r--linden/indra/llaudio/llvorbisdecode.h (renamed from linden/indra/llaudio/vorbisdecode.h)0
-rw-r--r--linden/indra/llaudio/llvorbisencode.cpp505
-rw-r--r--linden/indra/llaudio/llvorbisencode.h (renamed from linden/indra/llaudio/vorbisencode.h)11
-rw-r--r--linden/indra/llaudio/llwindgen.h (renamed from linden/indra/llaudio/windgen.h)0
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
6include(00-Common) 6include(00-Common)
7include(LLAudio)
7include(Audio) 8include(Audio)
8include(OPENAL) 9include(OPENAL)
9include(FMOD) 10include(FMOD)
@@ -12,9 +13,9 @@ include(LLCommon)
12include(LLMath) 13include(LLMath)
13include(LLMessage) 14include(LLMessage)
14include(LLVFS) 15include(LLVFS)
15include(LLMedia)
16 16
17include_directories( 17include_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
33set(llaudio_SOURCE_FILES 32set(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
41set(llaudio_HEADER_FILES 40set(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
52if (FMOD) 51if (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
71if (OPENAL) 72if (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 )
81endif (OPENAL) 82endif (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//-----------------------------------------------------------------------
43LLListener::LLListener()
44{
45 init();
46}
47
48//-----------------------------------------------------------------------
49LLListener::~LLListener()
50{
51}
52
53//-----------------------------------------------------------------------
54void LLListener::init(void)
55{
56 mPosition.zeroVec();
57 mListenAt.setVec(DEFAULT_AT);
58 mListenUp.setVec(DEFAULT_UP);
59 mVelocity.zeroVec();
60}
61
62//-----------------------------------------------------------------------
63void LLListener::translate(LLVector3 offset)
64{
65 mPosition += offset;
66}
67
68//-----------------------------------------------------------------------
69void LLListener::setPosition(LLVector3 pos)
70{
71 mPosition = pos;
72}
73
74//-----------------------------------------------------------------------
75LLVector3 LLListener::getPosition(void)
76{
77 return(mPosition);
78}
79
80//-----------------------------------------------------------------------
81LLVector3 LLListener::getAt(void)
82{
83 return(mListenAt);
84}
85
86//-----------------------------------------------------------------------
87LLVector3 LLListener::getUp(void)
88{
89 return(mListenUp);
90}
91
92//-----------------------------------------------------------------------
93void LLListener::setVelocity(LLVector3 vel)
94{
95 mVelocity = vel;
96}
97
98//-----------------------------------------------------------------------
99void LLListener::orient(LLVector3 up, LLVector3 at)
100{
101 mListenUp = up;
102 mListenAt = at;
103}
104
105//-----------------------------------------------------------------------
106void 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//-----------------------------------------------------------------------
117void LLListener::setDopplerFactor(F32 factor)
118{
119}
120
121//-----------------------------------------------------------------------
122F32 LLListener::getDopplerFactor()
123{
124 return (1.f);
125}
126
127//-----------------------------------------------------------------------
128void LLListener::setDistanceFactor(F32 factor)
129{
130}
131
132//-----------------------------------------------------------------------
133F32 LLListener::getDistanceFactor()
134{
135 return (1.f);
136}
137
138//-----------------------------------------------------------------------
139void LLListener::setRolloffFactor(F32 factor)
140{
141}
142
143//-----------------------------------------------------------------------
144F32 LLListener::getRolloffFactor()
145{
146 return (1.f);
147}
148
149//-----------------------------------------------------------------------
150void 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
38class 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
43class 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//-----------------------------------------------------------------------
42LLListener_FMOD::LLListener_FMOD()
43{
44 init();
45}
46
47//-----------------------------------------------------------------------
48LLListener_FMOD::~LLListener_FMOD()
49{
50}
51
52//-----------------------------------------------------------------------
53void 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//-----------------------------------------------------------------------
63void 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//-----------------------------------------------------------------------
71void 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//-----------------------------------------------------------------------
79void 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//-----------------------------------------------------------------------
87void 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//-----------------------------------------------------------------------
101void LLListener_FMOD::commitDeferredChanges()
102{
103 FSOUND_Update();
104}
105
106
107void LLListener_FMOD::setRolloffFactor(F32 factor)
108{
109 mRolloffFactor = factor;
110 FSOUND_3D_SetRolloffFactor(factor);
111}
112
113
114F32 LLListener_FMOD::getRolloffFactor()
115{
116 return mRolloffFactor;
117}
118
119
120void LLListener_FMOD::setDopplerFactor(F32 factor)
121{
122 mDopplerFactor = factor;
123 FSOUND_3D_SetDopplerFactor(factor);
124}
125
126
127F32 LLListener_FMOD::getDopplerFactor()
128{
129 return mDopplerFactor;
130}
131
132
133void LLListener_FMOD::setDistanceFactor(F32 factor)
134{
135 mDistanceFactor = factor;
136 FSOUND_3D_SetDistanceFactor(factor);
137}
138
139
140F32 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
39class 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
49extern LLAudioEngine *gAudiop; 49extern 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)
55extern void request_sound(const LLUUID &sound_guid); 53extern void request_sound(const LLUUID &sound_guid);
@@ -72,6 +70,15 @@ LLAudioEngine::~LLAudioEngine()
72{ 70{
73} 71}
74 72
73LLStreamingAudioInterface* LLAudioEngine::getStreamingAudioImpl()
74{
75 return mStreamingAudioImpl;
76}
77
78void LLAudioEngine::setStreamingAudioImpl(LLStreamingAudioInterface *impl)
79{
80 mStreamingAudioImpl = impl;
81}
75 82
76void LLAudioEngine::setDefaults() 83void 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)
180LLMediaBase::EStatus LLAudioEngine::getStatus()
181{
182 return mStatus;
183} 175}
184 176
185 177
186// virtual 178// virtual
187void LLAudioEngine::startInternetStream(const std::string& url) 179void 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
238void LLAudioEngine::stopInternetStream() 187void 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
256void LLAudioEngine::pauseInternetStream(int pause) 194void 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
279void LLAudioEngine::updateInternetStream() 201void LLAudioEngine::updateInternetStream()
280{ 202{
281 if (mInternetStreamMedia) 203 if (mStreamingAudioImpl)
282 mInternetStreamMedia->updateMedia(); 204 mStreamingAudioImpl->update();
283} 205}
284 206
285// virtual 207// virtual
286int LLAudioEngine::isInternetStreamPlaying() 208int 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
305void LLAudioEngine::getInternetStreamInfo(char* artist, char* title)
306{
307 artist[0] = 0;
308 title[0] = 0;
309}
310 216
311// virtual 217// virtual
312void LLAudioEngine::setInternetStreamGain(F32 vol) 218void 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
325const std::string& LLAudioEngine::getInternetStreamURL() 225std::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
673LLAudioBuffer *LLAudioEngine::getFreeBuffer() 569LLAudioBuffer * 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
823void LLAudioEngine::setMuted(bool muted) 719void 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
830void LLAudioEngine::setMasterGain(const F32 gain) 729void 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
836F32 LLAudioEngine::getMasterGain() 740F32 LLAudioEngine::getMasterGain()
@@ -852,7 +756,10 @@ F32 LLAudioEngine::getSecondaryGain(S32 type)
852 756
853F32 LLAudioEngine::getInternetStreamGain() 757F32 LLAudioEngine::getInternetStreamGain()
854{ 758{
855 return mInternetStreamGain; 759 if (mStreamingAudioImpl)
760 return mStreamingAudioImpl->getGain();
761 else
762 return 1.0f;
856} 763}
857 764
858void LLAudioEngine::setMaxWindGain(F32 gain) 765void 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
1023void LLAudioEngine::setDistanceFactor(F32 factor)
1024{
1025 if (mListenerp)
1026 {
1027 mListenerp->setDistanceFactor(factor);
1028 }
1029}
1030
1031
1032F32 LLAudioEngine::getDistanceFactor()
1033{
1034 if (mListenerp)
1035 {
1036 return mListenerp->getDistanceFactor();
1037 }
1038 else
1039 {
1040 return 0.f;
1041 }
1042}
1043
1044
1045void LLAudioEngine::setRolloffFactor(F32 factor) 929void 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
1073LLAudioSource *LLAudioEngine::findAudioSource(const LLUUID &source_id) 957LLAudioSource * 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
1089LLAudioData *LLAudioEngine::getAudioData(const LLUUID &audio_uuid) 973LLAudioData * 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
1153void LLAudioEngine::startNextTransfer() 1037void 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
1501bool LLAudioSource::play(const LLUUID &audio_uuid) 1390bool 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
1546bool LLAudioSource::isDone() 1443bool 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
1699LLAudioData *LLAudioSource::getCurrentData() 1596LLAudioData * LLAudioSource::getCurrentData()
1700{ 1597{
1701 return mCurrentDatap; 1598 return mCurrentDatap;
1702} 1599}
1703 1600
1704LLAudioData *LLAudioSource::getQueuedData() 1601LLAudioData * LLAudioSource::getQueuedData()
1705{ 1602{
1706 return mQueuedDatap; 1603 return mQueuedDatap;
1707} 1604}
1708 1605
1709LLAudioBuffer *LLAudioSource::getCurrentBuffer() 1606LLAudioBuffer * LLAudioSource::getCurrentBuffer()
1710{ 1607{
1711 if (!mCurrentDatap) 1608 if (!mCurrentDatap)
1712 { 1609 {
@@ -1737,7 +1634,7 @@ LLAudioChannel::LLAudioChannel() :
1737LLAudioChannel::~LLAudioChannel() 1634LLAudioChannel::~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
1749void LLAudioChannel::setSource(LLAudioSource *sourcep) 1646void 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
51class LLMediaBase;
52 48
53const F32 LL_WIND_UPDATE_INTERVAL = 0.1f; 49const F32 LL_WIND_UPDATE_INTERVAL = 0.1f;
54const F32 LL_ROLLOFF_MULTIPLIER_UNDER_WATER = 5.f; // How much sounds are weaker under water 50const F32 LL_ROLLOFF_MULTIPLIER_UNDER_WATER = 5.f; // How much sounds are weaker under water
@@ -75,7 +71,7 @@ class LLAudioData;
75class LLAudioChannel; 71class LLAudioChannel;
76class LLAudioChannelOpenAL; 72class LLAudioChannelOpenAL;
77class LLAudioBuffer; 73class LLAudioBuffer;
78 74class 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; }
190public: 184public:
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
259private: 248private:
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
49extern "C" { 53extern "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" {
53FSOUND_DSPUNIT *gWindDSP = NULL; 57FSOUND_DSPUNIT *gWindDSP = NULL;
54 58
55 59
56// Safe strcpy
57#if 0 //(unused) //LL_WINDOWS || LL_LINUX
58static 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
80LLAudioEngine_FMOD::LLAudioEngine_FMOD() 60LLAudioEngine_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
94bool LLAudioEngine_FMOD::init(const S32 num_channels, void* userdata) 72bool 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
299LLAudioBuffer *LLAudioEngine_FMOD::createBuffer() 277LLAudioBuffer * LLAudioEngine_FMOD::createBuffer()
300{ 278{
301 return new LLAudioBufferFMOD(); 279 return new LLAudioBufferFMOD();
302} 280}
303 281
304 282
305LLAudioChannel *LLAudioEngine_FMOD::createChannel() 283LLAudioChannel * 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//---------------------------------------------------------------------------
759void 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
776void 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
800signed 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
824void 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
903void 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
929void 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.
952int 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
969void 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
982LLAudioStreamFMOD::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
1000int 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
1015bool 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
1056int LLAudioStreamFMOD::getOpenState()
1057{
1058 int open_state = FSOUND_Stream_GetOpenState(mInternetStream);
1059 return open_state;
1060}
1061
1062void * F_CALLBACKAPI windCallback(void *originalbuffer, void *newbuffer, int length, void* userdata) 735void * 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
43class LLAudioStreamFMOD; 43class LLAudioStreamManagerFMOD;
44 44
45class LLAudioEngine_FMOD : public LLAudioEngine 45class 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:
83protected: 74protected:
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
143class LLAudioStreamFMOD
144{
145public:
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();
154protected:
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
41static const float WIND_BUFFER_SIZE_SEC = 0.05f; // 1/20th sec
42
41LLAudioEngine_OpenAL::LLAudioEngine_OpenAL() 43LLAudioEngine_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
58static 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
84bool LLAudioEngine_OpenAL::init(const S32 num_channels, void* userdata) 61bool 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
44class LLAudioEngine_OpenAL : public LLAudioEngine 43class 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//-----------------------------------------------------------------------
43LLListener::LLListener()
44{
45 init();
46}
47
48//-----------------------------------------------------------------------
49LLListener::~LLListener()
50{
51}
52
53//-----------------------------------------------------------------------
54void LLListener::init(void)
55{
56 mPosition.zeroVec();
57 mListenAt.setVec(DEFAULT_AT);
58 mListenUp.setVec(DEFAULT_UP);
59 mVelocity.zeroVec();
60}
61
62//-----------------------------------------------------------------------
63void LLListener::translate(LLVector3 offset)
64{
65 mPosition += offset;
66}
67
68//-----------------------------------------------------------------------
69void LLListener::setPosition(LLVector3 pos)
70{
71 mPosition = pos;
72}
73
74//-----------------------------------------------------------------------
75LLVector3 LLListener::getPosition(void)
76{
77 return(mPosition);
78}
79
80//-----------------------------------------------------------------------
81LLVector3 LLListener::getAt(void)
82{
83 return(mListenAt);
84}
85
86//-----------------------------------------------------------------------
87LLVector3 LLListener::getUp(void)
88{
89 return(mListenUp);
90}
91
92//-----------------------------------------------------------------------
93void LLListener::setVelocity(LLVector3 vel)
94{
95 mVelocity = vel;
96}
97
98//-----------------------------------------------------------------------
99void LLListener::orient(LLVector3 up, LLVector3 at)
100{
101 mListenUp = up;
102 mListenAt = at;
103}
104
105//-----------------------------------------------------------------------
106void 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//-----------------------------------------------------------------------
117void LLListener::setDopplerFactor(F32 factor)
118{
119}
120
121//-----------------------------------------------------------------------
122F32 LLListener::getDopplerFactor()
123{
124 return (1.f);
125}
126
127//-----------------------------------------------------------------------
128void LLListener::setRolloffFactor(F32 factor)
129{
130}
131
132//-----------------------------------------------------------------------
133F32 LLListener::getRolloffFactor()
134{
135 return (1.f);
136}
137
138//-----------------------------------------------------------------------
139void 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
38class 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
43class 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//-----------------------------------------------------------------------
42LLListener_FMOD::LLListener_FMOD()
43{
44 init();
45}
46
47//-----------------------------------------------------------------------
48LLListener_FMOD::~LLListener_FMOD()
49{
50}
51
52//-----------------------------------------------------------------------
53void LLListener_FMOD::init(void)
54{
55 // do inherited
56 LLListener::init();
57 mDopplerFactor = 1.0f;
58 mRolloffFactor = 1.0f;
59}
60
61//-----------------------------------------------------------------------
62void 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//-----------------------------------------------------------------------
70void 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//-----------------------------------------------------------------------
78void 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//-----------------------------------------------------------------------
86void 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//-----------------------------------------------------------------------
100void LLListener_FMOD::commitDeferredChanges()
101{
102 FSOUND_Update();
103}
104
105
106void LLListener_FMOD::setRolloffFactor(F32 factor)
107{
108 mRolloffFactor = factor;
109 FSOUND_3D_SetRolloffFactor(factor);
110}
111
112
113F32 LLListener_FMOD::getRolloffFactor()
114{
115 return mRolloffFactor;
116}
117
118
119void LLListener_FMOD::setDopplerFactor(F32 factor)
120{
121 mDopplerFactor = factor;
122 FSOUND_3D_SetDopplerFactor(factor);
123}
124
125
126F32 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
39class 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
39LLListener_OpenAL::LLListener_OpenAL() 39LLListener_OpenAL::LLListener_OpenAL()
40{ 40{
@@ -114,12 +114,3 @@ F32 LLListener_OpenAL::getRolloffFactor()
114} 114}
115 115
116 116
117void LLListener_OpenAL::setDistanceFactor(F32 factor)
118{
119 mDistanceFactor = factor;
120}
121
122F32 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
43class LLListener_OpenAL : public LLListener 42class 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.
40class 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
43class LLAudioStreamManagerFMOD
44{
45public:
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();
54protected:
55 FSOUND_STREAM* mInternetStream;
56 bool mReady;
57
58 std::string mInternetStreamURL;
59};
60
61
62
63//---------------------------------------------------------------------------
64// Internet Streaming
65//---------------------------------------------------------------------------
66LLStreamingAudio_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
85LLStreamingAudio_FMOD::~LLStreamingAudio_FMOD()
86{
87 // nothing interesting/safe to do.
88}
89
90
91void 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
116void 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
190void 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
216void 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.
239int 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
256F32 LLStreamingAudio_FMOD::getGain()
257{
258 return mGain;
259}
260
261
262std::string LLStreamingAudio_FMOD::getURL()
263{
264 return mURL;
265}
266
267
268void 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
284LLAudioStreamManagerFMOD::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
302int 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
317bool 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
358int 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
41class LLAudioStreamManagerFMOD;
42
43class 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
58private:
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
75S32 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
200S32 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
45const S32 LLVORBISENC_UNSUPPORTED_WORD_SIZE = 9; // unsupported word size 45const S32 LLVORBISENC_UNSUPPORTED_WORD_SIZE = 9; // unsupported word size
46const S32 LLVORBISENC_CLIP_TOO_LONG = 10; // source file is too long 46const S32 LLVORBISENC_CLIP_TOO_LONG = 10; // source file is too long
47 47
48const F32 LLVORBIS_CLIP_MAX_TIME = 10.0f;
49const U8 LLVORBIS_CLIP_MAX_CHANNELS = 2;
50const U32 LLVORBIS_CLIP_SAMPLE_RATE = 44100;
51const U32 LLVORBIS_CLIP_MAX_SAMPLES_PER_CHANNEL = (U32)(LLVORBIS_CLIP_MAX_TIME * LLVORBIS_CLIP_SAMPLE_RATE);
52const U32 LLVORBIS_CLIP_MAX_SAMPLES = LLVORBIS_CLIP_MAX_SAMPLES_PER_CHANNEL * LLVORBIS_CLIP_MAX_CHANNELS;
53const 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
57const size_t LLVORBIS_CLIP_REJECT_SAMPLES = LLVORBIS_CLIP_MAX_SAMPLES * 3;
58const size_t LLVORBIS_CLIP_REJECT_SIZE = LLVORBIS_CLIP_MAX_SAMPLE_DATA * 3;
48 59
49S32 check_for_invalid_wav_formats(const std::string& in_fname, std::string& error_msg); 60S32 check_for_invalid_wav_formats(const std::string& in_fname, std::string& error_msg);
50S32 encode_vorbis_file(const std::string& in_fname, const std::string& out_fname); 61S32 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