aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorSven Hesse2007-01-30 22:19:55 +0000
committerSven Hesse2007-01-30 22:19:55 +0000
commitcb8378065d2831fa1512dfce138cc0039eff98fb (patch)
tree8a2f720ee83cf583284c2721d6150959b3a8f7f1 /engines
parentb4bebad6f0c3ab23b6992575c9fee88ace8f49d2 (diff)
downloadscummvm-rg350-cb8378065d2831fa1512dfce138cc0039eff98fb.tar.gz
scummvm-rg350-cb8378065d2831fa1512dfce138cc0039eff98fb.tar.bz2
scummvm-rg350-cb8378065d2831fa1512dfce138cc0039eff98fb.zip
- Changed _soundFlags and implemented "compositions"
- Changed Snd to be a permanent audiostream, to have better control over stopping, looping and compositions - Some clean-up svn-id: r25292
Diffstat (limited to 'engines')
-rw-r--r--engines/gob/game.cpp7
-rw-r--r--engines/gob/game_v1.cpp2
-rw-r--r--engines/gob/game_v2.cpp8
-rw-r--r--engines/gob/global.cpp3
-rw-r--r--engines/gob/global.h1
-rw-r--r--engines/gob/gob.cpp15
-rw-r--r--engines/gob/init.cpp13
-rw-r--r--engines/gob/init_v1.cpp15
-rw-r--r--engines/gob/init_v2.cpp18
-rw-r--r--engines/gob/inter_v1.cpp2
-rw-r--r--engines/gob/inter_v2.cpp11
-rw-r--r--engines/gob/mult_v2.cpp1
-rw-r--r--engines/gob/music.cpp114
-rw-r--r--engines/gob/music.h37
-rw-r--r--engines/gob/sound.cpp163
-rw-r--r--engines/gob/sound.h41
16 files changed, 245 insertions, 206 deletions
diff --git a/engines/gob/game.cpp b/engines/gob/game.cpp
index e239248807..205258d628 100644
--- a/engines/gob/game.cpp
+++ b/engines/gob/game.cpp
@@ -351,6 +351,13 @@ void Game::freeSoundSlot(int16 slot) {
if ((slot < 0) || (slot >= 60) || (_soundSamples[slot] == 0))
return;
+ if (slot == _vm->_snd->getCompositionSlot()) {
+ if (_vm->_quitRequested)
+ _vm->_snd->stopComposition();
+ else
+ _vm->_snd->waitEndPlay();
+ }
+
if (_soundADL[slot]) {
if (_vm->_adlib && (_vm->_adlib->getIndex() == slot))
_vm->_adlib->stopPlay();
diff --git a/engines/gob/game_v1.cpp b/engines/gob/game_v1.cpp
index 7c807aef70..47f5475950 100644
--- a/engines/gob/game_v1.cpp
+++ b/engines/gob/game_v1.cpp
@@ -579,8 +579,6 @@ int16 Game_v1::checkCollisions(char handleMouse, int16 deltaTime, int16 *pResId,
_vm->_draw->animateCursor(-1);
_vm->_util->delay(10);
-
- _vm->_snd->loopSounds();
}
}
diff --git a/engines/gob/game_v2.cpp b/engines/gob/game_v2.cpp
index 1669da9e40..f9aa540308 100644
--- a/engines/gob/game_v2.cpp
+++ b/engines/gob/game_v2.cpp
@@ -92,18 +92,12 @@ void Game_v2::playTot(int16 skipPlay) {
_vm->_mult->initAll();
_vm->_mult->zeroMultData();
-/* for (i = 0; i < 50; i++)
- _vm->_draw->_spritesArray[i] = 0;*/
-
_vm->_draw->_spritesArray[20] = _vm->_draw->_frontSurface;
_vm->_draw->_spritesArray[21] = _vm->_draw->_backSurface;
_vm->_draw->_cursorSpritesBack = _vm->_draw->_cursorSprites;
} else
_vm->_inter->initControlVars(0);
- for (i = 0; i < 20; i++)
- _soundSamples[i] = 0;
-
_totTextData = 0;
_totResourceTable = 0;
_imFileData = 0;
@@ -661,8 +655,6 @@ int16 Game_v2::checkCollisions(char handleMouse, int16 deltaTime, int16 *pResId,
_vm->_draw->animateCursor(-1);
_vm->_util->delay(10);
-
- _vm->_snd->loopSounds();
}
}
diff --git a/engines/gob/global.cpp b/engines/gob/global.cpp
index d78b3eca29..6b2c54ecdd 100644
--- a/engines/gob/global.cpp
+++ b/engines/gob/global.cpp
@@ -37,8 +37,7 @@ Global::Global(GobEngine *vm) : _vm(vm) {
_videoMode = 0;
/* Sound */
- _presentSound = 0x8000; /* undefined values */
- _soundFlags = 0x8000;
+ _soundFlags = 0;
_blasterPort = 0;
_disableSoundCfg = 0;
diff --git a/engines/gob/global.h b/engines/gob/global.h
index 4fd5455201..aa1c6d95ca 100644
--- a/engines/gob/global.h
+++ b/engines/gob/global.h
@@ -80,7 +80,6 @@ public:
int16 _disableVideoCfg;
- uint16 _presentSound;
uint16 _soundFlags;
int16 _disableSoundCfg;
int16 _blasterPort;
diff --git a/engines/gob/gob.cpp b/engines/gob/gob.cpp
index 82302b3616..90ca277a9e 100644
--- a/engines/gob/gob.cpp
+++ b/engines/gob/gob.cpp
@@ -614,14 +614,10 @@ int GobEngine::init() {
else
error("GobEngine::init(): Unknown version of game engine");
_noMusic = MidiDriver::parseMusicDriver(ConfMan.get("music_driver")) == MD_NULL;
- if (!(_features & Gob::GF_AMIGA) &&
- (((_features & Gob::GF_MAC) && (_features & Gob::GF_GOB1)) ||
- (_features & Gob::GF_GOB2))) {
- if (_noMusic)
- _adlib = new Adlib_Dummy(this);
- else
- _adlib = new Adlib(this);
- }
+ if (!_noMusic && !(_features & Gob::GF_AMIGA) &&
+ (((_features & Gob::GF_MAC) && (_features & Gob::GF_GOB1)) ||
+ (_features & Gob::GF_GOB2)))
+ _adlib = new Adlib(this);
_vm = this;
_system->beginGFXTransaction();
@@ -642,7 +638,7 @@ int GobEngine::init() {
_global->_videoMode = 0x13;
_global->_useMouse = 1;
- _global->_soundFlags = 0;
+ _global->_soundFlags = MIDI_FLAG | SPEAKER_FLAG | BLASTER_FLAG | ADLIB_FLAG;
if (ConfMan.hasKey("language"))
_language = Common::parseLanguage(ConfMan.get("language"));
@@ -687,7 +683,6 @@ int GobEngine::init() {
// 640x480.
g_system->setFeatureState(OSystem::kFeatureAutoComputeDirtyRects, true);
-
return 0;
}
diff --git a/engines/gob/init.cpp b/engines/gob/init.cpp
index a026354eb2..c093f80851 100644
--- a/engines/gob/init.cpp
+++ b/engines/gob/init.cpp
@@ -50,18 +50,7 @@ Init::Init(GobEngine *vm) : _vm(vm) {
void Init::findBestCfg(void) {
_vm->_global->_videoMode = VIDMODE_VGA;
_vm->_global->_useMouse = _vm->_global->_mousePresent;
- if (_vm->_global->_presentSound & BLASTER_FLAG)
- _vm->_global->_soundFlags = BLASTER_FLAG | SPEAKER_FLAG | MIDI_FLAG;
- else if (_vm->_global->_presentSound & PROAUDIO_FLAG)
- _vm->_global->_soundFlags = PROAUDIO_FLAG | SPEAKER_FLAG | MIDI_FLAG;
- else if (_vm->_global->_presentSound & ADLIB_FLAG)
- _vm->_global->_soundFlags = ADLIB_FLAG | SPEAKER_FLAG | MIDI_FLAG;
- else if (_vm->_global->_presentSound & INTERSOUND_FLAG)
- _vm->_global->_soundFlags = INTERSOUND_FLAG | SPEAKER_FLAG;
- else if (_vm->_global->_presentSound & SPEAKER_FLAG)
- _vm->_global->_soundFlags = SPEAKER_FLAG;
- else
- _vm->_global->_soundFlags = 0;
+ _vm->_global->_soundFlags = MIDI_FLAG | SPEAKER_FLAG | BLASTER_FLAG | ADLIB_FLAG;
}
void Init::cleanup(void) {
diff --git a/engines/gob/init_v1.cpp b/engines/gob/init_v1.cpp
index 73a09dd34b..c6c7481e22 100644
--- a/engines/gob/init_v1.cpp
+++ b/engines/gob/init_v1.cpp
@@ -41,20 +41,13 @@ void Init_v1::soundVideo(int32 smallHeap, int16 flag) {
error("soundVideo: Video mode 0x%x is not supported!",
_vm->_global->_videoMode);
- //if ((flag & 4) == 0)
- // _vm->_video->findVideo();
-
_vm->_global->_mousePresent = 1;
_vm->_global->_inVM = 0;
- _vm->_global->_presentSound = 0; // FIXME: sound is not supported yet
-
_vm->_global->_sprAllocated = 0;
_vm->_gtimer->enableTimer();
- // _vm->_snd->setResetTimerFlag(debugFlag); // TODO
-
if (_vm->_global->_videoMode == 0x13)
_vm->_global->_colorCount = 256;
@@ -66,14 +59,6 @@ void Init_v1::soundVideo(int32 smallHeap, int16 flag) {
if (_vm->_global->_videoMode != 0)
_vm->_video->initSurfDesc(_vm->_global->_videoMode, 320, 200, PRIMARY_SURFACE);
-
- if (_vm->_global->_soundFlags & MIDI_FLAG) {
- _vm->_global->_soundFlags &= _vm->_global->_presentSound;
- if (_vm->_global->_presentSound & ADLIB_FLAG)
- _vm->_global->_soundFlags |= MIDI_FLAG;
- } else {
- _vm->_global->_soundFlags &= _vm->_global->_presentSound;
- }
}
} // End of namespace Gob
diff --git a/engines/gob/init_v2.cpp b/engines/gob/init_v2.cpp
index 86cc7d7dbb..129f75ebd5 100644
--- a/engines/gob/init_v2.cpp
+++ b/engines/gob/init_v2.cpp
@@ -45,40 +45,24 @@ void Init_v2::soundVideo(int32 smallHeap, int16 flag) {
_vm->_draw->_frontSurface = &_vm->_global->_primarySurfDesc;
_vm->_video->initSurfDesc(_vm->_global->_videoMode, _vm->_video->_surfWidth, 200, 0x80);
- //if ((flag & 4) == 0)
- // _vm->_video->findVideo();
-
_vm->_global->_mousePresent = 1;
_vm->_global->_inVM = 0;
- _vm->_global->_presentSound = 0; // FIXME: sound is not supported yet
-
_vm->_global->_sprAllocated = 0;
_vm->_gtimer->enableTimer();
- // _vm->_snd->setResetTimerFlag(debugFlag); // TODO
-
- if (_vm->_global->_videoMode == 0x13)
+ if ((_vm->_global->_videoMode == 0x13) || (_vm->_global->_videoMode == 0x14))
_vm->_global->_colorCount = 256;
_vm->_global->_pPaletteDesc = &_vm->_global->_paletteStruct;
_vm->_global->_pPaletteDesc->vgaPal = _vm->_draw->_vgaPalette;
_vm->_global->_pPaletteDesc->unused1 = _vm->_global->_unusedPalette1;
_vm->_global->_pPaletteDesc->unused2 = _vm->_global->_unusedPalette2;
-// _vm->_global->_pPrimarySurfDesc = &_vm->_global->_primarySurfDesc;
if (_vm->_global->_videoMode != 0)
_vm->_video->initSurfDesc(_vm->_global->_videoMode, _vm->_video->_surfWidth, 200,
PRIMARY_SURFACE);
-
- if (_vm->_global->_soundFlags & MIDI_FLAG) {
- _vm->_global->_soundFlags &= _vm->_global->_presentSound;
- if (_vm->_global->_presentSound & ADLIB_FLAG)
- _vm->_global->_soundFlags |= MIDI_FLAG;
- } else {
- _vm->_global->_soundFlags &= _vm->_global->_presentSound;
- }
}
} // End of namespace Gob
diff --git a/engines/gob/inter_v1.cpp b/engines/gob/inter_v1.cpp
index 408dcd481c..788f9a0f2a 100644
--- a/engines/gob/inter_v1.cpp
+++ b/engines/gob/inter_v1.cpp
@@ -1205,7 +1205,7 @@ bool Inter_v1::o1_playComposition(char &cmdCount, int16 &counter, int16 &retFlag
for (i = 0; i < 50; i++)
composition[i] = (int16)VAR_OFFSET(dataVar + i * 4);
- _vm->_snd->playComposition(_vm->_game->_soundSamples, composition, freqVal);
+ _vm->_snd->playComposition(composition, freqVal);
return false;
}
diff --git a/engines/gob/inter_v2.cpp b/engines/gob/inter_v2.cpp
index f605b11720..95e13ff43a 100644
--- a/engines/gob/inter_v2.cpp
+++ b/engines/gob/inter_v2.cpp
@@ -1401,7 +1401,16 @@ bool Inter_v2::o2_checkData(char &cmdCount, int16 &counter, int16 &retFlag) {
}
bool Inter_v2::o2_stopSound(char &cmdCount, int16 &counter, int16 &retFlag) {
- _vm->_snd->stopSound(_vm->_parse->parseValExpr());
+ int16 expr;
+
+ expr = _vm->_parse->parseValExpr();
+
+ if (expr < 0) {
+ if (_vm->_adlib)
+ _vm->_adlib->stopPlay();
+ } else
+ _vm->_snd->stopSound(expr);
+
_soundEndTimeKey = 0;
return false;
}
diff --git a/engines/gob/mult_v2.cpp b/engines/gob/mult_v2.cpp
index 2d53f893f2..c082859204 100644
--- a/engines/gob/mult_v2.cpp
+++ b/engines/gob/mult_v2.cpp
@@ -522,7 +522,6 @@ void Mult_v2::playMult(int16 startFrame, int16 endFrame, char checkEscape,
stop = doFadeAnim(stop);
stop = doSoundAnim(stop, _frame);
- _vm->_snd->loopSounds();
if (_frame >= endFrame)
stopNoClear = 1;
diff --git a/engines/gob/music.cpp b/engines/gob/music.cpp
index b074a15602..67608bcd67 100644
--- a/engines/gob/music.cpp
+++ b/engines/gob/music.cpp
@@ -82,7 +82,6 @@ Adlib::Adlib(GobEngine *vm) : _vm(vm) {
_dataSize = 0;
_rate = _vm->_mixer->getOutputRate();
_opl = makeAdlibOPL(_rate);
- _vm->_mixer->setupPremix(this, Audio::Mixer::kMusicSoundType);
_first = true;
_ended = false;
_playing = false;
@@ -92,74 +91,71 @@ Adlib::Adlib(GobEngine *vm) : _vm(vm) {
for (i = 0; i < 16; i ++)
_pollNotes[i] = 0;
-
setFreqs();
+
+ _vm->_mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_handle,
+ this, -1, 255, 0, false, true);
}
Adlib::~Adlib(void) {
+ Common::StackLock slock(_mutex);
+
+ _vm->_mixer->stopHandle(_handle);
OPLDestroy(_opl);
if (_data && _needFree)
delete[] _data;
- _vm->_mixer->setupPremix(0);
}
-void Adlib::premixerCall(int16 *buf, uint len) {
- _mutex.lock();
- if (!_playing) {
- memset(buf, 0, 2 * len * sizeof(int16));
- _mutex.unlock();
- return;
+int Adlib::readBuffer(int16 *buffer, const int numSamples) {
+ Common::StackLock slock(_mutex);
+ int samples;
+ int render;
+
+ if (!_playing || (numSamples < 0)) {
+ memset(buffer, 0, numSamples * sizeof(int16));
+ return numSamples;
}
- else {
- if (_first) {
- memset(buf, 0, 2 * len * sizeof(int16));
+ if (_first) {
+ memset(buffer, 0, numSamples * sizeof(int16));
+ pollMusic();
+ return numSamples;
+ }
+
+ samples = numSamples;
+ while (samples && _playing) {
+ if (_samplesTillPoll) {
+ render = (samples > _samplesTillPoll) ? (_samplesTillPoll) : (samples);
+ samples -= render;
+ _samplesTillPoll -= render;
+ YM3812UpdateOne(_opl, buffer, render);
+ buffer += render;
+ } else {
pollMusic();
- _mutex.unlock();
- return;
- }
- else {
- uint32 render;
- int16 *data = buf;
- uint datalen = len;
- while (datalen && _playing) {
- if (_samplesTillPoll) {
- render = (datalen > _samplesTillPoll) ?
- (_samplesTillPoll) : (datalen);
- datalen -= render;
- _samplesTillPoll -= render;
- YM3812UpdateOne(_opl, data, render);
- data += render;
- } else {
- pollMusic();
- if (_ended) {
- memset(data, 0, datalen * sizeof(int16));
- datalen = 0;
- }
- }
+ if (_ended) {
+ memset(buffer, 0, samples * sizeof(int16));
+ samples = 0;
}
}
- if (_ended) {
- _first = true;
- _ended = false;
- _playPos = _data + 3 + (_data[1] + 1) * 0x38;
- _samplesTillPoll = 0;
- if (_repCount == -1) {
- reset();
- setVoices();
- } else if (_repCount > 0) {
- _repCount--;
- reset();
- setVoices();
- }
- else
- _playing = false;
- }
- // Convert mono data to stereo
- for (int i = (len - 1); i >= 0; i--) {
- buf[2 * i] = buf[2 * i + 1] = buf[i];
+ }
+
+ if (_ended) {
+ _first = true;
+ _ended = false;
+ _playPos = _data + 3 + (_data[1] + 1) * 0x38;
+ _samplesTillPoll = 0;
+ if (_repCount == -1) {
+ reset();
+ setVoices();
+ } else if (_repCount > 0) {
+ _repCount--;
+ reset();
+ setVoices();
}
+ else
+ _playing = false;
}
- _mutex.unlock();
+
+ return numSamples;
}
void Adlib::writeOPL(byte reg, byte val) {
@@ -194,6 +190,7 @@ void Adlib::setFreqs(void) {
}
void Adlib::reset() {
+ _first = true;
OPLResetChip(_opl);
_samplesTillPoll = 0;
@@ -356,21 +353,12 @@ void Adlib::pollMusic(void) {
setVolume(channel, *(_playPos++));
setKey(channel, note, true, false);
break;
- case 0x10:
- warning("GOB2 Stub! ADL command 0x10");
- break;
- case 0x50:
- warning("GOB2 Stub! ADL command 0x50");
- break;
// Note on
case 0x90:
note = *(_playPos++);
_pollNotes[channel] = note;
setKey(channel, note, true, false);
break;
- case 0x60:
- warning("GOB2 Stub! ADL command 0x60");
- break;
// Last note off
case 0x80:
note = _pollNotes[channel];
diff --git a/engines/gob/music.h b/engines/gob/music.h
index fdc2e1cbb8..89d3d7acf4 100644
--- a/engines/gob/music.h
+++ b/engines/gob/music.h
@@ -39,7 +39,7 @@ class GobEngine;
class Adlib : public Audio::AudioStream {
public:
Adlib(GobEngine *vm);
- virtual ~Adlib();
+ ~Adlib();
void lock() { _mutex.lock(); }
void unlock() { _mutex.unlock(); }
@@ -50,9 +50,8 @@ public:
virtual void startPlay(void) { if (_data) _playing = true; }
virtual void stopPlay(void)
{
- _mutex.lock();
+ Common::StackLock slock(_mutex);
_playing = false;
- _mutex.unlock();
}
virtual void playTrack(const char *trackname);
virtual void playBgMusic(void);
@@ -61,12 +60,10 @@ public:
virtual void unload(void);
// AudioStream API
- int readBuffer(int16 *buffer, const int numSamples) {
- premixerCall(buffer, numSamples / 2);
- return numSamples;
- }
- bool isStereo() const { return true; }
- bool endOfData() const { return false; }
+ int readBuffer(int16 *buffer, const int numSamples);
+ bool isStereo() const { return false; }
+ bool endOfData() const { return !_playing; }
+ bool endOfStream() const { return false; }
int getRate() const { return _rate; }
protected:
@@ -74,6 +71,7 @@ protected:
static const char *_trackFiles[];
static const unsigned char _operators[];
static const unsigned char _volRegNums [];
+ Audio::SoundHandle _handle;
FM_OPL *_opl;
int _index;
byte *_data;
@@ -86,7 +84,7 @@ protected:
byte _notLin[11];
bool _notOn[11];
byte _pollNotes[16];
- uint32 _samplesTillPoll;
+ int _samplesTillPoll;
int32 _repCount;
bool _playing;
bool _first;
@@ -95,7 +93,6 @@ protected:
Common::Mutex _mutex;
GobEngine *_vm;
- void premixerCall(int16 *buf, uint len);
void writeOPL(byte reg, byte val);
void setFreqs(void);
void reset(void);
@@ -106,24 +103,6 @@ protected:
void pollMusic(void);
};
-/**
- * A dummy class for the "null" sound driver
- */
-class Adlib_Dummy: public Adlib {
-public:
- Adlib_Dummy(GobEngine *vm) : Adlib(vm) {}
-
- virtual void startPlay(void) {};
- virtual void stopPlay(void) {};
- virtual void playTrack(const char *trackname) {};
- 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 ~Adlib_Dummy() {};
-};
-
} // End of namespace Gob
#endif
diff --git a/engines/gob/sound.cpp b/engines/gob/sound.cpp
index aa7724a294..500a2e5295 100644
--- a/engines/gob/sound.cpp
+++ b/engines/gob/sound.cpp
@@ -61,24 +61,21 @@ int Snd::SquareWaveStream::readBuffer(int16 *buffer, const int numSamples) {
}
Snd::Snd(GobEngine *vm) : _vm(vm) {
- //CleanupFuncPtr cleanupFunc;// = &snd_cleanupFuncCallback();
_cleanupFunc = 0;
- for (int i = 0; i < ARRAYSIZE(_loopingSounds); i++)
- _loopingSounds[i] = NULL;
_playingSound = 0;
-}
-void Snd::loopSounds(void) {
- for (int i = 0; i < ARRAYSIZE(_loopingSounds); i++) {
- SoundDesc *snd = _loopingSounds[i];
- if (snd && !_vm->_mixer->isSoundHandleActive(snd->handle)) {
- if (snd->repCount-- > 0) {
- _vm->_mixer->playRaw(&snd->handle, snd->data, snd->size, snd->frequency, 0);
- } else {
- _loopingSounds[i] = NULL;
- }
- }
- }
+ _rate = _vm->_mixer->getOutputRate();
+ _end = true;
+ _data = 0;
+ _length = 0;
+ _freq = 0;
+ _repCount = 0;
+ _offset = 0.0;
+
+ _compositionPos = -1;
+
+ _vm->_mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_handle,
+ this, -1, 255, 0, false, true);
}
void Snd::setBlasterPort(int16 port) {return;}
@@ -94,28 +91,54 @@ void Snd::speakerOff(void) {
_vm->_mixer->stopHandle(_speakerHandle);
}
-void Snd::playSample(Snd::SoundDesc *sndDesc, int16 repCount, int16 frequency) {
- if (frequency <= 0)
- frequency = sndDesc->frequency;
+int8 Snd::getCompositionSlot(void) {
+ if (_compositionPos == -1)
+ return -1;
- for (int i = 0; i < ARRAYSIZE(_loopingSounds); i++)
- _loopingSounds[i] = 0;
- _vm->_mixer->stopHandle(sndDesc->handle);
+ return _composition[_compositionPos];
+}
- _vm->_mixer->playRaw(&sndDesc->handle, sndDesc->data, sndDesc->size, frequency, 0);
+void Snd::stopSound(int16 arg)
+{
+ Common::StackLock slock(_mutex);
- sndDesc->repCount = repCount - 1;
- sndDesc->frequency = frequency;
+ _data = 0;
+ _end = true;
+}
+
+void Snd::waitEndPlay(void) {
+ while (!_end)
+ _vm->_util->longDelay(200);
+ stopSound(0);
+}
+
+void Snd::stopComposition(void) {
+ if (_compositionPos != -1) {
+ stopSound(0);
+ _compositionPos = -1;
+ }
+}
+
+void Snd::nextCompositionPos(void) {
+ int8 slot;
- if (repCount > 1) {
- for (int i = 0; i < ARRAYSIZE(_loopingSounds); i++) {
- if (!_loopingSounds[i]) {
- _loopingSounds[i] = sndDesc;
- return;
- }
+ while ((++_compositionPos < 50) && ((slot = _composition[_compositionPos]) != -1)) {
+ if ((slot >= 0) && (slot <= 60) && (_vm->_game->_soundSamples[slot] != 0)
+ && !(_vm->_game->_soundTypes[slot] & 8)) {
+ setSample(_vm->_game->_soundSamples[slot], 1, 0);
+ return;
}
- warning("Looping sounds list is full");
}
+ _compositionPos = -1;
+}
+
+void Snd::playComposition(int16 *composition, int16 freqVal) {
+ waitEndPlay();
+ stopComposition();
+
+ for (int i = 0; i < 50; i++)
+ _composition[i] = composition[i];
+ nextCompositionPos();
}
void Snd::writeAdlib(int16 port, int16 data) {
@@ -133,12 +156,8 @@ Snd::SoundDesc *Snd::loadSoundData(const char *path) {
}
void Snd::freeSoundDesc(Snd::SoundDesc *sndDesc, bool freedata) {
- _vm->_mixer->stopHandle(sndDesc->handle);
-
- for (int i = 0; i < ARRAYSIZE(_loopingSounds); i++) {
- if (_loopingSounds[i] == sndDesc)
- _loopingSounds[i] = NULL;
- }
+ if (sndDesc == _curSoundDesc)
+ stopSound(0);
if (freedata) {
delete[] sndDesc->data;
@@ -146,7 +165,75 @@ void Snd::freeSoundDesc(Snd::SoundDesc *sndDesc, bool freedata) {
delete sndDesc;
}
-} // End of namespace Gob
+void Snd::setSample(Snd::SoundDesc *sndDesc, int16 repCount, int16 frequency) {
+ if (frequency <= 0)
+ frequency = sndDesc->frequency;
+ _curSoundDesc = sndDesc;
+ sndDesc->repCount = repCount - 1;
+ sndDesc->frequency = frequency;
+
+ _data = (int8 *) sndDesc->data;
+ _length = sndDesc->size;
+ _freq = frequency;
+ _ratio = ((double) _freq) / _rate;
+ _offset = 0.0;
+ _frac = 0;
+ _cur = 0;
+ _last = 0;
+ _repCount = repCount;
+ _end = false;
+ _playingSound = 0;
+}
+
+void Snd::playSample(Snd::SoundDesc *sndDesc, int16 repCount, int16 frequency) {
+ Common::StackLock slock(_mutex);
+ if (!_end)
+ return;
+
+ setSample(sndDesc, repCount, frequency);
+ if (!_vm->_mixer->isSoundHandleActive(_handle))
+ _vm->_mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_handle,
+ this, -1, 255, 0, false, true);
+}
+
+void Snd::checkEndSample(void) {
+ if (_compositionPos != -1)
+ nextCompositionPos();
+ else if ((_repCount == -1) || (--_repCount > 0)) {
+ _offset = 0.0;
+ _end = false;
+ _playingSound = 0;
+ } else {
+ _end = true;
+ _playingSound = 0;
+ }
+}
+
+int Snd::readBuffer(int16 *buffer, const int numSamples) {
+ memset(buffer, 0, numSamples);
+
+ for (int i = 0; i < numSamples; i++) {
+ Common::StackLock slock(_mutex);
+
+ if (!_data)
+ return i;
+ if (_end || (_offset >= _length))
+ checkEndSample();
+ if (_end)
+ return i;
+
+ *buffer++ = (int) (_last + (_cur - _last) * _frac);
+ _frac += _ratio;
+ while (_frac > 1) {
+ _frac -= 1;
+ _last = _cur;
+ _cur = _data[(int) _offset] << 8;
+ }
+ _offset += _ratio;
+ }
+ return numSamples;
+}
+} // End of namespace Gob
diff --git a/engines/gob/sound.h b/engines/gob/sound.h
index 5b32569ac1..dd059b44ee 100644
--- a/engines/gob/sound.h
+++ b/engines/gob/sound.h
@@ -28,7 +28,7 @@
namespace Gob {
-class Snd {
+class Snd : public Audio::AudioStream {
public:
struct SoundDesc {
Audio::SoundHandle handle;
@@ -45,7 +45,6 @@ public:
typedef void (*CleanupFuncPtr) (int16);
- SoundDesc *_loopingSounds[10]; // Should be enough
char _playingSound;
CleanupFuncPtr _cleanupFunc;
@@ -53,16 +52,23 @@ public:
void speakerOn(int16 frequency, int32 length);
void speakerOff(void);
SoundDesc *loadSoundData(const char *path);
- void stopSound(int16 arg){return;}
- void loopSounds(void);
+ void stopSound(int16 arg);
void playSample(SoundDesc *sndDesc, int16 repCount, int16 frequency);
- void playComposition(Snd::SoundDesc ** samples, int16 *composit, int16 freqVal) {;}
- void waitEndPlay(void) {;}
+ void playComposition(int16 *composition, int16 freqVal);
+ void stopComposition(void);
+ int8 getCompositionSlot(void);
+ void waitEndPlay(void);
// This deletes sndDesc and stops playing the sample.
// If freedata is set, it also delete[]s the sample data.
void freeSoundDesc(SoundDesc *sndDesc, bool freedata=true);
+ int readBuffer(int16 *buffer, const int numSamples);
+ bool isStereo() const { return false; }
+ bool endOfData() const { return _end; }
+ bool endOfStream() const { return false; }
+ int getRate() const { return _rate; }
+
protected:
// TODO: This is a very primitive square wave generator. The only thing is
// has in common with the PC speaker is that it sounds terrible.
@@ -91,6 +97,26 @@ protected:
SquareWaveStream _speakerStream;
Audio::SoundHandle _speakerHandle;
+ Audio::SoundHandle *_activeHandle;
+ Audio::SoundHandle _compositionHandle;
+ int16 _composition[50];
+ int8 _compositionPos;
+
+ Audio::SoundHandle _handle;
+ Common::Mutex _mutex;
+ SoundDesc *_curSoundDesc;
+ bool _end;
+ int8 *_data;
+ uint32 _length;
+ uint32 _rate;
+ int32 _freq;
+ int32 _repCount;
+ double _offset;
+ double _ratio;
+ double _frac;
+ int16 _cur;
+ int16 _last;
+
GobEngine *_vm;
void cleanupFuncCallback() {;}
@@ -101,6 +127,9 @@ protected:
void writeAdlib(int16 port, int16 data);
void setBlasterPort(int16 port);
void setResetTimerFlag(char flag){return;}
+ void setSample(Snd::SoundDesc *sndDesc, int16 repCount, int16 frequency);
+ void checkEndSample(void);
+ void nextCompositionPos(void);
};
} // End of namespace Gob