added code for non-looping music and implemented fading

svn-id: r11845
This commit is contained in:
Robert Göffringmann 2003-12-22 02:47:43 +00:00
parent fd4417e6bb
commit 44f1ed75fd
2 changed files with 118 additions and 39 deletions

View File

@ -32,12 +32,14 @@ SwordMusic::SwordMusic(OSystem *system, SoundMixer *pMixer) {
_system = system;
_mixer = pMixer;
_mixer->setupPremix(passMixerFunc, this);
_fading = 0;
_fading = false;
_playing = false;
_loop = false;
_mutex = _system->create_mutex();
_waveSize = _wavePos = _bufPos = _smpInBuf = 0;
_fadeSmpInBuf = _fadeBufPos = _waveSize = _wavePos = _bufPos = _smpInBuf = 0;
assert(_mixer->getOutputRate() == 22050);
_fadeBuf = NULL;
_musicBuf = NULL;
}
SwordMusic::~SwordMusic() {
@ -48,51 +50,103 @@ void SwordMusic::passMixerFunc(void *param, int16 *buf, uint len) {
((SwordMusic*)param)->mixer(buf, len);
}
void SwordMusic::mixer(int16 *buf, uint len) {
void SwordMusic::mixTo(int16 *src, int16 *dst, uint32 len) {
if (!_playing)
memset(buf, 0, 2 * len * sizeof(int16));
else {
_system->lock_mutex(_mutex);
len >>= 1;
if (len <= _smpInBuf) {
uint32 maxLen = BUFSIZE - _bufPos;
if (len >= maxLen) {
for (uint32 cnt = 0; cnt < maxLen; cnt++)
buf[(cnt << 2) | 0] = buf[(cnt << 2) | 1] =
buf[(cnt << 2) | 2] = buf[(cnt << 2) | 3] = (int16)READ_LE_UINT16(_musicBuf + _bufPos + cnt);
_smpInBuf -= maxLen;
_bufPos = 0;
len -= maxLen;
buf += maxLen * 4;
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 (len) {
for (uint32 cnt = 0; cnt < len; cnt++)
buf[(cnt << 2) | 0] = buf[(cnt << 2) | 1] =
buf[(cnt << 2) | 2] = buf[(cnt << 2) | 3] = (int16)READ_LE_UINT16(_musicBuf + _bufPos + cnt);
_smpInBuf -= len;
_bufPos += len;
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) {
_fading = _playing = false;
free(_musicBuf);
_musicBuf = NULL;
}
}
_system->unlock_mutex(_mutex);
}
}
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) {
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 < SAMPLERATE) && _playing) {
if ((_smpInBuf < 4 * SAMPLERATE) && _playing) {
_system->lock_mutex(_mutex);
uint32 loadTotal = BUFSIZE - _smpInBuf;
while (uint32 doLoad = loadTotal) {
if (BUFSIZE - ((_bufPos + _smpInBuf) % BUFSIZE) < loadTotal)
doLoad = BUFSIZE - (_bufPos + _smpInBuf) % BUFSIZE;
if (_waveSize - _wavePos < doLoad)
doLoad = _waveSize - _wavePos;
doLoad = MIN(doLoad, _waveSize - _wavePos);
int16 *dest = _musicBuf + ((_bufPos + _smpInBuf) % BUFSIZE);
_musicFile.read(dest, doLoad * 2);
_wavePos += doLoad;
if (_wavePos == _waveSize) {
_wavePos = 0;
_musicFile.seek(WAVEHEADERSIZE);
if (_loop) {
_wavePos = 0;
_musicFile.seek(WAVEHEADERSIZE);
} else
loadTotal = doLoad;
}
loadTotal -= doLoad;
_smpInBuf += doLoad;
@ -104,28 +158,49 @@ void SwordMusic::stream(void) {
void SwordMusic::startMusic(int32 tuneId, int32 loopFlag) {
_system->lock_mutex(_mutex);
_loop = (loopFlag > 0);
if (tuneId) {
if (tuneId) {
if (_musicFile.isOpen())
_musicFile.close();
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
_playing = false;
} else
_playing = false;
} else {
_fading = true;
_fadeVal = 32768;
if (_fadeBuf) {
free(_fadeBuf);
_fadeBuf = NULL;
}
}
} else if (_playing)
fadeDown();
_system->unlock_mutex(_mutex);
stream();
}
void SwordMusic::fadeDown(void) {
warning("stub: SwordMusic::fadeDown");
_fadeVal = 32768;
_fading = true;
if (_fadeBuf) {
free(_fadeBuf);
_fadeBuf = NULL;
}
}

View File

@ -28,7 +28,7 @@
#define TOTAL_TUNES 270
#define SAMPLERATE 11025
#define BUFSIZE (4 * SAMPLERATE)
#define BUFSIZE (6 * SAMPLERATE)
#define WAVEHEADERSIZE 0x2C
class SoundMixer;
@ -44,16 +44,20 @@ private:
File _musicFile;
OSystem *_system;
SoundMixer *_mixer;
uint16 _fading;
bool _fading;
uint16 _fadeVal;
bool _playing;
bool _loop;
OSystem::MutexRef _mutex;
static void passMixerFunc(void *param, int16 *buf, uint len);
void mixer(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 _musicBuf[BUFSIZE]; // samples for 8 seconds
int16 *_fadeBuf;
uint32 _fadeBufPos, _fadeSmpInBuf;
};
#endif // BSMUSIC_H