[Scummvm-cvs-logs] SF.net SVN: scummvm: [26870] scummvm/trunk/engines/cine

cyx at users.sourceforge.net cyx at users.sourceforge.net
Sat May 19 14:08:42 CEST 2007


Revision: 26870
          http://scummvm.svn.sourceforge.net/scummvm/?rev=26870&view=rev
Author:   cyx
Date:     2007-05-19 05:08:41 -0700 (Sat, 19 May 2007)

Log Message:
-----------
added basic support for Amiga music playback

Modified Paths:
--------------
    scummvm/trunk/engines/cine/cine.cpp
    scummvm/trunk/engines/cine/main_loop.cpp
    scummvm/trunk/engines/cine/module.mk
    scummvm/trunk/engines/cine/script.cpp
    scummvm/trunk/engines/cine/various.cpp

Added Paths:
-----------
    scummvm/trunk/engines/cine/sound.cpp
    scummvm/trunk/engines/cine/sound.h

Removed Paths:
-------------
    scummvm/trunk/engines/cine/sfx_player.cpp
    scummvm/trunk/engines/cine/sfx_player.h
    scummvm/trunk/engines/cine/sound_driver.cpp
    scummvm/trunk/engines/cine/sound_driver.h

Modified: scummvm/trunk/engines/cine/cine.cpp
===================================================================
--- scummvm/trunk/engines/cine/cine.cpp	2007-05-19 12:06:51 UTC (rev 26869)
+++ scummvm/trunk/engines/cine/cine.cpp	2007-05-19 12:08:41 UTC (rev 26870)
@@ -39,15 +39,13 @@
 #include "cine/main_loop.h"
 #include "cine/object.h"
 #include "cine/texte.h"
-#include "cine/sfx_player.h"
-#include "cine/sound_driver.h"
+#include "cine/sound.h"
 #include "cine/various.h"
 
 
 namespace Cine {
 
-SoundDriver *g_soundDriver;
-SfxPlayer *g_sfxPlayer;
+Sound *g_sound;
 Common::SaveFileManager *g_saveFileMan;
 
 CineEngine *g_cine;
@@ -96,16 +94,11 @@
 	_system->endGFXTransaction();
 
 	if (g_cine->getPlatform() == Common::kPlatformPC) {
-		if (g_cine->getGameType() == GType_FW) {
-			g_soundDriver = new AdlibSoundDriverINS(_mixer);
-		} else {
-			g_soundDriver = new AdlibSoundDriverADL(_mixer);
-		}
+		g_sound = new PCSound(_mixer, this);
 	} else {
 		// Paula chipset for Amiga and Atari versions
-		g_soundDriver = new PaulaSoundDriver(_mixer);
+		g_sound = new PaulaSound(_mixer, this);
 	}
-	g_sfxPlayer = new SfxPlayer(g_soundDriver);
 	g_saveFileMan = _saveFileMan;
 
 	initialize();
@@ -118,8 +111,7 @@
 
 	mainLoop(1);
 
-	delete g_sfxPlayer;
-	delete g_soundDriver;
+	delete g_sound;
 	return 0;
 }
 

Modified: scummvm/trunk/engines/cine/main_loop.cpp
===================================================================
--- scummvm/trunk/engines/cine/main_loop.cpp	2007-05-19 12:06:51 UTC (rev 26869)
+++ scummvm/trunk/engines/cine/main_loop.cpp	2007-05-19 12:08:41 UTC (rev 26870)
@@ -29,10 +29,9 @@
 
 #include "cine/main_loop.h"
 #include "cine/object.h"
-#include "cine/sfx_player.h"
 #include "cine/various.h"
 #include "cine/bg_list.h"
-#include "cine/sound_driver.h"
+#include "cine/sound.h"
 
 namespace Cine {
 
@@ -157,7 +156,7 @@
 		if (i % 2)
 			g_system->updateScreen();
 		g_system->delayMillis(10);
-		g_soundDriver->update();
+		g_sound->update();
 		manageEvents(0);
 	}
 }
@@ -246,7 +245,7 @@
 		strcpy(currentCtName, "");
 		strcpy(currentPartName, "");
 
-		g_sfxPlayer->stop();
+		g_sound->stopMusic();
 	}
 
 	do {
@@ -335,7 +334,7 @@
 	} while (!exitEngine && !quitFlag && var21 != 7);
 
 	hideMouse();
-	g_sfxPlayer->stop();
+	g_sound->stopMusic();
 	freeAnimDataTable();
 	unloadAllMasks();
 	freePrcLinkedList();

Modified: scummvm/trunk/engines/cine/module.mk
===================================================================
--- scummvm/trunk/engines/cine/module.mk	2007-05-19 12:06:51 UTC (rev 26869)
+++ scummvm/trunk/engines/cine/module.mk	2007-05-19 12:08:41 UTC (rev 26870)
@@ -15,8 +15,7 @@
 	prc.o \
 	rel.o \
 	script.o \
-	sfx_player.o \
-	sound_driver.o \
+	sound.o \
 	texte.o \
 	unpack.o \
 	various.o

Modified: scummvm/trunk/engines/cine/script.cpp
===================================================================
--- scummvm/trunk/engines/cine/script.cpp	2007-05-19 12:06:51 UTC (rev 26869)
+++ scummvm/trunk/engines/cine/script.cpp	2007-05-19 12:08:41 UTC (rev 26870)
@@ -28,8 +28,7 @@
 #include "cine/cine.h"
 #include "cine/bg_list.h"
 #include "cine/object.h"
