scummvm/sword2/sound.h
Robert Göffringmann c7dad332fa basically the same change as for bs1; don't keep the mutex locked while loading mp3, ogg or wave data. it blocks the playing thread for too long.
Also added index caching for the speech and music clusters to reduce seeks.

svn-id: r16849
2005-02-21 08:35:18 +00:00

259 lines
5.8 KiB
C++

/* Copyright (C) 1994-1998 Revolution Software Ltd.
* Copyright (C) 2003-2005 The ScummVM project
*
* 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 2
* 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header$
*/
/*****************************************************************************
* SOUND.H Sound engine
*
* SOUND.CPP Contains the sound engine, fx & music functions
* Some very 'sound' code in here ;)
*
* (16Dec96 JEL)
*
****************************************************************************/
#ifndef SOUND_H
#define SOUND_H
#include "common/file.h"
#include "sound/audiostream.h"
#include "sound/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 {
// 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
};
class CLUInputStream : public AudioStream {
private:
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 _pos >= _bufferEnd;
}
public:
CLUInputStream(File *file, int size);
~CLUInputStream();
int readBuffer(int16 *buffer, const int numSamples);
bool endOfData() const { return eosIntern(); }
bool isStereo() const { return false; }
int getRate() const { return 22050; }
};
struct SoundFileHandle {
File *file;
uint32 *idxTab;
uint32 idxLen;
uint32 fileSize;
uint32 fileType;
volatile bool inUse;
};
class MusicInputStream : public AudioStream {
private:
int _cd;
//File *_file;
SoundFileHandle *_fh;
uint32 _musicId;
AudioStream *_decoder;
int16 _buffer[BUFFER_SIZE];
const int16 *_bufferEnd;
const int16 *_pos;
bool _remove;
uint32 _numSamples;
uint32 _samplesLeft;
bool _looping;
int32 _fading;
int32 _fadeSamples;
bool _paused;
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();
int readBuffer(int16 *buffer, const int numSamples);
bool endOfData() const { return eosIntern(); }
bool isStereo() const { return _decoder->isStereo(); }
int getRate() const { return _decoder->getRate(); }
int whichCd() { return _cd; }
void fadeUp();
void fadeDown();
bool isReady() { return _decoder != NULL; }
int32 isFading() { return _fading; }
bool readyToRemove();
int32 getTimeRemaining();
};
class Sound : public AudioStream {
private:
Sword2Engine *_vm;
Common::Mutex _mutex;
struct FxQueueEntry {
PlayingSoundHandle 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;
PlayingSoundHandle _soundHandleSpeech;
MusicInputStream *_music[MAXMUS];
//File _musicFile[MAXMUS];
SoundFileHandle _musicFile[MAXMUS];
SoundFileHandle _speechFile[MAXMUS];
int16 *_mixBuffer;
int _mixBufferLen;
public:
Sound(Sword2Engine *vm);
~Sound();
// AudioStream API
int readBuffer(int16 *buffer, const int numSamples);
bool isStereo() const { return false; }
bool endOfData() const;
int getRate() const { return 22050; }
// End of AudioStream API
void clearFxQueue();
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 pauseAllSound();
void unpauseAllSound();
void queueFx(int32 res, int32 type, int32 delay, int32 volume, int32 pan);
int32 playFx(FxQueueEntry *fx);
int32 playFx(PlayingSoundHandle *handle, byte *data, uint32 len, uint8 vol, int8 pan, bool loop, SoundMixer::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);
uint32 preFetchCompSpeech(uint32 speechId, uint16 **buf);
int32 stopSpeech();
int32 streamCompMusic(uint32 musicId, bool loop);
void stopMusic(bool immediately);
int32 musicTimeRemaining();
};
} // End of namespace Sword2
#endif