[Scummvm-cvs-logs] CVS: scummvm/backends/midi mt32.cpp,NONE,1.1

Eugene Sandulenko sev at users.sourceforge.net
Fri Nov 5 17:46:34 CET 2004


Update of /cvsroot/scummvm/scummvm/backends/midi
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv27409/backends/midi

Added Files:
	mt32.cpp 
Log Message:
Major MT-32 emu overhaul based on KingGuppy's code.
 o added configure option
 o mi2 intro doesn't freeze anymore and has no sound glitches
 o missing instruments in many titles are fixed
 o numerous memory overwrite bugs are fixed
 o code is cleaned a lot and splitted into many smaller files
 o mt32.cpp went to backends/midi
 o synced with upstream code
 o reverberation fixed

 * don't complain about File class wrapper :)
 * all custom types are back
 * #pragmas are to do
 * maybe some indentation is wrong too

I prefer smaller commits, but this thing came in one piece.


--- NEW FILE: mt32.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2001-2004 The ScummVM project
 *
 * YM2612 tone generation code written by Tomoaki Hayasaka.
 * Used under the terms of the GNU General Public License.
 * Adpated to ScummVM by Jamieson Christian.
 *
 * 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/backends/midi/mt32.cpp,v 1.1 2004/11/06 01:41:29 sev Exp $
 */

#include "stdafx.h"
#include "common/scummsys.h"

#ifdef USE_MT32EMU

#include "backends/midi/mt32/mt32emu.h"

#include "backends/midi/emumidi.h"
#include "sound/mpu401.h"

#include "common/util.h"
#include "common/file.h"
#include "common/config-manager.h"

class MidiDriver_MT32 : public MidiDriver_Emulated {
private:
	MidiChannel_MPU401 _midi_channels[16];
	uint16 _channel_mask;
	MT32Emu::Synth *_synth;

	int _outputRate;

protected:
	void generate_samples(int16 *buf, int len);

public:
	MidiDriver_MT32(SoundMixer *mixer);
	virtual ~MidiDriver_MT32();

	int open();
	void close();
	void send(uint32 b);
	void sysEx(byte *msg, uint16 length);

	uint32 property(int prop, uint32 param);
	MidiChannel *allocateChannel();
	MidiChannel *getPercussionChannel();

	// AudioStream API
	bool isStereo() const { return true; }
	int getRate() const { return _outputRate; }
};

typedef File SFile;

class MT32File: public MT32Emu::File {
	SFile file;
public:
	bool open(const char *filename, OpenMode mode) {
		SFile::AccessMode accessMode = mode == OpenMode_read ? SFile::kFileReadMode : SFile::kFileWriteMode;
		return file.open(filename, accessMode);
	}
	void close() {
		return file.close();
	}
	size_t read(void *ptr, size_t size) {
		return file.read(ptr, size);
	}
	bool readLine(char *ptr, size_t size) {
		return file.gets(ptr, size) != NULL;
	}
	size_t write(const void *ptr, size_t size) {
		return file.write(ptr, size);
	}
	int readByte() {
		byte b = file.readByte();
		if (file.eof())
			return -1;
		return b;
	}
	bool writeByte(unsigned char out) {
		file.writeByte(out);
		if (file.ioFailed())
			return false;
		return true;
	}
	bool isEOF() {
		return file.eof();
	}
};

MT32Emu::File *MT32_OpenFile(void *userData, const char *filename, MT32Emu::File::OpenMode mode) {
	MT32File *file = new MT32File();
	if (!file->open(filename, mode)) {
		delete file;
		return NULL;
	}
	return file;
}

////////////////////////////////////////
//
// MidiDriver_MT32
//
////////////////////////////////////////

void report(int type, ...) {}

MidiDriver_MT32::MidiDriver_MT32(SoundMixer *mixer) : MidiDriver_Emulated(mixer) {
	_channel_mask = 0xFFFF; // Permit all 16 channels by default
	uint i;
	for (i = 0; i < ARRAYSIZE(_midi_channels); ++i) {
		_midi_channels [i].init (this, i);
	}
	_synth = NULL;

	_baseFreq = 1000;

	_outputRate = 44100;
}

MidiDriver_MT32::~MidiDriver_MT32() {
	if (_synth != NULL)
		delete _synth;
}

static void vdebug(void *data, const char *fmt, va_list list) {
	// do nothing here now
}

int MidiDriver_MT32::open() {
	MT32Emu::SynthProperties prop;

	if (_isOpen)
		return MERR_ALREADY_OPEN;

	MidiDriver_Emulated::open();
	
	memset(&prop, 0, sizeof(prop));
	prop.SampleRate = getRate();
	prop.UseReverb = true;
	prop.UseDefault = false;
	prop.RevType = 0;
	prop.RevTime = 5;
	prop.RevLevel = 3;
	prop.userData = (void *)1;
	prop.printDebug = &vdebug;
	prop.openFile = MT32_OpenFile;
	_synth = new MT32Emu::Synth();
	if (!_synth->open(prop))
		return MERR_DEVICE_NOT_AVAILABLE;

	_mixer->setupPremix(this);

	return 0;
}

void MidiDriver_MT32::send(uint32 b) {
	_synth->playMsg(b);
}

void MidiDriver_MT32::sysEx(byte *msg, uint16 length) {
	if (msg[0] == 0xf0) {
		_synth->playSysex(msg, length);
	} else {
		_synth->playSysexWithoutFraming(msg, length);
	}
}

void MidiDriver_MT32::close() {
	if (!_isOpen)
		return;
	_isOpen = false;

	// Detach the premix callback handler
	_mixer->setupPremix(0);

	_synth->close();
	delete _synth;
	_synth = NULL;
}

void MidiDriver_MT32::generate_samples(int16 *data, int len) {
	_synth->render(data, len);
}

uint32 MidiDriver_MT32::property (int prop, uint32 param) {
	switch (prop) {
		case PROP_CHANNEL_MASK:
			_channel_mask = param & 0xFFFF;
			return 1;
	}

	return 0;
}

MidiChannel *MidiDriver_MT32::allocateChannel() {
	MidiChannel_MPU401 *chan;
	uint i;

	for (i = 0; i < ARRAYSIZE(_midi_channels); ++i) {
		if (i == 9 || !(_channel_mask & (1 << i)))
			continue;
		chan = &_midi_channels[i];
		if (chan->allocate()) {
			return chan;
		}
	}
	return NULL;
}

MidiChannel *MidiDriver_MT32::getPercussionChannel() {
	return &_midi_channels [9];
}

////////////////////////////////////////
//
// MidiDriver_MT32 factory
//
////////////////////////////////////////

MidiDriver *MidiDriver_MT32_create(SoundMixer *mixer) {
	// HACK: It will stay here until engine plugin loader overhaul
	if (ConfMan.hasKey("extrapath"))                                        
		File::addDefaultDirectory(ConfMan.get("extrapath"));
	return new MidiDriver_MT32(mixer);
}

#endif





More information about the Scummvm-git-logs mailing list