diff options
author | Johannes Schickel | 2008-11-30 01:53:32 +0000 |
---|---|---|
committer | Johannes Schickel | 2008-11-30 01:53:32 +0000 |
commit | 893a79b01dd02ebc7475b7cdd0f5ec154229f51c (patch) | |
tree | 4e5888179f175d8660eab8c9828c25703affb2e2 /engines/kyra/sound.cpp | |
parent | fead4f304f2034de410564e113cef20563018d26 (diff) | |
download | scummvm-rg350-893a79b01dd02ebc7475b7cdd0f5ec154229f51c.tar.gz scummvm-rg350-893a79b01dd02ebc7475b7cdd0f5ec154229f51c.tar.bz2 scummvm-rg350-893a79b01dd02ebc7475b7cdd0f5ec154229f51c.zip |
Initial version of proper MIDI support for KYRA.
svn-id: r35174
Diffstat (limited to 'engines/kyra/sound.cpp')
-rw-r--r-- | engines/kyra/sound.cpp | 319 |
1 files changed, 0 insertions, 319 deletions
diff --git a/engines/kyra/sound.cpp b/engines/kyra/sound.cpp index 073639e4ca..63a97185c8 100644 --- a/engines/kyra/sound.cpp +++ b/engines/kyra/sound.cpp @@ -159,325 +159,6 @@ uint32 Sound::voicePlayedTime(const char *file) { #pragma mark - -SoundMidiPC::SoundMidiPC(KyraEngine_v1 *vm, Audio::Mixer *mixer, MidiDriver *driver) : Sound(vm, mixer) { - _driver = driver; - _passThrough = false; - - _musicParser = _sfxParser = 0; - _isMusicPlaying = _isSfxPlaying = false; - _eventFromMusic = false; - - _nativeMT32 = _useC55 = false; - - _fadeStartTime = 0; - _fadeMusicOut = false; - - memset(_channel, 0, sizeof(_channel)); - memset(_channelVolume, 50, sizeof(_channelVolume)); - _channelVolume[10] = 100; - for (int i = 0; i < 16; ++i) - _virChannel[i] = i; - - int ret = open(); - if (ret != MERR_ALREADY_OPEN && ret != 0) - error("Couldn't open midi driver"); -} - -SoundMidiPC::~SoundMidiPC() { - Common::StackLock lock(_mutex); - - delete _musicParser; - delete _sfxParser; - - _driver->setTimerCallback(0, 0); - close(); -} - -bool SoundMidiPC::init() { - _musicParser = MidiParser::createParser_XMIDI(); - _sfxParser = MidiParser::createParser_XMIDI(); - - if (!_musicParser || !_sfxParser) - return false; - - _musicParser->setMidiDriver(this); - _sfxParser->setMidiDriver(this); - - return true; -} - -void SoundMidiPC::updateVolumeSettings() { - _musicVolume = CLIP(ConfMan.getInt("music_volume"), 0, 255); - _sfxVolume = CLIP(ConfMan.getInt("sfx_volume"), 0, 255); - - updateChannelVolume(_musicVolume); -} - -void SoundMidiPC::hasNativeMT32(bool nativeMT32) { - _nativeMT32 = nativeMT32; - - // C55 appears to be XMIDI for General MIDI instruments - if (!_nativeMT32 && _vm->game() == GI_KYRA2) - _useC55 = true; - else - _useC55 = false; -} - -void SoundMidiPC::updateChannelVolume(uint8 volume) { - for (int i = 0; i < 32; ++i) { - if (_channel[i]) { - if (i >= 16) - _channel[i]->volume(_channelVolume[i - 16] * volume / 255); - else - _channel[i]->volume(_channelVolume[i] * volume / 255); - } - } -} - -int SoundMidiPC::open() { - // Don't ever call open without first setting the output driver! - if (!_driver) - return 255; - - int ret = _driver->open(); - if (ret) - return ret; - - _driver->setTimerCallback(this, &onTimer); - return 0; -} - -void SoundMidiPC::close() { - if (_driver) { - _driver->close(); - delete _driver; - } - _driver = 0; -} - -void SoundMidiPC::send(uint32 b) { - if (_passThrough) { - if ((b & 0xFFF0) == 0x007BB0) - return; - _driver->send(b); - return; - } - - const int volume = /*_eventFromMusic ? */_musicVolume/* : _sfxVolume*/; - - uint8 channel = (byte)(b & 0x0F); - if (((b & 0xFFF0) == 0x6FB0 || (b & 0xFFF0) == 0x6EB0) && channel != 9) { - if (_virChannel[channel] == channel) { - _virChannel[channel] = channel + 16; - if (!_channel[_virChannel[channel]]) - _channel[_virChannel[channel]] = _driver->allocateChannel(); - if (_channel[_virChannel[channel]]) - _channel[_virChannel[channel]]->volume(_channelVolume[channel] * volume / 255); - } - return; - } - - if ((b & 0xFFF0) == 0x07B0) { - // Adjust volume changes by master volume - uint8 vol = (uint8)((b >> 16) & 0x7F); - _channelVolume[channel] = vol; - vol = vol * volume / 255; - b = (b & 0xFF00FFFF) | (vol << 16); - } else if ((b & 0xF0) == 0xC0 && !_nativeMT32 && !_useC55) { - b = (b & 0xFFFF00FF) | (MidiDriver::_mt32ToGm[(b >> 8) & 0xFF] << 8); - } else if ((b & 0xFFF0) == 0x007BB0) { - //Only respond to All Notes Off if this channel - //has currently been allocated - if (!_channel[/*_virChannel[channel]*/channel]) - return; - } - - if (!_channel[_virChannel[channel]]) { - _channel[_virChannel[channel]] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel(); - if (_channel[_virChannel[channel]]) - _channel[_virChannel[channel]]->volume(_channelVolume[channel] * volume / 255); - } - if (_channel[_virChannel[channel]]) - _channel[_virChannel[channel]]->send(b); -} - -void SoundMidiPC::metaEvent(byte type, byte *data, uint16 length) { - switch (type) { - case 0x2F: // End of Track - if (_eventFromMusic) { - // remap all channels - for (int i = 0; i < 16; ++i) - _virChannel[i] = i; - } else { - _isSfxPlaying = false; - } - break; - default: - _driver->metaEvent(type, data, length); - break; - } -} - - -struct DeleterArray { - void operator ()(byte *ptr) { - delete[] ptr; - } -}; - -void SoundMidiPC::loadSoundFile(uint file) { - Common::StackLock lock(_mutex); - - internalLoadFile(fileListEntry(file)); -} - -void SoundMidiPC::loadSoundFile(Common::String file) { - Common::StackLock lock(_mutex); - - internalLoadFile(file); -} - -void SoundMidiPC::internalLoadFile(Common::String file) { - Common::String filename = file; - filename += "."; - filename += _useC55 ? "C55" : "XMI"; - - if (filename == _currentTrack) { - _isMusicPlaying = _isSfxPlaying = false; - _fadeStartTime = 0; - _fadeMusicOut = false; - updateChannelVolume(_musicVolume); - _musicParser->setTempo(0); - _sfxParser->setTempo(0); - _musicParser->property(MidiParser::mpAutoLoop, false); - _sfxParser->property(MidiParser::mpAutoLoop, false); - return; - } - - uint32 size; - uint8 *data = (_vm->resource())->fileData(filename.c_str(), &size); - - if (!data) { - warning("Couldn't load soundfile '%s'", filename.c_str()); - return; - } - - _currentTrack = filename; - - _musicParser->unloadMusic(); - _sfxParser->unloadMusic(); - _midiFile = Common::SharedPtr<byte>(data, DeleterArray()); - - _isMusicPlaying = _isSfxPlaying = false; - _fadeStartTime = 0; - _fadeMusicOut = false; - updateChannelVolume(_musicVolume); - - if (_musicParser->loadMusic(_midiFile.get(), size)) { - _musicParser->setTimerRate(getBaseTempo()); - _musicParser->setTempo(0); - _musicParser->property(MidiParser::mpAutoLoop, false); - } else { - warning("Error parsing music track '%s'", filename.c_str()); - } - - if (_sfxParser->loadMusic(_midiFile.get(), size)) { - _sfxParser->setTimerRate(getBaseTempo()); - _sfxParser->setTempo(0); - _sfxParser->property(MidiParser::mpAutoLoop, false); - } else { - warning("Error parsing sfx track '%s'", filename.c_str()); - } -} - -void SoundMidiPC::onTimer(void *refCon) { - SoundMidiPC *sound = (SoundMidiPC *)refCon; - Common::StackLock lock(sound->_mutex); - - // this should be set to the fadeToBlack value - static const uint32 musicFadeTime = 1 * 1000; - - if (sound->_fadeMusicOut) { - if (sound->_fadeStartTime + musicFadeTime > sound->_vm->_system->getMillis()) { - byte volume = (byte)((musicFadeTime - (sound->_vm->_system->getMillis() - sound->_fadeStartTime)) * sound->_musicVolume / musicFadeTime); - sound->updateChannelVolume(volume); - } else { - sound->_fadeStartTime = 0; - sound->_fadeMusicOut = false; - sound->_isMusicPlaying = false; - - sound->_eventFromMusic = true; - // from sound/midiparser.cpp - for (int i = 0; i < 128; ++i) { - for (int j = 0; j < 16; ++j) { - sound->send(0x80 | j | i << 8); - } - } - - for (int i = 0; i < 16; ++i) - sound->send(0x007BB0 | i); - } - } - - if (sound->_isMusicPlaying) { - sound->_eventFromMusic = true; - sound->_musicParser->onTimer(); - } - - if (sound->_isSfxPlaying) { - sound->_eventFromMusic = false; - sound->_sfxParser->onTimer(); - } -} - -void SoundMidiPC::playTrack(uint8 track) { - Common::StackLock lock(_mutex); - - if (_musicParser && (track != 0 || _nativeMT32) && _musicEnabled) { - _isMusicPlaying = true; - _fadeMusicOut = false; - _fadeStartTime = 0; - updateChannelVolume(_musicVolume); - _musicParser->setTrack(track); - _musicParser->jumpToTick(0); - _musicParser->setTempo(1); - _musicParser->property(MidiParser::mpAutoLoop, false); - } -} - -void SoundMidiPC::haltTrack() { - Common::StackLock lock(_mutex); - - if (_musicParser) { - _isMusicPlaying = false; - _fadeMusicOut = false; - _fadeStartTime = 0; - updateChannelVolume(_musicVolume); - _musicParser->setTrack(0); - _musicParser->jumpToTick(0); - _musicParser->setTempo(0); - } -} - -void SoundMidiPC::playSoundEffect(uint8 track) { - Common::StackLock lock(_mutex); - - if (_sfxParser && _sfxEnabled) { - _isSfxPlaying = true; - _sfxParser->setTrack(track); - _sfxParser->jumpToTick(0); - _sfxParser->setTempo(1); - _sfxParser->property(MidiParser::mpAutoLoop, false); - } -} - -void SoundMidiPC::beginFadeOut() { - _fadeMusicOut = true; - _fadeStartTime = _vm->_system->getMillis(); -} - -#pragma mark - - void KyraEngine_v1::snd_playTheme(int file, int track) { debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine_v1::snd_playTheme(%d, %d)", file, track); if (_curMusicTheme == file) |