aboutsummaryrefslogtreecommitdiff
path: root/audio/softsynth/mt32/c_interface
diff options
context:
space:
mode:
Diffstat (limited to 'audio/softsynth/mt32/c_interface')
-rw-r--r--audio/softsynth/mt32/c_interface/c_interface.cpp624
-rw-r--r--audio/softsynth/mt32/c_interface/c_interface.h362
-rw-r--r--audio/softsynth/mt32/c_interface/c_types.h298
-rw-r--r--audio/softsynth/mt32/c_interface/cpp_interface.h436
4 files changed, 1720 insertions, 0 deletions
diff --git a/audio/softsynth/mt32/c_interface/c_interface.cpp b/audio/softsynth/mt32/c_interface/c_interface.cpp
new file mode 100644
index 0000000000..a13c88bbe8
--- /dev/null
+++ b/audio/softsynth/mt32/c_interface/c_interface.cpp
@@ -0,0 +1,624 @@
+/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
+ * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 2.1 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "../globals.h"
+#include "../Types.h"
+#include "../File.h"
+#include "../FileStream.h"
+#include "../ROMInfo.h"
+#include "../Synth.h"
+#include "../MidiStreamParser.h"
+
+#include "c_types.h"
+#include "c_interface.h"
+
+using namespace MT32Emu;
+
+namespace MT32Emu {
+
+static mt32emu_service_version getSynthVersionID(mt32emu_service_i) {
+ return MT32EMU_SERVICE_VERSION_CURRENT;
+}
+
+static const mt32emu_service_i_v0 SERVICE_VTABLE = {
+ getSynthVersionID,
+ mt32emu_get_supported_report_handler_version,
+ mt32emu_get_supported_midi_receiver_version,
+ mt32emu_get_library_version_int,
+ mt32emu_get_library_version_string,
+ mt32emu_get_stereo_output_samplerate,
+ mt32emu_create_context,
+ mt32emu_free_context,
+ mt32emu_add_rom_data,
+ mt32emu_add_rom_file,
+ mt32emu_get_rom_info,
+ mt32emu_set_partial_count,
+ mt32emu_set_analog_output_mode,
+ mt32emu_open_synth,
+ mt32emu_close_synth,
+ mt32emu_is_open,
+ mt32emu_get_actual_stereo_output_samplerate,
+ mt32emu_flush_midi_queue,
+ mt32emu_set_midi_event_queue_size,
+ mt32emu_set_midi_receiver,
+ mt32emu_parse_stream,
+ mt32emu_parse_stream_at,
+ mt32emu_play_short_message,
+ mt32emu_play_short_message_at,
+ mt32emu_play_msg,
+ mt32emu_play_sysex,
+ mt32emu_play_msg_at,
+ mt32emu_play_sysex_at,
+ mt32emu_play_msg_now,
+ mt32emu_play_msg_on_part,
+ mt32emu_play_sysex_now,
+ mt32emu_write_sysex,
+ mt32emu_set_reverb_enabled,
+ mt32emu_is_reverb_enabled,
+ mt32emu_set_reverb_overridden,
+ mt32emu_is_reverb_overridden,
+ mt32emu_set_reverb_compatibility_mode,
+ mt32emu_is_mt32_reverb_compatibility_mode,
+ mt32emu_is_default_reverb_mt32_compatible,
+ mt32emu_set_dac_input_mode,
+ mt32emu_get_dac_input_mode,
+ mt32emu_set_midi_delay_mode,
+ mt32emu_get_midi_delay_mode,
+ mt32emu_set_output_gain,
+ mt32emu_get_output_gain,
+ mt32emu_set_reverb_output_gain,
+ mt32emu_get_reverb_output_gain,
+ mt32emu_set_reversed_stereo_enabled,
+ mt32emu_is_reversed_stereo_enabled,
+ mt32emu_render_bit16s,
+ mt32emu_render_float,
+ mt32emu_render_bit16s_streams,
+ mt32emu_render_float_streams,
+ mt32emu_has_active_partials,
+ mt32emu_is_active,
+ mt32emu_get_partial_count,
+ mt32emu_get_part_states,
+ mt32emu_get_partial_states,
+ mt32emu_get_playing_notes,
+ mt32emu_get_patch_name,
+ mt32emu_read_memory
+};
+
+} // namespace MT32Emu
+
+struct mt32emu_data {
+ ReportHandler *reportHandler;
+ Synth *synth;
+ const ROMImage *controlROMImage;
+ const ROMImage *pcmROMImage;
+ DefaultMidiStreamParser *midiParser;
+ Bit32u partialCount;
+ AnalogOutputMode analogOutputMode;
+};
+
+// Internal C++ utility stuff
+
+namespace MT32Emu {
+
+class DelegatingReportHandlerAdapter : public ReportHandler {
+public:
+ DelegatingReportHandlerAdapter(mt32emu_report_handler_i useReportHandler, void *useInstanceData) :
+ delegate(useReportHandler), instanceData(useInstanceData) {}
+
+protected:
+ const mt32emu_report_handler_i delegate;
+ void * const instanceData;
+
+private:
+ void printDebug(const char *fmt, va_list list) {
+ if (delegate.v0->printDebug == NULL) {
+ ReportHandler::printDebug(fmt, list);
+ } else {
+ delegate.v0->printDebug(instanceData, fmt, list);
+ }
+ }
+
+ void onErrorControlROM() {
+ if (delegate.v0->onErrorControlROM == NULL) {
+ ReportHandler::onErrorControlROM();
+ } else {
+ delegate.v0->onErrorControlROM(instanceData);
+ }
+ }
+
+ void onErrorPCMROM() {
+ if (delegate.v0->onErrorPCMROM == NULL) {
+ ReportHandler::onErrorPCMROM();
+ } else {
+ delegate.v0->onErrorPCMROM(instanceData);
+ }
+ }
+
+ void showLCDMessage(const char *message) {
+ if (delegate.v0->showLCDMessage == NULL) {
+ ReportHandler::showLCDMessage(message);
+ } else {
+ delegate.v0->showLCDMessage(instanceData, message);
+ }
+ }
+
+ void onMIDIMessagePlayed() {
+ if (delegate.v0->onMIDIMessagePlayed == NULL) {
+ ReportHandler::onMIDIMessagePlayed();
+ } else {
+ delegate.v0->onMIDIMessagePlayed(instanceData);
+ }
+ }
+
+ bool onMIDIQueueOverflow() {
+ if (delegate.v0->onMIDIQueueOverflow == NULL) {
+ return ReportHandler::onMIDIQueueOverflow();
+ }
+ return delegate.v0->onMIDIQueueOverflow(instanceData) != MT32EMU_BOOL_FALSE;
+ }
+
+ void onMIDISystemRealtime(Bit8u systemRealtime) {
+ if (delegate.v0->onMIDISystemRealtime == NULL) {
+ ReportHandler::onMIDISystemRealtime(systemRealtime);
+ } else {
+ delegate.v0->onMIDISystemRealtime(instanceData, systemRealtime);
+ }
+ }
+
+ void onDeviceReset() {
+ if (delegate.v0->onDeviceReset == NULL) {
+ ReportHandler::onDeviceReset();
+ } else {
+ delegate.v0->onDeviceReset(instanceData);
+ }
+ }
+
+ void onDeviceReconfig() {
+ if (delegate.v0->onDeviceReconfig == NULL) {
+ ReportHandler::onDeviceReconfig();
+ } else {
+ delegate.v0->onDeviceReconfig(instanceData);
+ }
+ }
+
+ void onNewReverbMode(Bit8u mode) {
+ if (delegate.v0->onNewReverbMode == NULL) {
+ ReportHandler::onNewReverbMode(mode);
+ } else {
+ delegate.v0->onNewReverbMode(instanceData, mode);
+ }
+ }
+
+ void onNewReverbTime(Bit8u time) {
+ if (delegate.v0->onNewReverbTime == NULL) {
+ ReportHandler::onNewReverbTime(time);
+ } else {
+ delegate.v0->onNewReverbTime(instanceData, time);
+ }
+ }
+
+ void onNewReverbLevel(Bit8u level) {
+ if (delegate.v0->onNewReverbLevel == NULL) {
+ ReportHandler::onNewReverbLevel(level);
+ } else {
+ delegate.v0->onNewReverbLevel(instanceData, level);
+ }
+ }
+
+ void onPolyStateChanged(Bit8u partNum) {
+ if (delegate.v0->onPolyStateChanged == NULL) {
+ ReportHandler::onPolyStateChanged(partNum);
+ } else {
+ delegate.v0->onPolyStateChanged(instanceData, partNum);
+ }
+ }
+
+ void onProgramChanged(Bit8u partNum, const char *soundGroupName, const char *patchName) {
+ if (delegate.v0->onProgramChanged == NULL) {
+ ReportHandler::onProgramChanged(partNum, soundGroupName, patchName);
+ } else {
+ delegate.v0->onProgramChanged(instanceData, partNum, soundGroupName, patchName);
+ }
+ }
+};
+
+class DelegatingMidiStreamParser : public DefaultMidiStreamParser {
+public:
+ DelegatingMidiStreamParser(const mt32emu_data *useData, mt32emu_midi_receiver_i useMIDIReceiver, void *useInstanceData) :
+ DefaultMidiStreamParser(*useData->synth), delegate(useMIDIReceiver), instanceData(useInstanceData) {}
+
+protected:
+ mt32emu_midi_receiver_i delegate;
+ void *instanceData;
+
+private:
+ void handleShortMessage(const Bit32u message) {
+ if (delegate.v0->handleShortMessage == NULL) {
+ DefaultMidiStreamParser::handleShortMessage(message);
+ } else {
+ delegate.v0->handleShortMessage(instanceData, message);
+ }
+ }
+
+ void handleSysex(const Bit8u *stream, const Bit32u length) {
+ if (delegate.v0->handleSysex == NULL) {
+ DefaultMidiStreamParser::handleSysex(stream, length);
+ } else {
+ delegate.v0->handleSysex(instanceData, stream, length);
+ }
+ }
+
+ void handleSystemRealtimeMessage(const Bit8u realtime) {
+ if (delegate.v0->handleSystemRealtimeMessage == NULL) {
+ DefaultMidiStreamParser::handleSystemRealtimeMessage(realtime);
+ } else {
+ delegate.v0->handleSystemRealtimeMessage(instanceData, realtime);
+ }
+ }
+};
+
+static mt32emu_return_code addROMFile(mt32emu_data *data, File *file) {
+ const ROMImage *image = ROMImage::makeROMImage(file);
+ const ROMInfo *info = image->getROMInfo();
+ if (info == NULL) {
+ ROMImage::freeROMImage(image);
+ return MT32EMU_RC_ROM_NOT_IDENTIFIED;
+ }
+ if (info->type == ROMInfo::Control) {
+ if (data->controlROMImage != NULL) {
+ delete data->controlROMImage->getFile();
+ ROMImage::freeROMImage(data->controlROMImage);
+ }
+ data->controlROMImage = image;
+ return MT32EMU_RC_ADDED_CONTROL_ROM;
+ } else if (info->type == ROMInfo::PCM) {
+ if (data->pcmROMImage != NULL) {
+ delete data->pcmROMImage->getFile();
+ ROMImage::freeROMImage(data->pcmROMImage);
+ }
+ data->pcmROMImage = image;
+ return MT32EMU_RC_ADDED_PCM_ROM;
+ }
+ ROMImage::freeROMImage(image);
+ return MT32EMU_RC_OK; // No support for reverb ROM yet.
+}
+
+} // namespace MT32Emu
+
+// C-visible implementation
+
+extern "C" {
+
+const mt32emu_service_i mt32emu_get_service_i() {
+ mt32emu_service_i i = { &SERVICE_VTABLE };
+ return i;
+}
+
+mt32emu_report_handler_version mt32emu_get_supported_report_handler_version() {
+ return MT32EMU_REPORT_HANDLER_VERSION_CURRENT;
+}
+
+mt32emu_midi_receiver_version mt32emu_get_supported_midi_receiver_version() {
+ return MT32EMU_MIDI_RECEIVER_VERSION_CURRENT;
+}
+
+mt32emu_bit32u mt32emu_get_library_version_int() {
+ return Synth::getLibraryVersionInt();
+}
+
+const char *mt32emu_get_library_version_string() {
+ return Synth::getLibraryVersionString();
+}
+
+mt32emu_bit32u mt32emu_get_stereo_output_samplerate(const mt32emu_analog_output_mode analog_output_mode) {
+ return Synth::getStereoOutputSampleRate(static_cast<AnalogOutputMode>(analog_output_mode));
+}
+
+mt32emu_context mt32emu_create_context(mt32emu_report_handler_i report_handler, void *instance_data) {
+ mt32emu_data *data = new mt32emu_data;
+ data->reportHandler = (report_handler.v0 != NULL) ? new DelegatingReportHandlerAdapter(report_handler, instance_data) : new ReportHandler;
+ data->synth = new Synth(data->reportHandler);
+ data->midiParser = new DefaultMidiStreamParser(*data->synth);
+ data->controlROMImage = NULL;
+ data->pcmROMImage = NULL;
+ data->partialCount = DEFAULT_MAX_PARTIALS;
+ data->analogOutputMode = AnalogOutputMode_COARSE;
+ return data;
+}
+
+void mt32emu_free_context(mt32emu_context data) {
+ if (data == NULL) return;
+ if (data->controlROMImage != NULL) {
+ delete data->controlROMImage->getFile();
+ ROMImage::freeROMImage(data->controlROMImage);
+ data->controlROMImage = NULL;
+ }
+ if (data->pcmROMImage != NULL) {
+ delete data->pcmROMImage->getFile();
+ ROMImage::freeROMImage(data->pcmROMImage);
+ data->pcmROMImage = NULL;
+ }
+ delete data->midiParser;
+ data->midiParser = NULL;
+ delete data->synth;
+ data->synth = NULL;
+ delete data->reportHandler;
+ data->reportHandler = NULL;
+ delete data;
+}
+
+mt32emu_return_code mt32emu_add_rom_data(mt32emu_context context, const mt32emu_bit8u *data, size_t data_size, const mt32emu_sha1_digest *sha1_digest) {
+ if (sha1_digest == NULL) return addROMFile(context, new ArrayFile(data, data_size));
+ return addROMFile(context, new ArrayFile(data, data_size, *sha1_digest));
+}
+
+mt32emu_return_code mt32emu_add_rom_file(mt32emu_context context, const char *filename) {
+ mt32emu_return_code rc = MT32EMU_RC_OK;
+ FileStream *fs = new FileStream;
+ if (fs->open(filename)) {
+ if (fs->getData() != NULL) {
+ rc = addROMFile(context, fs);
+ if (rc > 0) return rc;
+ } else {
+ rc = MT32EMU_RC_FILE_NOT_LOADED;
+ }
+ } else {
+ rc = MT32EMU_RC_FILE_NOT_FOUND;
+ }
+ delete fs;
+ return rc;
+}
+
+void mt32emu_get_rom_info(mt32emu_const_context context, mt32emu_rom_info *rom_info) {
+ const ROMInfo *romInfo = context->controlROMImage == NULL ? NULL : context->controlROMImage->getROMInfo();
+ if (romInfo != NULL) {
+ rom_info->control_rom_id = romInfo->shortName;
+ rom_info->control_rom_description = romInfo->description;
+ rom_info->control_rom_sha1_digest = romInfo->sha1Digest;
+ } else {
+ rom_info->control_rom_id = NULL;
+ rom_info->control_rom_description = NULL;
+ rom_info->control_rom_sha1_digest = NULL;
+ }
+ romInfo = context->pcmROMImage == NULL ? NULL : context->pcmROMImage->getROMInfo();
+ if (romInfo != NULL) {
+ rom_info->pcm_rom_id = romInfo->shortName;
+ rom_info->pcm_rom_description = romInfo->description;
+ rom_info->pcm_rom_sha1_digest = romInfo->sha1Digest;
+ } else {
+ rom_info->pcm_rom_id = NULL;
+ rom_info->pcm_rom_description = NULL;
+ rom_info->pcm_rom_sha1_digest = NULL;
+ }
+}
+
+void mt32emu_set_partial_count(mt32emu_context context, const mt32emu_bit32u partial_count) {
+ context->partialCount = partial_count;
+}
+
+void mt32emu_set_analog_output_mode(mt32emu_context context, const mt32emu_analog_output_mode analog_output_mode) {
+ context->analogOutputMode = static_cast<AnalogOutputMode>(analog_output_mode);
+}
+
+mt32emu_return_code mt32emu_open_synth(mt32emu_const_context context) {
+ if ((context->controlROMImage == NULL) || (context->pcmROMImage == NULL)) {
+ return MT32EMU_RC_MISSING_ROMS;
+ }
+ if (context->synth->open(*context->controlROMImage, *context->pcmROMImage, context->partialCount, context->analogOutputMode)) {
+ return MT32EMU_RC_OK;
+ }
+ return MT32EMU_RC_FAILED;
+}
+
+void mt32emu_close_synth(mt32emu_const_context context) {
+ context->synth->close();
+}
+
+mt32emu_boolean mt32emu_is_open(mt32emu_const_context context) {
+ return context->synth->isOpen() ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE;
+}
+
+mt32emu_bit32u mt32emu_get_actual_stereo_output_samplerate(mt32emu_const_context context) {
+ return context->synth->getStereoOutputSampleRate();
+}
+
+void mt32emu_flush_midi_queue(mt32emu_const_context context) {
+ context->synth->flushMIDIQueue();
+}
+
+mt32emu_bit32u mt32emu_set_midi_event_queue_size(mt32emu_const_context context, const mt32emu_bit32u queue_size) {
+ return context->synth->setMIDIEventQueueSize(queue_size);
+}
+
+void mt32emu_set_midi_receiver(mt32emu_context context, mt32emu_midi_receiver_i midi_receiver, void *instance_data) {
+ delete context->midiParser;
+ context->midiParser = (midi_receiver.v0 != NULL) ? new DelegatingMidiStreamParser(context, midi_receiver, instance_data) : new DefaultMidiStreamParser(*context->synth);
+}
+
+void mt32emu_parse_stream(mt32emu_const_context context, const mt32emu_bit8u *stream, mt32emu_bit32u length) {
+ context->midiParser->resetTimestamp();
+ context->midiParser->parseStream(stream, length);
+}
+
+void mt32emu_parse_stream_at(mt32emu_const_context context, const mt32emu_bit8u *stream, mt32emu_bit32u length, mt32emu_bit32u timestamp) {
+ context->midiParser->setTimestamp(timestamp);
+ context->midiParser->parseStream(stream, length);
+}
+
+void mt32emu_play_short_message(mt32emu_const_context context, mt32emu_bit32u message) {
+ context->midiParser->resetTimestamp();
+ context->midiParser->processShortMessage(message);
+}
+
+void mt32emu_play_short_message_at(mt32emu_const_context context, mt32emu_bit32u message, mt32emu_bit32u timestamp) {
+ context->midiParser->setTimestamp(timestamp);
+ context->midiParser->processShortMessage(message);
+}
+
+mt32emu_return_code mt32emu_play_msg(mt32emu_const_context context, mt32emu_bit32u msg) {
+ if (!context->synth->isOpen()) return MT32EMU_RC_NOT_OPENED;
+ return (context->synth->playMsg(msg)) ? MT32EMU_RC_OK : MT32EMU_RC_QUEUE_FULL;
+}
+
+mt32emu_return_code mt32emu_play_sysex(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len) {
+ if (!context->synth->isOpen()) return MT32EMU_RC_NOT_OPENED;
+ return (context->synth->playSysex(sysex, len)) ? MT32EMU_RC_OK : MT32EMU_RC_QUEUE_FULL;
+}
+
+mt32emu_return_code mt32emu_play_msg_at(mt32emu_const_context context, mt32emu_bit32u msg, mt32emu_bit32u timestamp) {
+ if (!context->synth->isOpen()) return MT32EMU_RC_NOT_OPENED;
+ return (context->synth->playMsg(msg, timestamp)) ? MT32EMU_RC_OK : MT32EMU_RC_QUEUE_FULL;
+}
+
+mt32emu_return_code mt32emu_play_sysex_at(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len, mt32emu_bit32u timestamp) {
+ if (!context->synth->isOpen()) return MT32EMU_RC_NOT_OPENED;
+ return (context->synth->playSysex(sysex, len, timestamp)) ? MT32EMU_RC_OK : MT32EMU_RC_QUEUE_FULL;
+}
+
+void mt32emu_play_msg_now(mt32emu_const_context context, mt32emu_bit32u msg) {
+ context->synth->playMsgNow(msg);
+}
+
+void mt32emu_play_msg_on_part(mt32emu_const_context context, mt32emu_bit8u part, mt32emu_bit8u code, mt32emu_bit8u note, mt32emu_bit8u velocity) {
+ context->synth->playMsgOnPart(part, code, note, velocity);
+}
+
+void mt32emu_play_sysex_now(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len) {
+ context->synth->playSysexNow(sysex, len);
+}
+
+void mt32emu_write_sysex(mt32emu_const_context context, mt32emu_bit8u channel, const mt32emu_bit8u *sysex, mt32emu_bit32u len) {
+ context->synth->writeSysex(channel, sysex, len);
+}
+
+void mt32emu_set_reverb_enabled(mt32emu_const_context context, const mt32emu_boolean reverb_enabled) {
+ context->synth->setReverbEnabled(reverb_enabled != MT32EMU_BOOL_FALSE);
+}
+
+mt32emu_boolean mt32emu_is_reverb_enabled(mt32emu_const_context context) {
+ return context->synth->isReverbEnabled() ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE;
+}
+
+void mt32emu_set_reverb_overridden(mt32emu_const_context context, const mt32emu_boolean reverb_overridden) {
+ context->synth->setReverbOverridden(reverb_overridden != MT32EMU_BOOL_FALSE);
+}
+
+mt32emu_boolean mt32emu_is_reverb_overridden(mt32emu_const_context context) {
+ return context->synth->isReverbOverridden() ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE;
+}
+
+void mt32emu_set_reverb_compatibility_mode(mt32emu_const_context context, const mt32emu_boolean mt32_compatible_mode) {
+ context->synth->setReverbCompatibilityMode(mt32_compatible_mode != MT32EMU_BOOL_FALSE);
+}
+
+mt32emu_boolean mt32emu_is_mt32_reverb_compatibility_mode(mt32emu_const_context context) {
+ return context->synth->isMT32ReverbCompatibilityMode() ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE;
+}
+
+mt32emu_boolean mt32emu_is_default_reverb_mt32_compatible(mt32emu_const_context context) {
+ return context->synth->isDefaultReverbMT32Compatible() ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE;
+}
+
+void mt32emu_set_dac_input_mode(mt32emu_const_context context, const mt32emu_dac_input_mode mode) {
+ context->synth->setDACInputMode(static_cast<DACInputMode>(mode));
+}
+
+mt32emu_dac_input_mode mt32emu_get_dac_input_mode(mt32emu_const_context context) {
+ return static_cast<mt32emu_dac_input_mode>(context->synth->getDACInputMode());
+}
+
+void mt32emu_set_midi_delay_mode(mt32emu_const_context context, const mt32emu_midi_delay_mode mode) {
+ context->synth->setMIDIDelayMode(static_cast<MIDIDelayMode>(mode));
+}
+
+mt32emu_midi_delay_mode mt32emu_get_midi_delay_mode(mt32emu_const_context context) {
+ return static_cast<mt32emu_midi_delay_mode>(context->synth->getMIDIDelayMode());
+}
+
+void mt32emu_set_output_gain(mt32emu_const_context context, float gain) {
+ context->synth->setOutputGain(gain);
+}
+
+float mt32emu_get_output_gain(mt32emu_const_context context) {
+ return context->synth->getOutputGain();
+}
+
+void mt32emu_set_reverb_output_gain(mt32emu_const_context context, float gain) {
+ context->synth->setReverbOutputGain(gain);
+}
+
+float mt32emu_get_reverb_output_gain(mt32emu_const_context context) {
+ return context->synth->getReverbOutputGain();
+}
+
+void mt32emu_set_reversed_stereo_enabled(mt32emu_const_context context, const mt32emu_boolean enabled) {
+ context->synth->setReversedStereoEnabled(enabled != MT32EMU_BOOL_FALSE);
+}
+
+mt32emu_boolean mt32emu_is_reversed_stereo_enabled(mt32emu_const_context context) {
+ return context->synth->isReversedStereoEnabled() ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE;
+}
+
+void mt32emu_render_bit16s(mt32emu_const_context context, mt32emu_bit16s *stream, mt32emu_bit32u len) {
+ context->synth->render(stream, len);
+}
+
+void mt32emu_render_float(mt32emu_const_context context, float *stream, mt32emu_bit32u len) {
+ context->synth->render(stream, len);
+}
+
+void mt32emu_render_bit16s_streams(mt32emu_const_context context, const mt32emu_dac_output_bit16s_streams *streams, mt32emu_bit32u len) {
+ context->synth->renderStreams(*(const DACOutputStreams<Bit16s> *)streams, len);
+}
+
+void mt32emu_render_float_streams(mt32emu_const_context context, const mt32emu_dac_output_float_streams *streams, mt32emu_bit32u len) {
+ context->synth->renderStreams(*(const DACOutputStreams<float> *)streams, len);
+}
+
+mt32emu_boolean mt32emu_has_active_partials(mt32emu_const_context context) {
+ return context->synth->hasActivePartials() ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE;
+}
+
+mt32emu_boolean mt32emu_is_active(mt32emu_const_context context) {
+ return context->synth->isActive() ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE;
+}
+
+mt32emu_bit32u mt32emu_get_partial_count(mt32emu_const_context context) {
+ return context->synth->getPartialCount();
+}
+
+mt32emu_bit32u mt32emu_get_part_states(mt32emu_const_context context) {
+ return context->synth->getPartStates();
+}
+
+void mt32emu_get_partial_states(mt32emu_const_context context, mt32emu_bit8u *partial_states) {
+ context->synth->getPartialStates(partial_states);
+}
+
+mt32emu_bit32u mt32emu_get_playing_notes(mt32emu_const_context context, mt32emu_bit8u part_number, mt32emu_bit8u *keys, mt32emu_bit8u *velocities) {
+ return context->synth->getPlayingNotes(part_number, keys, velocities);
+}
+
+const char *mt32emu_get_patch_name(mt32emu_const_context context, mt32emu_bit8u part_number) {
+ return context->synth->getPatchName(part_number);
+}
+
+void mt32emu_read_memory(mt32emu_const_context context, mt32emu_bit32u addr, mt32emu_bit32u len, mt32emu_bit8u *data) {
+ context->synth->readMemory(addr, len, data);
+}
+
+} // extern "C"
diff --git a/audio/softsynth/mt32/c_interface/c_interface.h b/audio/softsynth/mt32/c_interface/c_interface.h
new file mode 100644
index 0000000000..a2bdcb1254
--- /dev/null
+++ b/audio/softsynth/mt32/c_interface/c_interface.h
@@ -0,0 +1,362 @@
+/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
+ * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 2.1 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MT32EMU_C_INTERFACE_H
+#define MT32EMU_C_INTERFACE_H
+
+#include <stddef.h>
+
+#include "../globals.h"
+#include "c_types.h"
+
+#undef MT32EMU_EXPORT
+#define MT32EMU_EXPORT MT32EMU_EXPORT_ATTRIBUTE
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* == Context-independent functions == */
+
+/* === Interface handling === */
+
+/** Returns mt32emu_service_i interface. */
+MT32EMU_EXPORT const mt32emu_service_i mt32emu_get_service_i();
+
+#if MT32EMU_EXPORTS_TYPE == 2
+#undef MT32EMU_EXPORT
+#define MT32EMU_EXPORT
+#endif
+
+/**
+ * Returns the version ID of mt32emu_report_handler_i interface the library has been compiled with.
+ * This allows a client to fall-back gracefully instead of silently not receiving expected event reports.
+ */
+MT32EMU_EXPORT mt32emu_report_handler_version mt32emu_get_supported_report_handler_version();
+
+/**
+ * Returns the version ID of mt32emu_midi_receiver_version_i interface the library has been compiled with.
+ * This allows a client to fall-back gracefully instead of silently not receiving expected MIDI messages.
+ */
+MT32EMU_EXPORT mt32emu_midi_receiver_version mt32emu_get_supported_midi_receiver_version();
+
+/**
+ * Returns library version as an integer in format: 0x00MMmmpp, where:
+ * MM - major version number
+ * mm - minor version number
+ * pp - patch number
+ */
+MT32EMU_EXPORT mt32emu_bit32u mt32emu_get_library_version_int();
+
+/**
+ * Returns library version as a C-string in format: "MAJOR.MINOR.PATCH".
+ */
+MT32EMU_EXPORT const char *mt32emu_get_library_version_string();
+
+/**
+ * Returns output sample rate used in emulation of stereo analog circuitry of hardware units for particular analog_output_mode.
+ * See comment for mt32emu_analog_output_mode.
+ */
+MT32EMU_EXPORT mt32emu_bit32u mt32emu_get_stereo_output_samplerate(const mt32emu_analog_output_mode analog_output_mode);
+
+/* == Context-dependent functions == */
+
+/** Initialises a new emulation context and installs custom report handler if non-NULL. */
+MT32EMU_EXPORT mt32emu_context mt32emu_create_context(mt32emu_report_handler_i report_handler, void *instance_data);
+
+/** Closes and destroys emulation context. */
+MT32EMU_EXPORT void mt32emu_free_context(mt32emu_context context);
+
+/**
+ * Adds new ROM identified by its SHA1 digest to the emulation context replacing previously added ROM of the same type if any.
+ * Argument sha1_digest can be NULL, in this case the digest will be computed using the actual ROM data.
+ * If sha1_digest is set to non-NULL, it is assumed being correct and will not be recomputed.
+ * This function doesn't immediately change the state of already opened synth. Newly added ROM will take effect upon next call of mt32emu_open_synth().
+ * Returns positive value upon success.
+ */
+MT32EMU_EXPORT mt32emu_return_code mt32emu_add_rom_data(mt32emu_context context, const mt32emu_bit8u *data, size_t data_size, const mt32emu_sha1_digest *sha1_digest);
+
+/**
+ * Loads a ROM file, identify it by SHA1 digest, and adds it to the emulation context replacing previously added ROM of the same type if any.
+ * This function doesn't immediately change the state of already opened synth. Newly added ROM will take effect upon next call of mt32emu_open_synth().
+ * Returns positive value upon success.
+ */
+MT32EMU_EXPORT mt32emu_return_code mt32emu_add_rom_file(mt32emu_context context, const char *filename);
+
+/**
+ * Fills in mt32emu_rom_info structure with identifiers and descriptions of control and PCM ROM files identified and added to the synth context.
+ * If one of the ROM files is not loaded and identified yet, NULL is returned in the corresponding fields of the mt32emu_rom_info structure.
+ */
+MT32EMU_EXPORT void mt32emu_get_rom_info(mt32emu_const_context context, mt32emu_rom_info *rom_info);
+
+/**
+ * Allows to override the default maximum number of partials playing simultaneously within the emulation session.
+ * This function doesn't immediately change the state of already opened synth. Newly set vale will take effect upon next call of mt32emu_open_synth().
+ */
+MT32EMU_EXPORT void mt32emu_set_partial_count(mt32emu_context context, const mt32emu_bit32u partial_count);
+
+/**
+ * Allows to override the default mode for emulation of analogue circuitry of the hardware units within the emulation session.
+ * This function doesn't immediately change the state of already opened synth. Newly set vale will take effect upon next call of mt32emu_open_synth().
+ */
+MT32EMU_EXPORT void mt32emu_set_analog_output_mode(mt32emu_context context, const mt32emu_analog_output_mode analog_output_mode);
+
+/**
+ * Prepares the emulation context to receive MIDI messages and produce output audio data using aforehand added set of ROMs,
+ * and optionally set the maximum partial count and the analog output mode.
+ * Returns MT32EMU_RC_OK upon success.
+ */
+MT32EMU_EXPORT mt32emu_return_code mt32emu_open_synth(mt32emu_const_context context);
+
+/** Closes the emulation context freeing allocated resources. Added ROMs remain unaffected and ready for reuse. */
+MT32EMU_EXPORT void mt32emu_close_synth(mt32emu_const_context context);
+
+/** Returns true if the synth is in completely initialized state, otherwise returns false. */
+MT32EMU_EXPORT mt32emu_boolean mt32emu_is_open(mt32emu_const_context context);
+
+/**
+ * Returns actual output sample rate used in emulation of stereo analog circuitry of hardware units.
+ * See comment for mt32emu_analog_output_mode.
+ */
+MT32EMU_EXPORT mt32emu_bit32u mt32emu_get_actual_stereo_output_samplerate(mt32emu_const_context context);
+
+/** All the enqueued events are processed by the synth immediately. */
+MT32EMU_EXPORT void mt32emu_flush_midi_queue(mt32emu_const_context context);
+
+/**
+ * Sets size of the internal MIDI event queue. The queue size is set to the minimum power of 2 that is greater or equal to the size specified.
+ * The queue is flushed before reallocation.
+ * Returns the actual queue size being used.
+ */
+MT32EMU_EXPORT mt32emu_bit32u mt32emu_set_midi_event_queue_size(mt32emu_const_context context, const mt32emu_bit32u queue_size);
+
+/**
+ * Installs custom MIDI receiver object intended for receiving MIDI messages generated by MIDI stream parser.
+ * MIDI stream parser is involved when functions mt32emu_parse_stream() and mt32emu_play_short_message() or the likes are called.
+ * By default, parsed short MIDI messages and System Exclusive messages are sent to the synth input MIDI queue.
+ * This function allows to override default behaviour. If midi_receiver argument is set to NULL, the default behaviour is restored.
+ */
+MT32EMU_EXPORT void mt32emu_set_midi_receiver(mt32emu_context context, mt32emu_midi_receiver_i midi_receiver, void *instance_data);
+
+/* Enqueues a MIDI event for subsequent playback.
+ * The MIDI event will be processed not before the specified timestamp.
+ * The timestamp is measured as the global rendered sample count since the synth was created (at the native sample rate 32000 Hz).
+ * The minimum delay involves emulation of the delay introduced while the event is transferred via MIDI interface
+ * and emulation of the MCU busy-loop while it frees partials for use by a new Poly.
+ * Calls from multiple threads must be synchronised, although, no synchronisation is required with the rendering thread.
+ * onMIDIQueueOverflow callback is invoked when the MIDI event queue is full and the message cannot be enqueued.
+ */
+
+/**
+ * Parses a block of raw MIDI bytes and enqueues parsed MIDI messages for further processing ASAP.
+ * SysEx messages are allowed to be fragmented across several calls to this method. Running status is also handled for short messages.
+ * When a System Realtime MIDI message is parsed, onMIDISystemRealtime callback is invoked.
+ * NOTE: the total length of a SysEx message being fragmented shall not exceed MT32EMU_MAX_STREAM_BUFFER_SIZE (32768 bytes).
+ */
+MT32EMU_EXPORT void mt32emu_parse_stream(mt32emu_const_context context, const mt32emu_bit8u *stream, mt32emu_bit32u length);
+
+/**
+ * Parses a block of raw MIDI bytes and enqueues parsed MIDI messages to play at specified time.
+ * SysEx messages are allowed to be fragmented across several calls to this method. Running status is also handled for short messages.
+ * When a System Realtime MIDI message is parsed, onMIDISystemRealtime callback is invoked.
+ * NOTE: the total length of a SysEx message being fragmented shall not exceed MT32EMU_MAX_STREAM_BUFFER_SIZE (32768 bytes).
+ */
+MT32EMU_EXPORT void mt32emu_parse_stream_at(mt32emu_const_context context, const mt32emu_bit8u *stream, mt32emu_bit32u length, mt32emu_bit32u timestamp);
+
+/**
+ * Enqueues a single mt32emu_bit32u-encoded short MIDI message with full processing ASAP.
+ * The short MIDI message may contain no status byte, the running status is used in this case.
+ * When the argument is a System Realtime MIDI message, onMIDISystemRealtime callback is invoked.
+ */
+MT32EMU_EXPORT void mt32emu_play_short_message(mt32emu_const_context context, mt32emu_bit32u message);
+
+/**
+ * Enqueues a single mt32emu_bit32u-encoded short MIDI message to play at specified time with full processing.
+ * The short MIDI message may contain no status byte, the running status is used in this case.
+ * When the argument is a System Realtime MIDI message, onMIDISystemRealtime callback is invoked.
+ */
+MT32EMU_EXPORT void mt32emu_play_short_message_at(mt32emu_const_context context, mt32emu_bit32u message, mt32emu_bit32u timestamp);
+
+/** Enqueues a single short MIDI message to be processed ASAP. The message must contain a status byte. */
+MT32EMU_EXPORT mt32emu_return_code mt32emu_play_msg(mt32emu_const_context context, mt32emu_bit32u msg);
+/** Enqueues a single well formed System Exclusive MIDI message to be processed ASAP. */
+MT32EMU_EXPORT mt32emu_return_code mt32emu_play_sysex(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len);
+
+/** Enqueues a single short MIDI message to play at specified time. The message must contain a status byte. */
+MT32EMU_EXPORT mt32emu_return_code mt32emu_play_msg_at(mt32emu_const_context context, mt32emu_bit32u msg, mt32emu_bit32u timestamp);
+/** Enqueues a single well formed System Exclusive MIDI message to play at specified time. */
+MT32EMU_EXPORT mt32emu_return_code mt32emu_play_sysex_at(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len, mt32emu_bit32u timestamp);
+
+/* WARNING:
+ * The methods below don't ensure minimum 1-sample delay between sequential MIDI events,
+ * and a sequence of NoteOn and immediately succeeding NoteOff messages is always silent.
+ * A thread that invokes these methods must be explicitly synchronised with the thread performing sample rendering.
+ */
+
+/**
+ * Sends a short MIDI message to the synth for immediate playback. The message must contain a status byte.
+ * See the WARNING above.
+ */
+MT32EMU_EXPORT void mt32emu_play_msg_now(mt32emu_const_context context, mt32emu_bit32u msg);
+/**
+ * Sends unpacked short MIDI message to the synth for immediate playback. The message must contain a status byte.
+ * See the WARNING above.
+ */
+MT32EMU_EXPORT void mt32emu_play_msg_on_part(mt32emu_const_context context, mt32emu_bit8u part, mt32emu_bit8u code, mt32emu_bit8u note, mt32emu_bit8u velocity);
+
+/**
+ * Sends a single well formed System Exclusive MIDI message for immediate processing. The length is in bytes.
+ * See the WARNING above.
+ */
+MT32EMU_EXPORT void mt32emu_play_sysex_now(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len);
+/**
+ * Sends inner body of a System Exclusive MIDI message for direct processing. The length is in bytes.
+ * See the WARNING above.
+ */
+MT32EMU_EXPORT void mt32emu_write_sysex(mt32emu_const_context context, mt32emu_bit8u channel, const mt32emu_bit8u *sysex, mt32emu_bit32u len);
+
+/** Allows to disable wet reverb output altogether. */
+MT32EMU_EXPORT void mt32emu_set_reverb_enabled(mt32emu_const_context context, const mt32emu_boolean reverb_enabled);
+/** Returns whether wet reverb output is enabled. */
+MT32EMU_EXPORT mt32emu_boolean mt32emu_is_reverb_enabled(mt32emu_const_context context);
+/**
+ * Sets override reverb mode. In this mode, emulation ignores sysexes (or the related part of them) which control the reverb parameters.
+ * This mode is in effect until it is turned off. When the synth is re-opened, the override mode is unchanged but the state
+ * of the reverb model is reset to default.
+ */
+MT32EMU_EXPORT void mt32emu_set_reverb_overridden(mt32emu_const_context context, const mt32emu_boolean reverb_overridden);
+/** Returns whether reverb settings are overridden. */
+MT32EMU_EXPORT mt32emu_boolean mt32emu_is_reverb_overridden(mt32emu_const_context context);
+/**
+ * Forces reverb model compatibility mode. By default, the compatibility mode corresponds to the used control ROM version.
+ * Invoking this method with the argument set to true forces emulation of old MT-32 reverb circuit.
+ * When the argument is false, emulation of the reverb circuit used in new generation of MT-32 compatible modules is enforced
+ * (these include CM-32L and LAPC-I).
+ */
+MT32EMU_EXPORT void mt32emu_set_reverb_compatibility_mode(mt32emu_const_context context, const mt32emu_boolean mt32_compatible_mode);
+/** Returns whether reverb is in old MT-32 compatibility mode. */
+MT32EMU_EXPORT mt32emu_boolean mt32emu_is_mt32_reverb_compatibility_mode(mt32emu_const_context context);
+/** Returns whether default reverb compatibility mode is the old MT-32 compatibility mode. */
+MT32EMU_EXPORT mt32emu_boolean mt32emu_is_default_reverb_mt32_compatible(mt32emu_const_context context);
+
+/** Sets new DAC input mode. See mt32emu_dac_input_mode for details. */
+MT32EMU_EXPORT void mt32emu_set_dac_input_mode(mt32emu_const_context context, const mt32emu_dac_input_mode mode);
+/** Returns current DAC input mode. See mt32emu_dac_input_mode for details. */
+MT32EMU_EXPORT mt32emu_dac_input_mode mt32emu_get_dac_input_mode(mt32emu_const_context context);
+
+/** Sets new MIDI delay mode. See mt32emu_midi_delay_mode for details. */
+MT32EMU_EXPORT void mt32emu_set_midi_delay_mode(mt32emu_const_context context, const mt32emu_midi_delay_mode mode);
+/** Returns current MIDI delay mode. See mt32emu_midi_delay_mode for details. */
+MT32EMU_EXPORT mt32emu_midi_delay_mode mt32emu_get_midi_delay_mode(mt32emu_const_context context);
+
+/**
+ * Sets output gain factor for synth output channels. Applied to all output samples and unrelated with the synth's Master volume,
+ * it rather corresponds to the gain of the output analog circuitry of the hardware units. However, together with mt32emu_set_reverb_output_gain()
+ * it offers to the user a capability to control the gain of reverb and non-reverb output channels independently.
+ * Ignored in MT32EMU_DAC_PURE mode.
+ */
+MT32EMU_EXPORT void mt32emu_set_output_gain(mt32emu_const_context context, float gain);
+/** Returns current output gain factor for synth output channels. */
+MT32EMU_EXPORT float mt32emu_get_output_gain(mt32emu_const_context context);
+
+/**
+ * Sets output gain factor for the reverb wet output channels. It rather corresponds to the gain of the output
+ * analog circuitry of the hardware units. However, together with mt32emu_set_output_gain() it offers to the user a capability
+ * to control the gain of reverb and non-reverb output channels independently.
+ *
+ * Note: We're currently emulate CM-32L/CM-64 reverb quite accurately and the reverb output level closely
+ * corresponds to the level of digital capture. Although, according to the CM-64 PCB schematic,
+ * there is a difference in the reverb analogue circuit, and the resulting output gain is 0.68
+ * of that for LA32 analogue output. This factor is applied to the reverb output gain.
+ * Ignored in MT32EMU_DAC_PURE mode.
+ */
+MT32EMU_EXPORT void mt32emu_set_reverb_output_gain(mt32emu_const_context context, float gain);
+/** Returns current output gain factor for reverb wet output channels. */
+MT32EMU_EXPORT float mt32emu_get_reverb_output_gain(mt32emu_const_context context);
+
+/** Swaps left and right output channels. */
+MT32EMU_EXPORT void mt32emu_set_reversed_stereo_enabled(mt32emu_const_context context, const mt32emu_boolean enabled);
+/** Returns whether left and right output channels are swapped. */
+MT32EMU_EXPORT mt32emu_boolean mt32emu_is_reversed_stereo_enabled(mt32emu_const_context context);
+
+/**
+ * Renders samples to the specified output stream as if they were sampled at the analog stereo output.
+ * When mt32emu_analog_output_mode is set to ACCURATE (OVERSAMPLED), the output signal is upsampled to 48 (96) kHz in order
+ * to retain emulation accuracy in whole audible frequency spectra. Otherwise, native digital signal sample rate is retained.
+ * mt32emu_get_actual_stereo_output_samplerate() can be used to query actual sample rate of the output signal.
+ * The length is in frames, not bytes (in 16-bit stereo, one frame is 4 bytes). Uses NATIVE byte ordering.
+ */
+MT32EMU_EXPORT void mt32emu_render_bit16s(mt32emu_const_context context, mt32emu_bit16s *stream, mt32emu_bit32u len);
+/** Same as above but outputs to a float stereo stream. */
+MT32EMU_EXPORT void mt32emu_render_float(mt32emu_const_context context, float *stream, mt32emu_bit32u len);
+
+/**
+ * Renders samples to the specified output streams as if they appeared at the DAC entrance.
+ * No further processing performed in analog circuitry emulation is applied to the signal.
+ * NULL may be specified in place of any or all of the stream buffers to skip it.
+ * The length is in samples, not bytes. Uses NATIVE byte ordering.
+ */
+MT32EMU_EXPORT void mt32emu_render_bit16s_streams(mt32emu_const_context context, const mt32emu_dac_output_bit16s_streams *streams, mt32emu_bit32u len);
+/** Same as above but outputs to float streams. */
+MT32EMU_EXPORT void mt32emu_render_float_streams(mt32emu_const_context context, const mt32emu_dac_output_float_streams *streams, mt32emu_bit32u len);
+
+/** Returns true when there is at least one active partial, otherwise false. */
+MT32EMU_EXPORT mt32emu_boolean mt32emu_has_active_partials(mt32emu_const_context context);
+
+/** Returns true if mt32emu_has_active_partials() returns true, or reverb is (somewhat unreliably) detected as being active. */
+MT32EMU_EXPORT mt32emu_boolean mt32emu_is_active(mt32emu_const_context context);
+
+/** Returns the maximum number of partials playing simultaneously. */
+MT32EMU_EXPORT mt32emu_bit32u mt32emu_get_partial_count(mt32emu_const_context context);
+
+/**
+ * Returns current states of all the parts as a bit set. The least significant bit corresponds to the state of part 1,
+ * total of 9 bits hold the states of all the parts. If the returned bit for a part is set, there is at least one active
+ * non-releasing partial playing on this part. This info is useful in emulating behaviour of LCD display of the hardware units.
+ */
+MT32EMU_EXPORT mt32emu_bit32u mt32emu_get_part_states(mt32emu_const_context context);
+
+/**
+ * Fills in current states of all the partials into the array provided. Each byte in the array holds states of 4 partials
+ * starting from the least significant bits. The state of each partial is packed in a pair of bits.
+ * The array must be large enough to accommodate states of all the partials.
+ * @see getPartialCount()
+ */
+MT32EMU_EXPORT void mt32emu_get_partial_states(mt32emu_const_context context, mt32emu_bit8u *partial_states);
+
+/**
+ * Fills in information about currently playing notes on the specified part into the arrays provided. The arrays must be large enough
+ * to accommodate data for all the playing notes. The maximum number of simultaneously playing notes cannot exceed the number of partials.
+ * Argument partNumber should be 0..7 for Part 1..8, or 8 for Rhythm.
+ * Returns the number of currently playing notes on the specified part.
+ */
+MT32EMU_EXPORT mt32emu_bit32u mt32emu_get_playing_notes(mt32emu_const_context context, mt32emu_bit8u part_number, mt32emu_bit8u *keys, mt32emu_bit8u *velocities);
+
+/**
+ * Returns name of the patch set on the specified part.
+ * Argument partNumber should be 0..7 for Part 1..8, or 8 for Rhythm.
+ */
+MT32EMU_EXPORT const char *mt32emu_get_patch_name(mt32emu_const_context context, mt32emu_bit8u part_number);
+
+/** Stores internal state of emulated synth into an array provided (as it would be acquired from hardware). */
+MT32EMU_EXPORT void mt32emu_read_memory(mt32emu_const_context context, mt32emu_bit32u addr, mt32emu_bit32u len, mt32emu_bit8u *data);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif /* #ifndef MT32EMU_C_INTERFACE_H */
diff --git a/audio/softsynth/mt32/c_interface/c_types.h b/audio/softsynth/mt32/c_interface/c_types.h
new file mode 100644
index 0000000000..3cd8744235
--- /dev/null
+++ b/audio/softsynth/mt32/c_interface/c_types.h
@@ -0,0 +1,298 @@
+/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
+ * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 2.1 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MT32EMU_C_TYPES_H
+#define MT32EMU_C_TYPES_H
+
+#include <stdarg.h>
+#include <stddef.h>
+
+#include "../globals.h"
+
+#define MT32EMU_C_ENUMERATIONS
+#include "../Enumerations.h"
+#undef MT32EMU_C_ENUMERATIONS
+
+typedef unsigned int mt32emu_bit32u;
+typedef signed int mt32emu_bit32s;
+typedef unsigned short int mt32emu_bit16u;
+typedef signed short int mt32emu_bit16s;
+typedef unsigned char mt32emu_bit8u;
+typedef signed char mt32emu_bit8s;
+
+typedef char mt32emu_sha1_digest[41];
+
+typedef enum {
+ MT32EMU_BOOL_FALSE, MT32EMU_BOOL_TRUE
+} mt32emu_boolean;
+
+typedef enum {
+ /* Operation completed normally. */
+ MT32EMU_RC_OK = 0,
+ MT32EMU_RC_ADDED_CONTROL_ROM = 1,
+ MT32EMU_RC_ADDED_PCM_ROM = 2,
+
+ /* Definite error occurred. */
+ MT32EMU_RC_ROM_NOT_IDENTIFIED = -1,
+ MT32EMU_RC_FILE_NOT_FOUND = -2,
+ MT32EMU_RC_FILE_NOT_LOADED = -3,
+ MT32EMU_RC_MISSING_ROMS = -4,
+ MT32EMU_RC_NOT_OPENED = -5,
+ MT32EMU_RC_QUEUE_FULL = -6,
+
+ /* Undefined error occurred. */
+ MT32EMU_RC_FAILED = -100
+} mt32emu_return_code;
+
+/** Emulation context */
+typedef struct mt32emu_data *mt32emu_context;
+typedef const struct mt32emu_data *mt32emu_const_context;
+
+/* Convenience aliases */
+#ifndef __cplusplus
+typedef enum mt32emu_analog_output_mode mt32emu_analog_output_mode;
+typedef enum mt32emu_dac_input_mode mt32emu_dac_input_mode;
+typedef enum mt32emu_midi_delay_mode mt32emu_midi_delay_mode;
+typedef enum mt32emu_partial_state mt32emu_partial_state;
+#endif
+
+/** Contains identifiers and descriptions of ROM files being used. */
+typedef struct {
+ const char *control_rom_id;
+ const char *control_rom_description;
+ const char *control_rom_sha1_digest;
+ const char *pcm_rom_id;
+ const char *pcm_rom_description;
+ const char *pcm_rom_sha1_digest;
+} mt32emu_rom_info;
+
+/** Set of multiplexed output bit16s streams appeared at the DAC entrance. */
+typedef struct {
+ mt32emu_bit16s *nonReverbLeft;
+ mt32emu_bit16s *nonReverbRight;
+ mt32emu_bit16s *reverbDryLeft;
+ mt32emu_bit16s *reverbDryRight;
+ mt32emu_bit16s *reverbWetLeft;
+ mt32emu_bit16s *reverbWetRight;
+} mt32emu_dac_output_bit16s_streams;
+
+/** Set of multiplexed output float streams appeared at the DAC entrance. */
+typedef struct {
+ float *nonReverbLeft;
+ float *nonReverbRight;
+ float *reverbDryLeft;
+ float *reverbDryRight;
+ float *reverbWetLeft;
+ float *reverbWetRight;
+} mt32emu_dac_output_float_streams;
+
+/* === Interface handling === */
+
+/** Report handler interface versions */
+typedef enum {
+ MT32EMU_REPORT_HANDLER_VERSION_0 = 0,
+ MT32EMU_REPORT_HANDLER_VERSION_CURRENT = MT32EMU_REPORT_HANDLER_VERSION_0
+} mt32emu_report_handler_version;
+
+/** MIDI receiver interface versions */
+typedef enum {
+ MT32EMU_MIDI_RECEIVER_VERSION_0 = 0,
+ MT32EMU_MIDI_RECEIVER_VERSION_CURRENT = MT32EMU_MIDI_RECEIVER_VERSION_0
+} mt32emu_midi_receiver_version;
+
+/** Synth interface versions */
+typedef enum {
+ MT32EMU_SERVICE_VERSION_0 = 0,
+ MT32EMU_SERVICE_VERSION_CURRENT = MT32EMU_SERVICE_VERSION_0
+} mt32emu_service_version;
+
+/* === Report Handler Interface === */
+
+typedef union mt32emu_report_handler_i mt32emu_report_handler_i;
+
+/** Interface for handling reported events (initial version) */
+typedef struct {
+ /** Returns the actual interface version ID */
+ mt32emu_report_handler_version (*getVersionID)(mt32emu_report_handler_i i);
+
+ /** Callback for debug messages, in vprintf() format */
+ void (*printDebug)(void *instance_data, const char *fmt, va_list list);
+ /** Callbacks for reporting errors */
+ void (*onErrorControlROM)(void *instance_data);
+ void (*onErrorPCMROM)(void *instance_data);
+ /** Callback for reporting about displaying a new custom message on LCD */
+ void (*showLCDMessage)(void *instance_data, const char *message);
+ /** Callback for reporting actual processing of a MIDI message */
+ void (*onMIDIMessagePlayed)(void *instance_data);
+ /**
+ * Callback for reporting an overflow of the input MIDI queue.
+ * Returns MT32EMU_BOOL_TRUE if a recovery action was taken
+ * and yet another attempt to enqueue the MIDI event is desired.
+ */
+ mt32emu_boolean (*onMIDIQueueOverflow)(void *instance_data);
+ /**
+ * Callback invoked when a System Realtime MIDI message is detected in functions
+ * mt32emu_parse_stream and mt32emu_play_short_message and the likes.
+ */
+ void (*onMIDISystemRealtime)(void *instance_data, mt32emu_bit8u system_realtime);
+ /** Callbacks for reporting system events */
+ void (*onDeviceReset)(void *instance_data);
+ void (*onDeviceReconfig)(void *instance_data);
+ /** Callbacks for reporting changes of reverb settings */
+ void (*onNewReverbMode)(void *instance_data, mt32emu_bit8u mode);
+ void (*onNewReverbTime)(void *instance_data, mt32emu_bit8u time);
+ void (*onNewReverbLevel)(void *instance_data, mt32emu_bit8u level);
+ /** Callbacks for reporting various information */
+ void (*onPolyStateChanged)(void *instance_data, mt32emu_bit8u part_num);
+ void (*onProgramChanged)(void *instance_data, mt32emu_bit8u part_num, const char *sound_group_name, const char *patch_name);
+} mt32emu_report_handler_i_v0;
+
+/**
+ * Extensible interface for handling reported events.
+ * Union intended to view an interface of any subsequent version as any parent interface not requiring a cast.
+ * Elements are to be addressed using the tag of the interface version when they were introduced.
+ */
+union mt32emu_report_handler_i {
+ const mt32emu_report_handler_i_v0 *v0;
+};
+
+/* === MIDI Receiver Interface === */
+
+typedef union mt32emu_midi_receiver_i mt32emu_midi_receiver_i;
+
+/** Interface for receiving MIDI messages generated by MIDI stream parser (initial version) */
+typedef struct {
+ /** Returns the actual interface version ID */
+ mt32emu_midi_receiver_version (*getVersionID)(mt32emu_midi_receiver_i i);
+
+ /** Invoked when a complete short MIDI message is parsed in the input MIDI stream. */
+ void (*handleShortMessage)(void *instance_data, const mt32emu_bit32u message);
+
+ /** Invoked when a complete well-formed System Exclusive MIDI message is parsed in the input MIDI stream. */
+ void (*handleSysex)(void *instance_data, const mt32emu_bit8u stream[], const mt32emu_bit32u length);
+
+ /** Invoked when a System Realtime MIDI message is parsed in the input MIDI stream. */
+ void (*handleSystemRealtimeMessage)(void *instance_data, const mt32emu_bit8u realtime);
+} mt32emu_midi_receiver_i_v0;
+
+/**
+ * Extensible interface for receiving MIDI messages.
+ * Union intended to view an interface of any subsequent version as any parent interface not requiring a cast.
+ * Elements are to be addressed using the tag of the interface version when they were introduced.
+ */
+union mt32emu_midi_receiver_i {
+ const mt32emu_midi_receiver_i_v0 *v0;
+};
+
+/* === Service Interface === */
+
+typedef union mt32emu_service_i mt32emu_service_i;
+
+/**
+ * Basic interface that defines all the library services (initial version).
+ * The members closely resemble C functions declared in c_interface.h, and the intention is to provide for easier
+ * access when the library is dynamically loaded in run-time, e.g. as a plugin. This way the client only needs
+ * to bind to mt32emu_get_service_i() function instead of binding to each function it needs to use.
+ * See c_interface.h for parameter description.
+ */
+typedef struct {
+ /** Returns the actual interface version ID */
+ mt32emu_service_version (*getVersionID)(mt32emu_service_i i);
+ mt32emu_report_handler_version (*getSupportedReportHandlerVersionID)();
+ mt32emu_midi_receiver_version (*getSupportedMIDIReceiverVersionID)();
+
+ mt32emu_bit32u (*getLibraryVersionInt)();
+ const char *(*getLibraryVersionString)();
+
+ mt32emu_bit32u (*getStereoOutputSamplerate)(const mt32emu_analog_output_mode analog_output_mode);
+
+ mt32emu_context (*createContext)(mt32emu_report_handler_i report_handler, void *instance_data);
+ void (*freeContext)(mt32emu_context context);
+ mt32emu_return_code (*addROMData)(mt32emu_context context, const mt32emu_bit8u *data, size_t data_size, const mt32emu_sha1_digest *sha1_digest);
+ mt32emu_return_code (*addROMFile)(mt32emu_context context, const char *filename);
+ void (*getROMInfo)(mt32emu_const_context context, mt32emu_rom_info *rom_info);
+ void (*setPartialCount)(mt32emu_context context, const mt32emu_bit32u partial_count);
+ void (*setAnalogOutputMode)(mt32emu_context context, const mt32emu_analog_output_mode analog_output_mode);
+ mt32emu_return_code (*openSynth)(mt32emu_const_context context);
+ void (*closeSynth)(mt32emu_const_context context);
+ mt32emu_boolean (*isOpen)(mt32emu_const_context context);
+ mt32emu_bit32u (*getActualStereoOutputSamplerate)(mt32emu_const_context context);
+ void (*flushMIDIQueue)(mt32emu_const_context context);
+ mt32emu_bit32u (*setMIDIEventQueueSize)(mt32emu_const_context context, const mt32emu_bit32u queue_size);
+ void (*setMIDIReceiver)(mt32emu_context context, mt32emu_midi_receiver_i midi_receiver, void *instance_data);
+
+ void (*parseStream)(mt32emu_const_context context, const mt32emu_bit8u *stream, mt32emu_bit32u length);
+ void (*parseStream_At)(mt32emu_const_context context, const mt32emu_bit8u *stream, mt32emu_bit32u length, mt32emu_bit32u timestamp);
+ void (*playShortMessage)(mt32emu_const_context context, mt32emu_bit32u message);
+ void (*playShortMessageAt)(mt32emu_const_context context, mt32emu_bit32u message, mt32emu_bit32u timestamp);
+ mt32emu_return_code (*playMsg)(mt32emu_const_context context, mt32emu_bit32u msg);
+ mt32emu_return_code (*playSysex)(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len);
+ mt32emu_return_code (*playMsgAt)(mt32emu_const_context context, mt32emu_bit32u msg, mt32emu_bit32u timestamp);
+ mt32emu_return_code (*playSysexAt)(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len, mt32emu_bit32u timestamp);
+
+ void (*playMsgNow)(mt32emu_const_context context, mt32emu_bit32u msg);
+ void (*playMsgOnPart)(mt32emu_const_context context, mt32emu_bit8u part, mt32emu_bit8u code, mt32emu_bit8u note, mt32emu_bit8u velocity);
+ void (*playSysexNow)(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len);
+ void (*writeSysex)(mt32emu_const_context context, mt32emu_bit8u channel, const mt32emu_bit8u *sysex, mt32emu_bit32u len);
+
+ void (*setReverbEnabled)(mt32emu_const_context context, const mt32emu_boolean reverb_enabled);
+ mt32emu_boolean (*isReverbEnabled)(mt32emu_const_context context);
+ void (*setReverbOverridden)(mt32emu_const_context context, const mt32emu_boolean reverb_overridden);
+ mt32emu_boolean (*isReverbOverridden)(mt32emu_const_context context);
+ void (*setReverbCompatibilityMode)(mt32emu_const_context context, const mt32emu_boolean mt32_compatible_mode);
+ mt32emu_boolean (*isMT32ReverbCompatibilityMode)(mt32emu_const_context context);
+ mt32emu_boolean (*isDefaultReverbMT32Compatible)(mt32emu_const_context context);
+
+ void (*setDACInputMode)(mt32emu_const_context context, const mt32emu_dac_input_mode mode);
+ mt32emu_dac_input_mode (*getDACInputMode)(mt32emu_const_context context);
+
+ void (*setMIDIDelayMode)(mt32emu_const_context context, const mt32emu_midi_delay_mode mode);
+ mt32emu_midi_delay_mode (*getMIDIDelayMode)(mt32emu_const_context context);
+
+ void (*setOutputGain)(mt32emu_const_context context, float gain);
+ float (*getOutputGain)(mt32emu_const_context context);
+ void (*setReverbOutputGain)(mt32emu_const_context context, float gain);
+ float (*getReverbOutputGain)(mt32emu_const_context context);
+
+ void (*setReversedStereoEnabled)(mt32emu_const_context context, const mt32emu_boolean enabled);
+ mt32emu_boolean (*isReversedStereoEnabled)(mt32emu_const_context context);
+
+ void (*renderBit16s)(mt32emu_const_context context, mt32emu_bit16s *stream, mt32emu_bit32u len);
+ void (*renderFloat)(mt32emu_const_context context, float *stream, mt32emu_bit32u len);
+ void (*renderBit16sStreams)(mt32emu_const_context context, const mt32emu_dac_output_bit16s_streams *streams, mt32emu_bit32u len);
+ void (*renderFloatStreams)(mt32emu_const_context context, const mt32emu_dac_output_float_streams *streams, mt32emu_bit32u len);
+
+ mt32emu_boolean (*hasActivePartials)(mt32emu_const_context context);
+ mt32emu_boolean (*isActive)(mt32emu_const_context context);
+ mt32emu_bit32u (*getPartialCount)(mt32emu_const_context context);
+ mt32emu_bit32u (*getPartStates)(mt32emu_const_context context);
+ void (*getPartialStates)(mt32emu_const_context context, mt32emu_bit8u *partial_states);
+ mt32emu_bit32u (*getPlayingNotes)(mt32emu_const_context context, mt32emu_bit8u part_number, mt32emu_bit8u *keys, mt32emu_bit8u *velocities);
+ const char *(*getPatchName)(mt32emu_const_context context, mt32emu_bit8u part_number);
+ void (*readMemory)(mt32emu_const_context context, mt32emu_bit32u addr, mt32emu_bit32u len, mt32emu_bit8u *data);
+} mt32emu_service_i_v0;
+
+/**
+ * Extensible interface for all the library services.
+ * Union intended to view an interface of any subsequent version as any parent interface not requiring a cast.
+ * Elements are to be addressed using the tag of the interface version when they were introduced.
+ */
+union mt32emu_service_i {
+ const mt32emu_service_i_v0 *v0;
+};
+
+#endif /* #ifndef MT32EMU_C_TYPES_H */
diff --git a/audio/softsynth/mt32/c_interface/cpp_interface.h b/audio/softsynth/mt32/c_interface/cpp_interface.h
new file mode 100644
index 0000000000..41ddebcc02
--- /dev/null
+++ b/audio/softsynth/mt32/c_interface/cpp_interface.h
@@ -0,0 +1,436 @@
+/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
+ * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 2.1 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MT32EMU_CPP_INTERFACE_H
+#define MT32EMU_CPP_INTERFACE_H
+
+#include <cstdarg>
+
+#include "../globals.h"
+#include "c_types.h"
+
+#include "../Types.h"
+#include "../Enumerations.h"
+
+#if MT32EMU_API_TYPE == 2
+
+#define mt32emu_get_supported_report_handler_version i.v0->getSupportedReportHandlerVersionID
+#define mt32emu_get_supported_midi_receiver_version i.v0->getSupportedMIDIReceiverVersionID
+#define mt32emu_get_library_version_int i.v0->getLibraryVersionInt
+#define mt32emu_get_library_version_string i.v0->getLibraryVersionString
+#define mt32emu_get_stereo_output_samplerate i.v0->getStereoOutputSamplerate
+#define mt32emu_create_context i.v0->createContext
+#define mt32emu_free_context i.v0->freeContext
+#define mt32emu_add_rom_data i.v0->addROMData
+#define mt32emu_add_rom_file i.v0->addROMFile
+#define mt32emu_get_rom_info i.v0->getROMInfo
+#define mt32emu_set_partial_count i.v0->setPartialCount
+#define mt32emu_set_analog_output_mode i.v0->setAnalogOutputMode
+#define mt32emu_open_synth i.v0->openSynth
+#define mt32emu_close_synth i.v0->closeSynth
+#define mt32emu_is_open i.v0->isOpen
+#define mt32emu_get_actual_stereo_output_samplerate i.v0->getActualStereoOutputSamplerate
+#define mt32emu_flush_midi_queue i.v0->flushMIDIQueue
+#define mt32emu_set_midi_event_queue_size i.v0->setMIDIEventQueueSize
+#define mt32emu_set_midi_receiver i.v0->setMIDIReceiver
+#define mt32emu_parse_stream i.v0->parseStream
+#define mt32emu_parse_stream_at i.v0->parseStream_At
+#define mt32emu_play_short_message i.v0->playShortMessage
+#define mt32emu_play_short_message_at i.v0->playShortMessageAt
+#define mt32emu_play_msg i.v0->playMsg
+#define mt32emu_play_sysex i.v0->playSysex
+#define mt32emu_play_msg_at i.v0->playMsgAt
+#define mt32emu_play_sysex_at i.v0->playSysexAt
+#define mt32emu_play_msg_now i.v0->playMsgNow
+#define mt32emu_play_msg_on_part i.v0->playMsgOnPart
+#define mt32emu_play_sysex_now i.v0->playSysexNow
+#define mt32emu_write_sysex i.v0->writeSysex
+#define mt32emu_set_reverb_enabled i.v0->setReverbEnabled
+#define mt32emu_is_reverb_enabled i.v0->isReverbEnabled
+#define mt32emu_set_reverb_overridden i.v0->setReverbOverridden
+#define mt32emu_is_reverb_overridden i.v0->isReverbOverridden
+#define mt32emu_set_reverb_compatibility_mode i.v0->setReverbCompatibilityMode
+#define mt32emu_is_mt32_reverb_compatibility_mode i.v0->isMT32ReverbCompatibilityMode
+#define mt32emu_is_default_reverb_mt32_compatible i.v0->isDefaultReverbMT32Compatible
+#define mt32emu_set_dac_input_mode i.v0->setDACInputMode
+#define mt32emu_get_dac_input_mode i.v0->getDACInputMode
+#define mt32emu_set_midi_delay_mode i.v0->setMIDIDelayMode
+#define mt32emu_get_midi_delay_mode i.v0->getMIDIDelayMode
+#define mt32emu_set_output_gain i.v0->setOutputGain
+#define mt32emu_get_output_gain i.v0->getOutputGain
+#define mt32emu_set_reverb_output_gain i.v0->setReverbOutputGain
+#define mt32emu_get_reverb_output_gain i.v0->getReverbOutputGain
+#define mt32emu_set_reversed_stereo_enabled i.v0->setReversedStereoEnabled
+#define mt32emu_is_reversed_stereo_enabled i.v0->isReversedStereoEnabled
+#define mt32emu_render_bit16s i.v0->renderBit16s
+#define mt32emu_render_float i.v0->renderFloat
+#define mt32emu_render_bit16s_streams i.v0->renderBit16sStreams
+#define mt32emu_render_float_streams i.v0->renderFloatStreams
+#define mt32emu_has_active_partials i.v0->hasActivePartials
+#define mt32emu_is_active i.v0->isActive
+#define mt32emu_get_partial_count i.v0->getPartialCount
+#define mt32emu_get_part_states i.v0->getPartStates
+#define mt32emu_get_partial_states i.v0->getPartialStates
+#define mt32emu_get_playing_notes i.v0->getPlayingNotes
+#define mt32emu_get_patch_name i.v0->getPatchName
+#define mt32emu_read_memory i.v0->readMemory
+
+#else // #if MT32EMU_API_TYPE == 2
+
+#include "c_interface.h"
+
+#endif // #if MT32EMU_API_TYPE == 2
+
+namespace MT32Emu {
+
+namespace CppInterfaceImpl {
+
+static const mt32emu_report_handler_i NULL_REPORT_HANDLER = { NULL };
+static mt32emu_report_handler_i getReportHandlerThunk();
+static mt32emu_midi_receiver_i getMidiReceiverThunk();
+
+}
+
+/*
+ * The classes below correspond to the interfaces defined in c_types.h and provided for convenience when using C++.
+ * The approach used makes no assumption of any internal class data memory layout, since the C++ standard does not
+ * provide any detail in this area and leaves it up to the implementation. Therefore, this way portability is guaranteed,
+ * despite the implementation may be a little inefficient.
+ * See c_types.h and c_interface.h for description of the corresponding interface methods.
+ */
+
+// Defines the interface for handling reported events.
+// Corresponds to the current version of mt32emu_report_handler_i interface.
+class ReportHandler {
+public:
+ virtual void printDebug(const char *fmt, va_list list) = 0;
+ virtual void onErrorControlROM() = 0;
+ virtual void onErrorPCMROM() = 0;
+ virtual void showLCDMessage(const char *message) = 0;
+ virtual void onMIDIMessagePlayed() = 0;
+ virtual bool onMIDIQueueOverflow() = 0;
+ virtual void onMIDISystemRealtime(Bit8u system_realtime) = 0;
+ virtual void onDeviceReset() = 0;
+ virtual void onDeviceReconfig() = 0;
+ virtual void onNewReverbMode(Bit8u mode) = 0;
+ virtual void onNewReverbTime(Bit8u time) = 0;
+ virtual void onNewReverbLevel(Bit8u level) = 0;
+ virtual void onPolyStateChanged(Bit8u part_num) = 0;
+ virtual void onProgramChanged(Bit8u part_num, const char *sound_group_name, const char *patch_name) = 0;
+
+protected:
+ ~ReportHandler() {}
+};
+
+// Defines the interface for receiving MIDI messages generated by MIDI stream parser.
+// Corresponds to the current version of mt32emu_midi_receiver_i interface.
+class MidiReceiver {
+public:
+ virtual void handleShortMessage(const Bit32u message) = 0;
+ virtual void handleSysex(const Bit8u stream[], const Bit32u length) = 0;
+ virtual void handleSystemRealtimeMessage(const Bit8u realtime) = 0;
+
+protected:
+ ~MidiReceiver() {}
+};
+
+// Defines all the library services.
+// Corresponds to the current version of mt32emu_service_i interface.
+class Service {
+public:
+#if MT32EMU_API_TYPE == 2
+ explicit Service(mt32emu_service_i interface, mt32emu_context context = NULL) : i(interface), c(context) {}
+#else
+ explicit Service(mt32emu_context context = NULL) : c(context) {}
+#endif
+ ~Service() { if (c != NULL) mt32emu_free_context(c); }
+
+ // Context-independent methods
+
+#if MT32EMU_API_TYPE == 2
+ mt32emu_service_version getVersionID() { return i.v0->getVersionID(i); }
+#endif
+ mt32emu_report_handler_version getSupportedReportHandlerVersionID() { return mt32emu_get_supported_report_handler_version(); }
+ mt32emu_midi_receiver_version getSupportedMIDIReceiverVersionID() { return mt32emu_get_supported_midi_receiver_version(); }
+
+ Bit32u getLibraryVersionInt() { return mt32emu_get_library_version_int(); }
+ const char *getLibraryVersionString() { return mt32emu_get_library_version_string(); }
+
+ Bit32u getStereoOutputSamplerate(const AnalogOutputMode analog_output_mode) { return mt32emu_get_stereo_output_samplerate(static_cast<mt32emu_analog_output_mode>(analog_output_mode)); }
+
+ // Context-dependent methods
+
+ mt32emu_context getContext() { return c; }
+ void createContext(mt32emu_report_handler_i report_handler = CppInterfaceImpl::NULL_REPORT_HANDLER, void *instance_data = NULL) { freeContext(); c = mt32emu_create_context(report_handler, instance_data); }
+ void createContext(ReportHandler &report_handler) { createContext(CppInterfaceImpl::getReportHandlerThunk(), &report_handler); }
+ void freeContext() { if (c != NULL) { mt32emu_free_context(c); c = NULL; } }
+ mt32emu_return_code addROMData(const Bit8u *data, size_t data_size, const mt32emu_sha1_digest *sha1_digest = NULL) { return mt32emu_add_rom_data(c, data, data_size, sha1_digest); }
+ mt32emu_return_code addROMFile(const char *filename) { return mt32emu_add_rom_file(c, filename); }
+ void getROMInfo(mt32emu_rom_info *rom_info) { mt32emu_get_rom_info(c, rom_info); }
+ void setPartialCount(const Bit32u partial_count) { mt32emu_set_partial_count(c, partial_count); }
+ void setAnalogOutputMode(const AnalogOutputMode analog_output_mode) { mt32emu_set_analog_output_mode(c, static_cast<mt32emu_analog_output_mode>(analog_output_mode)); }
+ mt32emu_return_code openSynth() { return mt32emu_open_synth(c); }
+ void closeSynth() { mt32emu_close_synth(c); }
+ bool isOpen() { return mt32emu_is_open(c) != MT32EMU_BOOL_FALSE; }
+ Bit32u getActualStereoOutputSamplerate() { return mt32emu_get_actual_stereo_output_samplerate(c); }
+ void flushMIDIQueue() { mt32emu_flush_midi_queue(c); }
+ Bit32u setMIDIEventQueueSize(const Bit32u queue_size) { return mt32emu_set_midi_event_queue_size(c, queue_size); }
+ void setMIDIReceiver(mt32emu_midi_receiver_i midi_receiver, void *instance_data) { mt32emu_set_midi_receiver(c, midi_receiver, instance_data); }
+ void setMIDIReceiver(MidiReceiver &midi_receiver) { setMIDIReceiver(CppInterfaceImpl::getMidiReceiverThunk(), &midi_receiver); }
+
+ void parseStream(const Bit8u *stream, Bit32u length) { mt32emu_parse_stream(c, stream, length); }
+ void parseStream_At(const Bit8u *stream, Bit32u length, Bit32u timestamp) { mt32emu_parse_stream_at(c, stream, length, timestamp); }
+ void playShortMessage(Bit32u message) { mt32emu_play_short_message(c, message); }
+ void playShortMessageAt(Bit32u message, Bit32u timestamp) { mt32emu_play_short_message_at(c, message, timestamp); }
+ mt32emu_return_code playMsg(Bit32u msg) { return mt32emu_play_msg(c, msg); }
+ mt32emu_return_code playSysex(const Bit8u *sysex, Bit32u len) { return mt32emu_play_sysex(c, sysex, len); }
+ mt32emu_return_code playMsgAt(Bit32u msg, Bit32u timestamp) { return mt32emu_play_msg_at(c, msg, timestamp); }
+ mt32emu_return_code playSysexAt(const Bit8u *sysex, Bit32u len, Bit32u timestamp) { return mt32emu_play_sysex_at(c, sysex, len, timestamp); }
+
+ void playMsgNow(Bit32u msg) { mt32emu_play_msg_now(c, msg); }
+ void playMsgOnPart(Bit8u part, Bit8u code, Bit8u note, Bit8u velocity) { mt32emu_play_msg_on_part(c, part, code, note, velocity); }
+ void playSysexNow(const Bit8u *sysex, Bit32u len) { mt32emu_play_sysex_now(c, sysex, len); }
+ void writeSysex(Bit8u channel, const Bit8u *sysex, Bit32u len) { mt32emu_write_sysex(c, channel, sysex, len); }
+
+ void setReverbEnabled(const bool reverb_enabled) { mt32emu_set_reverb_enabled(c, reverb_enabled ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE); }
+ bool isReverbEnabled() { return mt32emu_is_reverb_enabled(c) != MT32EMU_BOOL_FALSE; }
+ void setReverbOverridden(const bool reverb_overridden) { mt32emu_set_reverb_overridden(c, reverb_overridden ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE); }
+ bool isReverbOverridden() { return mt32emu_is_reverb_overridden(c) != MT32EMU_BOOL_FALSE; }
+ void setReverbCompatibilityMode(const bool mt32_compatible_mode) { mt32emu_set_reverb_compatibility_mode(c, mt32_compatible_mode ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE); }
+ bool isMT32ReverbCompatibilityMode() { return mt32emu_is_mt32_reverb_compatibility_mode(c) != MT32EMU_BOOL_FALSE; }
+ bool isDefaultReverbMT32Compatible() { return mt32emu_is_default_reverb_mt32_compatible(c) != MT32EMU_BOOL_FALSE; }
+
+ void setDACInputMode(const DACInputMode mode) { mt32emu_set_dac_input_mode(c, static_cast<mt32emu_dac_input_mode>(mode)); }
+ DACInputMode getDACInputMode() { return static_cast<DACInputMode>(mt32emu_get_dac_input_mode(c)); }
+
+ void setMIDIDelayMode(const MIDIDelayMode mode) { mt32emu_set_midi_delay_mode(c, static_cast<mt32emu_midi_delay_mode>(mode)); }
+ MIDIDelayMode getMIDIDelayMode() { return static_cast<MIDIDelayMode>(mt32emu_get_midi_delay_mode(c)); }
+
+ void setOutputGain(float gain) { mt32emu_set_output_gain(c, gain); }
+ float getOutputGain() { return mt32emu_get_output_gain(c); }
+ void setReverbOutputGain(float gain) { mt32emu_set_reverb_output_gain(c, gain); }
+ float getReverbOutputGain() { return mt32emu_get_reverb_output_gain(c); }
+
+ void setReversedStereoEnabled(const bool enabled) { mt32emu_set_reversed_stereo_enabled(c, enabled ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE); }
+ bool isReversedStereoEnabled() { return mt32emu_is_reversed_stereo_enabled(c) != MT32EMU_BOOL_FALSE; }
+
+ void renderBit16s(Bit16s *stream, Bit32u len) { mt32emu_render_bit16s(c, stream, len); }
+ void renderFloat(float *stream, Bit32u len) { mt32emu_render_float(c, stream, len); }
+ void renderBit16sStreams(const mt32emu_dac_output_bit16s_streams *streams, Bit32u len) { mt32emu_render_bit16s_streams(c, streams, len); }
+ void renderFloatStreams(const mt32emu_dac_output_float_streams *streams, Bit32u len) { mt32emu_render_float_streams(c, streams, len); }
+
+ bool hasActivePartials() { return mt32emu_has_active_partials(c) != MT32EMU_BOOL_FALSE; }
+ bool isActive() { return mt32emu_is_active(c) != MT32EMU_BOOL_FALSE; }
+ Bit32u getPartialCount() { return mt32emu_get_partial_count(c); }
+ Bit32u getPartStates() { return mt32emu_get_part_states(c); }
+ void getPartialStates(Bit8u *partial_states) { mt32emu_get_partial_states(c, partial_states); }
+ Bit32u getPlayingNotes(Bit8u part_number, Bit8u *keys, Bit8u *velocities) { return mt32emu_get_playing_notes(c, part_number, keys, velocities); }
+ const char *getPatchName(Bit8u part_number) { return mt32emu_get_patch_name(c, part_number); }
+ void readMemory(Bit32u addr, Bit32u len, Bit8u *data) { mt32emu_read_memory(c, addr, len, data); }
+
+private:
+#if MT32EMU_API_TYPE == 2
+ const mt32emu_service_i i;
+#endif
+ mt32emu_context c;
+};
+
+namespace CppInterfaceImpl {
+
+static mt32emu_report_handler_version getReportHandlerVersionID(mt32emu_report_handler_i) {
+ return MT32EMU_REPORT_HANDLER_VERSION_CURRENT;
+}
+
+static void printDebug(void *instance_data, const char *fmt, va_list list) {
+ ((ReportHandler *)instance_data)->printDebug(fmt, list);
+}
+
+static void onErrorControlROM(void *instance_data) {
+ ((ReportHandler *)instance_data)->onErrorControlROM();
+}
+
+static void onErrorPCMROM(void *instance_data) {
+ ((ReportHandler *)instance_data)->onErrorPCMROM();
+}
+
+static void showLCDMessage(void *instance_data, const char *message) {
+ ((ReportHandler *)instance_data)->showLCDMessage(message);
+}
+
+static void onMIDIMessagePlayed(void *instance_data) {
+ ((ReportHandler *)instance_data)->onMIDIMessagePlayed();
+}
+
+static mt32emu_boolean onMIDIQueueOverflow(void *instance_data) {
+ return ((ReportHandler *)instance_data)->onMIDIQueueOverflow() ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE;
+}
+
+static void onMIDISystemRealtime(void *instance_data, mt32emu_bit8u system_realtime) {
+ ((ReportHandler *)instance_data)->onMIDISystemRealtime(system_realtime);
+}
+
+static void onDeviceReset(void *instance_data) {
+ ((ReportHandler *)instance_data)->onDeviceReset();
+}
+
+static void onDeviceReconfig(void *instance_data) {
+ ((ReportHandler *)instance_data)->onDeviceReconfig();
+}
+
+static void onNewReverbMode(void *instance_data, mt32emu_bit8u mode) {
+ ((ReportHandler *)instance_data)->onNewReverbMode(mode);
+}
+
+static void onNewReverbTime(void *instance_data, mt32emu_bit8u time) {
+ ((ReportHandler *)instance_data)->onNewReverbTime(time);
+}
+
+static void onNewReverbLevel(void *instance_data, mt32emu_bit8u level) {
+ ((ReportHandler *)instance_data)->onNewReverbLevel(level);
+}
+
+static void onPolyStateChanged(void *instance_data, mt32emu_bit8u part_num) {
+ ((ReportHandler *)instance_data)->onPolyStateChanged(part_num);
+}
+
+static void onProgramChanged(void *instance_data, mt32emu_bit8u part_num, const char *sound_group_name, const char *patch_name) {
+ ((ReportHandler *)instance_data)->onProgramChanged(part_num, sound_group_name, patch_name);
+}
+
+static mt32emu_report_handler_i getReportHandlerThunk() {
+ static const mt32emu_report_handler_i_v0 REPORT_HANDLER_V0_THUNK = {
+ getReportHandlerVersionID,
+ printDebug,
+ onErrorControlROM,
+ onErrorPCMROM,
+ showLCDMessage,
+ onMIDIMessagePlayed,
+ onMIDIQueueOverflow,
+ onMIDISystemRealtime,
+ onDeviceReset,
+ onDeviceReconfig,
+ onNewReverbMode,
+ onNewReverbTime,
+ onNewReverbLevel,
+ onPolyStateChanged,
+ onProgramChanged
+ };
+
+ static const mt32emu_report_handler_i REPORT_HANDLER_THUNK = { &REPORT_HANDLER_V0_THUNK };
+
+ return REPORT_HANDLER_THUNK;
+}
+
+static mt32emu_midi_receiver_version getMidiReceiverVersionID(mt32emu_midi_receiver_i) {
+ return MT32EMU_MIDI_RECEIVER_VERSION_CURRENT;
+}
+
+static void handleShortMessage(void *instance_data, const mt32emu_bit32u message) {
+ ((MidiReceiver *)instance_data)->handleShortMessage(message);
+}
+
+static void handleSysex(void *instance_data, const mt32emu_bit8u stream[], const mt32emu_bit32u length) {
+ ((MidiReceiver *)instance_data)->handleSysex(stream, length);
+}
+
+static void handleSystemRealtimeMessage(void *instance_data, const mt32emu_bit8u realtime) {
+ ((MidiReceiver *)instance_data)->handleSystemRealtimeMessage(realtime);
+}
+
+static mt32emu_midi_receiver_i getMidiReceiverThunk() {
+ static const mt32emu_midi_receiver_i_v0 MIDI_RECEIVER_V0_THUNK = {
+ getMidiReceiverVersionID,
+ handleShortMessage,
+ handleSysex,
+ handleSystemRealtimeMessage
+ };
+
+ static const mt32emu_midi_receiver_i MIDI_RECEIVER_THUNK = { &MIDI_RECEIVER_V0_THUNK };
+
+ return MIDI_RECEIVER_THUNK;
+}
+
+} // namespace CppInterfaceImpl
+
+} // namespace MT32Emu
+
+#if MT32EMU_API_TYPE == 2
+
+#undef mt32emu_get_supported_report_handler_version
+#undef mt32emu_get_supported_midi_receiver_version
+#undef mt32emu_get_library_version_int
+#undef mt32emu_get_library_version_string
+#undef mt32emu_get_stereo_output_samplerate
+#undef mt32emu_create_context
+#undef mt32emu_free_context
+#undef mt32emu_add_rom_data
+#undef mt32emu_add_rom_file
+#undef mt32emu_get_rom_info
+#undef mt32emu_set_partial_count
+#undef mt32emu_set_analog_output_mode
+#undef mt32emu_open_synth
+#undef mt32emu_close_synth
+#undef mt32emu_is_open
+#undef mt32emu_get_actual_stereo_output_samplerate
+#undef mt32emu_flush_midi_queue
+#undef mt32emu_set_midi_event_queue_size
+#undef mt32emu_set_midi_receiver
+#undef mt32emu_parse_stream
+#undef mt32emu_parse_stream_at
+#undef mt32emu_play_short_message
+#undef mt32emu_play_short_message_at
+#undef mt32emu_play_msg
+#undef mt32emu_play_sysex
+#undef mt32emu_play_msg_at
+#undef mt32emu_play_sysex_at
+#undef mt32emu_play_msg_now
+#undef mt32emu_play_msg_on_part
+#undef mt32emu_play_sysex_now
+#undef mt32emu_write_sysex
+#undef mt32emu_set_reverb_enabled
+#undef mt32emu_is_reverb_enabled
+#undef mt32emu_set_reverb_overridden
+#undef mt32emu_is_reverb_overridden
+#undef mt32emu_set_reverb_compatibility_mode
+#undef mt32emu_is_mt32_reverb_compatibility_mode
+#undef mt32emu_is_default_reverb_mt32_compatible
+#undef mt32emu_set_dac_input_mode
+#undef mt32emu_get_dac_input_mode
+#undef mt32emu_set_midi_delay_mode
+#undef mt32emu_get_midi_delay_mode
+#undef mt32emu_set_output_gain
+#undef mt32emu_get_output_gain
+#undef mt32emu_set_reverb_output_gain
+#undef mt32emu_get_reverb_output_gain
+#undef mt32emu_set_reversed_stereo_enabled
+#undef mt32emu_is_reversed_stereo_enabled
+#undef mt32emu_render_bit16s
+#undef mt32emu_render_float
+#undef mt32emu_render_bit16s_streams
+#undef mt32emu_render_float_streams
+#undef mt32emu_has_active_partials
+#undef mt32emu_is_active
+#undef mt32emu_get_partial_count
+#undef mt32emu_get_part_states
+#undef mt32emu_get_partial_states
+#undef mt32emu_get_playing_notes
+#undef mt32emu_get_patch_name
+#undef mt32emu_read_memory
+
+#endif // #if MT32EMU_API_TYPE == 2
+
+#endif /* #ifndef MT32EMU_CPP_INTERFACE_H */