aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--simon/midi.cpp65
-rw-r--r--simon/midi.h23
-rw-r--r--sound/midistreamer.cpp9
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;
}