[Scummvm-cvs-logs] SF.net SVN: scummvm:[49751] scummvm/trunk/engines/agi

sev at users.sourceforge.net sev at users.sourceforge.net
Tue Jun 15 12:34:45 CEST 2010


Revision: 49751
          http://scummvm.svn.sourceforge.net/scummvm/?rev=49751&view=rev
Author:   sev
Date:     2010-06-15 10:34:45 +0000 (Tue, 15 Jun 2010)

Log Message:
-----------
AGI: Implement FR #1913900.

FR #1913900: "AGI: MIDI support".
Currently it gets selected when Adlib is chosen. Finding a better
way to do it is a todo.

Also default instrument mapping is plain.

Based on original code by Jens. Christian Restemeier.

Modified Paths:
--------------
    scummvm/trunk/engines/agi/agi.cpp
    scummvm/trunk/engines/agi/loader_v2.cpp
    scummvm/trunk/engines/agi/loader_v3.cpp
    scummvm/trunk/engines/agi/module.mk
    scummvm/trunk/engines/agi/sound.cpp
    scummvm/trunk/engines/agi/sound.h

Added Paths:
-----------
    scummvm/trunk/engines/agi/sound_midi.cpp
    scummvm/trunk/engines/agi/sound_midi.h

Modified: scummvm/trunk/engines/agi/agi.cpp
===================================================================
--- scummvm/trunk/engines/agi/agi.cpp	2010-06-15 10:34:14 UTC (rev 49750)
+++ scummvm/trunk/engines/agi/agi.cpp	2010-06-15 10:34:45 UTC (rev 49751)
@@ -583,10 +583,13 @@
 	} else if (getPlatform() == Common::kPlatformCoCo3) {
 		_soundemu = SOUND_EMU_COCO3;
 	} else {
-		switch (MidiDriver::detectMusicDriver(MDT_PCSPK)) {
+		switch (MidiDriver::detectMusicDriver(MDT_PCSPK | MDT_ADLIB)) {
 		case MD_PCSPK:
 			_soundemu = SOUND_EMU_PC;
 			break;
+		case MD_ADLIB:
+			_soundemu = SOUND_EMU_MIDI;
+			break;
 		default:
 			_soundemu = SOUND_EMU_NONE;
 			break;

Modified: scummvm/trunk/engines/agi/loader_v2.cpp
===================================================================
--- scummvm/trunk/engines/agi/loader_v2.cpp	2010-06-15 10:34:14 UTC (rev 49750)
+++ scummvm/trunk/engines/agi/loader_v2.cpp	2010-06-15 10:34:45 UTC (rev 49751)
@@ -232,7 +232,7 @@
 
 		if (data != NULL) {
 			// Freeing of the raw resource from memory is delegated to the createFromRawResource-function
-			_vm->_game.sounds[n] = AgiSound::createFromRawResource(data, _vm->_game.dirSound[n].len, n, *_vm->_sound);
+			_vm->_game.sounds[n] = AgiSound::createFromRawResource(data, _vm->_game.dirSound[n].len, n, *_vm->_sound, _vm->_soundemu);
 			_vm->_game.dirSound[n].flags |= RES_LOADED;
 		} else {
 			ec = errBadResource;

Modified: scummvm/trunk/engines/agi/loader_v3.cpp
===================================================================
--- scummvm/trunk/engines/agi/loader_v3.cpp	2010-06-15 10:34:14 UTC (rev 49750)
+++ scummvm/trunk/engines/agi/loader_v3.cpp	2010-06-15 10:34:45 UTC (rev 49751)
@@ -316,7 +316,7 @@
 		data = loadVolRes(&_vm->_game.dirSound[n]);
 		if (data != NULL) {
 			// Freeing of the raw resource from memory is delegated to the createFromRawResource-function
-			_vm->_game.sounds[n] = AgiSound::createFromRawResource(data, _vm->_game.dirSound[n].len, n, *_vm->_sound);
+			_vm->_game.sounds[n] = AgiSound::createFromRawResource(data, _vm->_game.dirSound[n].len, n, *_vm->_sound, _vm->_soundemu);
 			_vm->_game.dirSound[n].flags |= RES_LOADED;
 		} else {
 			ec = errBadResource;

Modified: scummvm/trunk/engines/agi/module.mk
===================================================================
--- scummvm/trunk/engines/agi/module.mk	2010-06-15 10:34:14 UTC (rev 49750)
+++ scummvm/trunk/engines/agi/module.mk	2010-06-15 10:34:45 UTC (rev 49751)
@@ -31,6 +31,7 @@
 	saveload.o \
 	sound.o \
 	sound_2gs.o \
+	sound_midi.o \
 	sprite.o \
 	text.o \
 	view.o \

Modified: scummvm/trunk/engines/agi/sound.cpp
===================================================================
--- scummvm/trunk/engines/agi/sound.cpp	2010-06-15 10:34:14 UTC (rev 49750)
+++ scummvm/trunk/engines/agi/sound.cpp	2010-06-15 10:34:45 UTC (rev 49751)
@@ -29,9 +29,12 @@
 #include "common/random.h"
 #include "common/str-array.h"
 
+#include "sound/mididrv.h"
+
 #include "agi/agi.h"
 
 #include "agi/sound_2gs.h"
+#include "agi/sound_midi.h"
 
 namespace Agi {
 
@@ -41,7 +44,7 @@
 // TODO: add support for variable sampling rate in the output device
 //
 
-AgiSound *AgiSound::createFromRawResource(uint8 *data, uint32 len, int resnum, SoundMgr &manager) {
+AgiSound *AgiSound::createFromRawResource(uint8 *data, uint32 len, int resnum, SoundMgr &manager, int soundemu) {
 	if (data == NULL || len < 2) // Check for too small resource or no resource at all
 		return NULL;
 	uint16 type = READ_LE_UINT16(data);
@@ -50,9 +53,13 @@
 	case AGI_SOUND_SAMPLE:
 		return new IIgsSample(data, len, resnum, manager);
 	case AGI_SOUND_MIDI:
-		return new IIgsMidi  (data, len, resnum, manager);
+		return new IIgsMidi(data, len, resnum, manager);
 	case AGI_SOUND_4CHN:
-		return new PCjrSound (data, len, resnum, manager);
+		if (soundemu == SOUND_EMU_MIDI) {
+			return new MIDISound(data, len, resnum, manager);
+		} else {
+			return new PCjrSound(data, len, resnum, manager);
+		}
 	}
 
 	warning("Sound resource (%d) has unknown type (0x%04x). Not using the sound", resnum, type);
@@ -165,24 +172,29 @@
 		((IIgsMidi *) _vm->_game.sounds[_playingSound])->rewind();
 		break;
 	case AGI_SOUND_4CHN:
-		PCjrSound *pcjrSound = (PCjrSound *) _vm->_game.sounds[resnum];
+		if (_vm->_soundemu == SOUND_EMU_MIDI) {
+			_musicPlayer->playMIDI((MIDISound *)_vm->_game.sounds[resnum]);
+		} else {
 
-		// Initialize channel info
-		for (i = 0; i < NUM_CHANNELS; i++) {
-			_chn[i].type = type;
-			_chn[i].flags = AGI_SOUND_LOOP;
+			PCjrSound *pcjrSound = (PCjrSound *) _vm->_game.sounds[resnum];
 
-			if (_env) {
-				_chn[i].flags |= AGI_SOUND_ENVELOPE;
-				_chn[i].adsr = AGI_SOUND_ENV_ATTACK;
+			// Initialize channel info
+			for (i = 0; i < NUM_CHANNELS; i++) {
+				_chn[i].type = type;
+				_chn[i].flags = AGI_SOUND_LOOP;
+				
+				if (_env) {
+					_chn[i].flags |= AGI_SOUND_ENVELOPE;
+					_chn[i].adsr = AGI_SOUND_ENV_ATTACK;
+				}
+
+				_chn[i].ins = _waveform;
+				_chn[i].size = WAVEFORM_SIZE;
+				_chn[i].ptr = pcjrSound->getVoicePointer(i % 4);
+				_chn[i].timer = 0;
+				_chn[i].vol = 0;
+				_chn[i].end = 0;
 			}
-
-			_chn[i].ins = _waveform;
-			_chn[i].size = WAVEFORM_SIZE;
-			_chn[i].ptr = pcjrSound->getVoicePointer(i % 4);
-			_chn[i].timer = 0;
-			_chn[i].vol = 0;
-			_chn[i].end = 0;
 		}
 		break;
 	}
@@ -213,6 +225,10 @@
 			_gsSound->stopSounds();
 		}
 
+		if (_vm->_soundemu == SOUND_EMU_MIDI) {
+			_musicPlayer->stop();
+		}
+
 		_playingSound = -1;
 	}
 }
@@ -240,6 +256,8 @@
 		break;
 	case SOUND_EMU_COCO3:
 		break;
+	case SOUND_EMU_MIDI:
+		break;
 	}
 
 	report("Initializing sound:\n");
@@ -251,7 +269,8 @@
 		report("disabled\n");
 	}
 
-	_mixer->playStream(Audio::Mixer::kMusicSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
+	if (_vm->_soundemu != SOUND_EMU_MIDI)
+		_mixer->playStream(Audio::Mixer::kMusicSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
 
 	return r;
 }
@@ -607,12 +626,21 @@
 	_waveform = 0;
 	_disabledMidi = false;
 	_useChorus = true;	// FIXME: Currently always true?
+	_midiDriver = 0;
 
 	_gsSound = new IIgsSoundMgr;
+
+	if (_vm->_soundemu == SOUND_EMU_MIDI) {
+		MidiDriverType midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB);
+
+		_midiDriver = MidiDriver::createMidi(midiDriver);
+		_musicPlayer = new MusicPlayer(_midiDriver, this);
+	}
 }
 
 void SoundMgr::premixerCall(int16 *data, uint len) {
-	fillAudio(this, data, len);
+	if (_vm->_soundemu != SOUND_EMU_MIDI)
+		fillAudio(this, data, len);
 }
 
 void SoundMgr::setVolume(uint8 volume) {
@@ -622,6 +650,9 @@
 SoundMgr::~SoundMgr() {
 	free(_sndBuffer);
 	delete _gsSound;
+
+	delete _musicPlayer;
+	delete _midiDriver;
 }
 
 } // End of namespace Agi

Modified: scummvm/trunk/engines/agi/sound.h
===================================================================
--- scummvm/trunk/engines/agi/sound.h	2010-06-15 10:34:14 UTC (rev 49750)
+++ scummvm/trunk/engines/agi/sound.h	2010-06-15 10:34:45 UTC (rev 49751)
@@ -29,6 +29,8 @@
 #include "sound/audiostream.h"
 #include "sound/mixer.h"
 
+class MidiDriver;
+
 namespace Agi {
 
 #define BUFFER_SIZE	410
@@ -40,6 +42,7 @@
 #define SOUND_EMU_AMIGA	4
 #define SOUND_EMU_APPLE2GS 5
 #define SOUND_EMU_COCO3 6
+#define SOUND_EMU_MIDI 7
 
 #define WAVEFORM_SIZE   64
 #define ENV_ATTACK	10000		/**< envelope attack rate */
@@ -143,7 +146,7 @@
 	 * from memory using free() or delegate the responsibility onwards to some other
 	 * function!
 	 */
-	static AgiSound *createFromRawResource(uint8 *data, uint32 len, int resnum, SoundMgr &manager);
+	static AgiSound *createFromRawResource(uint8 *data, uint32 len, int resnum, SoundMgr &manager, int soundemu);
 
 protected:
 	SoundMgr &_manager; ///< AGI sound manager object
@@ -154,7 +157,7 @@
 class PCjrSound : public AgiSound {
 public:
 	PCjrSound(uint8 *data, uint32 len, int resnum, SoundMgr &manager);
-	~PCjrSound() { if (_data != NULL) free(_data); }
+	~PCjrSound() { free(_data); }
 	virtual uint16 type() { return _type; }
 	const uint8 *getVoicePointer(uint voiceNum);
 protected:
@@ -166,11 +169,11 @@
 class AgiEngine;
 class AgiBase;
 class IIgsSoundMgr;
+class MusicPlayer;
 
 struct IIgsExeInfo;
 
 class SoundMgr : public Audio::AudioStream {
-	AgiBase *_vm;
 
 public:
 	SoundMgr(AgiBase *agi, Audio::Mixer *pMixer);
@@ -196,15 +199,21 @@
 		return 22050;
 	}
 
+	int _endflag;
+	AgiBase *_vm;
+
 private:
 	Audio::Mixer *_mixer;
 	Audio::SoundHandle _soundHandle;
+
+	MusicPlayer *_musicPlayer;
+	MidiDriver *_midiDriver;
+
 	uint32 _sampleRate;
 
 	bool _playing;
 	ChannelInfo _chn[NUM_CHANNELS];
 	IIgsSoundMgr *_gsSound;
-	int _endflag;
 	int _playingSound;
 	uint8 _env;
 	bool _disabledMidi;

Added: scummvm/trunk/engines/agi/sound_midi.cpp
===================================================================
--- scummvm/trunk/engines/agi/sound_midi.cpp	                        (rev 0)
+++ scummvm/trunk/engines/agi/sound_midi.cpp	2010-06-15 10:34:45 UTC (rev 49751)
@@ -0,0 +1,340 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+// Code is based on:
+//
+// A very simple program, that converts an AGI-song into a MIDI-song.
+// Feel free to use it for anything.
+//
+// The default instrument is "piano" for all the channels, what gives
+// good results on most games. But I found, that some songs are interesting
+// with other instruments. If you want to experiment, modify the "instr"
+// array.
+//
+// Timing is not perfect, yet. It plays correct, when I use the
+// Gravis-Midiplayer, but the songs are too fast when I use playmidi on
+// Linux.
+// 
+// Original program developed by Jens. Christian Restemeier
+//
+
+// MIDI and digital music class
+
+#include "sound/audiostream.h"
+#include "sound/mididrv.h"
+#include "sound/midiparser.h"
+#include "common/config-manager.h"
+#include "common/file.h"
+#include "common/stream.h"
+
+#include "agi/agi.h"
+
+#include "agi/sound.h"
+#include "agi/sound_midi.h"
+
+#define SPEED_FACTOR 6
+
+namespace Agi {
+
+static uint32 convertSND2MIDI(byte *snddata, byte **data);
+
+MIDISound::MIDISound(uint8 *data, uint32 len, int resnum, SoundMgr &manager) : AgiSound(manager) {
+	_data = data; // Save the resource pointer
+	_len  = len;  // Save the resource's length
+	_type = READ_LE_UINT16(data); // Read sound resource's type
+	_isValid = (_type == AGI_SOUND_4CHN) && (_data != NULL) && (_len >= 2);
+
+	if (!_isValid) // Check for errors
+		warning("Error creating MIDI sound from resource %d (Type %d, length %d)", resnum, _type, len);
+}
+
+MusicPlayer::MusicPlayer(MidiDriver *driver, SoundMgr *manager) : _parser(0), _driver(driver), _isPlaying(false), _passThrough(false), _isGM(false), _manager(manager) {
+	memset(_channel, 0, sizeof(_channel));
+	memset(_channelVolume, 255, sizeof(_channelVolume));
+	_masterVolume = 0;
+	this->open();
+	_smfParser = MidiParser::createParser_SMF();
+	_midiMusicData = NULL;
+}
+
+MusicPlayer::~MusicPlayer() {
+	_driver->setTimerCallback(NULL, NULL);
+	stop();
+	this->close();
+	_smfParser->setMidiDriver(NULL);
+	delete _smfParser;
+	delete[] _midiMusicData;
+}
+
+void MusicPlayer::setChannelVolume(int channel) {
+	int newVolume = _channelVolume[channel] * _masterVolume / 255;
+	_channel[channel]->volume(newVolume);
+}
+
+void MusicPlayer::setVolume(int volume) {
+	Common::StackLock lock(_mutex);
+
+	volume = CLIP(volume, 0, 255);
+	if (_masterVolume == volume)
+		return;
+	_masterVolume = volume;
+
+	for (int i = 0; i < 16; ++i) {
+		if (_channel[i]) {
+			setChannelVolume(i);
+		}
+	}
+}
+
+int MusicPlayer::open() {
+	// Don't ever call open without first setting the output driver!
+	if (!_driver)
+		return 255;
+
+	int ret = _driver->open();
+	if (ret)
+		return ret;
+
+	_driver->setTimerCallback(this, &onTimer);
+	return 0;
+}
+
+void MusicPlayer::close() {
+	stop();
+	if (_driver)
+		_driver->close();
+	_driver = 0;
+}
+
+void MusicPlayer::send(uint32 b) {
+	if (_passThrough) {
+		_driver->send(b);
+		return;
+	}
+
+	byte channel = (byte)(b & 0x0F);
+	if ((b & 0xFFF0) == 0x07B0) {
+		// Adjust volume changes by master volume
+		byte volume = (byte)((b >> 16) & 0x7F);
+		_channelVolume[channel] = volume;
+		volume = volume * _masterVolume / 255;
+		b = (b & 0xFF00FFFF) | (volume << 16);
+	} else if ((b & 0xF0) == 0xC0 && !_isGM && !_nativeMT32) {
+		b = (b & 0xFFFF00FF) | MidiDriver::_mt32ToGm[(b >> 8) & 0xFF] << 8;
+	}
+	else if ((b & 0xFFF0) == 0x007BB0) {
+		//Only respond to All Notes Off if this channel
+		//has currently been allocated
+		if (_channel[b & 0x0F])
+			return;
+	}
+
+	if (!_channel[channel]) {
+		_channel[channel] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
+		// If a new channel is allocated during the playback, make sure
+		// its volume is correctly initialized.
+		if (_channel[channel])
+			setChannelVolume(channel);
+	}
+
+	if (_channel[channel])
+		_channel[channel]->send(b);
+}
+
+void MusicPlayer::metaEvent(byte type, byte *data, uint16 length) {
+
+	switch (type) {
+	case 0x2F:	// End of Track
+		stop();
+		break;
+	default:
+		//warning("Unhandled meta event: %02x", type);
+		break;
+	}
+}
+
+void MusicPlayer::onTimer(void *refCon) {
+	MusicPlayer *music = (MusicPlayer *)refCon;
+	Common::StackLock lock(music->_mutex);
+
+	if (music->_parser)
+		music->_parser->onTimer();
+}
+
+void MusicPlayer::playMIDI(MIDISound *track) {
+	stop();
+
+	_isGM = true;
+
+	// Convert AGI Sound data to MIDI
+	int midiMusicSize = convertSND2MIDI(track->_data, &_midiMusicData);
+
+	if (_smfParser->loadMusic(_midiMusicData, midiMusicSize)) {
+		MidiParser *parser = _smfParser;
+		parser->setTrack(0);
+		parser->setMidiDriver(this);
+		parser->setTimerRate(getBaseTempo());
+		parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1);
+
+		_parser = parser;
+
+		syncVolume();
+
+		_isPlaying = true;
+	}
+}
+
+void MusicPlayer::stop() {
+	Common::StackLock lock(_mutex);
+
+	if (!_isPlaying)
+		return;
+
+	_isPlaying = false;
+	if (_parser) {
+		_parser->unloadMusic();
+		_parser = NULL;
+	}
+
+	if (_manager->_endflag != -1)
+		_manager->_vm->setflag(_manager->_endflag, true);
+}
+
+void MusicPlayer::pause() {
+	setVolume(-1);
+	_isPlaying = false;
+}
+
+void MusicPlayer::resume() {
+	syncVolume();
+	_isPlaying = true;
+}
+
+void MusicPlayer::syncVolume() {
+	int volume = ConfMan.getInt("music_volume");
+	if (ConfMan.getBool("mute")) {
+		volume = -1;
+	}
+	setVolume(volume);
+}
+
+/* channel / intrument setup: */
+
+/* most songs are good with this: */
+unsigned char instr[] = {0, 0, 0};
+
+/* cool for sq2:
+unsigned char instr[] = {50, 51, 19};
+*/
+
+static void writeDelta(Common::MemoryWriteStreamDynamic *st, int32 delta) {
+	int32 i;
+
+	i = delta >> 21; if (i > 0) st->writeByte((i & 127) | 128); 
+	i = delta >> 14; if (i > 0) st->writeByte((i & 127) | 128);
+	i = delta >> 7;  if (i > 0) st->writeByte((i & 127) | 128);
+	st->writeByte(delta & 127);
+}
+
+static uint32 convertSND2MIDI(byte *snddata, byte **data) {
+	int32 lp, ep;
+	int n;
+	double ll;
+
+	Common::MemoryWriteStreamDynamic st;
+
+	ll = log10(pow(2.0, 1.0 / 12.0));
+
+	/* Header */
+	st.write("MThd", 4);
+	st.writeUint32BE(6);
+	st.writeUint16BE(1);    /* mode */
+	st.writeUint16BE(3);    /* number of tracks */
+	st.writeUint16BE(192);  /* ticks / quarter */
+
+	for (n = 0; n < 3; n++) {
+		uint16 start, end, pos;
+        
+		st.write("MTrk", 4);
+		lp = st.pos();
+		st.writeUint32BE(0);        /* chunklength */
+		writeDelta(&st, 0);       /* set instrument */
+		st.writeByte(0xc0 + n);
+		st.writeByte(instr[n]);
+		start = snddata[n * 2 + 0] | (snddata[n * 2 + 1] << 8);
+		end = ((snddata[n * 2 + 2] | (snddata[n * 2 + 3] << 8))) - 5;
+
+		for (pos = start; pos < end; pos += 5) {
+			uint16 freq,  dur;
+			dur = (snddata[pos + 0] | (snddata[pos + 1] << 8)) * SPEED_FACTOR;
+			freq = ((snddata[pos + 2] & 0x3F)  <<  4)  +  (snddata[pos + 3] & 0x0F);
+			if (snddata[pos + 2] > 0) {
+				double fr;
+				int note;
+				/* I don't know,  what frequency equals midi note 0 ... */
+				/* This moves the song 4 octaves down: */
+				fr = (log10(111860.0 / (double)freq) / ll) - 48; 
+				note = (int)floor(fr + 0.5);
+				if (note < 0) note = 0;
+				if (note > 127) note = 127;
+				/* note on */
+				writeDelta(&st, 0);
+				st.writeByte(144 + n);
+				st.writeByte(note);
+				st.writeByte(100);
+				/* note off */
+				writeDelta(&st, dur);
+				st.writeByte(128 + n);
+				st.writeByte(note);
+				st.writeByte(0);
+			} else {
+				/* note on */
+				writeDelta(&st, 0);
+				st.writeByte(144 + n);
+				st.writeByte(0);
+				st.writeByte(0);
+				/* note off */
+				writeDelta(&st, dur);
+				st.writeByte(128 + n);
+				st.writeByte(0);
+				st.writeByte(0);
+			}
+		}       
+		writeDelta(&st, 0);
+		st.writeByte(0xff);
+		st.writeByte(0x2f);
+		st.writeByte(0x0);
+		ep = st.pos();
+		st.seek(lp, SEEK_SET);
+		st.writeUint32BE((ep - lp) - 4);
+		st.seek(ep, SEEK_SET);
+	}
+
+	*data = st.getData();
+
+	return st.pos();
+}
+
+} // End of namespace Agi


Property changes on: scummvm/trunk/engines/agi/sound_midi.cpp
___________________________________________________________________
Added: svn:executable
   + *
Added: svn:mime-type
   + text/plain
Added: svn:keywords
   + Date Rev Author URL Id
Added: svn:eol-style
   + native

Added: scummvm/trunk/engines/agi/sound_midi.h
===================================================================
--- scummvm/trunk/engines/agi/sound_midi.h	                        (rev 0)
+++ scummvm/trunk/engines/agi/sound_midi.h	2010-06-15 10:34:45 UTC (rev 49751)
@@ -0,0 +1,113 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+// Music class
+
+#ifndef AGI_SOUND_MIDI_H
+#define AGI_SOUND_MIDI_H
+
+#include "sound/mididrv.h"
+#include "sound/midiparser.h"
+#include "common/mutex.h"
+
+namespace Agi {
+
+class MIDISound : public AgiSound {
+public:
+	MIDISound(uint8 *data, uint32 len, int resnum, SoundMgr &manager);
+	~MIDISound() { free(_data); }
+	virtual uint16 type() { return _type; }
+	uint8 *_data; ///< Raw sound resource data
+	uint32 _len;  ///< Length of the raw sound resource
+
+protected:
+	uint16 _type; ///< Sound resource type
+};
+
+class MusicPlayer : public MidiDriver {
+public:
+	MusicPlayer(MidiDriver *driver, SoundMgr *manager);
+	~MusicPlayer();
+
+	bool isPlaying() { return _isPlaying; }
+	void setPlaying(bool playing) { _isPlaying = playing; }
+
+	void setVolume(int volume);
+	int getVolume() { return _masterVolume; }
+	void syncVolume();
+
+	void setNativeMT32(bool b) { _nativeMT32 = b; }
+	bool hasNativeMT32() { return _nativeMT32; }
+	void playMIDI(MIDISound *track);
+	void stop();
+	void pause();
+	void resume();
+	void setLoop(bool loop) { _looping = loop; }
+	void setPassThrough(bool b) { _passThrough = b; }
+
+	void setGM(bool isGM) { _isGM = isGM; }
+
+	// MidiDriver interface implementation
+	int open();
+	void close();
+	void send(uint32 b);
+
+	void metaEvent(byte type, byte *data, uint16 length);
+
+	void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { }
+	uint32 getBaseTempo() { return _driver ? _driver->getBaseTempo() : 0; }
+
+	// Channel allocation functions
+	MidiChannel *allocateChannel() { return 0; }
+	MidiChannel *getPercussionChannel() { return 0; }
+
+	MidiParser *_parser;
+	Common::Mutex _mutex;
+
+protected:
+
+	static void onTimer(void *data);
+	void setChannelVolume(int channel);
+
+	MidiChannel *_channel[16];
+	MidiDriver *_driver;
+	MidiParser *_smfParser;
+	byte _channelVolume[16];
+	bool _nativeMT32;
+	bool _isGM;
+	bool _passThrough;
+
+	bool _isPlaying;
+	bool _looping;
+	byte _masterVolume;
+
+	byte *_midiMusicData;
+
+	SoundMgr *_manager;
+};
+
+} // End of namespace Agi
+
+#endif


Property changes on: scummvm/trunk/engines/agi/sound_midi.h
___________________________________________________________________
Added: svn:executable
   + *
Added: svn:mime-type
   + text/plain
Added: svn:keywords
   + Date Rev Author URL Id
Added: svn:eol-style
   + native


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list