diff options
author | Strangerke | 2011-06-29 16:15:41 +0200 |
---|---|---|
committer | Strangerke | 2011-06-29 16:15:41 +0200 |
commit | b0c9c9122fc678074aba30068e5b36d347208e65 (patch) | |
tree | 79a99db08ec985f2e5f1e216823b1104d5b753fb /engines/tsage/sound.h | |
parent | f2f3124246a77036f843dee2d83ad28084234ebc (diff) | |
parent | c32a3ea0d30336771bab460ecccb58c4614e6294 (diff) | |
download | scummvm-rg350-b0c9c9122fc678074aba30068e5b36d347208e65.tar.gz scummvm-rg350-b0c9c9122fc678074aba30068e5b36d347208e65.tar.bz2 scummvm-rg350-b0c9c9122fc678074aba30068e5b36d347208e65.zip |
Merge branch 'master' of github.com:scummvm/scummvm into soltys_wip2
Diffstat (limited to 'engines/tsage/sound.h')
-rw-r--r-- | engines/tsage/sound.h | 470 |
1 files changed, 468 insertions, 2 deletions
diff --git a/engines/tsage/sound.h b/engines/tsage/sound.h index 03ae77b703..27f30b9b08 100644 --- a/engines/tsage/sound.h +++ b/engines/tsage/sound.h @@ -24,23 +24,489 @@ #define TSAGE_SOUND_H #include "common/scummsys.h" +#include "common/mutex.h" +#include "common/queue.h" +#include "audio/audiostream.h" +#include "audio/fmopl.h" +#include "audio/mixer.h" +#include "common/list.h" #include "tsage/saveload.h" +#include "tsage/core.h" namespace tSage { +class Sound; + +#define SOUND_ARR_SIZE 16 +#define ROLAND_DRIVER_NUM 2 +#define ADLIB_DRIVER_NUM 3 + +struct trackInfoStruct { + int _numTracks; + int _chunks[SOUND_ARR_SIZE]; + int _voiceTypes[SOUND_ARR_SIZE]; +}; + +enum SoundDriverStatus {SNDSTATUS_FAILED = 0, SNDSTATUS_DETECTED = 1, SNDSTATUS_SKIPPED = 2}; +enum VoiceType {VOICETYPE_0 = 0, VOICETYPE_1 = 1}; + +class SoundDriverEntry { +public: + int driverNum; + SoundDriverStatus status; + int field2, field6; + Common::String shortDescription; + Common::String longDescription; +}; + +struct GroupData { + uint32 groupMask; + byte v1; + byte v2; + const byte *pData; +}; + +struct RegisterValue { + uint8 _regNum; + uint8 _value; + + RegisterValue(int regNum, int value) { + _regNum = regNum; _value = value; + } +}; + +class SoundDriver { +public: + Common::String _shortDescription, _longDescription; + int _minVersion, _maxVersion; + // The following fields were originally held in separate arrays in the SoundManager class + uint32 _groupMask; + const GroupData *_groupOffset; + int _driverResID; +public: + SoundDriver(); + virtual ~SoundDriver() {}; + + const Common::String &getShortDriverDescription() { return _shortDescription; } + const Common::String &getLongDriverDescription() { return _longDescription; } + + virtual bool open() { return true; } // Method #0 + virtual void close() {} // Method #1 + virtual bool reset() { return true; } // Method #2 + virtual const GroupData *getGroupData() { return NULL; } // Method #3 + virtual void installPatch(const byte *data, int size) {} // Method #4 + virtual void poll() {} // Method #5 + virtual void proc12() {} // Method #6 + virtual int setMasterVolume(int volume) { return 0; } // Method #7 + virtual void proc16() {} // Method #8 + virtual void proc18(int al, VoiceType voiceType) {} // Method #9 + virtual void proc20(int al, VoiceType voiceType) {} // Method #10 + virtual void proc22(int al, VoiceType voiceType, int v3) {} // Method #11 + virtual void proc24(int channel, int voiceIndex, Sound *sound, int v1, int v2) {} + virtual void setProgram(int channel, int program) {} // Method #13 + virtual void setVolume1(int channel, int v2, int v3, int volume) {} + virtual void setPitchBlend(int channel, int pitchBlend) {} // Method #15 + virtual void proc32(int channel, int program, int v0, int v1) {}// Method #16 + virtual void updateVoice(int channel) {} // Method #17 + virtual void proc36() {} // Method #18 + virtual void proc38(int channel, int cmd, int value) {} // Method #19 + virtual void setPitch(int channel, int pitchBlend) {} // Method #20 + virtual void proc42(int channel, int v0, int v1) {} // Method #21 +}; + +struct VoiceStructEntryType0 { + Sound *_sound; + int _channelNum; + int _priority; + int _fieldA; + Sound *_sound2; + int _channelNum2; + int _priority2; + int _field12; + Sound *_sound3; + int _channelNum3; + int _priority3; + int _field1A; +}; + +struct VoiceStructEntryType1 { + int _field4; + int _field5; + int _field6; + Sound *_sound; + int _channelNum; + int _priority; + Sound *_sound2; + int _channelNum2; + int _priority2; + Sound *_sound3; + int _channelNum3; + int _priority3; +}; + +struct VoiceStructEntry { + int _voiceNum; + int _field1; + SoundDriver *_driver; + + VoiceStructEntryType0 _type0; + VoiceStructEntryType1 _type1; +}; + +class VoiceTypeStruct { +public: + VoiceType _voiceType; + int _total; + int _numVoices; + int _field3; + + Common::Array<VoiceStructEntry> _entries; +}; + class SoundManager : public SaveListener { +private: + SoundDriver *instantiateDriver(int driverNum); public: - void dispatch() {} + bool __sndmgrReady; + int _ourSndResVersion, _ourDrvResVersion; + SynchronizedList<Sound *> _playList; + Common::List<SoundDriver *> _installedDrivers; + VoiceTypeStruct *_voiceTypeStructPtrs[SOUND_ARR_SIZE]; + uint32 _groupsAvail; + int _masterVol; + int _newVolume; + Common::Mutex _serverDisabledMutex; + Common::Mutex _serverSuspendedMutex; + bool _driversDetected; + SynchronizedList<Sound *> _soundList; + Common::List<SoundDriverEntry> _availableDrivers; + bool _needToRethink; + // Misc flags + bool _soTimeIndexFlag; +public: + SoundManager(); + ~SoundManager(); + + void dispatch(); virtual void listenerSynchronize(Serializer &s); virtual void postInit(); + void syncSounds(); + void update(); - void proc2() {} static void saveNotifier(bool postFlag); void saveNotifierProc(bool postFlag); static void loadNotifier(bool postFlag); void loadNotifierProc(bool postFlag); + + void installConfigDrivers(); + Common::List<SoundDriverEntry> &buildDriverList(bool detectFlag); + Common::List<SoundDriverEntry> &getDriverList(bool detectFlag); + void dumpDriverList(); + void installDriver(int driverNum); + bool isInstalled(int driverNum) const; + void unInstallDriver(int driverNum); + void checkResVersion(const byte *soundData); + int determineGroup(const byte *soundData); + int extractPriority(const byte *soundData); + int extractLoop(const byte *soundData); + bool isOnPlayList(Sound *sound); + void extractTrackInfo(trackInfoStruct *trackInfo, const byte *soundData, int groupNum); + void addToSoundList(Sound *sound); + void removeFromSoundList(Sound *sound); + void addToPlayList(Sound *sound); + void removeFromPlayList(Sound *sound); + void rethinkVoiceTypes(); + void updateSoundVol(Sound *sound); + void updateSoundPri(Sound *sound); + void updateSoundLoop(Sound *sound); + void setMasterVol(int volume); + int getMasterVol() const; + void loadSound(int soundNum, bool showErrors); + void unloadSound(int soundNum); + + // _sf methods + static SoundManager &sfManager(); + static void _sfTerminate(); + static int _sfDetermineGroup(const byte *soundData); + static void _sfAddToPlayList(Sound *sound); + static void _sfRemoveFromPlayList(Sound *sound); + static bool _sfIsOnPlayList(Sound *sound); + static void _sfRethinkSoundDrivers(); + static void _sfRethinkVoiceTypes(); + static void _sfUpdateVolume(Sound *sound); + static void _sfDereferenceAll(); + static void _sfUpdatePriority(Sound *sound); + static void _sfUpdateLoop(Sound *sound); + static void _sfSetMasterVol(int volume); + static void _sfExtractTrackInfo(trackInfoStruct *trackInfo, const byte *soundData, int groupNum); + static void _sfExtractGroupMask(); + static bool _sfInstallDriver(SoundDriver *driver); + static void _sfUnInstallDriver(SoundDriver *driver); + static void _sfInstallPatchBank(SoundDriver *driver, const byte *bankData); + static void _sfDoAddToPlayList(Sound *sound); + static bool _sfDoRemoveFromPlayList(Sound *sound); + static void _sfDoUpdateVolume(Sound *sound); + static void _sfSoundServer(); + static void _sfProcessFading(); + static void _sfUpdateVoiceStructs(); + static void _sfUpdateVoiceStructs2(); + static void _sfUpdateCallback(void *ref); }; +class Sound: public EventHandler { +private: + void _prime(int soundResID, bool dontQueue); + void _unPrime(); +public: + bool _stoppedAsynchronously; + int _soundResID; + int _group; + int _sndResPriority; + int _fixedPriority; + int _sndResLoop; + int _fixedLoop; + int _priority; + int _volume; + int _loop; + int _pausedCount; + int _mutedCount; + int _hold; + int _cueValue; + int _fadeDest; + int _fadeSteps; + int _fadeTicks; + int _fadeCounter; + bool _stopAfterFadeFlag; + uint32 _timer; + uint32 _newTimeIndex; + int _loopTimer; + int _chProgram[SOUND_ARR_SIZE]; + int _chModulation[SOUND_ARR_SIZE]; + int _chVolume[SOUND_ARR_SIZE]; + int _chPan[SOUND_ARR_SIZE]; + int _chDamper[SOUND_ARR_SIZE]; + int _chPitchBlend[SOUND_ARR_SIZE]; + int _chVoiceType[SOUND_ARR_SIZE]; + int _chNumVoices[SOUND_ARR_SIZE]; + int _chSubPriority[SOUND_ARR_SIZE]; + int _chFlags[SOUND_ARR_SIZE]; + bool _chWork[SOUND_ARR_SIZE]; + trackInfoStruct _trackInfo; + byte *_channelData[SOUND_ARR_SIZE]; + int _trkChannel[SOUND_ARR_SIZE]; + int _trkState[SOUND_ARR_SIZE]; + int _trkLoopState[SOUND_ARR_SIZE]; + int _trkIndex[SOUND_ARR_SIZE]; + int _trkLoopIndex[SOUND_ARR_SIZE]; + int _trkRest[SOUND_ARR_SIZE]; + int _trkLoopRest[SOUND_ARR_SIZE]; + + bool _primed; + bool _isEmpty; + byte *_remoteReceiver; +public: + Sound(); + ~Sound(); + + void synchronize(Serializer &s); + void orientAfterRestore(); + + void play(int soundResID); + void stop(); + void prime(int soundResID); + void unPrime(); + void go(); + void halt(void); + bool isPlaying(); + int getSoundNum() const; + bool isPrimed() const; + bool isPaused() const; + bool isMuted() const; + void pause(bool flag); + void mute(bool flag); + void fade(int fadeDest, int fadeSteps, int fadeTicks, bool stopAfterFadeFlag); + void setTimeIndex(uint32 timeIndex); + uint32 getTimeIndex() const; + int getCueValue() const; + void setCueValue(int cueValue); + void setVol(int volume); + int getVol() const; + void setPri(int priority); + void setLoop(int flag); + int getPri() const; + int getLoop(); + void holdAt(int amount); + void release(); + void orientAfterDriverChange(); + + // _so methods + void _soPrimeSound(bool dontQueue); + void _soSetTimeIndex(uint timeIndex); + bool _soServiceTracks(); + void _soPrimeChannelData(); + void _soRemoteReceive(); + void _soServiceTrackType0(int trackIndex, const byte *channelData); + void _soUpdateDamper(VoiceTypeStruct *voiceType, int channelNum, VoiceType mode, int v0); + void _soProc32(VoiceTypeStruct *vtStruct, int channelNum, VoiceType voiceType, int v0, int v1); + void _soProc42(VoiceTypeStruct *vtStruct, int channelNum, VoiceType voiceType, int v0); + void _soProc38(VoiceTypeStruct *vtStruct, int channelNum, VoiceType voiceType, int cmd, int value); + void _soProc40(VoiceTypeStruct *vtStruct, int channelNum, int pitchBlend); + void _soDoTrackCommand(int channelNum, int command, int value); + bool _soDoUpdateTracks(int command, int value); + void _soSetTrackPos(int trackIndex, int trackPos, int cueValue); + + void _soServiceTrackType1(int trackIndex, const byte *channelData); + int _soFindSound(VoiceTypeStruct *vtStruct, int channelNum); +}; + +class ASound: public EventHandler { +public: + Sound _sound; + Action *_action; + int _cueValue; + + ASound(); + ~ASound(); + virtual void synchronize(Serializer &s); + virtual void dispatch(); + + void play(int soundNum, Action *action = NULL, int volume = 127); + void stop(); + void prime(int soundNum, Action *action = NULL); + void unPrime(); + void go() { _sound.go(); } + void hault(void) { _sound.halt(); } + bool isPlaying() { return _sound.isPlaying(); } + int getSoundNum() const { return _sound.getSoundNum(); } + bool isPaused() const { return _sound.isPaused(); } + bool isMuted() const { return _sound.isMuted(); } + void pause(bool flag) { _sound.pause(flag); } + void mute(bool flag) { _sound.mute(flag); } + void fade(int fadeDest, int fadeSteps, int fadeTicks, bool stopAfterFadeFlag, Action *action); + void fadeIn() { fade(127, 5, 10, false, NULL); } + void fadeOut(Action *action) { fade(0, 5, 10, true, action); } + void setTimeIndex(uint32 timeIndex) { _sound.setTimeIndex(timeIndex); } + uint32 getTimeIndex() const { return _sound.getTimeIndex(); } + void setPri(int v) { _sound.setPri(v); } + void setLoop(int total) { _sound.setLoop(total); } + int getPri() const { return _sound.getPri(); } + int getLoop() { return _sound.getLoop(); } + void setVol(int volume) { _sound.setVol(volume); } + int getVol() const { return _sound.getVol(); } + void holdAt(int v) { _sound.holdAt(v); } + void release() { _sound.release(); } +}; + +#define ADLIB_CHANNEL_COUNT 9 + +class AdlibSoundDriver: public SoundDriver, Audio::AudioStream { +private: + GroupData _groupData; + Audio::Mixer *_mixer; + FM_OPL *_opl; + Audio::SoundHandle _soundHandle; + int _sampleRate; + byte _portContents[256]; + const byte *_patchData; + int _masterVolume; + Common::Queue<RegisterValue> _queue; + + bool _channelVoiced[ADLIB_CHANNEL_COUNT]; + int _channelVolume[ADLIB_CHANNEL_COUNT]; + int _v4405E[ADLIB_CHANNEL_COUNT]; + int _v44067[ADLIB_CHANNEL_COUNT]; + int _v44070[ADLIB_CHANNEL_COUNT]; + int _v44079[ADLIB_CHANNEL_COUNT]; + int _v44082[ADLIB_CHANNEL_COUNT + 1]; + int _pitchBlend[ADLIB_CHANNEL_COUNT]; + int _v4409E[ADLIB_CHANNEL_COUNT]; + + + void write(byte reg, byte value); + void flush(); + void updateChannelVolume(int channel); + void setVoice(int channel); + void clearVoice(int channel); + void updateChannel(int channel); + void setFrequency(int channel); +public: + AdlibSoundDriver(); + virtual ~AdlibSoundDriver(); + + virtual bool open(); + virtual void close(); + virtual bool reset(); + virtual const GroupData *getGroupData(); + virtual void installPatch(const byte *data, int size); + virtual int setMasterVolume(int volume); + virtual void proc32(int channel, int program, int v0, int v1); + virtual void updateVoice(int channel); + virtual void proc38(int channel, int cmd, int value); + virtual void setPitch(int channel, int pitchBlend); + + // AudioStream interface + virtual int readBuffer(int16 *buffer, const int numSamples); + virtual bool isStereo() const { return false; } + virtual bool endOfData() const { return false; } + virtual int getRate() const { return _sampleRate; } + + void update(int16 *buf, int len); +}; + +class AdlibFxSoundDriver: public SoundDriver, Audio::AudioStream { +private: + GroupData _groupData; + Audio::Mixer *_mixer; + FM_OPL *_opl; + Audio::SoundHandle _soundHandle; + int _sampleRate; + byte _portContents[256]; + int _masterVolume; + Common::Queue<RegisterValue> _queue; + + bool _channelVoiced[ADLIB_CHANNEL_COUNT]; + int _channelVolume[ADLIB_CHANNEL_COUNT]; + int _v4405E[ADLIB_CHANNEL_COUNT]; + int _v44067[ADLIB_CHANNEL_COUNT]; + int _v44070[ADLIB_CHANNEL_COUNT]; + int _v44079[ADLIB_CHANNEL_COUNT]; + int _v44082[ADLIB_CHANNEL_COUNT + 1]; + int _pitchBlend[ADLIB_CHANNEL_COUNT]; + int _v4409E[ADLIB_CHANNEL_COUNT]; + + + void write(byte reg, byte value); + void flush(); + void updateChannelVolume(int channel); + void setVoice(int channel); + void clearVoice(int channel); + void updateChannel(int channel); + void setFrequency(int channel); +public: + AdlibFxSoundDriver(); + virtual ~AdlibFxSoundDriver(); + + virtual bool open(); + virtual void close(); + virtual bool reset(); + virtual const GroupData *getGroupData(); + virtual void installPatch(const byte *data, int size) {} + virtual int setMasterVolume(int volume); + virtual void proc32(int channel, int program, int v0, int v1); + virtual void updateVoice(int channel); + virtual void proc38(int channel, int cmd, int value); + virtual void setPitch(int channel, int pitchBlend); + + // AudioStream interface + virtual int readBuffer(int16 *buffer, const int numSamples); + virtual bool isStereo() const { return false; } + virtual bool endOfData() const { return false; } + virtual int getRate() const { return _sampleRate; } + + void update(int16 *buf, int len); +}; + + } // End of namespace tSage #endif |