scummvm/engines/sword2/sound.h
2021-12-26 18:48:43 +01:00

285 lines
6.6 KiB
C++

/* 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.
*
* Additional copyright for this file:
* Copyright (C) 1994-1998 Revolution Software Ltd.
*
* 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/>.
*/
/*****************************************************************************
* SOUND.H Sound engine
*
* SOUND.CPP Contains the sound engine, fx & music functions
* Some very 'sound' code in here ;)
*
* (16Dec96 JEL)
*
****************************************************************************/
#ifndef SWORD2_SOUND_H
#define SWORD2_SOUND_H
#include "common/file.h"
#include "common/mutex.h"
#include "audio/audiostream.h"
#include "audio/mixer.h"
// Max number of sound fx
#define MAXMUS 2
// Max number of fx in queue at once
#define FXQ_LENGTH 32
#define BUFFER_SIZE 4096
namespace Sword2 {
enum {
kCLUMode = 1,
kMP3Mode,
kVorbisMode,
kFLACMode
};
enum {
kLeadInSound,
kLeadOutSound
};
enum {
// These three types correspond to types set by the scripts
FX_SPOT = 0,
FX_LOOP = 1,
FX_RANDOM = 2,
// These are used for FX queue bookkeeping
FX_SPOT2 = 3,
FX_LOOPING = 4
};
// Sound defines
enum {
RDSE_SAMPLEFINISHED = 0,
RDSE_SAMPLEPLAYING = 1,
RDSE_FXTOCLEAR = 0, // Unused
RDSE_FXCACHED = 1, // Unused
RDSE_FXSPOT = 0,
RDSE_FXLOOP = 1,
RDSE_FXLEADIN = 2,
RDSE_FXLEADOUT = 3,
RDSE_QUIET = 1,
RDSE_SPEAKING = 0
};
class CLUInputStream : public Audio::AudioStream {
private:
Common::File *_file;
bool _firstTime;
uint32 _file_pos;
uint32 _end_pos;
int16 _outbuf[BUFFER_SIZE];
byte _inbuf[BUFFER_SIZE];
const int16 *_bufferEnd;
const int16 *_pos;
uint16 _prev;
void refill();
inline bool eosIntern() const {
return !_file->isOpen() || _pos >= _bufferEnd;
}
public:
CLUInputStream(Common::File *file, int size);
~CLUInputStream() override;
int readBuffer(int16 *buffer, const int numSamples) override;
bool endOfData() const override { return eosIntern(); }
bool isStereo() const override { return false; }
int getRate() const override { return 22050; }
};
struct SoundFileHandle {
Common::File file;
uint32 *idxTab;
uint32 idxLen;
int32 fileSize;
uint32 fileType;
volatile bool inUse;
};
class MusicInputStream : public Audio::AudioStream {
private:
int _cd;
SoundFileHandle *_fh;
uint32 _musicId;
Audio::AudioStream *_decoder;
int16 _buffer[BUFFER_SIZE];
const int16 *_bufferEnd;
const int16 *_pos;
bool _remove;
uint32 _numSamples;
uint32 _samplesLeft;
bool _looping;
int32 _fading;
int32 _fadeSamples;
void refill();
inline bool eosIntern() const {
if (_looping)
return false;
return _remove || _pos >= _bufferEnd;
}
public:
MusicInputStream(int cd, SoundFileHandle *fh, uint32 musicId, bool looping);
~MusicInputStream() override;
int readBuffer(int16 *buffer, const int numSamples) override;
bool endOfData() const override { return eosIntern(); }
bool isStereo() const override { return _decoder->isStereo(); }
int getRate() const override { return _decoder->getRate(); }
int getCD() { return _cd; }
void fadeUp();
void fadeDown();
bool isReady() { return _decoder != NULL; }
int32 isFading() { return _fading; }
bool readyToRemove();
int32 getTimeRemaining();
};
class Sound : public Audio::AudioStream {
private:
Sword2Engine *_vm;
Common::Mutex _mutex;
Audio::SoundHandle _mixerSoundHandle;
Audio::SoundHandle _leadInHandle;
Audio::SoundHandle _leadOutHandle;
struct FxQueueEntry {
Audio::SoundHandle handle; // sound handle
uint32 resource; // resource id of sample
byte *data; // pointer to WAV data
uint32 len; // WAV data length
uint16 delay; // cycles to wait before playing (or 'random chance' if FX_RANDOM)
uint8 volume; // sound volume
int8 pan; // sound panning
uint8 type; // FX_SPOT, FX_RANDOM, FX_LOOP
};
FxQueueEntry _fxQueue[FXQ_LENGTH];
void triggerFx(uint8 i);
bool _reverseStereo;
bool _speechMuted;
bool _fxMuted;
bool _musicMuted;
bool _speechPaused;
bool _fxPaused;
bool _musicPaused;
int32 _loopingMusicId;
Audio::SoundHandle _soundHandleSpeech;
MusicInputStream *_music[MAXMUS];
SoundFileHandle _musicFile[MAXMUS];
SoundFileHandle _speechFile[MAXMUS];
int16 *_mixBuffer;
int _mixBufferLen;
public:
Sound(Sword2Engine *vm);
~Sound() override;
// AudioStream API
int readBuffer(int16 *buffer, const int numSamples) override;
bool isStereo() const override { return false; }
bool endOfData() const override;
int getRate() const override { return Sword2Engine::isPsx() ? 11025 : 22050; }
// End of AudioStream API
void clearFxQueue(bool killMovieSounds);
void processFxQueue();
void setReverseStereo(bool reverse);
bool isReverseStereo() const { return _reverseStereo; }
void muteSpeech(bool mute);
bool isSpeechMute() const { return _speechMuted; }
void muteFx(bool mute);
bool isFxMute() const { return _fxMuted; }
void muteMusic(bool mute) { _musicMuted = mute; }
bool isMusicMute() const { return _musicMuted; }
void setLoopingMusicId(int32 id) { _loopingMusicId = id; }
int32 getLoopingMusicId() const { return _loopingMusicId; }
void pauseSpeech();
void unpauseSpeech();
void pauseFx();
void unpauseFx();
void pauseMusic();
void unpauseMusic();
void playMovieSound(int32 res, int type);
void stopMovieSounds();
void queueFx(int32 res, int32 type, int32 delay, int32 volume, int32 pan);
int32 playFx(FxQueueEntry *fx);
int32 playFx(Audio::SoundHandle *handle, byte *data, uint32 len, uint8 vol, int8 pan, bool loop, Audio::Mixer::SoundType soundType);
int32 stopFx(int32 i);
int32 setFxIdVolumePan(int32 id, int vol, int pan = 255);
int32 getSpeechStatus();
int32 amISpeaking();
int32 playCompSpeech(uint32 speechId, uint8 vol, int8 pan);
int32 stopSpeech();
int32 streamCompMusic(uint32 musicId, bool loop);
void stopMusic(bool immediately);
int32 musicTimeRemaining();
void printFxQueue();
};
} // End of namespace Sword2
#endif