diff options
author | Eugene Sandulenko | 2004-04-29 03:52:59 +0000 |
---|---|---|
committer | Eugene Sandulenko | 2004-04-29 03:52:59 +0000 |
commit | bb8ee598c9c71b7ee8b55819099274605a7b6224 (patch) | |
tree | f38a18647b41d2e276cafcf09340eaad76a2a6f0 /saga/music.cpp | |
parent | b03304c8707313f624e9280e8c0c345f117092c5 (diff) | |
download | scummvm-rg350-bb8ee598c9c71b7ee8b55819099274605a7b6224.tar.gz scummvm-rg350-bb8ee598c9c71b7ee8b55819099274605a7b6224.tar.bz2 scummvm-rg350-bb8ee598c9c71b7ee8b55819099274605a7b6224.zip |
Music.cpp objectizing.
Initial MIDI checkin, doesn't work
svn-id: r13670
Diffstat (limited to 'saga/music.cpp')
-rw-r--r-- | saga/music.cpp | 194 |
1 files changed, 158 insertions, 36 deletions
diff --git a/saga/music.cpp b/saga/music.cpp index 2c230679bf..f345cfb83b 100644 --- a/saga/music.cpp +++ b/saga/music.cpp @@ -20,78 +20,200 @@ * $Header$ * */ +#include "saga.h" #include "reinherit.h" #include "yslib.h" -namespace Saga { - -static int MusicInitialized = 0; +#include "music.h" +#include "rscfile_mod.h" +#include "game_mod.h" +#include "sound/mididrv.h" +#include "sound/midiparser.h" -int SYSMUSIC_Init(int enabled) -{ - YS_IGNORE_PARAM(enabled); +namespace Saga { - if (MusicInitialized) { - return R_FAILURE; +// Instrument mapping for MT32 tracks emulated under GM. +static const byte mt32_to_gm[128] = { +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 0, 2, 4, 4, 5, 3, 16, 17, 18, 16, 16, 19, 20, 21, // 0x + 6, 6, 6, 7, 7, 7, 8, 112, 62, 62, 63, 63, 38, 38, 39, 39, // 1x + 88, 95, 52, 98, 97, 99, 14, 54, 102, 96, 53, 102, 81, 100, 14, 80, // 2x + 48, 48, 49, 45, 41, 40, 42, 42, 43, 46, 45, 24, 25, 28, 27, 104, // 3x + 32, 32, 34, 33, 36, 37, 35, 35, 79, 73, 72, 72, 74, 75, 64, 65, // 4x + 66, 67, 71, 71, 68, 69, 70, 22, 56, 59, 57, 57, 60, 60, 58, 61, // 5x + 61, 11, 11, 98, 14, 9, 14, 13, 12, 107, 107, 77, 78, 78, 76, 76, // 6x + 47, 117, 127, 118, 118, 116, 115, 119, 115, 112, 55, 124, 123, 0, 14, 117 // 7x +}; + +MusicPlayer::MusicPlayer(MidiDriver *driver) : _driver(driver), _looping(false) { + this->open(); +} + +MusicPlayer::~MusicPlayer() { + _driver->setTimerCallback(NULL, NULL); + _parser->unloadMusic(); + this->close(); + } + +void MusicPlayer::setVolume(int volume) { + if (volume < 0) + volume = 0; + else if (volume > 255) + volume = 255; + + if (_masterVolume == volume) + return; + + _masterVolume = volume; + + for (int i = 0; i < 16; ++i) { + if (_channel[i]) + _channel[i]->volume(_channelVolume[i] * _masterVolume / 255); + } +} + +int MusicPlayer::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 MusicPlayer::close() { + stopMusic(); + if (_driver) + _driver->close(); + _driver = 0; +} + +void MusicPlayer::send(uint32 b) { + byte channel = (byte)(b & 0x0F); + if ((b & 0xFFF0) == 0x07B0) { + // Adjust volume changes by master volume + byte volume = (byte)((b >> 16) & 0x7F); + _channelVolume[channel] = volume; + volume = volume * _masterVolume / 255; + b = (b & 0xFF00FFFF) | (volume << 16); + } else if ((b & 0xF0) == 0xC0 && !_nativeMT32) { + b = (b & 0xFFFF00FF) | mt32_to_gm[(b >> 8) & 0xFF] << 8; + } + else if ((b & 0xFFF0) == 0x007BB0) { + //Only respond to All Notes Off if this channel + //has currently been allocated + if (_channel[b & 0x0F]) + return; } + + if (!_channel[channel]) + _channel[channel] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel(); - MusicInitialized = 1; - return R_SUCCESS; + if (_channel[channel]) + _channel[channel]->send(b); +} + +void MusicPlayer::metaEvent(byte type, byte *data, uint16 length) { + //Only thing we care about is End of Track. + if (type != 0x2F) + return; + + if (_looping) + _parser->jumpToTick(0); + else + stopMusic(); +} + +void MusicPlayer::onTimer(void *refCon) { + MusicPlayer *music = (MusicPlayer *)refCon; + if (music->_isPlaying) + music->_parser->onTimer(); +} + +void MusicPlayer::playMusic() { + _isPlaying = true; +} + +void MusicPlayer::stopMusic() { + _isPlaying = false; + _parser->unloadMusic(); } -int SYSMUSIC_Shutdown(void) -{ - if (!MusicInitialized) { - return R_FAILURE; - } - MusicInitialized = 0; - return R_SUCCESS; +Music::Music(MidiDriver *driver, int enabled) : _enabled(enabled) { + _player = new MusicPlayer(driver); + _musicInitialized = 1; } -int SYSMUSIC_Play(ulong music_rn, uint flags) -{ - if (!MusicInitialized) { +Music::~Music() { + delete _player; +} + +int Music::play(ulong music_rn, uint flags) { + R_RSCFILE_CONTEXT *rsc_ctxt = NULL; + + uchar *resource_data; + size_t resource_size; + + if (!_musicInitialized) { return R_FAILURE; } - YS_IGNORE_PARAM(music_rn); - YS_IGNORE_PARAM(flags); + if (!_enabled) { + return R_SUCCESS; + } + + /* Load XMI resource data */ + GAME_GetFileContext(&rsc_ctxt, R_GAME_RESOURCEFILE, 0); + + if (RSC_LoadResource(rsc_ctxt, music_rn, &resource_data, + &resource_size) != R_SUCCESS ) { + R_printf(R_STDERR, "SYSMUSIC_Play(): Resource load failed: %ld", + music_rn); + return R_FAILURE; + } + + MidiParser *parser = MidiParser::createParser_XMIDI(); + if (!parser->loadMusic(resource_data, resource_size)) { + warning("Error reading track!"); + delete parser; + parser = 0; + } - return R_SUCCESS; + debug(0, "Music::play(%d, %d)", music_rn, flags); + parser->setTrack(0); + _player->_parser = parser; + _player->playMusic(); + return R_SUCCESS; } -int SYSMUSIC_Pause(void) -{ - if (!MusicInitialized) { +int Music::pause(void) { + if (!_musicInitialized) { return R_FAILURE; } return R_SUCCESS; - } -int SYSMUSIC_Resume(void) -{ - if (!MusicInitialized) { +int Music::resume(void) { + if (!_musicInitialized) { return R_FAILURE; } return R_SUCCESS; - } -int SYSMUSIC_Stop(void) -{ - - if (!MusicInitialized) { +int Music::stop(void) { + if (!_musicInitialized) { return R_FAILURE; } return R_SUCCESS; - } } // End of namespace Saga |