-#include "cine/sfx_player.h"
-#include "cine/sound_driver.h"
+#include "cine/sound.h"
 #include "cine/various.h"
 
 namespace Cine {
@@ -1509,44 +1508,22 @@
 	const char *param = getNextString();
 
 	debugC(5, kCineDebugScript, "Line: %d: loadMusic(%s)", _currentLine, param);
-
-	if (g_cine->getPlatform() == Common::kPlatformAmiga ||
-			g_cine->getPlatform() == Common::kPlatformAtariST) {
-		warning("STUB: o1_loadMusic");
-		return;
-	}
-
-	g_sfxPlayer->load(param);
+	g_sound->loadMusic(param);
 }
 
 void o1_playMusic() {
 	debugC(5, kCineDebugScript, "Line: %d: playMusic()", _currentLine);
-	if (g_cine->getPlatform() == Common::kPlatformAmiga ||
-			g_cine->getPlatform() == Common::kPlatformAtariST) {
-		warning("STUB: o1_playMusic");
-		return;
-	}
-	g_sfxPlayer->play();
+	g_sound->playMusic();
 }
 
 void o1_fadeOutMusic() {
 	debugC(5, kCineDebugScript, "Line: %d: fadeOutMusic()", _currentLine);
-	if (g_cine->getPlatform() == Common::kPlatformAmiga ||
-			g_cine->getPlatform() == Common::kPlatformAtariST) {
-		warning("STUB: o1_fadeOutMusic");
-		return;
-	}
-	g_sfxPlayer->fadeOut();
+	g_sound->fadeOutMusic();
 }
 
 void o1_stopSample() {
 	debugC(5, kCineDebugScript, "Line: %d: stopSample()", _currentLine);
-	if (g_cine->getPlatform() == Common::kPlatformAmiga ||
-			g_cine->getPlatform() == Common::kPlatformAtariST) {
-		warning("STUB: o1_stopSample");
-		return;
-	}
-	g_sfxPlayer->stop();
+	g_sound->stopMusic();
 }
 
 void o1_op71() {
@@ -1571,74 +1548,59 @@
 	getNextWord();
 }
 
-void o1_playSampleAmiga() {
-	int num = getNextByte();
-	int channel = getNextByte();
-	int freq = getNextWord();
-	int repeat = getNextByte();
-	int volume = getNextWord();
-	int size = getNextWord();
-
-	if (size == 0xFFFF) {
-		size = animDataTable[num].width * animDataTable[num].height;
-	}
-	
-	if (channel < 10) { // || _currentOpcode == 0x78
-		int channel1, channel2;
-		if (channel == 0) {
-			channel1 = 0;
-			channel2 = 1;
-		} else {
-			channel1 = 2;
-			channel2 = 3;			
-		}
-		((PaulaSoundDriver *)g_soundDriver)->queueSound(channel1, freq, animDataTable[num].ptr1, size, -1, volume, 63, repeat);
-		((PaulaSoundDriver *)g_soundDriver)->queueSound(channel2, freq, animDataTable[num].ptr1, size,  1, volume,  0, repeat);
-	} else {
-		channel -= 10;
-		if (volume > 63) {
-			volume = 63;
-		}
-		((PaulaSoundDriver *)g_soundDriver)->queueSound(channel, freq, animDataTable[num].ptr1, size, 0, 0, volume, repeat);
-	}
-}
-
 void o1_playSample() {
 	debugC(5, kCineDebugScript, "Line: %d: playSample()", _currentLine);
 
-	if (g_cine->getPlatform() == Common::kPlatformAmiga || g_cine->getPlatform() == Common::kPlatformAtariST) {
-		o1_playSampleAmiga();
-		return;
-	}
-
 	byte anim = getNextByte();
 	byte channel = getNextByte();
 
-	getNextWord();
-	getNextByte();
+	uint16 freq = getNextWord();
+	byte repeat = getNextByte();
 
 	int16 volume = getNextWord();
-	uint16 flag = getNextWord();
+	uint16 size = getNextWord();
 
-	if (volume > 63)
-		volume = 63;
-	if (volume < 0)
-		volume = 63;
+	if (!animDataTable[anim].ptr1) {
+		return;
+	}
 
-	if (animDataTable[anim].ptr1) {
+	if (g_cine->getPlatform() == Common::kPlatformAmiga || g_cine->getPlatform() == Common::kPlatformAtariST) {
+		if (size == 0xFFFF) {
+			size = animDataTable[anim].width * animDataTable[anim].height;
+		}
+		if (channel < 10) { // || _currentOpcode == 0x78
+			int channel1, channel2;
+			if (channel == 0) {
+				channel1 = 0;
+				channel2 = 1;
+			} else {
+				channel1 = 2;
+				channel2 = 3;			
+			}
+			g_sound->playSound(channel1, freq, animDataTable[anim].ptr1, size, -1, volume, 63, repeat);
+			g_sound->playSound(channel2, freq, animDataTable[anim].ptr1, size,  1, volume,  0, repeat);
+		} else {
+			channel -= 10;
+			if (volume > 63) {
+				volume = 63;
+			}
+			g_sound->playSound(channel, freq, animDataTable[anim].ptr1, size, 0, 0, volume, repeat);
+		}
+	} else {
+		if (volume > 63 || volume < 0) {
+			volume = 63;
+		}
 		if (channel >= 10) {
 			channel -= 10;
 		}
 		if (volume < 50) {
 			volume = 50;
 		}
-
-		g_sfxPlayer->stop();
-					
-		if (flag == 0xFFFF) {
-			g_soundDriver->playSound(animDataTable[anim].ptr1, 0, channel, volume);
+		g_sound->stopMusic();
+		if (size == 0xFFFF) {
+			g_sound->playSound(channel, 0, animDataTable[anim].ptr1, 0, 0, 0, volume, 0);
 		} else {
-			g_soundDriver->resetChannel(channel);
+			g_sound->stopSound(channel);
 		}
 	}
 }
@@ -1689,12 +1651,12 @@
 }
 
 void o2_playSampleAlt() {
-	int num = getNextByte();
-	int channel = getNextByte();
-	int freq = getNextWord();
+	byte num = getNextByte();
+	byte channel = getNextByte();
+	uint16 frequency = getNextWord();
 	getNextByte();
 	getNextWord();
-	int size = getNextWord();
+	uint16 size = getNextWord();
 
 	if (size == 0xFFFF) {
 		size = animDataTable[num].width * animDataTable[num].height;
@@ -1704,8 +1666,7 @@
 			// if speaker output is enabled, play sound on it
 			// if it's another device, don't play anything
 		} else {
-			g_soundDriver->setChannelFrequency(channel, freq);
-			g_soundDriver->playSound(animDataTable[num].ptr1, size, channel, 63);
+			g_sound->playSound(channel, frequency, animDataTable[num].ptr1, size, 0, 0, 63, 0);
 		}
 	}
 }

