mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-13 21:31:53 +00:00
added code for non-looping music and implemented fading
svn-id: r11845
This commit is contained in:
parent
fd4417e6bb
commit
44f1ed75fd
145
sword1/music.cpp
145
sword1/music.cpp
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user