1 /* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
2 
3 #include "SoundItem.h"
4 
5 #include <sstream>
6 #include <stdexcept>
7 #include <cfloat>
8 
9 #include "SoundBuffer.h"
10 #include "System/UnsyncedRNG.h"
11 
12 namespace
13 {
14 	UnsyncedRNG randnum; // no need for strong randomness here, so default seed is ok
15 
16 	template <typename T>
MapEntryValExtract(const std::map<std::string,std::string> & map,const std::string & key,T & t)17 	inline bool MapEntryValExtract(const std::map<std::string, std::string>& map, const std::string& key, T& t)
18 	{
19 		std::map<std::string, std::string>::const_iterator it = map.find(key);
20 		if (it != map.end())
21 		{
22 			std::istringstream stream(it->second);
23 			stream >> t;
24 			return true;
25 		}
26 		else
27 			return false;
28 	}
29 
30 	template <typename T>
FitInIntervall(const T & lower,T & val,const T & upper)31 	void FitInIntervall(const T& lower, T& val, const T& upper)
32 	{
33 		val = std::max(std::min(val, upper), lower);
34 	}
35 }
36 
SoundItem(boost::shared_ptr<SoundBuffer> _buffer,const std::map<std::string,std::string> & items)37 SoundItem::SoundItem(boost::shared_ptr<SoundBuffer> _buffer, const std::map<std::string, std::string>& items)
38 	: buffer(_buffer)
39 	, gain(1.0)
40 	, gainMod(0)
41 	, pitch(1.0)
42 	, pitchMod(0)
43 	, dopplerScale(1.0)
44 	, maxDist(FLT_MAX)
45 	, rolloff(1.0f)
46 	, priority(0)
47 	, maxConcurrent(16)
48 	, currentlyPlaying(0)
49 	, loopTime(0)
50 	, in3D(true)
51 {
52 	if (!MapEntryValExtract(items, "name", name))
53 		name = buffer->GetFilename();
54 
55 	MapEntryValExtract(items, "gain", gain);
56 	MapEntryValExtract(items, "gainmod", gainMod);
57 	FitInIntervall(0.f, gainMod, 1.f);
58 	MapEntryValExtract(items, "pitch", pitch);
59 	MapEntryValExtract(items, "pitchmod", pitchMod);
60 	FitInIntervall(0.f, pitchMod, 1.f);
61 	MapEntryValExtract(items, "dopplerscale", dopplerScale);
62 	MapEntryValExtract(items, "priority", priority);
63 	MapEntryValExtract(items, "maxconcurrent", maxConcurrent);
64 	MapEntryValExtract(items, "maxdist", maxDist);
65 	MapEntryValExtract(items, "rolloff", rolloff);
66 	MapEntryValExtract(items, "in3d", in3D);
67 	MapEntryValExtract(items, "looptime", loopTime);
68 }
69 
PlayNow()70 bool SoundItem::PlayNow()
71 {
72 	if (maxConcurrent >= currentlyPlaying)
73 	{
74 		currentlyPlaying++;
75 		return true;
76 	}
77 	else
78 	{
79 		return false;
80 	}
81 }
82 
StopPlay()83 void SoundItem::StopPlay()
84 {
85 	assert(currentlyPlaying > 0);
86 	--currentlyPlaying;
87 }
88 
GetGain() const89 float SoundItem::GetGain() const
90 {
91 	float tgain = 0;
92 	if (gainMod > 0)
93 		tgain = (float(randnum(200))/100.f - 1.f)*gainMod;
94 	return gain * (1.f + tgain);
95 }
96 
GetPitch() const97 float SoundItem::GetPitch() const
98 {
99 	float tpitch = 0;
100 	if (pitchMod > 0)
101 		tpitch = (float(randnum(200))/100.f - 1.f)*pitchMod;
102 	return pitch * (1.f + tpitch);
103 }
104