Deleted: scummvm/trunk/engines/cine/sfx_player.cpp
===================================================================
--- scummvm/trunk/engines/cine/sfx_player.cpp	2007-05-19 12:06:51 UTC (rev 26869)
+++ scummvm/trunk/engines/cine/sfx_player.cpp	2007-05-19 12:08:41 UTC (rev 26870)
@@ -1,196 +0,0 @@
-/* ScummVM - Scumm Interpreter
- * Copyright (C) 2006 The ScummVM project
- *
- * cinE Engine is (C) 2004-2005 by CinE Team
- *
- * 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$
- *
- */
-
-#include "common/stdafx.h"
-#include "common/endian.h"
-#include "common/system.h"
-
-#include "cine/cine.h"
-#include "cine/sfx_player.h"
-#include "cine/sound_driver.h"
-#include "cine/unpack.h"
-#include "cine/various.h"
-
-namespace Cine {
-
-SfxPlayer::SfxPlayer(SoundDriver *driver)
-	: _playing(false), _driver(driver) {
-	memset(_instrumentsData, 0, sizeof(_instrumentsData));
-	_sfxData = NULL;
-	_fadeOutCounter = 0;
-	_driver->setUpdateCallback(updateCallback, this);
-}
-
-SfxPlayer::~SfxPlayer() {
-	_driver->setUpdateCallback(NULL, NULL);
-	if (_playing) {
-		stop();
-	}
-}
-
-bool SfxPlayer::load(const char *song) {
-	debug(9, "SfxPlayer::load('%s')", song);
-	
-	/* stop (w/ fade out) the previous song */
-	while (_fadeOutCounter != 0 && _fadeOutCounter < 100) {
-		g_system->delayMillis(50);
-	}
-	_fadeOutCounter = 0;
-
-	if (_playing) {
-		stop();
-	}
-
-	/* like the original PC version, skip introduction song (file doesn't exist) */
-	if (g_cine->getGameType() == Cine::GType_OS && strncmp(song, "INTRO", 5) == 0) {
-		return 0;
-	}
-		
-	_sfxData = readBundleSoundFile(song);
-	if (!_sfxData) {
-		warning("Unable to load soundfx module '%s'", song);
-		return 0;
-	}
-
-	for (int i = 0; i < NUM_INSTRUMENTS; ++i) {
-		_instrumentsData[i] = NULL;
-		
-		char instrument[13];
-		memcpy(instrument, _sfxData + 20 + i * 30, 12);
-		instrument[12] = '\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 SfxPlayer::play() {
-	debug(9, "SfxPlayer::play()");
-	if (_sfxData) {
-		for (int i = 0; i < NUM_CHANNELS; ++i) {
-			_instrumentsChannelTable[i] = -1;
-		}
-		_currentPos = 0;
-		_currentOrder = 0;
-		_numOrders = _sfxData[470];
-		_eventsDelay = (252 - _sfxData[471]) * 50 / 1060;
-		_updateTicksCounter = 0;
-		_playing = true;
-	}
-}
-
-void SfxPlayer::stop() {
-	if (_playing || _fadeOutCounter != 0) {
-		_fadeOutCounter = 0;
-		_playing = false;
-		for (int i = 0; i < NUM_CHANNELS; ++i) {
-			_driver->stopChannel(i);
-		}
-		_driver->stopSound();
-		unload();
-	}
-}
-
-void SfxPlayer::fadeOut() {
-	if (_playing) {
-		_fadeOutCounter = 1;
-		_playing = false;
-	}
-}
-
-void SfxPlayer::updateCallback(void *ref) {
-	((SfxPlayer *)ref)->update();
-}
-
-void SfxPlayer::update() {
-	if (_playing || (_fadeOutCounter != 0 && _fadeOutCounter < 100)) {
-		++_updateTicksCounter;
-		if (_updateTicksCounter > _eventsDelay) {
-			handleEvents();
-			_updateTicksCounter = 0;
-		}
-	}
-}
-
-void SfxPlayer::handleEvents() {
-	const byte *patternData = _sfxData + 600;
-	const byte *orderTable = _sfxData + 472;
-	uint16 patternNum = orderTable[_currentOrder] * 1024;
-
-	for (int i = 0; i < 4; ++i) {
-		handlePattern(i, patternData + patternNum + _currentPos);
-		patternData += 4;
-	}
-
-	if (_fadeOutCounter != 0 && _fadeOutCounter < 100) {
-		_fadeOutCounter += 2;
-	}
-	_currentPos += 16;
-	if (_currentPos >= 1024) {
-		_currentPos = 0;
-		++_currentOrder;
-		if (_currentOrder == _numOrders) {
-			_currentOrder = 0;
-		}
-	}
-	debug(7, "_currentOrder=%d/%d _currentPos=%d", _currentOrder, _numOrders, _currentPos);
-}
-
-void SfxPlayer::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 SfxPlayer::unload() {
-	for (int i = 0; i < NUM_INSTRUMENTS; ++i) {
-		free(_instrumentsData[i]);
-		_instrumentsData[i] = NULL;
-	}
-	free(_sfxData);
-	_sfxData = NULL;
-}
-
-} // End of namespace Cine

Deleted: scummvm/trunk/engines/cine/sfx_player.h
===================================================================
--- scummvm/trunk/engines/cine/sfx_player.h	2007-05-19 12:06:51 UTC (rev 26869)
+++ scummvm/trunk/engines/cine/sfx_player.h	2007-05-19 12:08:41 UTC (rev 26870)
@@ -1,74 +0,0 @@
-/* ScummVM - Scumm Interpreter
- * Copyright (C) 2006 The ScummVM project
- *
- * cinE Engine is (C) 2004-2005 by CinE Team
- *
- * 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$
- *
- */
-
-#ifndef CINE_SFXPLAYER_H
-#define CINE_SFXPLAYER_H
-
-namespace Cine {
-
-class SoundDriver;
-
-class SfxPlayer {
-public:
-
-	enum {
-		NUM_INSTRUMENTS = 15,
-		NUM_CHANNELS = 4
-	};
-	
-	SfxPlayer(SoundDriver *driver);
-	~SfxPlayer();
-
-	bool load(const char *song);
-	void play();
-	void stop();
-	void fadeOut();
-
-	static void updateCallback(void *ref);
-
-private:
-
-	void update();
-	void handleEvents();
-	void handlePattern(int channel, const byte *patternData);
-	void unload();
-
-	bool _playing;
-	int _currentPos;
-	int _currentOrder;
-	int _numOrders;
-	int _eventsDelay;
-	int _fadeOutCounter;
-	int _updateTicksCounter;
-	int _instrumentsChannelTable[NUM_CHANNELS];
-	byte *_sfxData;
-	byte *_instrumentsData[NUM_INSTRUMENTS];
-	SoundDriver *_driver;
-};
-
-extern SfxPlayer *g_sfxPlayer; // TEMP
-
-} // End of namespace Cine
-
-#endif				/* _SFXPLAYER_H_ */

Copied: scummvm/trunk/engines/cine/sound.cpp (from rev 26868, scummvm/trunk/engines/cine/sound_driver.cpp)
===================================================================
--- scummvm/trunk/engines/cine/sound.cpp	                        (rev 0)
+++ scummvm/trunk/engines/cine/sound.cpp	2007-05-19 12:08:41 UTC (rev 26870)
@@ -0,0 +1,849 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2006 The ScummVM project
+ *
+ * cinE Engine is (C) 2004-2005 by CinE Team
+ *
+ * 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$
+ *
+ */
+
+#include "common/stdafx.h"
+#include "common/endian.h"
+#include "common/file.h"
+#include "common/system.h"
+
+#include "cine/cine.h"
+#include "cine/sound.h"
+
+#include "sound/audiostream.h"
+#include "sound/fmopl.h"
+#include "sound/mods/soundfx.h"
+
+namespace Cine {
+
+class PCSoundDriver {
+public:
+	typedef void (*UpdateCallback)(void *);
+
+	virtual ~PCSoundDriver() {}
+
+	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 ""; }
+
+	void setUpdateCallback(UpdateCallback upCb, void *ref);
+	void resetChannel(int channel);
+	void findNote(int freq, int *note, int *oct) const;
+
+protected:
+	UpdateCallback _upCb;
+	void *_upRef;
+
+	static const int _noteTable[];
+	static const int _noteTableCount;
+};
+
+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
+};
+
+const int PCSoundDriver::_noteTableCount = ARRAYSIZE(_noteTable);
+
+struct AdlibRegisterSoundInstrument {
+	uint16 vibrato;
+	uint16 attackDecay;
+	uint16 sustainRelease;
+	uint16 feedbackStrength;
+	uint16 keyScaling;
+	uint16 outputLevel;
+	uint16 freqMod;
+};
+
+struct AdlibSoundInstrument {
+	byte mode;
+	byte channel;
+	AdlibRegisterSoundInstrument regMod;
+	AdlibRegisterSoundInstrument regCar;
+	byte waveSelectMod;
+	byte waveSelectCar;
+	byte amDepth;
+};
+
+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 {
+public:
+
+	PCSoundFxPlayer(PCSoundDriver *driver);
+	~PCSoundFxPlayer();
+
+	bool load(const char *song);
+	void play();
+	void stop();
+	void fadeOut();
+
+	static void updateCallback(void *ref);
+
+	enum {
+		NUM_INSTRUMENTS = 15,
+		NUM_CHANNELS = 4
+	};
+
+private:
+
+	void update();
+	void handleEvents();
+	void handlePattern(int channel, const byte *patternData);
+	void unload();
+
+	bool _playing;
+	int _currentPos;
+	int _currentOrder;
+	int _numOrders;
+	int _eventsDelay;
+	int _fadeOutCounter;
+	int _updateTicksCounter;
+	int _instrumentsChannelTable[NUM_CHANNELS];
+	byte *_sfxData;
+	byte *_instrumentsData[NUM_INSTRUMENTS];
+	PCSoundDriver *_driver;
+};
+
+
+void PCSoundDriver::setUpdateCallback(UpdateCallback upCb, void *ref) {
+	_upCb = upCb;
+	_upRef = ref;
+}
+
+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;
+}
+
+void PCSoundDriver::resetChannel(int channel) {
+	stopChannel(channel);
+	stopAll();
+}
+
+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);
+}
+
+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);
+	}
+}
+
+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);
+	}
+}
+
+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);
+}
+
+int AdlibSoundDriver::readBuffer(int16 *buffer, const int numSamples) {
+	update(buffer, numSamples);
+	return numSamples;
+}
+
+void AdlibSoundDriver::initCard() {
+	_vibrato = 0x20;
+	OPLWriteReg(_opl, 0xBD, _vibrato);
+	OPLWriteReg(_opl, 0x08, 0x40);
+
+	int i;
+	for (i = 0; i < 18; ++i) {
+		OPLWriteReg(_opl, 0x40 | _operatorsTable[i], 0);
+	}
+	for (i = 0; i < 9; ++i) {
+		OPLWriteReg(_opl, 0xB0 | i, 0);
+	}
+	for (i = 0; i < 9; ++i) {
+		OPLWriteReg(_opl, 0xC0 | i, 0);
+	}
+	for (i = 0; i < 18; ++i) {
+		OPLWriteReg(_opl, 0x60 | _operatorsTable[i], 0);
+	}
+	for (i = 0; i < 18; ++i) {
+		OPLWriteReg(_opl, 0x80 | _operatorsTable[i], 0);
+	}
+	for (i = 0; i < 18; ++i) {
+		OPLWriteReg(_opl, 0x20 | _operatorsTable[i], 0);
+	}
+	for (i = 0; i < 18; ++i) {
+		OPLWriteReg(_opl, 0xE0 | _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;
+	}
+}
+
+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 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 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), _driver(driver) {
+	memset(_instrumentsData, 0, sizeof(_instrumentsData));
+	_sfxData = NULL;
+	_fadeOutCounter = 0;
+	_driver->setUpdateCallback(updateCallback, this);
+}
+
+PCSoundFxPlayer::~PCSoundFxPlayer() {
+	_driver->setUpdateCallback(NULL, NULL);
+	if (_playing) {
+		stop();
+	}
+}
+
+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();
+	}
+
+	_sfxData = readBundleSoundFile(song);
+	if (!_sfxData) {
+		warning("Unable to load soundfx module '%s'", song);
+		return 0;
+	}
+
+	for (int i = 0; i < NUM_INSTRUMENTS; ++i) {
+		_instrumentsData[i] = NULL;
+
+		char instrument[13];
+		memcpy(instrument, _sfxData + 20 + i * 30, 12);
+		instrument[12] = '\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 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 = (252 - _sfxData[471]) * 50 / 1060;
+		_updateTicksCounter = 0;
+		_playing = true;
+	}
+}
+
+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();
+	}
+}
+
+void PCSoundFxPlayer::fadeOut() {
+	if (_playing) {
+		_fadeOutCounter = 1;
+		_playing = false;
+	}
+}
+
+void PCSoundFxPlayer::updateCallback(void *ref) {
+	((PCSoundFxPlayer *)ref)->update();
+}
+
+void PCSoundFxPlayer::update() {
+	if (_playing || (_fadeOutCounter != 0 && _fadeOutCounter < 100)) {
+		++_updateTicksCounter;
+		if (_updateTicksCounter > _eventsDelay) {
+			handleEvents();
+			_updateTicksCounter = 0;
+		}
+	}
+}
+
+void PCSoundFxPlayer::handleEvents() {
+	const byte *patternData = _sfxData + 600;
+	const byte *orderTable = _sfxData + 472;
+	uint16 patternNum = orderTable[_currentOrder] * 1024;
+
+	for (int i = 0; i < 4; ++i) {
+		handlePattern(i, patternData + patternNum + _currentPos);
+		patternData += 4;
+	}
+
+	if (_fadeOutCounter != 0 && _fadeOutCounter < 100) {
+		_fadeOutCounter += 2;
+	}
+	_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;
+}
+
+
+PCSound::PCSound(Audio::Mixer *mixer, CineEngine *vm)
+	: Sound(mixer, vm) {
+	if (_vm->getGameType() == GType_FW) {
+		_soundDriver = new AdlibSoundDriverINS(_mixer);
+	} else {
+		_soundDriver = new AdlibSoundDriverADL(_mixer);
+	}
+	_player = new PCSoundFxPlayer(_soundDriver);
+}
+
+PCSound::~PCSound() {
+	delete _player;
+	delete _soundDriver;
+}
+
+void PCSound::loadMusic(const char *name) {
+	_player->load(name);
+}
+
+void PCSound::playMusic() {
+	_player->play();
+}
+
+void PCSound::stopMusic() {
+	_player->stop();
+}
+
+void PCSound::fadeOutMusic() {
+	_player->fadeOut();
+}
+
+void PCSound::playSound(int channel, int frequency, const uint8 *data, int size, int volumeStep, int stepCount, int volume, int repeat) {
+	_soundDriver->playSample(data, size, channel, volume);
+}
+
+void PCSound::stopSound(int channel) {
+	_soundDriver->resetChannel(channel);
+}
+
+PaulaSound::PaulaSound(Audio::Mixer *mixer, CineEngine *vm)
+	: Sound(mixer, vm) {
+	memset(_soundChannelsTable, 0, sizeof(_soundChannelsTable));
+	_moduleStream = 0;
+}
+
+PaulaSound::~PaulaSound() {
+}
+
+void PaulaSound::loadMusic(const char *name) {
+	Common::File f;
+	if (f.open(name)) {
+		_moduleStream = Audio::makeSoundFxStream(&f, _mixer->getOutputRate());
+	}
+}
+
+void PaulaSound::playMusic() {
+	_mixer->stopHandle(_moduleHandle);
+	if (_moduleStream) {
+		_mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_moduleHandle, _moduleStream);
+	}
+}
+
+void PaulaSound::stopMusic() {
+	_mixer->stopHandle(_moduleHandle);
+}
+
+void PaulaSound::fadeOutMusic() {
+	// TODO
+	stopMusic();
+}
+
+void PaulaSound::playSound(int channel, int frequency, const uint8 *data, int size, int volumeStep, int stepCount, int volume, int repeat) {
+	SoundChannel *ch = &_soundChannelsTable[channel];
+	ch->frequency = frequency;
+	ch->data = data;
+	ch->size = size;
+	ch->volumeStep = volumeStep;
+	ch->stepCount = stepCount;
+	ch->step = stepCount;
+	ch->repeat = repeat != 0;
+	ch->volume = volume;
+}
+
+void PaulaSound::stopSound(int channel) {
+	_mixer->stopHandle(_channelsTable[channel]);
+}
+
+void PaulaSound::update() {
+	// process volume slides and start sound playback
+	for (int i = 0; i < NUM_CHANNELS; ++i) {
+		SoundChannel *ch = &_soundChannelsTable[i];
+		if (ch->data) {
+			if (ch->step) {
+				--ch->step;
+				continue;
+			}
+			ch->step = ch->stepCount;
+			ch->volume = CLIP(ch->volume + ch->volumeStep, 0, 63);
+			playSoundChannel(i, ch->frequency, ch->data, ch->size, ch->volume);
+			if (!ch->repeat) {
+				ch->data = 0;
+			}
+		}
+	}
+}
+
+void PaulaSound::playSoundChannel(int channel, int frequency, const uint8 *data, int size, int volume) {
+	stopSound(channel);
+	assert(frequency > 0);
+	frequency = PAULA_FREQ / frequency;
+	size = MIN<int>(size - SPL_HDR_SIZE, READ_BE_UINT16(data + 4));
+	data += SPL_HDR_SIZE;
+	if (size > 0) {
+		_mixer->playRaw(Audio::Mixer::kSFXSoundType, &_channelsTable[channel], const_cast<byte *>(data), size, frequency, 0);
+		_mixer->setChannelVolume(_channelsTable[channel], volume * Audio::Mixer::kMaxChannelVolume / 63);
+	}
+}
+
+} // End of namespace Cine

