diff options
Diffstat (limited to 'engines/sci')
-rw-r--r-- | engines/sci/resource.cpp | 152 | ||||
-rw-r--r-- | engines/sci/resource.h | 36 | ||||
-rw-r--r-- | engines/sci/sfx/music.cpp | 141 | ||||
-rw-r--r-- | engines/sci/sfx/music.h | 6 | ||||
-rw-r--r-- | engines/sci/sfx/soundcmd.cpp | 2 |
5 files changed, 178 insertions, 159 deletions
diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index c8b109f070..14a72af1b0 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -1808,89 +1808,105 @@ bool ResourceManager::hasSci1Voc900() { return offset == res->size; } -SoundResource::SoundResource(uint32 resNumber, ResourceManager *resMan) : _resMan(resMan) { - Resource *res = _resMan->findResource(ResourceId(kResourceTypeSound, resNumber), true); - if (!res) +SoundResource::SoundResource(uint32 resNumber, ResourceManager *resMan, SciVersion soundVersion) : _resMan(resMan), _soundVersion(soundVersion) { + Resource *resource = _resMan->findResource(ResourceId(kResourceTypeSound, resNumber), true); + int trackNr, channelNr; + if (!resource) return; - _innerResource = res; - - byte *ptr = res->data, *p1; - tagChannel *pCh; - // count # of tracks - nTracks = 0; - while ((*ptr++) != 0xFF) { - nTracks++; - while (*ptr != 0xFF) - ptr += 6; - ptr++; - } - aTracks = new tagTrack[nTracks]; - ptr = res->data; - for (int i = 0; i < nTracks; i++) { - // SCI01/SCI1/SCI11 - // Track info starts with track-type:BYTE - // Then track-information gets appeneded Unknown:WORD, TrackOffset:WORD, TrackSize:WORD - // 0xFF:BYTE as terminator to end that track and begin with another track-type - // track-type 0xFF means end-of-tracks - - aTracks[i].type = (kTrackType) * ptr++; - // counting # of channels used - p1 = ptr; - aTracks[i].nChannels = 0; - while (*p1 != 0xFF) { - p1 += 6; - aTracks[i].nChannels++; + _innerResource = resource; + + byte *data = resource->data, *data2; + Channel *channel; + + switch (_soundVersion) { + case SCI_VERSION_0_EARLY: + error("SCI0 sound data currently not supported"); + break; + + case SCI_VERSION_1_EARLY: + case SCI_VERSION_1_LATE: + // count # of tracks + _trackCount = 0; + while ((*data++) != 0xFF) { + _trackCount++; + while (*data != 0xFF) + data += 6; + data++; } - aTracks[i].aChannels = new tagChannel[aTracks[i].nChannels]; - if (aTracks[i].type != 0xF0) // digital track marker - not supported at time - { - aTracks[i].nDigital = 0xFF; // meanwhile - no ditigal channel associated - for (int j = 0; j < aTracks[i].nChannels; j++) { - pCh = &aTracks[i].aChannels[j]; - pCh->unk = READ_LE_UINT16(ptr); - pCh->ptr = res->data + READ_LE_UINT16(ptr + 2) + 2; - pCh->size = READ_LE_UINT16(ptr + 4) - 2; // not counting channel header - pCh->number = *(pCh->ptr - 2); - pCh->poly = *(pCh->ptr - 1); - pCh->time = pCh->prev = 0; - if (pCh->number == 0xFE) // digital channel - aTracks[i].nDigital = j; - ptr += 6; + _tracks = new Track[_trackCount]; + data = resource->data; + for (trackNr = 0; trackNr < _trackCount; trackNr++) { + // SCI01/SCI1/SCI11 + // Track info starts with track-type:BYTE + // Then channel-information gets appeneded Unknown:WORD, ChannelOffset:WORD, ChannelSize:WORD + // 0xFF:BYTE as terminator to end that track and begin with another track-type + // track-type 0xFF means end-of-tracks + + _tracks[trackNr].type = (TrackType) *data++; + // counting # of channels used + data2 = data; + _tracks[trackNr].channelCount = 0; + while (*data2 != 0xFF) { + data2 += 6; + _tracks[trackNr].channelCount++; } - } else { - // Skip over digital track - ptr += 6; + _tracks[trackNr].channels = new Channel[_tracks[trackNr].channelCount]; + if (_tracks[trackNr].type != 0xF0) { // digital track marker - not supported at time + _tracks[trackNr].nDigital = 0xFF; // meanwhile - no ditigal channel associated + for (channelNr = 0; channelNr < _tracks[trackNr].channelCount; channelNr++) { + channel = &_tracks[trackNr].channels[channelNr]; + channel->unk = READ_LE_UINT16(data); + channel->data = resource->data + READ_LE_UINT16(data + 2) + 2; + channel->size = READ_LE_UINT16(data + 4) - 2; // not counting channel header + channel->number = *(channel->data - 2); + channel->poly = *(channel->data - 1); + channel->time = channel->prev = 0; + if (channel->number == 0xFE) // digital channel + _tracks[trackNr].nDigital = channelNr; + data += 6; + } + } else { + // Skip over digital track + data += 6; + } + data++; // skipping 0xFF that closes channels list } - ptr++; // skipping 0xFF that closes channels list - } - /* - digital track ->ptr points to header: - [w] sample rate - [w] size - [w] ? 00 00 maybe compression flag - [w] ? size again - decompressed size maybe - */ + /* + digital track ->ptr points to header: + [w] sample rate + [w] size + [w] ? 00 00 maybe compression flag + [w] ? size again - decompressed size maybe + */ + break; + } } //---------------------------------------------------- SoundResource::~SoundResource() { - for (int i = 0; i < nTracks; i++) - delete[] aTracks[i].aChannels; - delete[] aTracks; + for (int trackNr = 0; trackNr < _trackCount; trackNr++) + delete[] _tracks[trackNr].channels; + delete[] _tracks; _resMan->unlockResource(_innerResource); } //---------------------------------------------------- -SoundResource::tagTrack* SoundResource::getTrackByNumber(uint16 number) { - if (/*number >= 0 &&*/number < nTracks) - return &aTracks[number]; +SoundResource::Track* SoundResource::getTrackByNumber(uint16 number) { + if (_soundVersion == SCI_VERSION_0_EARLY) + return &_tracks[0]; + + if (/*number >= 0 &&*/number < _trackCount) + return &_tracks[number]; return NULL; } -SoundResource::tagTrack* SoundResource::getTrackByType(kTrackType type) { - for (int i = 0; i < nTracks; i++) { - if (aTracks[i].type == type) - return &aTracks[i]; +SoundResource::Track* SoundResource::getTrackByType(TrackType type) { + if (_soundVersion == SCI_VERSION_0_EARLY) + return &_tracks[0]; + + for (int trackNr = 0; trackNr < _trackCount; trackNr++) { + if (_tracks[trackNr].type == type) + return &_tracks[trackNr]; } return NULL; } diff --git a/engines/sci/resource.h b/engines/sci/resource.h index 914b75cd1e..ef0674badd 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -429,40 +429,42 @@ protected: class SoundResource { public: - enum kTrackType { - kTrackAdlib = 0, - kTrackGameBlaster = 9, - kTrackMT32 = 12, - kTrackSpeaker = 18, - kTrackTandy = 19 + enum TrackType { + TRACKTYPE_ADLIB = 0, + TRACKTYPE_GAMEBLASTER = 9, + TRACKTYPE_MT32 = 12, + TRACKTYPE_SPEAKER = 18, + TRACKTYPE_TANDY = 19, + TRACKTYPE_NONE = 255 }; - struct tagChannel { + struct Channel { byte number; byte poly; uint16 unk; uint16 size; - byte *ptr; + byte *data; long time; byte prev; }; - struct tagTrack { - kTrackType type; + struct Track { + TrackType type; byte nDigital; - byte nChannels; - tagChannel *aChannels; + byte channelCount; + Channel *channels; uint sz; }; public: - SoundResource(uint32 resNumber, ResourceManager *resMan); + SoundResource(uint32 resNumber, ResourceManager *resMan, SciVersion soundVersion); ~SoundResource(); - tagTrack *getTrackByNumber(uint16 number); - tagTrack *getTrackByType(kTrackType type); + Track *getTrackByNumber(uint16 number); + Track *getTrackByType(TrackType type); private: - byte nTracks; - tagTrack *aTracks; + SciVersion _soundVersion; + int _trackCount; + Track *_tracks; Resource *_innerResource; ResourceManager *_resMan; }; diff --git a/engines/sci/sfx/music.cpp b/engines/sci/sfx/music.cpp index c011a66a3d..6111655d62 100644 --- a/engines/sci/sfx/music.cpp +++ b/engines/sci/sfx/music.cpp @@ -282,46 +282,46 @@ void SciMusic::loadPatchMT32() { //---------------------------------------- void SciMusic::soundInitSnd(MusicEntry *pSnd) { - //_mutex.lock(); + SoundResource::Track *track = NULL; - SoundResource::tagTrack *pTrack = NULL; + //_mutex.lock(); switch (_midiType) { case MD_PCSPK: - pTrack = pSnd->soundRes->getTrackByType(SoundResource::kTrackSpeaker); + track = pSnd->soundRes->getTrackByType(SoundResource::TRACKTYPE_SPEAKER); break; case MD_PCJR: - pTrack = pSnd->soundRes->getTrackByType(SoundResource::kTrackTandy); + track = pSnd->soundRes->getTrackByType(SoundResource::TRACKTYPE_TANDY); break; case MD_ADLIB: - pTrack = pSnd->soundRes->getTrackByType(SoundResource::kTrackAdlib); + track = pSnd->soundRes->getTrackByType(SoundResource::TRACKTYPE_ADLIB); break; case MD_MT32: - pTrack = pSnd->soundRes->getTrackByType(SoundResource::kTrackMT32); + track = pSnd->soundRes->getTrackByType(SoundResource::TRACKTYPE_MT32); break; default: break; } // attempting to select default MT-32/Roland track - if (!pTrack) - pTrack = pSnd->soundRes->getTrackByType(SoundResource::kTrackMT32); - if (pTrack) { + if (!track) + track = pSnd->soundRes->getTrackByType(SoundResource::TRACKTYPE_MT32); + if (track) { // if MIDI device is selected but there is no digital track in sound resource // try to use adlib's digital sample if possible - if (_midiType <= MD_MT32 && pTrack->nDigital == 0xFF && _bMultiMidi) { - if (pSnd->soundRes->getTrackByType(SoundResource::kTrackAdlib)->nDigital != 0xFF) - pTrack = pSnd->soundRes->getTrackByType(SoundResource::kTrackAdlib); + if (_midiType <= MD_MT32 && track->nDigital == 0xFF && _bMultiMidi) { + if (pSnd->soundRes->getTrackByType(SoundResource::TRACKTYPE_ADLIB)->nDigital != 0xFF) + track = pSnd->soundRes->getTrackByType(SoundResource::TRACKTYPE_ADLIB); } // play digital sample - if (pTrack->nDigital != 0xFF) { - byte *pdata = pTrack->aChannels[pTrack->nDigital].ptr; - int rate = READ_LE_UINT16(pdata); - uint32 size = READ_LE_UINT16(pdata + 2); - assert(READ_LE_UINT16(pdata + 4) == 0); // Possibly a compression flag - //assert(READ_LE_UINT16(pdata + 6) == size); + if (track->nDigital != 0xFF) { + byte *channelData = track->channels[track->nDigital].data; + int rate = READ_LE_UINT16(channelData); + uint32 size = READ_LE_UINT16(channelData + 2); + assert(READ_LE_UINT16(channelData + 4) == 0); // Possibly a compression flag + //assert(READ_LE_UINT16(channelData + 6) == size); if (pSnd->pStreamAud) delete pSnd->pStreamAud; - pSnd->pStreamAud = Audio::makeLinearInputStream(pdata + 8, size, rate, + pSnd->pStreamAud = Audio::makeLinearInputStream(channelData + 8, size, rate, Audio::Mixer::FLAG_UNSIGNED, 0, 0); pSnd->hCurrentAud = Audio::SoundHandle(); } else { @@ -331,7 +331,7 @@ void SciMusic::soundInitSnd(MusicEntry *pSnd) { pSnd->pMidiParser->setMidiDriver(_pMidiDrv); pSnd->pMidiParser->setTimerRate(_dwTempo); } - pSnd->pMidiParser->loadMusic(pTrack, pSnd); + pSnd->pMidiParser->loadMusic(track, pSnd); } } @@ -482,7 +482,7 @@ void SciMusic::soundSetMasterVolume(uint16 vol) { // MidiParser_SCI::MidiParser_SCI() : MidiParser() { - _pMidiData = NULL; + _mixedData = NULL; // mididata contains delta in 1/60th second // values of ppqn and tempo are found experimentally and may be wrong _ppqn = 1; @@ -493,15 +493,15 @@ MidiParser_SCI::~MidiParser_SCI() { unloadMusic(); } //--------------------------------------------- -bool MidiParser_SCI::loadMusic(SoundResource::tagTrack *ptrack, MusicEntry *psnd) { +bool MidiParser_SCI::loadMusic(SoundResource::Track *track, MusicEntry *psnd) { unloadMusic(); - _pTrack = ptrack; + _track = track; _pSnd = psnd; setVolume(psnd->volume); midiMixChannels(); _num_tracks = 1; - _tracks[0] = _pMidiData; + _tracks[0] = _mixedData; setTrack(0); _loopTick = 0; return true; @@ -511,9 +511,9 @@ void MidiParser_SCI::unloadMusic() { allNotesOff(); resetTracking(); _num_tracks = 0; - if (_pMidiData) { - delete[] _pMidiData; - _pMidiData = NULL; + if (_mixedData) { + delete[] _mixedData; + _mixedData = NULL; } } @@ -629,13 +629,13 @@ byte MidiParser_SCI::midiGetNextChannel(long ticker) { byte curr = 0xFF; long closest = ticker + 1000000, next = 0; - for (int i = 0; i < _pTrack->nChannels; i++) { - if (_pTrack->aChannels[i].time == -1) // channel ended + for (int i = 0; i < _track->channelCount; i++) { + if (_track->channels[i].time == -1) // channel ended continue; - next = *_pTrack->aChannels[i].ptr; // when the next event shoudl occur + next = *_track->channels[i].data; // when the next event shoudl occur if (next == 0xF8) // 0xF8 means 240 ticks delay next = 240; - next += _pTrack->aChannels[i].time; + next += _track->channels[i].time; if (next < closest) { curr = i; closest = next; @@ -646,79 +646,80 @@ byte MidiParser_SCI::midiGetNextChannel(long ticker) { } //---------------------------------------- byte *MidiParser_SCI::midiMixChannels() { - int lSize = 0; - byte **pDataPtr = new byte *[_pTrack->nChannels]; - for (int i = 0; i < _pTrack->nChannels; i++) { - pDataPtr[i] = _pTrack->aChannels[i].ptr; - _pTrack->aChannels[i].time = 0; - _pTrack->aChannels[i].prev = 0; - lSize += _pTrack->aChannels[i].size; + int totalSize = 0; + byte **dataPtr = new byte *[_track->channelCount]; + + for (int i = 0; i < _track->channelCount; i++) { + dataPtr[i] = _track->channels[i].data; + _track->channels[i].time = 0; + _track->channels[i].prev = 0; + totalSize += _track->channels[i].size; } - byte *pOutData = new byte[lSize * 2]; // FIXME: creates overhead and still may be not enough to hold all data - _pMidiData = pOutData; + byte *mixedData = new byte[totalSize * 2]; // FIXME: creates overhead and still may be not enough to hold all data + _mixedData = mixedData; long ticker = 0; byte curr, delta; byte cmd, par1, global_prev = 0; long new_delta; - SoundResource::tagChannel *pCh; + SoundResource::Channel *channel; while ((curr = midiGetNextChannel(ticker)) != 0xFF) { // there is still active channel - pCh = &_pTrack->aChannels[curr]; - delta = *pCh->ptr++; - pCh->time += (delta == 0xF8 ? 240 : delta); // when the comamnd is supposed to occur + channel = &_track->channels[curr]; + delta = *channel->data++; + channel->time += (delta == 0xF8 ? 240 : delta); // when the comamnd is supposed to occur if (delta == 0xF8) continue; - new_delta = pCh->time - ticker; + new_delta = channel->time - ticker; ticker += new_delta; - cmd = *pCh->ptr++; + cmd = *channel->data++; if (cmd != 0xFC) { // output new delta while (new_delta > 240) { - *pOutData++ = 0xF8; + *mixedData++ = 0xF8; new_delta -= 240; } - *pOutData++ = (byte)new_delta; + *mixedData++ = (byte)new_delta; } switch (cmd) { case 0xF0: // sysEx - *pOutData++ = cmd; + *mixedData++ = cmd; do { - par1 = *pCh->ptr++; - *pOutData++ = par1; // out + par1 = *channel->data++; + *mixedData++ = par1; // out } while (par1 != 0xF7); break; case 0xFC: // end channel - pCh->time = -1; // FIXME + channel->time = -1; // FIXME break; default: // MIDI command if (cmd & 0x80) - par1 = *pCh->ptr++; + par1 = *channel->data++; else {// running status par1 = cmd; - cmd = pCh->prev; + cmd = channel->prev; } if (cmd != global_prev) - *pOutData++ = cmd; // out cmd - *pOutData++ = par1;// pout par1 + *mixedData++ = cmd; // out cmd + *mixedData++ = par1;// pout par1 if (nMidiParams[(cmd >> 4) - 8] == 2) - *pOutData++ = *pCh->ptr++; // out par2 - pCh->prev = cmd; + *mixedData++ = *channel->data++; // out par2 + channel->prev = cmd; global_prev = cmd; }// switch(cmd) }// while (curr) // mixing finished. inserting stop event - *pOutData++ = 0; - *pOutData++ = 0xFF; - *pOutData++ = 0x2F; - *pOutData++ = 0x00; - *pOutData++ = 0x00; + *mixedData++ = 0; + *mixedData++ = 0xFF; + *mixedData++ = 0x2F; + *mixedData++ = 0x00; + *mixedData++ = 0x00; - for (int i = 0; i < _pTrack->nChannels; i++) - _pTrack->aChannels[i].ptr = pDataPtr[i]; + for (int channelNr = 0; channelNr < _track->channelCount; channelNr++) + _track->channels[channelNr].data = dataPtr[channelNr]; - delete[] pDataPtr; - return _pMidiData; + delete[] dataPtr; + return _mixedData; } void MidiParser_SCI::setVolume(byte bVolume) { @@ -728,9 +729,9 @@ void MidiParser_SCI::setVolume(byte bVolume) { _volume = bVolume; // sending volume change to all active channels - for (int i = 0; i < _pTrack->nChannels; i++) - if (_pTrack->aChannels[i].number <= 0xF) - _driver->send(0xB0 + _pTrack->aChannels[i].number, 7, _volume); + for (int i = 0; i < _track->channelCount; i++) + if (_track->channels[i].number <= 0xF) + _driver->send(0xB0 + _track->channels[i].number, 7, _volume); } } } // end of namespace SCI diff --git a/engines/sci/sfx/music.h b/engines/sci/sfx/music.h index 5fc6ea8325..91ca0626f2 100644 --- a/engines/sci/sfx/music.h +++ b/engines/sci/sfx/music.h @@ -160,7 +160,7 @@ class MidiParser_SCI : public MidiParser { public: MidiParser_SCI(); ~MidiParser_SCI(); - bool loadMusic(SoundResource::tagTrack *ptrack, MusicEntry *psnd); + bool loadMusic(SoundResource::Track *track, MusicEntry *psnd); bool loadMusic(byte *, uint32) { return false; } @@ -177,8 +177,8 @@ protected: void parseNextEvent(EventInfo &info); byte *midiMixChannels(); byte midiGetNextChannel(long ticker); - byte *_pMidiData; - SoundResource::tagTrack *_pTrack; + byte *_mixedData; + SoundResource::Track *_track; MusicEntry *_pSnd; uint32 _loopTick; byte _volume; diff --git a/engines/sci/sfx/soundcmd.cpp b/engines/sci/sfx/soundcmd.cpp index 98d4b53f74..2a153e6076 100644 --- a/engines/sci/sfx/soundcmd.cpp +++ b/engines/sci/sfx/soundcmd.cpp @@ -288,7 +288,7 @@ void SoundCommandParser::cmdInitHandle(reg_t obj, int16 value) { newSound->soundRes = 0; newSound->resnum = number; if (number && _resMan->testResource(ResourceId(kResourceTypeSound, number))) - newSound->soundRes = new SoundResource(number, _resMan); + newSound->soundRes = new SoundResource(number, _resMan, _doSoundVersion); newSound->soundObj = obj; newSound->loop = GET_SEL32V(_segMan, obj, loop) == 0xFFFF ? 1 : 0; newSound->prio = GET_SEL32V(_segMan, obj, pri) & 0xFF; |