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 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283
|
/* 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/>.
*
*/
#ifndef SCUMM_HE_SOUND_HE_H
#define SCUMM_HE_SOUND_HE_H
#include "common/scummsys.h"
#include "common/mutex.h"
#include "scumm/sound.h"
#include "scumm/he/mixer_he.h"
#include "audio/audiostream.h"
namespace Scumm {
#define HSND_DYN_SOUND_CHAN -1
#define HSND_TALKIE_SLOT 1
#define HSND_SOUND_STOPPED 1
#define HSND_SOUND_ENDED 2
#define HSND_SOUND_TIMEOUT 3
#define HSND_TIMER_SLOT 4
#define HSND_MAX_CALLBACK_SCRIPTS 20
#define HSND_MAX_CHANNELS 8
#define HSND_CHANNEL_0 10000
#define HSND_CHANNEL_1 10001
#define HSND_CHANNEL_2 10002
#define HSND_CHANNEL_3 10003
#define HSND_CHANNEL_4 10004
#define HSND_CHANNEL_5 10005
#define HSND_CHANNEL_6 10006
#define HSND_CHANNEL_7 10007
#define HSND_MAX_SOUND_VARS 26
#define HSND_DEFAULT_FREQUENCY 11025
#define HSND_BASE_FREQ_FACTOR 1024
#define HSND_SOUND_FREQ_BASE 1024
#define HSND_MAX_VOLUME 255
#define HSND_SOUND_PAN_LEFT 0
#define HSND_SOUND_PAN_CENTER 64
#define HSND_SOUND_PAN_RIGHT 127
#define HSND_FIRST_SPOOLING_SOUND 4000
#define HSND_MAX_FREQ_RATIO 4
#define HSND_MAX_SPOOLING_CODE_SIZE 16384
#define HSND_SBNG_TYPE_ALL 0xF8
#define HSND_SBNG_DATA_ALL 0x07
#define HSND_SBNG_MAGIC_NUMBER 0x2000
#define HSND_SBNG_MAGIC_MASK 0xF000
#define HSND_SBNG_END 0x00
#define HSND_SBNG_FACE 0x10
#define HSND_SBNG_SET_SET 0x20
#define HSND_SBNG_SET_ADD 0x30
#define HSND_SBNG_SET_SUB 0x38
#define HSND_SBNG_SET_MUL 0x40
#define HSND_SBNG_SET_DIV 0x50
#define HSND_SBNG_SET_INC 0x60
#define HSND_SBNG_SET_DEC 0x68
#define HSND_SBNG_VARORVAL 0x03
#define HSND_SBNG_VARVAL 0x02
#define HSND_SNDVAR_TOKENS 26
#define XSH2_FLAG_HAS_PRIORITY 0x01
#define WAVE_FORMAT_PCM 1
#define WAVE_FORMAT_IMA_ADPCM 17
#define WAVE_RIFF_HEADER_LEN 44
#define HSND_RES_OFFSET_ID1 0 // uint32, DIGI or MIDI header
#define HSND_RES_OFFSET_LEN1 4 // uint32
#define HSND_RES_OFFSET_ID 8 // uint32, HSHD header
#define HSND_RES_OFFSET_LEN2 12 // uint32
#define HSND_RES_OFFSET_COMPRESSED 16 // uint8, header data
#define HSND_RES_OFFSET_FORMATTED 17 // uint8
#define HSND_RES_OFFSET_KILL_PRIO 18 // uint8
#define HSND_RES_OFFSET_DEAD_PRIO 19 // uint8
#define HSND_RES_OFFSET_LEFT_VOLUME 20 // uint8
#define HSND_RES_OFFSET_RIGHT_VOLUME 21 // uint8
#define HSND_RES_OFFSET_FREQUENCY 22 // uint16
#define HSND_RES_OFFSET_MONDO_OFFSET 24 // uint32
#define HSND_RES_OFFSET_BITS_PER_SAMPLE 28 // uint8
#define HSND_RES_OFFSET_SAMPLE_CHANNELS 29 // uint8
#define HSND_RES_OFFSET_UNUSED3 30 // uint8
#define HSND_RES_OFFSET_UNUSED4 31 // uint8
#define HSND_RES_OFFSET_ID3 32 // uint32, SDAT header
#define HSND_RES_OFFSET_LEN3 36 // uint32
#define HSND_RES_OFFSET_SOUND_DATA 40
// Used both in SoundHE and HEMixer
struct HESoundModifiers {
HESoundModifiers(int mFrequencyShift, int mPan, int mVolume) {
// Hey, turns out Moonbase Commander just LOVES sending out invalid modifiers :-)
/*
assert(mFrequencyShift >= HSND_SOUND_FREQ_BASE / HSND_MAX_FREQ_RATIO);
assert(mFrequencyShift <= HSND_SOUND_FREQ_BASE * HSND_MAX_FREQ_RATIO);
assert(mPan >= HSND_SOUND_PAN_LEFT && mPan <= HSND_SOUND_PAN_RIGHT);
assert(mVolume >= 0 && mVolume <= HSND_MAX_VOLUME);
*/
frequencyShift = mFrequencyShift;
pan = mPan;
volume = mVolume;
}
HESoundModifiers() {
frequencyShift = HSND_SOUND_FREQ_BASE;
pan = HSND_SOUND_PAN_CENTER;
volume = HSND_MAX_VOLUME;
}
int frequencyShift;
int pan;
int volume;
};
struct HESpoolingMusicItem {
int32 song;
int32 offset;
int32 size;
char filename[128];
};
class ScummEngine_v60he;
class HEMixer;
class SoundHE : public Sound {
friend class HEMixer;
protected:
ScummEngine_v60he *_vm;
int _overrideFreq;
Common::Mutex *_mutex;
HEMixer *_heMixer;
struct HESoundCallbackItem {
int32 sound;
int32 channel;
int32 whatFrame;
};
HESoundCallbackItem _soundCallbackScripts[HSND_MAX_CALLBACK_SCRIPTS];
HESpoolingMusicItem *_heSpoolingMusicTable;
struct PCMWaveFormat {
uint16 wFormatTag;
uint16 wChannels;
uint32 dwSamplesPerSec;
uint32 dwAvgBytesPerSec;
uint16 wBlockAlign;
uint16 wBitsPerSample;
};
int32 _heSpoolingMusicCount;
Common::File _heSpoolingMusicFile;
byte _heSpoolingCodeBuffer[HSND_MAX_SPOOLING_CODE_SIZE];
public: // Used by createSound()
struct {
int sound;
int codeOffset;
byte *codeBuffer;
int priority;
int frequency;
int timeout;
bool hasSoundTokens;
int soundVars[HSND_MAX_SOUND_VARS];
int age;
void clearChannel() {
sound = 0;
codeOffset = 0;
codeBuffer = nullptr;
priority = 0;
frequency = 0;
timeout = 0;
hasSoundTokens = false;
memset(soundVars, 0, sizeof(soundVars));
age = 0;
}
} _heChannel[HSND_MAX_CHANNELS];
// Used throughout script functions
int32 _createSndId;
int32 _createSndLastAppend;
int32 _createSndLastPos;
int32 _baseSndSize;
public:
SoundHE(ScummEngine *parent, Audio::Mixer *mixer, Common::Mutex *mutex);
~SoundHE() override;
void startSound(int sound, int heOffset = 0, int heChannel = 0, int heFlags = 0, int heFreq = 0, int hePan = 0, int heVol = 0) override;
void addSoundToQueue(int sound, int heOffset = 0, int heChannel = 0, int heFlags = 0, int heFreq = 0, int hePan = 0, int heVol = 0) override;
void modifySound(int sound, int offset, int frequencyShift, int pan, int volume, int flags) override;
int isSoundRunning(int sound) const override;
bool isSoundInUse(int sound) const override;
void stopSound(int sound) override;
void stopAllSounds() override;
int hsFindSoundChannel(int sound) const;
void setupSound() override;
void pauseSounds(bool pause) override;
bool getHEMusicDetails(int id, int &musicOffs, int &musicSize);
int getNextDynamicChannel();
bool isSoundCodeUsed(int sound);
int getSoundPosition(int sound);
int getSoundVar(int sound, int var);
void setSoundVar(int sound, int var, int val);
void setSoundVolume(int sound, int volume);
void triggerSound(int soundId, int heOffset, int heChannel, int heFlags, HESoundModifiers modifiers);
void triggerSpoolingSound(int soundId, int heOffset, int heChannel, int heFlags, HESoundModifiers modifiers);
void triggerDigitalSound(int soundId, int heOffset, int heChannel, int heFlags);
void triggerMidiSound(int soundId, int heOffset);
void triggerRIFFSound(int soundId, int heOffset, int heChannel, int heFlags, HESoundModifiers modifiers);
void triggerXSOUSound(int soundId, int heOffset, int heChannel, int heFlags);
void hsStartDigitalSound(int sound, int offset, byte *addr, int sound_data, int globType, int globNum,
int sampleCount, int frequency, int channel, int priority, int soundCode,
int flags, int bitsPerSample, int soundChannelCount, HESoundModifiers modifiers);
void hsStopDigitalSound(int sound);
void handleSoundFrame();
void feedMixer();
void unqueueSoundCallbackScripts();
void checkSoundTimeouts();
void digitalSoundCallback(int message, int channel, bool earlyCallback = false);
void queueSoundCallbackScript(int sound, int channel, int message);
void runSoundCode();
void processSoundOpcodes(int sound, byte *codePtr, int *soundVars);
void setOverrideFreq(int freq);
void setupHEMusicFile();
void playVoice(uint32 offset, uint32 length);
void playVoiceFile(char *filename);
void stopDigitalSound(int sound);
void createSound(int snd1id, int snd2id);
int getChannelPosition(int channel);
const byte *findWavBlock(uint32 tag, const byte *block);
int getCurrentSpeechOffset();
bool is3DOSound(int sound) const;
protected:
void processSoundQueues() override;
private:
int _heTalkOffset = 0;
bool _stopActorTalkingFlag = false;
bool _inSoundCallbackFlag = false;
int _soundCallbacksQueueSize = 0;
int _soundAlreadyInQueueCount = 0;
int _inUnqueueCallbackScripts = 0;
int _soundsDebugFrameCounter = 0;
int _dynamicSoundAgeCounter = 0;
};
} // End of namespace Scumm
#endif
|