Copied: scummvm/trunk/engines/cine/sound.h (from rev 26868, scummvm/trunk/engines/cine/sound_driver.h)
===================================================================
--- scummvm/trunk/engines/cine/sound.h	                        (rev 0)
+++ scummvm/trunk/engines/cine/sound.h	2007-05-19 12:08:41 UTC (rev 26870)
@@ -0,0 +1,129 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2006 The ScummVM project
+ *
+ * cinE Engine is (C) 2004-2005 by CinE Team
+ *
+ * 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$
+ *
+ */
+
+#ifndef CINE_SOUND_H_
+#define CINE_SOUND_H_
+
+#include "common/util.h"
+#include "sound/mixer.h"
+
+namespace Audio {
+	class AudioStream;
+}
+
+namespace Cine {
+
+class CineEngine;
+
+class Sound {
+public:
+
+	Sound(Audio::Mixer *mixer, CineEngine *vm) : _mixer(mixer), _vm(vm) {}
+	virtual ~Sound() {}
+
+	virtual void loadMusic(const char *name) = 0;
+	virtual void playMusic() = 0;
+	virtual void stopMusic() = 0;
+	virtual void fadeOutMusic() = 0;
+
+	virtual void playSound(int channel, int frequency, const uint8 *data, int size, int volumeStep, int stepCount, int volume, int repeat) = 0;
+	virtual void stopSound(int channel) = 0;
+	virtual void update() {}
+
+protected:
+
+	Audio::Mixer *_mixer;
+	CineEngine *_vm;
+};
+
+class PCSoundDriver;
+class PCSoundFxPlayer;
+
+class PCSound : public Sound {
+public:
+
+	PCSound(Audio::Mixer *mixer, CineEngine *vm);
+	virtual ~PCSound();
+
+	virtual void loadMusic(const char *name);
+	virtual void playMusic();
+	virtual void stopMusic();
+	virtual void fadeOutMusic();
+
+	virtual void playSound(int channel, int frequency, const uint8 *data, int size, int volumeStep, int stepCount, int volume, int repeat);
+	virtual void stopSound(int channel);
+
+protected:
+
+	PCSoundDriver *_soundDriver;
+	PCSoundFxPlayer *_player;
+};
+
+class PaulaSound : public Sound {
+public:
+
+	PaulaSound(Audio::Mixer *mixer, CineEngine *vm);
+	virtual ~PaulaSound();
+
+	virtual void loadMusic(const char *name);
+	virtual void playMusic();
+	virtual void stopMusic();
+	virtual void fadeOutMusic();
+
+	virtual void playSound(int channel, int frequency, const uint8 *data, int size, int volumeStep, int stepCount, int volume, int repeat);
+	virtual void stopSound(int channel);
+	virtual void update();
+
+	enum {
+		PAULA_FREQ = 7093789,
+		NUM_CHANNELS = 4,
+		SPL_HDR_SIZE = 22
+	};
+
+	struct SoundChannel {
+		int frequency;
+		const uint8 *data;
+		int size;
+		int volumeStep;
+		int stepCount;
+		int step;
+		bool repeat;
+		int volume;
+	};
+
+protected:
+
+	void playSoundChannel(int channel, int frequency, const uint8 *data, int size, int volume);
+
+	Audio::SoundHandle _channelsTable[NUM_CHANNELS];
+	SoundChannel _soundChannelsTable[NUM_CHANNELS];
+	Audio::SoundHandle _moduleHandle;
+	Audio::AudioStream *_moduleStream;
+};
+
+extern Sound *g_sound;
+
+} // End of namespace Cine
+
+#endif /* CINE_SOUND_H_ */

