1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2010 Matt RAYKOWSKI (sfb) <matt.raykowski@gmail.com>
6 // Copyright (C) 2012 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
8 // This program is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU Affero General Public License as
10 // published by the Free Software Foundation, either version 3 of the
11 // License, or (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU Affero General Public License for more details.
18 // You should have received a copy of the GNU Affero General Public License
19 // along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "nel/sound/background_sound_manager.h"
23 #include "nel/sound/background_source.h"
26 using namespace NLMISC
;
32 CBackgroundSource::CBackgroundSource(CBackgroundSound
*backgroundSound
, bool spawn
, TSpawnEndCallback cb
, void *cbUserParam
, NL3D::CCluster
*cluster
, CGroupController
*groupController
)
33 : CSourceCommon(backgroundSound
, spawn
, cb
, cbUserParam
, cluster
, groupController
)
35 _BackgroundSound
= backgroundSound
;
38 CBackgroundSource::~CBackgroundSource()
44 TSoundId
CBackgroundSource::getSound()
49 void CBackgroundSource::setGain( float gain
)
51 CSourceCommon::setGain(gain
);
53 std::vector
<TSubSource
>::iterator
first(_Sources
.begin()), last(_Sources
.end());
54 for (; first
!= last
; ++first
)
56 if (first
->Source
!= 0)
58 first
->Source
->setGain(first
->Source
->getSound()->getGain() * gain
);
59 first
->Source
->setRelativeGain(_Gain
);
63 void CBackgroundSource::setRelativeGain( float gain
)
65 CSourceCommon::setRelativeGain(gain
);
67 std::vector
<TSubSource
>::iterator
first(_Sources
.begin()), last(_Sources
.end());
68 for (; first
!= last
; ++first
)
70 if (first
->Source
!= 0)
71 first
->Source
->setRelativeGain(_Gain
);
75 void CBackgroundSource::setPos( const NLMISC::CVector
& pos
)
77 CSourceCommon::setPos(pos
);
79 std::vector
<TSubSource
>::iterator
first(_Sources
.begin()), last(_Sources
.end());
80 for (; first
!= last
; ++first
)
82 if (first
->Source
!= 0)
83 first
->Source
->setPos(pos
);
87 void CBackgroundSource::setVelocity( const NLMISC::CVector
& vel
)
89 CSourceCommon::setVelocity(vel
);
91 std::vector
<TSubSource
>::iterator
first(_Sources
.begin()), last(_Sources
.end());
92 for (; first
!= last
; ++first
)
94 if (first
->Source
!= 0)
95 first
->Source
->setVelocity(vel
);
98 void CBackgroundSource::setDirection( const NLMISC::CVector
& dir
)
100 CSourceCommon::setDirection(dir
);
102 std::vector
<TSubSource
>::iterator
first(_Sources
.begin()), last(_Sources
.end());
103 for (; first
!= last
; ++first
)
105 if (first
->Source
!= 0)
106 first
->Source
->setDirection(dir
);
112 void CBackgroundSource::play()
117 CAudioMixerUser
*mixer
= CAudioMixerUser::instance();
119 const vector
<CBackgroundSound::TSoundInfo
> &sounds
= _BackgroundSound
->getSounds();
120 vector
<CBackgroundSound::TSoundInfo
>::const_iterator
first(sounds
.begin()), last(sounds
.end());
122 for (; first
!= last
; ++first
)
124 TSubSource subSource
;
125 subSource
.Source
= mixer
->createSource(first
->SoundName
, false, 0, 0, _Cluster
, NULL
, _GroupController
);
126 if (subSource
.Source
!= NULL
)
127 subSource
.Source
->setPriority(_Priority
);
128 subSource
.Filter
= first
->Filter
;
129 subSource
.Status
= SUB_STATUS_STOP
;
130 _Sources
.push_back(subSource
);
133 updateFilterValues(mixer
->getBackgroundSoundManager()->getFilterValues());
135 CSourceCommon::play();
138 void CBackgroundSource::stop()
142 while (!_Sources
.empty())
144 TSubSource
&subSource
= _Sources
.back();
145 if (subSource
.Source
!= NULL
)
147 delete subSource
.Source
;
153 CSourceCommon::stop();
155 CAudioMixerUser::instance()->unregisterUpdate(this);
158 void CBackgroundSource::updateFilterValues(const float *filterValues
)
160 bool needUpdate
= false;
161 std::vector
<TSubSource
>::iterator
first(_Sources
.begin()), last(_Sources
.end());
162 for (; first
!= last
; ++first
)
164 TSubSource
&ss
= *first
;
168 for (uint i
=0; i
<UAudioMixer::TBackgroundFlags::NB_BACKGROUND_FLAGS
; ++i
)
170 if (ss
.Filter
.Flags
[i
])
172 // this filter is used
173 gain
*= filterValues
[i
];
177 if (gain
== 0 && ss
.Status
!= SUB_STATUS_STOP
)
179 // need to completely stop the sound
180 if (ss
.Source
->isPlaying())
182 ss
.Status
= SUB_STATUS_STOP
;
184 else if (gain
> 0 && ss
.Status
!= SUB_STATUS_PLAY
)
186 // need to restard the sound
187 // ss.Source->setRelativeGain(gain * _Gain);
188 ss
.Source
->setGain(ss
.Source
->getSound()->getGain() * gain
);
189 ss
.Source
->setRelativeGain(_Gain
);
190 ss
.Source
->setPitch(ss
.Source
->getSound()->getPitch() * _Pitch
);
191 ss
.Source
->setPos(_Position
);
193 // some sub sound can be too far from the listener,
194 // we must handle this in order to start them when the listener
196 ss
.Status
= ss
.Source
->isPlaying() ? SUB_STATUS_PLAY
: SUB_STATUS_PLAY_FAIL
;
198 needUpdate
|= (ss
.Status
== SUB_STATUS_PLAY_FAIL
);
200 else //if (ss.Status == SUB_STATUS_PLAY)
202 // just update the gain
203 ss
.Source
->setGain(ss
.Source
->getSound()->getGain() * gain
);
204 ss
.Source
->setRelativeGain(_Gain
);
209 // if some some sub sound fail to play...
211 CAudioMixerUser::instance()->registerUpdate(this);
215 void CBackgroundSource::onUpdate()
217 bool needUpdate
= false;
218 // Some sub source are distance clipped, so retry to start them.
219 std::vector
<TSubSource
>::iterator
first(_Sources
.begin()), last(_Sources
.end());
220 for (; first
!= last
; ++first
)
222 TSubSource
&ss
= *first
;
223 if (ss
.Status
== SUB_STATUS_PLAY_FAIL
)
226 // some sub sound can be too far from the listener,
227 // we must handle this in order to start them when the listener
229 ss
.Status
= ss
.Source
->isPlaying() ? SUB_STATUS_PLAY
: SUB_STATUS_PLAY_FAIL
;
231 needUpdate
|= (ss
.Status
== SUB_STATUS_PLAY_FAIL
);
235 // no more update needed ?
237 CAudioMixerUser::instance()->unregisterUpdate(this);