Ticket #8460: kyra_sound_v1.patch

File kyra_sound_v1.patch, 13.4 KB (added by lordhoto, 15 years ago)

patch against todays cvs

  • kyra/kyra.cpp

    diff --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvm.cvs/kyra/kyra.cpp ./scummvm/kyra/kyra.cpp
    old new  
    155155        assert(_midi);
    156156        _midi->hasNativeMT32(native_mt32);
    157157        _midi->setVolume(255);
    158 
     158       
    159159        _res = new Resource(this);
    160160        assert(_res);
    161161        _screen = new Screen(this, _system);
     
    349349        _skipIntroFlag = true; // only true if user already played the game once
    350350        _seq_copyViewOffs = 1;
    351351       
    352 //      snd_kyraPlayTheme(0);
     352        snd_playTheme(kIntro, 2);
     353        snd_setSoundEffectFile(kIntro);
     354        debug("Done");
    353355        setTalkCoords(0x90);
    354356
    355357        memset(_screen->_palette1, 0, 768);
     
    781783                        }
    782784                        break;
    783785                case 24: { // sound related
    784                                 seqData++;
    785                                 warning("Sequence opcode 24 skipped");
     786                                uint8 param = *seqData++;
     787                                waitTicks(3);
     788                                snd_playSoundEffect(param);
    786789                        }
    787790                        break;
    788791                case 25: { // sound related
    789                                 seqData++;
    790                                 warning("Sequence opcode 25 skipped");
     792                                uint8 param = *seqData++;
     793                                snd_seqMessage(param);
    791794                        }
    792795                        break;
    793796                case 26:
  • kyra/kyra.h

    diff --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvm.cvs/kyra/kyra.h ./scummvm/kyra/kyra.h
    old new  
    6060class Screen;
    6161
    6262class KyraEngine : public Engine {
     63        friend class MusicPlayer;
    6364public:
    6465
    6566        KyraEngine(GameDetector *detector, OSystem *system);
     
    7475       
    7576        Common::RandomSource _rnd;
    7677
     78        enum {
     79                kIntro = 0,
     80                kKyraMisc = 11
     81        };
     82
    7783protected:
    7884
    7985        int go();
     
    108114        uint16 wsa_getNumFrames(WSAMovieV1 *wsa) const;
    109115        void wsa_play(WSAMovieV1 *wsa, int frameNum, int x, int y, int pageNum);
    110116        void wsa_processFrame(WSAMovieV1 *wsa, int frameNum, uint8 *dst);
     117
     118        void snd_playTheme(int file, int track = 0);
     119        void snd_playTrack(int track);
     120        void snd_startTrack();
     121        void snd_haltTrack();
     122        void snd_setSoundEffectFile(int file);
     123        void snd_playSoundEffect(int track);
     124        void snd_seqMessage(int msg);
    111125               
    112126        uint8 _game;
    113127        bool _fastMode;
  • kyra/sound.cpp

    diff --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvm.cvs/kyra/sound.cpp ./scummvm/kyra/sound.cpp
    old new  
    2222#include "common/stdafx.h"
    2323#include "kyra/resource.h"
    2424#include "kyra/sound.h"
     25#include "common/system.h"
    2526
    2627namespace Kyra {
    2728
     
    2930        _engine = engine;
    3031        _driver = driver;
    3132        _passThrough = false;
    32         _isPlaying = _nativeMT32 = false;
    33 
    34         memset(_channel, 0, sizeof(MidiChannel*) * 16);
    35         memset(_channelVolume, 255, sizeof(uint8) * 16);
     33        _eventFromMusic = false;
     34        _fadeMusicOut = _sfxIsPlaying = false;
     35        _isPlaying = _isLooping = _nativeMT32 = false;
     36        _soundEffect = _parser = 0;
     37
     38        memset(_channel, 0, sizeof(MidiChannel*) * 32);
     39        memset(_channelVolume, 50, sizeof(uint8) * 16);
     40        _channelVolume[10] = 100;
     41        for (int i = 0; i < 16; ++i) {
     42                _virChannel[i] = i;
     43        }
    3644        _volume = 0;
    3745
    3846        int ret = open();
     
    5664                return;
    5765
    5866        _volume = volume;
    59         for (int i = 0; i < 16; ++i) {
     67        for (int i = 0; i < 32; ++i) {
    6068                if (_channel[i]) {
    61                         _channel[i]->volume(_channelVolume[i] * _volume / 255);
     69                        if (i >= 16) {
     70                                _channel[i]->volume(_channelVolume[i - 16] * _volume / 255);
     71                        } else {
     72                                _channel[i]->volume(_channelVolume[i] * _volume / 255);
     73                        }
    6274                }
    6375        }
    6476}
     
    8496
    8597void MusicPlayer::send(uint32 b) {
    8698        if (_passThrough) {
     99                if ((b & 0xFFF0) == 0x007BB0)
     100                        return;
    87101                _driver->send(b);
    88102                return;
    89103        }
    90104
    91105        uint8 channel = (byte)(b & 0x0F);
     106        if (((b & 0xFFF0) == 0x6FB0 || (b & 0xFFF0) == 0x6EB0) && channel != 9) {
     107                if (_virChannel[channel] == channel) {
     108                        _virChannel[channel] = channel + 16;
     109                        if (!_channel[_virChannel[channel]])
     110                                _channel[_virChannel[channel]] = _driver->allocateChannel();
     111                        _channel[_virChannel[channel]]->volume(_channelVolume[channel] * _volume / 255);
     112                }
     113                return;
     114        }
     115
    92116        if ((b & 0xFFF0) == 0x07B0) {
    93117                // Adjust volume changes by master volume
    94118                uint8 volume = (uint8)((b >> 16) & 0x7F);
     
    104128                        return;
    105129        }
    106130
    107         if (!_channel[channel])
    108                 _channel[channel] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
    109         if (_channel[channel])
    110                 _channel[channel]->send(b);
     131        if (!_channel[_virChannel[channel]]) {
     132                _channel[_virChannel[channel]] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
     133                _channel[_virChannel[channel]]->volume(_channelVolume[channel] * _volume / 255);
     134        }
     135        if (_channel[_virChannel[channel]])
     136                _channel[_virChannel[channel]]->send(b);
    111137}
    112138
    113139void MusicPlayer::metaEvent(byte type, byte *data, uint16 length) {
    114140        switch (type) {
    115141        case 0x2F:      // End of Track
    116                 _parser->jumpToTick(0);
     142                if (_eventFromMusic) {
     143                        if (!_isLooping) {
     144                                _isPlaying = false;
     145                        }
     146
     147                        // remap all channels
     148                        for (int i = 0; i < 16; ++i) {
     149                                _virChannel[i] = i;
     150                        }
     151
     152                } else {
     153                        _sfxIsPlaying = false;
     154                }
    117155                break;
    118156        default:
    119                 warning("Unhandled meta event: 0x%02x", type);
     157                _driver->metaEvent(type, data, length);
    120158                break;
    121159        }
    122160}
     
    134172}
    135173
    136174void MusicPlayer::playMusic(uint8* data, uint32 size) {
    137         if (_isPlaying)
    138                 stopMusic();
     175        stopMusic();
    139176
    140177        _parser = MidiParser::createParser_XMIDI();
    141178        assert(_parser);
     
    150187        _parser->setTrack(0);
    151188        _parser->setMidiDriver(this);
    152189        _parser->setTimerRate(getBaseTempo());
     190        _parser->property(MidiParser::mpAutoLoop, false);
     191}
     192
     193void MusicPlayer::loadSoundEffectFile(const char* file) {
     194        uint32 size;
     195        uint8 *data = (_engine->resource())->fileData(file, &size);
     196
     197        if (!data) {
     198                warning("couldn't load '%s'", file);
     199                return;
     200        }
    153201
    154         _isPlaying = true;
     202        loadSoundEffectFile(data, size);
     203}
     204
     205void MusicPlayer::loadSoundEffectFile(uint8* data, uint32 size) {
     206        stopSoundEffect();
     207
     208        _soundEffect = MidiParser::createParser_XMIDI();
     209        assert(_soundEffect);
     210
     211        if (!_soundEffect->loadMusic(data, size)) {
     212                warning("Error reading track!");
     213                delete _parser;
     214                _parser = 0;
     215                return;
     216        }
     217
     218        _soundEffect->setTrack(0);
     219        _soundEffect->setMidiDriver(this);
     220        _soundEffect->setTimerRate(getBaseTempo());
     221        _soundEffect->property(MidiParser::mpAutoLoop, false);
    155222}
    156223
    157224void MusicPlayer::stopMusic() {
    158         _isPlaying = false;
     225        _isLooping = false;
    159226        if (_parser) {
    160227                _parser->unloadMusic();
    161228                delete _parser;
    162                 _parser = NULL;
     229                _parser = 0;
     230        }
     231}
     232
     233void MusicPlayer::stopSoundEffect() {
     234        if (_soundEffect) {
     235                _soundEffect->unloadMusic();
     236                delete _soundEffect;
     237                _soundEffect = 0;
    163238        }
    164239}
    165240
    166241void MusicPlayer::onTimer(void *refCon) {
    167242        MusicPlayer *music = (MusicPlayer *)refCon;
    168         if (music->_isPlaying)
    169                 music->_parser->onTimer();
     243
     244        // this should be set to the fadeToBlack value
     245        const static uint32 musicFadeTime = 2 * 1000;
     246        if (music->_fadeMusicOut && music->_fadeStartTime + musicFadeTime > music->_engine->_system->getMillis()) {
     247                byte volume = (byte)((musicFadeTime - (music->_engine->_system->getMillis() - music->_fadeStartTime)) * 255 / musicFadeTime);
     248                music->setVolume(volume);
     249        } else if(music->_fadeStartTime) {
     250                music->setVolume(255);
     251                music->_fadeStartTime = 0;
     252                music->_fadeMusicOut = false;
     253        }
     254
     255        if (music->_isPlaying) {
     256                if (music->_parser) {
     257                        music->_eventFromMusic = true;
     258                        music->_parser->onTimer();
     259                }
     260        }
     261
     262        if (music->_sfxIsPlaying) {
     263                if (music->_soundEffect) {
     264                        music->_eventFromMusic = false;
     265                        music->_soundEffect->onTimer();
     266                }
     267        }
    170268}
    171269
    172 void MusicPlayer::playTrack(uint8 track) {
     270void MusicPlayer::playTrack(uint8 track, bool loop) {
    173271        if (_parser) {
    174272                _isPlaying = true;
     273                _isLooping = loop;
    175274                _parser->setTrack(track);
    176275                _parser->jumpToTick(0);
     276                _parser->setTempo(1);
     277                _parser->property(MidiParser::mpAutoLoop, loop);
     278        }
     279}
     280
     281void MusicPlayer::playSoundEffect(uint8 track) {
     282        if (_soundEffect) {
     283                _sfxIsPlaying = true;
     284                _soundEffect->setTrack(track);
     285                _soundEffect->jumpToTick(0);
     286                _soundEffect->property(MidiParser::mpAutoLoop, false);
     287        }
     288}
     289
     290void MusicPlayer::beginFadeOut() {
     291        // this should be something like fade out...
     292        _fadeMusicOut = true;
     293        _fadeStartTime = _engine->_system->getMillis();
     294}
     295
     296void KyraEngine::snd_playTheme(int file, int track) {
     297        switch(file) {
     298                case kIntro:
     299                        debug(9, "Load music file 'INTRO.XMI'");
     300                        _midi->playMusic("INTRO.XMI");
     301                break;
     302
     303                default:
     304                        warning("Unkown music file: %d", file);
     305                        return;
     306                break;
     307        }
     308
     309        debug(9, "Playing track: %d", track);
     310        _midi->playTrack(track, false);
     311}
     312
     313void KyraEngine::snd_playTrack(int track) {
     314        debug(9, "Playing track: %d", track);
     315        _midi->playTrack(track, false);
     316}
     317
     318void KyraEngine::snd_setSoundEffectFile(int file) {
     319        switch(file) {
     320                case kIntro:
     321                        debug(3, "Load soundeffect file 'INTRO.XMI'");
     322                        _midi->loadSoundEffectFile("INTRO.XMI");
     323                break;
     324
     325                case kKyraMisc:
     326                        debug(3, "Load soundeffect file 'KYRAMISC.XMI'");
     327                        _midi->loadSoundEffectFile("KYRAMISC.XMI");
     328                break;
     329
     330                default:
     331                        warning("Unkown soundeffect file: %d", file);
     332                        return;
     333                break;
     334        }
     335}
     336
     337void KyraEngine::snd_playSoundEffect(int track) {
     338        debug(9, "Playing soundeffect: %d", track);
     339        _midi->playSoundEffect(track);
     340}
     341
     342void KyraEngine::snd_startTrack() {
     343        _midi->startTrack();
     344}
     345
     346void KyraEngine::snd_haltTrack() {
     347        _midi->haltTrack();
     348}
     349
     350void KyraEngine::snd_seqMessage(int msg) {
     351        debug(9, "snd_seqMessage(%.02d)", msg);
     352        switch(msg) {
     353                case 0:
     354                        warning("snd_seqMessage(0)");
     355                break;
     356
     357                case 1:
     358                        _midi->beginFadeOut();
     359                break;
     360
     361                case 56:
     362                        snd_playTheme(kIntro, 3);
     363                break;
     364
     365                case 57:
     366                        snd_playTheme(kIntro, 4);
     367                break;
     368
     369                case 58:
     370                        snd_playTheme(kIntro, 5);
     371                break;
     372
     373                default:
     374                        warning("Unknown seq. message: %.02d", msg);
     375                break;
    177376        }
    178377}
    179378
  • kyra/sound.h

    diff --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvm.cvs/kyra/sound.h ./scummvm/kyra/sound.h
    old new  
    2929#include "kyra/kyra.h"
    3030
    3131namespace Kyra {
    32         class MusicPlayer : public MidiDriver {
    3332
    34         public:
     33class MusicPlayer : public MidiDriver {
    3534
    36                 MusicPlayer(MidiDriver* driver, KyraEngine* engine);
    37                 ~MusicPlayer();
     35public:
    3836
    39                 void setVolume(int volume);
    40                 int getVolume() { return _volume; }
     37        MusicPlayer(MidiDriver* driver, KyraEngine* engine);
     38        ~MusicPlayer();
    4139
    42                 void hasNativeMT32(bool nativeMT32) { _nativeMT32 = nativeMT32; }
     40        void setVolume(int volume);
     41        int getVolume() { return _volume; }
     42
     43        void hasNativeMT32(bool nativeMT32) { _nativeMT32 = nativeMT32; }
     44
     45        void playMusic(const char* file);
     46        void playMusic(uint8* data, uint32 size);
     47        void stopMusic();
     48
     49        void playTrack(uint8 track, bool looping = true);
     50        void haltTrack() { _isPlaying = false; }
     51        void startTrack() { _isPlaying = true; }
     52        void setPassThrough(bool b)     { _passThrough = b; }
     53
     54        void loadSoundEffectFile(const char* file);
     55        void loadSoundEffectFile(uint8* data, uint32 size);
     56        void stopSoundEffect();
     57
     58        void playSoundEffect(uint8 track);
     59
     60        void beginFadeOut();
     61
     62        //MidiDriver interface implementation
     63        int open();
     64        void close();
     65        void send(uint32 b);
     66        void metaEvent(byte type, byte *data, uint16 length);
     67
     68        void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { }
     69        uint32 getBaseTempo(void) { return _driver ? _driver->getBaseTempo() : 0; }
     70
     71        //Channel allocation functions
     72        MidiChannel *allocateChannel()          { return 0; }
     73        MidiChannel *getPercussionChannel()     { return 0; }
     74
     75protected:
     76
     77        static void onTimer(void *data);
     78
     79        MidiChannel* _channel[32];
     80        int _virChannel[16];
     81        uint8 _channelVolume[16];
     82        MidiDriver* _driver;
     83        bool _nativeMT32;
     84        bool _passThrough;
     85        uint8 _volume;
     86        bool _isPlaying;
     87        bool _sfxIsPlaying;
     88        uint32 _fadeStartTime;
     89        bool _fadeMusicOut;
     90        bool _isLooping;
     91        bool _eventFromMusic;
     92        MidiParser* _parser;
     93        MidiParser* _soundEffect;
     94        KyraEngine* _engine;
    4395
    44                 void playMusic(const char* file);
    45                 void playMusic(uint8* data, uint32 size);
    46                 void stopMusic();
     96};
    4797
    48                 void playTrack(uint8 track);
    49                 void setPassThrough(bool b)     { _passThrough = b; }
    50 
    51                 //MidiDriver interface implementation
    52                 int open();
    53                 void close();
    54                 void send(uint32 b);
    55                 void metaEvent(byte type, byte *data, uint16 length);
    56 
    57                 void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { }
    58                 uint32 getBaseTempo(void) { return _driver ? _driver->getBaseTempo() : 0; }
    59 
    60                 //Channel allocation functions
    61                 MidiChannel *allocateChannel()          { return 0; }
    62                 MidiChannel *getPercussionChannel()     { return 0; }
    63 
    64         protected:
    65 
    66                 static void onTimer(void *data);
    67 
    68                 MidiChannel* _channel[16];
    69                 uint8 _channelVolume[16];
    70                 MidiDriver* _driver;
    71                 bool _nativeMT32;
    72                 bool _passThrough;
    73                 uint8 _volume;
    74                 bool _isPlaying;
    75                 MidiParser* _parser;
    76                 KyraEngine* _engine;
    77 
    78         };
    7998} // end of namespace Kyra
    8099
    81100#endif
  • sound/midiparser_xmidi.cpp

    diff --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvm.cvs/sound/midiparser_xmidi.cpp ./scummvm/sound/midiparser_xmidi.cpp
    old new  
    6969        _inserted_delta = 0;
    7070        info.event = *(_position._play_pos++);
    7171        switch (info.event >> 4) {
     72        case 0x7:
     73                // TODO: why has the kyra intro this strange event?
     74                // maybe it is handeld in another way, but for now this will work
     75                warning("Kyrandia Hack, if this is NOT Kyrandia pls report it! (info.event: 0x%X)", info.event);
     76                parseNextEvent(info);
     77                break;
    7278        case 0x9: // Note On
    7379                info.basic.param1 = *(_position._play_pos++);
    7480                info.basic.param2 = *(_position._play_pos++);