diff options
author | Max Horn | 2003-12-22 08:22:04 +0000 |
---|---|---|
committer | Max Horn | 2003-12-22 08:22:04 +0000 |
commit | 1e5496b2c8fc998e9210d90e05ff006e0409918a (patch) | |
tree | 30bc67d198403af556e378733d95d38d9261d802 | |
parent | 44f1ed75fd76fd9842acd5784a31672a37536996 (diff) | |
download | scummvm-rg350-1e5496b2c8fc998e9210d90e05ff006e0409918a.tar.gz scummvm-rg350-1e5496b2c8fc998e9210d90e05ff006e0409918a.tar.bz2 scummvm-rg350-1e5496b2c8fc998e9210d90e05ff006e0409918a.zip |
Moved bundle music code from class Sound to IMuseDigital (seems more natural; and allows for various cleanup)
svn-id: r11846
-rw-r--r-- | scumm/bundle.cpp | 30 | ||||
-rw-r--r-- | scumm/imuse_digi.cpp | 381 | ||||
-rw-r--r-- | scumm/imuse_digi.h | 37 | ||||
-rw-r--r-- | scumm/resource.cpp | 5 | ||||
-rw-r--r-- | scumm/saveload.cpp | 3 | ||||
-rw-r--r-- | scumm/script_v8.cpp | 3 | ||||
-rw-r--r-- | scumm/smush/insane.cpp | 1 | ||||
-rw-r--r-- | scumm/smush/smush_player.cpp | 4 | ||||
-rw-r--r-- | scumm/sound.cpp | 350 | ||||
-rw-r--r-- | scumm/sound.h | 33 | ||||
-rw-r--r-- | scumm/string.cpp | 3 |
11 files changed, 433 insertions, 417 deletions
diff --git a/scumm/bundle.cpp b/scumm/bundle.cpp index cf0deae08a..6c78199f46 100644 --- a/scumm/bundle.cpp +++ b/scumm/bundle.cpp @@ -93,7 +93,7 @@ static const byte imxOtherTable[6][128] = { } }; -const byte imxShortTable[] = { +static const byte imxShortTable[] = { 0, 0, 1, 3, 7, 15, 31, 63 }; @@ -436,12 +436,16 @@ int32 Bundle::getNumberOfMusicSamplesByName(const char *name) { return number; } -#define NextBit bit = mask & 1; mask >>= 1; \ - if (!--bitsleft) { \ - mask = READ_LE_UINT16(srcptr); \ - srcptr += 2; \ - bitsleft = 16; \ - } +#define NextBit \ + do { \ + bit = mask & 1; \ + mask >>= 1; \ + if (!--bitsleft) { \ + mask = READ_LE_UINT16(srcptr); \ + srcptr += 2; \ + bitsleft = 16; \ + } \ + } while (0) static int32 compDecode(byte *src, byte *dst) { byte *result, *srcptr = src, *dstptr = dst; @@ -449,12 +453,16 @@ static int32 compDecode(byte *src, byte *dst) { srcptr += 2; while (1) { - NextBit if (bit) { + NextBit; + if (bit) { *dstptr++ = *srcptr++; } else { - NextBit if (!bit) { - NextBit size = bit << 1; - NextBit size = (size | bit) + 3; + NextBit; + if (!bit) { + NextBit; + size = bit << 1; + NextBit; + size = (size | bit) + 3; data = *srcptr++ | 0xffffff00; } else { data = *srcptr++; diff --git a/scumm/imuse_digi.cpp b/scumm/imuse_digi.cpp index b4ee1386d5..980f2a2254 100644 --- a/scumm/imuse_digi.cpp +++ b/scumm/imuse_digi.cpp @@ -20,6 +20,8 @@ #include "stdafx.h" #include "common/timer.h" +#include "scumm/actor.h" +#include "scumm/bundle.h" #include "scumm/imuse_digi.h" #include "scumm/scumm.h" #include "scumm/sound.h" @@ -684,6 +686,37 @@ static byte *readCreativeVocFile(byte *ptr, int32 &size, int &rate) { return ret_sound; } +static uint32 decode12BitsSample(byte *src, byte **dst, uint32 size, bool stereo) { + uint32 s_size = (size / 3) * 4; + uint32 loop_size = s_size / 4; + if (stereo) { + s_size *= 2; + } + byte *ptr = *dst = (byte *)malloc(s_size); + + uint32 tmp; + while (loop_size--) { + byte v1 = *src++; + byte v2 = *src++; + byte v3 = *src++; + tmp = ((((v2 & 0x0f) << 8) | v1) << 4) - 0x8000; + *ptr++ = (byte)((tmp >> 8) & 0xff); + *ptr++ = (byte)(tmp & 0xff); + if (stereo) { + *ptr++ = (byte)((tmp >> 8) & 0xff); + *ptr++ = (byte)(tmp & 0xff); + } + tmp = ((((v2 & 0xf0) << 4) | v3) << 4) - 0x8000; + *ptr++ = (byte)((tmp >> 8) & 0xff); + *ptr++ = (byte)(tmp & 0xff); + if (stereo) { + *ptr++ = (byte)((tmp >> 8) & 0xff); + *ptr++ = (byte)(tmp & 0xff); + } + } + return s_size; +} + void IMuseDigital::timer_handler(void *refCon) { IMuseDigital *imuseDigital = (IMuseDigital *)refCon; imuseDigital->musicTimer(); @@ -697,6 +730,13 @@ IMuseDigital::IMuseDigital(ScummEngine *scumm) } _scumm->_timer->installTimerProc(timer_handler, 200000, this); _pause = false; + + _nameBundleMusic = ""; + _musicBundleBufFinal = NULL; + _musicBundleBufOutput = NULL; + _musicDisk = 0; + + _bundle = new Bundle(); } IMuseDigital::~IMuseDigital() { @@ -705,6 +745,8 @@ IMuseDigital::~IMuseDigital() { for (int l = 0; l < MAX_DIGITAL_CHANNELS; l++) { _scumm->_mixer->stopHandle(_channel[l]._handle); } + + delete _bundle; } void IMuseDigital::musicTimer() { @@ -883,7 +925,7 @@ void IMuseDigital::startSound(int sound) { if (_channel[l]._bits == 12) { _channel[l]._mixerSize *= 2; _channel[l]._mixerFlags |= SoundMixer::FLAG_16BITS; - _channel[l]._size = _scumm->_sound->decode12BitsSample(ptr, &_channel[l]._data, size, (_channel[l]._channels == 2) ? false : true); + _channel[l]._size = decode12BitsSample(ptr, &_channel[l]._data, size, (_channel[l]._channels == 2) ? false : true); } else if (_channel[l]._bits == 8) { _channel[l]._mixerFlags |= SoundMixer::FLAG_UNSIGNED; if (_channel[l]._channels == 1) { @@ -928,6 +970,7 @@ void IMuseDigital::stopAllSounds() { void IMuseDigital::pause(bool p) { _pause = p; + pauseBundleMusic(p); } int32 IMuseDigital::doCommand(int a, int b, int c, int d, int e, int f, int g, int h) { @@ -1041,7 +1084,7 @@ int32 IMuseDigital::doCommand(int a, int b, int c, int d, int e, int f, int g, i } if (_scumm->_gameId == GID_DIG) { if (b == 1000) { // STATE_NULL - _scumm->_sound->stopBundleMusic(); + stopBundleMusic(); return 0; } for (l = 0;; l++) { @@ -1052,30 +1095,30 @@ int32 IMuseDigital::doCommand(int a, int b, int c, int d, int e, int f, int g, i int music = _digStateMusicMap[l].table_index; debug(5, "Play imuse music: %s, %s, %s", _digStateMusicTable[music].name, _digStateMusicTable[music].title, _digStateMusicTable[music].filename); if ((_digStateMusicTable[music].filename[0] != 0) && - (strcmp(_digStateMusicTable[_digStateMusicTable[music].unk3].filename, _scumm->_sound->_nameBundleMusic) != 0) ) { - _scumm->_sound->playBundleMusic(_digStateMusicTable[music].filename); + (strcmp(_digStateMusicTable[_digStateMusicTable[music].unk3].filename, _nameBundleMusic) != 0) ) { + playBundleMusic(_digStateMusicTable[music].filename); } return 0; } } } else if ((_scumm->_gameId == GID_CMI) && (_scumm->_features & GF_DEMO)) { if (b == 2) { - _scumm->_sound->playBundleMusic("in1.imx"); + playBundleMusic("in1.imx"); } else if (b == 4) { - _scumm->_sound->playBundleMusic("in2.imx"); + playBundleMusic("in2.imx"); } else if (b == 8) { - _scumm->_sound->playBundleMusic("out1.imx"); + playBundleMusic("out1.imx"); } else if (b == 9) { - _scumm->_sound->playBundleMusic("out2.imx"); + playBundleMusic("out2.imx"); } else if (b == 16) { - _scumm->_sound->playBundleMusic("gun.imx"); + playBundleMusic("gun.imx"); } else { warning("imuse digital: set state unknown for cmi demo: %d, room: %d", b, this->_scumm->_currentRoom); return 1; } } else if (_scumm->_gameId == GID_CMI) { if (b == 1000) { // STATE_NULL - _scumm->_sound->stopBundleMusic(); + stopBundleMusic(); return 0; } for (l = 0;; l++) { @@ -1085,7 +1128,7 @@ int32 IMuseDigital::doCommand(int a, int b, int c, int d, int e, int f, int g, i if ((_comiStateMusicTable[l].id == b)) { debug(5, "Play imuse music: %s, %s, %s", _comiStateMusicTable[l].name, _comiStateMusicTable[l].title, _comiStateMusicTable[l].filename); if (_comiStateMusicTable[l].filename[0] != 0) { - _scumm->_sound->playBundleMusic(_comiStateMusicTable[l].filename); + playBundleMusic(_comiStateMusicTable[l].filename); } return 0; } @@ -1119,7 +1162,7 @@ int32 IMuseDigital::doCommand(int a, int b, int c, int d, int e, int f, int g, i if ((_digSeqMusicTable[l].room == b)) { debug(5, "Play imuse music: %s, %s, %s", _digSeqMusicTable[l].name, _digSeqMusicTable[l].title, _digSeqMusicTable[l].filename); if (_digSeqMusicTable[l].filename[0] != 0) { - _scumm->_sound->playBundleMusic(_digSeqMusicTable[l].filename); + playBundleMusic(_digSeqMusicTable[l].filename); } return 0; } @@ -1132,7 +1175,7 @@ int32 IMuseDigital::doCommand(int a, int b, int c, int d, int e, int f, int g, i if ((_comiSeqMusicTable[l].id == b)) { debug(5, "Play imuse music: %s, %s, %s", _comiSeqMusicTable[l].name, _comiSeqMusicTable[l].title, _comiSeqMusicTable[l].filename); if (_comiSeqMusicTable[l].filename[0] != 0) { - _scumm->_sound->playBundleMusic(_comiSeqMusicTable[l].filename); + playBundleMusic(_comiSeqMusicTable[l].filename); } return 0; } @@ -1188,6 +1231,318 @@ int IMuseDigital::getSoundStatus(int sound) const { return 0; } +#pragma mark - + +void IMuseDigital::music_handler(void *refCon) { + ((IMuseDigital *)refCon)->bundleMusicHandler(); +} + +void IMuseDigital::playBundleMusic(const char *song) { + if (_scumm->_silentDigitalImuse) { + return; + } + + if (_nameBundleMusic[0] == 0) { + if (_scumm->_gameId == GID_CMI) { + _outputMixerSize = (22050 * 2 * 2); + + char bunfile[20]; + if (_scumm->_features & GF_DEMO) { + if (_bundle->openMusicFile("music.bun", _scumm->getGameDataPath()) == false) { + _outputMixerSize = 0; + return; + } + } else { + + sprintf(bunfile, "musdisk%d.bun", _scumm->VAR(_scumm->VAR_CURRENTDISK)); + if (_musicDisk != _scumm->VAR(_scumm->VAR_CURRENTDISK)) + _bundle->closeMusicFile(); + + if (_bundle->openMusicFile(bunfile, _scumm->getGameDataPath()) == false) { + if (_bundle->openMusicFile("music.bun", _scumm->getGameDataPath()) == false) { + _outputMixerSize = 0; + return; + } + } + + _musicDisk = (byte)_scumm->VAR(_scumm->VAR_CURRENTDISK); + } + } else { + _outputMixerSize = ((22050 * 2 * 2) / 4) * 3; + + if (_bundle->openMusicFile("digmusic.bun", _scumm->getGameDataPath()) == false) + return; + } + _musicBundleBufFinal = (byte *)malloc(_outputMixerSize); + _musicBundleBufOutput = (byte *)malloc(((_outputMixerSize / 0x2000) + 1) * _outputMixerSize); + _currentSampleBundleMusic = 0; + _offsetSampleBundleMusic = 0; + _offsetBufBundleMusic = 0; + _bundleMusicPosition = 0; + _bundleSongPosInMs = 0; + _pauseBundleMusic = false; + _musicBundleToBeChanged = false; + _bundleMusicTrack = 0; + _numberSamplesBundleMusic = _bundle->getNumberOfMusicSamplesByName(song); + _nameBundleMusic = song; + _scumm->_timer->installTimerProc(&music_handler, 1000000, this); + } else if (strcmp(_nameBundleMusic, song) != 0) { + _newNameBundleMusic = song; + _musicBundleToBeChanged = true; + } +} + +void IMuseDigital::pauseBundleMusic(bool state) { + _pauseBundleMusic = state; +} + +void IMuseDigital::stopBundleMusic() { + // First stop the music timer + _scumm->_timer->removeTimerProc(&music_handler); + _nameBundleMusic = ""; + _scumm->_mixer->stopHandle(_bundleMusicTrack); + if (_musicBundleBufFinal) { + free(_musicBundleBufFinal); + _musicBundleBufFinal = NULL; + } + if (_musicBundleBufOutput) { + free(_musicBundleBufOutput); + _musicBundleBufOutput = NULL; + } +} + +void IMuseDigital::bundleMusicHandler() { + byte *ptr; + int32 l, num = _numberSamplesBundleMusic, length, k; + int32 rate = 22050; + int32 tag, size = -1, header_size = 0; + + if (_pauseBundleMusic) + return; + + if (_musicBundleToBeChanged) { + _nameBundleMusic = _newNameBundleMusic; + _numberSamplesBundleMusic = _bundle->getNumberOfMusicSamplesByName(_nameBundleMusic); + _currentSampleBundleMusic = 0; + _offsetSampleBundleMusic = 0; + _offsetBufBundleMusic = 0; + _musicBundleToBeChanged = false; + _bundleMusicPosition = 0; + _bundleSongPosInMs = 0; + } + + ptr = _musicBundleBufOutput; + + for (k = 0, l = _currentSampleBundleMusic; l < num; k++) { + length = _bundle->decompressMusicSampleByName(_nameBundleMusic, l, (_musicBundleBufOutput + ((k * 0x2000) + _offsetBufBundleMusic))); + _offsetSampleBundleMusic += length; + + if (l == 0) { + tag = READ_BE_UINT32(ptr); ptr += 4; + if (tag != MKID_BE('iMUS')) { + error("Decompressing bundle song failed (unknown tag '%s')", tag2str(tag)); + } + + ptr += 12; + while (tag != MKID_BE('DATA')) { + tag = READ_BE_UINT32(ptr); ptr += 4; + switch(tag) { + case MKID_BE('FRMT'): + ptr += 12; + _bundleMusicSampleBits = READ_BE_UINT32(ptr); ptr += 4; + rate = READ_BE_UINT32(ptr); ptr += 4; + _bundleSampleChannels = READ_BE_UINT32(ptr); ptr += 4; + break; + case MKID_BE('TEXT'): + case MKID_BE('REGN'): + case MKID_BE('STOP'): + case MKID_BE('JUMP'): + case MKID_BE('SYNC'): + size = READ_BE_UINT32(ptr); ptr += size + 4; + break; + case MKID_BE('DATA'): + size = READ_BE_UINT32(ptr); ptr += 4; + break; + + default: + error("Unknown sound header %c%c%c%c", + (byte)(tag >> 24), + (byte)(tag >> 16), + (byte)(tag >> 8), + (byte)tag); + } + } + if (size < 0) { + error("Decompressing sound failed (missing size field)"); + } + header_size = (ptr - _musicBundleBufOutput); + } + + l++; + _currentSampleBundleMusic = l; + + if (_offsetSampleBundleMusic >= _outputMixerSize + header_size) { + memcpy(_musicBundleBufFinal, (_musicBundleBufOutput + header_size), _outputMixerSize); + _offsetBufBundleMusic = _offsetSampleBundleMusic - _outputMixerSize - header_size; + memcpy(_musicBundleBufOutput, (_musicBundleBufOutput + (_outputMixerSize + header_size)), _offsetBufBundleMusic); + _offsetSampleBundleMusic = _offsetBufBundleMusic; + break; + } + } + + if (_currentSampleBundleMusic == num) { + _currentSampleBundleMusic = 0; + _offsetSampleBundleMusic = 0; + _offsetBufBundleMusic = 0; + _bundleMusicPosition = 0; + _bundleSongPosInMs = 0; + } + + ptr = _musicBundleBufFinal; + + byte *buffer = NULL; + uint32 final_size; + if (_bundleMusicSampleBits == 12) { + final_size = decode12BitsSample(ptr, &buffer, _outputMixerSize, false); + } else if (_bundleMusicSampleBits == 16) { + buffer = (byte *)malloc(_outputMixerSize); + final_size = _outputMixerSize; + memcpy(buffer, ptr, _outputMixerSize); + } else { + warning("IMuseDigital::bundleMusicHandler TODO: more newStream options..."); + return; + } + + _bundleSongPosInMs = (_bundleMusicPosition * 5) / (_outputMixerSize / 200); + _bundleMusicPosition += final_size; + if (_bundleMusicTrack == 0) + _scumm->_mixer->newStream(&_bundleMusicTrack, rate, SoundMixer::FLAG_16BITS | SoundMixer::FLAG_STEREO, 300000); + _scumm->_mixer->appendStream(_bundleMusicTrack, buffer, final_size); + free(buffer); +} + +void IMuseDigital::playBundleSound(const char *sound, PlayingSoundHandle *handle) { + byte *ptr = 0, *orig_ptr = 0; + byte *final; + bool result; + + if (_scumm->_noDigitalSamples) + return; + + if (_scumm->_gameId == GID_CMI) { + if (_scumm->_features & GF_DEMO) { + result = _bundle->openVoiceFile("voice.bun", _scumm->getGameDataPath()); + } else { + char voxfile[20]; + sprintf(voxfile, "voxdisk%d.bun", _scumm->VAR(_scumm->VAR_CURRENTDISK)); + if (_voiceDisk != _scumm->VAR(_scumm->VAR_CURRENTDISK)) + _bundle->closeVoiceFile(); + + result = _bundle->openVoiceFile(voxfile, _scumm->getGameDataPath()); + + if (result == false) + result = _bundle->openVoiceFile("voice.bun", _scumm->getGameDataPath()); + _voiceDisk = (byte)_scumm->VAR(_scumm->VAR_CURRENTDISK); + } + } else if (_scumm->_gameId == GID_DIG) + result = _bundle->openVoiceFile("digvoice.bun", _scumm->getGameDataPath()); + else + error("Don't know which bundle file to load"); + + if (!result) + return; + + int32 rate = 22050, pan = 0, channels, output_size = 0; + int32 tag, size = -1, bits = 0; + + if (_scumm->_gameId == GID_CMI) { + char name[20]; + strcpy(name, sound); + if (!(_scumm->_features & GF_DEMO)) // CMI demo does not have .IMX for voice but does for music... + strcat(name, ".IMX"); + output_size = _bundle->decompressVoiceSampleByName(name, &ptr); + } else { + output_size = _bundle->decompressVoiceSampleByName(sound, &ptr); + } + + orig_ptr = ptr; + if (output_size == 0 || orig_ptr == 0) { + goto bail; + } + + tag = READ_BE_UINT32(ptr); ptr += 4; + if (tag != MKID_BE('iMUS')) { + warning("Decompression of bundle sound failed"); + goto bail; + } + + ptr += 12; + while (tag != MKID_BE('DATA')) { + tag = READ_BE_UINT32(ptr); ptr += 4; + switch(tag) { + case MKID_BE('FRMT'): + ptr += 12; + bits = READ_BE_UINT32(ptr); ptr += 4; + rate = READ_BE_UINT32(ptr); ptr += 4; + channels = READ_BE_UINT32(ptr); ptr += 4; + break; + case MKID_BE('TEXT'): + case MKID_BE('REGN'): + case MKID_BE('STOP'): + case MKID_BE('JUMP'): + case MKID_BE('SYNC'): + size = READ_BE_UINT32(ptr); ptr += size + 4; + break; + case MKID_BE('DATA'): + size = READ_BE_UINT32(ptr); ptr += 4; + break; + default: + error("Unknown sound header %c%c%c%c", + (byte)(tag >> 24), + (byte)(tag >> 16), + (byte)(tag >> 8), + (byte)tag); + } + } + + if (size < 0) { + warning("Decompression sound failed (no size field)"); + goto bail; + } + + final = (byte *)malloc(size); + memcpy(final, ptr, size); + + if (_scumm->_actorToPrintStrFor != 0xFF && _scumm->_actorToPrintStrFor != 0) { + Actor *a = _scumm->derefActor(_scumm->_actorToPrintStrFor, "playBundleSound"); + rate = (rate * a->talkFrequency) / 256; + + // Adjust to fit the mixer's notion of panning. + if (pan != 64) + pan = 2 * a->talkPan - 127; + } + + // Stop any sound currently playing on the given handle + if (handle) + _scumm->_mixer->stopHandle(*handle); + + if (bits == 8) { + _scumm->_mixer->playRaw(handle, final, size, rate, SoundMixer::FLAG_UNSIGNED | SoundMixer::FLAG_AUTOFREE, -1, 255, pan); + } else if (bits == 16) { + // FIXME: For some weird reasons, sometimes we get an odd size, even though + // the data is supposed to be in 16 bit format... that makes no sense... + size &= ~1; + _scumm->_mixer->playRaw(handle, final, size, rate, SoundMixer::FLAG_16BITS | SoundMixer::FLAG_AUTOFREE, -1, 255, pan); + } else { + warning("IMuseDigital::playBundleSound() to do more options to playRaw..."); + } + +bail: + free(orig_ptr); +} + + + } // End of namespace Scumm #ifdef __PALM_OS__ diff --git a/scumm/imuse_digi.h b/scumm/imuse_digi.h index 620eea16e5..161f27e10f 100644 --- a/scumm/imuse_digi.h +++ b/scumm/imuse_digi.h @@ -34,6 +34,7 @@ namespace Scumm { #define MAX_IMUSE_REGIONS 3 class ScummEngine; +class Bundle; /** * iMuse Digital Implementation for SCUMM v7 and higher. @@ -68,9 +69,43 @@ private: ScummEngine *_scumm; bool _pause; - static void timer_handler(void *engine); + static void timer_handler(void *refConf); void musicTimer(); + // + // Bundle music + // + const char *_nameBundleMusic; + const char *_newNameBundleMusic; + byte _musicDisk; + byte _voiceDisk; + int32 _currentSampleBundleMusic; + int32 _numberSamplesBundleMusic; + int32 _offsetSampleBundleMusic; + int32 _offsetBufBundleMusic; + byte *_musicBundleBufFinal; + byte *_musicBundleBufOutput; + bool _pauseBundleMusic; + PlayingSoundHandle _bundleMusicTrack; + bool _musicBundleToBeChanged; + int32 _bundleMusicSampleBits; + int32 _outputMixerSize; + int32 _bundleSampleChannels; + int32 _bundleMusicPosition; + + static void music_handler(void *refCon); + void bundleMusicHandler(); + + void playBundleMusic(const char *song); + void pauseBundleMusic(bool state); + +public: + int32 _bundleSongPosInMs; + Bundle *_bundle; // FIXME: should be protected but is used by ScummEngine::askForDisk + + void stopBundleMusic(); + void playBundleSound(const char *sound, PlayingSoundHandle *handle); + public: IMuseDigital(ScummEngine *scumm); ~IMuseDigital(); diff --git a/scumm/resource.cpp b/scumm/resource.cpp index 471a2cd52e..ea62be8b22 100644 --- a/scumm/resource.cpp +++ b/scumm/resource.cpp @@ -26,6 +26,7 @@ #include "scumm/bundle.h" #include "scumm/dialogs.h" #include "scumm/imuse.h" +#include "scumm/imuse_digi.h" #include "scumm/object.h" #include "scumm/resource.h" #include "scumm/scumm.h" @@ -227,8 +228,8 @@ void ScummEngine::askForDisk(const char *filename, int disknum) { if (_version == 8) { char result; - _sound->_bundle->closeVoiceFile(); - _sound->_bundle->closeMusicFile(); + _imuseDigital->_bundle->closeVoiceFile(); + _imuseDigital->_bundle->closeMusicFile(); #ifdef MACOSX sprintf(buf, "Cannot find file: '%s'\nPlease insert disc %d.\nHit OK to retry, Cancel to exit", filename, disknum); diff --git a/scumm/saveload.cpp b/scumm/saveload.cpp index f9fbdc9430..d477063ef5 100644 --- a/scumm/saveload.cpp +++ b/scumm/saveload.cpp @@ -126,7 +126,8 @@ bool ScummEngine::loadState(int slot, bool compat, SaveFileManager *mgr) { memcpy(_saveLoadName, hdr.name, sizeof(hdr.name)); _sound->stopAllSounds(); - _sound->stopBundleMusic(); + if (_imuseDigital) + _imuseDigital->stopBundleMusic(); _sound->stopCD(); _sound->pauseSounds(true); diff --git a/scumm/script_v8.cpp b/scumm/script_v8.cpp index 5a45b9f8eb..123451ca8d 100644 --- a/scumm/script_v8.cpp +++ b/scumm/script_v8.cpp @@ -24,6 +24,7 @@ #include "scumm/actor.h" #include "scumm/akos.h" #include "scumm/charset.h" +#include "scumm/imuse_digi.h" #include "scumm/intern.h" #include "scumm/object.h" #include "scumm/resource.h" @@ -1483,7 +1484,7 @@ void ScummEngine_v8::o8_kernelGetFunctions() { case 0xE1: // imGetMusicPosition warning("o8_kernelGetFunctions: imGetMusicPosition(stub)"); // FIXME - get this stuff to be properly implemented - push(_sound->_bundleSongPosInMs); + push(_imuseDigital->_bundleSongPosInMs); break; case 0xE2: // musicLipSyncWidth case 0xE3: // musicLipSyncHeight diff --git a/scumm/smush/insane.cpp b/scumm/smush/insane.cpp index e65281be1e..b247dc4c79 100644 --- a/scumm/smush/insane.cpp +++ b/scumm/smush/insane.cpp @@ -8213,7 +8213,6 @@ void Insane::smush_setupSanFile(const char *filename, int32 offset) { _player->seekSan(filename, _scumm->getGameDataPath(), offset); _scumm->_imuseDigital->pause(false); - _scumm->_sound->pauseBundleMusic(false); } } diff --git a/scumm/smush/smush_player.cpp b/scumm/smush/smush_player.cpp index 36396eb515..8028d5eff7 100644 --- a/scumm/smush/smush_player.cpp +++ b/scumm/smush/smush_player.cpp @@ -244,7 +244,6 @@ void SmushPlayer::init() { _frame = 0; - _scumm->_sound->pauseBundleMusic(true); if (_scumm->_imuseDigital) { _scumm->_imuseDigital->pause(true); } @@ -293,7 +292,6 @@ void SmushPlayer::deinit() { if (_scumm->_imuseDigital) { _scumm->_imuseDigital->pause(false); } - _scumm->_sound->pauseBundleMusic(false); _scumm->_fullRedraw = true; } @@ -373,7 +371,7 @@ void SmushPlayer::handleIACT(Chunk &b) { checkBlock(b, TYPE_IACT, 8); debug(6, "SmushPlayer::handleImuseAction()"); - int code = b.getWord(); + /* int code = */ b.getWord(); int flags = b.getWord(); int unknown = b.getShort(); int track_flags = b.getWord(); diff --git a/scumm/sound.cpp b/scumm/sound.cpp index 06be1f4673..ce475a4ad7 100644 --- a/scumm/sound.cpp +++ b/scumm/sound.cpp @@ -22,7 +22,6 @@ #include "stdafx.h" #include "scumm/actor.h" -#include "scumm/bundle.h" #include "scumm/imuse.h" #include "scumm/imuse_digi.h" #include "scumm/scumm.h" @@ -57,21 +56,14 @@ Sound::Sound(ScummEngine *parent) { memset(this,0,sizeof(Sound)); // palmos _scumm = parent; - _nameBundleMusic = ""; - _musicBundleBufFinal = NULL; - _musicBundleBufOutput = NULL; - _musicDisk = 0; _talkChannelHandle = 0; _currentCDSound = 0; _sfxFile = 0; - - _bundle = new Bundle(); } Sound::~Sound() { delete _sfxFile; - delete _bundle; } void Sound::addSoundToQueue(int sound) { @@ -821,8 +813,6 @@ void Sound::pauseSounds(bool pause) { _scumm->_mixer->pauseAll(pause); - _scumm->_sound->pauseBundleMusic(pause); - if (_scumm->_imuseDigital) { _scumm->_imuseDigital->pause(pause); } @@ -978,346 +968,6 @@ bool Sound::isSfxFinished() const { return !_scumm->_mixer->hasActiveSFXChannel(); } -uint32 Sound::decode12BitsSample(byte *src, byte **dst, uint32 size, bool stereo) { - uint32 s_size = (size / 3) * 4; - uint32 loop_size = s_size / 4; - if (stereo) { - s_size *= 2; - } - byte *ptr = *dst = (byte *)malloc(s_size); - - uint32 tmp; - while (loop_size--) { - byte v1 = *src++; - byte v2 = *src++; - byte v3 = *src++; - tmp = ((((v2 & 0x0f) << 8) | v1) << 4) - 0x8000; - *ptr++ = (byte)((tmp >> 8) & 0xff); - *ptr++ = (byte)(tmp & 0xff); - if (stereo) { - *ptr++ = (byte)((tmp >> 8) & 0xff); - *ptr++ = (byte)(tmp & 0xff); - } - tmp = ((((v2 & 0xf0) << 4) | v3) << 4) - 0x8000; - *ptr++ = (byte)((tmp >> 8) & 0xff); - *ptr++ = (byte)(tmp & 0xff); - if (stereo) { - *ptr++ = (byte)((tmp >> 8) & 0xff); - *ptr++ = (byte)(tmp & 0xff); - } - } - return s_size; -} - -static void music_handler(void *refCon) { - Sound *sound = (Sound *)refCon; - sound->bundleMusicHandler(g_scumm); -} - -void Sound::playBundleMusic(const char *song) { - if (_scumm->_silentDigitalImuse) { - return; - } - - if (_nameBundleMusic[0] == 0) { - if (_scumm->_gameId == GID_CMI) { - _outputMixerSize = (22050 * 2 * 2); - - char bunfile[20]; - if (_scumm->_features & GF_DEMO) { - if (_bundle->openMusicFile("music.bun", _scumm->getGameDataPath()) == false) { - _outputMixerSize = 0; - return; - } - } else { - - sprintf(bunfile, "musdisk%d.bun", _scumm->VAR(_scumm->VAR_CURRENTDISK)); - if (_musicDisk != _scumm->VAR(_scumm->VAR_CURRENTDISK)) - _bundle->closeMusicFile(); - - if (_bundle->openMusicFile(bunfile, _scumm->getGameDataPath()) == false) { - if (_bundle->openMusicFile("music.bun", _scumm->getGameDataPath()) == false) { - _outputMixerSize = 0; - return; - } - } - - _musicDisk = (byte)_scumm->VAR(_scumm->VAR_CURRENTDISK); - } - } else { - _outputMixerSize = ((22050 * 2 * 2) / 4) * 3; - - if (_bundle->openMusicFile("digmusic.bun", _scumm->getGameDataPath()) == false) - return; - } - _musicBundleBufFinal = (byte *)malloc(_outputMixerSize); - _musicBundleBufOutput = (byte *)malloc(((_outputMixerSize / 0x2000) + 1) * _outputMixerSize); - _currentSampleBundleMusic = 0; - _offsetSampleBundleMusic = 0; - _offsetBufBundleMusic = 0; - _bundleMusicPosition = 0; - _bundleSongPosInMs = 0; - _pauseBundleMusic = false; - _musicBundleToBeChanged = false; - _bundleMusicTrack = 0; - _numberSamplesBundleMusic = _bundle->getNumberOfMusicSamplesByName(song); - _nameBundleMusic = song; - _scumm->_timer->installTimerProc(&music_handler, 1000000, this); - } else if (strcmp(_nameBundleMusic, song) != 0) { - _newNameBundleMusic = song; - _musicBundleToBeChanged = true; - } -} - -void Sound::pauseBundleMusic(bool state) { - _pauseBundleMusic = state; -} - -void Sound::stopBundleMusic() { - // First stop the music timer - _scumm->_timer->removeTimerProc(&music_handler); - _nameBundleMusic = ""; - _scumm->_mixer->stopHandle(_bundleMusicTrack); - if (_musicBundleBufFinal) { - free(_musicBundleBufFinal); - _musicBundleBufFinal = NULL; - } - if (_musicBundleBufOutput) { - free(_musicBundleBufOutput); - _musicBundleBufOutput = NULL; - } -} - -void Sound::bundleMusicHandler(ScummEngine *scumm) { - byte *ptr; - int32 l, num = _numberSamplesBundleMusic, length, k; - int32 rate = 22050; - int32 tag, size = -1, header_size = 0; - - if (_pauseBundleMusic) - return; - - if (_musicBundleToBeChanged) { - _nameBundleMusic = _newNameBundleMusic; - _numberSamplesBundleMusic = _bundle->getNumberOfMusicSamplesByName(_nameBundleMusic); - _currentSampleBundleMusic = 0; - _offsetSampleBundleMusic = 0; - _offsetBufBundleMusic = 0; - _musicBundleToBeChanged = false; - _bundleMusicPosition = 0; - _bundleSongPosInMs = 0; - } - - ptr = _musicBundleBufOutput; - - for (k = 0, l = _currentSampleBundleMusic; l < num; k++) { - length = _bundle->decompressMusicSampleByName(_nameBundleMusic, l, (_musicBundleBufOutput + ((k * 0x2000) + _offsetBufBundleMusic))); - _offsetSampleBundleMusic += length; - - if (l == 0) { - tag = READ_BE_UINT32(ptr); ptr += 4; - if (tag != MKID_BE('iMUS')) { - error("Decompressing bundle song failed (unknown tag '%s')", tag2str(tag)); - } - - ptr += 12; - while (tag != MKID_BE('DATA')) { - tag = READ_BE_UINT32(ptr); ptr += 4; - switch(tag) { - case MKID_BE('FRMT'): - ptr += 12; - _bundleMusicSampleBits = READ_BE_UINT32(ptr); ptr += 4; - rate = READ_BE_UINT32(ptr); ptr += 4; - _bundleSampleChannels = READ_BE_UINT32(ptr); ptr += 4; - break; - case MKID_BE('TEXT'): - case MKID_BE('REGN'): - case MKID_BE('STOP'): - case MKID_BE('JUMP'): - case MKID_BE('SYNC'): - size = READ_BE_UINT32(ptr); ptr += size + 4; - break; - case MKID_BE('DATA'): - size = READ_BE_UINT32(ptr); ptr += 4; - break; - - default: - error("Unknown sound header %c%c%c%c", - (byte)(tag >> 24), - (byte)(tag >> 16), - (byte)(tag >> 8), - (byte)tag); - } - } - if (size < 0) { - error("Decompressing sound failed (missing size field)"); - } - header_size = (ptr - _musicBundleBufOutput); - } - - l++; - _currentSampleBundleMusic = l; - - if (_offsetSampleBundleMusic >= _outputMixerSize + header_size) { - memcpy(_musicBundleBufFinal, (_musicBundleBufOutput + header_size), _outputMixerSize); - _offsetBufBundleMusic = _offsetSampleBundleMusic - _outputMixerSize - header_size; - memcpy(_musicBundleBufOutput, (_musicBundleBufOutput + (_outputMixerSize + header_size)), _offsetBufBundleMusic); - _offsetSampleBundleMusic = _offsetBufBundleMusic; - break; - } - } - - if (_currentSampleBundleMusic == num) { - _currentSampleBundleMusic = 0; - _offsetSampleBundleMusic = 0; - _offsetBufBundleMusic = 0; - _bundleMusicPosition = 0; - _bundleSongPosInMs = 0; - } - - ptr = _musicBundleBufFinal; - - byte *buffer = NULL; - uint32 final_size; - if (_bundleMusicSampleBits == 12) { - final_size = decode12BitsSample(ptr, &buffer, _outputMixerSize, false); - } else if (_bundleMusicSampleBits == 16) { - buffer = (byte *)malloc(_outputMixerSize); - final_size = _outputMixerSize; - memcpy(buffer, ptr, _outputMixerSize); - } else { - warning("Sound::bundleMusicHandler TODO: more newStream options..."); - return; - } - - _bundleSongPosInMs = (_bundleMusicPosition * 5) / (_outputMixerSize / 200); - _bundleMusicPosition += final_size; - if (_bundleMusicTrack == 0) - _scumm->_mixer->newStream(&_bundleMusicTrack, rate, SoundMixer::FLAG_16BITS | SoundMixer::FLAG_STEREO, 300000); - _scumm->_mixer->appendStream(_bundleMusicTrack, buffer, final_size); - free(buffer); -} - -void Sound::playBundleSound(char *sound, PlayingSoundHandle *handle) { - byte *ptr = 0, *orig_ptr = 0; - byte *final; - bool result; - - if (_scumm->_noDigitalSamples) - return; - - if (_scumm->_gameId == GID_CMI) { - if (_scumm->_features & GF_DEMO) { - result = _bundle->openVoiceFile("voice.bun", _scumm->getGameDataPath()); - } else { - char voxfile[20]; - sprintf(voxfile, "voxdisk%d.bun", _scumm->VAR(_scumm->VAR_CURRENTDISK)); - if (_voiceDisk != _scumm->VAR(_scumm->VAR_CURRENTDISK)) - _bundle->closeVoiceFile(); - - result = _bundle->openVoiceFile(voxfile, _scumm->getGameDataPath()); - - if (result == false) - result = _bundle->openVoiceFile("voice.bun", _scumm->getGameDataPath()); - _voiceDisk = (byte)_scumm->VAR(_scumm->VAR_CURRENTDISK); - } - } else if (_scumm->_gameId == GID_DIG) - result = _bundle->openVoiceFile("digvoice.bun", _scumm->getGameDataPath()); - else - error("Don't know which bundle file to load"); - - if (!result) - return; - - int32 rate = 22050, pan = 0, channels, output_size = 0; - int32 tag, size = -1, bits = 0; - - if (_scumm->_gameId == GID_CMI) { - char name[20]; - strcpy(name, sound); - if (!(_scumm->_features & GF_DEMO)) // CMI demo does not have .IMX for voice but does for music... - strcat(name, ".IMX"); - output_size = _bundle->decompressVoiceSampleByName(name, &ptr); - } else { - output_size = _bundle->decompressVoiceSampleByName(sound, &ptr); - } - - orig_ptr = ptr; - if (output_size == 0 || orig_ptr == 0) { - goto bail; - } - - tag = READ_BE_UINT32(ptr); ptr += 4; - if (tag != MKID_BE('iMUS')) { - warning("Decompression of bundle sound failed"); - goto bail; - } - - ptr += 12; - while (tag != MKID_BE('DATA')) { - tag = READ_BE_UINT32(ptr); ptr += 4; - switch(tag) { - case MKID_BE('FRMT'): - ptr += 12; - bits = READ_BE_UINT32(ptr); ptr += 4; - rate = READ_BE_UINT32(ptr); ptr += 4; - channels = READ_BE_UINT32(ptr); ptr += 4; - break; - case MKID_BE('TEXT'): - case MKID_BE('REGN'): - case MKID_BE('STOP'): - case MKID_BE('JUMP'): - case MKID_BE('SYNC'): - size = READ_BE_UINT32(ptr); ptr += size + 4; - break; - case MKID_BE('DATA'): - size = READ_BE_UINT32(ptr); ptr += 4; - break; - default: - error("Unknown sound header %c%c%c%c", - (byte)(tag >> 24), - (byte)(tag >> 16), - (byte)(tag >> 8), - (byte)tag); - } - } - - if (size < 0) { - warning("Decompression sound failed (no size field)"); - goto bail; - } - - final = (byte *)malloc(size); - memcpy(final, ptr, size); - - if (_scumm->_actorToPrintStrFor != 0xFF && _scumm->_actorToPrintStrFor != 0) { - Actor *a = _scumm->derefActor(_scumm->_actorToPrintStrFor, "playBundleSound"); - rate = (rate * a->talkFrequency) / 256; - - // Adjust to fit the mixer's notion of panning. - if (pan != 64) - pan = 2 * a->talkPan - 127; - } - - // Stop any sound currently playing on the given handle - if (handle) - _scumm->_mixer->stopHandle(*handle); - - if (bits == 8) { - _scumm->_mixer->playRaw(handle, final, size, rate, SoundMixer::FLAG_UNSIGNED | SoundMixer::FLAG_AUTOFREE, -1, 255, pan); - } else if (bits == 16) { - // FIXME: For some weird reasons, sometimes we get an odd size, even though - // the data is supposed to be in 16 bit format... that makes no sense... - size &= ~1; - _scumm->_mixer->playRaw(handle, final, size, rate, SoundMixer::FLAG_16BITS | SoundMixer::FLAG_AUTOFREE, -1, 255, pan); - } else { - warning("Sound::playBundleSound() to do more options to playRaw..."); - } - -bail: - free(orig_ptr); -} - void Sound::playSfxSound(void *sound, uint32 size, uint rate, bool isUnsigned, PlayingSoundHandle *handle) { byte flags = SoundMixer::FLAG_AUTOFREE; if (isUnsigned) diff --git a/scumm/sound.h b/scumm/sound.h index e1b6c7c64d..263208c304 100644 --- a/scumm/sound.h +++ b/scumm/sound.h @@ -28,7 +28,6 @@ class File; namespace Scumm { -class Bundle; class ScummEngine; struct MP3OffsetTable; @@ -38,28 +37,6 @@ protected: int16 _soundQuePos, _soundQue[0x100]; int16 _soundQue2Pos, _soundQue2[10]; -public: - const char *_nameBundleMusic; - int32 _bundleMusicPosition; - int32 _bundleSongPosInMs; - -protected: - const char *_newNameBundleMusic; - byte _musicDisk; - byte _voiceDisk; - int32 _currentSampleBundleMusic; - int32 _numberSamplesBundleMusic; - int32 _offsetSampleBundleMusic; - int32 _offsetBufBundleMusic; - byte *_musicBundleBufFinal; - byte *_musicBundleBufOutput; - bool _pauseBundleMusic; - PlayingSoundHandle _bundleMusicTrack; - bool _musicBundleToBeChanged; - int32 _bundleMusicSampleBits; - int32 _outputMixerSize; - int32 _bundleSampleChannels; - File *_sfxFile; uint32 _talk_sound_a1, _talk_sound_a2, _talk_sound_b1, _talk_sound_b2; byte _talk_sound_mode; @@ -81,8 +58,6 @@ public: PlayingSoundHandle _talkChannelHandle; // Handle of mixer channel actor is talking on bool _soundsPaused; byte _sfxMode; - - Bundle *_bundle; // FIXME: should be protected but is used by ScummEngine::askForDisk public: Sound(ScummEngine *parent); @@ -105,14 +80,6 @@ public: void setupSound(); void pauseSounds(bool pause); - void playBundleMusic(const char *song); - void pauseBundleMusic(bool state); - void bundleMusicHandler(ScummEngine *scumm); - void stopBundleMusic(); - void playBundleSound(char *sound, PlayingSoundHandle *handle); - - uint32 decode12BitsSample(byte *src, byte **dst, uint32 size, bool stereo); - void startCDTimer(); void stopCDTimer(); diff --git a/scumm/string.cpp b/scumm/string.cpp index fc55dda3d5..f9f01f8f51 100644 --- a/scumm/string.cpp +++ b/scumm/string.cpp @@ -25,6 +25,7 @@ #include "scumm/actor.h" #include "scumm/charset.h" #include "scumm/dialogs.h" +#include "scumm/imuse_digi.h" #include "scumm/verbs.h" #include "scumm/sound.h" @@ -899,7 +900,7 @@ const byte *ScummEngine::translateTextAndPlaySpeech(const byte *ptr) { pointer[j] = 0; // Play speech - _sound->playBundleSound(pointer, &_sound->_talkChannelHandle); + _imuseDigital->playBundleSound(pointer, &_sound->_talkChannelHandle); ptr = _transText; } |