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 ¶ms) {
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 ¶ms) {
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 ¶ms) {
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 ¶ms) {
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 ¶ms) {
89 PARAMS1(int, volume);
90 _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, volume);
91 }
92
Music_GetVolume(ScriptMethodParams & params)93 void AGSWaves::Music_GetVolume(ScriptMethodParams ¶ms) {
94 params._result = _mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType);
95 }
96
SFX_Stop(ScriptMethodParams & params)97 void AGSWaves::SFX_Stop(ScriptMethodParams ¶ms) {
98 PARAMS1(int, sfxNum); //, int, fademsOUT);
99 StopSFX(sfxNum);
100 }
101
SFX_SetPosition(ScriptMethodParams & params)102 void AGSWaves::SFX_SetPosition(ScriptMethodParams ¶ms) {
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 ¶ms) {
145 PARAMS1(int, volume);
146 _mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, volume);
147 }
148
Load_SFX(ScriptMethodParams & params)149 void AGSWaves::Load_SFX(ScriptMethodParams ¶ms) {
150 // PARAMS1(int, sfxNum);
151 // LoadSFX(sfxNum);
152 }
153
Audio_Apply_Filter(ScriptMethodParams & params)154 void AGSWaves::Audio_Apply_Filter(ScriptMethodParams ¶ms) {
155 PARAMS1(int, Frequency);
156
157 GlitchFix();
158 ApplyFilter(Frequency);
159 }
160
Audio_Remove_Filter(ScriptMethodParams & params)161 void AGSWaves::Audio_Remove_Filter(ScriptMethodParams ¶ms) {
162 }
163
SFX_AllowOverlap(ScriptMethodParams & params)164 void AGSWaves::SFX_AllowOverlap(ScriptMethodParams ¶ms) {
165 PARAMS2(int, sfxNum, int, allow);
166 SFX[sfxNum]._allow = allow;
167 }
168
SFX_Filter(ScriptMethodParams & params)169 void AGSWaves::SFX_Filter(ScriptMethodParams ¶ms) {
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