[Scummvm-cvs-logs] CVS: scummvm/scumm player_mod.cpp,NONE,2.1 player_mod.h,NONE,2.1 player_v2a.cpp,NONE,2.1 player_v2a.h,NONE,2.1 debugger.cpp,1.89,1.90 module.mk,1.25,1.26 player_v3a.cpp,1.11,1.12 player_v3a.h,1.8,1.9 scumm.h,1.303,1.304 scummvm.cpp,2.400,2.401 sound.cpp,1.254,1.255

Travis Howell kirben at users.sourceforge.net
Tue Sep 23 23:58:02 CEST 2003


Update of /cvsroot/scummvm/scummvm/scumm
In directory sc8-pr-cvs1:/tmp/cvs-serv13731/scumm

Modified Files:
	debugger.cpp module.mk player_v3a.cpp player_v3a.h scumm.h 
	scummvm.cpp sound.cpp 
Added Files:
	player_mod.cpp player_mod.h player_v2a.cpp player_v2a.h 
Log Message:

More Amiga V2/V3 sound updates from _Q_:
1. A Player_MOD class, basically acts as a simplified mixer that mixes at 60Hz intervals (or whatever interval you specify), this gives smooth music playback in player_v3a
2. Some changes to player_v3a as a result of #1, including reduced music volume
3. player_v2a, and the necessary additions to scummvm.cpp/scumm.h


--- NEW FILE: player_mod.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2001  Ludvig Strigeus
 * Copyright (C) 2001-2003 The ScummVM project
 *
 * 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/scumm/player_mod.cpp,v 2.1 2003/09/24 06:56:30 kirben Exp $
 *
 */

#include "player_mod.h"

////////////////////////////////////////
//
// Generic Amiga MOD mixer - provides a 60Hz 'update' routine.
//
////////////////////////////////////////

Player_MOD::Player_MOD(Scumm *scumm) {
	int i;
	_mixer = scumm->_mixer;
	_samplerate = scumm->_system->property(OSystem::PROP_GET_SAMPLE_RATE, 0);
	_mixamt = 0;
	_mixpos = 0;

	for (i = 0; i < MOD_MAXCHANS; i++) {
		_channels[i].id = 0;
		_channels[i].vol = 0;
		_channels[i].freq = 0;
		_channels[i].ptr = NULL;
		_channels[i].converter = NULL;
		_channels[i].input = NULL;
	}

	_playproc = NULL;
	_playparam = NULL;

	_mixer->setupPremix(premix_proc, this);
}

Player_MOD::~Player_MOD() {
	// Detach the premix callback handler
	_mixer->setupPremix(0, 0);
	for (int i = 0; i < MOD_MAXCHANS; i++) {
		if (!_channels[i].id)
			continue;
		delete _channels[i].ptr;
		delete _channels[i].converter;
		delete _channels[i].input;
	}
}

void Player_MOD::setMasterVolume (int vol) {
	_maxvol = vol;
}

void Player_MOD::setUpdateProc(ModUpdateProc *proc, void *param, int freq) {
	_playproc = proc;
	_playparam = param;
	_mixamt = _samplerate / freq;
}
void Player_MOD::clearUpdateProc() {
	_playproc = NULL;
	_playparam = NULL;
	_mixamt = 0;
}

void Player_MOD::startChannel (int id, const char *data, int size, int rate, uint8 vol, int loopStart, int loopEnd, int8 pan) {
	int i;
	if (id == 0)
		error("player_mod - attempted to start channel id 0");

	for (i = 0; i < MOD_MAXCHANS; i++) {
		if (!_channels[i].id)
			break;
	}
	if (i == MOD_MAXCHANS) {
		warning("player_mod - too many music channels playing (%i max)",MOD_MAXCHANS);
		return;
	}
	_channels[i].id = id;
	_channels[i].vol = vol;
	_channels[i].pan = pan;
	_channels[i].ptr = (byte *)data;
	_channels[i].freq = rate;
	_channels[i].input = makeLinearInputStream(SoundMixer::FLAG_AUTOFREE | (loopStart != loopEnd ? SoundMixer::FLAG_LOOP : 0), (byte *)data, size, loopStart, loopEnd - loopStart);
	_channels[i].converter = makeRateConverter(rate, _mixer->getOutputRate(), false, false);
}