Deleted: scummvm/trunk/engines/cine/sound_driver.cpp
===================================================================
--- scummvm/trunk/engines/cine/sound_driver.cpp	2007-05-19 12:06:51 UTC (rev 26869)
+++ scummvm/trunk/engines/cine/sound_driver.cpp	2007-05-19 12:08:41 UTC (rev 26870)
@@ -1,495 +0,0 @@
-/* ScummVM - Scumm Interpreter
- * Copyright (C) 2006 The ScummVM project
- *
- * cinE Engine is (C) 2004-2005 by CinE Team
- *
- * 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$
- *
- */
-
-#include "common/stdafx.h"
-#include "common/endian.h"
-
-#include "cine/cine.h"
-#include "cine/sound_driver.h"
-
-#include "sound/mixer.h"
-
-namespace Cine {
-
-void SoundDriver::setUpdateCallback(UpdateCallback upCb, void *ref) {
-	_upCb = upCb;
-	_upRef = ref;
-}
-
-void SoundDriver::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;
-}
-
-void SoundDriver::resetChannel(int channel) {
-	stopChannel(channel);
-	stopSound();
-}
-
-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);
-}
-
-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);
-	}
-}
-
-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);
-	}
-}
-
-void AdlibSoundDriver::stopSound() {
-	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);
-}
-
-int AdlibSoundDriver::readBuffer(int16 *buffer, const int numSamples) {
-	update(buffer, numSamples);
-	return numSamples;
-}
-
-void AdlibSoundDriver::initCard() {
-	_vibrato = 0x20;
-	OPLWriteReg(_opl, 0xBD, _vibrato);
-	OPLWriteReg(_opl, 0x08, 0x40);
-	
-	int i;
-	for (i = 0; i < 18; ++i) {
-		OPLWriteReg(_opl, 0x40 | _operatorsTable[i], 0);
-	}
-	for (i = 0; i < 9; ++i) {
-		OPLWriteReg(_opl, 0xB0 | i, 0);
-	}
-	for (i = 0; i < 9; ++i) {
-		OPLWriteReg(_opl, 0xC0 | i, 0);
-	}
-	for (i = 0; i < 18; ++i) {
-		OPLWriteReg(_opl, 0x60 | _operatorsTable[i], 0);
-	}
-	for (i = 0; i < 18; ++i) {
-		OPLWriteReg(_opl, 0x80 | _operatorsTable[i], 0);
-	}
-	for (i = 0; i < 18; ++i) {
-		OPLWriteReg(_opl, 0x20 | _operatorsTable[i], 0);
-	}
-	for (i = 0; i < 18; ++i) {
-		OPLWriteReg(_opl, 0xE0 | _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;
-	}
-}
-
-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 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 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::playSound(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::playSound(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);
-	}
-}
-
-const int SoundDriver::_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
-};
-
-const int SoundDriver::_noteTableCount = ARRAYSIZE(_noteTable);
-
-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);
-
-
-PaulaSoundDriver::PaulaSoundDriver(Audio::Mixer *mixer)
-	: _mixer(mixer) {
-	memset(_channelsFreqTable, 0, sizeof(_channelsFreqTable));
-	memset(_soundsQueue, 0, sizeof(_soundsQueue));
-}
-
-void PaulaSoundDriver::setupChannel(int channel, const byte *data, int instrument, int volume) {
-}
-
-void PaulaSoundDriver::setChannelFrequency(int channel, int frequency) {
-	assert(frequency > 0);
-	_channelsFreqTable[channel] = PAULA_FREQ / frequency;
-}
-
-void PaulaSoundDriver::stopChannel(int channel) {
-	_mixer->stopHandle(_channelsTable[channel]);
-}
-
-void PaulaSoundDriver::playSound(const byte *data, int size, int channel, int volume) {
-	stopChannel(channel);
-	size = MIN<int>(size - SPL_HDR_SIZE, READ_BE_UINT16(data + 4));
-	data += SPL_HDR_SIZE;
-	if (size > 0) {
-		_mixer->playRaw(Audio::Mixer::kSFXSoundType, &_channelsTable[channel], const_cast<byte *>(data), size, _channelsFreqTable[channel], 0);	
-		_mixer->setChannelVolume(_channelsTable[channel], volume * Audio::Mixer::kMaxChannelVolume / 63);
-	}
-}
-
-void PaulaSoundDriver::stopSound() {
-	for (int i = 0; i < NUM_CHANNELS; ++i) {
-		_mixer->stopHandle(_channelsTable[i]);
-	}
-}
-
-void PaulaSoundDriver::queueSound(int channel, int frequency, const uint8 *data, int size, int volumeStep, int stepCount, int volume, int repeat) {
-	SoundQueue *sq = &_soundsQueue[channel];
-	sq->freq = frequency;
-	sq->data = data;
-	sq->size = size;
-	sq->volumeStep = volumeStep;
-	sq->stepCount = stepCount;
-	sq->step = stepCount;
-	sq->repeat = repeat != 0;
-	sq->volume = volume;
-}
-
-void PaulaSoundDriver::update() {
-	// process volume slides and start sound playback
-	for (int i = 0; i < NUM_CHANNELS; ++i) {
-		SoundQueue *sq = &_soundsQueue[i];
-		if (sq->data) {
-			if (sq->step) {
-				--sq->step;
-				continue;
-			}
-			sq->step = sq->stepCount;
-			sq->volume = CLIP(sq->volume + sq->volumeStep, 0, 63);
-			setChannelFrequency(i, sq->freq);
-			playSound(sq->data, sq->size, i, sq->volume);
-			if (!sq->repeat) {
-				sq->data = 0;
-			}
-		}
-	}
-}
-
-} // End of namespace Cine

