[Scummvm-cvs-logs] SF.net SVN: scummvm: [26869] scummvm/trunk/sound

cyx at users.sourceforge.net cyx at users.sourceforge.net
Sat May 19 14:06:51 CEST 2007


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

Log Message:
-----------
added Amiga SoundFx module player code, used by Amiga versions of the following Delphine Software games : Future Wars, Operation Stealth, Cruise for a Corpse and Another World

Modified Paths:
--------------
    scummvm/trunk/sound/mods/paula.h
    scummvm/trunk/sound/module.mk

Added Paths:
-----------
    scummvm/trunk/sound/mods/soundfx.cpp
    scummvm/trunk/sound/mods/soundfx.h

Modified: scummvm/trunk/sound/mods/paula.h
===================================================================
--- scummvm/trunk/sound/mods/paula.h	2007-05-18 21:12:23 UTC (rev 26868)
+++ scummvm/trunk/sound/mods/paula.h	2007-05-19 12:06:51 UTC (rev 26869)
@@ -41,7 +41,7 @@
 	~Paula();
 
 	bool playing() const { return _playing; }
-	void setInterruptFreq(int freq) { _intFreq = freq; }
+	void setInterruptFreq(int freq) { _curInt = _intFreq = freq; }
 	void setPanning(byte voice, byte panning) {
 		assert(voice < NUM_VOICES);
 		_voice[voice].panning = panning;

Added: scummvm/trunk/sound/mods/soundfx.cpp
===================================================================
--- scummvm/trunk/sound/mods/soundfx.cpp	                        (rev 0)
+++ scummvm/trunk/sound/mods/soundfx.cpp	2007-05-19 12:06:51 UTC (rev 26869)
@@ -0,0 +1,298 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/stdafx.h"
+#include "common/endian.h"
+
+#include "sound/mods/paula.h"
+#include "sound/mods/soundfx.h"
+#include "sound/audiostream.h"
+
+namespace Audio {
+
+struct SoundFxInstrument {
+	uint8 name[23];
+	uint16 len;
+	uint8 finetune;
+	uint8 volume;
+	uint16 repeatPos;
+	uint16 repeatLen;
+	int8 *data;
+};
+
+class SoundFx : public Paula {
+public:
+
+	enum {
+		NUM_CHANNELS = 4,
+		NUM_INSTRUMENTS = 15,
+		CIA_FREQ = 715909
+	};
+
+	SoundFx(int rate, bool stereo);
+	virtual ~SoundFx();
+
+	bool load(Common::SeekableReadStream *data);
+	void play();
+
+protected:
+
+	void handlePattern(int ch, uint32 pat);
+	void updateEffects(int ch);
+	void handleTick();
+
+	void startPaula();
+	void stopPaula();
+	void setPaulaChannelPeriod(uint8 channel, int16 period);
+	void setPaulaChannelVolume(uint8 channel, uint8 volume);
+	void enablePaulaChannel(uint8 channel);
+	void disablePaulaChannel(uint8 channel);
+	void setupPaulaChannel(uint8 channel, const int8 *data, uint16 len, uint16 repeatPos, uint16 repeatLen);
+
+	virtual void interrupt();
+
+	uint8 _ticks;
+	uint16 _delay;
+	SoundFxInstrument _instruments[NUM_INSTRUMENTS];
+	uint8 _numOrders;
+	uint8 _curOrder;
+	uint16 _curPos;
+	uint8 _ordersTable[128];
+	uint8 *_patternData;
+	int8 *_instrumentData;
+	int _eventsFreq;
+	uint16 _effects[NUM_CHANNELS];
+};
+
+SoundFx::SoundFx(int rate, bool stereo)
+	: Paula(stereo, rate) {
+	_ticks = 0;
+	_delay = 0;
+	memset(_instruments, 0, sizeof(_instruments));
+	_numOrders = 0;
+	_curOrder = 0;
+	_curPos = 0;
+	memset(_ordersTable, 0, sizeof(_ordersTable));
+	_patternData = 0;
+	_instrumentData = 0;
+	_eventsFreq = 0;
+	memset(_effects, 0, sizeof(_effects));
+}
+
+SoundFx::~SoundFx() {
+	free(_patternData);
+	free(_instrumentData);
+}
+
+bool SoundFx::load(Common::SeekableReadStream *data) {
+	bool loaded = false;
+	int instrumentsSize[15];
+	int totalInstrumentsSize = 0;
+	for (int i = 0; i < NUM_INSTRUMENTS; ++i) {
+		instrumentsSize[i] = data->readUint32BE();
+		totalInstrumentsSize += instrumentsSize[i];
+	}
+	uint8 tag[4];
+	data->read(tag, 4);
+	if (memcmp(tag, "SONG", 4) == 0) {
+		_delay = data->readUint16BE();
+		data->skip(7 * 2);
+		for (int i = 0; i < NUM_INSTRUMENTS; ++i) {
+			SoundFxInstrument *ins = &_instruments[i];
+			data->read(ins->name, 22); ins->name[22] = 0;
+			ins->len = data->readUint16BE();
+			ins->finetune = data->readByte();
+			ins->volume = data->readByte();
+			ins->repeatPos = data->readUint16BE();
+			ins->repeatLen = data->readUint16BE();
+		}
+		_numOrders = data->readByte();
+		data->skip(1);
+		data->read(_ordersTable, 128);
+		int maxOrder = 0;
+		for (int i = 0; i < _numOrders; ++i) {
+			if (_ordersTable[i] > maxOrder) {
+				maxOrder = _ordersTable[i];
+			}
+		}
+		int patternSize = (maxOrder + 1) * 4 * 4 * 64;
+		_patternData = (uint8 *)malloc(patternSize);
+		if (_patternData) {
+			data->read(_patternData, patternSize);
+			_instrumentData = (int8 *)malloc(totalInstrumentsSize);
+			if (_instrumentData) {
+				data->read(_instrumentData, totalInstrumentsSize);
+				int8 *p = _instrumentData;
+				for (int i = 0; i < NUM_INSTRUMENTS; ++i) {
+					SoundFxInstrument *ins = &_instruments[i];
+					assert(ins->len <= 2 || ins->len * 2 <= instrumentsSize[i]);
+					assert(ins->repeatLen <= 2 || (ins->repeatPos + ins->repeatLen) * 2 <= instrumentsSize[i]);
+					if (instrumentsSize[i] != 0) {
+						ins->data = p;
+						p += instrumentsSize[i];
+					}
+				}
+				loaded = true;
+			}
+		}
+	}
+	return loaded;
+}
+
+void SoundFx::play() {
+	_curPos = 0;
+	_curOrder = 0;
+	_ticks = 0;
+	_eventsFreq = CIA_FREQ / _delay;
+	setInterruptFreq(_rate / _eventsFreq);
+	startPaula();
+}
+
+void SoundFx::handlePattern(int ch, uint32 pat) {
+	uint16 note1 = pat >> 16;
+	uint16 note2 = pat & 0xFFFF;
+	if (note1 != 0xFFFD) {
+		int ins = (note2 & 0xF000) >> 12;
+		if (ins != 0) {
+			SoundFxInstrument *i = &_instruments[ins - 1];
+			setupPaulaChannel(ch, i->data, i->len, i->repeatPos, i->repeatLen);
+			int effect = (note2 & 0xF00) >> 8;
+			int volume = i->volume;
+			switch (effect) {
+			case 5: // volume up
+				volume += (note2 & 0xFF);
+				if (volume > 63) {
+					volume = 63;
+				}
+				break;
+			case 6: // volume down
+				volume -= (note2 & 0xFF);
+				if (volume < 0) {
+					volume = 0;
+				}
+				break;
+			}
+			setPaulaChannelVolume(ch, volume);
+		}
+	}
+	_effects[ch] = note2;
+	if (note1 == 0xFFFD) { // PIC
+		_effects[ch] = 0;
+	} else if (note1 == 0xFFFE) { // STP
+		disablePaulaChannel(ch);
+	} else if (note1 != 0) {
+		setPaulaChannelPeriod(ch, note1);
+		enablePaulaChannel(ch);
+	}
+}
+
+void SoundFx::updateEffects(int ch) {
+	// updateEffects() is a no-op in all Delphine Software games using SoundFx : FW,OS,Cruise,AW
+	if (_effects[ch] != 0) {
+		switch (_effects[ch]) {
+		case 1: // appreggiato
+		case 2: // pitchbend
+		case 3: // ledon, enable low-pass filter
+		case 4: // ledoff, disable low-pass filter
+		case 7: // set step up
+		case 8: // set step down
+			warning("Unhandled effect %d\n", _effects[ch]);
+			break;
+		}
+	}
+}
+
+void SoundFx::handleTick() {
+	++_ticks;
+	if (_ticks != 6) {
+		for (int ch = 0; ch < 4; ++ch) {
+			updateEffects(ch);
+		}
+	} else {
+		_ticks = 0;
+		const uint8 *patternData = _patternData + _ordersTable[_curOrder] * 1024 + _curPos;
+		for (int ch = 0; ch < 4; ++ch) {
+			handlePattern(ch, READ_BE_UINT32(patternData));
+			patternData += 4;
+		}
+		_curPos += 4 * 4;
+		if (_curPos >= 1024) {
+			_curPos = 0;
+			++_curOrder;
+			if (_curOrder == _numOrders) {
+				stopPaula();
+			}
+		}
+	}
+}
+
+void SoundFx::startPaula() {
+	_playing = true;
+	_end = false;
+}
+
+void SoundFx::stopPaula() {
+	_playing = false;
+	_end = true;
+}
+
+void SoundFx::setPaulaChannelPeriod(uint8 channel, int16 period) {
+	_voice[channel].period = period;
+}
+
+void SoundFx::setPaulaChannelVolume(uint8 channel, uint8 volume) {
+	_voice[channel].volume = volume;
+}
+
+void SoundFx::enablePaulaChannel(uint8 channel) {
+}
+
+void SoundFx::disablePaulaChannel(uint8 channel) {
+	_voice[channel].period = 0;
+}
+
+void SoundFx::setupPaulaChannel(uint8 channel, const int8 *data, uint16 len, uint16 repeatPos, uint16 repeatLen) {
+	if (data && len > 1) {
+		Channel *ch = &_voice[channel];
+		ch->data = data;
+		ch->dataRepeat = data + repeatPos * 2;
+		ch->length = len * 2;
+		ch->lengthRepeat = repeatLen * 2;
+		ch->offset = 0;
+	}
+}
+
+void SoundFx::interrupt() {
+	handleTick();
+}
+
+AudioStream *makeSoundFxStream(Common::SeekableReadStream *data, int rate, bool stereo) {
+	SoundFx *stream = new SoundFx(rate, stereo);
+	if (stream->load(data)) {
+		stream->play();
+		return stream;
+	}
+	delete stream;
+	return 0;
+}
+
+} // End of namespace Audio


Property changes on: scummvm/trunk/sound/mods/soundfx.cpp
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Date Rev Author URL Id
Name: svn:eol-style
   + native

Added: scummvm/trunk/sound/mods/soundfx.h
===================================================================
--- scummvm/trunk/sound/mods/soundfx.h	                        (rev 0)
+++ scummvm/trunk/sound/mods/soundfx.h	2007-05-19 12:06:51 UTC (rev 26869)
@@ -0,0 +1,37 @@
+
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef SOUND_MODS_SOUNDFX_H
+#define SOUND_MODS_SOUNDFX_H
+
+#include "common/stream.h"
+
+namespace Audio {
+
+class AudioStream;
+
+AudioStream *makeSoundFxStream(Common::SeekableReadStream *data, int rate = 44100, bool stereo = true);
+
+} // End of namespace Audio
+
+#endif


Property changes on: scummvm/trunk/sound/mods/soundfx.h
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Date Rev Author URL Id
Name: svn:eol-style
   + native

Modified: scummvm/trunk/sound/module.mk
===================================================================
--- scummvm/trunk/sound/module.mk	2007-05-18 21:12:23 UTC (rev 26868)
+++ scummvm/trunk/sound/module.mk	2007-05-19 12:06:51 UTC (rev 26869)
@@ -25,6 +25,7 @@
 	mods/protracker.o \
 	mods/paula.o \
 	mods/rjp1.o \
+	mods/soundfx.o \
 	softsynth/adlib.o \
 	softsynth/ym2612.o \
 	softsynth/fluidsynth.o \


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