void Player_MOD::stopChannel(int id) {
	if (id == 0)
		error("player_mod - attempted to stop channel id 0");
	for (int i = 0; i < MOD_MAXCHANS; i++) {
		if (_channels[i].id == id) {
			delete _channels[i].ptr;
			_channels[i].ptr = NULL;
			delete _channels[i].converter;
			_channels[i].converter = NULL;
			delete _channels[i].input;
			_channels[i].input = NULL;
			_channels[i].id = 0;
			_channels[i].vol = 0;
			_channels[i].freq = 0;
		}
	}
}
void Player_MOD::setChannelVol(int id, uint8 vol) {
	if (id == 0)
		error("player_mod - attempted to set volume for channel id 0");
	for (int i = 0; i < MOD_MAXCHANS; i++) {
		if (_channels[i].id == id) {
			_channels[i].vol = vol;
			break;
		}
	}
}

void Player_MOD::setChannelPan(int id, int8 pan) {
	if (id == 0)
		error("player_mod - attempted to set pan for channel id 0");
	for (int i = 0; i < MOD_MAXCHANS; i++) {
		if (_channels[i].id == id) {
			_channels[i].pan = pan;
			break;
		}
	}
}

void Player_MOD::setChannelFreq(int id, int freq) {
	if (id == 0)
		error("player_mod - attempted to set frequency for channel id 0");
	for (int i = 0; i < MOD_MAXCHANS; i++) {
		if (_channels[i].id == id) {
			_channels[i].freq = freq;
			delete _channels[i].converter;
			_channels[i].converter = makeRateConverter(freq, _mixer->getOutputRate(), false, false);
			break;
		}
	}
}

void Player_MOD::premix_proc(void *param, int16 *buf, uint len) {
	((Player_MOD *) param)->do_mix(buf, len);
}

void Player_MOD::do_mix (int16 *data, uint len) {
	int i;
	int dpos = 0;
	uint dlen = 0;
	memset(data, 0, 2 * len * sizeof(int16));
	while (len) {
		if (_playproc) {
			dlen = _mixamt - _mixpos;
			if (!_mixpos)
				_playproc(_playparam);
			if (dlen <= len) {
				_mixpos = 0;
				len -= dlen;
			} else {
				_mixpos = _mixamt - len;
				dlen = len;
				len = 0;
			}
		} else {
			dlen = len;
			len = 0;
		}
		for (i = 0; i < MOD_MAXCHANS; i++)
			if (_channels[i].id) {
				st_volume_t vol_l = (127 - _channels[i].pan) * _channels[i].vol / 127;
				st_volume_t vol_r = (127 + _channels[i].pan) * _channels[i].vol / 127;
				_channels[i].converter->flow(*_channels[i].input, &data[dpos*2], dlen, vol_l, vol_r);
			}
		dpos += dlen;
	}
}

--- NEW FILE: player_mod.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2001  Ludvig Strigeus
 * Copyright (C) 2001-2003 The ScummVM project
 *
 * 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/scumm/player_mod.h,v 2.1 2003/09/24 06:56:30 kirben Exp $
 *
 */

#ifndef PLAYER_MOD_H
#define PLAYER_MOD_H

#include "scumm.h"
#include "sound/mixer.h"
#include "sound/audiostream.h"
#include "sound/rate.h"

#define	MOD_MAXCHANS	16

class Player_MOD {
public:
	Player_MOD(Scumm *scumm);
	virtual ~Player_MOD();
	virtual void setMasterVolume(int vol);

	virtual void startChannel(int id, const char *data, int size, int rate, uint8 vol, int loopStart = 0, int loopEnd = 0, int8 pan = 0);
	virtual void stopChannel(int id);
	virtual void setChannelVol(int id, uint8 vol);
	virtual void setChannelPan(int id, int8 pan);
	virtual void setChannelFreq(int id, int freq);

	typedef void ModUpdateProc(void *param);

	virtual void setUpdateProc(ModUpdateProc *proc, void *param, int freq);
	virtual void clearUpdateProc();

private:
	SoundMixer *_mixer;

	uint32 _mixamt;
	uint32 _mixpos;
	int _samplerate;

