diff options
author | Jamieson Christian | 2003-05-20 01:12:40 +0000 |
---|---|---|
committer | Jamieson Christian | 2003-05-20 01:12:40 +0000 |
commit | db8256df8a2b28e546cd0eba8b95b26f937a5d01 (patch) | |
tree | 100bce87ae3f9ffc2010694541e13bff7549639f | |
parent | f1982ec9d609693542dbc3522288f911d20d7136 (diff) | |
download | scummvm-rg350-db8256df8a2b28e546cd0eba8b95b26f937a5d01.tar.gz scummvm-rg350-db8256df8a2b28e546cd0eba8b95b26f937a5d01.tar.bz2 scummvm-rg350-db8256df8a2b28e546cd0eba8b95b26f937a5d01.zip |
More thorough parameterFade and deferredCommand implementation.
Lot of guesswork. parameterFade STILL NEEDS A LOT OF WORK!
These additions at least partially correct the music behavior
in the Tunnel of Love when shorting the controls.
svn-id: r7704
-rw-r--r-- | scumm/imuse.cpp | 180 |
1 files changed, 164 insertions, 16 deletions
diff --git a/scumm/imuse.cpp b/scumm/imuse.cpp index 3ce50ab8e5..055731e1b4 100644 --- a/scumm/imuse.cpp +++ b/scumm/imuse.cpp @@ -64,6 +64,19 @@ struct HookDatas { int set(byte cls, byte value, byte chan); }; +struct ParameterFade { + int param; + int start; + int end; + uint32 total_time; + uint32 current_time; +}; + +struct DeferredCommand { + MidiDriver *midi; + uint32 time_left; + int a, b, c, d, e, f; +}; struct Player { IMuseInternal *_se; @@ -102,6 +115,7 @@ struct Player { bool _abort; HookDatas _hook; + ParameterFade _parameterFades[4]; bool _mt32emulate; bool _isGM; @@ -136,6 +150,9 @@ struct Player { void play_active_notes(); void cancel_volume_fade(); + void addParameterTransition (int param, int target, int time); + void transitionParameters(); + static void decode_sysex_bytes(byte *src, byte *dst, int len); void clear_active_note(int chan, byte note); @@ -329,6 +346,7 @@ private: uint16 _active_notes[128]; Instrument _global_adlib_instruments[32]; CommandQueue _cmd_queue[64]; + DeferredCommand _deferredCommands[4]; byte *findTag(int sound, char *tag, int index); bool isMT32(int sound); @@ -355,6 +373,9 @@ private: int32 ImClearTrigger (int sound, int id); int32 ImFireAllTriggers (int sound); + void addDeferredCommand (int time, int a, int b, int c, int d, int e, int f); + void handleDeferredCommands (MidiDriver *midi); + int enqueue_command(int a, int b, int c, int d, int e, int f, int g); int enqueue_trigger(int sound, int marker); int query_queue(int param); @@ -807,6 +828,8 @@ void IMuseInternal::on_timer (MidiDriver *midi) { if (_paused) return; + if (midi == _midi_native || !_midi_native) + handleDeferredCommands (midi); sequencer_timers (midi); expire_sustain_notes (midi); expire_volume_faders (midi); @@ -1297,19 +1320,11 @@ int32 IMuseInternal::doCommand(int a, int b, int c, int d, int e, int f, int g, return getSoundStatus(b); case 14: // Sam and Max: Parameter transition - switch (d) { - case 1: - // Volume fade - player = this->get_player_byid (b); - if (player) - player->fade_vol (e, f); - return 0; - - default: - warning ("[%02d] doCommand (14): Unknown transition %d to value %d over %d ticks", b, d, e, f); - } + player = this->get_player_byid (b); + if (player) + player->addParameterTransition (d, e, f); + return 0; - return -1; case 15: // Sam & Max: Set hook for a "maybe" jump for (i = ARRAYSIZE(_players), player = _players; i != 0; i--, player++) { @@ -1356,10 +1371,9 @@ int32 IMuseInternal::doCommand(int a, int b, int c, int d, int e, int f, int g, return ImClearTrigger (b, d); case 20: // Sam & Max: Deferred Command - // FIXME: Right now this acts as an immediate command. - // The significance of parameter b is unknown. - warning ("Incomplete support for iMuse::doCommand(20)"); - return doCommand (c, d, e, f, g, h, 0, 0); + // warning ("[--] doCommand (20): %3d %3d %3d %3d %3d %3d (%d)", c, d, e, f, g, h, b); + addDeferredCommand (b, c, d, e, f, g, h); + return 0; case 2: case 3: return 0; @@ -2901,6 +2915,10 @@ void Player::sequencer_timer() { uint32 counter; byte *song_ptr; + // First handle any parameter transitions + // that are occuring. + transitionParameters(); + counter = _timer_counter + _timer_speed; _timer_counter = counter & 0xFFFF; _cur_pos += counter >> 16; @@ -2934,6 +2952,136 @@ void Player::sequencer_timer() { } } +void IMuseInternal::handleDeferredCommands (MidiDriver *midi) { + uint32 advance = midi->getBaseTempo() / 500; + + DeferredCommand *ptr = &_deferredCommands[0]; + int i; + for (i = ARRAYSIZE(_deferredCommands); i; --i, ++ptr) { + if (!ptr->time_left) + continue; + if (ptr->time_left <= advance) { + doCommand (ptr->a, ptr->b, ptr->c, ptr->d, ptr->e, ptr->f, 0, 0); + ptr->time_left = advance; + } + ptr->time_left -= advance; + } +} + +// "time" is referenced as hundredths of a second. +// IS THAT CORRECT?? +// We convert it to microseconds before prceeding +void IMuseInternal::addDeferredCommand (int time, int a, int b, int c, int d, int e, int f) { + DeferredCommand *ptr = &_deferredCommands[0]; + int i; + for (i = ARRAYSIZE(_deferredCommands); i; --i, ++ptr) { + if (!ptr->time_left) + break; + } + + if (ptr) { + ptr->midi = _midi_native ? _midi_native : _midi_adlib; + ptr->time_left = time * 10000; + ptr->a = a; + ptr->b = b; + ptr->c = c; + ptr->d = d; + ptr->e = e; + ptr->f = f; + } +} + +// "time" is referenced as hundredths of a second. +// IS THAT CORRECT?? +// We convert it to microseconds before prceeding +void Player::addParameterTransition (int param, int target, int time) { + int start; + + switch (param) { + case 1: + // Volume fades are handled differently. + fade_vol (target, time); + return; + + case 3: + // FIXME: Is this transpose? And what's the scale? + // It's set to fade to -2400 in the tunnel of love. + warning ("parameterTransition(3) outside Tunnel of Love?"); + start = _transpose; + target /= 200; + break; + + case 4: + // FIXME: Is the speed from 0-100? + // Right now I convert it to 0-128. + start = _speed; + target = target * 128 / 100; + break; + + case 127: + // FIXME: This MIGHT fade ALL supported parameters, + // but I'm not sure. + return; + + default: + warning ("Unknown transition parameter %d", param); + return; + } + + ParameterFade *ptr = &_parameterFades[0]; + ParameterFade *best = 0; + int i; + for (i = ARRAYSIZE(_parameterFades); i; --i, ++ptr) { + if (ptr->param == param) { + best = ptr; + start = ptr->end; + break; + } else if (!ptr->param) { + best = ptr; + } + } + + if (best) { + best->param = param; + best->start = start; + best->end = target; + best->total_time = (uint32) time * 10000; + best->current_time = 0; + } +} + +void Player::transitionParameters() { + uint32 advance = _midi->getBaseTempo() / 500; + int value; + + ParameterFade *ptr = &_parameterFades[0]; + int i; + for (i = ARRAYSIZE(_parameterFades); i; --i, ++ptr) { + if (!ptr->param) + continue; + + ptr->current_time += advance; + if (ptr->current_time > ptr->total_time) + ptr->current_time = ptr->total_time; + value = (int32) ptr->start + (int32) (ptr->end - ptr->start) * (int32) ptr->current_time / (int32) ptr->total_time; + + switch (ptr->param) { + case 4: + // Speed. + set_speed ((byte) value); + break; + + case 3: + // FIXME: Is this really transpose? + set_transpose (0, value); + break; + } + + if (ptr->current_time >= ptr->total_time) + ptr->param = 0; + } +} + //////////////////////////////////////////////////////////// enum { |