aboutsummaryrefslogtreecommitdiff
path: root/engines/gob/music.h
diff options
context:
space:
mode:
Diffstat (limited to 'engines/gob/music.h')
-rw-r--r--engines/gob/music.h200
1 files changed, 181 insertions, 19 deletions
diff --git a/engines/gob/music.h b/engines/gob/music.h
index f2db978f75..89d8e2933c 100644
--- a/engines/gob/music.h
+++ b/engines/gob/music.h
@@ -30,29 +30,194 @@
#include "common/mutex.h"
#include "gob/gob.h"
+#include "gob/util.h"
namespace Gob {
class GobEngine;
-class Music : public Audio::AudioStream {
+// Emulation of the "Paula" Amiga music chip
+class Paula: public Audio::AudioStream {
public:
- Music(GobEngine *vm);
- virtual ~Music();
+ Paula(GobEngine *vm, bool stereo = false, int intFreq = 0);
+ ~Paula();
+
+ bool playing() const { return _playing; }
+ void setInterruptFreq(int freq) { _intFreq = freq; }
+ void clearVoice(int voice);
+ void clearVoices() { int i; for (i = 0; i < 4; i++) clearVoice(i); }
+ virtual void startPlay(void) {}
+ virtual void stopPlay(void) {}
+ virtual void pausePlay(bool pause) {}
+
+// AudioStream API
+ int readBuffer(int16 *buffer, const int numSamples);
+ bool isStereo() const { return _stereo; }
+ bool endOfData() const { return _end; }
+ int getRate() const { return _rate; }
+
+protected:
+ struct Channel {
+ int8 *data;
+ int8 *dataRepeat;
+ uint32 length;
+ uint32 lengthRepeat;
+ int16 period;
+ byte volume;
+ double offset;
+ byte panning; // For stereo mixing; 0: left, 1: right
+ } _voice[4];
+
+ int _rate;
+ int _intFreq;
+ int _curInt;
+ bool _stereo;
+ bool _end;
+ bool _playing;
+
+ GobEngine *_vm;
+
+ void mix(int16 *&buf, int8 data, int voice) {
+ if (_stereo) {
+ *buf++ += _voice[voice].panning == 0 ? 2 * _voice[voice].volume * data : 0;
+ *buf++ += _voice[voice].panning == 1 ? 2 * _voice[voice].volume * data : 0;
+ } else
+ *buf++ += _voice[voice].volume * data;
+ }
+ virtual void interrupt(void) {};
+};
+
+class Infogrames : public Paula {
+public:
+ class Instruments {
+ public:
+ struct Sample {
+ int8 *data;
+ int8 *dataRepeat;
+ uint32 length;
+ uint32 lengthRepeat;
+ } _samples[32];
+
+ uint8 _count;
+ int8 *_sampleData;
+
+ Instruments();
+ ~Instruments();
+
+ bool load(Common::SeekableReadStream &ins);
+ bool load(const char *ins) {
+ Common::File f;
+
+ if (f.open(ins))
+ return load(f);
+ return false;
+ }
+ };
+
+ Infogrames(GobEngine *vm, bool stereo = false);
+ ~Infogrames();
+
+ Instruments *getInstruments(void) const { return _instruments; }
+ bool getRepeating(void) const { return _repCount != 0; }
+ void setRepeating (int32 repCount) { _repCount = repCount; }
+ void restart(void) { if (!_data || !_instruments) return; init(); _end = false; }
+ virtual void startPlay(void) { if (_data && _instruments) { restart(); _playing = true; } }
+ virtual void stopPlay(void) { _playing = false; }
+ virtual void pausePlay(bool pause) { _playing = !pause; }
+
+ bool load(Common::SeekableReadStream &dum);
+ bool load(const char *dum) {
+ Common::File f;
+
+ if (f.open(dum))
+ return load(f);
+ return false;
+ }
+ void unload(bool destroyInstruments = false);
+ template<typename T> bool loadInstruments(T ins) {
+ unload(true);
+ _instruments = new Instruments();
+ if (!_instruments->load(ins)) {
+ delete _instruments;
+ _instruments = 0;
+ return false;
+ }
+ return true;
+ }
+
+protected:
+ Instruments *_instruments;
+
+ static const uint8 tickCount[];
+ static const uint16 periods[];
+ byte *_data;
+ int32 _repCount;
+
+ uint16 _volume;
+ int16 _period;
+ byte *_volSlideBlocks;
+ byte *_periodSlideBlocks;
+ byte *_subSong;
+ byte *_cmdBlocks;
+ uint8 _sample;
+ uint8 _speedCounter;
+ uint8 _speed;
+ uint8 _newVol;
+ uint8 _field_1E;
+
+ struct Slide {
+ int16 finetuneNeg;
+ int16 finetunePos;
+ byte *data;
+ int8 amount;
+ uint8 dataOffset;
+ uint8 flags; // 0: Apply finetune modifier, 2: Don't slide, 7: Continuous
+ uint8 curDelay1;
+ uint8 curDelay2;
+ };
+ struct Channel {
+ byte *cmdBlockIndices;
+ byte *cmds;
+ byte *cmdBlocks;
+ Slide volSlide;
+ Slide periodSlide;
+ int16 curPeriod;
+ int16 period;
+ uint16 curCmdBlock;
+ uint16 flags; // 0: Need init, 5: Loop cmdBlocks, 6: Ignore channel
+ uint8 ticks;
+ uint8 tickCount;
+ int8 periodMod;
+ uint8 field_2B;
+ uint8 field_2C;
+ uint8 field_2F;
+ } _chn[4];
+
+ void init(void);
+ void reset(void);
+ void getNextSample(Channel &chn);
+ int16 tune(Slide &slide, int16 start) const;
+ virtual void interrupt(void);
+};
+
+class Adlib : public Audio::AudioStream {
+public:
+ Adlib(GobEngine *vm);
+ virtual ~Adlib();
void lock() { _mutex.lock(); }
void unlock() { _mutex.unlock(); }
- bool playing() { return _playing; }
- bool getRepeating(void) { return _repCount != 0; }
+ bool playing() const { return _playing; }
+ bool getRepeating(void) const { return _repCount != 0; }
void setRepeating (int32 repCount) { _repCount = repCount; }
- int getIndex(void) { return _index; }
+ int getIndex(void) const { return _index; }
virtual void startPlay(void);
virtual void stopPlay(void) { _mutex.lock(); _playing = false; _mutex.unlock(); }
virtual void playTrack(const char *trackname);
virtual void playBgMusic(void);
- virtual bool loadMusic(const char *filename);
- virtual void loadFromMemory(byte *data, int index=-1);
- virtual void unloadMusic(void);
+ virtual bool load(const char *filename);
+ virtual void load(byte *data, int index=-1);
+ virtual void unload(void);
// AudioStream API
int readBuffer(int16 *buffer, const int numSamples) {
@@ -100,22 +265,19 @@ protected:
void pollMusic(void);
};
-class Music_Dummy: public Music {
+class Adlib_Dummy: public Adlib {
public:
- Music_Dummy(GobEngine *vm) : Music(vm) {
- _vm->_mixer->setupPremix(0);
- OPLDestroy(_opl);
- }
+ Adlib_Dummy(GobEngine *vm) : Adlib(vm) {}
virtual void startPlay(void) {};
virtual void stopPlay(void) {};
virtual void playTrack(const char *trackname) {};
- virtual void playBgMusic(void) {};
- virtual bool loadMusic(const char *filename) { return true; };
- virtual void loadFromMemory(byte *data) {};
- virtual void unloadMusic(void) {};
+ virtual void playBgAdlib(void) {};
+ virtual bool load(const char *filename) { return true; }
+ virtual void load(byte *data, int index=-1) {}
+ virtual void unload(void) {};
- virtual ~Music_Dummy() {};
+ virtual ~Adlib_Dummy() {};
};
} // End of namespace Gob