	struct soundChan
	{
		int id;
		uint8 vol;
		int8 pan;
		uint16 freq;
		byte *ptr;
		RateConverter *converter;
		AudioInputStream *input;
	} _channels[MOD_MAXCHANS];

	uint8 _maxvol;

	static void premix_proc(void *param, int16 *buf, uint len);
	virtual void do_mix(int16 *buf, uint len);
	
	ModUpdateProc *_playproc;
	void *_playparam;
};

#endif

--- NEW FILE: player_v2a.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2001  Ludvig Strigeus
 * Copyright (C) 2001-2003 The ScummVM project
 *
 * 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/scumm/player_v2a.cpp,v 2.1 2003/09/24 06:56:30 kirben Exp $
[...1268 lines suppressed...]
	for (i = 0; i < V2A_MAXSLOTS; i++) {
		if ((_slot[i].id) && (!_slot[i].sound->update())) {
			_slot[i].sound->stop();
			_slot[i].sound = NULL;
			_slot[i].id = 0;
		}
	}
}

int Player_V2A::getMusicTimer() const {
	return 0;	// FIXME - need to keep track of playing music resources
}

int Player_V2A::getSoundStatus(int nr) const {
	for (int i = 0; i < V2A_MAXSLOTS; i++) {
		if (_slot[i].id == nr)
			return 1;
	}
	return 0;
}

--- NEW FILE: player_v2a.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2001  Ludvig Strigeus
 * Copyright (C) 2001-2003 The ScummVM project
 *
 * 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/scumm/player_v2a.h,v 2.1 2003/09/24 06:56:30 kirben Exp $
 *
 */

#ifndef PLAYER_V2A_H
#define PLAYER_V2A_H

#include "common/scummsys.h"
#include "common/system.h"
#include "scumm/music.h"
#include "scumm/player_mod.h"

#define	V2A_MAXSLOTS 8

class Scumm;
class SoundMixer;

class V2A_Sound;

class Player_V2A : public MusicEngine {
public:
	Player_V2A(Scumm *scumm);
	virtual ~Player_V2A();

	virtual void setMasterVolume(int vol);
	virtual void startSound(int nr);
	virtual void stopSound(int nr);
	virtual void stopAllSounds();
	virtual int  getMusicTimer() const;
	virtual int  getSoundStatus(int nr) const;

private:
	OSystem *_system;
	Scumm *_scumm;
	Player_MOD *_mod;

	struct soundSlot
	{
		int id;
		V2A_Sound *sound;
	} _slot[V2A_MAXSLOTS];
	int getSoundSlot (int id = 0) const;

	static void update_proc(void *param);
	void updateSound();
};

#endif

