1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or(at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #include "audio/decoders/vorbis.h"
24 #include "common/file.h"
25 #include "common/fs.h"
26 #include "common/util.h"
27 #include "ags/plugins/ags_waves/ags_waves.h"
28 #include "ags/ags.h"
29 
30 namespace AGS3 {
31 namespace Plugins {
32 namespace AGSWaves {
33 
34 const float PI = 3.14159265f;
35 
SFX_Play(ScriptMethodParams & params)36 void AGSWaves::SFX_Play(ScriptMethodParams &params) {
37 	PARAMS2(int, sfxNum, int, repeat);
38 
39 	SoundEffect &effect = SFX[sfxNum];
40 	if (_mixer->isSoundHandleActive(effect._soundHandle)) {
41 		if (effect._allow == 1) {
42 			// In this case we should start the sound on a new channel, not stopping
43 			// the one currently playing.
44 			warning("TODO: play overlapping sound with SFX_Play");
45 		}
46 		return;
47 	}
48 	_mixer->stopHandle(effect._soundHandle);
49 
50 	Common::FSNode fsNode = ::AGS::g_vm->getGameFolder().getChild(
51 		"sounds").getChild(Common::String::format("sound%d.sfx", sfxNum));
52 
53 	Audio::AudioStream *sound = loadOGG(fsNode);
54 
55 	if (sound != nullptr) {
56 		effect._volume = 255;
57 
58 		playStream(Audio::Mixer::kSFXSoundType, &effect._soundHandle, sound, repeat);
59 
60 		if (OGG_Filter && effect._filter && effect._volume > 1) {
61 			warning("TODO: Mix_RegisterEffect(grabChan, LPEffect, NULL, NULL);");
62 		}
63 
64 		effect._repeat = repeat;
65 	}
66 }
67 
SFX_SetVolume(ScriptMethodParams & params)68 void AGSWaves::SFX_SetVolume(ScriptMethodParams &params) {
69 	PARAMS2(int, sfxNum, int, volume);
70 
71 	SoundEffect &effect = SFX[sfxNum];
72 	_mixer->setChannelVolume(effect._soundHandle, volume);
73 	effect._volume = volume;
74 }
75 
SFX_GetVolume(ScriptMethodParams & params)76 void AGSWaves::SFX_GetVolume(ScriptMethodParams &params) {
77 	PARAMS1(int, sfxNum);
78 
79 	SoundEffect &effect = SFX[sfxNum];
80 	params._result = _mixer->getChannelVolume(effect._soundHandle);
81 }
82 
Music_Play(ScriptMethodParams & params)83 void AGSWaves::Music_Play(ScriptMethodParams &params) {
84 	PARAMS6(int, MFX, int, repeat, int, fadeinMS, int, fadeoutMS, int, Position, bool, fixclick);
85 	MusicPlay(MFX, repeat, fadeinMS, fadeoutMS, Position, false, fixclick);
86 }
87 
Music_SetVolume(ScriptMethodParams & params)88 void AGSWaves::Music_SetVolume(ScriptMethodParams &params) {
89 	PARAMS1(int, volume);
90 	_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, volume);
91 }
92 
Music_GetVolume(ScriptMethodParams & params)93 void AGSWaves::Music_GetVolume(ScriptMethodParams &params) {
94 	params._result = _mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType);
95 }
96 
SFX_Stop(ScriptMethodParams & params)97 void AGSWaves::SFX_Stop(ScriptMethodParams &params) {
98 	PARAMS1(int, sfxNum); //, int, fademsOUT);
99 	StopSFX(sfxNum);
100 }
101 
SFX_SetPosition(ScriptMethodParams & params)102 void AGSWaves::SFX_SetPosition(ScriptMethodParams &params) {
103 	PARAMS4(int, sfxNum, int, xS, int, yS, int, intensity);
104 
105 	SoundEffect &effect = SFX[sfxNum];
106 
107 	if (_mixer->isSoundHandleActive(effect._soundHandle)) {
108 		int angle = 0;
109 		int dist = 0;
110 
111 		if (xS != 0 && yS != 0) {
112 			int pid = _engine->GetPlayerCharacter();
113 			playerCharacter = _engine->GetCharacter(pid);
114 
115 			int x1 = Character_GetX((intptr_t)playerCharacter);
116 			int y1 = Character_GetY((intptr_t)playerCharacter);
117 
118 			int x2 = xS;
119 			int y2 = yS;
120 
121 			int defx = (x1 - x2) * (x1 - x2);
122 			int defy = (y1 - y2) * (y1 - y2);
123 
124 			float SquareRoot = sqrt(float(defx + defy));
125 			dist = int(SquareRoot) - intensity;
126 			if (dist > 255) dist = 255;
127 			if (dist < 0)  dist = 0;
128 
129 			float xDiff = float(x2 - x1);
130 			float yDiff = float(y2 - y1);
131 			float at2 = atan2(yDiff, xDiff);
132 
133 			float angles = (at2 * 360.0 / PI);
134 			angle = int(angles);//%360;
135 		}
136 
137 		// TODO: Change Mix_SetPosition to ScummVM equivalent
138 		//Mix_SetPosition(id, angle, dist);
139 		(void)angle;
140 		(void)dist;
141 	}
142 }
143 
SFX_SetGlobalVolume(ScriptMethodParams & params)144 void AGSWaves::SFX_SetGlobalVolume(ScriptMethodParams &params) {
145 	PARAMS1(int, volume);
146 	_mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, volume);
147 }
148 
Load_SFX(ScriptMethodParams & params)149 void AGSWaves::Load_SFX(ScriptMethodParams &params) {
150 //	PARAMS1(int, sfxNum);
151 //	LoadSFX(sfxNum);
152 }
153 
Audio_Apply_Filter(ScriptMethodParams & params)154 void AGSWaves::Audio_Apply_Filter(ScriptMethodParams &params) {
155 	PARAMS1(int, Frequency);
156 
157 	GlitchFix();
158 	ApplyFilter(Frequency);
159 }
160 
Audio_Remove_Filter(ScriptMethodParams & params)161 void AGSWaves::Audio_Remove_Filter(ScriptMethodParams &params) {
162 }
163 
SFX_AllowOverlap(ScriptMethodParams & params)164 void AGSWaves::SFX_AllowOverlap(ScriptMethodParams &params) {
165 	PARAMS2(int, sfxNum, int, allow);
166 	SFX[sfxNum]._allow = allow;
167 }
168 
SFX_Filter(ScriptMethodParams & params)169 void AGSWaves::SFX_Filter(ScriptMethodParams &params) {
170 	PARAMS2(int, sfxNum, int, enable);
171 
172 	// THIS ENABLES/DISABLES the SFX LOW PASS FILTER,
173 	// I think by default all sound effects are affected by low pass, but there are some that i've manually disabled from being affected by it with this command
174 	SFX[sfxNum]._filter = enable;
175 }
176 
loadOGG(const Common::FSNode & fsNode)177 Audio::AudioStream *AGSWaves::loadOGG(const Common::FSNode &fsNode) {
178 #ifdef USE_VORBIS
179 	if (fsNode.exists()) {
180 		Common::File *soundFile = new Common::File();
181 		if (!soundFile->open(fsNode))
182 			error("Failed to open");
183 
184 		Audio::AudioStream *stream = Audio::makeVorbisStream(soundFile, DisposeAfterUse::YES);
185 		assert(stream);
186 		return stream;
187 	}
188 #endif
189 
190 	return nullptr;
191 }
192 
playStream(Audio::Mixer::SoundType type,Audio::SoundHandle * handle,Audio::AudioStream * stream,int repeat)193 void AGSWaves::playStream(Audio::Mixer::SoundType type, Audio::SoundHandle *handle, Audio::AudioStream *stream, int repeat) {
194 	if (!handle || !stream)
195 		return;
196 
197 	if (repeat != 0) {
198 		Audio::SeekableAudioStream *sas =
199 			dynamic_cast<Audio::SeekableAudioStream *>(stream);
200 		assert(sas);
201 
202 		// -1 for infinite, >0 number of successive repeats
203 		Audio::LoopingAudioStream *las =
204 			new Audio::LoopingAudioStream(sas, repeat + 1);
205 		_mixer->playStream(type, handle, las);
206 	} else {
207 		_mixer->playStream(type, handle, stream);
208 	}
209 }
210 
StopSFX(int sfxNum)211 void AGSWaves::StopSFX(int sfxNum) {
212 	SoundEffect &effect = SFX[sfxNum];
213 	_mixer->stopHandle(effect._soundHandle);
214 	effect._playing = 0;
215 	effect._repeat = 0;
216 	effect._channel = -2;
217 }
218 
stopAllSounds()219 void AGSWaves::stopAllSounds() {
220 	for (int i = 0; i < 500; ++i)
221 		StopSFX(i);
222 
223 	_mixer->stopHandle(MFXStream._soundHandle);
224 }
225 
GlitchFix()226 void AGSWaves::GlitchFix() {
227 	// TODO: Implementation
228 }
229 
ApplyFilter(int setFrequency)230 void AGSWaves::ApplyFilter(int setFrequency) {
231 	// THIS TURNS ON THE LOW PASS FILTER
232 	OGG_Filter = true;
233 	GeneralAudio.FilterFrequency = setFrequency;
234 	SetFilterFrequency(setFrequency);
235 }
236 
SetFilterFrequency(int setFrequency)237 void AGSWaves::SetFilterFrequency(int setFrequency) {
238 	// TODO: Implementation
239 }
240 
MusicPlay(int MusicToPlay,int repeat,int fadeinMS,int fadeoutMS,int pos,bool forceplay,bool fixclick)241 void AGSWaves::MusicPlay(int MusicToPlay, int repeat, int fadeinMS, int fadeoutMS, int pos, bool forceplay, bool fixclick) {
242 	if (GeneralAudio.Disabled) {
243 		return;
244 	}
245 
246 	// Stop any previous music
247 	_mixer->stopHandle(MFXStream._soundHandle);
248 
249 	// Load OGG file for music
250 	Common::FSNode fsNode = ::AGS::g_vm->getGameFolder().getChild(
251 		"Music").getChild(Common::String::format("music%d.mfx", MusicToPlay));
252 	Audio::AudioStream *musicStream = loadOGG(fsNode);
253 	if (!musicStream)
254 		return;
255 
256 	bool samefile = currentMusic != MusicToPlay;
257 	if (forceplay)
258 		samefile = true;
259 
260 	if (samefile) {
261 		currentMusicRepeat = repeat;
262 		currentMusicFadein = fadeinMS;
263 		currentMusic = MusicToPlay;
264 
265 		if (!MFXStream.Switch) {
266 			MFXStream.Channel = 0;
267 
268 			playStream(Audio::Mixer::kMusicSoundType,
269 				&MFXStream._soundHandle, musicStream, repeat);
270 
271 			MFXStream.ID = MusicToPlay;
272 			MFXStream.FadeTime = (fadeinMS / 1000) * 40;
273 			MFXStream.FadeRate = (float)_mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType)
274 				/ (float)MFXStream.FadeTime;
275 			MFXStream.FadeVolume = 0.0;
276 			MFXStream.HaltedZero = false;
277 			//MusicVolCanBeAdjusted=true;
278 		} else {
279 			MFXStream.HaltedOne = false;
280 			MFXStream.Channel = 1;
281 
282 			playStream(Audio::Mixer::kMusicSoundType,
283 				&MFXStream._soundHandle, musicStream, repeat);
284 
285 			MFXStream.ID = MusicToPlay;
286 			MFXStream.FadeTime = (fadeoutMS / 1000) * 40;
287 			MFXStream.FadeVolume = 0.0;//float(MusicGetVolume());
288 			MFXStream.FadeRate = (float)_mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType)
289 				/ (float)MFXStream.FadeTime;
290 			//MusicVolCanBeAdjusted=false;
291 		}
292 
293 		MFXStream.Switch = !MFXStream.Switch;
294 	}
295 }
296 
297 } // namespace AGSWaves
298 } // namespace Plugins
299 } // namespace AGS3
300