1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
|
/* 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
* (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 <http://www.gnu.org/licenses/>.
*
*/
//=============================================================================
//
// ACSOUND - AGS sound system wrapper
//
//=============================================================================
#ifndef AGS_ENGINE_MEDIA_AUDIO_SOUNDCLIP_H
#define AGS_ENGINE_MEDIA_AUDIO_SOUNDCLIP_H
#include "audio/mixer.h"
#include "audio/audiostream.h"
#include "common/stream.h"
namespace AGS3 {
// SOUNDCLIP's state and parameter updates sync with the audio core in
// batches, only when the engine updates the game, never while the user script
// is being executed. The sync is performed by calling update().
// This is to ensure that the clip reference, state and properties don't change
// in the middle of the script's command sequence.
// TODO: one of the biggest problems with sound clips currently is that it
// provides several methods of applying volume, which may ignore or override
// each other, and does not shape a consistent interface.
// Improving this situation is only possible with massive refactory of
// sound clip use, taking backwards-compatible audio system in account.
enum SoundClipState {
SoundClipInitial, SoundClipPlaying, SoundClipPaused, SoundClipStopped
};
struct SOUNDCLIP {
SOUNDCLIP();
virtual ~SOUNDCLIP() {}
// TODO: move these to private
int _sourceClipID;
int _sourceClipType;
bool _repeat;
int _priority;
int _xSource, _ySource; // Used for positioning sounds in game rooms
int _maximumPossibleDistanceAway;
int _vol255;
int _vol100;
int _volModifier;
int _panning;
int _panningAsPercentage;
int _directionalVolModifier;
virtual int play() = 0;
virtual void pause() = 0;
virtual void resume() = 0;
/**
* Seeks to the position, where pos units depend on the audio type:
* - MIDI - the beat number
* - MOD / XM / S3M - the pattern number
* - WAV / VOC - the sample number
* - OGG / MP3 - milliseconds
*/
virtual void seek(int offset) = 0;
/**
* Seeks to the position in milliseconds
*/
virtual void seek_ms(int pos_ms) = 0;
virtual int play_from(int position) = 0;
virtual bool is_playing() = 0; // true if playing or paused. false if never played or stopped.
virtual bool is_paused() = 0; // true if paused
/**
* Get legacy sound format type
*/
virtual int get_sound_type() const = 0;
/**
* Return current position in frames
*/
virtual int get_pos() = 0;
/**
* Return the position in milliseconds
*/
virtual int get_pos_ms() = 0;
/**
* Return total track length in ms (or 0)
*/
virtual int get_length_ms() = 0;
virtual void set_panning(int newPanning) = 0;
virtual void set_speed(int new_speed) = 0;
virtual void poll() = 0;
/**
* Gets clip's volume property, as percentage (0 - 100);
* note this may not be the real volume of playback (which could e.g. be muted)
*/
inline int get_volume100() const { return _vol100; }
/**
* Gets clip's volume measured in 255 units
*/
inline int get_volume255() const { return _vol255; }
/**
* Gets clip's panning (-100 - +100)
*/
inline int get_panning() const { return _panning; }
/**
* Gets clip's playback speed in clip ms per real second
*/
inline int get_speed() const { return _speed; }
/**
* Gets if clip is muted (without changing the volume setting)
*/
inline bool is_muted() const { return _muted; }
/**
* Sets the current volume property, as percentage (0 - 100)
*/
void set_volume100(int volume);
/**
* Sets the current volume property, as a level (0 - 255)
*/
void set_volume255(int volume);
/**
* Explicitly defines both percentage and absolute volume value,
* without calculating it from given percentage.
* NOTE: this overrides the mute
*/
void set_volume_direct(int vol_percent, int vol_absolute);
/**
* Mutes sound clip, while preserving current volume property
* for the future reference; when unmuted, that property is
* used to restart previous volume.
*/
void set_mute(bool mute);
/**
* Apply arbitrary permanent volume modifier, in absolute units (0 - 255);
* this is distinct value that is used in conjunction with current volume
* (can be both positive and negative).
*/
void apply_volume_modifier(int mod);
/**
* Apply permanent directional volume modifier, in absolute units (0 - 255)
* this is distinct value that is used in conjunction with current volume
* (can be both positive and negative).
*/
void apply_directional_modifier(int mod);
inline bool is_ready() { return is_playing(); }
/**
* Returns if the clip is still playing, otherwise it's finished
*/
bool update();
protected:
virtual void adjust_volume() = 0;
// mute mode overrides the volume; if set, any volume assigned is stored
// in properties, but not applied to playback itself
bool _muted = false;
// speed of playback, in clip ms per real second
int _speed = 0;
bool _paramsChanged = false;
// helper function for calculating volume with applied modifiers
inline int get_final_volume() const {
int final_vol = _vol255 + _volModifier + _directionalVolModifier;
return final_vol >= 0 ? final_vol : 0;
}
};
struct SoundClipWaveBase : public SOUNDCLIP {
private:
Audio::Mixer::SoundType _soundType = Audio::Mixer::kPlainSoundType;
int pos_to_posms(int pos) const;
public:
Audio::Mixer *_mixer;
Audio::AudioStream *_stream;
Audio::SoundHandle _soundHandle;
SoundClipState _state;
bool _waitingToPlay = false;
SoundClipWaveBase(Audio::AudioStream *stream, bool repeat = false);
~SoundClipWaveBase() override;
void setType(Audio::Mixer::SoundType type);
void poll() override;
int play() override;
int play_from(int position) override;
void pause() override;
void resume() override;
bool is_playing() override;
bool is_paused() override;
void seek(int offset) override;
void seek_ms(int pos_ms) override;
int get_pos() override;
int get_pos_ms() override;
int get_length_ms() override;
void set_panning(int newPanning) override;
void set_speed(int new_speed) override;
void adjust_volume() override;
};
template<int SOUND_TYPE>
struct SoundClipWave : public SoundClipWaveBase {
SoundClipWave(Audio::AudioStream *stream, bool repeat = false) :
SoundClipWaveBase(stream, repeat) {}
int get_sound_type() const {
return SOUND_TYPE;
}
};
} // namespace AGS3
#endif
|