Index: debugger.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/debugger.cpp,v
retrieving revision 1.89
retrieving revision 1.90
diff -u -d -r1.89 -r1.90
--- debugger.cpp	24 Sep 2003 06:33:58 -0000	1.89
+++ debugger.cpp	24 Sep 2003 06:56:30 -0000	1.90
@@ -361,7 +361,7 @@
 }
 
 bool ScummDebugger::Cmd_IMuse(int argc, const char **argv) {
-	if (!_s->_imuse && !_s->_playerV2) {
+	if (!_s->_imuse && !_s->_musicEngine) {
 		Debug_Printf("No iMuse engine is active.\n");
 		return true;
 	}

Index: module.mk
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/module.mk,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -d -r1.25 -r1.26
--- module.mk	18 Sep 2003 13:03:56 -0000	1.25
+++ module.mk	24 Sep 2003 06:56:30 -0000	1.26
@@ -22,9 +22,11 @@
 	scumm/midiparser_eup.o \
 	scumm/nut_renderer.o \
 	scumm/object.o \
-	scumm/player_v1.o\
-	scumm/player_v2.o\
-	scumm/player_v3a.o\
+	scumm/player_mod.o \
+	scumm/player_v1.o \
+	scumm/player_v2.o \
+	scumm/player_v2a.o \
+	scumm/player_v3a.o \
 	scumm/resource.o \
 	scumm/resource_v2.o \
 	scumm/resource_v3.o \

Index: player_v3a.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/player_v3a.cpp,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- player_v3a.cpp	18 Sep 2003 19:56:38 -0000	1.11
+++ player_v3a.cpp	24 Sep 2003 06:56:30 -0000	1.12
@@ -24,8 +24,6 @@
 #include "base/engine.h"
 #include "player_v3a.h"
 #include "scumm.h"
-#include "sound/mixer.h"
-#include "common/timer.h"
 
 static const uint16 note_freqs[4][12] = {
 	{0x06B0,0x0650,0x05F4,0x05A0,0x054C,0x0500,0x04B8,0x0474,0x0434,0x03F8,0x03C0,0x0388},
@@ -44,13 +42,14 @@
 	int i;
 	_scumm = scumm;
 	_system = scumm->_system;
-	_mixer = scumm->_mixer;
-
-	for (i = 0; i < V3A_MAXSFX; i++)
-		_sfx[i].id = _sfx[i].dur = 0;
-
-	for (i = 0; i < V3A_MAXMUS; i++)
-		_mus[i].id = _mus[i].dur = 0;
+	for (i = 0; i < V3A_MAXMUS; i++) {
+		_mus[i].id = 0;
+		_mus[i].dur = 0;
+	}
+	for (i = 0; i < V3A_MAXSFX; i++) {
+		_sfx[i].id = 0;
+		_sfx[i].dur = 0;
+	}
 
 	_curSong = 0;
 	_songData = NULL;
@@ -59,36 +58,63 @@
 
 	_music_timer = 0;
 
-	_maxvol = 255;
-
-	scumm->_timer->installProcedure(timerHandler, 16666, this);
-
 	_isinit = false;
+
+	_mod = new Player_MOD(scumm);
+	_mod->setUpdateProc(update_proc, this, 60);
 }
 
 Player_V3A::~Player_V3A() {
-	_scumm->_timer->releaseProcedure(timerHandler);
-	if (!_isinit)
-		return;
-	for (int i = 0; _wavetable[i] != NULL; i++) {
-		for (int j = 0; j < 6; j++) {
-			free(_wavetable[i]->_idat[j]);
-			free(_wavetable[i]->_ldat[j]);
+	int i;
+	delete _mod;
+	if (_isinit) {
+		for (i = 0; _wavetable[i] != NULL; i++) {
+			for (int j = 0; j < 6; j++) {
+				free(_wavetable[i]->_idat[j]);
+				free(_wavetable[i]->_ldat[j]);
+			}
+			free(_wavetable[i]);
 		}
-		free(_wavetable[i]);
+		free(_wavetable);
 	}
-	free(_wavetable);
 }
 
 void Player_V3A::setMasterVolume (int vol) {
-	_maxvol = vol;
+	_mod->setMasterVolume(vol);
+}
+
+int Player_V3A::getMusChan (int id) const {
+	int i;
+	for (i = 0; i < V3A_MAXMUS; i++) {
+		if (_mus[i].id == id)
+			break;
+	}
+	if (i == V3A_MAXMUS) {
+		if (id == 0)
+			warning("player_v3a - out of music channels");
+		return -1;
+	}
+	return i;
+}
+int Player_V3A::getSfxChan (int id) const {
+	int i;
+	for (i = 0; i < V3A_MAXSFX; i++) {
+		if (_sfx[i].id == id)
+			break;
+	}
+	if (i == V3A_MAXSFX) {
+		if (id == 0)
+			warning("player_v3a - out of sfx channels");
+		return -1;
+	}
+	return i;
 }
 
 void Player_V3A::stopAllSounds() {
 	int i;
 	for (i = 0; i < V3A_MAXMUS; i++) {
 		if (_mus[i].id)
-			_mixer->stopID(V3A_MUS_BASEID + i);
+			_mod->stopChannel(_mus[i].id);
 		_mus[i].id = 0;
 		_mus[i].dur = 0;
 	}
@@ -98,7 +124,7 @@
 	_songData = NULL;
 	for (i = 0; i < V3A_MAXSFX; i++) {
 		if (_sfx[i].id)
-			_mixer->stopID(V3A_SFX_BASEID + i);
+			_mod->stopChannel(_sfx[i].id | 0x100);
 		_sfx[i].id = 0;
 		_sfx[i].dur = 0;
 	}
@@ -106,10 +132,14 @@
 
 void Player_V3A::stopSound(int nr) {
 	int i;
+	if (nr == 0) {	// Amiga Loom does this near the end, when Chaos casts SILENCE on Hetchel
+		stopAllSounds();
+		return;
+	}
 	if (nr == _curSong) {
 		for (i = 0; i < V3A_MAXMUS; i++) {
 			if (_mus[i].id)
-				_mixer->stopID(V3A_MUS_BASEID + i);
+				_mod->stopChannel(_mus[i].id);
 			_mus[i].id = 0;
 			_mus[i].dur = 0;
 		}
@@ -118,59 +148,21 @@
 		_songDelay = 0;
 		_songData = NULL;
 	} else {
-		for (i = 0; i < V3A_MAXSFX; i++) {
-			if (_sfx[i].id == nr) {
-				_mixer->stopID(V3A_SFX_BASEID + i);
-				_sfx[i].id = 0;
-				_sfx[i].dur = 0;
-				break;
-			}
+		i = getSfxChan(nr);
+		if (i != -1) {
+			_mod->stopChannel(nr | 0x100);
+			_sfx[i].id = 0;
+			_sfx[i].dur = 0;
 		}
 	}
 }
 
-void Player_V3A::playSoundSFX (int nr, char *data, int size, int rate, int vol, int tl, bool looped, int loopStart, int loopEnd) {
-	int i;
-	for (i = 0; i < V3A_MAXSFX; i++) {
-		if (!_sfx[i].id)
-			break;
-	}
-	if (i == V3A_MAXSFX) {
-		warning("player_v3a - too many sound effects playing (%i max)",V3A_MAXSFX);
-		return;
-	}
-	_sfx[i].id = nr;
-	_sfx[i].dur = tl;
-
-	vol = (vol * _maxvol) / 255;
-	_mixer->playRaw(NULL, data, size, rate, SoundMixer::FLAG_AUTOFREE | (looped ? SoundMixer::FLAG_LOOP : 0),
-		V3A_SFX_BASEID + i, vol, 0, loopStart, loopEnd);
-}
-
-void Player_V3A::playSoundMUS (char *data, int size, int rate, int vol, int tl, bool looped, int loopStart, int loopEnd) {
-	int i;
-	for (i = 0; i < V3A_MAXMUS; i++) {
-		if (!_mus[i].id)
-			break;
-	}
-	if (i == V3A_MAXMUS) {
-		warning("player_v3a - too many music channels playing (%i max)",V3A_MAXMUS);
-		return;
-	}
-	_mus[i].id = i + 1;
-	_mus[i].dur = tl;
-
-	vol = (vol * _maxvol) / 255;
-	_mixer->playRaw(NULL, data, size, rate, SoundMixer::FLAG_AUTOFREE | (looped ? SoundMixer::FLAG_LOOP : 0),
-		V3A_MUS_BASEID + i, vol, 0, loopStart, loopEnd);
-}
-
 void Player_V3A::startSound(int nr) {
 	assert(_scumm);
 	byte *data = _scumm->getResourceAddress(rtSound, nr);
 	assert(data);
 
-	if (_scumm->_gameId != GID_INDY3 && _scumm->_gameId != GID_LOOM)
+	if ((_scumm->_gameId != GID_INDY3) && (_scumm->_gameId != GID_LOOM))
 		error("player_v3a - unknown game!");
 
 	if (!_isinit) {
@@ -223,6 +215,8 @@
 		stopSound(nr);	// if a sound is playing, restart it
 	
 	if (data[26]) {
+		if (_curSong)
+			stopSound(_curSong);
 		_curSong = nr;
 		_songData = data;
 		_songPtr = 0x1C;
@@ -232,43 +226,49 @@
 		int size = READ_BE_UINT16(data + 12);
 		int rate = 3579545 / READ_BE_UINT16(data + 20);
 		char *sound = (char *)malloc(size);
-		int vol = (data[24] << 2) | (data[24] >> 4);
+		int vol = (data[24] << 1) | (data[24] >> 5);	// if I boost this to 0-255, it gets too loud and starts to clip
 		memcpy(sound,data + READ_BE_UINT16(data + 8),size);
+		int loopStart = 0, loopEnd = 0;
+		bool looped = false;
 		if ((READ_BE_UINT16(data + 16) || READ_BE_UINT16(data + 6))) {
-			// the first check is for complex (pitch-bending) looped sounds
-			// the second check is for simple looped sounds
-			int loopStart = READ_BE_UINT16(data + 10) - READ_BE_UINT16(data + 8);
-			int loopEnd = READ_BE_UINT16(data + 14);
-			int tl = -1;
-			if ((_scumm->_gameId == GID_INDY3) && (nr == 60))
-				tl = 240;	// the "airplane dive" sound needs to end on its own - the game won't stop it
-			playSoundSFX(nr, sound, size, rate, vol, tl, true, loopStart, loopEnd);
-		} else {
-			int tl = 1 + 60 * size / rate;
-			playSoundSFX(nr, sound, size, rate, vol, tl, false);
+			loopStart = READ_BE_UINT16(data + 10) - READ_BE_UINT16(data + 8);
+			loopEnd = READ_BE_UINT16(data + 14);
+			looped = true;
 		}
+		int i = getSfxChan();
+		_sfx[i].id = nr;
+		_sfx[i].dur = looped ? -1 : (1 + 60 * size / rate);
+		if ((_scumm->_gameId == GID_INDY3) && (nr == 60))
+			_sfx[i].dur = 240;
+		_mod->startChannel(nr | 0x100, sound, size, rate, vol, loopStart, loopEnd);
 	}
 }
 
-void Player_V3A::timerHandler(void *refCon) {
-	Player_V3A *player = (Player_V3A *)refCon;
-	assert(player);
-	player->playMusic();
+void Player_V3A::update_proc(void *param) {
+	((Player_V3A *)param)->playMusic();
 }
 
 void Player_V3A::playMusic() {
 	int i;
-	for (i = 0; i < V3A_MAXSFX; i++) {
-		if ((_sfx[i].dur) && (!--_sfx[i].dur))
-			stopSound(_sfx[i].id);
-	}
 	for (i = 0; i < V3A_MAXMUS; i++) {
-		if ((_mus[i].dur) && (!--_mus[i].dur)) {
-			_scumm->_mixer->stopID(V3A_MUS_BASEID + i);
+		if (_mus[i].id) {
+			_mus[i].dur--;
+			if (_mus[i].dur)
+				continue;
+			_mod->stopChannel(_mus[i].id);
 			_mus[i].id = 0;
-			_mus[i].dur = 0;
 		}
 	}
+	for (i = 0; i < V3A_MAXSFX; i++) {
+		if (_sfx[i].id) {
+			_sfx[i].dur--;
+			if (_sfx[i].dur)
+				continue;
+			_mod->stopChannel(_sfx[i].id | 0x100);
+			_sfx[i].id = 0;
+		}
+	}
+
 	_music_timer++;
 	if (!_curSong)
 		return;
@@ -295,8 +295,7 @@
 		}
 		inst &= 0xF;
 		pit = _songData[_songPtr++];
-		vol = _songData[_songPtr++] & 0x7F;
-		vol = (vol << 1) | (vol >> 7);	// 7-bit volume (Amiga drops the bottom bit), convert to 8-bit
+		vol = _songData[_songPtr++] & 0x7F;	// if I boost this to 0-255, it gets too loud and starts to clip
 		dur = _songData[_songPtr++];
 		if (pit == 0) {
 			_songDelay = dur;
@@ -309,13 +308,18 @@
 			oct = 0;
 		if (oct > 5)
 			oct = 5;
+		int rate = 3579545 / note_freqs[_wavetable[inst]->_oct[oct]][pit];
 		char *data = (char *)malloc(_wavetable[inst]->_ilen[oct] + _wavetable[inst]->_llen[oct]);
 		if (_wavetable[inst]->_idat[oct])
 			memcpy(data, _wavetable[inst]->_idat[oct], _wavetable[inst]->_ilen[oct]);
 		if (_wavetable[inst]->_ldat[oct])
 			memcpy(data + _wavetable[inst]->_ilen[oct], _wavetable[inst]->_ldat[oct], _wavetable[inst]->_llen[oct]);
-		playSoundMUS(data, _wavetable[inst]->_ilen[oct] + _wavetable[inst]->_llen[oct], 3579545 / note_freqs[_wavetable[inst]->_oct[oct]][pit], vol, dur,
-			(_wavetable[inst]->_ldat[oct] != NULL), _wavetable[inst]->_ilen[oct], _wavetable[inst]->_ilen[oct] + _wavetable[inst]->_llen[oct]);
+
+		i = getMusChan();
+		_mus[i].id = i + 1;
+		_mus[i].dur = dur;
+		_mod->startChannel(_mus[i].id, data, _wavetable[inst]->_ilen[oct] + _wavetable[inst]->_llen[oct], rate, vol,
+			_wavetable[inst]->_ilen[oct], _wavetable[inst]->_ilen[oct] + _wavetable[inst]->_llen[oct]);
 	}
 }
 
@@ -326,8 +330,7 @@
 int Player_V3A::getSoundStatus(int nr) const {
 	if (nr == _curSong)
 		return 1;
-	for (int i = 0; i < V3A_MAXSFX; i++)
-		if (_sfx[i].id == nr)
-			return 1;
+	if (getSfxChan(nr) != -1)
+		return 1;
 	return 0;
 }

Index: player_v3a.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/player_v3a.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- player_v3a.h	18 Sep 2003 19:56:38 -0000	1.8
+++ player_v3a.h	24 Sep 2003 06:56:30 -0000	1.9
@@ -26,12 +26,10 @@
 #include "common/scummsys.h"
 #include "common/system.h"
 #include "scumm/music.h"
+#include "scumm/player_mod.h"
 
-#define V3A_MAXMUS 8
-#define V3A_MAXSFX 8
-
-#define	V3A_MUS_BASEID	(1)
-#define	V3A_SFX_BASEID	(V3A_MUS_BASEID + V3A_MAXMUS)
+#define	V3A_MAXMUS	8
+#define	V3A_MAXSFX	8
 
 class Scumm;
 class SoundMixer;
@@ -42,26 +40,31 @@
 	virtual ~Player_V3A();
 
 	virtual void setMasterVolume(int vol);
-
 	virtual void startSound(int nr);
 	virtual void stopSound(int nr);
 	virtual void stopAllSounds();
 	virtual int  getMusicTimer() const;
-
 	virtual int  getSoundStatus(int nr) const;
 
-protected:
-	SoundMixer *_mixer;
+private:
 	OSystem *_system;
 	Scumm *_scumm;
+	Player_MOD *_mod;
 
-	struct soundChan
+	struct musChan
 	{
-		uint16 id;
-		uint16 dur;
-	} _mus[V3A_MAXMUS], _sfx[V3A_MAXSFX];
-	
-	uint8 _maxvol;
+		int id;
+		int dur;
+	} _mus[V3A_MAXMUS];
+	int getMusChan (int id = 0) const;
+
+	struct sfxChan
+	{
+		int id;
+		int dur;
+		// SFX will eventually have pitch bends
+	} _sfx[V3A_MAXSFX];
+	int getSfxChan (int id = 0) const;
 
 	int _curSong;
 	uint8 *_songData;
@@ -80,11 +83,8 @@
 		int16 _pitadjust;
 	} **_wavetable;
 
-	void playSoundSFX (int nr, char *data, int size, int rate, int vol, int tl, bool looped, int loopStart = 0, int loopEnd = 0);
-	void playSoundMUS (char *data, int size, int rate, int vol, int tl, bool looped, int loopStart = 0, int loopEnd = 0);
-
+	static void update_proc(void *param);
 	void playMusic();
-	static void timerHandler(void *engine);
 };
 
 #endif

Index: scumm.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/scumm.h,v
retrieving revision 1.303
retrieving revision 1.304
diff -u -d -r1.303 -r1.304
--- scumm.h	18 Sep 2003 02:07:17 -0000	1.303
+++ scumm.h	24 Sep 2003 06:56:30 -0000	1.304
@@ -43,6 +43,7 @@
 class MusicEngine;
 class NewGui;
 class Player_V2;
+class Player_V2A;
 class Player_V3A;
 class Scumm;
 class ScummDebugger;
@@ -260,6 +261,7 @@
 	IMuse *_imuse;
 	IMuseDigital *_imuseDigital;
 	Player_V2 *_playerV2;
+	Player_V2A *_playerV2A;
 	Player_V3A *_playerV3A;
 	MusicEngine *_musicEngine;
 	Sound *_sound;

Index: scummvm.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/scummvm.cpp,v
retrieving revision 2.400
retrieving revision 2.401
diff -u -d -r2.400 -r2.401
--- scummvm.cpp	24 Sep 2003 05:59:32 -0000	2.400
+++ scummvm.cpp	24 Sep 2003 06:56:30 -0000	2.401
@@ -44,6 +44,7 @@
 #include "scumm/object.h"
 #include "scumm/player_v1.h"
 #include "scumm/player_v2.h"
+#include "scumm/player_v2a.h"
 #include "scumm/player_v3a.h"
 #include "scumm/resource.h"
 #include "scumm/scumm.h"
@@ -719,10 +720,13 @@
 	_imuse = NULL;
 	_imuseDigital = NULL;
 	_playerV2 = NULL;
+	_playerV2A = NULL;
 	_playerV3A = NULL;
 	_musicEngine = NULL;
 	if (_features & GF_DIGI_IMUSE) {
 		_musicEngine = _imuseDigital = new IMuseDigital(this);
+	} else if ((_features & GF_AMIGA) && (_version == 2)) {
+		_musicEngine = _playerV2A = new Player_V2A(this);
 	} else if ((_features & GF_AMIGA) && (_version == 3)) {
 		_musicEngine = _playerV3A = new Player_V3A(this);
 	} else if ((_features & GF_AMIGA) && (_version < 5)) {
@@ -1329,6 +1333,8 @@
 		// Covered automatically by the Sound class
 	} else if (_playerV2) {
 		VAR(VAR_MUSIC_TIMER) = _playerV2->getMusicTimer();
+	} else if (_playerV2A) {
+		VAR(VAR_MUSIC_TIMER) = _playerV2A->getMusicTimer();
 	} else if (_playerV3A) {
 		VAR(VAR_MUSIC_TIMER) = _playerV3A->getMusicTimer();
 	} else if (_imuse) {

Index: sound.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/sound.cpp,v
retrieving revision 1.254
retrieving revision 1.255
diff -u -d -r1.254 -r1.255
--- sound.cpp	24 Sep 2003 06:33:59 -0000	1.254
+++ sound.cpp	24 Sep 2003 06:56:30 -0000	1.255
@@ -25,8 +25,6 @@
 #include "bundle.h"
 #include "imuse.h"
 #include "imuse_digi.h"
-#include "player_v2.h"
-#include "player_v3a.h"
 #include "scumm.h"
 #include "sound.h"
 
@@ -437,28 +435,6 @@
 		sound = (char *)malloc(size);
 		int vol = ptr[24] * 4;
 		memcpy(sound,ptr + READ_BE_UINT16(ptr + 8), size);
-		_scumm->_mixer->playRaw(NULL, sound, size, rate, SoundMixer::FLAG_AUTOFREE, soundID, vol, 0);
-	}
-	else if ((_scumm->_features & GF_AMIGA) && (_scumm->_version <= 2) && READ_BE_UINT16(ptr + 14) == 0x0880) {
-		size = READ_BE_UINT16(ptr + 6);
-		int start = READ_BE_UINT16(ptr + 8);
-		start += 10;
-		rate = 11000;
-		int vol = 255;
-		int i = 0;
-
-		while (i < start) {
-			if ((READ_BE_UINT16(ptr) == 0x357c) && (READ_BE_UINT16(ptr + 4) == 6))
-				rate = 3579545 / READ_BE_UINT16(ptr + 2);
-
-			if ((READ_BE_UINT16(ptr) == 0x357c) && (READ_BE_UINT16(ptr + 4) == 8))
-				vol = READ_BE_UINT16(ptr + 2) * 4;
-			ptr += 2;
-			i += 2;
-		}
-
-		sound = (char *)malloc(size);
-		memcpy(sound, ptr, size);
 		_scumm->_mixer->playRaw(NULL, sound, size, rate, SoundMixer::FLAG_AUTOFREE, soundID, vol, 0);
 	}
 	else {





More information about the Scummvm-git-logs mailing list