diff options
author | Colin Snover | 2016-11-24 09:24:00 -0600 |
---|---|---|
committer | Colin Snover | 2016-11-25 12:14:13 -0600 |
commit | b4dbd6d3c275097b4be964b7da4478ff930cbaa7 (patch) | |
tree | bb9039cb088654fc93a7048eae799d53b06f3aa9 /audio/softsynth/mt32/c_interface | |
parent | b5b5c4f341530c41c73cc0d97e7ddae9cbc1d926 (diff) | |
download | scummvm-rg350-b4dbd6d3c275097b4be964b7da4478ff930cbaa7.tar.gz scummvm-rg350-b4dbd6d3c275097b4be964b7da4478ff930cbaa7.tar.bz2 scummvm-rg350-b4dbd6d3c275097b4be964b7da4478ff930cbaa7.zip |
MT32: Update Munt to 2.0.0
This changeset also removes unnecessary direct modifications to
Munt code to ease future updates. To update Munt in the future:
1. Replace all source files in the `softsynth/mt32` directory with
new files from the upstream `mt32emu/src` directory;
2. Update `config.h` with the correct version number for the new
version of Munt;
3. Update `module.mk` to match the list of sources given in
`mt32emu/CMakeLists.txt libmt32emu_SOURCES`.
Diffstat (limited to 'audio/softsynth/mt32/c_interface')
-rw-r--r-- | audio/softsynth/mt32/c_interface/c_interface.cpp | 624 | ||||
-rw-r--r-- | audio/softsynth/mt32/c_interface/c_interface.h | 362 | ||||
-rw-r--r-- | audio/softsynth/mt32/c_interface/c_types.h | 298 | ||||
-rw-r--r-- | audio/softsynth/mt32/c_interface/cpp_interface.h | 436 |
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 */ |