aboutsummaryrefslogtreecommitdiff
path: root/sword1
diff options
context:
space:
mode:
authorTorbjörn Andersson2004-01-01 15:22:15 +0000
committerTorbjörn Andersson2004-01-01 15:22:15 +0000
commit18f8916c3aef4b0dec659a0c053517bb9c7aa880 (patch)
tree16240c407a58b01362e039b4141006dc1d49d369 /sword1
parent033a847e7769ce46a13fbcdd58230d22623600f7 (diff)
downloadscummvm-rg350-18f8916c3aef4b0dec659a0c053517bb9c7aa880.tar.gz
scummvm-rg350-18f8916c3aef4b0dec659a0c053517bb9c7aa880.tar.bz2
scummvm-rg350-18f8916c3aef4b0dec659a0c053517bb9c7aa880.zip
Rewrote the music code. It now follows the same basic idea as the one in
BS2, which has worked pretty well so far. I haven't implemented pausing and volume since the code I replaced didn't have it either, as far as I could tell. svn-id: r12070
Diffstat (limited to 'sword1')
-rw-r--r--sword1/control.cpp1
-rw-r--r--sword1/music.cpp269
-rw-r--r--sword1/music.h44
-rw-r--r--sword1/sword1.cpp2
4 files changed, 142 insertions, 174 deletions
diff --git a/sword1/control.cpp b/sword1/control.cpp
index e4f7a28797..1216220aea 100644
--- a/sword1/control.cpp
+++ b/sword1/control.cpp
@@ -231,7 +231,6 @@ uint8 SwordControl::runPanel(void) {
_music->startMusic(61, 1);
do {
- _music->stream();
if (newMode) {
mode = newMode;
fullRefresh = true;
diff --git a/sword1/music.cpp b/sword1/music.cpp
index 4f76dc21db..e4dfa33d84 100644
--- a/sword1/music.cpp
+++ b/sword1/music.cpp
@@ -19,192 +19,149 @@
*
*/
-// todo: add fadeout, crossfading.
-// this code always loops. make it depend on _loopFlag
-
#include "stdafx.h"
#include "music.h"
#include "sound/mixer.h"
#include "common/util.h"
#include "common/file.h"
+// This means fading takes about half a second. This may need some tuning...
+#define FADE_SAMPLES 5512
+
+// These functions are only called from SwordMusic, so I'm just going to
+// assume that if locking is needed it has already been taken care of.
+
+void SwordMusicHandle::fadeDown() {
+ if (_fading < 0)
+ _fading = -_fading;
+ else if (_fading == 0)
+ _fading = FADE_SAMPLES;
+}
+
+void SwordMusicHandle::fadeUp() {
+ if (_fading > 0)
+ _fading = -_fading;
+ else if (_fading == 0)
+ _fading = -FADE_SAMPLES;
+}
+
+bool SwordMusicHandle::endOfData() const {
+ return !streaming();
+}
+
+int SwordMusicHandle::readBuffer(int16 *buffer, const int numSamples) {
+ int samples;
+ for (samples = 0; samples < numSamples && !endOfData(); samples++)
+ *buffer++ = read();
+ return samples;
+}
+
+int16 SwordMusicHandle::read() {
+ if (!streaming())
+ return 0;
+ int16 sample = _file.readUint16LE();
+ if (_file.ioFailed()) {
+ if (!_looping) {
+ stop();
+ return 0;
+ }
+ _file.clearIOFailed();
+ _file.seek(WAVEHEADERSIZE);
+ sample = _file.readUint16LE();
+ }
+ if (_fading > 0) {
+ if (--_fading == 0) {
+ _looping = false;
+ _file.close();
+ }
+ sample = (sample * _fading) / FADE_SAMPLES;
+ } else if (_fading < 0) {
+ _fading++;
+ sample = (sample * (FADE_SAMPLES + _fading)) / FADE_SAMPLES;
+ }
+ return sample;
+}
+
+bool SwordMusicHandle::play(const char *filename, bool loop) {
+ uint8 wavHeader[WAVEHEADERSIZE];
+ stop();
+ _file.open(filename);
+ if (!_file.isOpen())
+ return false;
+ _file.read(wavHeader, WAVEHEADERSIZE);
+ _stereo = (READ_LE_UINT16(wavHeader + 0x16) == 2);
+ _rate = READ_LE_UINT16(wavHeader + 0x18);
+ _looping = loop;
+ fadeUp();
+ return true;
+}
+
+void SwordMusicHandle::stop() {
+ if (_file.isOpen())
+ _file.close();
+ _fading = 0;
+ _looping = false;
+}
+
SwordMusic::SwordMusic(OSystem *system, SoundMixer *pMixer) {
_system = system;
_mixer = pMixer;
_mixer->setupPremix(passMixerFunc, this);
- _fading = false;
- _playing = false;
- _loop = false;
_mutex = _system->create_mutex();
- _fadeSmpInBuf = _fadeBufPos = _waveSize = _wavePos = _bufPos = _smpInBuf = 0;
- assert(_mixer->getOutputRate() == 22050);
- _fadeBuf = NULL;
- _musicBuf = NULL;
+ _converter[0] = NULL;
+ _converter[1] = NULL;
}
SwordMusic::~SwordMusic() {
_mixer->setupPremix(0, 0);
+ delete _converter[0];
+ delete _converter[1];
}
void SwordMusic::passMixerFunc(void *param, int16 *buf, uint len) {
((SwordMusic*)param)->mixer(buf, len);
}
-void SwordMusic::mixTo(int16 *src, int16 *dst, uint32 len) {
- if (!_playing)
- memset(dst, 0, len * 8);
- if (!_fading) { // no fading, simply copy it over
- for (uint32 cnt = 0; cnt < len; cnt++)
- dst[(cnt << 2) | 0] = dst[(cnt << 2) | 1] =
- dst[(cnt << 2) | 2] = dst[(cnt << 2) | 3] = (int16)READ_LE_UINT16(src + cnt);
- } else {
- if (_fadeBuf) { // do a cross fade
- for (uint32 cnt = 0; cnt < len; cnt++) {
- int16 resVal = ((int16)READ_LE_UINT16(_fadeBuf + _fadeBufPos) * _fadeVal) >> 15;
- resVal += ((int16)READ_LE_UINT16(src + cnt) * (32768 - _fadeVal)) >> 15;
- dst[(cnt << 2) | 0] = dst[(cnt << 2) | 1] =
- dst[(cnt << 2) | 2] = dst[(cnt << 2) | 3] = resVal;
- _fadeVal--;
- _fadeBufPos++;
- _fadeSmpInBuf--;
- }
- if ((!_fadeVal) || (!_fadeSmpInBuf)) {
- free(_fadeBuf);
- _fadeBuf = NULL;
- _fading = false;
- }
- if (_fadeBufPos == BUFSIZE)
- _fadeBufPos = 0;
- } else { // simple fadeout
- for (uint32 cnt = 0; cnt < len; cnt++) {
- dst[(cnt << 2) | 0] = dst[(cnt << 2) | 1] =
- dst[(cnt << 2) | 2] = dst[(cnt << 2) | 3] =
- ((int16)READ_LE_UINT16(src + cnt) * _fadeVal) >> 15;
- _fadeVal--;
- }
- if ((!_fadeVal) || (!_smpInBuf)) {
- _fading = _playing = false;
- free(_musicBuf);
- _musicBuf = NULL;
- }
- }
- }
-}
-
void SwordMusic::mixer(int16 *buf, uint32 len) {
- if (!_playing) {
- memset(buf, 0, 2 * len * sizeof(int16));
- return;
- }
- uint32 remain = 0;
- if (_smpInBuf < (len >> 1)) {
- if (_loop)
- return;
- remain = (len >> 1) - _smpInBuf;
- len = _smpInBuf << 1;
- }
- _system->lock_mutex(_mutex);
- len >>= 1;
- while (len) {
- uint32 length = len;
- length = MIN(length, BUFSIZE - _bufPos);
- if (_fading && _fadeBuf) {
- length = MIN(length, (uint32)_fadeVal);
- length = MIN(length, _fadeSmpInBuf);
- length = MIN(length, BUFSIZE - _fadeBufPos);
- }
- mixTo(_musicBuf + _bufPos, buf, length);
- len -= length;
- buf += 4 * length;
- _bufPos += length;
- _smpInBuf -= length;
- if (_bufPos == BUFSIZE)
- _bufPos = 0;
- }
- if (remain) {
- memset(buf, 0, remain * 8);
- _playing = false;
- }
- _system->unlock_mutex(_mutex);
-}
-
-void SwordMusic::stream(void) {
- // make sure we've got enough samples in buffer.
- if ((_smpInBuf < 4 * SAMPLERATE) && _playing && _musicFile.isOpen()) {
- _system->lock_mutex(_mutex);
- uint32 loadTotal = BUFSIZE - _smpInBuf;
- while (uint32 doLoad = loadTotal) {
- if (BUFSIZE - ((_bufPos + _smpInBuf) % BUFSIZE) < loadTotal)
- doLoad = BUFSIZE - (_bufPos + _smpInBuf) % BUFSIZE;
- doLoad = MIN(doLoad, _waveSize - _wavePos);
-
- int16 *dest = _musicBuf + ((_bufPos + _smpInBuf) % BUFSIZE);
- _musicFile.read(dest, doLoad * 2);
- _wavePos += doLoad;
- if (_wavePos == _waveSize) {
- if (_loop) {
- _wavePos = 0;
- _musicFile.seek(WAVEHEADERSIZE);
- } else
- loadTotal = doLoad;
- }
- loadTotal -= doLoad;
- _smpInBuf += doLoad;
+ Common::StackLock lock(_mutex);
+ for (int i = 0; i < ARRAYSIZE(_handles); i++) {
+ if (_handles[i].streaming() && _converter[i]) {
+ st_volume_t vol = 255;
+ _converter[i]->flow(_handles[i], buf, len, vol, vol);
}
- _system->unlock_mutex(_mutex);
}
}
void SwordMusic::startMusic(int32 tuneId, int32 loopFlag) {
- _system->lock_mutex(_mutex);
- _loop = (loopFlag > 0);
- if (tuneId) {
- if (_musicFile.isOpen())
- _musicFile.close();
+ Common::StackLock lock(_mutex);
+ if (strlen(_tuneList[tuneId]) > 0) {
+ int newStream = 0;
+ if (_handles[0].streaming() && _handles[1].streaming()) {
+ // If both handles are playing, stop the one that's
+ // fading down.
+ if (_handles[0].fading() > 0)
+ _handles[0].stop();
+ else
+ _handles[1].stop();
+ }
+ if (_handles[0].streaming()) {
+ _handles[0].fadeDown();
+ newStream = 1;
+ } else if (_handles[1].streaming()) {
+ _handles[1].fadeDown();
+ newStream = 0;
+ }
char fName[20];
sprintf(fName, "music/%s.wav", _tuneList[tuneId]);
- _musicFile.open(fName);
- if (_musicFile.isOpen()) {
- if (_playing) { // do a cross fade
- _fadeBuf = _musicBuf;
- _fadeBufPos = _bufPos;
- _fadeSmpInBuf = _smpInBuf;
- _fading = true;
- _fadeVal = 32768;
- } else
- _fading = false;
- _musicBuf = (int16*)malloc(BUFSIZE * 2);
-
- _musicFile.seek(0x28);
- _waveSize = _musicFile.readUint32LE() / 2;
- _wavePos = 0;
- _smpInBuf = 0;
- _bufPos = 0;
- _playing = true;
- } else {
- _fading = true;
- _fadeVal = 32768;
- if (_fadeBuf) {
- free(_fadeBuf);
- _fadeBuf = NULL;
- }
- }
- } else {
- if (_playing)
- fadeDown();
- if (_musicFile.isOpen())
- _musicFile.close();
+ _handles[newStream].play(fName, loopFlag);
+ delete _converter[newStream];
+ _converter[newStream] = makeRateConverter(_handles[newStream].getRate(), _mixer->getOutputRate(), _handles[newStream].isStereo(), false);
}
- _system->unlock_mutex(_mutex);
- stream();
}
-void SwordMusic::fadeDown(void) {
- _fadeVal = 32768;
- _fading = true;
- if (_fadeBuf) {
- free(_fadeBuf);
- _fadeBuf = NULL;
- }
+void SwordMusic::fadeDown() {
+ Common::StackLock lock(_mutex);
+ for (int i = 0; i < ARRAYSIZE(_handles); i++)
+ if (_handles[i].streaming())
+ _handles[i].fadeDown();
}
-
diff --git a/sword1/music.h b/sword1/music.h
index 1b98239e76..7820efec3e 100644
--- a/sword1/music.h
+++ b/sword1/music.h
@@ -25,39 +25,53 @@
#include "scummsys.h"
#include "common/system.h"
#include "common/file.h"
+#include "sound/audiostream.h"
+#include "sound/rate.h"
+
#define TOTAL_TUNES 270
-#define SAMPLERATE 11025
-#define BUFSIZE (6 * SAMPLERATE)
#define WAVEHEADERSIZE 0x2C
class SoundMixer;
+class SwordMusicHandle : public AudioInputStream {
+private:
+ File _file;
+ bool _looping;
+ int32 _fading;
+ int _rate;
+ bool _stereo;
+public:
+ SwordMusicHandle() : _looping(false), _fading(0) {}
+ virtual int readBuffer(int16 *buffer, const int numSamples);
+ int16 read();
+ bool play(const char *filename, bool loop);
+ void stop();
+ void fadeUp();
+ void fadeDown();
+ bool streaming() const { return _file.isOpen(); }
+ int32 fading() { return _fading; }
+ bool endOfData() const;
+ bool endOfStream() const { return false; }
+ bool isStereo() const { return _stereo; }
+ int getRate() const { return _rate; }
+};
+
class SwordMusic {
public:
SwordMusic(OSystem *system, SoundMixer *pMixer);
~SwordMusic();
- void stream(void);
void startMusic(int32 tuneId, int32 loopFlag);
- void fadeDown(void);
+ void fadeDown();
private:
- File _musicFile;
+ SwordMusicHandle _handles[2];
+ RateConverter *_converter[2];
OSystem *_system;
SoundMixer *_mixer;
- bool _fading;
- uint16 _fadeVal;
- bool _playing;
- bool _loop;
OSystem::MutexRef _mutex;
static void passMixerFunc(void *param, int16 *buf, uint len);
- void mixTo(int16 *src, int16 *dst, uint32 len);
void mixer(int16 *buf, uint32 len);
static const char _tuneList[TOTAL_TUNES][8]; // in staticres.cpp
- uint32 _waveSize, _wavePos;
- int16 *_musicBuf; // samples for 6 seconds
- uint32 _bufPos, _smpInBuf;
- int16 *_fadeBuf;
- uint32 _fadeBufPos, _fadeSmpInBuf;
};
#endif // BSMUSIC_H
diff --git a/sword1/sword1.cpp b/sword1/sword1.cpp
index 19bbe51a03..5360910410 100644
--- a/sword1/sword1.cpp
+++ b/sword1/sword1.cpp
@@ -1116,7 +1116,6 @@ uint8 SwordEngine::mainLoop(void) {
SwordLogic::_scriptVars[SCREEN] = SwordLogic::_scriptVars[NEW_SCREEN];
do {
- _music->stream();
uint32 frameTime = _system->get_msecs();
_logic->engine();
_logic->updateScreenParams(); // sets scrolling
@@ -1154,7 +1153,6 @@ uint8 SwordEngine::mainLoop(void) {
if ((retCode == 0) && (SwordLogic::_scriptVars[SCREEN] != 53) && _systemVars.wantFade) {
_screen->fadeDownPalette();
while (_screen->stillFading()) {
- _music->stream();
_screen->updateScreen();
delay(1000/12);
}