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;  } | 