Deleted: scummvm/trunk/engines/cine/sound_driver.h
===================================================================
--- scummvm/trunk/engines/cine/sound_driver.h	2007-05-19 12:06:51 UTC (rev 26869)
+++ scummvm/trunk/engines/cine/sound_driver.h	2007-05-19 12:08:41 UTC (rev 26870)
@@ -1,182 +0,0 @@
-/* ScummVM - Scumm Interpreter
- * Copyright (C) 2006 The ScummVM project
- *
- * cinE Engine is (C) 2004-2005 by CinE Team
- *
- * 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$
- *
- */
-
-#ifndef CINE_SOUNDDRIVER_H
-#define CINE_SOUNDDRIVER_H
-
-#include "sound/audiostream.h"
-#include "sound/fmopl.h"
-#include "sound/mixer.h"
-
-namespace Cine {
-
-class SoundDriver {
-public:
-	typedef void (*UpdateCallback)(void *);
-
-	virtual ~SoundDriver() {}
-
-	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 playSound(const byte *data, int size, int channel, int volume) = 0;
-	virtual void stopSound() = 0;
-	virtual const char *getInstrumentExtension() const { return ""; }
-	virtual void update() {}
-	
-	void setUpdateCallback(UpdateCallback upCb, void *ref);
-	void resetChannel(int channel);
-	void findNote(int freq, int *note, int *oct) const;
-
-protected:
-	UpdateCallback _upCb;
-	void *_upRef;
-
-	static const int _noteTable[];
-	static const int _noteTableCount;
-};
-
-struct AdlibRegisterSoundInstrument {
-	uint16 vibrato;
-	uint16 attackDecay;
-	uint16 sustainRelease;
-	uint16 feedbackStrength;
-	uint16 keyScaling;
-	uint16 outputLevel;
-	uint16 freqMod;
-};
-
-struct AdlibSoundInstrument {
-	byte mode;
-	byte channel;
-	AdlibRegisterSoundInstrument regMod;
-	AdlibRegisterSoundInstrument regCar;
-	byte waveSelectMod;
-	byte waveSelectCar;
-	byte amDepth;
-};
-	
-class AdlibSoundDriver : public SoundDriver, Audio::AudioStream {
-public:
-	AdlibSoundDriver(Audio::Mixer *mixer);
-	virtual ~AdlibSoundDriver();
-
-	// SoundDriver interface
-	virtual void setupChannel(int channel, const byte *data, int instrument, int volume);
-	virtual void stopChannel(int channel);
-	virtual void stopSound();
-
-	// 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;
-};
-
-// 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 playSound(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 playSound(const byte *data, int size, int channel, int volume);
-};
-
-class PaulaSoundDriver : public SoundDriver {
-public:
-	PaulaSoundDriver(Audio::Mixer *mixer);
-	
-	virtual void setupChannel(int channel, const byte *data, int instrument, int volume);
-	virtual void setChannelFrequency(int channel, int frequency);
-	virtual void stopChannel(int channel);
-	virtual void playSound(const byte *data, int size, int channel, int volume);
-	virtual void stopSound();
-	
-	// Future Wars specific
-	void queueSound(int channel, int frequency, const uint8 *data, int size, int volumeStep, int stepCount, int volume, int repeat);
-	virtual void update();
-
-	enum {
-		PAULA_FREQ = 7093789,
-		NUM_CHANNELS = 4,
-		SPL_HDR_SIZE = 22
-	};
-	
-	struct SoundQueue {
-		int freq;
-		const uint8 *data;
-		int size;
-		int volumeStep;
-		int stepCount;
-		int step;
-		bool repeat;
-		int volume;
-	};
-
-private:
-	Audio::Mixer *_mixer;
-	Audio::SoundHandle _channelsTable[NUM_CHANNELS];
-	uint _channelsFreqTable[NUM_CHANNELS];
-	SoundQueue _soundsQueue[NUM_CHANNELS];
-};
-
-extern SoundDriver *g_soundDriver; // TEMP
-
-} // End of namespace Cine
-
-#endif /* CINE_SOUNDDRIVER_H_ */

Modified: scummvm/trunk/engines/cine/various.cpp
===================================================================
--- scummvm/trunk/engines/cine/various.cpp	2007-05-19 12:06:51 UTC (rev 26869)
+++ scummvm/trunk/engines/cine/various.cpp	2007-05-19 12:08:41 UTC (rev 26870)
@@ -29,7 +29,7 @@
 #include "cine/cine.h"
 #include "cine/main_loop.h"
 #include "cine/object.h"
-#include "cine/sfx_player.h"
+#include "cine/sound.h"
 #include "cine/bg_list.h"
 #include "cine/various.h"
 
@@ -438,7 +438,7 @@
 		return false;
 	}
 
-	g_sfxPlayer->stop();
+	g_sound->stopMusic();
 	freeAnimDataTable();
 	unloadAllMasks();
 	// if (g_cine->getGameType() == Cine::GType_OS) {


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