- DOSBox pathes now use mt32emu API type 3

- Added version checks
This commit is contained in:
sergm
2017-03-05 18:45:06 +02:00
parent 9850356144
commit 9638fcaf2e
2 changed files with 198 additions and 144 deletions

View File

@@ -59,10 +59,10 @@ index 61d15e5..0ec8ebc 100644
Bitu cmd_len;
diff --git a/src/gui/midi_mt32.cpp b/src/gui/midi_mt32.cpp
new file mode 100644
index 0000000..7c34fca
index 0000000..3f66f66
--- /dev/null
+++ b/src/gui/midi_mt32.cpp
@@ -0,0 +1,269 @@
@@ -0,0 +1,298 @@
+#include <SDL_thread.h>
+#include <SDL_endian.h>
+#include "control.h"
@@ -85,6 +85,17 @@ index 0000000..7c34fca
+}
+
+bool MidiHandler_mt32::Open(const char *conf) {
+ service = new MT32Emu::Service();
+ Bit32u version = service->getLibraryVersionInt();
+ if (version < 0x020100) {
+ delete service;
+ service = NULL;
+ LOG_MSG("MT32: libmt32emu version is too old: %s", service->getLibraryVersionString());
+ return false;
+ }
+ service->createContext(getReportHandlerInterface(), this);
+ mt32emu_return_code rc;
+
+ Section_prop *section = static_cast<Section_prop *>(control->GetSection("midi"));
+ const char *romDir = section->Get_string("mt32.romdir");
+ if (romDir == NULL) romDir = "./"; // Paranoid NULL-check, should never happen
@@ -101,59 +112,58 @@ index 0000000..7c34fca
+ }
+
+ char pathName[4096];
+ MT32Emu::FileStream controlROMFile;
+ MT32Emu::FileStream pcmROMFile;
+
+ makeROMPathName(pathName, romDir, "CM32L_CONTROL.ROM", addPathSeparator);
+ if (!controlROMFile.open(pathName)) {
+ if (MT32EMU_RC_ADDED_CONTROL_ROM != service->addROMFile(pathName)) {
+ makeROMPathName(pathName, romDir, "MT32_CONTROL.ROM", addPathSeparator);
+ if (!controlROMFile.open(pathName)) {
+ if (MT32EMU_RC_ADDED_CONTROL_ROM != service->addROMFile(pathName)) {
+ delete service;
+ service = NULL;
+ LOG_MSG("MT32: Control ROM file not found");
+ return false;
+ }
+ }
+ makeROMPathName(pathName, romDir, "CM32L_PCM.ROM", addPathSeparator);
+ if (!pcmROMFile.open(pathName)) {
+ if (MT32EMU_RC_ADDED_PCM_ROM != service->addROMFile(pathName)) {
+ makeROMPathName(pathName, romDir, "MT32_PCM.ROM", addPathSeparator);
+ if (!pcmROMFile.open(pathName)) {
+ if (MT32EMU_RC_ADDED_PCM_ROM != service->addROMFile(pathName)) {
+ delete service;
+ service = NULL;
+ LOG_MSG("MT32: PCM ROM file not found");
+ return false;
+ }
+ }
+ const MT32Emu::ROMImage *controlROMImage = MT32Emu::ROMImage::makeROMImage(&controlROMFile);
+ const MT32Emu::ROMImage *pcmROMImage = MT32Emu::ROMImage::makeROMImage(&pcmROMFile);
+
+ MT32Emu::AnalogOutputMode analogOutputMode = (MT32Emu::AnalogOutputMode)section->Get_int("mt32.analog");
+ service->setPartialCount(Bit32u(section->Get_int("mt32.partials")));
+ service->setAnalogOutputMode((MT32Emu::AnalogOutputMode)section->Get_int("mt32.analog"));
+ int sampleRate = section->Get_int("mt32.rate");
+ service->setStereoOutputSampleRate(sampleRate);
+ service->setSamplerateConversionQuality((MT32Emu::SamplerateConversionQuality)section->Get_int("mt32.src.quality"));
+
+ synth = new MT32Emu::Synth(&reportHandler);
+ if (!synth->open(*controlROMImage, *pcmROMImage, section->Get_int("mt32.partials"), analogOutputMode)) {
+ delete synth;
+ synth = NULL;
+ LOG_MSG("MT32: Error initialising emulation");
+ if (MT32EMU_RC_OK != (rc = service->openSynth())) {
+ delete service;
+ service = NULL;
+ LOG_MSG("MT32: Error initialising emulation: %i", rc);
+ return false;
+ }
+ MT32Emu::ROMImage::freeROMImage(controlROMImage);
+ MT32Emu::ROMImage::freeROMImage(pcmROMImage);
+
+ if (strcmp(section->Get_string("mt32.reverb.mode"), "auto") != 0) {
+ Bit8u reverbsysex[] = {0x10, 0x00, 0x01, 0x00, 0x05, 0x03};
+ reverbsysex[3] = (Bit8u)atoi(section->Get_string("mt32.reverb.mode"));
+ reverbsysex[4] = (Bit8u)section->Get_int("mt32.reverb.time");
+ reverbsysex[5] = (Bit8u)section->Get_int("mt32.reverb.level");
+ synth->writeSysex(16, reverbsysex, 6);
+ synth->setReverbOverridden(true);
+ service->writeSysex(16, reverbsysex, 6);
+ service->setReverbOverridden(true);
+ }
+
+ synth->setDACInputMode((MT32Emu::DACInputMode)section->Get_int("mt32.dac"));
+ service->setDACInputMode((MT32Emu::DACInputMode)section->Get_int("mt32.dac"));
+
+ synth->setReversedStereoEnabled(section->Get_bool("mt32.reverse.stereo"));
+ service->setReversedStereoEnabled(section->Get_bool("mt32.reverse.stereo"));
+ noise = section->Get_bool("mt32.verbose");
+ renderInThread = section->Get_bool("mt32.thread");
+
+ if (noise) LOG_MSG("MT32: Set maximum number of partials %d", synth->getPartialCount());
+ if (noise) LOG_MSG("MT32: Set maximum number of partials %d", service->getPartialCount());
+
+ int sampleRate = section->Get_int("mt32.rate");
+ src = new MT32Emu::SampleRateConverter(*synth, sampleRate, (MT32Emu::SamplerateConversionQuality)section->Get_int("mt32.src.quality"));
+ if (noise) LOG_MSG("MT32: Adding mixer channel at sample rate %d", sampleRate);
+ chan = MIXER_AddChannel(mixerCallBack, sampleRate, "MT32");
+
@@ -170,7 +180,7 @@ index 0000000..7c34fca
+ framesPerAudioBuffer = (latency * sampleRate) / MILLIS_PER_SECOND;
+ audioBufferSize = framesPerAudioBuffer << 1;
+ audioBuffer = new Bit16s[audioBufferSize];
+ src->getOutputSamples(audioBuffer, framesPerAudioBuffer - 1);
+ service->renderBit16s(audioBuffer, framesPerAudioBuffer - 1);
+ renderPos = (framesPerAudioBuffer - 1) << 1;
+ playedBuffers = 1;
+ lock = SDL_CreateMutex();
@@ -202,27 +212,25 @@ index 0000000..7c34fca
+ }
+ MIXER_DelChannel(chan);
+ chan = NULL;
+ delete src;
+ src = NULL;
+ synth->close();
+ delete synth;
+ synth = NULL;
+ service->closeSynth();
+ delete service;
+ service = NULL;
+ open = false;
+}
+
+void MidiHandler_mt32::PlayMsg(Bit8u *msg) {
+ if (renderInThread) {
+ synth->playMsg(SDL_SwapLE32(*(Bit32u *)msg), getMidiEventTimestamp());
+ service->playMsgAt(SDL_SwapLE32(*(Bit32u *)msg), getMidiEventTimestamp());
+ } else {
+ synth->playMsg(SDL_SwapLE32(*(Bit32u *)msg));
+ service->playMsg(SDL_SwapLE32(*(Bit32u *)msg));
+ }
+}
+
+void MidiHandler_mt32::PlaySysex(Bit8u *sysex, Bitu len) {
+ if (renderInThread) {
+ synth->playSysex(sysex, len, getMidiEventTimestamp());
+ service->playSysexAt(sysex, len, getMidiEventTimestamp());
+ } else {
+ synth->playSysex(sysex, len);
+ service->playSysex(sysex, len);
+ }
+}
+
@@ -243,7 +251,49 @@ index 0000000..7c34fca
+ strcat(pathName, fileName);
+}
+
+MidiHandler_mt32::MidiHandler_mt32() : open(false), chan(NULL), synth(NULL), src(NULL), thread(NULL) {
+mt32emu_report_handler_i MidiHandler_mt32::getReportHandlerInterface() {
+ class ReportHandler {
+ public:
+ static mt32emu_report_handler_version getReportHandlerVersionID(mt32emu_report_handler_i) {
+ return MT32EMU_REPORT_HANDLER_VERSION_0;
+ }
+
+ static void printDebug(void *instance_data, const char *fmt, va_list list) {
+ MidiHandler_mt32 &midiHandler_mt32 = *(MidiHandler_mt32 *)instance_data;
+ if (midiHandler_mt32.noise) {
+ char s[1024];
+ vsnprintf(s, 1023, fmt, list);
+ LOG_MSG("MT32: %s", s);
+ }
+ }
+
+ static void onErrorControlROM(void *) {
+ LOG_MSG("MT32: Couldn't open Control ROM file");
+ }
+
+ static void onErrorPCMROM(void *) {
+ LOG_MSG("MT32: Couldn't open PCM ROM file");
+ }
+
+ static void showLCDMessage(void *, const char *message) {
+ LOG_MSG("MT32: LCD-Message: %s", message);
+ }
+ };
+
+ static const mt32emu_report_handler_i_v0 REPORT_HANDLER_V0_IMPL = {
+ ReportHandler::getReportHandlerVersionID,
+ ReportHandler::printDebug,
+ ReportHandler::onErrorControlROM,
+ ReportHandler::onErrorPCMROM,
+ ReportHandler::showLCDMessage
+ };
+
+ static const mt32emu_report_handler_i REPORT_HANDLER_I = { &REPORT_HANDLER_V0_IMPL };
+
+ return REPORT_HANDLER_I;
+}
+
+MidiHandler_mt32::MidiHandler_mt32() : open(false), chan(NULL), service(NULL), thread(NULL) {
+}
+
+MidiHandler_mt32::~MidiHandler_mt32() {
@@ -279,7 +329,7 @@ index 0000000..7c34fca
+ SDL_UnlockMutex(lock);
+ }
+ } else {
+ src->getOutputSamples((Bit16s *)MixTemp, len);
+ service->renderBit16s((Bit16s *)MixTemp, len);
+ chan->AddSamples_s16(len, (Bit16s *)MixTemp);
+ }
+}
@@ -301,7 +351,7 @@ index 0000000..7c34fca
+ SDL_CondWait(framesInBufferChanged, lock);
+ SDL_UnlockMutex(lock);
+ } else {
+ src->getOutputSamples(audioBuffer + renderPosSnap, framesToRender);
+ service->renderBit16s(audioBuffer + renderPosSnap, framesToRender);
+ renderPos = (renderPosSnap + samplesToRender) % audioBufferSize;
+ if (renderPosSnap == playPos) {
+ SDL_LockMutex(lock);
@@ -311,39 +361,24 @@ index 0000000..7c34fca
+ }
+ }
+}
+
+void MidiHandler_mt32::MT32ReportHandler::onErrorControlROM() {
+ LOG_MSG("MT32: Couldn't open Control ROM file");
+}
+
+void MidiHandler_mt32::MT32ReportHandler::onErrorPCMROM() {
+ LOG_MSG("MT32: Couldn't open PCM ROM file");
+}
+
+void MidiHandler_mt32::MT32ReportHandler::showLCDMessage(const char *message) {
+ LOG_MSG("MT32: LCD-Message: %s", message);
+}
+
+void MidiHandler_mt32::MT32ReportHandler::printDebug(const char *fmt, va_list list) {
+ MidiHandler_mt32 &midiHandler_mt32 = MidiHandler_mt32::GetInstance();
+ if (midiHandler_mt32.noise) {
+ char s[1024];
+ vsnprintf(s, 1023, fmt, list);
+ LOG_MSG("MT32: %s", s);
+ }
+}
diff --git a/src/gui/midi_mt32.h b/src/gui/midi_mt32.h
new file mode 100644
index 0000000..087f5a1
index 0000000..eb32729
--- /dev/null
+++ b/src/gui/midi_mt32.h
@@ -0,0 +1,57 @@
@@ -0,0 +1,55 @@
+#ifndef DOSBOX_MIDI_MT32_H
+#define DOSBOX_MIDI_MT32_H
+
+#include "mixer.h"
+
+#define MT32EMU_API_TYPE 3
+#include <mt32emu/mt32emu.h>
+
+#if MT32EMU_VERSION_MAJOR != 2 || MT32EMU_VERSION_MINOR < 1
+#error Incompatible mt32emu library version
+#endif
+
+struct SDL_Thread;
+
+class MidiHandler_mt32 : public MidiHandler {
@@ -358,8 +393,7 @@ index 0000000..087f5a1
+
+private:
+ MixerChannel *chan;
+ MT32Emu::Synth *synth;
+ MT32Emu::SampleRateConverter *src;
+ MT32Emu::Service *service;
+ SDL_Thread *thread;
+ SDL_mutex *lock;
+ SDL_cond *framesInBufferChanged;
@@ -371,23 +405,16 @@ index 0000000..087f5a1
+ volatile bool stopProcessing;
+ bool open, noise, renderInThread;
+
+ class MT32ReportHandler : public MT32Emu::ReportHandler {
+ protected:
+ virtual void onErrorControlROM();
+ virtual void onErrorPCMROM();
+ virtual void showLCDMessage(const char *message);
+ virtual void printDebug(const char *fmt, va_list list);
+ } reportHandler;
+
+ static void mixerCallBack(Bitu len);
+ static int processingThread(void *);
+ static void makeROMPathName(char pathName[], const char romDir[], const char fileName[], bool addPathSeparator);
+ static mt32emu_report_handler_i getReportHandlerInterface();
+
+ MidiHandler_mt32();
+ ~MidiHandler_mt32();
+
+ Bit32u inline getMidiEventTimestamp() {
+ return Bit32u(src->convertOutputToSynthTimestamp(playedBuffers * framesPerAudioBuffer + (playPos >> 1)));
+ return service->convertOutputToSynthTimestamp(Bit32u(playedBuffers * framesPerAudioBuffer + (playPos >> 1)));
+ }
+
+ void handleMixerCallBack(Bitu len);

View File

@@ -57,10 +57,10 @@ index 57181e0..3bc943b 100644
void MIDI_RawOutByte(Bit8u data) {
diff --git a/src/gui/midi_mt32.cpp b/src/gui/midi_mt32.cpp
new file mode 100644
index 0000000..7c34fca
index 0000000..3f66f66
--- /dev/null
+++ b/src/gui/midi_mt32.cpp
@@ -0,0 +1,269 @@
@@ -0,0 +1,298 @@
+#include <SDL_thread.h>
+#include <SDL_endian.h>
+#include "control.h"
@@ -83,6 +83,17 @@ index 0000000..7c34fca
+}
+
+bool MidiHandler_mt32::Open(const char *conf) {
+ service = new MT32Emu::Service();
+ Bit32u version = service->getLibraryVersionInt();
+ if (version < 0x020100) {
+ delete service;
+ service = NULL;
+ LOG_MSG("MT32: libmt32emu version is too old: %s", service->getLibraryVersionString());
+ return false;
+ }
+ service->createContext(getReportHandlerInterface(), this);
+ mt32emu_return_code rc;
+
+ Section_prop *section = static_cast<Section_prop *>(control->GetSection("midi"));
+ const char *romDir = section->Get_string("mt32.romdir");
+ if (romDir == NULL) romDir = "./"; // Paranoid NULL-check, should never happen
@@ -99,59 +110,58 @@ index 0000000..7c34fca
+ }
+
+ char pathName[4096];
+ MT32Emu::FileStream controlROMFile;
+ MT32Emu::FileStream pcmROMFile;
+
+ makeROMPathName(pathName, romDir, "CM32L_CONTROL.ROM", addPathSeparator);
+ if (!controlROMFile.open(pathName)) {
+ if (MT32EMU_RC_ADDED_CONTROL_ROM != service->addROMFile(pathName)) {
+ makeROMPathName(pathName, romDir, "MT32_CONTROL.ROM", addPathSeparator);
+ if (!controlROMFile.open(pathName)) {
+ if (MT32EMU_RC_ADDED_CONTROL_ROM != service->addROMFile(pathName)) {
+ delete service;
+ service = NULL;
+ LOG_MSG("MT32: Control ROM file not found");
+ return false;
+ }
+ }
+ makeROMPathName(pathName, romDir, "CM32L_PCM.ROM", addPathSeparator);
+ if (!pcmROMFile.open(pathName)) {
+ if (MT32EMU_RC_ADDED_PCM_ROM != service->addROMFile(pathName)) {
+ makeROMPathName(pathName, romDir, "MT32_PCM.ROM", addPathSeparator);
+ if (!pcmROMFile.open(pathName)) {
+ if (MT32EMU_RC_ADDED_PCM_ROM != service->addROMFile(pathName)) {
+ delete service;
+ service = NULL;
+ LOG_MSG("MT32: PCM ROM file not found");
+ return false;
+ }
+ }
+ const MT32Emu::ROMImage *controlROMImage = MT32Emu::ROMImage::makeROMImage(&controlROMFile);
+ const MT32Emu::ROMImage *pcmROMImage = MT32Emu::ROMImage::makeROMImage(&pcmROMFile);
+
+ MT32Emu::AnalogOutputMode analogOutputMode = (MT32Emu::AnalogOutputMode)section->Get_int("mt32.analog");
+ service->setPartialCount(Bit32u(section->Get_int("mt32.partials")));
+ service->setAnalogOutputMode((MT32Emu::AnalogOutputMode)section->Get_int("mt32.analog"));
+ int sampleRate = section->Get_int("mt32.rate");
+ service->setStereoOutputSampleRate(sampleRate);
+ service->setSamplerateConversionQuality((MT32Emu::SamplerateConversionQuality)section->Get_int("mt32.src.quality"));
+
+ synth = new MT32Emu::Synth(&reportHandler);
+ if (!synth->open(*controlROMImage, *pcmROMImage, section->Get_int("mt32.partials"), analogOutputMode)) {
+ delete synth;
+ synth = NULL;
+ LOG_MSG("MT32: Error initialising emulation");
+ if (MT32EMU_RC_OK != (rc = service->openSynth())) {
+ delete service;
+ service = NULL;
+ LOG_MSG("MT32: Error initialising emulation: %i", rc);
+ return false;
+ }
+ MT32Emu::ROMImage::freeROMImage(controlROMImage);
+ MT32Emu::ROMImage::freeROMImage(pcmROMImage);
+
+ if (strcmp(section->Get_string("mt32.reverb.mode"), "auto") != 0) {
+ Bit8u reverbsysex[] = {0x10, 0x00, 0x01, 0x00, 0x05, 0x03};
+ reverbsysex[3] = (Bit8u)atoi(section->Get_string("mt32.reverb.mode"));
+ reverbsysex[4] = (Bit8u)section->Get_int("mt32.reverb.time");
+ reverbsysex[5] = (Bit8u)section->Get_int("mt32.reverb.level");
+ synth->writeSysex(16, reverbsysex, 6);
+ synth->setReverbOverridden(true);
+ service->writeSysex(16, reverbsysex, 6);
+ service->setReverbOverridden(true);
+ }
+
+ synth->setDACInputMode((MT32Emu::DACInputMode)section->Get_int("mt32.dac"));
+ service->setDACInputMode((MT32Emu::DACInputMode)section->Get_int("mt32.dac"));
+
+ synth->setReversedStereoEnabled(section->Get_bool("mt32.reverse.stereo"));
+ service->setReversedStereoEnabled(section->Get_bool("mt32.reverse.stereo"));
+ noise = section->Get_bool("mt32.verbose");
+ renderInThread = section->Get_bool("mt32.thread");
+
+ if (noise) LOG_MSG("MT32: Set maximum number of partials %d", synth->getPartialCount());
+ if (noise) LOG_MSG("MT32: Set maximum number of partials %d", service->getPartialCount());
+
+ int sampleRate = section->Get_int("mt32.rate");
+ src = new MT32Emu::SampleRateConverter(*synth, sampleRate, (MT32Emu::SamplerateConversionQuality)section->Get_int("mt32.src.quality"));
+ if (noise) LOG_MSG("MT32: Adding mixer channel at sample rate %d", sampleRate);
+ chan = MIXER_AddChannel(mixerCallBack, sampleRate, "MT32");
+
@@ -168,7 +178,7 @@ index 0000000..7c34fca
+ framesPerAudioBuffer = (latency * sampleRate) / MILLIS_PER_SECOND;
+ audioBufferSize = framesPerAudioBuffer << 1;
+ audioBuffer = new Bit16s[audioBufferSize];
+ src->getOutputSamples(audioBuffer, framesPerAudioBuffer - 1);
+ service->renderBit16s(audioBuffer, framesPerAudioBuffer - 1);
+ renderPos = (framesPerAudioBuffer - 1) << 1;
+ playedBuffers = 1;
+ lock = SDL_CreateMutex();
@@ -200,27 +210,25 @@ index 0000000..7c34fca
+ }
+ MIXER_DelChannel(chan);
+ chan = NULL;
+ delete src;
+ src = NULL;
+ synth->close();
+ delete synth;
+ synth = NULL;
+ service->closeSynth();
+ delete service;
+ service = NULL;
+ open = false;
+}
+
+void MidiHandler_mt32::PlayMsg(Bit8u *msg) {
+ if (renderInThread) {
+ synth->playMsg(SDL_SwapLE32(*(Bit32u *)msg), getMidiEventTimestamp());
+ service->playMsgAt(SDL_SwapLE32(*(Bit32u *)msg), getMidiEventTimestamp());
+ } else {
+ synth->playMsg(SDL_SwapLE32(*(Bit32u *)msg));
+ service->playMsg(SDL_SwapLE32(*(Bit32u *)msg));
+ }
+}
+
+void MidiHandler_mt32::PlaySysex(Bit8u *sysex, Bitu len) {
+ if (renderInThread) {
+ synth->playSysex(sysex, len, getMidiEventTimestamp());
+ service->playSysexAt(sysex, len, getMidiEventTimestamp());
+ } else {
+ synth->playSysex(sysex, len);
+ service->playSysex(sysex, len);
+ }
+}
+
@@ -241,7 +249,49 @@ index 0000000..7c34fca
+ strcat(pathName, fileName);
+}
+
+MidiHandler_mt32::MidiHandler_mt32() : open(false), chan(NULL), synth(NULL), src(NULL), thread(NULL) {
+mt32emu_report_handler_i MidiHandler_mt32::getReportHandlerInterface() {
+ class ReportHandler {
+ public:
+ static mt32emu_report_handler_version getReportHandlerVersionID(mt32emu_report_handler_i) {
+ return MT32EMU_REPORT_HANDLER_VERSION_0;
+ }
+
+ static void printDebug(void *instance_data, const char *fmt, va_list list) {
+ MidiHandler_mt32 &midiHandler_mt32 = *(MidiHandler_mt32 *)instance_data;
+ if (midiHandler_mt32.noise) {
+ char s[1024];
+ vsnprintf(s, 1023, fmt, list);
+ LOG_MSG("MT32: %s", s);
+ }
+ }
+
+ static void onErrorControlROM(void *) {
+ LOG_MSG("MT32: Couldn't open Control ROM file");
+ }
+
+ static void onErrorPCMROM(void *) {
+ LOG_MSG("MT32: Couldn't open PCM ROM file");
+ }
+
+ static void showLCDMessage(void *, const char *message) {
+ LOG_MSG("MT32: LCD-Message: %s", message);
+ }
+ };
+
+ static const mt32emu_report_handler_i_v0 REPORT_HANDLER_V0_IMPL = {
+ ReportHandler::getReportHandlerVersionID,
+ ReportHandler::printDebug,
+ ReportHandler::onErrorControlROM,
+ ReportHandler::onErrorPCMROM,
+ ReportHandler::showLCDMessage
+ };
+
+ static const mt32emu_report_handler_i REPORT_HANDLER_I = { &REPORT_HANDLER_V0_IMPL };
+
+ return REPORT_HANDLER_I;
+}
+
+MidiHandler_mt32::MidiHandler_mt32() : open(false), chan(NULL), service(NULL), thread(NULL) {
+}
+
+MidiHandler_mt32::~MidiHandler_mt32() {
@@ -277,7 +327,7 @@ index 0000000..7c34fca
+ SDL_UnlockMutex(lock);
+ }
+ } else {
+ src->getOutputSamples((Bit16s *)MixTemp, len);
+ service->renderBit16s((Bit16s *)MixTemp, len);
+ chan->AddSamples_s16(len, (Bit16s *)MixTemp);
+ }
+}
@@ -299,7 +349,7 @@ index 0000000..7c34fca
+ SDL_CondWait(framesInBufferChanged, lock);
+ SDL_UnlockMutex(lock);
+ } else {
+ src->getOutputSamples(audioBuffer + renderPosSnap, framesToRender);
+ service->renderBit16s(audioBuffer + renderPosSnap, framesToRender);
+ renderPos = (renderPosSnap + samplesToRender) % audioBufferSize;
+ if (renderPosSnap == playPos) {
+ SDL_LockMutex(lock);
@@ -309,39 +359,24 @@ index 0000000..7c34fca
+ }
+ }
+}
+
+void MidiHandler_mt32::MT32ReportHandler::onErrorControlROM() {
+ LOG_MSG("MT32: Couldn't open Control ROM file");
+}
+
+void MidiHandler_mt32::MT32ReportHandler::onErrorPCMROM() {
+ LOG_MSG("MT32: Couldn't open PCM ROM file");
+}
+
+void MidiHandler_mt32::MT32ReportHandler::showLCDMessage(const char *message) {
+ LOG_MSG("MT32: LCD-Message: %s", message);
+}
+
+void MidiHandler_mt32::MT32ReportHandler::printDebug(const char *fmt, va_list list) {
+ MidiHandler_mt32 &midiHandler_mt32 = MidiHandler_mt32::GetInstance();
+ if (midiHandler_mt32.noise) {
+ char s[1024];
+ vsnprintf(s, 1023, fmt, list);
+ LOG_MSG("MT32: %s", s);
+ }
+}
diff --git a/src/gui/midi_mt32.h b/src/gui/midi_mt32.h
new file mode 100644
index 0000000..087f5a1
index 0000000..eb32729
--- /dev/null
+++ b/src/gui/midi_mt32.h
@@ -0,0 +1,57 @@
@@ -0,0 +1,55 @@
+#ifndef DOSBOX_MIDI_MT32_H
+#define DOSBOX_MIDI_MT32_H
+
+#include "mixer.h"
+
+#define MT32EMU_API_TYPE 3
+#include <mt32emu/mt32emu.h>
+
+#if MT32EMU_VERSION_MAJOR != 2 || MT32EMU_VERSION_MINOR < 1
+#error Incompatible mt32emu library version
+#endif
+
+struct SDL_Thread;
+
+class MidiHandler_mt32 : public MidiHandler {
@@ -356,8 +391,7 @@ index 0000000..087f5a1
+
+private:
+ MixerChannel *chan;
+ MT32Emu::Synth *synth;
+ MT32Emu::SampleRateConverter *src;
+ MT32Emu::Service *service;
+ SDL_Thread *thread;
+ SDL_mutex *lock;
+ SDL_cond *framesInBufferChanged;
@@ -369,23 +403,16 @@ index 0000000..087f5a1
+ volatile bool stopProcessing;
+ bool open, noise, renderInThread;
+
+ class MT32ReportHandler : public MT32Emu::ReportHandler {
+ protected:
+ virtual void onErrorControlROM();
+ virtual void onErrorPCMROM();
+ virtual void showLCDMessage(const char *message);
+ virtual void printDebug(const char *fmt, va_list list);
+ } reportHandler;
+
+ static void mixerCallBack(Bitu len);
+ static int processingThread(void *);
+ static void makeROMPathName(char pathName[], const char romDir[], const char fileName[], bool addPathSeparator);
+ static mt32emu_report_handler_i getReportHandlerInterface();
+
+ MidiHandler_mt32();
+ ~MidiHandler_mt32();
+
+ Bit32u inline getMidiEventTimestamp() {
+ return Bit32u(src->convertOutputToSynthTimestamp(playedBuffers * framesPerAudioBuffer + (playPos >> 1)));
+ return service->convertOutputToSynthTimestamp(Bit32u(playedBuffers * framesPerAudioBuffer + (playPos >> 1)));
+ }
+
+ void handleMixerCallBack(Bitu len);