diff options
author | Jamieson Christian | 2002-11-18 09:08:45 +0000 |
---|---|---|
committer | Jamieson Christian | 2002-11-18 09:08:45 +0000 |
commit | 5214cb3463804bda39b10d52e4a7f6ccd943780d (patch) | |
tree | c857f7f0c58bfd65bd5e1e0fb03a0b3c2d434419 | |
parent | 713f11d99eb28474bcb8b31942c89e9fa8b66575 (diff) | |
download | scummvm-rg350-5214cb3463804bda39b10d52e4a7f6ccd943780d.tar.gz scummvm-rg350-5214cb3463804bda39b10d52e4a7f6ccd943780d.tar.bz2 scummvm-rg350-5214cb3463804bda39b10d52e4a7f6ccd943780d.zip |
Added support for volume and pause control to Simon music.
Note that MidiStreamer is now used as a streaming wrapper
for ALL MidiDriver types, even those that natively support
streaming. This is because MidiStreamer supports a hybrid
of streamed and non-streamed MIDI, which is necessary to
support interactive events.
svn-id: r5596
-rw-r--r-- | simon/midi.cpp | 65 | ||||
-rw-r--r-- | simon/midi.h | 23 | ||||
-rw-r--r-- | sound/midistreamer.cpp | 9 |
3 files changed, 64 insertions, 33 deletions
diff --git a/simon/midi.cpp b/simon/midi.cpp index 04b727dd77..cf31d24b0f 100644 --- a/simon/midi.cpp +++ b/simon/midi.cpp @@ -31,6 +31,13 @@ // FIXME: This is a horrible place to put this, but for now.... #include "sound/midistreamer.cpp" +MidiPlayer::MidiPlayer() { + // Since initialize() is called every time the music changes, + // this is where we'll initialize stuff that must persist + // between songs. + _masterVolume = 255; +} + void MidiPlayer::read_all_songs(File *in, uint music) { uint i, num; @@ -178,21 +185,16 @@ void MidiPlayer::initialize() int i; for (i = 0; i != 16; i++) - _volumeTable[i] = 100; + _volumeTable[i] = 127; _midiDriver->property(MidiDriver::PROP_TIMEDIV, _songs[0].ppqn); res = _midiDriver->open(MidiDriver::MO_STREAMING); - if (res == MidiDriver::MERR_STREAMING_NOT_AVAILABLE) { - // No direct streaming, slap a front-end on. - _midiDriver = new MidiStreamer (_midiDriver); - _midiDriver->property (MidiDriver::PROP_TIMEDIV, _songs[0].ppqn); - _midiDriver->set_stream_callback (this, on_fill); - res = _midiDriver->open (MidiDriver::MO_STREAMING); - } - if (res != 0) error("MidiPlayer::initializer, got %s", MidiDriver::get_error_name(res)); + + if (_paused) + _midiDriver->pause (true); } int MidiPlayer::fill(MidiEvent *me, int num_event) @@ -261,8 +263,8 @@ bool MidiPlayer::fill_helper(NoteRec *nr, MidiEvent *me) if ((nr->cmd & 0xF0) == 0xB0 && nr->param_1 == 7) { _volumeTable[nr->cmd & 0xF] = nr->param_2; - nr->param_1 = 0x76; - me->event = nr->cmd | (nr->param_1 << 8) | (nr->param_2 << 16) /* | MEVT_F_CALLBACK */ ; +// nr->param_1 = 0x76; + me->event = nr->cmd | (nr->param_1 << 8) | ((nr->param_2 * _masterVolume / 255) << 16) /* | MEVT_F_CALLBACK */ ; } return true; @@ -414,27 +416,52 @@ void MidiPlayer::unload() void MidiPlayer::play() { - _midiDriver->pause(false); + if (!_paused) + _midiDriver->pause(false); } -void MidiPlayer::pause(bool b) +void MidiPlayer::pause (bool b) { + if (_paused == b) + return; + _paused = b; _midiDriver->pause(b); + + for (int i = ARRAYSIZE (_volumeTable); i; --i) { + _midiDriver->send (((_paused ? 0 : (_volumeTable[i-1] * _masterVolume / 255)) << 16) | (7 << 8) | 0xB0 | i); + } + } -uint MidiPlayer::get_volume() +int MidiPlayer::get_volume() { - // TODO: implement me - return 0; + return _masterVolume; } -void MidiPlayer::set_volume(uint volume) +void MidiPlayer::set_volume (int volume) { - // TODO: implement me + if (volume < 0) + volume = 0; + else if (volume > 255) + volume = 255; + + if (_masterVolume == volume) + return; + + _masterVolume = volume; + + // Now tell all the channels this. + if (_midiDriver && !_paused) { + for (int i = ARRAYSIZE (_volumeTable); i; --i) { + _midiDriver->send (((_volumeTable[i-1] * _masterVolume / 255) << 16) | (7 << 8) | 0xB0 | i); + } + } } void MidiPlayer::set_driver(MidiDriver *md) { - _midiDriver = md; + // We must always use the MidiStreamer front-end + // so we can support user-initiated MIDI events (like volume). + _midiDriver = new MidiStreamer (md); _midiDriver->set_stream_callback(this, on_fill); } diff --git a/simon/midi.h b/simon/midi.h index 064acca416..3653a37316 100644 --- a/simon/midi.h +++ b/simon/midi.h @@ -28,15 +28,17 @@ struct MidiEvent; class MidiPlayer { public: - void read_all_songs(File *in, uint music); - void read_all_songs_old(File *in, uint music); + MidiPlayer(); + + void read_all_songs (File *in, uint music); + void read_all_songs_old (File *in, uint music); void initialize(); void shutdown(); void play(); - void pause(bool b); - uint get_volume(); - void set_volume(uint volume); - void set_driver(MidiDriver *md); + void pause (bool b); + int get_volume(); + void set_volume (int volume); + void set_driver (MidiDriver *md); private: struct Track { @@ -69,8 +71,9 @@ private: uint _lastDelay; Song *_currentSong; Song _songs[8]; - uint32 _volumeTable[16]; - + byte _volumeTable[16]; // 0-127 + byte _masterVolume; // 0-255 + bool _paused; void read_mthd(File *in, Song *s, bool old, uint music); @@ -79,8 +82,8 @@ private: static uint32 track_read_gamma(Track *t); static byte track_read_byte(Track *t); - int fill(MidiEvent *me, int num_event); - bool fill_helper(NoteRec *nr, MidiEvent *me); + int fill (MidiEvent *me, int num_event); + bool fill_helper (NoteRec *nr, MidiEvent *me); void reset_tracks(); void read_next_note(Track *t, NoteRec *nr); diff --git a/sound/midistreamer.cpp b/sound/midistreamer.cpp index bb94ca2eef..fcd4109c81 100644 --- a/sound/midistreamer.cpp +++ b/sound/midistreamer.cpp @@ -30,8 +30,8 @@ private: MidiDriver *_target; StreamCallback *_stream_proc; void *_stream_param; - int _mode; - bool _paused; + volatile int _mode; + volatile bool _paused; MidiEvent _events [64]; int _event_count; @@ -52,7 +52,7 @@ public: int open(int mode); void close(); - void send(uint32 b) { _target->send (b); } + void send(uint32 b) { if (_mode) _target->send (b); } void pause(bool p) { _paused = p; } void set_stream_callback(void *param, StreamCallback *sc); void setPitchBendRange (byte channel, uint range) { _target->setPitchBendRange (channel, range); } @@ -87,6 +87,7 @@ int MidiStreamer::timer_thread (void *param) { MidiStreamer *mid = (MidiStreamer *) param; int old_time, cur_time; while (mid->_mode) { + g_system->delay_msecs (100); while (!mid->_stream_proc); old_time = g_system->get_msecs(); while (!mid->_paused) { @@ -104,7 +105,7 @@ int MidiStreamer::timer_thread (void *param) { // just to catch anything still playing. int i; for (i = 0; i < 16; ++i) - mid->send ((0x7B << 8) | 0xB0 | i); + mid->_target->send ((0x7B << 8) | 0xB0 | i); mid->_active = false; return 0; } |