/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* of the License, or(at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
#include "audio/decoders/vorbis.h"
#include "common/util.h"
#include "ags/plugins/ags_waves/ags_waves.h"
#include "ags/shared/util/stdio_compat.h"
#include "ags/ags.h"
namespace AGS3 {
namespace Plugins {
namespace AGSWaves {
//const float PI = 3.14159265f;
void AGSWaves::SFX_Play(ScriptMethodParams ¶ms) {
PARAMS2(int, sfxNum, int, repeat);
SoundEffect &effect = SFX[sfxNum];
if (_mixer->isSoundHandleActive(effect._soundHandle)) {
if (effect._allow == 1) {
// In this case we should start the sound on a new channel, not stopping
// the one currently playing.
warning("TODO: play overlapping sound with SFX_Play");
}
return;
}
_mixer->stopHandle(effect._soundHandle);
Common::ArchiveMemberPtr member = getFile(Common::String::format("sounds/sound%d.sfx", sfxNum).c_str());
Audio::AudioStream *sound = loadOGG(member);
if (sound != nullptr) {
effect._volume = 255;
playStream(Audio::Mixer::kSFXSoundType, &effect._soundHandle, sound, repeat);
if (OGG_Filter && effect._filter && effect._volume > 1) {
warning("TODO: Mix_RegisterEffect(grabChan, LPEffect, NULL, NULL);");
}
effect._repeat = repeat;
} else {
debug(0, "AGSWaves::SFX_Play couldn't load sfx %d", sfxNum);
}
}
void AGSWaves::SFX_SetVolume(ScriptMethodParams ¶ms) {
PARAMS2(int, sfxNum, int, volume);
SoundEffect &effect = SFX[sfxNum];
_mixer->setChannelVolume(effect._soundHandle, volume);
effect._volume = volume;
}
void AGSWaves::SFX_GetVolume(ScriptMethodParams ¶ms) {
PARAMS1(int, sfxNum);
SoundEffect &effect = SFX[sfxNum];
params._result = _mixer->getChannelVolume(effect._soundHandle);
}
void AGSWaves::Music_Play(ScriptMethodParams ¶ms) {
PARAMS6(int, MFX, int, repeat, int, fadeinMS, int, fadeoutMS, int, Position, bool, fixclick);
MusicPlay(MFX, repeat, fadeinMS, fadeoutMS, Position, false, fixclick);
}
void AGSWaves::Music_SetVolume(ScriptMethodParams ¶ms) {
PARAMS1(int, volume);
_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, volume);
}
void AGSWaves::Music_GetVolume(ScriptMethodParams ¶ms) {
params._result = _mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType);
}
void AGSWaves::SFX_Stop(ScriptMethodParams ¶ms) {
PARAMS1(int, sfxNum); //, int, fademsOUT);
StopSFX(sfxNum);
}
void AGSWaves::SFX_SetPosition(ScriptMethodParams ¶ms) {
#if 0
PARAMS4(int, sfxNum, int, xS, int, yS, int, intensity);
SoundEffect &effect = SFX[sfxNum];
if (_mixer->isSoundHandleActive(effect._soundHandle)) {
int angle = 0;
int dist = 0;
if (xS != 0 && yS != 0) {
int pid = _engine->GetPlayerCharacter();
playerCharacter = _engine->GetCharacter(pid);
int x1 = Character_GetX((intptr_t)playerCharacter);
int y1 = Character_GetY((intptr_t)playerCharacter);
int x2 = xS;
int y2 = yS;
int defx = (x1 - x2) * (x1 - x2);
int defy = (y1 - y2) * (y1 - y2);
float SquareRoot = sqrt(float(defx + defy));
dist = int(SquareRoot) - intensity;
if (dist > 255) dist = 255;
if (dist < 0) dist = 0;
float xDiff = float(x2 - x1);
float yDiff = float(y2 - y1);
float at2 = atan2(yDiff, xDiff);
float angles = (at2 * 360.0 / PI);
angle = int(angles);//%360;
}
// TODO: Change Mix_SetPosition to ScummVM equivalent
//Mix_SetPosition(id, angle, dist);
(void)angle;
(void)dist;
}
#endif
debug(0, "TODO: SFX_Setposition positional sound not yet implemented");
}
void AGSWaves::SFX_SetGlobalVolume(ScriptMethodParams ¶ms) {
PARAMS1(int, volume);
_mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, volume);
}
void AGSWaves::Load_SFX(ScriptMethodParams ¶ms) {
// PARAMS1(int, sfxNum);
// LoadSFX(sfxNum);
}
void AGSWaves::Audio_Apply_Filter(ScriptMethodParams ¶ms) {
PARAMS1(int, Frequency);
GlitchFix();
ApplyFilter(Frequency);
}
void AGSWaves::Audio_Remove_Filter(ScriptMethodParams ¶ms) {
}
void AGSWaves::SFX_AllowOverlap(ScriptMethodParams ¶ms) {
PARAMS2(int, sfxNum, int, allow);
SFX[sfxNum]._allow = allow;
}
void AGSWaves::SFX_Filter(ScriptMethodParams ¶ms) {
PARAMS2(int, sfxNum, int, enable);
// THIS ENABLES/DISABLES the SFX LOW PASS FILTER,
// 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
SFX[sfxNum]._filter = enable;
}
Audio::AudioStream *AGSWaves::loadOGG(const Common::ArchiveMemberPtr &member) {
#ifdef USE_VORBIS
if (member) {
Audio::AudioStream *stream = Audio::makeVorbisStream(member->createReadStream(), DisposeAfterUse::YES);
return stream;
}
#endif
return nullptr;
}
void AGSWaves::playStream(Audio::Mixer::SoundType type, Audio::SoundHandle *handle, Audio::AudioStream *stream, int repeat) {
if (!handle || !stream)
return;
if (repeat != 0) {
Audio::SeekableAudioStream *sas =
dynamic_cast(stream);
assert(sas);
// -1 for infinite, >0 number of successive repeats
Audio::LoopingAudioStream *las =
new Audio::LoopingAudioStream(sas, repeat + 1);
_mixer->playStream(type, handle, las);
} else {
_mixer->playStream(type, handle, stream);
}
}
void AGSWaves::StopSFX(int sfxNum) {
SoundEffect &effect = SFX[sfxNum];
_mixer->stopHandle(effect._soundHandle);
effect._playing = 0;
effect._repeat = 0;
effect._channel = -2;
}
void AGSWaves::stopAllSounds() {
for (int i = 0; i < 500; ++i)
StopSFX(i);
_mixer->stopHandle(MFXStream._soundHandle);
}
void AGSWaves::GlitchFix() {
// TODO: Implementation
}
void AGSWaves::ApplyFilter(int setFrequency) {
// THIS TURNS ON THE LOW PASS FILTER
OGG_Filter = true;
GeneralAudio.FilterFrequency = setFrequency;
SetFilterFrequency(setFrequency);
}
void AGSWaves::SetFilterFrequency(int setFrequency) {
// TODO: Implementation
}
void AGSWaves::MusicPlay(int MusicToPlay, int repeat, int fadeinMS, int fadeoutMS, int pos, bool forceplay, bool fixclick) {
if (GeneralAudio.Disabled) {
return;
}
// Stop any previous music
_mixer->stopHandle(MFXStream._soundHandle);
// Load OGG file for music
Common::ArchiveMemberPtr member = getFile(Common::String::format("music/music%d.mfx", MusicToPlay).c_str());
Audio::AudioStream *musicStream = loadOGG(member);
if (!musicStream)
return;
bool samefile = currentMusic != MusicToPlay;
if (forceplay)
samefile = true;
if (samefile) {
currentMusicRepeat = repeat;
currentMusicFadein = fadeinMS;
currentMusic = MusicToPlay;
if (!MFXStream.Switch) {
MFXStream.Channel = 0;
playStream(Audio::Mixer::kMusicSoundType,
&MFXStream._soundHandle, musicStream, repeat);
MFXStream.ID = MusicToPlay;
MFXStream.FadeTime = (fadeinMS / 1000) * 40;
MFXStream.FadeRate = (float)_mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType)
/ (float)MFXStream.FadeTime;
MFXStream.FadeVolume = 0.0;
MFXStream.HaltedZero = false;
//MusicVolCanBeAdjusted=true;
} else {
MFXStream.HaltedOne = false;
MFXStream.Channel = 1;
playStream(Audio::Mixer::kMusicSoundType,
&MFXStream._soundHandle, musicStream, repeat);
MFXStream.ID = MusicToPlay;
MFXStream.FadeTime = (fadeoutMS / 1000) * 40;
MFXStream.FadeVolume = 0.0;//float(MusicGetVolume());
MFXStream.FadeRate = (float)_mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType)
/ (float)MFXStream.FadeTime;
//MusicVolCanBeAdjusted=false;
}
MFXStream.Switch = !MFXStream.Switch;
}
}
} // namespace AGSWaves
} // namespace Plugins
} // namespace AGS3