[Scummvm-cvs-logs] SF.net SVN: scummvm:[41506] scummvm/trunk/engines/cruise

dreammaster at users.sourceforge.net dreammaster at users.sourceforge.net
Sun Jun 14 05:39:30 CEST 2009


Revision: 41506
          http://scummvm.svn.sourceforge.net/scummvm/?rev=41506&view=rev
Author:   dreammaster
Date:     2009-06-14 03:39:30 +0000 (Sun, 14 Jun 2009)

Log Message:
-----------
Beginnings of music support for Cruise, based on the cine engine sound code (note that the music played isn't yet correct, though)

Modified Paths:
--------------
    scummvm/trunk/engines/cruise/cruise.cpp
    scummvm/trunk/engines/cruise/cruise.h
    scummvm/trunk/engines/cruise/function.cpp
    scummvm/trunk/engines/cruise/menu.cpp
    scummvm/trunk/engines/cruise/saveload.cpp
    scummvm/trunk/engines/cruise/sound.cpp
    scummvm/trunk/engines/cruise/sound.h

Modified: scummvm/trunk/engines/cruise/cruise.cpp
===================================================================
--- scummvm/trunk/engines/cruise/cruise.cpp	2009-06-14 00:30:59 UTC (rev 41505)
+++ scummvm/trunk/engines/cruise/cruise.cpp	2009-06-14 03:39:30 UTC (rev 41506)
@@ -52,26 +52,24 @@
 	_currentVolumeFile = new Common::File();
 #endif
 
-	Common::addDebugChannel(kCruiseDebugScript, "Script",
-	                             "Script debug level");
+	Common::addDebugChannel(kCruiseDebugScript, "scripts", "Scripts debug level");
+	Common::addDebugChannel(kCruiseDebugSound, "sound", "Sound debug level");
 
 	// Setup mixer
 	_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType,
-	                              ConfMan.getInt("sfx_volume"));
+			ConfMan.getInt("sfx_volume"));
 	_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType,
-	                              ConfMan.getInt("music_volume"));
+			ConfMan.getInt("music_volume"));
 
 	_vm = this;
 	_debugger = new Debugger();
-	_music = new MusicPlayer();
-	_sound = new SoundPlayer();
+	_sound = new PCSound(_mixer, this);
 
 	syst->getEventManager()->registerRandomSource(_rnd, "cruise");
 }
 
 CruiseEngine::~CruiseEngine() {
 	delete _debugger;
-	delete _music;
 	delete _sound;
 
 	freeSystem();

Modified: scummvm/trunk/engines/cruise/cruise.h
===================================================================
--- scummvm/trunk/engines/cruise/cruise.h	2009-06-14 00:30:59 UTC (rev 41505)
+++ scummvm/trunk/engines/cruise/cruise.h	2009-06-14 03:39:30 UTC (rev 41506)
@@ -57,8 +57,7 @@
 	bool _preLoad;
 	Debugger *_debugger;
 	MidiDriver *_driver;
-	MusicPlayer *_music;
-	SoundPlayer *_sound;
+	PCSound *_sound;
 	bool _mt32, _adlib;
 	int _musicVolume;
 	Common::StringList _langStrings;
@@ -90,8 +89,7 @@
 	uint32 getFeatures() const;
 	Common::Language getLanguage() const;
 	Common::Platform getPlatform() const;
-	MusicPlayer &music() { return *_music; }
-	SoundPlayer &sound() { return *_sound; }
+	PCSound &sound() { return *_sound; }
 	bool mt32() const { return _mt32; }
 	bool adlib() const { return _adlib; }
 	virtual GUI::Debugger *getDebugger() { return _debugger; }
@@ -128,7 +126,8 @@
 };
 
 enum {
-	kCruiseDebugScript = 1 << 0
+	kCruiseDebugScript = 1 << 0,
+	kCruiseDebugSound = 1 << 1
 };
 
 enum {

Modified: scummvm/trunk/engines/cruise/function.cpp
===================================================================
--- scummvm/trunk/engines/cruise/function.cpp	2009-06-14 00:30:59 UTC (rev 41505)
+++ scummvm/trunk/engines/cruise/function.cpp	2009-06-14 03:39:30 UTC (rev 41506)
@@ -1354,22 +1354,22 @@
 
 	strcpy(buffer, ptr);
 	strToUpper(buffer);
-	_vm->music().loadSong(buffer);
+	_vm->sound().loadMusic(buffer);
 
 	changeCursor(CURSOR_NORMAL);
 	return 0;
 }
 
 int16 Op_PlaySong(void) {
-	if (_vm->music().songLoaded() && !_vm->music().songPlayed())
-		_vm->music().startSong();
+	if (_vm->sound().songLoaded() && !_vm->sound().songPlayed())
+		_vm->sound().playMusic();
 
 	return 0;
 }
 
 int16 Op_StopSong(void) {
-	if (_vm->music().isPlaying())
-		_vm->music().stop();
+	if (_vm->sound().isPlaying())
+		_vm->sound().stopMusic();
 
 	return 0;
 }
