aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/gob/sound/adlib.cpp65
-rw-r--r--engines/gob/sound/adlib.h16
-rw-r--r--engines/gob/sound/adlplayer.cpp11
-rw-r--r--engines/gob/sound/adlplayer.h2
-rw-r--r--engines/gob/sound/musplayer.cpp18
-rw-r--r--engines/gob/sound/musplayer.h1
6 files changed, 50 insertions, 63 deletions
diff --git a/engines/gob/sound/adlib.cpp b/engines/gob/sound/adlib.cpp
index b92e20b42c..20fbced63c 100644
--- a/engines/gob/sound/adlib.cpp
+++ b/engines/gob/sound/adlib.cpp
@@ -93,7 +93,7 @@ const uint16 AdLib::kHihatParams [kParamCount] = {
0, 1, 0, 15, 11, 0, 7, 5, 0, 0, 0, 0, 0, 0 };
-AdLib::AdLib(Audio::Mixer &mixer) : _mixer(&mixer), _opl(0),
+AdLib::AdLib(Audio::Mixer &mixer, int callbackFreq) : _mixer(&mixer), _opl(0),
_toPoll(0), _repCount(0), _first(true), _playing(false), _ended(true) {
_rate = _mixer->getOutputRate();
@@ -103,6 +103,7 @@ AdLib::AdLib(Audio::Mixer &mixer) : _mixer(&mixer), _opl(0),
createOPL();
initOPL();
+ _opl->start(new Common::Functor0Mem<void, AdLib>(this, &AdLib::onTimer), callbackFreq);
_mixer->playStream(Audio::Mixer::kMusicSoundType, &_handle,
this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
}
@@ -144,38 +145,34 @@ void AdLib::createOPL() {
}
int AdLib::readBuffer(int16 *buffer, const int numSamples) {
+ return _opl->readBuffer(buffer, numSamples);
+}
+
+void AdLib::onTimer() {
Common::StackLock slock(_mutex);
- // Nothing to do, fill with silence
- if (!_playing) {
- memset(buffer, 0, numSamples * sizeof(int16));
- return numSamples;
+ // Nothing to do
+ if (!_playing)
+ return;
+
+ // Check if there's anything to do on this step
+ // If not, decrease the poll number and move on
+ if (_toPoll > 0) {
+ _toPoll--;
+ return;
}
- // Read samples from the OPL, polling in more music when necessary
- uint32 samples = numSamples;
- while (samples && _playing) {
- if (_toPoll) {
- const uint32 render = MIN(samples, _toPoll);
-
- _opl->readBuffer(buffer, render);
-
- buffer += render;
- samples -= render;
- _toPoll -= render;
-
- } else {
- // Song ended, fill the rest with silence
- if (_ended) {
- memset(buffer, 0, samples * sizeof(int16));
- samples = 0;
- break;
- }
-
- // Poll more music
- _toPoll = pollMusic(_first);
- _first = false;
+ // Poll until we have to delay until the next poll
+ while (_toPoll == 0 && _playing) {
+ // Song ended, break out
+ if (_ended) {
+ _toPoll = 0;
+ break;
}
+
+ // Poll more music
+ _toPoll = pollMusic(_first);
+ _first = false;
}
// Song ended, loop if requested
@@ -195,8 +192,6 @@ int AdLib::readBuffer(int16 *buffer, const int numSamples) {
} else
_playing = false;
}
-
- return numSamples;
}
bool AdLib::isStereo() const {
@@ -204,7 +199,7 @@ bool AdLib::isStereo() const {
}
bool AdLib::endOfData() const {
- return !_playing;
+ return false;
}
bool AdLib::endOfStream() const {
@@ -231,10 +226,6 @@ void AdLib::setRepeating(int32 repCount) {
_repCount = repCount;
}
-uint32 AdLib::getSamplesPerSecond() const {
- return _rate * (isStereo() ? 2 : 1);
-}
-
void AdLib::startPlay() {
Common::StackLock slock(_mutex);
@@ -639,4 +630,8 @@ void AdLib::setFreq(uint8 voice, uint16 note, bool on) {
writeOPL(0xB0 + voice, value);
}
+void AdLib::setTimerFrequency(int timerFrequency) {
+ _opl->setCallbackFrequency(timerFrequency);
+}
+
} // End of namespace Gob
diff --git a/engines/gob/sound/adlib.h b/engines/gob/sound/adlib.h
index 8071249374..6a6215298a 100644
--- a/engines/gob/sound/adlib.h
+++ b/engines/gob/sound/adlib.h
@@ -37,7 +37,7 @@ namespace Gob {
/** Base class for a player of an AdLib music format. */
class AdLib : public Audio::AudioStream {
public:
- AdLib(Audio::Mixer &mixer);
+ AdLib(Audio::Mixer &mixer, int callbackFrequency);
virtual ~AdLib();
bool isPlaying() const; ///< Are we currently playing?
@@ -120,8 +120,6 @@ protected:
static const int kOPLMidC = 48; ///< A mid C for the OPL.
- /** Return the number of samples per second. */
- uint32 getSamplesPerSecond() const;
/** Write a value into an OPL register. */
void writeOPL(byte reg, byte val);
@@ -135,7 +133,7 @@ protected:
/** The callback function that's called for polling more AdLib commands.
*
* @param first Is this the first poll since the start of the song?
- * @return The number of samples until the next poll.
+ * @return The number of ticks until the next poll.
*/
virtual uint32 pollMusic(bool first) = 0;
@@ -207,6 +205,11 @@ protected:
/** Switch a voice off. */
void noteOff(uint8 voice);
+ /**
+ * Set the OPL timer frequency
+ */
+ void setTimerFrequency(int timerFrequency);
+
private:
static const uint8 kOperatorType [kOperatorCount];
static const uint8 kOperatorOffset[kOperatorCount];
@@ -300,6 +303,11 @@ private:
void changePitch(uint8 voice, uint16 pitchBend);
void setFreq(uint8 voice, uint16 note, bool on);
+
+ /**
+ * Callback function for OPL
+ */
+ void onTimer();
};
} // End of namespace Gob
diff --git a/engines/gob/sound/adlplayer.cpp b/engines/gob/sound/adlplayer.cpp
index 384a928360..e5a276032b 100644
--- a/engines/gob/sound/adlplayer.cpp
+++ b/engines/gob/sound/adlplayer.cpp
@@ -28,7 +28,7 @@
namespace Gob {
-ADLPlayer::ADLPlayer(Audio::Mixer &mixer) : AdLib(mixer),
+ADLPlayer::ADLPlayer(Audio::Mixer &mixer) : AdLib(mixer, 1000),
_songData(0), _songDataSize(0), _playPos(0) {
}
@@ -135,14 +135,7 @@ uint32 ADLPlayer::pollMusic(bool first) {
if (delay & 0x80)
delay = ((delay & 3) << 8) | *_playPos++;
- return getSampleDelay(delay);
-}
-
-uint32 ADLPlayer::getSampleDelay(uint16 delay) const {
- if (delay == 0)
- return 0;
-
- return ((uint32)delay * getSamplesPerSecond()) / 1000;
+ return delay;
}
void ADLPlayer::rewind() {
diff --git a/engines/gob/sound/adlplayer.h b/engines/gob/sound/adlplayer.h
index 3edd238343..bd43cc091c 100644
--- a/engines/gob/sound/adlplayer.h
+++ b/engines/gob/sound/adlplayer.h
@@ -76,8 +76,6 @@ private:
bool readHeader (Common::SeekableReadStream &adl, int &timbreCount);
bool readTimbres (Common::SeekableReadStream &adl, int timbreCount);
bool readSongData(Common::SeekableReadStream &adl);
-
- uint32 getSampleDelay(uint16 delay) const;
};
} // End of namespace Gob
diff --git a/engines/gob/sound/musplayer.cpp b/engines/gob/sound/musplayer.cpp
index 7001a5724b..bf90d44735 100644
--- a/engines/gob/sound/musplayer.cpp
+++ b/engines/gob/sound/musplayer.cpp
@@ -27,7 +27,7 @@
namespace Gob {
-MUSPlayer::MUSPlayer(Audio::Mixer &mixer) : AdLib(mixer),
+MUSPlayer::MUSPlayer(Audio::Mixer &mixer) : AdLib(mixer, 60),
_songData(0), _songDataSize(0), _playPos(0), _songID(0) {
}
@@ -43,15 +43,6 @@ void MUSPlayer::unload() {
unloadMUS();
}
-uint32 MUSPlayer::getSampleDelay(uint16 delay) const {
- if (delay == 0)
- return 0;
-
- uint32 freq = (_ticksPerBeat * _tempo) / 60;
-
- return ((uint32)delay * getSamplesPerSecond()) / freq;
-}
-
void MUSPlayer::skipToTiming() {
while (*_playPos < 0x80)
_playPos++;
@@ -67,7 +58,7 @@ uint32 MUSPlayer::pollMusic(bool first) {
}
if (first)
- return getSampleDelay(*_playPos++);
+ return *_playPos++;
uint16 delay = 0;
while (delay == 0) {
@@ -100,6 +91,7 @@ uint32 MUSPlayer::pollMusic(bool first) {
uint32 denom = *_playPos++;
_tempo = _baseTempo * num + ((_baseTempo * denom) >> 7);
+ setTimerFrequency((_ticksPerBeat * _tempo) / 60);
_playPos++;
} else {
@@ -182,7 +174,7 @@ uint32 MUSPlayer::pollMusic(bool first) {
delay += *_playPos++;
}
- return getSampleDelay(delay);
+ return delay;
}
void MUSPlayer::rewind() {
@@ -193,6 +185,8 @@ void MUSPlayer::rewind() {
setPercussionMode(_soundMode != 0);
setPitchRange(_pitchBendRange);
+
+ setTimerFrequency((_ticksPerBeat * _tempo) / 60);
}
bool MUSPlayer::loadSND(Common::SeekableReadStream &snd) {
diff --git a/engines/gob/sound/musplayer.h b/engines/gob/sound/musplayer.h
index c76c5aab38..7c1189b84b 100644
--- a/engines/gob/sound/musplayer.h
+++ b/engines/gob/sound/musplayer.h
@@ -97,7 +97,6 @@ private:
bool readMUSHeader(Common::SeekableReadStream &mus);
bool readMUSSong (Common::SeekableReadStream &mus);
- uint32 getSampleDelay(uint16 delay) const;
void setInstrument(uint8 voice, uint8 instrument);
void skipToTiming();