aboutsummaryrefslogtreecommitdiff
path: root/backends/midi/mt32.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'backends/midi/mt32.cpp')
-rw-r--r--backends/midi/mt32.cpp243
1 files changed, 243 insertions, 0 deletions
diff --git a/backends/midi/mt32.cpp b/backends/midi/mt32.cpp
new file mode 100644
index 0000000000..2931e94c71
--- /dev/null
+++ b/backends/midi/mt32.cpp
@@ -0,0 +1,243 @@
+/* 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$
+ */
+
+#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