Ticket #8460: kyra_sound_v2.patch
File kyra_sound_v2.patch, 14.3 KB (added by , 19 years ago) |
---|
-
kyra/kyra.cpp
diff --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvm.cvs/kyra/kyra.cpp ./scummvm/kyra/kyra.cpp
old new 142 142 _system->initSize(320, 200); 143 143 _system->endGFXTransaction(); 144 144 145 int midiDrv = MidiDriver::detectMusicDriver(MDT_NATIVE | MDT_ADLIB | MDT_PREFER_NATIVE); 145 // for now we prefer MIDI-to-Adlib conversion over native midi 146 int midiDrv = MidiDriver::detectMusicDriver(MDT_NATIVE | MDT_ADLIB/* | MDT_PREFER_NATIVE*/); 146 147 bool native_mt32 = (ConfMan.getBool("native_mt32") || (midiDrv == MD_MT32)); 147 148 148 149 MidiDriver *driver = MidiDriver::createMidi(midiDrv); … … 158 159 assert(_midi); 159 160 _midi->hasNativeMT32(native_mt32); 160 161 _midi->setVolume(255); 161 162 162 163 _res = new Resource(this); 163 164 assert(_res); 164 165 _screen = new Screen(this, _system); … … 504 505 _skipIntroFlag = true; // only true if user already played the game once 505 506 _seq_copyViewOffs = true; 506 507 _screen->setFont(Screen::FID_8_FNT); 507 // snd_kyraPlayTheme(0); 508 snd_playTheme(MIDI_INTRO, 2); 509 snd_setSoundEffectFile(MIDI_INTRO); 508 510 setTalkCoords(144); 509 511 for (int i = 0; i < ARRAYSIZE(introProcTable) && !seq_skipSequence(); ++i) { 510 512 (this->*introProcTable[i])(); … … 947 949 } 948 950 break; 949 951 case 24: { // sound related 950 seqData++; 951 warning("Sequence opcode 24 skipped"); 952 uint8 param = *seqData++; 953 waitTicks(3); 954 snd_playSoundEffect(param); 952 955 } 953 956 break; 954 957 case 25: { // sound related 955 seqData++;956 warning("Sequence opcode 25 skipped");958 uint8 param = *seqData++; 959 snd_seqMessage(param); 957 960 } 958 961 break; 959 962 case 26: -
kyra/kyra.h
diff --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvm.cvs/kyra/kyra.h ./scummvm/kyra/kyra.h
old new 88 88 class Screen; 89 89 90 90 class KyraEngine : public Engine { 91 friend class MusicPlayer; 91 92 public: 92 93 93 94 enum { … … 109 110 110 111 typedef void (KyraEngine::*IntroProc)(); 111 112 113 enum { 114 MIDI_INTRO = 0, 115 MIDI_KYRAMISC = 11 116 }; 117 112 118 protected: 113 119 114 120 int go(); … … 149 155 uint16 wsa_getNumFrames(WSAMovieV1 *wsa) const; 150 156 void wsa_play(WSAMovieV1 *wsa, int frameNum, int x, int y, int pageNum); 151 157 void wsa_processFrame(WSAMovieV1 *wsa, int frameNum, uint8 *dst); 158 159 void snd_playTheme(int file, int track = 0); 160 void snd_playTrack(int track); 161 void snd_startTrack(); 162 void snd_haltTrack(); 163 void snd_setSoundEffectFile(int file); 164 void snd_playSoundEffect(int track); 165 void snd_seqMessage(int msg); 152 166 153 167 uint8 _game; 154 168 bool _fastMode; -
kyra/sound.cpp
diff --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvm.cvs/kyra/sound.cpp ./scummvm/kyra/sound.cpp
old new 22 22 #include "common/stdafx.h" 23 23 #include "kyra/resource.h" 24 24 #include "kyra/sound.h" 25 #include "common/system.h" 25 26 26 27 namespace Kyra { 27 28 28 MusicPlayer::MusicPlayer(MidiDriver * driver, KyraEngine*engine) {29 MusicPlayer::MusicPlayer(MidiDriver *driver, KyraEngine *engine) { 29 30 _engine = engine; 30 31 _driver = driver; 31 32 _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 _soundEffectSource = _parserSource = 0; 38 39 memset(_channel, 0, sizeof(MidiChannel*) * 32); 40 memset(_channelVolume, 50, sizeof(uint8) * 16); 41 _channelVolume[10] = 100; 42 for (int i = 0; i < 16; ++i) { 43 _virChannel[i] = i; 44 } 36 45 _volume = 0; 37 46 38 47 int ret = open(); … … 56 65 return; 57 66 58 67 _volume = volume; 59 for (int i = 0; i < 16; ++i) {68 for (int i = 0; i < 32; ++i) { 60 69 if (_channel[i]) { 61 _channel[i]->volume(_channelVolume[i] * _volume / 255); 70 if (i >= 16) { 71 _channel[i]->volume(_channelVolume[i - 16] * _volume / 255); 72 } else { 73 _channel[i]->volume(_channelVolume[i] * _volume / 255); 74 } 62 75 } 63 76 } 64 77 } … … 84 97 85 98 void MusicPlayer::send(uint32 b) { 86 99 if (_passThrough) { 100 if ((b & 0xFFF0) == 0x007BB0) 101 return; 87 102 _driver->send(b); 88 103 return; 89 104 } 90 105 91 106 uint8 channel = (byte)(b & 0x0F); 107 if (((b & 0xFFF0) == 0x6FB0 || (b & 0xFFF0) == 0x6EB0) && channel != 9) { 108 if (_virChannel[channel] == channel) { 109 _virChannel[channel] = channel + 16; 110 if (!_channel[_virChannel[channel]]) 111 _channel[_virChannel[channel]] = _driver->allocateChannel(); 112 _channel[_virChannel[channel]]->volume(_channelVolume[channel] * _volume / 255); 113 } 114 return; 115 } 116 92 117 if ((b & 0xFFF0) == 0x07B0) { 93 118 // Adjust volume changes by master volume 94 119 uint8 volume = (uint8)((b >> 16) & 0x7F); … … 104 129 return; 105 130 } 106 131 107 if (!_channel[channel]) 108 _channel[channel] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel(); 109 if (_channel[channel]) 110 _channel[channel]->send(b); 132 if (!_channel[_virChannel[channel]]) { 133 _channel[_virChannel[channel]] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel(); 134 _channel[_virChannel[channel]]->volume(_channelVolume[channel] * _volume / 255); 135 } 136 if (_channel[_virChannel[channel]]) 137 _channel[_virChannel[channel]]->send(b); 111 138 } 112 139 113 140 void MusicPlayer::metaEvent(byte type, byte *data, uint16 length) { 114 141 switch (type) { 115 142 case 0x2F: // End of Track 116 _parser->jumpToTick(0); 143 if (_eventFromMusic) { 144 if (!_isLooping) { 145 _isPlaying = false; 146 } 147 148 // remap all channels 149 for (int i = 0; i < 16; ++i) { 150 _virChannel[i] = i; 151 } 152 153 } else { 154 _sfxIsPlaying = false; 155 } 117 156 break; 118 157 default: 119 warning("Unhandled meta event: 0x%02x", type);158 _driver->metaEvent(type, data, length); 120 159 break; 121 160 } 122 161 } 123 162 124 void MusicPlayer::playMusic(const char *file) {163 void MusicPlayer::playMusic(const char *file) { 125 164 uint32 size; 126 165 uint8 *data = (_engine->resource())->fileData(file, &size); 127 166 … … 133 172 playMusic(data, size); 134 173 } 135 174 136 void MusicPlayer::playMusic(uint8* data, uint32 size) { 137 if (_isPlaying) 138 stopMusic(); 175 void MusicPlayer::playMusic(uint8 *data, uint32 size) { 176 stopMusic(); 139 177 178 _parserSource = data; 140 179 _parser = MidiParser::createParser_XMIDI(); 141 180 assert(_parser); 142 181 … … 150 189 _parser->setTrack(0); 151 190 _parser->setMidiDriver(this); 152 191 _parser->setTimerRate(getBaseTempo()); 192 _parser->property(MidiParser::mpAutoLoop, false); 193 } 194 195 void MusicPlayer::loadSoundEffectFile(const char *file) { 196 uint32 size; 197 uint8 *data = (_engine->resource())->fileData(file, &size); 198 199 if (!data) { 200 warning("couldn't load '%s'", file); 201 return; 202 } 203 204 loadSoundEffectFile(data, size); 205 } 206 207 void MusicPlayer::loadSoundEffectFile(uint8 *data, uint32 size) { 208 stopSoundEffect(); 209 210 _soundEffectSource = data; 211 _soundEffect = MidiParser::createParser_XMIDI(); 212 assert(_soundEffect); 213 214 if (!_soundEffect->loadMusic(data, size)) { 215 warning("Error reading track!"); 216 delete _parser; 217 _parser = 0; 218 return; 219 } 153 220 154 _isPlaying = true; 221 _soundEffect->setTrack(0); 222 _soundEffect->setMidiDriver(this); 223 _soundEffect->setTimerRate(getBaseTempo()); 224 _soundEffect->property(MidiParser::mpAutoLoop, false); 155 225 } 156 226 157 227 void MusicPlayer::stopMusic() { 228 _isLooping = false; 158 229 _isPlaying = false; 159 230 if (_parser) { 160 231 _parser->unloadMusic(); 161 232 delete _parser; 162 _parser = NULL; 233 _parser = 0; 234 delete [] _parserSource; 235 _parserSource = 0; 236 } 237 } 238 239 void MusicPlayer::stopSoundEffect() { 240 _sfxIsPlaying = false; 241 if (_soundEffect) { 242 _soundEffect->unloadMusic(); 243 delete _soundEffect; 244 _soundEffect = 0; 245 delete [] _soundEffectSource; 246 _soundEffectSource = 0; 163 247 } 164 248 } 165 249 166 250 void MusicPlayer::onTimer(void *refCon) { 167 251 MusicPlayer *music = (MusicPlayer *)refCon; 168 if (music->_isPlaying) 169 music->_parser->onTimer(); 252 253 // this should be set to the fadeToBlack value 254 const static uint32 musicFadeTime = 2 * 1000; 255 if (music->_fadeMusicOut && music->_fadeStartTime + musicFadeTime > music->_engine->_system->getMillis()) { 256 byte volume = (byte)((musicFadeTime - (music->_engine->_system->getMillis() - music->_fadeStartTime)) * 255 / musicFadeTime); 257 music->setVolume(volume); 258 } else if(music->_fadeStartTime) { 259 music->setVolume(255); 260 music->_fadeStartTime = 0; 261 music->_fadeMusicOut = false; 262 } 263 264 if (music->_isPlaying) { 265 if (music->_parser) { 266 music->_eventFromMusic = true; 267 music->_parser->onTimer(); 268 } 269 } 270 271 if (music->_sfxIsPlaying) { 272 if (music->_soundEffect) { 273 music->_eventFromMusic = false; 274 music->_soundEffect->onTimer(); 275 } 276 } 170 277 } 171 278 172 void MusicPlayer::playTrack(uint8 track ) {279 void MusicPlayer::playTrack(uint8 track, bool loop) { 173 280 if (_parser) { 174 281 _isPlaying = true; 282 _isLooping = loop; 175 283 _parser->setTrack(track); 176 284 _parser->jumpToTick(0); 285 _parser->setTempo(1); 286 _parser->property(MidiParser::mpAutoLoop, loop); 287 } 288 } 289 290 void MusicPlayer::playSoundEffect(uint8 track) { 291 if (_soundEffect) { 292 _sfxIsPlaying = true; 293 _soundEffect->setTrack(track); 294 _soundEffect->jumpToTick(0); 295 _soundEffect->property(MidiParser::mpAutoLoop, false); 296 } 297 } 298 299 void MusicPlayer::beginFadeOut() { 300 // this should be something like fade out... 301 _fadeMusicOut = true; 302 _fadeStartTime = _engine->_system->getMillis(); 303 } 304 305 void KyraEngine::snd_playTheme(int file, int track) { 306 debug(9, "snd_playTheme(%d)", file); 307 switch(file) { 308 case MIDI_INTRO: 309 _midi->playMusic("INTRO.XMI"); 310 break; 311 312 default: 313 warning("Unkown music file: %d", file); 314 break; 315 } 316 317 _midi->playTrack(track, false); 318 } 319 320 void KyraEngine::snd_playTrack(int track) { 321 debug(9, "snd_playTrack(%d)", track); 322 _midi->playTrack(track, false); 323 } 324 325 void KyraEngine::snd_setSoundEffectFile(int file) { 326 debug(9, "snd_setSoundEffectFile(%d)", file); 327 switch(file) { 328 case MIDI_INTRO: 329 _midi->loadSoundEffectFile("INTRO.XMI"); 330 break; 331 332 case MIDI_KYRAMISC: 333 _midi->loadSoundEffectFile("KYRAMISC.XMI"); 334 break; 335 336 default: 337 break; 338 } 339 } 340 341 void KyraEngine::snd_playSoundEffect(int track) { 342 debug(9, "snd_playSoundEffect(%d)", track); 343 _midi->playSoundEffect(track); 344 } 345 346 void KyraEngine::snd_startTrack() { 347 _midi->startTrack(); 348 } 349 350 void KyraEngine::snd_haltTrack() { 351 _midi->haltTrack(); 352 } 353 354 void KyraEngine::snd_seqMessage(int msg) { 355 debug(9, "snd_seqMessage(%.02d)", msg); 356 switch(msg) { 357 case 0: 358 // nothing to do here... 359 break; 360 361 case 1: 362 _midi->beginFadeOut(); 363 break; 364 365 case 56: 366 snd_playTheme(MIDI_INTRO, 3); 367 break; 368 369 case 57: 370 snd_playTheme(MIDI_INTRO, 4); 371 break; 372 373 case 58: 374 snd_playTheme(MIDI_INTRO, 5); 375 break; 376 377 default: 378 warning("Unknown seq. message: %.02d", msg); 379 break; 177 380 } 178 381 } 179 382 -
kyra/sound.h
diff --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvm.cvs/kyra/sound.h ./scummvm/kyra/sound.h
old new 29 29 #include "kyra/kyra.h" 30 30 31 31 namespace Kyra { 32 class MusicPlayer : public MidiDriver {33 32 34 public: 33 class MusicPlayer : public MidiDriver { 35 34 36 MusicPlayer(MidiDriver* driver, KyraEngine* engine); 37 ~MusicPlayer(); 35 public: 38 36 39 void setVolume(int volume);40 int getVolume() { return _volume; }37 MusicPlayer(MidiDriver *driver, KyraEngine *engine); 38 ~MusicPlayer(); 41 39 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 bool isMT32() { return _nativeMT32; } 45 46 void playMusic(const char* file); 47 void playMusic(uint8* data, uint32 size); 48 void stopMusic(); 49 50 void playTrack(uint8 track, bool looping = true); 51 void haltTrack() { _isPlaying = false; } 52 void startTrack() { _isPlaying = true; } 53 void setPassThrough(bool b) { _passThrough = b; } 54 55 void loadSoundEffectFile(const char* file); 56 void loadSoundEffectFile(uint8* data, uint32 size); 57 void stopSoundEffect(); 58 59 void playSoundEffect(uint8 track); 60 61 void beginFadeOut(); 62 63 //MidiDriver interface implementation 64 int open(); 65 void close(); 66 void send(uint32 b); 67 void metaEvent(byte type, byte *data, uint16 length); 68 69 void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { } 70 uint32 getBaseTempo(void) { return _driver ? _driver->getBaseTempo() : 0; } 71 72 //Channel allocation functions 73 MidiChannel *allocateChannel() { return 0; } 74 MidiChannel *getPercussionChannel() { return 0; } 75 76 protected: 77 78 static void onTimer(void *data); 79 80 MidiChannel* _channel[32]; 81 int _virChannel[16]; 82 uint8 _channelVolume[16]; 83 MidiDriver* _driver; 84 bool _nativeMT32; 85 bool _passThrough; 86 uint8 _volume; 87 bool _isPlaying; 88 bool _sfxIsPlaying; 89 uint32 _fadeStartTime; 90 bool _fadeMusicOut; 91 bool _isLooping; 92 bool _eventFromMusic; 93 MidiParser *_parser; 94 byte *_parserSource; 95 MidiParser *_soundEffect; 96 byte *_soundEffectSource; 97 KyraEngine *_engine; 43 98 44 void playMusic(const char* file); 45 void playMusic(uint8* data, uint32 size); 46 void stopMusic(); 99 }; 47 100 48 void playTrack(uint8 track);49 void setPassThrough(bool b) { _passThrough = b; }50 51 //MidiDriver interface implementation52 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 functions61 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 };79 101 } // end of namespace Kyra 80 102 81 103 #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 53 53 uint32 value = 0; 54 54 int i; 55 55 56 for (i = 0; i < 4; ++i) { 56 // Kyra seems to handle it like this 57 // not only with 4 bytes at maximum 58 for (i = 0; true; ++i) { 57 59 if (pos[0] & 0x80) 58 60 break; 59 61 value += *pos++;