mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-01 08:23:15 +00:00
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
This commit is contained in:
parent
713f11d99e
commit
5214cb3463
@ -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);
|
||||
}
|
||||
|
23
simon/midi.h
23
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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user