diff options
Diffstat (limited to 'engines/sci/sfx/music.cpp')
-rw-r--r-- | engines/sci/sfx/music.cpp | 573 |
1 files changed, 0 insertions, 573 deletions
diff --git a/engines/sci/sfx/music.cpp b/engines/sci/sfx/music.cpp deleted file mode 100644 index 30721f0531..0000000000 --- a/engines/sci/sfx/music.cpp +++ /dev/null @@ -1,573 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -#include "sound/audiostream.h" -#include "common/config-manager.h" - -#include "sci/sci.h" -#include "sci/console.h" -#include "sci/resource.h" -#include "sci/engine/kernel.h" -#include "sci/engine/state.h" -#include "sci/sfx/midiparser.h" -#include "sci/sfx/music.h" -#include "sci/sfx/softseq/pcjr.h" - -namespace Sci { - -SciMusic::SciMusic(SciVersion soundVersion) - : _soundVersion(soundVersion), _soundOn(true) { - - // Reserve some space in the playlist, to avoid expensive insertion - // operations - _playList.reserve(10); -} - -SciMusic::~SciMusic() { - if (_pMidiDrv) { - _pMidiDrv->close(); - delete _pMidiDrv; - } -} - -void SciMusic::init() { - // system init - _pMixer = g_system->getMixer(); - _pMixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt( - "sfx_volume")); - _pMixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, - ConfMan.getInt("speech_volume")); - _pMixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, - ConfMan.getInt("music_volume")); - // SCI sound init - _dwTempo = 0; - - const MidiDriverDescription *md = MidiDriver::findMusicDriver(ConfMan.get("music_driver")); - _midiType = md ? md->id : MD_AUTO; - - switch (_midiType) { - case MD_ADLIB: - // FIXME: There's no Amiga sound option, so we hook it up to Adlib - if (((SciEngine *)g_engine)->getPlatform() == Common::kPlatformAmiga) - _pMidiDrv = MidiPlayer_Amiga_create(); - else - _pMidiDrv = MidiPlayer_Adlib_create(); - break; - case MD_PCJR: - _pMidiDrv = new MidiPlayer_PCJr(); - break; - case MD_PCSPK: - _pMidiDrv = new MidiPlayer_PCSpeaker(); - break; - case MD_MT32: - // TODO - default: - warning("Unhandled MIDI type, switching to Adlib"); - _midiType = MD_ADLIB; - _pMidiDrv = MidiPlayer_Adlib_create(); - break; - } - - if (_pMidiDrv) { - _pMidiDrv->open(); - _pMidiDrv->setTimerCallback(this, &miditimerCallback); - _dwTempo = _pMidiDrv->getBaseTempo(); - } else - warning("Can't initialise music driver"); - _bMultiMidi = ConfMan.getBool("multi_midi"); -} - -void SciMusic::clearPlayList() { - _pMixer->stopAll(); - - _mutex.lock(); - while (!_playList.empty()) { - soundStop(_playList[0]); - soundKill(_playList[0]); - } - _mutex.unlock(); -} - -void SciMusic::miditimerCallback(void *p) { - SciMusic *aud = (SciMusic *)p; - - Common::StackLock lock(aud->_mutex); - aud->onTimer(); -} - -void SciMusic::soundSetSoundOn(bool soundOnFlag) { - Common::StackLock lock(_mutex); - - _soundOn = soundOnFlag; - _pMidiDrv->playSwitch(soundOnFlag); -} - -uint16 SciMusic::soundGetVoices() { - Common::StackLock lock(_mutex); - - return _pMidiDrv->getPolyphony(); -} - -MusicEntry *SciMusic::getSlot(reg_t obj) { - Common::StackLock lock(_mutex); - - const MusicList::iterator end = _playList.end(); - for (MusicList::iterator i = _playList.begin(); i != end; ++i) { - if ((*i)->soundObj == obj) - return *i; - } - - return NULL; -} - -void SciMusic::setReverb(byte reverb) { - _reverb = reverb; - - // TODO: actually set reverb for MT-32 - - // A good test case for this are the first two rooms in Longbow: - // reverb is set for the first room (the cave) and is subsequently - // cleared when Robin exits the cave -} - -void SciMusic::resetDriver() { - Common::StackLock lock(_mutex); - - _pMidiDrv->close(); - _pMidiDrv->open(); - _pMidiDrv->setTimerCallback(this, &miditimerCallback); -} - -static int f_compare(const void *arg1, const void *arg2) { - return ((const MusicEntry *)arg2)->prio - ((const MusicEntry *)arg1)->prio; -} - -void SciMusic::sortPlayList() { - MusicEntry ** pData = _playList.begin(); - qsort(pData, _playList.size(), sizeof(MusicEntry *), &f_compare); -} - -#if 0 -void SciMusic::patchSysEx(byte * addr, byte *pdata, int len) { - byte *buff = new byte[7 + len + 1]; - uint16 chk = 0; - int i; - - buff[0] = 0x41; - buff[1] = 0x10; - buff[2] = 0x16; - buff[3] = 0x12; - buff[4] = addr[0]; - buff[5] = addr[1]; - buff[6] = addr[2]; - for (i = 0; i < len; i++) { - buff[7 + i] = pdata[i]; - chk += pdata[i]; - } - chk += addr[0] + addr[1] + addr[2]; - buff[7 + i] = 128 - chk % 128; - _pMidiDrv->sysEx(buff, len + 8); - delete[] buff; -} - -void SciMusic::patchUpdateAddr(byte *addr, int len) { - addr[2] += len; - if (addr[2] >= 0x7F) { - addr[1]++; - addr[2] -= 0x80; - } -} -#endif - -// FIXME: This should be done at the driver level -#if 0 -void SciMusic::loadPatch() { - if (_midiType == MD_MT32) - loadPatchMT32(); -} -#endif - -#if 0 -// currently loads patch 1.pat for Roland/MT-32 device -void SciMusic::loadPatchMT32() { - //byte sysText[] = { 0x20, 0, 0 }; - byte sysMem[] = { 0x5, 0, 0 }; // patch memory - byte sysRhytm[] = { 0x3, 0x1, 0x10 }; // rhytm - byte sysMsg3[15] = { 0x41, 0x10, 0x16, 0x12, 0x52, 0, 0xA, 0x16, 0x16, - 0x16, 0x16, 0x16, 0x16, 0x20, 0x80 }; - byte sysTimbre[] = { 0x8, 0, 0 }; // timbre memory - byte sysSystem[] = { 0x10, 0, 4 }; // partial reserve & midi channel - byte arr[3][11]; - - Resource *res = ((SciEngine *)g_engine)->getResourceManager()->findResource(ResourceId(kResourceTypePatch, 1), 0); - - if (res) { - byte *pData = res->data, *p; - // welcome message - //patchSysEx(sysText, pData + 20, 20); - // reading reverb mode, time and level - p = pData + 74; - for (int i = 0; i < 11; i++) { - arr[0][i] = *p++; - arr[1][i] = *p++; - arr[2][i] = *p++; - } - // sub_657 - patch memory - for (int i = 0; i < 48; i++) { - patchSysEx(sysMem, p, 8); - patchUpdateAddr(sysMem, 8); - p += 8; - } - // sub_696 - timbre - byte dl = *p++, cl = 0; - while (dl--) { - patchSysEx(sysTimbre, p, 14); // common area - patchUpdateAddr(sysTimbre, 14); - patchSysEx(sysTimbre, p + 14, 58);// partial 1 - patchUpdateAddr(sysTimbre, 58); - patchSysEx(sysTimbre, p + 72, 58);// partial 2 - patchUpdateAddr(sysTimbre, 58); - patchSysEx(sysTimbre, p + 130, 58);// partial 3 - patchUpdateAddr(sysTimbre, 58); - patchSysEx(sysTimbre, p + 188, 58);// partial 4 - patchUpdateAddr(sysTimbre, 58); - p += 246; - cl += 2; - sysTimbre[1] = cl; - sysTimbre[2] = 0; - } - // patch memory or rhytm - uint16 flag = READ_BE_UINT16(p); - p += 2; - if (flag == 0xABCD) { - // sub_657 - for (int i = 0; i < 48; i++) { - patchSysEx(sysMem, p, 8); - patchUpdateAddr(sysMem, 8); - p += 8; - } - } else if (flag == 0xDCBA) { - // sub_756 - for (int i = 0; i < 64; i++) { - patchSysEx(sysRhytm, p, 4); - patchUpdateAddr(sysRhytm, 4); - p += 4; - } - patchSysEx(sysSystem, p, 18); - } - // after-init text message - //patchSysEx(sysText, pData, 20); - // some final sysex - _pMidiDrv->sysEx(sysMsg3, 15); - // releasing patch resource - //g_sci->ResMgr.ResUnload(SCI_RES_PATCH, 1); - debug("MT-32 patch loaded"); - } -} -#endif - - -void SciMusic::soundInitSnd(MusicEntry *pSnd) { - SoundResource::Track *track = NULL; - int channelFilterMask = 0; - - switch (_midiType) { - case MD_PCSPK: - track = pSnd->soundRes->getTrackByType(SoundResource::TRACKTYPE_SPEAKER); - break; - case MD_PCJR: - track = pSnd->soundRes->getTrackByType(SoundResource::TRACKTYPE_TANDY); - break; - case MD_ADLIB: - track = pSnd->soundRes->getTrackByType(SoundResource::TRACKTYPE_ADLIB); - break; - case MD_MT32: - track = pSnd->soundRes->getTrackByType(SoundResource::TRACKTYPE_MT32); - break; - default: - // Should never occur - error("soundInitSnd: Unknown MIDI type"); - break; - } - - 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 (_bMultiMidi && pSnd->soundRes->getTrackByType(SoundResource::TRACKTYPE_ADLIB)->digitalChannelNr != -1) - track = pSnd->soundRes->getTrackByType(SoundResource::TRACKTYPE_ADLIB); - // Play digital sample - if (track->digitalChannelNr != -1) { - byte *channelData = track->channels[track->digitalChannelNr].data; - delete pSnd->pStreamAud; - pSnd->pStreamAud = Audio::makeLinearInputStream(channelData, track->digitalSampleSize, track->digitalSampleRate, - Audio::Mixer::FLAG_UNSIGNED, 0, 0); - pSnd->soundType = Audio::Mixer::kSFXSoundType; - pSnd->hCurrentAud = Audio::SoundHandle(); - } else { - // play MIDI track - _mutex.lock(); - pSnd->soundType = Audio::Mixer::kMusicSoundType; - if (pSnd->pMidiParser == NULL) { - pSnd->pMidiParser = new MidiParser_SCI(_soundVersion); - pSnd->pMidiParser->setMidiDriver(_pMidiDrv); - pSnd->pMidiParser->setTimerRate(_dwTempo); - pSnd->pMidiParser->property(MidiParser::mpCenterPitchWheelOnUnload, 1); - } - - pSnd->pauseCounter = 0; - - // Find out what channels to filter for SCI0 - channelFilterMask = pSnd->soundRes->getChannelFilterMask(_pMidiDrv->getPlayMask(_soundVersion)); - pSnd->pMidiParser->loadMusic(track, pSnd, channelFilterMask, _soundVersion); - - // Fast forward to the last position and perform associated events when loading - pSnd->pMidiParser->jumpToTick(pSnd->ticker, true); - _mutex.unlock(); - } - } -} - -void SciMusic::onTimer() { - const MusicList::iterator end = _playList.end(); - for (MusicList::iterator i = _playList.begin(); i != end; ++i) - (*i)->onTimer(); -} - -void SciMusic::soundPlay(MusicEntry *pSnd) { - _mutex.lock(); - - uint sz = _playList.size(), i; - // searching if sound is already in _playList - for (i = 0; i < sz && _playList[i] != pSnd; i++) - ; - if (i == sz) {// not found - _playList.push_back(pSnd); - sortPlayList(); - } - - _mutex.unlock(); // unlock to perform mixer-related calls - - if (pSnd->pStreamAud && !_pMixer->isSoundHandleActive(pSnd->hCurrentAud)) { - // Are we supposed to loop the stream? - if (pSnd->loop > 1) - pSnd->pStreamAud->setNumLoops(pSnd->loop); - else - pSnd->pStreamAud->setNumLoops(1); - _pMixer->playInputStream(pSnd->soundType, &pSnd->hCurrentAud, - pSnd->pStreamAud, -1, pSnd->volume, 0, false); - } else { - _mutex.lock(); - if (pSnd->pMidiParser) { - pSnd->pMidiParser->setVolume(pSnd->volume); - if (pSnd->status == kSoundStopped) - pSnd->pMidiParser->jumpToTick(0); - } - _mutex.unlock(); - } - - pSnd->status = kSoundPlaying; -} - -void SciMusic::soundStop(MusicEntry *pSnd) { - pSnd->status = kSoundStopped; - if (pSnd->pStreamAud) - _pMixer->stopHandle(pSnd->hCurrentAud); - - _mutex.lock(); - if (pSnd->pMidiParser) - pSnd->pMidiParser->stop(); - _mutex.unlock(); -} - -void SciMusic::soundSetVolume(MusicEntry *pSnd, byte volume) { - assert(volume <= MUSIC_VOLUME_MAX); - if (pSnd->pStreamAud) { - _pMixer->setChannelVolume(pSnd->hCurrentAud, volume * 2); // Mixer is 0-255, SCI is 0-127 - } else if (pSnd->pMidiParser) { - _mutex.lock(); - pSnd->pMidiParser->setVolume(volume); - _mutex.unlock(); - } -} - -void SciMusic::soundSetPriority(MusicEntry *pSnd, byte prio) { - Common::StackLock lock(_mutex); - - pSnd->prio = prio; - sortPlayList(); -} - -void SciMusic::soundKill(MusicEntry *pSnd) { - pSnd->status = kSoundStopped; - - _mutex.lock(); - if (pSnd->pMidiParser) { - pSnd->pMidiParser->unloadMusic(); - delete pSnd->pMidiParser; - pSnd->pMidiParser = NULL; - } - _mutex.unlock(); - - if (pSnd->pStreamAud) { - _pMixer->stopHandle(pSnd->hCurrentAud); - pSnd->pStreamAud = NULL; - } - - _mutex.lock(); - uint sz = _playList.size(), i; - // Remove sound from playlist - for (i = 0; i < sz; i++) { - if (_playList[i] == pSnd) { - delete _playList[i]->soundRes; - delete _playList[i]; - _playList.remove_at(i); - break; - } - } - _mutex.unlock(); -} - -void SciMusic::soundPause(MusicEntry *pSnd) { - pSnd->pauseCounter++; - if (pSnd->status != kSoundPlaying) - return; - pSnd->status = kSoundPaused; - if (pSnd->pStreamAud) { - _pMixer->pauseHandle(pSnd->hCurrentAud, true); - } else { - _mutex.lock(); - if (pSnd->pMidiParser) - pSnd->pMidiParser->pause(); - _mutex.unlock(); - } -} - -void SciMusic::soundResume(MusicEntry *pSnd) { - if (pSnd->pauseCounter > 0) - pSnd->pauseCounter--; - if (pSnd->pauseCounter != 0) - return; - if (pSnd->status != kSoundPaused) - return; - soundPlay(pSnd); -} - -uint16 SciMusic::soundGetMasterVolume() { - return (_pMixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType) + 8) * 0xF / Audio::Mixer::kMaxMixerVolume; -} - -void SciMusic::soundSetMasterVolume(uint16 vol) { - vol = vol & 0xF; // 0..15 - vol = vol * Audio::Mixer::kMaxMixerVolume / 0xF; - // "master volume" is music and SFX only, speech (audio resources) are supposed to be unaffected - _pMixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, vol); - _pMixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, vol); -} - -void SciMusic::printPlayList(Console *con) { - Common::StackLock lock(_mutex); - - const char *musicStatus[] = { "Stopped", "Initialized", "Paused", "Playing" }; - - const MusicList::iterator end = _playList.end(); - for (MusicList::iterator i = _playList.begin(); i != end; ++i) { - con->DebugPrintf("%d: %04x:%04x, priority: %d, status: %s\n", i, - PRINT_REG((*i)->soundObj), (*i)->prio, - musicStatus[(*i)->status]); - } -} - -MusicEntry::MusicEntry() { - soundObj = NULL_REG; - - soundRes = 0; - resnum = 0; - - dataInc = 0; - ticker = 0; - signal = 0; - prio = 0; - loop = 0; - volume = MUSIC_VOLUME_DEFAULT; - hold = 0; - - pauseCounter = 0; - sampleLoopCounter = 0; - - fadeTo = 0; - fadeStep = 0; - fadeTicker = 0; - fadeTickerStep = 0; - fadeSetVolume = false; - fadeCompleted = false; - - status = kSoundStopped; - - soundType = Audio::Mixer::kMusicSoundType; - - pStreamAud = 0; - pMidiParser = 0; -} - -MusicEntry::~MusicEntry() { -} - -void MusicEntry::onTimer() { - if (status != kSoundPlaying) - return; - - // Fade MIDI and digital sound effects - if (fadeStep) - doFade(); - - // Only process MIDI streams in this thread, not digital sound effects - if (pMidiParser) { - pMidiParser->onTimer(); - ticker = (uint16)pMidiParser->getTick(); - } -} - -void MusicEntry::doFade() { - if (fadeTicker) - fadeTicker--; - else { - int16 fadeVolume = volume; - fadeTicker = fadeTickerStep; - fadeVolume += fadeStep; - if (((fadeStep > 0) && (fadeVolume >= fadeTo)) || ((fadeStep < 0) && (fadeVolume <= fadeTo))) { - fadeVolume = fadeTo; - fadeStep = 0; - fadeCompleted = true; - } - volume = fadeVolume; - - // Only process MIDI streams in this thread, not digital sound effects - if (pMidiParser) - pMidiParser->setVolume(volume); - fadeSetVolume = true; // set flag so that SoundCommandParser::cmdUpdateCues will set the volume of the stream - } -} - -} // End of namespace Sci |