@@ -1383,12 +1383,12 @@
 int16 Op_SongSize(void) {
 	int size, oldSize;
 
-	if (_vm->music().songLoaded()) {
-		byte *pSize = _vm->music().songData() + 470;
-		oldSize = *pSize;
+	if (_vm->sound().songLoaded()) {
+		oldSize = _vm->sound().numOrders();
+		
 		size = popVar();
 		if ((size >= 1) && (size < 128))
-			*pSize = size;
+			_vm->sound().setNumOrders(size);
 	} else
 		oldSize = 0;
 
@@ -1399,35 +1399,34 @@
 	int value = popVar();
 	int offset = popVar();
 
-	if (_vm->music().songLoaded()) {
-		byte *pData = _vm->music().songData();
-		*(pData + 472 + offset) = (byte)value;
+	if (_vm->sound().songLoaded()) {
+		_vm->sound().setPattern(offset, value);
 	}
 
 	return 0;
 }
 
 int16 Op_FadeSong(void) {
-	_vm->music().fadeSong();
+	_vm->sound().fadeSong();
 
 	return 0;
 }
 
 int16 Op_FreeSong(void) {
-	_vm->music().stop();
-	_vm->music().removeSong();
+	_vm->sound().stopMusic();
+	_vm->sound().removeMusic();
 	return 0;
 }
 
 int16 Op_SongLoop(void) {
-	bool oldLooping = _vm->music().looping();
-	_vm->music().setLoop(popVar() != 0);
+	bool oldLooping = _vm->sound().musicLooping();
+	_vm->sound().musicLoop(popVar() != 0);
 
 	return oldLooping;
 }
 
 int16 Op_SongPlayed(void) {
-	return _vm->music().songPlayed();
+	return _vm->sound().songPlayed();
 }
 
 void setVar49Value(int value) {
@@ -1632,7 +1631,7 @@
 }
 
 int16 Op_SetVolume(void) {
-	int oldVolume = _vm->music().getVolume() >> 2;
+	int oldVolume = _vm->sound().getVolume() >> 2;
 	int newVolume = popVar();
 
 	// TODO: The game seems to expect the volume will only range from 0 - 63, so for now
@@ -1641,7 +1640,7 @@
 	if (newVolume > 63) newVolume = 63;
 	if (newVolume >= 0) {
 		int volume = 63 - newVolume;
-		_vm->music().setVolume(volume << 2);
+		_vm->sound().setVolume(volume << 2);
 	}
 
 	return oldVolume >> 2;

Modified: scummvm/trunk/engines/cruise/menu.cpp
===================================================================
--- scummvm/trunk/engines/cruise/menu.cpp	2009-06-14 00:30:59 UTC (rev 41505)
+++ scummvm/trunk/engines/cruise/menu.cpp	2009-06-14 03:39:30 UTC (rev 41506)
@@ -207,7 +207,7 @@
 
 	if (playerMenuEnabled && displayOn) {
 		if (remdo) {
-			_vm->music().removeSong();
+			_vm->sound().stopMusic();
 			freeStuff2();
 		}
 		/*

Modified: scummvm/trunk/engines/cruise/saveload.cpp
===================================================================
--- scummvm/trunk/engines/cruise/saveload.cpp	2009-06-14 00:30:59 UTC (rev 41505)
+++ scummvm/trunk/engines/cruise/saveload.cpp	2009-06-14 03:39:30 UTC (rev 41506)
@@ -610,7 +610,7 @@
 
 static void DoSync(Common::Serializer &s) {
 	syncBasicInfo(s);
-	_vm->music().doSync(s);
+	_vm->sound().doSync(s);
 
 	syncPalette(s, newPal);
 	syncPalette(s, workpal);

Modified: scummvm/trunk/engines/cruise/sound.cpp
===================================================================
--- scummvm/trunk/engines/cruise/sound.cpp	2009-06-14 00:30:59 UTC (rev 41505)
+++ scummvm/trunk/engines/cruise/sound.cpp	2009-06-14 03:39:30 UTC (rev 41506)
@@ -30,67 +30,210 @@
 #include "cruise/sound.h"
 #include "cruise/volume.h"
 
+#include "sound/audiostream.h"
+#include "sound/fmopl.h"
+#include "sound/mods/soundfx.h"
+
 namespace Cruise {
 
-MusicPlayer::MusicPlayer(): _looping(false), _isPlaying(false), _songPlayed(false) {
-	_songPointer = NULL;
-	_masterVolume = 0;
-}
+class PCSoundDriver {
+public:
+	typedef void (*UpdateCallback)(void *);
 
-MusicPlayer::~MusicPlayer() {
-	stop();
-	if (_songPointer != NULL)
-		free(_songPointer);
-}
+	virtual ~PCSoundDriver() {}
 
-void MusicPlayer::setVolume(int volume) {
-	_vm->_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, volume);
+	virtual void setupChannel(int channel, const byte *data, int instrument, int volume) = 0;
+	virtual void setChannelFrequency(int channel, int frequency) = 0;
+	virtual void stopChannel(int channel) = 0;
+	virtual void playSample(const byte *data, int size, int channel, int volume) = 0;
+	virtual void stopAll() = 0;
+	virtual const char *getInstrumentExtension() const { return ""; }
 
-	if (_masterVolume == volume)
-		return;
+	void setUpdateCallback(UpdateCallback upCb, void *ref);
+	void resetChannel(int channel);
+	void findNote(int freq, int *note, int *oct) const;
 
-	_masterVolume = volume;
-}
+protected:
+	UpdateCallback _upCb;
+	void *_upRef;
 
-void MusicPlayer::stop() {
-	_isPlaying = false;
-	_songPlayed = songLoaded();
-}
+	static const int _noteTable[];
+	static const int _noteTableCount;
+};
 
-void MusicPlayer::pause() {
-	setVolume(-1);
-	_isPlaying = false;
-}
+const int PCSoundDriver::_noteTable[] = {
+	0xEEE, 0xE17, 0xD4D, 0xC8C, 0xBD9, 0xB2F, 0xA8E, 0x9F7,
+	0x967, 0x8E0, 0x861, 0x7E8, 0x777, 0x70B, 0x6A6, 0x647,
+	0x5EC, 0x597, 0x547, 0x4FB, 0x4B3, 0x470, 0x430, 0x3F4,
+	0x3BB, 0x385, 0x353, 0x323, 0x2F6, 0x2CB, 0x2A3, 0x27D,
+	0x259, 0x238, 0x218, 0x1FA, 0x1DD, 0x1C2, 0x1A9, 0x191,
+	0x17B, 0x165, 0x151, 0x13E, 0x12C, 0x11C, 0x10C, 0x0FD,
+	0x0EE, 0x0E1, 0x0D4, 0x0C8, 0x0BD, 0x0B2, 0x0A8, 0x09F,
+	0x096, 0x08E, 0x086, 0x07E, 0x077, 0x070, 0x06A, 0x064,
+	0x05E, 0x059, 0x054, 0x04F, 0x04B, 0x047, 0x043, 0x03F,
+	0x03B, 0x038, 0x035, 0x032, 0x02F, 0x02C, 0x02A, 0x027,
+	0x025, 0x023, 0x021, 0x01F, 0x01D, 0x01C, 0x01A, 0x019,
+	0x017, 0x016, 0x015, 0x013, 0x012, 0x011, 0x010, 0x00F
+};
 
-void MusicPlayer::resume() {
-	setVolume(_masterVolume);
-	_isPlaying = true;
-	_songPlayed = false;
-}
+const int PCSoundDriver::_noteTableCount = ARRAYSIZE(_noteTable);
 
-void MusicPlayer::doSync(Common::Serializer &s) {
-	// synchronise current music name, if any, state, and position
-	s.syncBytes((byte *)_musicName, 33);
-	uint16 v = (uint16)songLoaded();
-	s.syncAsSint16LE(v);
-	s.syncAsSint16LE(_songPlayed);
-	s.syncAsSint16LE(_looping);
-}
+struct AdlibRegisterSoundInstrument {
+	uint8 vibrato;
+	uint8 attackDecay;
+	uint8 sustainRelease;
+	uint8 feedbackStrength;
+	uint8 keyScaling;
+	uint8 outputLevel;
+	uint8 freqMod;
+};
 
-void MusicPlayer::loadSong(const char *name) {
-	char tempName[20], baseName[20];
-	uint8 *sampleData;
+struct AdlibSoundInstrument {
+	byte mode;
+	byte channel;
+	AdlibRegisterSoundInstrument regMod;
+	AdlibRegisterSoundInstrument regCar;
+	byte waveSelectMod;
+	byte waveSelectCar;
+	byte amDepth;
+};
 
-	if (songLoaded())
-		removeSong();
+class AdlibSoundDriver : public PCSoundDriver, Audio::AudioStream {
+public:
+	AdlibSoundDriver(Audio::Mixer *mixer);
+	virtual ~AdlibSoundDriver();
 
+	// PCSoundDriver interface
+	virtual void setupChannel(int channel, const byte *data, int instrument, int volume);
+	virtual void stopChannel(int channel);
+	virtual void stopAll();
+
+	// AudioStream interface
+	virtual int readBuffer(int16 *buffer, const int numSamples);
+	virtual bool isStereo() const { return false; }
+	virtual bool endOfData() const { return false; }
+	virtual int getRate() const { return _sampleRate; }
+
+	void initCard();
+	void update(int16 *buf, int len);
+	void setupInstrument(const byte *data, int channel);
+	void loadRegisterInstrument(const byte *data, AdlibRegisterSoundInstrument *reg);
+	virtual void loadInstrument(const byte *data, AdlibSoundInstrument *asi) = 0;
+
+protected:
+	FM_OPL *_opl;
+	int _sampleRate;
+	Audio::Mixer *_mixer;
+	Audio::SoundHandle _soundHandle;
+
+	byte _vibrato;
+	int _channelsVolumeTable[4];
+	AdlibSoundInstrument _instrumentsTable[4];
+
+	static const int _freqTable[];
+	static const int _freqTableCount;
+	static const int _operatorsTable[];
+	static const int _operatorsTableCount;
+	static const int _voiceOperatorsTable[];
+	static const int _voiceOperatorsTableCount;
+};
+
+const int AdlibSoundDriver::_freqTable[] = {
+	0x157, 0x16C, 0x181, 0x198, 0x1B1, 0x1CB,
+	0x1E6, 0x203, 0x222, 0x243, 0x266, 0x28A
+};
+
+const int AdlibSoundDriver::_freqTableCount = ARRAYSIZE(_freqTable);
+
+const int AdlibSoundDriver::_operatorsTable[] = {
+	0, 1, 2, 3, 4, 5, 8, 9, 10, 11, 12, 13,	16, 17, 18, 19, 20, 21
+};
+
+const int AdlibSoundDriver::_operatorsTableCount = ARRAYSIZE(_operatorsTable);
+
+const int AdlibSoundDriver::_voiceOperatorsTable[] = {
+	0, 3, 1, 4, 2, 5, 6, 9, 7, 10, 8, 11, 12, 15, 16, 16, 14, 14, 17, 17, 13, 13
+};
+
+const int AdlibSoundDriver::_voiceOperatorsTableCount = ARRAYSIZE(_voiceOperatorsTable);
+
+// Future Wars Adlib driver
+class AdlibSoundDriverINS : public AdlibSoundDriver {
+public:
+	AdlibSoundDriverINS(Audio::Mixer *mixer) : AdlibSoundDriver(mixer) {}
+	virtual const char *getInstrumentExtension() const { return ".INS"; }
+	virtual void loadInstrument(const byte *data, AdlibSoundInstrument *asi);
+	virtual void setChannelFrequency(int channel, int frequency);
+	virtual void playSample(const byte *data, int size, int channel, int volume);
+};
+
+// Operation Stealth Adlib driver
+class AdlibSoundDriverADL : public AdlibSoundDriver {
+public:
+	AdlibSoundDriverADL(Audio::Mixer *mixer) : AdlibSoundDriver(mixer) {}
+	virtual const char *getInstrumentExtension() const { return ".ADL"; }
+	virtual void loadInstrument(const byte *data, AdlibSoundInstrument *asi);
+	virtual void setChannelFrequency(int channel, int frequency);
+	virtual void playSample(const byte *data, int size, int channel, int volume);
+};
+
+class PCSoundFxPlayer {
+private:
+	enum {
+		NUM_INSTRUMENTS = 15,
+		NUM_CHANNELS = 4
+	};
+
+	void update();
+	void handleEvents();
+	void handlePattern(int channel, const byte *patternData);
+
+	char _musicName[33];
+	bool _playing;
+	bool _songPlayed;
+	int _currentPos;
+	int _currentOrder;
+	int _numOrders;
+	int _eventsDelay;
+	bool _looping;
+	int _fadeOutCounter;
+	int _updateTicksCounter;
+	int _instrumentsChannelTable[NUM_CHANNELS];
+	byte *_sfxData;
+	byte *_instrumentsData[NUM_INSTRUMENTS];
+	PCSoundDriver *_driver;
+
+public:
+	PCSoundFxPlayer(PCSoundDriver *driver);
+	~PCSoundFxPlayer();
+
+	bool load(const char *song);
+	void play();
+	void stop();
+	void unload();
+	void fadeOut();
+	void doSync(Common::Serializer &s);
+
+	static void updateCallback(void *ref);
+
+	bool songLoaded() const { return _sfxData != NULL; }
+	bool songPlayed() const { return _songPlayed; }
+	bool playing() const { return _playing; }
+	uint8 numOrders() const { assert(_sfxData); return _sfxData[470]; }
+	void setNumOrders(uint8 v) { assert(_sfxData); _sfxData[470] = v; }
+	void setPattern(int offset, uint8 value) { assert(_sfxData); _sfxData[472 + offset] = value; }
+	bool looping() const { return _looping; }
+	void setLooping(bool v) { _looping = v; }
+};
+
+byte *readBundleSoundFile(const char *name) {
 	// Load the correct file
 	int fileIdx = findFileInDisks(name);
-	if (fileIdx < 0) return;
+	if (fileIdx < 0) return NULL;
 
 	int unpackedSize = volumePtrToFileDescriptor[fileIdx].extSize + 2;
-	_songPointer = (byte *)malloc(unpackedSize);
-	assert(_songPointer);
+	byte *data = (byte *)malloc(unpackedSize);
+	assert(data);
 
 	if (volumePtrToFileDescriptor[fileIdx].size + 2 != unpackedSize) {
 		uint8 *packedBuffer = (uint8 *)mallocAndZero(volumePtrToFileDescriptor[fileIdx].size + 2);
@@ -99,130 +242,652 @@
 
 		uint32 realUnpackedSize = READ_BE_UINT32(packedBuffer + volumePtrToFileDescriptor[fileIdx].size - 4);
 
-		delphineUnpack(_songPointer, packedBuffer, volumePtrToFileDescriptor[fileIdx].size);
-		_songSize = realUnpackedSize;
+		delphineUnpack(data, packedBuffer, volumePtrToFileDescriptor[fileIdx].size);
 
 		free(packedBuffer);
 	} else {
-		loadPackedFileToMem(fileIdx, _songPointer);
-		_songSize = unpackedSize;
+		loadPackedFileToMem(fileIdx, data);
 	}
 
-	strcpy(_musicName, name);
+	return data;
+}
 
-	// Get the details of the song
-	// TODO: Figure this out for sure for use in actually playing song
-	//int size = *(_songPointer + 470);
-	//int speed = 244 - *(_songPointer + 471);
-	//int musicSpeed = (speed * 100) / 1060;
 
+void PCSoundDriver::setUpdateCallback(UpdateCallback upCb, void *ref) {
+	_upCb = upCb;
+	_upRef = ref;
+}
 
-	// Get the file without the extension
-	strcpy(baseName, name);
-	char *p = strchr(baseName, '.');
-	if (p)
-		*p = '\0';
+void PCSoundDriver::findNote(int freq, int *note, int *oct) const {
+	*note = _noteTableCount - 1;
+	for (int i = 0; i < _noteTableCount; ++i) {
+		if (_noteTable[i] <= freq) {
+			*note = i;
+			break;
+		}
+	}
+	*oct = *note / 12;
+}
 
-	// Get the instruments states file
-	strcpy(tempName, baseName);
-	strcat(tempName, ".IST");
+void PCSoundDriver::resetChannel(int channel) {
+	stopChannel(channel);
+	stopAll();
+}
 
-	fileIdx = findFileInDisks(tempName);
-	if (fileIdx >= 0) {
-		// TODO: Figure out instrument state usage
-		uint8 instrumentState[15];
-		loadPackedFileToMem(fileIdx, instrumentState);
+AdlibSoundDriver::AdlibSoundDriver(Audio::Mixer *mixer)
+	: _mixer(mixer) {
+	_sampleRate = _mixer->getOutputRate();
+	_opl = makeAdlibOPL(_sampleRate);
+	memset(_channelsVolumeTable, 0, sizeof(_channelsVolumeTable));
+	memset(_instrumentsTable, 0, sizeof(_instrumentsTable));
+	initCard();
+	_mixer->playInputStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, false, true);
+}
+
+AdlibSoundDriver::~AdlibSoundDriver() {
+	_mixer->stopHandle(_soundHandle);
+	OPLDestroy(_opl);
+}
+
+void AdlibSoundDriver::setupChannel(int channel, const byte *data, int instrument, int volume) {
+	assert(channel < 4);
+	if (data) {
+		if (volume > 80) {
+			volume = 80;
+		} else if (volume < 0) {
+			volume = 0;
+		}
+		volume += volume / 4;
+		if (volume > 127) {
+			volume = 127;
+		}
+		_channelsVolumeTable[channel] = volume;
+		setupInstrument(data, channel);
 	}
+}
 
-	for (int instrumentCtr = 0; instrumentCtr < 15; ++instrumentCtr) {
-		if (_vm->mt32()) {
-			// Handle loading Roland instrument data
-			strcpy(tempName, baseName);
-			strcat(tempName, ".H32");
+void AdlibSoundDriver::stopChannel(int channel) {
+	assert(channel < 4);
+	AdlibSoundInstrument *ins = &_instrumentsTable[channel];
+	if (ins->mode != 0 && ins->channel == 6) {
+		channel = 6;
+	}
+	if (ins->mode == 0 || channel == 6) {
+		OPLWriteReg(_opl, 0xB0 | channel, 0);
+	}
+	if (ins->mode != 0) {
+		_vibrato &= ~(1 << (10 - ins->channel));
+		OPLWriteReg(_opl, 0xBD, _vibrato);
+	}
+}
 
-			sampleData = loadInstrument(tempName, instrumentCtr);
-			if (sampleData) {
-				int v = *sampleData;
-				if ((v >= 128) && (v < 192))
-					patchMidi(0x80000L + (instrumentCtr * 512), sampleData + 1, 254);
+void AdlibSoundDriver::stopAll() {
+	int i;
+	for (i = 0; i < 18; ++i) {
+		OPLWriteReg(_opl, 0x40 | _operatorsTable[i], 63);
+	}
+	for (i = 0; i < 9; ++i) {
+		OPLWriteReg(_opl, 0xB0 | i, 0);
+	}
+	OPLWriteReg(_opl, 0xBD, 0);
+}
 
-				// TODO: Currently I'm freeing the instrument data immediately. The original
-				// holds onto the sample data, so it may actually still be needed
-				free(sampleData);
-			}
-		} else if (_vm->adlib()) {
-			// Handle loading Adlib instrument data
-			strcpy(tempName, baseName);
-			strcat(tempName, ".ADL");
+int AdlibSoundDriver::readBuffer(int16 *buffer, const int numSamples) {
+	update(buffer, numSamples);
+	return numSamples;
+}
 
-			fileIdx = findFileInDisks(tempName);
-			if (fileIdx >= 0) {
-				sampleData = (byte *)malloc(volumePtrToFileDescriptor[fileIdx].extSize + 2);
-				assert(sampleData);
-				loadPackedFileToMem(fileIdx, sampleData);
+void AdlibSoundDriver::initCard() {
+	_vibrato = 0x20;
+	OPLWriteReg(_opl, 0xBD, _vibrato);
+	OPLWriteReg(_opl, 0x08, 0x40);
 
-				// TODO: Make use of sample data
+	static const int oplRegs[] = { 0x40, 0x60, 0x80, 0x20, 0xE0 };
 
-				free(sampleData);
+	for (int i = 0; i < 9; ++i) {
+		OPLWriteReg(_opl, 0xB0 | i, 0);
+	}
+	for (int i = 0; i < 9; ++i) {
+		OPLWriteReg(_opl, 0xC0 | i, 0);
+	}
+
+	for (int j = 0; j < 5; j++) {
+		for (int i = 0; i < 18; ++i) {
+			OPLWriteReg(_opl, oplRegs[j] | _operatorsTable[i], 0);
+		}
+	}
+
+	OPLWriteReg(_opl, 1, 0x20);
+	OPLWriteReg(_opl, 1, 0);
+}
+
+void AdlibSoundDriver::update(int16 *buf, int len) {
+	static int samplesLeft = 0;
+	while (len != 0) {
+		int count = samplesLeft;
+		if (count > len) {
+			count = len;
+		}
+		samplesLeft -= count;
+		len -= count;
+		YM3812UpdateOne(_opl, buf, count);
+		if (samplesLeft == 0) {
+			if (_upCb) {
+				(*_upCb)(_upRef);
 			}
+			samplesLeft = _sampleRate / 50;
 		}
+		buf += count;
 	}
+}
 
-	_songPlayed = false;
-	_isPlaying = false;
+void AdlibSoundDriver::setupInstrument(const byte *data, int channel) {
+	assert(channel < 4);
+	AdlibSoundInstrument *ins = &_instrumentsTable[channel];
+	loadInstrument(data, ins);
+
+	int mod, car, tmp;
+	const AdlibRegisterSoundInstrument *reg;
+
+	if (ins->mode != 0)  {
+		mod = _operatorsTable[_voiceOperatorsTable[2 * ins->channel + 0]];
+		car = _operatorsTable[_voiceOperatorsTable[2 * ins->channel + 1]];
+	} else {
+		mod = _operatorsTable[_voiceOperatorsTable[2 * channel + 0]];
+		car = _operatorsTable[_voiceOperatorsTable[2 * channel + 1]];
+	}
+
+	if (ins->mode == 0 || ins->channel == 6) {
+		reg = &ins->regMod;
+		OPLWriteReg(_opl, 0x20 | mod, reg->vibrato);
+		if (reg->freqMod) {
+			tmp = reg->outputLevel & 0x3F;
+		} else {
+			tmp = (63 - (reg->outputLevel & 0x3F)) * _channelsVolumeTable[channel];
+			tmp = 63 - (2 * tmp + 127) / (2 * 127);
+		}
+		OPLWriteReg(_opl, 0x40 | mod, tmp | (reg->keyScaling << 6));
+		OPLWriteReg(_opl, 0x60 | mod, reg->attackDecay);
+		OPLWriteReg(_opl, 0x80 | mod, reg->sustainRelease);
+		if (ins->mode != 0) {
+			OPLWriteReg(_opl, 0xC0 | ins->channel, reg->feedbackStrength);
+		} else {
+			OPLWriteReg(_opl, 0xC0 | channel, reg->feedbackStrength);
+		}
+		OPLWriteReg(_opl, 0xE0 | mod, ins->waveSelectMod);
+	}
+
+	reg = &ins->regCar;
+	OPLWriteReg(_opl, 0x20 | car, reg->vibrato);
+	tmp = (63 - (reg->outputLevel & 0x3F)) * _channelsVolumeTable[channel];
+	tmp = 63 - (2 * tmp + 127) / (2 * 127);
+	OPLWriteReg(_opl, 0x40 | car, tmp | (reg->keyScaling << 6));
+	OPLWriteReg(_opl, 0x60 | car, reg->attackDecay);
+	OPLWriteReg(_opl, 0x80 | car, reg->sustainRelease);
+	OPLWriteReg(_opl, 0xE0 | car, ins->waveSelectCar);
 }
 
-void MusicPlayer::startSong() {
-	if (songLoaded()) {
-		// Start playing song here
+void AdlibSoundDriver::loadRegisterInstrument(const byte *data, AdlibRegisterSoundInstrument *reg) {
+	reg->vibrato = 0;
+	if (READ_LE_UINT16(data + 18)) { // amplitude vibrato
+		reg->vibrato |= 0x80;
 	}
+	if (READ_LE_UINT16(data + 20)) { // frequency vibrato
+		reg->vibrato |= 0x40;
+	}
+	if (READ_LE_UINT16(data + 10)) { // sustaining sound
+		reg->vibrato |= 0x20;
+	}
+	if (READ_LE_UINT16(data + 22)) { // envelope scaling
+		reg->vibrato |= 0x10;
+	}
+	reg->vibrato |= READ_LE_UINT16(data + 2) & 0xF; // frequency multiplier
+
+	reg->attackDecay = READ_LE_UINT16(data + 6) << 4; // attack rate
+	reg->attackDecay |= READ_LE_UINT16(data + 12) & 0xF; // decay rate
+
+	reg->sustainRelease = READ_LE_UINT16(data + 8) << 4; // sustain level
+	reg->sustainRelease |= READ_LE_UINT16(data + 14) & 0xF; // release rate
+
+	reg->feedbackStrength = READ_LE_UINT16(data + 4) << 1; // feedback
+	if (READ_LE_UINT16(data + 24) == 0) { // frequency modulation
+		reg->feedbackStrength |= 1;
+	}
+
+	reg->keyScaling = READ_LE_UINT16(data);
+	reg->outputLevel = READ_LE_UINT16(data + 16);
+	reg->freqMod = READ_LE_UINT16(data + 24);
 }
 
-void MusicPlayer::removeSong() {
-	if (isPlaying())
+void AdlibSoundDriverINS::loadInstrument(const byte *data, AdlibSoundInstrument *asi) {
+	asi->mode = *data++;
+	asi->channel = *data++;
+	loadRegisterInstrument(data, &asi->regMod); data += 26;
+	loadRegisterInstrument(data, &asi->regCar); data += 26;
+	asi->waveSelectMod = data[0] & 3; data += 2;
+	asi->waveSelectCar = data[0] & 3; data += 2;
+	asi->amDepth = data[0]; data += 2;
+}
+
+void AdlibSoundDriverINS::setChannelFrequency(int channel, int frequency) {
+	assert(channel < 4);
+	AdlibSoundInstrument *ins = &_instrumentsTable[channel];
+	if (ins->mode != 0 && ins->channel == 6) {
+		channel = 6;
+	}
+	if (ins->mode == 0 || ins->channel == 6) {
+		int freq, note, oct;
+		findNote(frequency, &note, &oct);
+		if (channel == 6) {
+			note %= 12;
+		}
+		freq = _freqTable[note % 12];
+		OPLWriteReg(_opl, 0xA0 | channel, freq);
+		freq = ((note / 12) << 2) | ((freq & 0x300) >> 8);
+		if (ins->mode == 0) {
+			freq |= 0x20;
+		}
+		OPLWriteReg(_opl, 0xB0 | channel, freq);
+	}
+	if (ins->mode != 0) {
+		_vibrato |= 1 << (10 - ins->channel);
+		OPLWriteReg(_opl, 0xBD, _vibrato);
+	}
+}
+
+void AdlibSoundDriverINS::playSample(const byte *data, int size, int channel, int volume) {
+	assert(channel < 4);
+	_channelsVolumeTable[channel] = 127;
+	resetChannel(channel);
+	setupInstrument(data + 257, channel);
+	AdlibSoundInstrument *ins = &_instrumentsTable[channel];
+	if (ins->mode != 0 && ins->channel == 6) {
+		channel = 6;
+	}
+	if (ins->mode == 0 || channel == 6) {
+		uint16 note = 12;
+		int freq = _freqTable[note % 12];
+		OPLWriteReg(_opl, 0xA0 | channel, freq);
+		freq = ((note / 12) << 2) | ((freq & 0x300) >> 8);
+		if (ins->mode == 0) {
+			freq |= 0x20;
+		}
+		OPLWriteReg(_opl, 0xB0 | channel, freq);
+	}
+	if (ins->mode != 0) {
+		_vibrato |= 1 << (10 - ins->channel);
+		OPLWriteReg(_opl, 0xBD, _vibrato);
+	}
+}
+
+void AdlibSoundDriverADL::loadInstrument(const byte *data, AdlibSoundInstrument *asi) {
+	asi->mode = *data++;
+	asi->channel = *data++;
+	asi->waveSelectMod = *data++ & 3;
+	asi->waveSelectCar = *data++ & 3;
+	asi->amDepth = *data++;
+	++data;
+	loadRegisterInstrument(data, &asi->regMod); data += 26;
+	loadRegisterInstrument(data, &asi->regCar); data += 26;
+}
+
+void AdlibSoundDriverADL::setChannelFrequency(int channel, int frequency) {
+	assert(channel < 4);
+	AdlibSoundInstrument *ins = &_instrumentsTable[channel];
+	if (ins->mode != 0) {
+		channel = ins->channel;
+		if (channel == 9) {
+			channel = 8;
+		} else if (channel == 10) {
+			channel = 7;
+		}
+	}
+	int freq, note, oct;
+	findNote(frequency, &note, &oct);
+
+	note += oct * 12;
+	if (ins->amDepth) {
+		note = ins->amDepth;
+	}
+	if (note < 0) {
+		note = 0;
+	}
+
+	freq = _freqTable[note % 12];
+	OPLWriteReg(_opl, 0xA0 | channel, freq);
+	freq = ((note / 12) << 2) | ((freq & 0x300) >> 8);
+	if (ins->mode == 0) {
+		freq |= 0x20;
+	}
+	OPLWriteReg(_opl, 0xB0 | channel, freq);
+	if (ins->mode != 0) {
+		_vibrato |= 1 << (10 - channel);
+		OPLWriteReg(_opl, 0xBD, _vibrato);
+	}
+}
+
+void AdlibSoundDriverADL::playSample(const byte *data, int size, int channel, int volume) {
+	assert(channel < 4);
+	_channelsVolumeTable[channel] = 127;
+	setupInstrument(data, channel);
+	AdlibSoundInstrument *ins = &_instrumentsTable[channel];
+	if (ins->mode != 0 && ins->channel == 6) {
+		OPLWriteReg(_opl, 0xB0 | channel, 0);
+	}
+	if (ins->mode != 0) {
+		_vibrato &= ~(1 << (10 - ins->channel));
+		OPLWriteReg(_opl, 0xBD, _vibrato);
+	}
+	if (ins->mode != 0) {
+		channel = ins->channel;
+		if (channel == 9) {
+			channel = 8;
+		} else if (channel == 10) {
+			channel = 7;
+		}
+	}
+	uint16 note = 48;
+	if (ins->amDepth) {
+		note = ins->amDepth;
+	}
+	int freq = _freqTable[note % 12];
+	OPLWriteReg(_opl, 0xA0 | channel, freq);
+	freq = ((note / 12) << 2) | ((freq & 0x300) >> 8);
+	if (ins->mode == 0) {
+		freq |= 0x20;
+	}
+	OPLWriteReg(_opl, 0xB0 | channel, freq);
+	if (ins->mode != 0) {
+		_vibrato |= 1 << (10 - channel);
+		OPLWriteReg(_opl, 0xBD, _vibrato);
+	}
+}
+
+PCSoundFxPlayer::PCSoundFxPlayer(PCSoundDriver *driver)
+	: _playing(false), _songPlayed(false), _driver(driver) {
+	memset(_instrumentsData, 0, sizeof(_instrumentsData));
+	_sfxData = NULL;
+	_fadeOutCounter = 0;
+	_driver->setUpdateCallback(updateCallback, this);
+}
+
+PCSoundFxPlayer::~PCSoundFxPlayer() {
+	_driver->setUpdateCallback(NULL, NULL);
+	if (_playing) {
 		stop();
+	}
+}
 
-	if (_songPointer) {
-		free(_songPointer);
-		_songPointer = NULL;
+bool PCSoundFxPlayer::load(const char *song) {
+	debug(9, "PCSoundFxPlayer::load('%s')", song);
+
+	/* stop (w/ fade out) the previous song */
+	while (_fadeOutCounter != 0 && _fadeOutCounter < 100) {
+		g_system->delayMillis(50);
 	}
+	_fadeOutCounter = 0;
 
+	if (_playing) {
+		stop();
+	}
+
+	strcpy(_musicName, song);
 	_songPlayed = false;
+	_looping = false;
+	_sfxData = readBundleSoundFile(song);
+	if (!_sfxData) {
+		warning("Unable to load soundfx module '%s'", song);
+		return 0;
+	}
 
-	strcpy(_musicName, "");
+	for (int i = 0; i < NUM_INSTRUMENTS; ++i) {
+		_instrumentsData[i] = NULL;
+
+		char instrument[64];
+		memset(instrument, 0, 64); // Clear the data first
+		memcpy(instrument, _sfxData + 20 + i * 30, 12);
+		instrument[63] = '\0';
+
+		if (strlen(instrument) != 0) {
+			char *dot = strrchr(instrument, '.');
+			if (dot) {
+				*dot = '\0';
+			}
+			strcat(instrument, _driver->getInstrumentExtension());
+			_instrumentsData[i] = readBundleSoundFile(instrument);
+			if (!_instrumentsData[i]) {
+				warning("Unable to load soundfx instrument '%s'", instrument);
+			}
+		}
+	}
+	return 1;
 }
 
-void MusicPlayer::fadeSong() {
-	// TODO: Implement fading properly
-	stop();
+void PCSoundFxPlayer::play() {
+	debug(9, "PCSoundFxPlayer::play()");
+	if (_sfxData) {
+		for (int i = 0; i < NUM_CHANNELS; ++i) {
+			_instrumentsChannelTable[i] = -1;
+		}
+		_currentPos = 0;
+		_currentOrder = 0;
+		_numOrders = _sfxData[470];
+		_eventsDelay = (244 - _sfxData[471]) * 100 / 1060;
+		_updateTicksCounter = 0;
+		_playing = true;
+	}
 }
 
-void MusicPlayer::patchMidi(uint32 adr, const byte *data, int size) {
-	// TODO: Handle patching midi
+void PCSoundFxPlayer::stop() {
+	if (_playing || _fadeOutCounter != 0) {
+		_fadeOutCounter = 0;
+		_playing = false;
+		for (int i = 0; i < NUM_CHANNELS; ++i) {
+			_driver->stopChannel(i);
+		}
+		_driver->stopAll();
+		unload();
+	}
 }
 
-byte *MusicPlayer::loadInstrument(const char *name, int i) {
-	// Find the resource
-	int fileIdx = findFileInDisks(name);
-	if (fileIdx < 0) {
-		warning("Instrument '%s' not found", name);
-		return NULL;
+void PCSoundFxPlayer::fadeOut() {
+	if (_playing) {
+		_fadeOutCounter = 1;
+		_playing = false;
 	}
+}
 
-	int size = volumePtrToFileDescriptor[fileIdx].extSize;
+void PCSoundFxPlayer::updateCallback(void *ref) {
+	((PCSoundFxPlayer *)ref)->update();
+}
 
-	// Get the data
-	byte *tmp = (byte *)malloc(size);
-	assert(tmp);
-	loadPackedFileToMem(fileIdx, tmp);
+void PCSoundFxPlayer::update() {
+	if (_playing || (_fadeOutCounter != 0 && _fadeOutCounter < 100)) {
+		++_updateTicksCounter;
+		if (_updateTicksCounter > _eventsDelay) {
+			handleEvents();
+			_updateTicksCounter = 0;
+		}
+	}
+}
 
-	// Create a copy of the resource that's 22 bytes smaller
-	byte *result = (byte *)malloc(size - 22);
-	assert(result);
-	Common::copy(tmp, tmp + size - 22, result);
+void PCSoundFxPlayer::handleEvents() {
+	const byte *patternData = _sfxData + 600 + 1800;
+	const byte *orderTable = _sfxData + 472;
+	uint16 patternNum = orderTable[_currentOrder] * 1024;
 
-	free(tmp);
-	return result;
+	for (int i = 0; i < 4; ++i) {
+		handlePattern(i, patternData + patternNum + _currentPos);
+		patternData += 4;
+	}
+
+	if (_fadeOutCounter != 0 && _fadeOutCounter < 100) {
+		_fadeOutCounter += 2;
+	}
+	if (_fadeOutCounter >= 100) {
+		stop();
+		return;
+	}
+
+	_currentPos += 16;
+	if (_currentPos >= 1024) {
+		_currentPos = 0;
+		++_currentOrder;
+		if (_currentOrder == _numOrders) {
+			_currentOrder = 0;
+		}
+	}
+	debug(7, "_currentOrder=%d/%d _currentPos=%d", _currentOrder, _numOrders, _currentPos);
 }
 
+void PCSoundFxPlayer::handlePattern(int channel, const byte *patternData) {
+	int instrument = patternData[2] >> 4;
+	if (instrument != 0) {
+		--instrument;
+		if (_instrumentsChannelTable[channel] != instrument || _fadeOutCounter != 0) {
+			_instrumentsChannelTable[channel] = instrument;
+			const int volume = _sfxData[instrument] - _fadeOutCounter;
+			_driver->setupChannel(channel, _instrumentsData[instrument], instrument, volume);
+		}
+	}
+	int16 freq = (int16)READ_BE_UINT16(patternData);
+	if (freq > 0) {
+		_driver->stopChannel(channel);
+		_driver->setChannelFrequency(channel, freq);
+	}
+}
+
+void PCSoundFxPlayer::unload() {
+	for (int i = 0; i < NUM_INSTRUMENTS; ++i) {
+		free(_instrumentsData[i]);
+		_instrumentsData[i] = NULL;
+	}
+	free(_sfxData);
+	_sfxData = NULL;
+	_songPlayed = true;
+}
+
+void PCSoundFxPlayer::doSync(Common::Serializer &s) {
+	s.syncBytes((byte *)_musicName, 33);
+	uint16 v = (uint16)songLoaded();
+	s.syncAsSint16LE(v);
+	s.syncAsSint16LE(_songPlayed);
+	s.syncAsSint16LE(_looping);
+}
+
+PCSound::PCSound(Audio::Mixer *mixer, CruiseEngine *vm) {
+	_vm = vm;
+	_mixer = mixer;
+	_soundDriver = new AdlibSoundDriverADL(_mixer);
+	_player = new PCSoundFxPlayer(_soundDriver);
+}
+
+PCSound::~PCSound() {
+	delete _player;
+	delete _soundDriver;
+}
+
+void PCSound::loadMusic(const char *name) {
+	debugC(5, kCruiseDebugSound, "PCSound::loadMusic('%s')", name);
+	_player->load(name);
+}
+
+void PCSound::playMusic() {
+	debugC(5, kCruiseDebugSound, "PCSound::playMusic()");
+	_player->play();
+}
+
+void PCSound::stopMusic() {
+	debugC(5, kCruiseDebugSound, "PCSound::stopMusic()");
+	_player->stop();
+}
+
+void PCSound::removeMusic() {
+	debugC(5, kCruiseDebugSound, "PCSound::removeMusic()");
+	_player->unload();
+}
+
+void PCSound::fadeOutMusic() {
+	debugC(5, kCruiseDebugSound, "PCSound::fadeOutMusic()");
+	_player->fadeOut();
+}
+
+void PCSound::playSound(int channel, int frequency, const uint8 *data, int size, int volumeStep, int stepCount, int volume, int repeat) {
+	debugC(5, kCruiseDebugSound, "PCSound::playSound() channel %d size %d", channel, size);
+	_soundDriver->playSample(data, size, channel, volume);
+}
+
+void PCSound::stopSound(int channel) {
+	debugC(5, kCruiseDebugSound, "PCSound::stopSound() channel %d", channel);
+	_soundDriver->resetChannel(channel);
+}
+
+void PCSound::stopChannel(int channel) {
+	debugC(5, kCruiseDebugSound, "PCSound::stopChannel() channel %d", channel);
+	_soundDriver->stopChannel(channel);
+}
+
+bool PCSound::isPlaying() const {
+	return _player->playing();
+}
+
+bool PCSound::songLoaded() const {
+	return _player->songLoaded();
+}
+
+bool PCSound::songPlayed() const {
+	return _player->songPlayed();
+}
+
+void PCSound::fadeSong() {
+	_player->fadeOut();
+}
+
+uint8 PCSound::numOrders() const {
+	return _player->numOrders();
+}
+
+void PCSound::setNumOrders(uint8 v) {
+	_player->setNumOrders(v);
+}
+
+void PCSound::setPattern(int offset, uint8 value) {
+	_player->setPattern(offset, value);
+}
+
+bool PCSound::musicLooping() const {
+	return _player->looping();
+}
+
+void PCSound::musicLoop(bool v) {
+	_player->setLooping(v);
+	warning("TODO: set music looping");
+}
+
+void PCSound::startNote(int channel, int volume, int speed) {
+	warning("TODO: startNote");
+//	_soundDriver->setVolume(channel, volume);
+	_soundDriver->setChannelFrequency(channel, speed);
+}
+
+void PCSound::setVolume(int volume) {
+	warning("TODO: setVolume");
+}
+
+uint8 PCSound::getVolume() {
+	warning("TODO: getVolume");
+	return 63;
+}
+
+void PCSound::startSound(int channelNum, const byte *ptr, int size, int speed, int volume, bool loop) {
+	warning("TODO: validate startSound");
+	playSound(channelNum, speed, ptr, size, 0, 0, volume, loop);
+}
+
+void PCSound::doSync(Common::Serializer &s) {
+	warning("TODO: doSync fx properties");
+	_player->doSync(s);
+//	_soundDriver->doSync(s);
+}
+
 } // End of namespace Cruise

Modified: scummvm/trunk/engines/cruise/sound.h
===================================================================
--- scummvm/trunk/engines/cruise/sound.h	2009-06-14 00:30:59 UTC (rev 41505)
+++ scummvm/trunk/engines/cruise/sound.h	2009-06-14 03:39:30 UTC (rev 41506)
@@ -33,60 +33,47 @@
 
 namespace Cruise {
 
-class MusicPlayer {
-private:
-	byte _channelVolume[16];
-	int _fadeVolume;
-	char _musicName[33];
+class CruiseEngine;
+class PCSoundDriver;
+class PCSoundFxPlayer;
 
-	bool _isPlaying;
-	bool _songPlayed;
-	bool _looping;
-	byte _masterVolume;
-
-	byte *_songPointer;
-	// TODO: lib_SongSize
-	int _songSize;
-
-	void patchMidi(uint32 adr, const byte *data, int size);
-	byte *loadInstrument(const char *name, int i);
+class PCSound {
+private:
+	Audio::Mixer *_mixer;
+	CruiseEngine *_vm;
+protected:
+	PCSoundDriver *_soundDriver;
+	PCSoundFxPlayer *_player;
 public:
-	MusicPlayer();
-	~MusicPlayer();
+	PCSound(Audio::Mixer *mixer, CruiseEngine *vm);
+	virtual ~PCSound();
 
-	void setVolume(int volume);
-	int getVolume() const { return _masterVolume; }
+	virtual void loadMusic(const char *name);
+	virtual void playMusic();
+	virtual void stopMusic();
+	virtual void removeMusic();
+	virtual void fadeOutMusic();
 
-	void stop();
-	void pause();
-	void resume();
-
-	// Common public access methods
+	virtual void playSound(int channel, int frequency, const uint8 *data, int size, int volumeStep, int stepCount, int volume, int repeat);
+	virtual void startSound(int channelNum, const byte *ptr, int size, int speed, int volume, bool loop);
+	virtual void stopSound(int channel);
+	
 	void doSync(Common::Serializer &s);
-	void loadSong(const char *name);
-	void startSong();
-	void stopSong();
-	void removeSong();
+	void stopChannel(int channel);
+	bool isPlaying() const;
+	bool songLoaded() const;
+	bool songPlayed() const;
 	void fadeSong();
-
-	bool songLoaded() const { return _songPointer != NULL; }
-	bool songPlayed() const { return _songPlayed; }
-	bool isPlaying() const { return _isPlaying; }
-	bool looping() const { return _looping; }
-	byte *songData() { return _songPointer; }
-	void setPlaying(bool playing) { _isPlaying = playing; }
-	void setLoop(bool loop) { _looping = loop; }
+	uint8 numOrders() const;
+	void setNumOrders(uint8 v);
+	void setPattern(int offset, uint8 value);
+	bool musicLooping() const;
+	void musicLoop(bool v);
+	void startNote(int channel, int volume, int speed);
+	void setVolume(int volume);
+	uint8 getVolume();
 };
 
-class SoundPlayer {
-public:
-	SoundPlayer() {}
-
-	void startSound(int channelNum, const byte *ptr, int size, int speed, int volume, bool loop) {}
-	void startNote(int channelNum, int speed, int volume) {}
-	void stopChannel(int channelNum) {}
-};
-
 } // End of namespace Cruise
 
 #endif


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