Update internal MUNT to version 2.7.0
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
@@ -24,7 +24,9 @@
|
||||
#include "c_types.h"
|
||||
|
||||
#undef MT32EMU_EXPORT
|
||||
#undef MT32EMU_EXPORT_V
|
||||
#define MT32EMU_EXPORT MT32EMU_EXPORT_ATTRIBUTE
|
||||
#define MT32EMU_EXPORT_V(symbol_version_tag) MT32EMU_EXPORT
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -35,24 +37,28 @@ extern "C" {
|
||||
/* === Interface handling === */
|
||||
|
||||
/** Returns mt32emu_service_i interface. */
|
||||
MT32EMU_EXPORT mt32emu_service_i mt32emu_get_service_i();
|
||||
MT32EMU_EXPORT mt32emu_service_i MT32EMU_C_CALL mt32emu_get_service_i(void);
|
||||
|
||||
#if MT32EMU_EXPORTS_TYPE == 2
|
||||
#undef MT32EMU_EXPORT
|
||||
#undef MT32EMU_EXPORT_V
|
||||
#define MT32EMU_EXPORT
|
||||
#define MT32EMU_EXPORT_V(symbol_version_tag) 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();
|
||||
MT32EMU_EXPORT mt32emu_report_handler_version MT32EMU_C_CALL mt32emu_get_supported_report_handler_version(void);
|
||||
|
||||
/**
|
||||
* 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();
|
||||
MT32EMU_EXPORT mt32emu_midi_receiver_version MT32EMU_C_CALL mt32emu_get_supported_midi_receiver_version(void);
|
||||
|
||||
/* === Utility === */
|
||||
|
||||
/**
|
||||
* Returns library version as an integer in format: 0x00MMmmpp, where:
|
||||
@@ -60,67 +66,149 @@ MT32EMU_EXPORT mt32emu_midi_receiver_version mt32emu_get_supported_midi_receiver
|
||||
* mm - minor version number
|
||||
* pp - patch number
|
||||
*/
|
||||
MT32EMU_EXPORT mt32emu_bit32u mt32emu_get_library_version_int();
|
||||
MT32EMU_EXPORT mt32emu_bit32u MT32EMU_C_CALL mt32emu_get_library_version_int(void);
|
||||
|
||||
/**
|
||||
* Returns library version as a C-string in format: "MAJOR.MINOR.PATCH".
|
||||
*/
|
||||
MT32EMU_EXPORT const char *mt32emu_get_library_version_string();
|
||||
MT32EMU_EXPORT const char * MT32EMU_C_CALL mt32emu_get_library_version_string(void);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
MT32EMU_EXPORT mt32emu_bit32u MT32EMU_C_CALL mt32emu_get_stereo_output_samplerate(const mt32emu_analog_output_mode analog_output_mode);
|
||||
|
||||
/**
|
||||
* Returns the value of analog_output_mode for which the output signal may retain its full frequency spectrum
|
||||
* at the sample rate specified by the target_samplerate argument.
|
||||
* See comment for mt32emu_analog_output_mode.
|
||||
*/
|
||||
MT32EMU_EXPORT mt32emu_analog_output_mode mt32emu_get_best_analog_output_mode(const double target_samplerate);
|
||||
MT32EMU_EXPORT mt32emu_analog_output_mode MT32EMU_C_CALL mt32emu_get_best_analog_output_mode(const double target_samplerate);
|
||||
|
||||
/* === ROM handling === */
|
||||
|
||||
/**
|
||||
* Retrieves a list of identifiers (as C-strings) of supported machines. Argument machine_ids points to the array of size
|
||||
* machine_ids_size to be filled.
|
||||
* Returns the number of identifiers available for retrieval. The size of the target array to be allocated can be found
|
||||
* by passing NULL in argument machine_ids; argument machine_ids_size is ignored in this case.
|
||||
*/
|
||||
MT32EMU_EXPORT_V(2.5) size_t MT32EMU_C_CALL mt32emu_get_machine_ids(const char **machine_ids, size_t machine_ids_size);
|
||||
/**
|
||||
* Retrieves a list of identifiers (as C-strings) of supported ROM images. Argument rom_ids points to the array of size
|
||||
* rom_ids_size to be filled. Optional argument machine_id can be used to indicate a specific machine to retrieve ROM identifiers
|
||||
* for; if NULL, identifiers of all the ROM images supported by the emulation engine are retrieved.
|
||||
* Returns the number of ROM identifiers available for retrieval. The size of the target array to be allocated can be found
|
||||
* by passing NULL in argument rom_ids; argument rom_ids_size is ignored in this case. If argument machine_id contains
|
||||
* an unrecognised value, 0 is returned.
|
||||
*/
|
||||
MT32EMU_EXPORT_V(2.5) size_t MT32EMU_C_CALL mt32emu_get_rom_ids(const char **rom_ids, size_t rom_ids_size, const char *machine_id);
|
||||
|
||||
/**
|
||||
* Identifies a ROM image the provided data array contains by its SHA1 digest. Optional argument machine_id can be used to indicate
|
||||
* a specific machine to identify the ROM image for; if NULL, the ROM image is identified for any supported machine.
|
||||
* A mt32emu_rom_info structure supplied in argument rom_info is filled in accordance with the provided ROM image; unused fields
|
||||
* are filled with NULLs. If the content of the ROM image is not identified successfully (e.g. when the ROM image is incompatible
|
||||
* with the specified machine), all fields of rom_info are filled with NULLs.
|
||||
* Returns MT32EMU_RC_OK upon success or a negative error code otherwise.
|
||||
*/
|
||||
MT32EMU_EXPORT_V(2.5) mt32emu_return_code MT32EMU_C_CALL mt32emu_identify_rom_data(mt32emu_rom_info *rom_info, const mt32emu_bit8u *data, size_t data_size, const char *machine_id);
|
||||
/**
|
||||
* Loads the content of the file specified by argument filename and identifies a ROM image the file contains by its SHA1 digest.
|
||||
* Optional argument machine_id can be used to indicate a specific machine to identify the ROM image for; if NULL, the ROM image
|
||||
* is identified for any supported machine.
|
||||
* A mt32emu_rom_info structure supplied in argument rom_info is filled in accordance with the provided ROM image; unused fields
|
||||
* are filled with NULLs. If the content of the file is not identified successfully (e.g. when the ROM image is incompatible
|
||||
* with the specified machine), all fields of rom_info are filled with NULLs.
|
||||
* Returns MT32EMU_RC_OK upon success or a negative error code otherwise.
|
||||
*/
|
||||
MT32EMU_EXPORT_V(2.5) mt32emu_return_code MT32EMU_C_CALL mt32emu_identify_rom_file(mt32emu_rom_info *rom_info, const char *filename, const char *machine_id);
|
||||
|
||||
/* == 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);
|
||||
MT32EMU_EXPORT mt32emu_context MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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.
|
||||
* Adds a new full ROM data image 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().
|
||||
* The provided data array is NOT copied and used directly for efficiency. The caller should not deallocate it while the emulation
|
||||
* context is referring to the ROM data.
|
||||
* 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);
|
||||
MT32EMU_EXPORT mt32emu_return_code MT32EMU_C_CALL 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().
|
||||
* Loads a ROM file that contains a full ROM data image, identifies it by the 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);
|
||||
MT32EMU_EXPORT mt32emu_return_code MT32EMU_C_CALL mt32emu_add_rom_file(mt32emu_context context, const char *filename);
|
||||
|
||||
/**
|
||||
* Merges a pair of compatible ROM data image parts into a full image and adds it to the emulation context replacing previously
|
||||
* added ROM of the same type if any. Each partial image is identified by its SHA1 digest. Arguments partN_sha1_digest can be NULL,
|
||||
* in this case the digest will be computed using the actual ROM data. If a non-NULL SHA1 value is provided, it is assumed being
|
||||
* correct and will not be recomputed. The provided data arrays may be deallocated as soon as the function completes.
|
||||
* 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_V(2.5) mt32emu_return_code MT32EMU_C_CALL mt32emu_merge_and_add_rom_data(mt32emu_context context, const mt32emu_bit8u *part1_data, size_t part1_data_size, const mt32emu_sha1_digest *part1_sha1_digest, const mt32emu_bit8u *part2_data, size_t part2_data_size, const mt32emu_sha1_digest *part2_sha1_digest);
|
||||
|
||||
/**
|
||||
* Loads a pair of files that contains compatible parts of a full ROM image, identifies them by the SHA1 digest, merges these
|
||||
* parts into a full ROM image 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_V(2.5) mt32emu_return_code MT32EMU_C_CALL mt32emu_merge_and_add_rom_files(mt32emu_context context, const char *part1_filename, const char *part2_filename);
|
||||
|
||||
/**
|
||||
* Loads a file that contains a ROM image of a specific machine, identifies it by the SHA1 digest, and adds it to the emulation
|
||||
* context. The ROM image can only be identified successfully if it is compatible with the specified machine.
|
||||
* Full and partial ROM images are supported and handled according to the following rules:
|
||||
* - a file with any compatible ROM image is added if none (of the same type) exists in the emulation context;
|
||||
* - a file with any compatible ROM image replaces any image of the same type that is incompatible with the specified machine;
|
||||
* - a file with a full ROM image replaces the previously added partial ROM of the same type;
|
||||
* - a file with a partial ROM image is merged with the previously added ROM image if pairable;
|
||||
* - otherwise, the file is ignored.
|
||||
* The described behaviour allows the caller application to traverse a directory with ROM files attempting to add each one in turn.
|
||||
* As soon as both the full control and the full PCM ROM images are added and / or merged, the iteration can be stopped.
|
||||
* This function doesn't immediately change the state of already opened synth. Newly added ROMs will take effect upon next call of
|
||||
* mt32emu_open_synth().
|
||||
* Returns a positive value in case changes have been made, MT32EMU_RC_OK if the file has been ignored or a negative error code
|
||||
* upon failure.
|
||||
*/
|
||||
MT32EMU_EXPORT_V(2.5) mt32emu_return_code MT32EMU_C_CALL mt32emu_add_machine_rom_file(mt32emu_context context, const char *machine_id, 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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 value 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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 value 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_set_analog_output_mode(mt32emu_context context, const mt32emu_analog_output_mode analog_output_mode);
|
||||
|
||||
/**
|
||||
* Allows to convert the synthesiser output to any desired sample rate. The samplerate conversion
|
||||
@@ -131,7 +219,7 @@ MT32EMU_EXPORT void mt32emu_set_analog_output_mode(mt32emu_context context, cons
|
||||
* This function doesn't immediately change the state of already opened synth.
|
||||
* Newly set value will take effect upon next call of mt32emu_open_synth().
|
||||
*/
|
||||
MT32EMU_EXPORT void mt32emu_set_stereo_output_samplerate(mt32emu_context context, const double samplerate);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_set_stereo_output_samplerate(mt32emu_context context, const double samplerate);
|
||||
|
||||
/**
|
||||
* Several samplerate conversion quality options are provided which allow to trade-off the conversion speed vs.
|
||||
@@ -140,66 +228,79 @@ MT32EMU_EXPORT void mt32emu_set_stereo_output_samplerate(mt32emu_context context
|
||||
* This function doesn't immediately change the state of already opened synth.
|
||||
* Newly set value will take effect upon next call of mt32emu_open_synth().
|
||||
*/
|
||||
MT32EMU_EXPORT void mt32emu_set_samplerate_conversion_quality(mt32emu_context context, const mt32emu_samplerate_conversion_quality quality);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_set_samplerate_conversion_quality(mt32emu_context context, const mt32emu_samplerate_conversion_quality quality);
|
||||
|
||||
/**
|
||||
* Selects new type of the wave generator and renderer to be used during subsequent calls to mt32emu_open_synth().
|
||||
* By default, MT32EMU_RT_BIT16S is selected.
|
||||
* See mt32emu_renderer_type for details.
|
||||
*/
|
||||
MT32EMU_EXPORT void mt32emu_select_renderer_type(mt32emu_context context, const mt32emu_renderer_type renderer_type);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_select_renderer_type(mt32emu_context context, const mt32emu_renderer_type renderer_type);
|
||||
|
||||
/**
|
||||
* Returns previously selected type of the wave generator and renderer.
|
||||
* See mt32emu_renderer_type for details.
|
||||
*/
|
||||
MT32EMU_EXPORT mt32emu_renderer_type mt32emu_get_selected_renderer_type(mt32emu_context context);
|
||||
MT32EMU_EXPORT mt32emu_renderer_type MT32EMU_C_CALL mt32emu_get_selected_renderer_type(mt32emu_context context);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
MT32EMU_EXPORT mt32emu_return_code MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT mt32emu_boolean MT32EMU_C_CALL mt32emu_is_open(mt32emu_const_context context);
|
||||
|
||||
/**
|
||||
* Returns actual sample rate of the fully processed output stereo signal.
|
||||
* If samplerate conversion is used (i.e. when mt32emu_set_stereo_output_samplerate() has been invoked with a non-zero value),
|
||||
* the returned value is the desired output samplerate rounded down to the closest integer.
|
||||
* Otherwise, the output samplerate is choosen depending on the emulation mode of stereo analog circuitry of hardware units.
|
||||
* Otherwise, the output samplerate is chosen depending on the emulation mode of stereo analog circuitry of hardware units.
|
||||
* See comment for mt32emu_analog_output_mode for more info.
|
||||
*/
|
||||
MT32EMU_EXPORT mt32emu_bit32u mt32emu_get_actual_stereo_output_samplerate(mt32emu_const_context context);
|
||||
MT32EMU_EXPORT mt32emu_bit32u MT32EMU_C_CALL mt32emu_get_actual_stereo_output_samplerate(mt32emu_const_context context);
|
||||
|
||||
/**
|
||||
* Returns the number of samples produced at the internal synth sample rate (32000 Hz)
|
||||
* that correspond to the given number of samples at the output sample rate.
|
||||
* Intended to facilitate audio time synchronisation.
|
||||
*/
|
||||
MT32EMU_EXPORT mt32emu_bit32u mt32emu_convert_output_to_synth_timestamp(mt32emu_const_context context, mt32emu_bit32u output_timestamp);
|
||||
MT32EMU_EXPORT mt32emu_bit32u MT32EMU_C_CALL mt32emu_convert_output_to_synth_timestamp(mt32emu_const_context context, mt32emu_bit32u output_timestamp);
|
||||
|
||||
/**
|
||||
* Returns the number of samples produced at the output sample rate
|
||||
* that correspond to the given number of samples at the internal synth sample rate (32000 Hz).
|
||||
* Intended to facilitate audio time synchronisation.
|
||||
*/
|
||||
MT32EMU_EXPORT mt32emu_bit32u mt32emu_convert_synth_to_output_timestamp(mt32emu_const_context context, mt32emu_bit32u synth_timestamp);
|
||||
MT32EMU_EXPORT mt32emu_bit32u MT32EMU_C_CALL mt32emu_convert_synth_to_output_timestamp(mt32emu_const_context context, mt32emu_bit32u synth_timestamp);
|
||||
|
||||
/** All the enqueued events are processed by the synth immediately. */
|
||||
MT32EMU_EXPORT void mt32emu_flush_midi_queue(mt32emu_const_context context);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT mt32emu_bit32u MT32EMU_C_CALL mt32emu_set_midi_event_queue_size(mt32emu_const_context context, const mt32emu_bit32u queue_size);
|
||||
|
||||
/**
|
||||
* Configures the SysEx storage of the internal MIDI event queue.
|
||||
* Supplying 0 in the storage_buffer_size argument makes the SysEx data stored
|
||||
* in multiple dynamically allocated buffers per MIDI event. These buffers are only disposed
|
||||
* when a new MIDI event replaces the SysEx event in the queue, thus never on the rendering thread.
|
||||
* This is the default behaviour.
|
||||
* In contrast, when a positive value is specified, SysEx data will be stored in a single preallocated buffer,
|
||||
* which makes this kind of storage safe for use in a realtime thread. Additionally, the space retained
|
||||
* by a SysEx event, that has been processed and thus is no longer necessary, is disposed instantly.
|
||||
* Note, the queue is flushed and recreated in the process so that its size remains intact.
|
||||
*/
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_configure_midi_event_queue_sysex_storage(mt32emu_const_context context, const mt32emu_bit32u storage_buffer_size);
|
||||
|
||||
/**
|
||||
* Installs custom MIDI receiver object intended for receiving MIDI messages generated by MIDI stream parser.
|
||||
@@ -207,13 +308,13 @@ MT32EMU_EXPORT mt32emu_bit32u mt32emu_set_midi_event_queue_size(mt32emu_const_co
|
||||
* 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_set_midi_receiver(mt32emu_context context, mt32emu_midi_receiver_i midi_receiver, void *instance_data);
|
||||
|
||||
/**
|
||||
* Returns current value of the global counter of samples rendered since the synth was created (at the native sample rate 32000 Hz).
|
||||
* This method helps to compute accurate timestamp of a MIDI message to use with the methods below.
|
||||
*/
|
||||
MT32EMU_EXPORT mt32emu_bit32u mt32emu_get_internal_rendered_sample_count(mt32emu_const_context context);
|
||||
MT32EMU_EXPORT mt32emu_bit32u MT32EMU_C_CALL mt32emu_get_internal_rendered_sample_count(mt32emu_const_context context);
|
||||
|
||||
/* Enqueues a MIDI event for subsequent playback.
|
||||
* The MIDI event will be processed not before the specified timestamp.
|
||||
@@ -230,7 +331,7 @@ MT32EMU_EXPORT mt32emu_bit32u mt32emu_get_internal_rendered_sample_count(mt32emu
|
||||
* 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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.
|
||||
@@ -238,31 +339,31 @@ MT32EMU_EXPORT void mt32emu_parse_stream(mt32emu_const_context context, const mt
|
||||
* 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT mt32emu_return_code MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT mt32emu_return_code MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT mt32emu_return_code MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT mt32emu_return_code MT32EMU_C_CALL 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,
|
||||
@@ -274,66 +375,73 @@ MT32EMU_EXPORT mt32emu_return_code mt32emu_play_sysex_at(mt32emu_const_context c
|
||||
* 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT mt32emu_boolean MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT mt32emu_boolean MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT mt32emu_boolean MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT mt32emu_boolean MT32EMU_C_CALL mt32emu_is_default_reverb_mt32_compatible(mt32emu_const_context context);
|
||||
|
||||
/**
|
||||
* If enabled, reverb buffers for all modes are kept around allocated all the time to avoid memory
|
||||
* allocating/freeing in the rendering thread, which may be required for realtime operation.
|
||||
* Otherwise, reverb buffers that are not in use are deleted to save memory (the default behaviour).
|
||||
*/
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_preallocate_reverb_memory(mt32emu_const_context context, const mt32emu_boolean enabled);
|
||||
|
||||
/** 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT mt32emu_dac_input_mode MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT mt32emu_midi_delay_mode MT32EMU_C_CALL 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.
|
||||
*/
|
||||
MT32EMU_EXPORT void mt32emu_set_output_gain(mt32emu_const_context context, float gain);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT float MT32EMU_C_CALL 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
|
||||
@@ -345,14 +453,34 @@ MT32EMU_EXPORT float mt32emu_get_output_gain(mt32emu_const_context context);
|
||||
* 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.
|
||||
*/
|
||||
MT32EMU_EXPORT void mt32emu_set_reverb_output_gain(mt32emu_const_context context, float gain);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT float MT32EMU_C_CALL mt32emu_get_reverb_output_gain(mt32emu_const_context context);
|
||||
|
||||
/**
|
||||
* Sets (or removes) an override for the current volume (output level) on a specific part.
|
||||
* When the part volume is overridden, the MIDI controller Volume (7) on the MIDI channel this part is assigned to
|
||||
* has no effect on the output level of this part. Similarly, the output level value set on this part via a SysEx that
|
||||
* modifies the Patch temp structure is disregarded.
|
||||
* To enable the override mode, argument volumeOverride should be in range 0..100, setting a value outside this range
|
||||
* disables the previously set override, if any.
|
||||
* Note: Setting volumeOverride to 0 mutes the part completely, meaning no sound is generated at all.
|
||||
* This is unlike the behaviour of real devices - setting 0 volume on a part may leave it still producing
|
||||
* sound at a very low level.
|
||||
* Argument partNumber should be 0..7 for Part 1..8, or 8 for Rhythm.
|
||||
*/
|
||||
MT32EMU_EXPORT_V(2.6) void MT32EMU_C_CALL mt32emu_set_part_volume_override(mt32emu_const_context context, mt32emu_bit8u part_number, mt32emu_bit8u volume_override);
|
||||
/**
|
||||
* Returns the overridden volume previously set on a specific part; a value outside the range 0..100 means no override
|
||||
* is currently in effect.
|
||||
* Argument partNumber should be 0..7 for Part 1..8, or 8 for Rhythm.
|
||||
*/
|
||||
MT32EMU_EXPORT_V(2.6) mt32emu_bit8u MT32EMU_C_CALL mt32emu_get_part_volume_override(mt32emu_const_context context, mt32emu_bit8u part_number);
|
||||
|
||||
/** Swaps left and right output channels. */
|
||||
MT32EMU_EXPORT void mt32emu_set_reversed_stereo_enabled(mt32emu_const_context context, const mt32emu_boolean enabled);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT mt32emu_boolean MT32EMU_C_CALL mt32emu_is_reversed_stereo_enabled(mt32emu_const_context context);
|
||||
|
||||
/**
|
||||
* Allows to toggle the NiceAmpRamp mode.
|
||||
@@ -362,9 +490,36 @@ MT32EMU_EXPORT mt32emu_boolean mt32emu_is_reversed_stereo_enabled(mt32emu_const_
|
||||
* We also prefer the quality improvement over the emulation accuracy,
|
||||
* so this mode is enabled by default.
|
||||
*/
|
||||
MT32EMU_EXPORT void mt32emu_set_nice_amp_ramp_enabled(mt32emu_const_context context, const mt32emu_boolean enabled);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_set_nice_amp_ramp_enabled(mt32emu_const_context context, const mt32emu_boolean enabled);
|
||||
/** Returns whether NiceAmpRamp mode is enabled. */
|
||||
MT32EMU_EXPORT mt32emu_boolean mt32emu_is_nice_amp_ramp_enabled(mt32emu_const_context context);
|
||||
MT32EMU_EXPORT mt32emu_boolean MT32EMU_C_CALL mt32emu_is_nice_amp_ramp_enabled(mt32emu_const_context context);
|
||||
|
||||
/**
|
||||
* Allows to toggle the NicePanning mode.
|
||||
* Despite the Roland's manual specifies allowed panpot values in range 0-14,
|
||||
* the LA-32 only receives 3-bit pan setting in fact. In particular, this
|
||||
* makes it impossible to set the "middle" panning for a single partial.
|
||||
* In the NicePanning mode, we enlarge the pan setting accuracy to 4 bits
|
||||
* making it smoother thus sacrificing the emulation accuracy.
|
||||
* This mode is disabled by default.
|
||||
*/
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_set_nice_panning_enabled(mt32emu_const_context context, const mt32emu_boolean enabled);
|
||||
/** Returns whether NicePanning mode is enabled. */
|
||||
MT32EMU_EXPORT mt32emu_boolean MT32EMU_C_CALL mt32emu_is_nice_panning_enabled(mt32emu_const_context context);
|
||||
|
||||
/**
|
||||
* Allows to toggle the NicePartialMixing mode.
|
||||
* LA-32 is known to mix partials either in-phase (so that they are added)
|
||||
* or in counter-phase (so that they are subtracted instead).
|
||||
* In some cases, this quirk isn't highly desired because a pair of closely
|
||||
* sounding partials may occasionally cancel out.
|
||||
* In the NicePartialMixing mode, the mixing is always performed in-phase,
|
||||
* thus making the behaviour more predictable.
|
||||
* This mode is disabled by default.
|
||||
*/
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_set_nice_partial_mixing_enabled(mt32emu_const_context context, const mt32emu_boolean enabled);
|
||||
/** Returns whether NicePartialMixing mode is enabled. */
|
||||
MT32EMU_EXPORT mt32emu_boolean MT32EMU_C_CALL mt32emu_is_nice_partial_mixing_enabled(mt32emu_const_context context);
|
||||
|
||||
/**
|
||||
* Renders samples to the specified output stream as if they were sampled at the analog stereo output at the desired sample rate.
|
||||
@@ -372,9 +527,9 @@ MT32EMU_EXPORT mt32emu_boolean mt32emu_is_nice_amp_ramp_enabled(mt32emu_const_co
|
||||
* mode of analog circuitry emulation. See mt32emu_analog_output_mode.
|
||||
* 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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.
|
||||
@@ -382,25 +537,25 @@ MT32EMU_EXPORT void mt32emu_render_float(mt32emu_const_context context, float *s
|
||||
* 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT mt32emu_boolean MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT mt32emu_boolean MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT mt32emu_bit32u MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT mt32emu_bit32u MT32EMU_C_CALL 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
|
||||
@@ -408,7 +563,7 @@ MT32EMU_EXPORT mt32emu_bit32u mt32emu_get_part_states(mt32emu_const_context cont
|
||||
* 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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
|
||||
@@ -416,16 +571,71 @@ MT32EMU_EXPORT void mt32emu_get_partial_states(mt32emu_const_context context, mt
|
||||
* 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);
|
||||
MT32EMU_EXPORT mt32emu_bit32u MT32EMU_C_CALL 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.
|
||||
* The returned value is a null-terminated string which is guaranteed to remain valid until the next call to one of functions
|
||||
* that perform sample rendering or immediate SysEx processing (e.g. mt32emu_play_sysex_now).
|
||||
*/
|
||||
MT32EMU_EXPORT const char *mt32emu_get_patch_name(mt32emu_const_context context, mt32emu_bit8u part_number);
|
||||
MT32EMU_EXPORT const char * MT32EMU_C_CALL mt32emu_get_patch_name(mt32emu_const_context context, mt32emu_bit8u part_number);
|
||||
|
||||
/**
|
||||
* Retrieves the name of the sound group the timbre identified by arguments timbre_group and timbre_number is associated with.
|
||||
* Values 0-3 of timbre_group correspond to the timbre banks GROUP A, GROUP B, MEMORY and RHYTHM.
|
||||
* For all but the RHYTHM timbre bank, allowed values of timbre_number are in range 0-63. The number of timbres
|
||||
* contained in the RHYTHM bank depends on the used control ROM version.
|
||||
* The argument sound_group_name must point to an array of at least 8 characters. The result is a null-terminated string.
|
||||
* Returns whether the specified timbre has been found and the result written in sound_group_name.
|
||||
*/
|
||||
MT32EMU_EXPORT_V(2.7) mt32emu_boolean MT32EMU_C_CALL mt32emu_get_sound_group_name(mt32emu_const_context context, char *sound_group_name, mt32emu_bit8u timbre_group, mt32emu_bit8u timbre_number);
|
||||
/**
|
||||
* Retrieves the name of the timbre identified by arguments timbre_group and timbre_number.
|
||||
* Values 0-3 of timbre_group correspond to the timbre banks GROUP A, GROUP B, MEMORY and RHYTHM.
|
||||
* For all but the RHYTHM timbre bank, allowed values of timbre_number are in range 0-63. The number of timbres
|
||||
* contained in the RHYTHM bank depends on the used control ROM version.
|
||||
* The argument sound_name must point to an array of at least 11 characters. The result is a null-terminated string.
|
||||
* Returns whether the specified timbre has been found and the result written in sound_name.
|
||||
*/
|
||||
MT32EMU_EXPORT_V(2.7) mt32emu_boolean MT32EMU_C_CALL mt32emu_get_sound_name(mt32emu_const_context context, char *sound_name, mt32emu_bit8u timbreGroup, mt32emu_bit8u timbreNumber);
|
||||
|
||||
/** 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_read_memory(mt32emu_const_context context, mt32emu_bit32u addr, mt32emu_bit32u len, mt32emu_bit8u *data);
|
||||
|
||||
/**
|
||||
* Retrieves the current state of the emulated MT-32 display facilities.
|
||||
* Typically, the state is updated during the rendering. When that happens, a related callback from mt32emu_report_handler_i_v1
|
||||
* is invoked. However, there might be no need to invoke this method after each update, e.g. when the render buffer is just
|
||||
* a few milliseconds long.
|
||||
* The argument target_buffer must point to an array of at least 21 characters. The result is a null-terminated string.
|
||||
* The argument narrow_lcd enables a condensed representation of the displayed information in some cases. This is mainly intended
|
||||
* to route the result to a hardware LCD that is only 16 characters wide. Automatic scrolling of longer strings is not supported.
|
||||
* Returns whether the MIDI MESSAGE LED is ON and fills the target_buffer parameter.
|
||||
*/
|
||||
MT32EMU_EXPORT_V(2.6) mt32emu_boolean MT32EMU_C_CALL mt32emu_get_display_state(mt32emu_const_context context, char *target_buffer, const mt32emu_boolean narrow_lcd);
|
||||
|
||||
/**
|
||||
* Resets the emulated LCD to the main mode (Master Volume). This has the same effect as pressing the Master Volume button
|
||||
* while the display shows some other message. Useful for the new-gen devices as those require a special Display Reset SysEx
|
||||
* to return to the main mode e.g. from showing a custom display message or a checksum error.
|
||||
*/
|
||||
MT32EMU_EXPORT_V(2.6) void MT32EMU_C_CALL mt32emu_set_main_display_mode(mt32emu_const_context context);
|
||||
|
||||
/**
|
||||
* Permits to select an arbitrary display emulation model that does not necessarily match the actual behaviour implemented
|
||||
* in the control ROM version being used.
|
||||
* Invoking this method with the argument set to true forces emulation of the old-gen MT-32 display features.
|
||||
* Otherwise, emulation of the new-gen devices is enforced (these include CM-32L and LAPC-I as if these were connected to an LCD).
|
||||
*/
|
||||
MT32EMU_EXPORT_V(2.6) void MT32EMU_C_CALL mt32emu_set_display_compatibility(mt32emu_const_context context, mt32emu_boolean old_mt32_compatibility_enabled);
|
||||
/** Returns whether the currently configured features of the emulated display are compatible with the old-gen MT-32 devices. */
|
||||
MT32EMU_EXPORT_V(2.6) mt32emu_boolean MT32EMU_C_CALL mt32emu_is_display_old_mt32_compatible(mt32emu_const_context context);
|
||||
/**
|
||||
* Returns whether the emulated display features configured by default depending on the actual control ROM version
|
||||
* are compatible with the old-gen MT-32 devices.
|
||||
*/
|
||||
MT32EMU_EXPORT_V(2.6) mt32emu_boolean MT32EMU_C_CALL mt32emu_is_default_display_old_mt32_compatible(mt32emu_const_context context);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
@@ -27,6 +27,12 @@
|
||||
#include "../Enumerations.h"
|
||||
#undef MT32EMU_C_ENUMERATIONS
|
||||
|
||||
#ifdef _WIN32
|
||||
# define MT32EMU_C_CALL __cdecl
|
||||
#else
|
||||
# define MT32EMU_C_CALL
|
||||
#endif
|
||||
|
||||
typedef unsigned int mt32emu_bit32u;
|
||||
typedef signed int mt32emu_bit32s;
|
||||
typedef unsigned short int mt32emu_bit16u;
|
||||
@@ -45,6 +51,8 @@ typedef enum {
|
||||
MT32EMU_RC_OK = 0,
|
||||
MT32EMU_RC_ADDED_CONTROL_ROM = 1,
|
||||
MT32EMU_RC_ADDED_PCM_ROM = 2,
|
||||
MT32EMU_RC_ADDED_PARTIAL_CONTROL_ROM = 3,
|
||||
MT32EMU_RC_ADDED_PARTIAL_PCM_ROM = 4,
|
||||
|
||||
/* Definite error occurred. */
|
||||
MT32EMU_RC_ROM_NOT_IDENTIFIED = -1,
|
||||
@@ -53,6 +61,8 @@ typedef enum {
|
||||
MT32EMU_RC_MISSING_ROMS = -4,
|
||||
MT32EMU_RC_NOT_OPENED = -5,
|
||||
MT32EMU_RC_QUEUE_FULL = -6,
|
||||
MT32EMU_RC_ROMS_NOT_PAIRABLE = -7,
|
||||
MT32EMU_RC_MACHINE_NOT_IDENTIFIED = -8,
|
||||
|
||||
/* Undefined error occurred. */
|
||||
MT32EMU_RC_FAILED = -100
|
||||
@@ -107,7 +117,8 @@ typedef struct {
|
||||
/** 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_1 = 1,
|
||||
MT32EMU_REPORT_HANDLER_VERSION_CURRENT = MT32EMU_REPORT_HANDLER_VERSION_1
|
||||
} mt32emu_report_handler_version;
|
||||
|
||||
/** MIDI receiver interface versions */
|
||||
@@ -121,7 +132,11 @@ typedef enum {
|
||||
MT32EMU_SERVICE_VERSION_0 = 0,
|
||||
MT32EMU_SERVICE_VERSION_1 = 1,
|
||||
MT32EMU_SERVICE_VERSION_2 = 2,
|
||||
MT32EMU_SERVICE_VERSION_CURRENT = MT32EMU_SERVICE_VERSION_2
|
||||
MT32EMU_SERVICE_VERSION_3 = 3,
|
||||
MT32EMU_SERVICE_VERSION_4 = 4,
|
||||
MT32EMU_SERVICE_VERSION_5 = 5,
|
||||
MT32EMU_SERVICE_VERSION_6 = 6,
|
||||
MT32EMU_SERVICE_VERSION_CURRENT = MT32EMU_SERVICE_VERSION_6
|
||||
} mt32emu_service_version;
|
||||
|
||||
/* === Report Handler Interface === */
|
||||
@@ -129,42 +144,59 @@ typedef enum {
|
||||
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);
|
||||
#define MT32EMU_REPORT_HANDLER_I_V0 \
|
||||
/** Returns the actual interface version ID */ \
|
||||
mt32emu_report_handler_version (MT32EMU_C_CALL *getVersionID)(mt32emu_report_handler_i i); \
|
||||
\
|
||||
/** Callback for debug messages, in vprintf() format */ \
|
||||
void (MT32EMU_C_CALL *printDebug)(void *instance_data, const char *fmt, va_list list); \
|
||||
/** Callbacks for reporting errors */ \
|
||||
void (MT32EMU_C_CALL *onErrorControlROM)(void *instance_data); \
|
||||
void (MT32EMU_C_CALL *onErrorPCMROM)(void *instance_data); \
|
||||
/** Callback for reporting about displaying a new custom message on LCD */ \
|
||||
void (MT32EMU_C_CALL *showLCDMessage)(void *instance_data, const char *message); \
|
||||
/** Callback for reporting actual processing of a MIDI message */ \
|
||||
void (MT32EMU_C_CALL *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);
|
||||
*/ \
|
||||
mt32emu_boolean (MT32EMU_C_CALL *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);
|
||||
*/ \
|
||||
void (MT32EMU_C_CALL *onMIDISystemRealtime)(void *instance_data, mt32emu_bit8u system_realtime); \
|
||||
/** Callbacks for reporting system events */ \
|
||||
void (MT32EMU_C_CALL *onDeviceReset)(void *instance_data); \
|
||||
void (MT32EMU_C_CALL *onDeviceReconfig)(void *instance_data); \
|
||||
/** Callbacks for reporting changes of reverb settings */ \
|
||||
void (MT32EMU_C_CALL *onNewReverbMode)(void *instance_data, mt32emu_bit8u mode); \
|
||||
void (MT32EMU_C_CALL *onNewReverbTime)(void *instance_data, mt32emu_bit8u time); \
|
||||
void (MT32EMU_C_CALL *onNewReverbLevel)(void *instance_data, mt32emu_bit8u level); \
|
||||
/** Callbacks for reporting various information */ \
|
||||
void (MT32EMU_C_CALL *onPolyStateChanged)(void *instance_data, mt32emu_bit8u part_num); \
|
||||
void (MT32EMU_C_CALL *onProgramChanged)(void *instance_data, mt32emu_bit8u part_num, const char *sound_group_name, const char *patch_name);
|
||||
|
||||
#define MT32EMU_REPORT_HANDLER_I_V1 \
|
||||
/**
|
||||
* Invoked to signal about a change of the emulated LCD state. Use mt32emu_get_display_state to retrieve the actual data.
|
||||
* This callback will not be invoked on further changes, until the client retrieves the LCD state.
|
||||
*/ \
|
||||
void (MT32EMU_C_CALL *onLCDStateUpdated)(void *instance_data); \
|
||||
/** Invoked when the emulated MIDI MESSAGE LED changes state. The led_state parameter represents whether the LED is ON. */ \
|
||||
void (MT32EMU_C_CALL *onMidiMessageLEDStateUpdated)(void *instance_data, mt32emu_boolean led_state);
|
||||
|
||||
typedef struct {
|
||||
MT32EMU_REPORT_HANDLER_I_V0
|
||||
} mt32emu_report_handler_i_v0;
|
||||
|
||||
typedef struct {
|
||||
MT32EMU_REPORT_HANDLER_I_V0
|
||||
MT32EMU_REPORT_HANDLER_I_V1
|
||||
} mt32emu_report_handler_i_v1;
|
||||
|
||||
/**
|
||||
* Extensible interface for handling reported events.
|
||||
* Union intended to view an interface of any subsequent version as any parent interface not requiring a cast.
|
||||
@@ -172,8 +204,12 @@ typedef struct {
|
||||
*/
|
||||
union mt32emu_report_handler_i {
|
||||
const mt32emu_report_handler_i_v0 *v0;
|
||||
const mt32emu_report_handler_i_v1 *v1;
|
||||
};
|
||||
|
||||
#undef MT32EMU_REPORT_HANDLER_I_V0
|
||||
#undef MT32EMU_REPORT_HANDLER_I_V1
|
||||
|
||||
/* === MIDI Receiver Interface === */
|
||||
|
||||
typedef union mt32emu_midi_receiver_i mt32emu_midi_receiver_i;
|
||||
@@ -181,16 +217,16 @@ 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);
|
||||
mt32emu_midi_receiver_version (MT32EMU_C_CALL *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);
|
||||
void (MT32EMU_C_CALL *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);
|
||||
void (MT32EMU_C_CALL *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);
|
||||
void (MT32EMU_C_CALL *handleSystemRealtimeMessage)(void *instance_data, const mt32emu_bit8u realtime);
|
||||
} mt32emu_midi_receiver_i_v0;
|
||||
|
||||
/**
|
||||
@@ -215,93 +251,124 @@ typedef union mt32emu_service_i mt32emu_service_i;
|
||||
*/
|
||||
#define MT32EMU_SERVICE_I_V0 \
|
||||
/** 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_service_version (MT32EMU_C_CALL *getVersionID)(mt32emu_service_i i); \
|
||||
mt32emu_report_handler_version (MT32EMU_C_CALL *getSupportedReportHandlerVersionID)(void); \
|
||||
mt32emu_midi_receiver_version (MT32EMU_C_CALL *getSupportedMIDIReceiverVersionID)(void); \
|
||||
\
|
||||
mt32emu_bit32u (*getLibraryVersionInt)(); \
|
||||
const char *(*getLibraryVersionString)(); \
|
||||
mt32emu_bit32u (MT32EMU_C_CALL *getLibraryVersionInt)(void); \
|
||||
const char *(MT32EMU_C_CALL *getLibraryVersionString)(void); \
|
||||
\
|
||||
mt32emu_bit32u (*getStereoOutputSamplerate)(const mt32emu_analog_output_mode analog_output_mode); \
|
||||
mt32emu_bit32u (MT32EMU_C_CALL *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); \
|
||||
mt32emu_context (MT32EMU_C_CALL *createContext)(mt32emu_report_handler_i report_handler, void *instance_data); \
|
||||
void (MT32EMU_C_CALL *freeContext)(mt32emu_context context); \
|
||||
mt32emu_return_code (MT32EMU_C_CALL *addROMData)(mt32emu_context context, const mt32emu_bit8u *data, size_t data_size, const mt32emu_sha1_digest *sha1_digest); \
|
||||
mt32emu_return_code (MT32EMU_C_CALL *addROMFile)(mt32emu_context context, const char *filename); \
|
||||
void (MT32EMU_C_CALL *getROMInfo)(mt32emu_const_context context, mt32emu_rom_info *rom_info); \
|
||||
void (MT32EMU_C_CALL *setPartialCount)(mt32emu_context context, const mt32emu_bit32u partial_count); \
|
||||
void (MT32EMU_C_CALL *setAnalogOutputMode)(mt32emu_context context, const mt32emu_analog_output_mode analog_output_mode); \
|
||||
mt32emu_return_code (MT32EMU_C_CALL *openSynth)(mt32emu_const_context context); \
|
||||
void (MT32EMU_C_CALL *closeSynth)(mt32emu_const_context context); \
|
||||
mt32emu_boolean (MT32EMU_C_CALL *isOpen)(mt32emu_const_context context); \
|
||||
mt32emu_bit32u (MT32EMU_C_CALL *getActualStereoOutputSamplerate)(mt32emu_const_context context); \
|
||||
void (MT32EMU_C_CALL *flushMIDIQueue)(mt32emu_const_context context); \
|
||||
mt32emu_bit32u (MT32EMU_C_CALL *setMIDIEventQueueSize)(mt32emu_const_context context, const mt32emu_bit32u queue_size); \
|
||||
void (MT32EMU_C_CALL *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 (MT32EMU_C_CALL *parseStream)(mt32emu_const_context context, const mt32emu_bit8u *stream, mt32emu_bit32u length); \
|
||||
void (MT32EMU_C_CALL *parseStream_At)(mt32emu_const_context context, const mt32emu_bit8u *stream, mt32emu_bit32u length, mt32emu_bit32u timestamp); \
|
||||
void (MT32EMU_C_CALL *playShortMessage)(mt32emu_const_context context, mt32emu_bit32u message); \
|
||||
void (MT32EMU_C_CALL *playShortMessageAt)(mt32emu_const_context context, mt32emu_bit32u message, mt32emu_bit32u timestamp); \
|
||||
mt32emu_return_code (MT32EMU_C_CALL *playMsg)(mt32emu_const_context context, mt32emu_bit32u msg); \
|
||||
mt32emu_return_code (MT32EMU_C_CALL *playSysex)(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len); \
|
||||
mt32emu_return_code (MT32EMU_C_CALL *playMsgAt)(mt32emu_const_context context, mt32emu_bit32u msg, mt32emu_bit32u timestamp); \
|
||||
mt32emu_return_code (MT32EMU_C_CALL *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 (MT32EMU_C_CALL *playMsgNow)(mt32emu_const_context context, mt32emu_bit32u msg); \
|
||||
void (MT32EMU_C_CALL *playMsgOnPart)(mt32emu_const_context context, mt32emu_bit8u part, mt32emu_bit8u code, mt32emu_bit8u note, mt32emu_bit8u velocity); \
|
||||
void (MT32EMU_C_CALL *playSysexNow)(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len); \
|
||||
void (MT32EMU_C_CALL *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 (MT32EMU_C_CALL *setReverbEnabled)(mt32emu_const_context context, const mt32emu_boolean reverb_enabled); \
|
||||
mt32emu_boolean (MT32EMU_C_CALL *isReverbEnabled)(mt32emu_const_context context); \
|
||||
void (MT32EMU_C_CALL *setReverbOverridden)(mt32emu_const_context context, const mt32emu_boolean reverb_overridden); \
|
||||
mt32emu_boolean (MT32EMU_C_CALL *isReverbOverridden)(mt32emu_const_context context); \
|
||||
void (MT32EMU_C_CALL *setReverbCompatibilityMode)(mt32emu_const_context context, const mt32emu_boolean mt32_compatible_mode); \
|
||||
mt32emu_boolean (MT32EMU_C_CALL *isMT32ReverbCompatibilityMode)(mt32emu_const_context context); \
|
||||
mt32emu_boolean (MT32EMU_C_CALL *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 (MT32EMU_C_CALL *setDACInputMode)(mt32emu_const_context context, const mt32emu_dac_input_mode mode); \
|
||||
mt32emu_dac_input_mode (MT32EMU_C_CALL *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 (MT32EMU_C_CALL *setMIDIDelayMode)(mt32emu_const_context context, const mt32emu_midi_delay_mode mode); \
|
||||
mt32emu_midi_delay_mode (MT32EMU_C_CALL *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 (MT32EMU_C_CALL *setOutputGain)(mt32emu_const_context context, float gain); \
|
||||
float (MT32EMU_C_CALL *getOutputGain)(mt32emu_const_context context); \
|
||||
void (MT32EMU_C_CALL *setReverbOutputGain)(mt32emu_const_context context, float gain); \
|
||||
float (MT32EMU_C_CALL *getReverbOutputGain)(mt32emu_const_context context); \
|
||||
\
|
||||
void (*setReversedStereoEnabled)(mt32emu_const_context context, const mt32emu_boolean enabled); \
|
||||
mt32emu_boolean (*isReversedStereoEnabled)(mt32emu_const_context context); \
|
||||
void (MT32EMU_C_CALL *setReversedStereoEnabled)(mt32emu_const_context context, const mt32emu_boolean enabled); \
|
||||
mt32emu_boolean (MT32EMU_C_CALL *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); \
|
||||
void (MT32EMU_C_CALL *renderBit16s)(mt32emu_const_context context, mt32emu_bit16s *stream, mt32emu_bit32u len); \
|
||||
void (MT32EMU_C_CALL *renderFloat)(mt32emu_const_context context, float *stream, mt32emu_bit32u len); \
|
||||
void (MT32EMU_C_CALL *renderBit16sStreams)(mt32emu_const_context context, const mt32emu_dac_output_bit16s_streams *streams, mt32emu_bit32u len); \
|
||||
void (MT32EMU_C_CALL *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_boolean (MT32EMU_C_CALL *hasActivePartials)(mt32emu_const_context context); \
|
||||
mt32emu_boolean (MT32EMU_C_CALL *isActive)(mt32emu_const_context context); \
|
||||
mt32emu_bit32u (MT32EMU_C_CALL *getPartialCount)(mt32emu_const_context context); \
|
||||
mt32emu_bit32u (MT32EMU_C_CALL *getPartStates)(mt32emu_const_context context); \
|
||||
void (MT32EMU_C_CALL *getPartialStates)(mt32emu_const_context context, mt32emu_bit8u *partial_states); \
|
||||
mt32emu_bit32u (MT32EMU_C_CALL *getPlayingNotes)(mt32emu_const_context context, mt32emu_bit8u part_number, mt32emu_bit8u *keys, mt32emu_bit8u *velocities); \
|
||||
const char *(MT32EMU_C_CALL *getPatchName)(mt32emu_const_context context, mt32emu_bit8u part_number); \
|
||||
void (MT32EMU_C_CALL *readMemory)(mt32emu_const_context context, mt32emu_bit32u addr, mt32emu_bit32u len, mt32emu_bit8u *data);
|
||||
|
||||
#define MT32EMU_SERVICE_I_V1 \
|
||||
mt32emu_analog_output_mode (*getBestAnalogOutputMode)(const double target_samplerate); \
|
||||
void (*setStereoOutputSampleRate)(mt32emu_context context, const double samplerate); \
|
||||
void (*setSamplerateConversionQuality)(mt32emu_context context, const mt32emu_samplerate_conversion_quality quality); \
|
||||
void (*selectRendererType)(mt32emu_context context, mt32emu_renderer_type renderer_type); \
|
||||
mt32emu_renderer_type (*getSelectedRendererType)(mt32emu_context context); \
|
||||
mt32emu_bit32u (*convertOutputToSynthTimestamp)(mt32emu_const_context context, mt32emu_bit32u output_timestamp); \
|
||||
mt32emu_bit32u (*convertSynthToOutputTimestamp)(mt32emu_const_context context, mt32emu_bit32u synth_timestamp);
|
||||
mt32emu_analog_output_mode (MT32EMU_C_CALL *getBestAnalogOutputMode)(const double target_samplerate); \
|
||||
void (MT32EMU_C_CALL *setStereoOutputSampleRate)(mt32emu_context context, const double samplerate); \
|
||||
void (MT32EMU_C_CALL *setSamplerateConversionQuality)(mt32emu_context context, const mt32emu_samplerate_conversion_quality quality); \
|
||||
void (MT32EMU_C_CALL *selectRendererType)(mt32emu_context context, mt32emu_renderer_type renderer_type); \
|
||||
mt32emu_renderer_type (MT32EMU_C_CALL *getSelectedRendererType)(mt32emu_context context); \
|
||||
mt32emu_bit32u (MT32EMU_C_CALL *convertOutputToSynthTimestamp)(mt32emu_const_context context, mt32emu_bit32u output_timestamp); \
|
||||
mt32emu_bit32u (MT32EMU_C_CALL *convertSynthToOutputTimestamp)(mt32emu_const_context context, mt32emu_bit32u synth_timestamp);
|
||||
|
||||
#define MT32EMU_SERVICE_I_V2 \
|
||||
mt32emu_bit32u (*getInternalRenderedSampleCount)(mt32emu_const_context context); \
|
||||
void (*setNiceAmpRampEnabled)(mt32emu_const_context context, const mt32emu_boolean enabled); \
|
||||
mt32emu_boolean (*isNiceAmpRampEnabled)(mt32emu_const_context context);
|
||||
mt32emu_bit32u (MT32EMU_C_CALL *getInternalRenderedSampleCount)(mt32emu_const_context context); \
|
||||
void (MT32EMU_C_CALL *setNiceAmpRampEnabled)(mt32emu_const_context context, const mt32emu_boolean enabled); \
|
||||
mt32emu_boolean (MT32EMU_C_CALL *isNiceAmpRampEnabled)(mt32emu_const_context context);
|
||||
|
||||
#define MT32EMU_SERVICE_I_V3 \
|
||||
void (MT32EMU_C_CALL *setNicePanningEnabled)(mt32emu_const_context context, const mt32emu_boolean enabled); \
|
||||
mt32emu_boolean (MT32EMU_C_CALL *isNicePanningEnabled)(mt32emu_const_context context); \
|
||||
void (MT32EMU_C_CALL *setNicePartialMixingEnabled)(mt32emu_const_context context, const mt32emu_boolean enabled); \
|
||||
mt32emu_boolean (MT32EMU_C_CALL *isNicePartialMixingEnabled)(mt32emu_const_context context); \
|
||||
void (MT32EMU_C_CALL *preallocateReverbMemory)(mt32emu_const_context context, const mt32emu_boolean enabled); \
|
||||
void (MT32EMU_C_CALL *configureMIDIEventQueueSysexStorage)(mt32emu_const_context context, const mt32emu_bit32u storage_buffer_size);
|
||||
|
||||
#define MT32EMU_SERVICE_I_V4 \
|
||||
size_t (MT32EMU_C_CALL *getMachineIDs)(const char **machine_ids, size_t machine_ids_size); \
|
||||
size_t (MT32EMU_C_CALL *getROMIDs)(const char **rom_ids, size_t rom_ids_size, const char *machine_id); \
|
||||
mt32emu_return_code (MT32EMU_C_CALL *identifyROMData)(mt32emu_rom_info *rom_info, const mt32emu_bit8u *data, size_t data_size, const char *machine_id); \
|
||||
mt32emu_return_code (MT32EMU_C_CALL *identifyROMFile)(mt32emu_rom_info *rom_info, const char *filename, const char *machine_id); \
|
||||
\
|
||||
mt32emu_return_code (MT32EMU_C_CALL *mergeAndAddROMData)(mt32emu_context context, const mt32emu_bit8u *part1_data, size_t part1_data_size, const mt32emu_sha1_digest *part1_sha1_digest, const mt32emu_bit8u *part2_data, size_t part2_data_size, const mt32emu_sha1_digest *part2_sha1_digest); \
|
||||
mt32emu_return_code (MT32EMU_C_CALL *mergeAndAddROMFiles)(mt32emu_context context, const char *part1_filename, const char *part2_filename); \
|
||||
mt32emu_return_code (MT32EMU_C_CALL *addMachineROMFile)(mt32emu_context context, const char *machine_id, const char *filename);
|
||||
|
||||
#define MT32EMU_SERVICE_I_V5 \
|
||||
mt32emu_boolean (MT32EMU_C_CALL *getDisplayState)(mt32emu_const_context context, char *target_buffer, const mt32emu_boolean narrow_lcd); \
|
||||
void (MT32EMU_C_CALL *setMainDisplayMode)(mt32emu_const_context context); \
|
||||
void (MT32EMU_C_CALL *setDisplayCompatibility)(mt32emu_const_context context, mt32emu_boolean old_mt32_compatibility_enabled); \
|
||||
mt32emu_boolean (MT32EMU_C_CALL *isDisplayOldMT32Compatible)(mt32emu_const_context context); \
|
||||
mt32emu_boolean (MT32EMU_C_CALL *isDefaultDisplayOldMT32Compatible)(mt32emu_const_context context); \
|
||||
void (MT32EMU_C_CALL *setPartVolumeOverride)(mt32emu_const_context context, mt32emu_bit8u part_number, mt32emu_bit8u volume_override); \
|
||||
mt32emu_bit8u (MT32EMU_C_CALL *getPartVolumeOverride)(mt32emu_const_context context, mt32emu_bit8u part_number);
|
||||
|
||||
#define MT32EMU_SERVICE_I_V6 \
|
||||
mt32emu_boolean (MT32EMU_C_CALL *getSoundGroupName)(mt32emu_const_context context, char *sound_group_name, mt32emu_bit8u timbre_group, mt32emu_bit8u timbre_number); \
|
||||
mt32emu_boolean (MT32EMU_C_CALL *getSoundName)(mt32emu_const_context context, char *sound_name, mt32emu_bit8u timbre_group, mt32emu_bit8u timbre_number);
|
||||
|
||||
typedef struct {
|
||||
MT32EMU_SERVICE_I_V0
|
||||
@@ -318,6 +385,40 @@ typedef struct {
|
||||
MT32EMU_SERVICE_I_V2
|
||||
} mt32emu_service_i_v2;
|
||||
|
||||
typedef struct {
|
||||
MT32EMU_SERVICE_I_V0
|
||||
MT32EMU_SERVICE_I_V1
|
||||
MT32EMU_SERVICE_I_V2
|
||||
MT32EMU_SERVICE_I_V3
|
||||
} mt32emu_service_i_v3;
|
||||
|
||||
typedef struct {
|
||||
MT32EMU_SERVICE_I_V0
|
||||
MT32EMU_SERVICE_I_V1
|
||||
MT32EMU_SERVICE_I_V2
|
||||
MT32EMU_SERVICE_I_V3
|
||||
MT32EMU_SERVICE_I_V4
|
||||
} mt32emu_service_i_v4;
|
||||
|
||||
typedef struct {
|
||||
MT32EMU_SERVICE_I_V0
|
||||
MT32EMU_SERVICE_I_V1
|
||||
MT32EMU_SERVICE_I_V2
|
||||
MT32EMU_SERVICE_I_V3
|
||||
MT32EMU_SERVICE_I_V4
|
||||
MT32EMU_SERVICE_I_V5
|
||||
} mt32emu_service_i_v5;
|
||||
|
||||
typedef struct {
|
||||
MT32EMU_SERVICE_I_V0
|
||||
MT32EMU_SERVICE_I_V1
|
||||
MT32EMU_SERVICE_I_V2
|
||||
MT32EMU_SERVICE_I_V3
|
||||
MT32EMU_SERVICE_I_V4
|
||||
MT32EMU_SERVICE_I_V5
|
||||
MT32EMU_SERVICE_I_V6
|
||||
} mt32emu_service_i_v6;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
@@ -327,10 +428,18 @@ union mt32emu_service_i {
|
||||
const mt32emu_service_i_v0 *v0;
|
||||
const mt32emu_service_i_v1 *v1;
|
||||
const mt32emu_service_i_v2 *v2;
|
||||
const mt32emu_service_i_v3 *v3;
|
||||
const mt32emu_service_i_v4 *v4;
|
||||
const mt32emu_service_i_v5 *v5;
|
||||
const mt32emu_service_i_v6 *v6;
|
||||
};
|
||||
|
||||
#undef MT32EMU_SERVICE_I_V0
|
||||
#undef MT32EMU_SERVICE_I_V1
|
||||
#undef MT32EMU_SERVICE_I_V2
|
||||
#undef MT32EMU_SERVICE_I_V3
|
||||
#undef MT32EMU_SERVICE_I_V4
|
||||
#undef MT32EMU_SERVICE_I_V5
|
||||
#undef MT32EMU_SERVICE_I_V6
|
||||
|
||||
#endif /* #ifndef MT32EMU_C_TYPES_H */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
@@ -41,10 +41,17 @@ mt32emu_service_i mt32emu_get_service_i();
|
||||
#define mt32emu_get_library_version_string i.v0->getLibraryVersionString
|
||||
#define mt32emu_get_stereo_output_samplerate i.v0->getStereoOutputSamplerate
|
||||
#define mt32emu_get_best_analog_output_mode iV1()->getBestAnalogOutputMode
|
||||
#define mt32emu_get_machine_ids iV4()->getMachineIDs
|
||||
#define mt32emu_get_rom_ids iV4()->getROMIDs
|
||||
#define mt32emu_identify_rom_data iV4()->identifyROMData
|
||||
#define mt32emu_identify_rom_file iV4()->identifyROMFile
|
||||
#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_merge_and_add_rom_data iV4()->mergeAndAddROMData
|
||||
#define mt32emu_merge_and_add_rom_files iV4()->mergeAndAddROMFiles
|
||||
#define mt32emu_add_machine_rom_file iV4()->addMachineROMFile
|
||||
#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
|
||||
@@ -60,6 +67,7 @@ mt32emu_service_i mt32emu_get_service_i();
|
||||
#define mt32emu_convert_synth_to_output_timestamp iV1()->convertSynthToOutputTimestamp
|
||||
#define mt32emu_flush_midi_queue i.v0->flushMIDIQueue
|
||||
#define mt32emu_set_midi_event_queue_size i.v0->setMIDIEventQueueSize
|
||||
#define mt32emu_configure_midi_event_queue_sysex_storage iV3()->configureMIDIEventQueueSysexStorage
|
||||
#define mt32emu_set_midi_receiver i.v0->setMIDIReceiver
|
||||
#define mt32emu_get_internal_rendered_sample_count iV2()->getInternalRenderedSampleCount
|
||||
#define mt32emu_parse_stream i.v0->parseStream
|
||||
@@ -81,6 +89,7 @@ mt32emu_service_i mt32emu_get_service_i();
|
||||
#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_preallocate_reverb_memory iV3()->preallocateReverbMemory
|
||||
#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
|
||||
@@ -89,10 +98,16 @@ mt32emu_service_i mt32emu_get_service_i();
|
||||
#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_part_volume_override iV5()->setPartVolumeOverride
|
||||
#define mt32emu_get_part_volume_override iV5()->getPartVolumeOverride
|
||||
#define mt32emu_set_reversed_stereo_enabled i.v0->setReversedStereoEnabled
|
||||
#define mt32emu_is_reversed_stereo_enabled i.v0->isReversedStereoEnabled
|
||||
#define mt32emu_set_nice_amp_ramp_enabled iV2()->setNiceAmpRampEnabled
|
||||
#define mt32emu_is_nice_amp_ramp_enabled iV2()->isNiceAmpRampEnabled
|
||||
#define mt32emu_set_nice_panning_enabled iV3()->setNicePanningEnabled
|
||||
#define mt32emu_is_nice_panning_enabled iV3()->isNicePanningEnabled
|
||||
#define mt32emu_set_nice_partial_mixing_enabled iV3()->setNicePartialMixingEnabled
|
||||
#define mt32emu_is_nice_partial_mixing_enabled iV3()->isNicePartialMixingEnabled
|
||||
#define mt32emu_render_bit16s i.v0->renderBit16s
|
||||
#define mt32emu_render_float i.v0->renderFloat
|
||||
#define mt32emu_render_bit16s_streams i.v0->renderBit16sStreams
|
||||
@@ -104,7 +119,14 @@ mt32emu_service_i mt32emu_get_service_i();
|
||||
#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_get_sound_group_name iV6()->getSoundGroupName
|
||||
#define mt32emu_get_sound_name iV6()->getSoundName
|
||||
#define mt32emu_read_memory i.v0->readMemory
|
||||
#define mt32emu_get_display_state iV5()->getDisplayState
|
||||
#define mt32emu_set_main_display_mode iV5()->setMainDisplayMode
|
||||
#define mt32emu_set_display_compatibility iV5()->setDisplayCompatibility
|
||||
#define mt32emu_is_display_old_mt32_compatible iV5()->isDisplayOldMT32Compatible
|
||||
#define mt32emu_is_default_display_old_mt32_compatible iV5()->isDefaultDisplayOldMT32Compatible
|
||||
|
||||
#else // #if MT32EMU_API_TYPE == 2
|
||||
|
||||
@@ -117,7 +139,7 @@ namespace MT32Emu {
|
||||
namespace CppInterfaceImpl {
|
||||
|
||||
static const mt32emu_report_handler_i NULL_REPORT_HANDLER = { NULL };
|
||||
static mt32emu_report_handler_i getReportHandlerThunk();
|
||||
static mt32emu_report_handler_i getReportHandlerThunk(mt32emu_report_handler_version);
|
||||
static mt32emu_midi_receiver_i getMidiReceiverThunk();
|
||||
|
||||
}
|
||||
@@ -130,8 +152,8 @@ static mt32emu_midi_receiver_i getMidiReceiverThunk();
|
||||
* 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.
|
||||
// Defines the interface for handling reported events (initial version).
|
||||
// Corresponds to the mt32emu_report_handler_i_v0 interface.
|
||||
class IReportHandler {
|
||||
public:
|
||||
virtual void printDebug(const char *fmt, va_list list) = 0;
|
||||
@@ -153,6 +175,17 @@ protected:
|
||||
~IReportHandler() {}
|
||||
};
|
||||
|
||||
// Extends IReportHandler, so that the client may supply callbacks for reporting signals about updated display state.
|
||||
// Corresponds to the mt32emu_report_handler_i_v1 interface.
|
||||
class IReportHandlerV1 : public IReportHandler {
|
||||
public:
|
||||
virtual void onLCDStateUpdated() = 0;
|
||||
virtual void onMidiMessageLEDStateUpdated(bool ledState) = 0;
|
||||
|
||||
protected:
|
||||
~IReportHandlerV1() {}
|
||||
};
|
||||
|
||||
// Defines the interface for receiving MIDI messages generated by MIDI stream parser.
|
||||
// Corresponds to the current version of mt32emu_midi_receiver_i interface.
|
||||
class IMidiReceiver {
|
||||
@@ -190,14 +223,24 @@ public:
|
||||
Bit32u getStereoOutputSamplerate(const AnalogOutputMode analog_output_mode) { return mt32emu_get_stereo_output_samplerate(static_cast<mt32emu_analog_output_mode>(analog_output_mode)); }
|
||||
AnalogOutputMode getBestAnalogOutputMode(const double target_samplerate) { return static_cast<AnalogOutputMode>(mt32emu_get_best_analog_output_mode(target_samplerate)); }
|
||||
|
||||
size_t getMachineIDs(const char **machine_ids, size_t machine_ids_size) { return mt32emu_get_machine_ids(machine_ids, machine_ids_size); }
|
||||
size_t getROMIDs(const char **rom_ids, size_t rom_ids_size, const char *machine_id) { return mt32emu_get_rom_ids(rom_ids, rom_ids_size, machine_id); }
|
||||
mt32emu_return_code identifyROMData(mt32emu_rom_info *rom_info, const Bit8u *data, size_t data_size, const char *machine_id) { return mt32emu_identify_rom_data(rom_info, data, data_size, machine_id); }
|
||||
mt32emu_return_code identifyROMFile(mt32emu_rom_info *rom_info, const char *filename, const char *machine_id) { return mt32emu_identify_rom_file(rom_info, filename, machine_id); }
|
||||
|
||||
// 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(IReportHandler &report_handler) { createContext(CppInterfaceImpl::getReportHandlerThunk(), &report_handler); }
|
||||
void createContext(IReportHandler &report_handler) { createContext(CppInterfaceImpl::getReportHandlerThunk(MT32EMU_REPORT_HANDLER_VERSION_0), &report_handler); }
|
||||
void createContext(IReportHandlerV1 &report_handler) { createContext(CppInterfaceImpl::getReportHandlerThunk(MT32EMU_REPORT_HANDLER_VERSION_1), &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); }
|
||||
mt32emu_return_code mergeAndAddROMData(const Bit8u *part1_data, size_t part1_data_size, const Bit8u *part2_data, size_t part2_data_size) { return mt32emu_merge_and_add_rom_data(c, part1_data, part1_data_size, NULL, part2_data, part2_data_size, NULL); }
|
||||
mt32emu_return_code mergeAndAddROMData(const Bit8u *part1_data, size_t part1_data_size, const mt32emu_sha1_digest *part1_sha1_digest, const Bit8u *part2_data, size_t part2_data_size, const mt32emu_sha1_digest *part2_sha1_digest) { return mt32emu_merge_and_add_rom_data(c, part1_data, part1_data_size, part1_sha1_digest, part2_data, part2_data_size, part2_sha1_digest); }
|
||||
mt32emu_return_code mergeAndAddROMFiles(const char *part1_filename, const char *part2_filename) { return mt32emu_merge_and_add_rom_files(c, part1_filename, part2_filename); }
|
||||
mt32emu_return_code addMachineROMFile(const char *machine_id, const char *filename) { return mt32emu_add_machine_rom_file(c, machine_id, 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)); }
|
||||
@@ -213,6 +256,7 @@ public:
|
||||
Bit32u convertSynthToOutputTimestamp(Bit32u synth_timestamp) { return mt32emu_convert_synth_to_output_timestamp(c, synth_timestamp); }
|
||||
void flushMIDIQueue() { mt32emu_flush_midi_queue(c); }
|
||||
Bit32u setMIDIEventQueueSize(const Bit32u queue_size) { return mt32emu_set_midi_event_queue_size(c, queue_size); }
|
||||
void configureMIDIEventQueueSysexStorage(const Bit32u storage_buffer_size) { mt32emu_configure_midi_event_queue_sysex_storage(c, storage_buffer_size); }
|
||||
void setMIDIReceiver(mt32emu_midi_receiver_i midi_receiver, void *instance_data) { mt32emu_set_midi_receiver(c, midi_receiver, instance_data); }
|
||||
void setMIDIReceiver(IMidiReceiver &midi_receiver) { setMIDIReceiver(CppInterfaceImpl::getMidiReceiverThunk(), &midi_receiver); }
|
||||
|
||||
@@ -238,6 +282,7 @@ public:
|
||||
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 preallocateReverbMemory(const bool enabled) { mt32emu_preallocate_reverb_memory(c, enabled ? MT32EMU_BOOL_TRUE : 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)); }
|
||||
@@ -250,12 +295,21 @@ public:
|
||||
void setReverbOutputGain(float gain) { mt32emu_set_reverb_output_gain(c, gain); }
|
||||
float getReverbOutputGain() { return mt32emu_get_reverb_output_gain(c); }
|
||||
|
||||
void setPartVolumeOverride(Bit8u part_number, Bit8u volume_override) { mt32emu_set_part_volume_override(c, part_number, volume_override); }
|
||||
Bit8u getPartVolumeOverride(Bit8u part_number) { return mt32emu_get_part_volume_override(c, part_number); }
|
||||
|
||||
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 setNiceAmpRampEnabled(const bool enabled) { mt32emu_set_nice_amp_ramp_enabled(c, enabled ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE); }
|
||||
bool isNiceAmpRampEnabled() { return mt32emu_is_nice_amp_ramp_enabled(c) != MT32EMU_BOOL_FALSE; }
|
||||
|
||||
void setNicePanningEnabled(const bool enabled) { mt32emu_set_nice_panning_enabled(c, enabled ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE); }
|
||||
bool isNicePanningEnabled() { return mt32emu_is_nice_panning_enabled(c) != MT32EMU_BOOL_FALSE; }
|
||||
|
||||
void setNicePartialMixingEnabled(const bool enabled) { mt32emu_set_nice_partial_mixing_enabled(c, enabled ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE); }
|
||||
bool isNicePartialMixingEnabled() { return mt32emu_is_nice_partial_mixing_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); }
|
||||
@@ -268,8 +322,17 @@ public:
|
||||
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); }
|
||||
bool getSoundGroupName(char *soundGroupName, Bit8u timbreGroup, Bit8u timbreNumber) { return mt32emu_get_sound_group_name(c, soundGroupName, timbreGroup, timbreNumber) != MT32EMU_BOOL_FALSE; }
|
||||
bool getSoundName(char *soundName, Bit8u timbreGroup, Bit8u timbreNumber) { return mt32emu_get_sound_name(c, soundName, timbreGroup, timbreNumber) != MT32EMU_BOOL_FALSE; }
|
||||
void readMemory(Bit32u addr, Bit32u len, Bit8u *data) { mt32emu_read_memory(c, addr, len, data); }
|
||||
|
||||
bool getDisplayState(char *target_buffer, const bool narrow_lcd) { return mt32emu_get_display_state(c, target_buffer, narrow_lcd ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE) != MT32EMU_BOOL_FALSE; }
|
||||
void setMainDisplayMode() { mt32emu_set_main_display_mode(c); }
|
||||
|
||||
void setDisplayCompatibility(const bool oldMT32CompatibilityEnabled) { mt32emu_set_display_compatibility(c, oldMT32CompatibilityEnabled ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE); }
|
||||
bool isDisplayOldMT32Compatible() { return mt32emu_is_display_old_mt32_compatible(c) != MT32EMU_BOOL_FALSE; }
|
||||
bool isDefaultDisplayOldMT32Compatible() { return mt32emu_is_default_display_old_mt32_compatible(c) != MT32EMU_BOOL_FALSE; }
|
||||
|
||||
private:
|
||||
#if MT32EMU_API_TYPE == 2
|
||||
const mt32emu_service_i i;
|
||||
@@ -279,108 +342,138 @@ private:
|
||||
#if MT32EMU_API_TYPE == 2
|
||||
const mt32emu_service_i_v1 *iV1() { return (getVersionID() < MT32EMU_SERVICE_VERSION_1) ? NULL : i.v1; }
|
||||
const mt32emu_service_i_v2 *iV2() { return (getVersionID() < MT32EMU_SERVICE_VERSION_2) ? NULL : i.v2; }
|
||||
const mt32emu_service_i_v3 *iV3() { return (getVersionID() < MT32EMU_SERVICE_VERSION_3) ? NULL : i.v3; }
|
||||
const mt32emu_service_i_v4 *iV4() { return (getVersionID() < MT32EMU_SERVICE_VERSION_4) ? NULL : i.v4; }
|
||||
const mt32emu_service_i_v5 *iV5() { return (getVersionID() < MT32EMU_SERVICE_VERSION_5) ? NULL : i.v5; }
|
||||
const mt32emu_service_i_v6 *iV6() { return (getVersionID() < MT32EMU_SERVICE_VERSION_6) ? NULL : i.v6; }
|
||||
#endif
|
||||
|
||||
Service(const Service &); // prevent copy-construction
|
||||
Service& operator=(const Service &); // prevent assignment
|
||||
};
|
||||
|
||||
namespace CppInterfaceImpl {
|
||||
|
||||
static mt32emu_report_handler_version getReportHandlerVersionID(mt32emu_report_handler_i) {
|
||||
return MT32EMU_REPORT_HANDLER_VERSION_CURRENT;
|
||||
}
|
||||
static mt32emu_report_handler_version MT32EMU_C_CALL getReportHandlerVersionID(mt32emu_report_handler_i);
|
||||
|
||||
static void printDebug(void *instance_data, const char *fmt, va_list list) {
|
||||
static void MT32EMU_C_CALL printDebug(void *instance_data, const char *fmt, va_list list) {
|
||||
static_cast<IReportHandler *>(instance_data)->printDebug(fmt, list);
|
||||
}
|
||||
|
||||
static void onErrorControlROM(void *instance_data) {
|
||||
static void MT32EMU_C_CALL onErrorControlROM(void *instance_data) {
|
||||
static_cast<IReportHandler *>(instance_data)->onErrorControlROM();
|
||||
}
|
||||
|
||||
static void onErrorPCMROM(void *instance_data) {
|
||||
static void MT32EMU_C_CALL onErrorPCMROM(void *instance_data) {
|
||||
static_cast<IReportHandler *>(instance_data)->onErrorPCMROM();
|
||||
}
|
||||
|
||||
static void showLCDMessage(void *instance_data, const char *message) {
|
||||
static void MT32EMU_C_CALL showLCDMessage(void *instance_data, const char *message) {
|
||||
static_cast<IReportHandler *>(instance_data)->showLCDMessage(message);
|
||||
}
|
||||
|
||||
static void onMIDIMessagePlayed(void *instance_data) {
|
||||
static void MT32EMU_C_CALL onMIDIMessagePlayed(void *instance_data) {
|
||||
static_cast<IReportHandler *>(instance_data)->onMIDIMessagePlayed();
|
||||
}
|
||||
|
||||
static mt32emu_boolean onMIDIQueueOverflow(void *instance_data) {
|
||||
static mt32emu_boolean MT32EMU_C_CALL onMIDIQueueOverflow(void *instance_data) {
|
||||
return static_cast<IReportHandler *>(instance_data)->onMIDIQueueOverflow() ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE;
|
||||
}
|
||||
|
||||
static void onMIDISystemRealtime(void *instance_data, mt32emu_bit8u system_realtime) {
|
||||
static void MT32EMU_C_CALL onMIDISystemRealtime(void *instance_data, mt32emu_bit8u system_realtime) {
|
||||
static_cast<IReportHandler *>(instance_data)->onMIDISystemRealtime(system_realtime);
|
||||
}
|
||||
|
||||
static void onDeviceReset(void *instance_data) {
|
||||
static void MT32EMU_C_CALL onDeviceReset(void *instance_data) {
|
||||
static_cast<IReportHandler *>(instance_data)->onDeviceReset();
|
||||
}
|
||||
|
||||
static void onDeviceReconfig(void *instance_data) {
|
||||
static void MT32EMU_C_CALL onDeviceReconfig(void *instance_data) {
|
||||
static_cast<IReportHandler *>(instance_data)->onDeviceReconfig();
|
||||
}
|
||||
|
||||
static void onNewReverbMode(void *instance_data, mt32emu_bit8u mode) {
|
||||
static void MT32EMU_C_CALL onNewReverbMode(void *instance_data, mt32emu_bit8u mode) {
|
||||
static_cast<IReportHandler *>(instance_data)->onNewReverbMode(mode);
|
||||
}
|
||||
|
||||
static void onNewReverbTime(void *instance_data, mt32emu_bit8u time) {
|
||||
static void MT32EMU_C_CALL onNewReverbTime(void *instance_data, mt32emu_bit8u time) {
|
||||
static_cast<IReportHandler *>(instance_data)->onNewReverbTime(time);
|
||||
}
|
||||
|
||||
static void onNewReverbLevel(void *instance_data, mt32emu_bit8u level) {
|
||||
static void MT32EMU_C_CALL onNewReverbLevel(void *instance_data, mt32emu_bit8u level) {
|
||||
static_cast<IReportHandler *>(instance_data)->onNewReverbLevel(level);
|
||||
}
|
||||
|
||||
static void onPolyStateChanged(void *instance_data, mt32emu_bit8u part_num) {
|
||||
static void MT32EMU_C_CALL onPolyStateChanged(void *instance_data, mt32emu_bit8u part_num) {
|
||||
static_cast<IReportHandler *>(instance_data)->onPolyStateChanged(part_num);
|
||||
}
|
||||
|
||||
static void onProgramChanged(void *instance_data, mt32emu_bit8u part_num, const char *sound_group_name, const char *patch_name) {
|
||||
static void MT32EMU_C_CALL onProgramChanged(void *instance_data, mt32emu_bit8u part_num, const char *sound_group_name, const char *patch_name) {
|
||||
static_cast<IReportHandler *>(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 void MT32EMU_C_CALL onLCDStateUpdated(void *instance_data) {
|
||||
static_cast<IReportHandlerV1 *>(instance_data)->onLCDStateUpdated();
|
||||
}
|
||||
|
||||
static mt32emu_midi_receiver_version getMidiReceiverVersionID(mt32emu_midi_receiver_i) {
|
||||
static void MT32EMU_C_CALL onMidiMessageLEDStateUpdated(void *instance_data, mt32emu_boolean led_state) {
|
||||
static_cast<IReportHandlerV1 *>(instance_data)->onMidiMessageLEDStateUpdated(led_state != MT32EMU_BOOL_FALSE);
|
||||
}
|
||||
|
||||
#define MT32EMU_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_v0 REPORT_HANDLER_V0_THUNK = {
|
||||
MT32EMU_REPORT_HANDLER_V0_THUNK
|
||||
};
|
||||
|
||||
static const mt32emu_report_handler_i_v1 REPORT_HANDLER_V1_THUNK = {
|
||||
MT32EMU_REPORT_HANDLER_V0_THUNK,
|
||||
onLCDStateUpdated,
|
||||
onMidiMessageLEDStateUpdated
|
||||
};
|
||||
|
||||
#undef MT32EMU_REPORT_HANDLER_THUNK_V0
|
||||
|
||||
static mt32emu_report_handler_version MT32EMU_C_CALL getReportHandlerVersionID(mt32emu_report_handler_i thunk) {
|
||||
if (thunk.v0 == &REPORT_HANDLER_V0_THUNK) return MT32EMU_REPORT_HANDLER_VERSION_0;
|
||||
return MT32EMU_REPORT_HANDLER_VERSION_CURRENT;
|
||||
}
|
||||
|
||||
static mt32emu_report_handler_i getReportHandlerThunk(mt32emu_report_handler_version versionID) {
|
||||
mt32emu_report_handler_i thunk;
|
||||
if (versionID == MT32EMU_REPORT_HANDLER_VERSION_0) thunk.v0 = &REPORT_HANDLER_V0_THUNK;
|
||||
else thunk.v1 = &REPORT_HANDLER_V1_THUNK;
|
||||
return thunk;
|
||||
}
|
||||
|
||||
static mt32emu_midi_receiver_version MT32EMU_C_CALL getMidiReceiverVersionID(mt32emu_midi_receiver_i) {
|
||||
return MT32EMU_MIDI_RECEIVER_VERSION_CURRENT;
|
||||
}
|
||||
|
||||
static void handleShortMessage(void *instance_data, const mt32emu_bit32u message) {
|
||||
static void MT32EMU_C_CALL handleShortMessage(void *instance_data, const mt32emu_bit32u message) {
|
||||
static_cast<IMidiReceiver *>(instance_data)->handleShortMessage(message);
|
||||
}
|
||||
|
||||
static void handleSysex(void *instance_data, const mt32emu_bit8u stream[], const mt32emu_bit32u length) {
|
||||
static void MT32EMU_C_CALL handleSysex(void *instance_data, const mt32emu_bit8u stream[], const mt32emu_bit32u length) {
|
||||
static_cast<IMidiReceiver *>(instance_data)->handleSysex(stream, length);
|
||||
}
|
||||
|
||||
static void handleSystemRealtimeMessage(void *instance_data, const mt32emu_bit8u realtime) {
|
||||
static void MT32EMU_C_CALL handleSystemRealtimeMessage(void *instance_data, const mt32emu_bit8u realtime) {
|
||||
static_cast<IMidiReceiver *>(instance_data)->handleSystemRealtimeMessage(realtime);
|
||||
}
|
||||
|
||||
@@ -409,10 +502,17 @@ static mt32emu_midi_receiver_i getMidiReceiverThunk() {
|
||||
#undef mt32emu_get_library_version_string
|
||||
#undef mt32emu_get_stereo_output_samplerate
|
||||
#undef mt32emu_get_best_analog_output_mode
|
||||
#undef mt32emu_get_machine_ids
|
||||
#undef mt32emu_get_rom_ids
|
||||
#undef mt32emu_identify_rom_data
|
||||
#undef mt32emu_identify_rom_file
|
||||
#undef mt32emu_create_context
|
||||
#undef mt32emu_free_context
|
||||
#undef mt32emu_add_rom_data
|
||||
#undef mt32emu_add_rom_file
|
||||
#undef mt32emu_merge_and_add_rom_data
|
||||
#undef mt32emu_merge_and_add_rom_files
|
||||
#undef mt32emu_add_machine_rom_file
|
||||
#undef mt32emu_get_rom_info
|
||||
#undef mt32emu_set_partial_count
|
||||
#undef mt32emu_set_analog_output_mode
|
||||
@@ -428,6 +528,7 @@ static mt32emu_midi_receiver_i getMidiReceiverThunk() {
|
||||
#undef mt32emu_convert_synth_to_output_timestamp
|
||||
#undef mt32emu_flush_midi_queue
|
||||
#undef mt32emu_set_midi_event_queue_size
|
||||
#undef mt32emu_configure_midi_event_queue_sysex_storage
|
||||
#undef mt32emu_set_midi_receiver
|
||||
#undef mt32emu_get_internal_rendered_sample_count
|
||||
#undef mt32emu_parse_stream
|
||||
@@ -449,6 +550,7 @@ static mt32emu_midi_receiver_i getMidiReceiverThunk() {
|
||||
#undef mt32emu_set_reverb_compatibility_mode
|
||||
#undef mt32emu_is_mt32_reverb_compatibility_mode
|
||||
#undef mt32emu_is_default_reverb_mt32_compatible
|
||||
#undef mt32emu_preallocate_reverb_memory
|
||||
#undef mt32emu_set_dac_input_mode
|
||||
#undef mt32emu_get_dac_input_mode
|
||||
#undef mt32emu_set_midi_delay_mode
|
||||
@@ -461,6 +563,10 @@ static mt32emu_midi_receiver_i getMidiReceiverThunk() {
|
||||
#undef mt32emu_is_reversed_stereo_enabled
|
||||
#undef mt32emu_set_nice_amp_ramp_enabled
|
||||
#undef mt32emu_is_nice_amp_ramp_enabled
|
||||
#undef mt32emu_set_nice_panning_enabled
|
||||
#undef mt32emu_is_nice_panning_enabled
|
||||
#undef mt32emu_set_nice_partial_mixing_enabled
|
||||
#undef mt32emu_is_nice_partial_mixing_enabled
|
||||
#undef mt32emu_render_bit16s
|
||||
#undef mt32emu_render_float
|
||||
#undef mt32emu_render_bit16s_streams
|
||||
@@ -472,7 +578,14 @@ static mt32emu_midi_receiver_i getMidiReceiverThunk() {
|
||||
#undef mt32emu_get_partial_states
|
||||
#undef mt32emu_get_playing_notes
|
||||
#undef mt32emu_get_patch_name
|
||||
#undef mt32emu_get_sound_group_name
|
||||
#undef mt32emu_get_sound_name
|
||||
#undef mt32emu_read_memory
|
||||
#undef mt32emu_get_display_state
|
||||
#undef mt32emu_set_main_display_mode
|
||||
#undef mt32emu_set_display_compatibility
|
||||
#undef mt32emu_is_display_old_mt32_compatible
|
||||
#undef mt32emu_is_default_display_old_mt32_compatible
|
||||
|
||||
#endif // #if MT32EMU_API_TYPE == 2
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
@@ -18,9 +18,9 @@
|
||||
#ifndef MT32EMU_CONFIG_H
|
||||
#define MT32EMU_CONFIG_H
|
||||
|
||||
#define MT32EMU_VERSION "2.2.0"
|
||||
#define MT32EMU_VERSION "2.7.0"
|
||||
#define MT32EMU_VERSION_MAJOR 2
|
||||
#define MT32EMU_VERSION_MINOR 2
|
||||
#define MT32EMU_VERSION_MINOR 7
|
||||
#define MT32EMU_VERSION_PATCH 0
|
||||
|
||||
/* Library Exports Configuration
|
||||
@@ -37,4 +37,9 @@
|
||||
|
||||
#define MT32EMU_API_TYPE 0
|
||||
|
||||
#define MT32EMU_WITH_LIBSOXR_RESAMPLER 0
|
||||
#define MT32EMU_WITH_LIBSAMPLERATE_RESAMPLER 0
|
||||
#define MT32EMU_WITH_INTERNAL_RESAMPLER 1
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
@@ -20,27 +20,35 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
/* Support for compiling shared library. */
|
||||
/* Support for compiling shared library.
|
||||
* MT32EMU_SHARED and mt32emu_EXPORTS are defined when building a shared library.
|
||||
* MT32EMU_SHARED should also be defined for Windows platforms that provides for a small performance benefit,
|
||||
* and it _must_ be defined along with MT32EMU_RUNTIME_VERSION_CHECK when using MSVC.
|
||||
*/
|
||||
#ifdef MT32EMU_SHARED
|
||||
#if defined _WIN32 || defined __CYGWIN__
|
||||
#ifdef _MSC_VER
|
||||
#ifdef mt32emu_EXPORTS
|
||||
#define MT32EMU_EXPORT_ATTRIBUTE _declspec(dllexport)
|
||||
#else /* #ifdef mt32emu_EXPORTS */
|
||||
#define MT32EMU_EXPORT_ATTRIBUTE _declspec(dllimport)
|
||||
#endif /* #ifdef mt32emu_EXPORTS */
|
||||
#else /* #ifdef _MSC_VER */
|
||||
#ifdef mt32emu_EXPORTS
|
||||
#define MT32EMU_EXPORT_ATTRIBUTE __attribute__ ((dllexport))
|
||||
#else /* #ifdef mt32emu_EXPORTS */
|
||||
#define MT32EMU_EXPORT_ATTRIBUTE __attribute__ ((dllimport))
|
||||
#endif /* #ifdef mt32emu_EXPORTS */
|
||||
#endif /* #ifdef _MSC_VER */
|
||||
#else /* #if defined _WIN32 || defined __CYGWIN__ */
|
||||
#define MT32EMU_EXPORT_ATTRIBUTE __attribute__ ((visibility("default")))
|
||||
#endif /* #if defined _WIN32 || defined __CYGWIN__ */
|
||||
# if defined _WIN32 || defined __CYGWIN__ || defined __OS2__
|
||||
# ifdef _MSC_VER
|
||||
# ifdef mt32emu_EXPORTS
|
||||
# define MT32EMU_EXPORT_ATTRIBUTE _declspec(dllexport)
|
||||
# else /* #ifdef mt32emu_EXPORTS */
|
||||
# define MT32EMU_EXPORT_ATTRIBUTE _declspec(dllimport)
|
||||
# endif /* #ifdef mt32emu_EXPORTS */
|
||||
# else /* #ifdef _MSC_VER */
|
||||
# ifdef mt32emu_EXPORTS
|
||||
# define MT32EMU_EXPORT_ATTRIBUTE __attribute__ ((dllexport))
|
||||
# else /* #ifdef mt32emu_EXPORTS */
|
||||
# define MT32EMU_EXPORT_ATTRIBUTE __attribute__ ((dllimport))
|
||||
# endif /* #ifdef mt32emu_EXPORTS */
|
||||
# endif /* #ifdef _MSC_VER */
|
||||
# else /* #if defined _WIN32 || defined __CYGWIN__ || defined __OS2__ */
|
||||
# ifdef mt32emu_EXPORTS
|
||||
# define MT32EMU_EXPORT_ATTRIBUTE __attribute__ ((visibility("default")))
|
||||
# else /* #ifdef mt32emu_EXPORTS */
|
||||
# define MT32EMU_EXPORT_ATTRIBUTE
|
||||
# endif /* #ifdef mt32emu_EXPORTS */
|
||||
# endif /* #if defined _WIN32 || defined __CYGWIN__ || defined __OS2__ */
|
||||
#else /* #ifdef MT32EMU_SHARED */
|
||||
#define MT32EMU_EXPORT_ATTRIBUTE
|
||||
# define MT32EMU_EXPORT_ATTRIBUTE
|
||||
#endif /* #ifdef MT32EMU_SHARED */
|
||||
|
||||
#if MT32EMU_EXPORTS_TYPE == 1 || MT32EMU_EXPORTS_TYPE == 2
|
||||
@@ -49,6 +57,33 @@
|
||||
#define MT32EMU_EXPORT MT32EMU_EXPORT_ATTRIBUTE
|
||||
#endif
|
||||
|
||||
/* Facilitates easier tracking of the library version when an external symbol was introduced.
|
||||
* Particularly useful for shared library builds on POSIX systems that support symbol versioning,
|
||||
* so that the version map file can be generated automatically.
|
||||
*/
|
||||
#define MT32EMU_EXPORT_V(symbol_version_tag) MT32EMU_EXPORT
|
||||
|
||||
/* Helpers for compile-time version checks */
|
||||
|
||||
/* Encodes the given version components to a single integer value to simplify further checks. */
|
||||
#define MT32EMU_VERSION_INT(major, minor, patch) ((major << 16) | (minor << 8) | patch)
|
||||
|
||||
/* The version of this library build, as an integer. */
|
||||
#define MT32EMU_CURRENT_VERSION_INT MT32EMU_VERSION_INT(MT32EMU_VERSION_MAJOR, MT32EMU_VERSION_MINOR, MT32EMU_VERSION_PATCH)
|
||||
|
||||
/* Compares the current library version with the given version components. Intended for feature checks. */
|
||||
#define MT32EMU_VERSION_ATLEAST(major, minor, patch) (MT32EMU_CURRENT_VERSION_INT >= MT32EMU_VERSION_INT(major, minor, patch))
|
||||
|
||||
/* Implements a simple version check that ensures full API compatibility of this library build
|
||||
* with the application requirements. The latter can be derived from the versions of used public symbols.
|
||||
*
|
||||
* Note: This macro is intended for a quick compile-time check. To ensure compatibility of an application
|
||||
* linked with a shared library, an automatic version check can be engaged with help of the build option
|
||||
* libmt32emu_WITH_VERSION_TAGGING. For a fine-grained feature checking in run-time, see functions
|
||||
* mt32emu_get_library_version_int and Synth::getLibraryVersionInt.
|
||||
*/
|
||||
#define MT32EMU_IS_COMPATIBLE(major, minor) (MT32EMU_VERSION_MAJOR == major && MT32EMU_VERSION_MINOR >= minor)
|
||||
|
||||
/* Useful constants */
|
||||
|
||||
/* Sample rate to use in mixing. With the progress of development, we've found way too many thing dependent.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
@@ -37,28 +37,23 @@
|
||||
*/
|
||||
|
||||
#ifdef MT32EMU_API_TYPE
|
||||
#if MT32EMU_API_TYPE == 0 && (MT32EMU_EXPORTS_TYPE == 1 || MT32EMU_EXPORTS_TYPE == 2)
|
||||
#error Incompatible setting MT32EMU_API_TYPE=0
|
||||
#elif MT32EMU_API_TYPE == 1 && (MT32EMU_EXPORTS_TYPE == 0 || MT32EMU_EXPORTS_TYPE == 2)
|
||||
#error Incompatible setting MT32EMU_API_TYPE=1
|
||||
#elif MT32EMU_API_TYPE == 2 && (MT32EMU_EXPORTS_TYPE == 0)
|
||||
#error Incompatible setting MT32EMU_API_TYPE=2
|
||||
#elif MT32EMU_API_TYPE == 3 && (MT32EMU_EXPORTS_TYPE == 0 || MT32EMU_EXPORTS_TYPE == 2)
|
||||
#error Incompatible setting MT32EMU_API_TYPE=3
|
||||
#endif
|
||||
# if MT32EMU_API_TYPE == 0 && (MT32EMU_EXPORTS_TYPE == 1 || MT32EMU_EXPORTS_TYPE == 2)
|
||||
# error Incompatible setting MT32EMU_API_TYPE=0
|
||||
# elif MT32EMU_API_TYPE == 1 && (MT32EMU_EXPORTS_TYPE == 0 || MT32EMU_EXPORTS_TYPE == 2)
|
||||
# error Incompatible setting MT32EMU_API_TYPE=1
|
||||
# elif MT32EMU_API_TYPE == 2 && (MT32EMU_EXPORTS_TYPE == 0)
|
||||
# error Incompatible setting MT32EMU_API_TYPE=2
|
||||
# elif MT32EMU_API_TYPE == 3 && (MT32EMU_EXPORTS_TYPE == 0 || MT32EMU_EXPORTS_TYPE == 2)
|
||||
# error Incompatible setting MT32EMU_API_TYPE=3
|
||||
# endif
|
||||
#else /* #ifdef MT32EMU_API_TYPE */
|
||||
#if 0 < MT32EMU_EXPORTS_TYPE && MT32EMU_EXPORTS_TYPE < 3
|
||||
#define MT32EMU_API_TYPE MT32EMU_EXPORTS_TYPE
|
||||
#else
|
||||
#define MT32EMU_API_TYPE 0
|
||||
#endif
|
||||
# if 0 < MT32EMU_EXPORTS_TYPE && MT32EMU_EXPORTS_TYPE < 3
|
||||
# define MT32EMU_API_TYPE MT32EMU_EXPORTS_TYPE
|
||||
# else
|
||||
# define MT32EMU_API_TYPE 0
|
||||
# endif
|
||||
#endif /* #ifdef MT32EMU_API_TYPE */
|
||||
|
||||
/* MT32EMU_SHARED should be defined when building shared library, especially for Windows platforms. */
|
||||
/*
|
||||
#define MT32EMU_SHARED
|
||||
*/
|
||||
|
||||
#include "globals.h"
|
||||
|
||||
#if !defined(__cplusplus) || MT32EMU_API_TYPE == 1
|
||||
@@ -79,6 +74,14 @@
|
||||
#include "MidiStreamParser.h"
|
||||
#include "SampleRateConverter.h"
|
||||
|
||||
#if MT32EMU_RUNTIME_VERSION_CHECK == 1
|
||||
#include "VersionTagging.h"
|
||||
#endif
|
||||
|
||||
#endif /* #if !defined(__cplusplus) || MT32EMU_API_TYPE == 1 */
|
||||
|
||||
#if MT32EMU_RUNTIME_VERSION_CHECK == 2
|
||||
#include "VersionTagging.h"
|
||||
#endif
|
||||
|
||||
#endif /* #ifndef MT32EMU_MT32EMU_H */
|
||||
|
||||
@@ -18,11 +18,13 @@
|
||||
extern void givealbuffer_midi(void *buf, uint32_t size);
|
||||
extern void al_set_midi(int freq, int buf_size);
|
||||
|
||||
|
||||
static mt32emu_report_handler_version get_mt32_report_handler_version(mt32emu_report_handler_i i);
|
||||
static void display_mt32_message(void *instance_data, const char *message);
|
||||
|
||||
static const mt32emu_report_handler_i_v0 handler_mt32_v0 = {
|
||||
/** Returns the actual interface version ID */
|
||||
NULL, // mt32emu_report_handler_version (*getVersionID)(mt32emu_report_handler_i i);
|
||||
get_mt32_report_handler_version, // mt32emu_report_handler_version (*getVersionID)(mt32emu_report_handler_i i);
|
||||
|
||||
/** Callback for debug messages, in vprintf() format */
|
||||
NULL, // void (*printDebug)(void *instance_data, const char *fmt, va_list list);
|
||||
@@ -59,7 +61,7 @@ static const mt32emu_report_handler_i_v0 handler_mt32_v0 = {
|
||||
/** Alternate report handler for Roland CM-32L */
|
||||
static const mt32emu_report_handler_i_v0 handler_cm32l_v0 = {
|
||||
/** Returns the actual interface version ID */
|
||||
NULL, // mt32emu_report_handler_version (*getVersionID)(mt32emu_report_handler_i i);
|
||||
get_mt32_report_handler_version, // mt32emu_report_handler_version (*getVersionID)(mt32emu_report_handler_i i);
|
||||
|
||||
/** Callback for debug messages, in vprintf() format */
|
||||
NULL, // void (*printDebug)(void *instance_data, const char *fmt, va_list list);
|
||||
@@ -138,6 +140,12 @@ static float *buffer = NULL;
|
||||
static int16_t *buffer_int16 = NULL;
|
||||
static int midi_pos = 0;
|
||||
|
||||
static mt32emu_report_handler_version
|
||||
get_mt32_report_handler_version(mt32emu_report_handler_i i)
|
||||
{
|
||||
return MT32EMU_REPORT_HANDLER_VERSION_0;
|
||||
}
|
||||
|
||||
static void
|
||||
display_mt32_message(void *instance_data, const char *message)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
@@ -273,6 +273,8 @@ Analog *Analog::createAnalog(const AnalogOutputMode mode, const bool oldMT32Anal
|
||||
return new AnalogImpl<IntSampleEx>(mode, oldMT32AnalogLPF);
|
||||
case RendererType_FLOAT:
|
||||
return new AnalogImpl<FloatSample>(mode, oldMT32AnalogLPF);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
@@ -633,6 +633,8 @@ BReverbModel *BReverbModel::createBReverbModel(const ReverbMode mode, const bool
|
||||
return new BReverbModelImpl<IntSample>(mode, mt32CompatibleModel);
|
||||
case RendererType_FLOAT:
|
||||
return new BReverbModelImpl<FloatSample>(mode, mt32CompatibleModel);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
# Copyright 2020,2021 David Hrdlička.
|
||||
#
|
||||
|
||||
add_library(mt32emu STATIC Analog.cpp BReverbModel.cpp File.cpp FileStream.cpp
|
||||
add_library(mt32emu STATIC Analog.cpp BReverbModel.cpp Display.cpp File.cpp FileStream.cpp
|
||||
LA32Ramp.cpp LA32FloatWaveGenerator.cpp LA32WaveGenerator.cpp
|
||||
MidiStreamParser.cpp Part.cpp Partial.cpp PartialManager.cpp
|
||||
Poly.cpp ROMInfo.cpp SampleRateConverter.cpp
|
||||
|
||||
354
src/sound/munt/Display.cpp
Normal file
354
src/sound/munt/Display.cpp
Normal file
@@ -0,0 +1,354 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2022 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 <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include "internals.h"
|
||||
|
||||
#include "Display.h"
|
||||
#include "Part.h"
|
||||
#include "Structures.h"
|
||||
#include "Synth.h"
|
||||
|
||||
namespace MT32Emu {
|
||||
|
||||
/* Details on the emulation model.
|
||||
*
|
||||
* There are four display modes emulated:
|
||||
* - main (Master Volume), set upon startup after showing the welcoming banner;
|
||||
* - program change notification;
|
||||
* - custom display message received via a SysEx;
|
||||
* - error banner (e.g. the MIDI message checksum error).
|
||||
* Stuff like cursor blinking, patch selection mode, test mode, reaction to the front panel buttons, etc. is out of scope, as more
|
||||
* convenient UI/UX solutions are likely desired in applications, if at all.
|
||||
*
|
||||
* Note, despite the LAPC and CM devices come without the LCD and the front panel buttons, the control ROM does support these,
|
||||
* if connected to the main board. That's intended for running the test mode in a service centre, as documented.
|
||||
*
|
||||
* Within the aforementioned scope, the observable hardware behaviour differs noticeably, depending on the control ROM version.
|
||||
* At least three milestones can be identified:
|
||||
* - with MT-32 control ROM V1.06, custom messages are no longer shown unless the display is in the main (Master Volume) mode;
|
||||
* - with MT-32 control ROM V2.04, new function introduced - Display Reset yet added many other changes (taking the full SysEx
|
||||
* address into account when processing custom messages and special handling of the ASCII control characters are among them);
|
||||
* all the second-gen devices, including LAPC-I and CM-32L, behave very similarly;
|
||||
* - in the third-gen devices, the LCD support was partially cut down in the control ROM (basically, only the status
|
||||
* of the test mode, the ROM version and the checksum warnings are shown) - it's not fun, so this is NOT emulated.
|
||||
*
|
||||
* Features of the old-gen units.
|
||||
* - Any message with the first address byte 0x20 is processed and has some effect on the LCD. Messages with any other first
|
||||
* address byte (e.g. starting with 0x21 or 0x1F7F7F with an overlap) are not considered display-relevant.
|
||||
* - The second and the third address byte are largely irrelevant. Only presence of the second address byte makes an observable
|
||||
* difference, not the data within.
|
||||
* - Any string received in the custom message is normalised - all ASCII control characters are replaced with spaces, messages
|
||||
* shorter than 20 bytes are filled up with spaces to the full supported length. However, should a timbre name contain an ASCII
|
||||
* control character, it is displayed nevertheless, with zero meaning the end-of-string.
|
||||
* - Special message 0x20 (of just 1 address byte) shows the contents of the custom message buffer with either the last received
|
||||
* message or the empty buffer initially filled with spaces. See the note below about the priorities of the display modes.
|
||||
* - Messages containing two or three bytes with just the address are considered empty and fill the custom message buffer with
|
||||
* all spaces. The contents of the empty buffer is then shown, depending on the priority of the current display mode.
|
||||
* - Timing: custom messages are shown until an external event occurs like pressing a front panel button, receiving a new custom
|
||||
* message, program change, etc., and for indefinitely long otherwise. A program change notification is shown for about 1300
|
||||
* milliseconds; when the timer expires, the display returns to the main mode (irrespective to the current display mode).
|
||||
* When an error occurs, the warning is shown for a limited time only, similarly to the program change notifications.
|
||||
* - The earlier old-gen devices treat all display modes with equal priority, except the main mode, which has a lower one. This
|
||||
* makes it possible e.g. to replace the error banner with a custom message or a program change notification, and so on.
|
||||
* A slightly improved behaviour is observed since the control ROM V1.06, when custom messages were de-prioritised. But still,
|
||||
* a program change beats an error banner even in the later models.
|
||||
*
|
||||
* Features of the second-gen units.
|
||||
* - All three bytes in SysEx address are now relevant.
|
||||
* - It is possible to replace individual characters in the custom message buffer which are addressed individually within
|
||||
* the range 0x200000-0x200013.
|
||||
* - Writes to higher addresses up to 0x20007F simply make the custom message buffer shown, with either the last received message
|
||||
* or the empty buffer initially filled with spaces.
|
||||
* - Writes to address 0x200100 trigger the Display Reset function which resets the display to the main (Master Volume) mode.
|
||||
* Similarly, showing an error banner is ended. If a program change notification is shown, this function does nothing, however.
|
||||
* - Writes to other addresses are not considered display-relevant, albeit writing a long string to lower addresses
|
||||
* (e.g. 0x1F7F7F) that overlaps the display range does result in updating and showing the custom display message.
|
||||
* - Writing a long string that covers the custom message buffer and address 0x200100 does both things, i.e. updates the buffer
|
||||
* and triggers the Display Reset function.
|
||||
* - While the display is not in a user interaction mode, custom messages and error banners have the highest display priority.
|
||||
* As long as these are shown, program change notifications are suppressed. The display only leaves this mode when the Display
|
||||
* Reset function is triggered or a front panel button is pressed. Notably, when the user enters the menu, all custom messages
|
||||
* are ignored, including the Display Reset command, but error banners are shown nevertheless.
|
||||
* - Sending cut down messages with partially specified address rather leads to undefined behaviour, except for a two-byte message
|
||||
* 0x20 0x00 which consistently shows the content of the custom message buffer (if priority permits). Otherwise, the behaviour
|
||||
* depends on the previously submitted address, e.g. the two-byte version of Display Reset may fail depending on the third byte
|
||||
* of the previous message. One-byte message 0x20 seemingly does Display Reset yet writes a zero character to a position derived
|
||||
* from the third byte of the preceding message.
|
||||
*
|
||||
* Some notes on the behaviour that is common to all hardware models.
|
||||
* - The display is DM2011 with LSI SED1200D-0A. This unit supports 4 user-programmable characters stored in CGRAM, all 4 get
|
||||
* loaded at startup. Character #0 is empty (with the cursor underline), #1 is the full block (used to mark active parts),
|
||||
* #2 is the pipe character (identical to #124 from the CGROM) and #3 is a variation on "down arrow". During normal operation,
|
||||
* those duplicated characters #2 and #124 are both used in different places and character #3 can only be made visible by adding
|
||||
* it either to a custom timbre name or a custom message. Character #0 is probably never shown as this code has special meaning
|
||||
* in the processing routines. For simplicity, we only use characters #124 and #1 in this model.
|
||||
* - When the main mode is active, the current state of the first 5 parts and the rhythm part is represented by replacing the part
|
||||
* symbol with the full rectangle character (#1 from the CGRAM). For voice parts, the rectangle is shown as long as at least one
|
||||
* partial is playing in a non-releasing phase on that part. For the rhythm part, the rectangle blinks briefly when a new NoteOn
|
||||
* message is received on that part (sometimes even when that actually produces no sound).
|
||||
*/
|
||||
|
||||
static const char MASTER_VOLUME_WITH_DELIMITER[] = "| 0";
|
||||
static const char MASTER_VOLUME_WITH_DELIMITER_AND_PREFIX[] = "|vol: 0";
|
||||
static const Bit8u RHYTHM_PART_CODE = 'R';
|
||||
static const Bit8u FIELD_DELIMITER = '|';
|
||||
static const Bit8u ACTIVE_PART_INDICATOR = 1;
|
||||
|
||||
static const Bit32u DISPLAYED_VOICE_PARTS_COUNT = 5;
|
||||
static const Bit32u SOUND_GROUP_NAME_WITH_DELIMITER_SIZE = 8;
|
||||
static const Bit32u MASTER_VOLUME_WITH_DELIMITER_SIZE = sizeof(MASTER_VOLUME_WITH_DELIMITER) - 1;
|
||||
static const Bit32u MASTER_VOLUME_WITH_DELIMITER_AND_PREFIX_SIZE = sizeof(MASTER_VOLUME_WITH_DELIMITER_AND_PREFIX) - 1;
|
||||
|
||||
// This is the period to show those short blinks of MIDI MESSAGE LED and the rhythm part state.
|
||||
// Two related countdowns are initialised to 8 and touched each 10 milliseconds by the software timer 0 interrupt handler.
|
||||
static const Bit32u BLINK_TIME_MILLIS = 80;
|
||||
static const Bit32u BLINK_TIME_FRAMES = BLINK_TIME_MILLIS * SAMPLE_RATE / 1000;
|
||||
|
||||
// This is based on the (free-running) TIMER1 overflow interrupt. The timer is 16-bit and clocked at 500KHz.
|
||||
// The message is displayed until 10 overflow interrupts occur. At the standard sample rate, it counts
|
||||
// precisely as 41943.04 frame times.
|
||||
static const Bit32u SCHEDULED_DISPLAY_MODE_RESET_FRAMES = 41943;
|
||||
|
||||
/**
|
||||
* Copies up to lengthLimit characters from possibly null-terminated source to destination. The character of destination located
|
||||
* at the position of the null terminator (if any) in source and the rest of destination are left untouched.
|
||||
*/
|
||||
static void copyNullTerminatedString(Bit8u *destination, const Bit8u *source, Bit32u lengthLimit) {
|
||||
for (Bit32u i = 0; i < lengthLimit; i++) {
|
||||
Bit8u c = source[i];
|
||||
if (c == 0) break;
|
||||
destination[i] = c;
|
||||
}
|
||||
}
|
||||
|
||||
Display::Display(Synth &useSynth) :
|
||||
synth(useSynth),
|
||||
lastLEDState(),
|
||||
lcdDirty(),
|
||||
lcdUpdateSignalled(),
|
||||
lastRhythmPartState(),
|
||||
mode(Mode_STARTUP_MESSAGE),
|
||||
midiMessagePlayedSinceLastReset(),
|
||||
rhythmNotePlayedSinceLastReset()
|
||||
{
|
||||
scheduleDisplayReset();
|
||||
const Bit8u *startupMessage = &synth.controlROMData[synth.controlROMMap->startupMessage];
|
||||
memcpy(displayBuffer, startupMessage, LCD_TEXT_SIZE);
|
||||
memset(customMessageBuffer, ' ', LCD_TEXT_SIZE);
|
||||
memset(voicePartStates, 0, sizeof voicePartStates);
|
||||
}
|
||||
|
||||
void Display::checkDisplayStateUpdated(bool &midiMessageLEDState, bool &midiMessageLEDUpdated, bool &lcdUpdated) {
|
||||
midiMessageLEDState = midiMessagePlayedSinceLastReset;
|
||||
maybeResetTimer(midiMessagePlayedSinceLastReset, midiMessageLEDResetTimestamp);
|
||||
// Note, the LED represents activity of the voice parts only.
|
||||
for (Bit32u partIndex = 0; !midiMessageLEDState && partIndex < 8; partIndex++) {
|
||||
midiMessageLEDState = voicePartStates[partIndex];
|
||||
}
|
||||
midiMessageLEDUpdated = lastLEDState != midiMessageLEDState;
|
||||
lastLEDState = midiMessageLEDState;
|
||||
|
||||
if (displayResetScheduled && shouldResetTimer(displayResetTimestamp)) setMainDisplayMode();
|
||||
|
||||
if (lastRhythmPartState != rhythmNotePlayedSinceLastReset && mode == Mode_MAIN) lcdDirty = true;
|
||||
lastRhythmPartState = rhythmNotePlayedSinceLastReset;
|
||||
maybeResetTimer(rhythmNotePlayedSinceLastReset, rhythmStateResetTimestamp);
|
||||
|
||||
lcdUpdated = lcdDirty && !lcdUpdateSignalled;
|
||||
if (lcdUpdated) lcdUpdateSignalled = true;
|
||||
}
|
||||
|
||||
bool Display::getDisplayState(char *targetBuffer, bool narrowLCD) {
|
||||
if (lcdUpdateSignalled) {
|
||||
lcdDirty = false;
|
||||
lcdUpdateSignalled = false;
|
||||
|
||||
switch (mode) {
|
||||
case Mode_CUSTOM_MESSAGE:
|
||||
if (synth.isDisplayOldMT32Compatible()) {
|
||||
memcpy(displayBuffer, customMessageBuffer, LCD_TEXT_SIZE);
|
||||
} else {
|
||||
copyNullTerminatedString(displayBuffer, customMessageBuffer, LCD_TEXT_SIZE);
|
||||
}
|
||||
break;
|
||||
case Mode_ERROR_MESSAGE: {
|
||||
const Bit8u *sysexErrorMessage = &synth.controlROMData[synth.controlROMMap->sysexErrorMessage];
|
||||
memcpy(displayBuffer, sysexErrorMessage, LCD_TEXT_SIZE);
|
||||
break;
|
||||
}
|
||||
case Mode_PROGRAM_CHANGE: {
|
||||
Bit8u *writePosition = displayBuffer;
|
||||
*writePosition++ = '1' + lastProgramChangePartIndex;
|
||||
*writePosition++ = FIELD_DELIMITER;
|
||||
if (narrowLCD) {
|
||||
writePosition[TIMBRE_NAME_SIZE] = 0;
|
||||
} else {
|
||||
memcpy(writePosition, lastProgramChangeSoundGroupName, SOUND_GROUP_NAME_WITH_DELIMITER_SIZE);
|
||||
writePosition += SOUND_GROUP_NAME_WITH_DELIMITER_SIZE;
|
||||
}
|
||||
copyNullTerminatedString(writePosition, lastProgramChangeTimbreName, TIMBRE_NAME_SIZE);
|
||||
break;
|
||||
}
|
||||
case Mode_MAIN: {
|
||||
Bit8u *writePosition = displayBuffer;
|
||||
for (Bit32u partIndex = 0; partIndex < DISPLAYED_VOICE_PARTS_COUNT; partIndex++) {
|
||||
*writePosition++ = voicePartStates[partIndex] ? ACTIVE_PART_INDICATOR : '1' + partIndex;
|
||||
*writePosition++ = ' ';
|
||||
}
|
||||
*writePosition++ = lastRhythmPartState ? ACTIVE_PART_INDICATOR : RHYTHM_PART_CODE;
|
||||
*writePosition++ = ' ';
|
||||
if (narrowLCD) {
|
||||
memcpy(writePosition, MASTER_VOLUME_WITH_DELIMITER, MASTER_VOLUME_WITH_DELIMITER_SIZE);
|
||||
writePosition += MASTER_VOLUME_WITH_DELIMITER_SIZE;
|
||||
*writePosition = 0;
|
||||
} else {
|
||||
memcpy(writePosition, MASTER_VOLUME_WITH_DELIMITER_AND_PREFIX, MASTER_VOLUME_WITH_DELIMITER_AND_PREFIX_SIZE);
|
||||
writePosition += MASTER_VOLUME_WITH_DELIMITER_AND_PREFIX_SIZE;
|
||||
}
|
||||
Bit32u masterVol = synth.mt32ram.system.masterVol;
|
||||
while (masterVol > 0) {
|
||||
std::div_t result = std::div(masterVol, 10);
|
||||
*--writePosition = '0' + result.rem;
|
||||
masterVol = result.quot;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(targetBuffer, displayBuffer, LCD_TEXT_SIZE);
|
||||
targetBuffer[LCD_TEXT_SIZE] = 0;
|
||||
return lastLEDState;
|
||||
}
|
||||
|
||||
void Display::setMainDisplayMode() {
|
||||
displayResetScheduled = false;
|
||||
mode = Mode_MAIN;
|
||||
lcdDirty = true;
|
||||
}
|
||||
|
||||
void Display::midiMessagePlayed() {
|
||||
midiMessagePlayedSinceLastReset = true;
|
||||
midiMessageLEDResetTimestamp = synth.renderedSampleCount + BLINK_TIME_FRAMES;
|
||||
}
|
||||
|
||||
void Display::rhythmNotePlayed() {
|
||||
rhythmNotePlayedSinceLastReset = true;
|
||||
rhythmStateResetTimestamp = synth.renderedSampleCount + BLINK_TIME_FRAMES;
|
||||
midiMessagePlayed();
|
||||
if (synth.isDisplayOldMT32Compatible() && mode == Mode_CUSTOM_MESSAGE) setMainDisplayMode();
|
||||
}
|
||||
|
||||
void Display::voicePartStateChanged(Bit8u partIndex, bool activated) {
|
||||
if (mode == Mode_MAIN) lcdDirty = true;
|
||||
voicePartStates[partIndex] = activated;
|
||||
if (synth.isDisplayOldMT32Compatible() && mode == Mode_CUSTOM_MESSAGE) setMainDisplayMode();
|
||||
}
|
||||
|
||||
void Display::masterVolumeChanged() {
|
||||
if (mode == Mode_MAIN) lcdDirty = true;
|
||||
}
|
||||
|
||||
void Display::programChanged(Bit8u partIndex) {
|
||||
if (!synth.isDisplayOldMT32Compatible() && (mode == Mode_CUSTOM_MESSAGE || mode == Mode_ERROR_MESSAGE)) return;
|
||||
mode = Mode_PROGRAM_CHANGE;
|
||||
lcdDirty = true;
|
||||
scheduleDisplayReset();
|
||||
lastProgramChangePartIndex = partIndex;
|
||||
const Part *part = synth.getPart(partIndex);
|
||||
lastProgramChangeSoundGroupName = synth.getSoundGroupName(part);
|
||||
memcpy(lastProgramChangeTimbreName, part->getCurrentInstr(), TIMBRE_NAME_SIZE);
|
||||
}
|
||||
|
||||
void Display::checksumErrorOccurred() {
|
||||
if (mode != Mode_ERROR_MESSAGE) {
|
||||
mode = Mode_ERROR_MESSAGE;
|
||||
lcdDirty = true;
|
||||
}
|
||||
if (synth.isDisplayOldMT32Compatible()) {
|
||||
scheduleDisplayReset();
|
||||
} else {
|
||||
displayResetScheduled = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Display::customDisplayMessageReceived(const Bit8u *message, Bit32u startIndex, Bit32u length) {
|
||||
if (synth.isDisplayOldMT32Compatible()) {
|
||||
for (Bit32u i = 0; i < LCD_TEXT_SIZE; i++) {
|
||||
Bit8u c = i < length ? message[i] : ' ';
|
||||
if (c < 32 || 127 < c) c = ' ';
|
||||
customMessageBuffer[i] = c;
|
||||
}
|
||||
if (!synth.controlROMFeatures->quirkDisplayCustomMessagePriority
|
||||
&& (mode == Mode_PROGRAM_CHANGE || mode == Mode_ERROR_MESSAGE)) return false;
|
||||
// Note, real devices keep the display reset timer running.
|
||||
} else {
|
||||
if (startIndex > 0x80) return false;
|
||||
if (startIndex == 0x80) {
|
||||
if (mode != Mode_PROGRAM_CHANGE) setMainDisplayMode();
|
||||
return false;
|
||||
}
|
||||
displayResetScheduled = false;
|
||||
if (startIndex < LCD_TEXT_SIZE) {
|
||||
if (length > LCD_TEXT_SIZE - startIndex) length = LCD_TEXT_SIZE - startIndex;
|
||||
memcpy(customMessageBuffer + startIndex, message, length);
|
||||
}
|
||||
}
|
||||
mode = Mode_CUSTOM_MESSAGE;
|
||||
lcdDirty = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Display::displayControlMessageReceived(const Bit8u *messageBytes, Bit32u length) {
|
||||
Bit8u emptyMessage[] = { 0 };
|
||||
if (synth.isDisplayOldMT32Compatible()) {
|
||||
if (length == 1) {
|
||||
customDisplayMessageReceived(customMessageBuffer, 0, LCD_TEXT_SIZE);
|
||||
} else {
|
||||
customDisplayMessageReceived(emptyMessage, 0, 0);
|
||||
}
|
||||
} else {
|
||||
// Always assume the third byte to be zero for simplicity.
|
||||
if (length == 2) {
|
||||
customDisplayMessageReceived(emptyMessage, messageBytes[1] << 7, 0);
|
||||
} else if (length == 1) {
|
||||
customMessageBuffer[0] = 0;
|
||||
customDisplayMessageReceived(emptyMessage, 0x80, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Display::scheduleDisplayReset() {
|
||||
displayResetTimestamp = synth.renderedSampleCount + SCHEDULED_DISPLAY_MODE_RESET_FRAMES;
|
||||
displayResetScheduled = true;
|
||||
}
|
||||
|
||||
bool Display::shouldResetTimer(Bit32u scheduledResetTimestamp) {
|
||||
// Deals with wrapping of renderedSampleCount.
|
||||
return Bit32s(scheduledResetTimestamp - synth.renderedSampleCount) < 0;
|
||||
}
|
||||
|
||||
void Display::maybeResetTimer(bool &timerState, Bit32u scheduledResetTimestamp) {
|
||||
if (timerState && shouldResetTimer(scheduledResetTimestamp)) timerState = false;
|
||||
}
|
||||
|
||||
} // namespace MT32Emu
|
||||
91
src/sound/munt/Display.h
Normal file
91
src/sound/munt/Display.h
Normal file
@@ -0,0 +1,91 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2022 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_DISPLAY_H
|
||||
#define MT32EMU_DISPLAY_H
|
||||
|
||||
#include "globals.h"
|
||||
#include "Types.h"
|
||||
|
||||
namespace MT32Emu {
|
||||
|
||||
class Synth;
|
||||
|
||||
/** Facilitates emulation of internal state of the MIDI MESSAGE LED and the MT-32 LCD. */
|
||||
class Display {
|
||||
public:
|
||||
static const unsigned int LCD_TEXT_SIZE = 20;
|
||||
|
||||
enum Mode {
|
||||
Mode_MAIN, // a.k.a. Master Volume
|
||||
Mode_STARTUP_MESSAGE,
|
||||
Mode_PROGRAM_CHANGE,
|
||||
Mode_CUSTOM_MESSAGE,
|
||||
Mode_ERROR_MESSAGE
|
||||
};
|
||||
|
||||
Display(Synth &synth);
|
||||
void checkDisplayStateUpdated(bool &midiMessageLEDState, bool &midiMessageLEDUpdated, bool &lcdUpdated);
|
||||
/** Returns whether the MIDI MESSAGE LED is ON and fills the targetBuffer parameter. */
|
||||
bool getDisplayState(char *targetBuffer, bool narrowLCD);
|
||||
void setMainDisplayMode();
|
||||
|
||||
void midiMessagePlayed();
|
||||
void rhythmNotePlayed();
|
||||
void voicePartStateChanged(Bit8u partIndex, bool activated);
|
||||
void masterVolumeChanged();
|
||||
void programChanged(Bit8u partIndex);
|
||||
void checksumErrorOccurred();
|
||||
bool customDisplayMessageReceived(const Bit8u *message, Bit32u startIndex, Bit32u length);
|
||||
void displayControlMessageReceived(const Bit8u *messageBytes, Bit32u length);
|
||||
|
||||
private:
|
||||
typedef Bit8u DisplayBuffer[LCD_TEXT_SIZE];
|
||||
|
||||
static const unsigned int TIMBRE_NAME_SIZE = 10;
|
||||
|
||||
Synth &synth;
|
||||
|
||||
bool lastLEDState;
|
||||
bool lcdDirty;
|
||||
bool lcdUpdateSignalled;
|
||||
bool lastRhythmPartState;
|
||||
bool voicePartStates[8];
|
||||
|
||||
Bit8u lastProgramChangePartIndex;
|
||||
const char *lastProgramChangeSoundGroupName;
|
||||
Bit8u lastProgramChangeTimbreName[TIMBRE_NAME_SIZE];
|
||||
|
||||
Mode mode;
|
||||
Bit32u displayResetTimestamp;
|
||||
bool displayResetScheduled;
|
||||
Bit32u midiMessageLEDResetTimestamp;
|
||||
bool midiMessagePlayedSinceLastReset;
|
||||
Bit32u rhythmStateResetTimestamp;
|
||||
bool rhythmNotePlayedSinceLastReset;
|
||||
|
||||
DisplayBuffer displayBuffer;
|
||||
DisplayBuffer customMessageBuffer;
|
||||
|
||||
void scheduleDisplayReset();
|
||||
bool shouldResetTimer(Bit32u scheduledResetTimestamp);
|
||||
void maybeResetTimer(bool &timerState, Bit32u scheduledResetTimestamp);
|
||||
};
|
||||
|
||||
} // namespace MT32Emu
|
||||
|
||||
#endif // #ifndef MT32EMU_DISPLAY_H
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
@@ -15,8 +15,8 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef MT32EMU_SHARED
|
||||
#include <locale>
|
||||
#if defined MT32EMU_SHARED && defined MT32EMU_INSTALL_DEFAULT_LOCALE
|
||||
#include <clocale>
|
||||
#endif
|
||||
|
||||
#include "internals.h"
|
||||
@@ -25,13 +25,18 @@
|
||||
|
||||
namespace MT32Emu {
|
||||
|
||||
// This initialises C locale with the user-preferred system locale once facilitating access
|
||||
// to ROM files with localised pathnames. This is only necessary in rare cases e.g. when building
|
||||
// shared library statically linked with C runtime with old MS VC versions, so that the C locale
|
||||
// set by the client application does not have effect, and thus such ROM files cannot be opened.
|
||||
static inline void configureSystemLocale() {
|
||||
#ifdef MT32EMU_SHARED
|
||||
#if defined MT32EMU_SHARED && defined MT32EMU_INSTALL_DEFAULT_LOCALE
|
||||
static bool configured = false;
|
||||
|
||||
if (configured) return;
|
||||
configured = true;
|
||||
std::locale::global(std::locale(""));
|
||||
|
||||
setlocale(LC_ALL, "");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
@@ -236,7 +236,7 @@ float LA32FloatWaveGenerator::generateNextSample(const Bit32u ampVal, const Bit1
|
||||
relWavePos -= cosineLen + hLen;
|
||||
}
|
||||
|
||||
// To ensure the output wave has no breaks, two different windows are appied to the beginning and the ending of the resonance sine segment
|
||||
// To ensure the output wave has no breaks, two different windows are applied to the beginning and the ending of the resonance sine segment
|
||||
if (relWavePos < 0.5f * cosineLen) {
|
||||
float syncSine = sin(FLOAT_PI * relWavePos / cosineLen);
|
||||
if (relWavePos < 0.0f) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
@@ -173,7 +173,7 @@ void LA32WaveGenerator::generateNextResonanceWaveLogSample() {
|
||||
// Unsure about resonanceSinePosition here. It's possible that dedicated counter & decrement are used. Although, cutoff is finely ramped, so maybe not.
|
||||
logSampleValue += resonanceAmpSubtraction + (((resonanceSinePosition >> 4) * decayFactor) >> 8);
|
||||
|
||||
// To ensure the output wave has no breaks, two different windows are appied to the beginning and the ending of the resonance sine segment
|
||||
// To ensure the output wave has no breaks, two different windows are applied to the beginning and the ending of the resonance sine segment
|
||||
if (phase == POSITIVE_RISING_SINE_SEGMENT || phase == NEGATIVE_FALLING_SINE_SEGMENT) {
|
||||
// The window is synchronous sine here
|
||||
logSampleValue += Tables::getInstance().logsin9[(squareWavePosition >> 9) & 511] << 2;
|
||||
@@ -183,7 +183,7 @@ void LA32WaveGenerator::generateNextResonanceWaveLogSample() {
|
||||
}
|
||||
|
||||
if (cutoffVal < MIDDLE_CUTOFF_VALUE) {
|
||||
// For the cutoff values below the cutoff middle point, it seems the amp of the resonance wave is expotentially decayed
|
||||
// For the cutoff values below the cutoff middle point, it seems the amp of the resonance wave is exponentially decayed
|
||||
logSampleValue += 31743 + ((MIDDLE_CUTOFF_VALUE - cutoffVal) >> 9);
|
||||
} else if (cutoffVal < RESONANCE_DECAY_THRESHOLD_CUTOFF_VALUE) {
|
||||
// For the cutoff values below this point, the amp of the resonance wave is sinusoidally decayed
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
@@ -120,7 +120,9 @@ public:
|
||||
};
|
||||
class DisplayMemoryRegion : public MemoryRegion {
|
||||
public:
|
||||
DisplayMemoryRegion(Synth *useSynth) : MemoryRegion(useSynth, NULL, NULL, MR_Display, MT32EMU_MEMADDR(0x200000), SYSEX_BUFFER_SIZE - 1, 1) {}
|
||||
// Note, we set realMemory to NULL despite the real devices buffer inbound strings. However, it is impossible to retrieve them.
|
||||
// This entrySize permits emulation of handling a 20-byte display message sent to an old-gen device at address 0x207F7F.
|
||||
DisplayMemoryRegion(Synth *useSynth) : MemoryRegion(useSynth, NULL, NULL, MR_Display, MT32EMU_MEMADDR(0x200000), 0x4013, 1) {}
|
||||
};
|
||||
class ResetMemoryRegion : public MemoryRegion {
|
||||
public:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
@@ -59,10 +59,12 @@ Part::Part(Synth *useSynth, unsigned int usePartNum) {
|
||||
}
|
||||
currentInstr[0] = 0;
|
||||
currentInstr[10] = 0;
|
||||
volumeOverride = 255;
|
||||
modulation = 0;
|
||||
expression = 100;
|
||||
pitchBend = 0;
|
||||
activePartialCount = 0;
|
||||
activeNonReleasingPolyCount = 0;
|
||||
memset(patchCache, 0, sizeof(patchCache));
|
||||
}
|
||||
|
||||
@@ -166,7 +168,7 @@ void Part::refresh() {
|
||||
patchCache[t].reverb = patchTemp->patch.reverbSwitch > 0;
|
||||
}
|
||||
memcpy(currentInstr, timbreTemp->common.name, 10);
|
||||
synth->newTimbreSet(partNum, patchTemp->patch.timbreGroup, patchTemp->patch.timbreNum, currentInstr);
|
||||
synth->newTimbreSet(partNum);
|
||||
updatePitchBenderRange();
|
||||
}
|
||||
|
||||
@@ -317,7 +319,21 @@ void Part::setVolume(unsigned int midiVolume) {
|
||||
}
|
||||
|
||||
Bit8u Part::getVolume() const {
|
||||
return patchTemp->outputLevel;
|
||||
return volumeOverride <= 100 ? volumeOverride : patchTemp->outputLevel;
|
||||
}
|
||||
|
||||
void Part::setVolumeOverride(Bit8u volume) {
|
||||
volumeOverride = volume;
|
||||
// When volume is 0, we want the part to stop producing any sound at all.
|
||||
// For that to achieve, we have to actually stop processing NoteOn MIDI messages; merely
|
||||
// returning 0 volume is not enough - the output may still be generated at a very low level.
|
||||
// But first, we have to stop all the currently playing polys. This behaviour may also help
|
||||
// with performance issues, because parts muted this way barely consume CPU resources.
|
||||
if (volume == 0) allSoundOff();
|
||||
}
|
||||
|
||||
Bit8u Part::getVolumeOverride() const {
|
||||
return volumeOverride;
|
||||
}
|
||||
|
||||
Bit8u Part::getExpression() const {
|
||||
@@ -380,6 +396,7 @@ void RhythmPart::noteOn(unsigned int midiKey, unsigned int velocity) {
|
||||
synth->printDebug("%s: Attempted to play invalid key %d (velocity %d)", name, midiKey, velocity);
|
||||
return;
|
||||
}
|
||||
synth->rhythmNotePlayed();
|
||||
unsigned int key = midiKey;
|
||||
unsigned int drumNum = key - 24;
|
||||
int drumTimbreNum = rhythmTemp[drumNum].timbre;
|
||||
@@ -609,6 +626,27 @@ void Part::partialDeactivated(Poly *poly) {
|
||||
}
|
||||
}
|
||||
|
||||
void RhythmPart::polyStateChanged(PolyState, PolyState) {}
|
||||
|
||||
void Part::polyStateChanged(PolyState oldState, PolyState newState) {
|
||||
switch (newState) {
|
||||
case POLY_Playing:
|
||||
if (activeNonReleasingPolyCount++ == 0) synth->voicePartStateChanged(partNum, true);
|
||||
break;
|
||||
case POLY_Releasing:
|
||||
case POLY_Inactive:
|
||||
if (oldState == POLY_Playing || oldState == POLY_Held) {
|
||||
if (--activeNonReleasingPolyCount == 0) synth->voicePartStateChanged(partNum, false);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#ifdef MT32EMU_TRACE_POLY_STATE_CHANGES
|
||||
synth->printDebug("Part %d: Changed poly state %d->%d, activeNonReleasingPolyCount=%d", partNum, oldState, newState, activeNonReleasingPolyCount);
|
||||
#endif
|
||||
}
|
||||
|
||||
PolyList::PolyList() : firstPoly(NULL), lastPoly(NULL) {}
|
||||
|
||||
bool PolyList::isEmpty() const {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
@@ -55,6 +55,7 @@ private:
|
||||
bool holdpedal;
|
||||
|
||||
unsigned int activePartialCount;
|
||||
unsigned int activeNonReleasingPolyCount;
|
||||
PatchCache patchCache[4];
|
||||
PolyList activePolys;
|
||||
|
||||
@@ -69,6 +70,8 @@ protected:
|
||||
MemParams::PatchTemp *patchTemp;
|
||||
char name[8]; // "Part 1".."Part 8", "Rhythm"
|
||||
char currentInstr[11];
|
||||
// Values outside the valid range 0..100 imply no override.
|
||||
Bit8u volumeOverride;
|
||||
Bit8u modulation;
|
||||
Bit8u expression;
|
||||
Bit32s pitchBend;
|
||||
@@ -95,8 +98,10 @@ public:
|
||||
virtual void noteOff(unsigned int midiKey);
|
||||
void allNotesOff();
|
||||
void allSoundOff();
|
||||
Bit8u getVolume() const; // Internal volume, 0-100, exposed for use by ExternalInterface
|
||||
void setVolume(unsigned int midiVolume);
|
||||
Bit8u getVolume() const; // Effective output level, valid range 0..100.
|
||||
void setVolume(unsigned int midiVolume); // Valid range 0..127, as defined for MIDI controller 7.
|
||||
Bit8u getVolumeOverride() const;
|
||||
void setVolumeOverride(Bit8u volumeOverride);
|
||||
Bit8u getModulation() const;
|
||||
void setModulation(unsigned int midiModulation);
|
||||
Bit8u getExpression() const;
|
||||
@@ -122,6 +127,7 @@ public:
|
||||
|
||||
// This should only be called by Poly
|
||||
void partialDeactivated(Poly *poly);
|
||||
virtual void polyStateChanged(PolyState oldState, PolyState newState);
|
||||
|
||||
// These are rather specialised, and should probably only be used by PartialManager
|
||||
bool abortFirstPoly(PolyState polyState);
|
||||
@@ -146,6 +152,7 @@ public:
|
||||
unsigned int getAbsTimbreNum() const;
|
||||
void setPan(unsigned int midiPan);
|
||||
void setProgram(unsigned int patchNum);
|
||||
void polyStateChanged(PolyState oldState, PolyState newState);
|
||||
};
|
||||
|
||||
} // namespace MT32Emu
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
@@ -53,7 +53,7 @@ void Poly::reset(unsigned int newKey, unsigned int newVelocity, bool newSustain,
|
||||
activePartialCount--;
|
||||
}
|
||||
}
|
||||
state = POLY_Inactive;
|
||||
setState(POLY_Inactive);
|
||||
}
|
||||
|
||||
key = newKey;
|
||||
@@ -65,7 +65,7 @@ void Poly::reset(unsigned int newKey, unsigned int newVelocity, bool newSustain,
|
||||
partials[i] = newPartials[i];
|
||||
if (newPartials[i] != NULL) {
|
||||
activePartialCount++;
|
||||
state = POLY_Playing;
|
||||
setState(POLY_Playing);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -80,7 +80,7 @@ bool Poly::noteOff(bool pedalHeld) {
|
||||
if (state == POLY_Held) {
|
||||
return false;
|
||||
}
|
||||
state = POLY_Held;
|
||||
setState(POLY_Held);
|
||||
} else {
|
||||
startDecay();
|
||||
}
|
||||
@@ -98,7 +98,7 @@ bool Poly::startDecay() {
|
||||
if (state == POLY_Inactive || state == POLY_Releasing) {
|
||||
return false;
|
||||
}
|
||||
state = POLY_Releasing;
|
||||
setState(POLY_Releasing);
|
||||
|
||||
for (int t = 0; t < 4; t++) {
|
||||
Partial *partial = partials[t];
|
||||
@@ -123,6 +123,13 @@ bool Poly::startAbort() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void Poly::setState(PolyState newState) {
|
||||
if (state == newState) return;
|
||||
PolyState oldState = state;
|
||||
state = newState;
|
||||
part->polyStateChanged(oldState, newState);
|
||||
}
|
||||
|
||||
void Poly::backupCacheToPartials(PatchCache cache[4]) {
|
||||
for (int partialNum = 0; partialNum < 4; partialNum++) {
|
||||
Partial *partial = partials[partialNum];
|
||||
@@ -171,7 +178,7 @@ void Poly::partialDeactivated(Partial *partial) {
|
||||
}
|
||||
}
|
||||
if (activePartialCount == 0) {
|
||||
state = POLY_Inactive;
|
||||
setState(POLY_Inactive);
|
||||
if (part->getSynth()->abortingPoly == this) {
|
||||
part->getSynth()->abortingPoly = NULL;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
@@ -41,6 +41,8 @@ private:
|
||||
|
||||
Poly *next;
|
||||
|
||||
void setState(PolyState state);
|
||||
|
||||
public:
|
||||
Poly();
|
||||
void setPart(Part *usePart);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
@@ -19,45 +19,164 @@
|
||||
|
||||
#include "internals.h"
|
||||
|
||||
#include "File.h"
|
||||
#include "ROMInfo.h"
|
||||
|
||||
namespace MT32Emu {
|
||||
|
||||
static const ROMInfo *getKnownROMInfoFromList(Bit32u index) {
|
||||
// Known ROMs
|
||||
static const ROMInfo CTRL_MT32_V1_04 = {65536, "5a5cb5a77d7d55ee69657c2f870416daed52dea7", ROMInfo::Control, "ctrl_mt32_1_04", "MT-32 Control v1.04", ROMInfo::Full, NULL};
|
||||
static const ROMInfo CTRL_MT32_V1_05 = {65536, "e17a3a6d265bf1fa150312061134293d2b58288c", ROMInfo::Control, "ctrl_mt32_1_05", "MT-32 Control v1.05", ROMInfo::Full, NULL};
|
||||
static const ROMInfo CTRL_MT32_V1_06 = {65536, "a553481f4e2794c10cfe597fef154eef0d8257de", ROMInfo::Control, "ctrl_mt32_1_06", "MT-32 Control v1.06", ROMInfo::Full, NULL};
|
||||
static const ROMInfo CTRL_MT32_V1_07 = {65536, "b083518fffb7f66b03c23b7eb4f868e62dc5a987", ROMInfo::Control, "ctrl_mt32_1_07", "MT-32 Control v1.07", ROMInfo::Full, NULL};
|
||||
static const ROMInfo CTRL_MT32_BLUER = {65536, "7b8c2a5ddb42fd0732e2f22b3340dcf5360edf92", ROMInfo::Control, "ctrl_mt32_bluer", "MT-32 Control BlueRidge", ROMInfo::Full, NULL};
|
||||
namespace {
|
||||
|
||||
struct ROMInfoList {
|
||||
const ROMInfo * const *romInfos;
|
||||
const Bit32u itemCount;
|
||||
};
|
||||
|
||||
struct ROMInfoLists {
|
||||
ROMInfoList mt32_1_04;
|
||||
ROMInfoList mt32_1_05;
|
||||
ROMInfoList mt32_1_06;
|
||||
ROMInfoList mt32_1_07;
|
||||
ROMInfoList mt32_bluer;
|
||||
ROMInfoList mt32_2_03;
|
||||
ROMInfoList mt32_2_04;
|
||||
ROMInfoList mt32_2_06;
|
||||
ROMInfoList mt32_2_07;
|
||||
ROMInfoList cm32l_1_00;
|
||||
ROMInfoList cm32l_1_02;
|
||||
ROMInfoList cm32ln_1_00;
|
||||
ROMInfoList fullROMInfos;
|
||||
ROMInfoList partialROMInfos;
|
||||
ROMInfoList allROMInfos;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#define _CALC_ARRAY_LENGTH(x) Bit32u(sizeof (x) / sizeof *(x) - 1)
|
||||
|
||||
static const ROMInfoLists &getROMInfoLists() {
|
||||
static ROMInfo CTRL_MT32_V1_04_A = {32768, "9cd4858014c4e8a9dff96053f784bfaac1092a2e", ROMInfo::Control, "ctrl_mt32_1_04_a", "MT-32 Control v1.04", ROMInfo::Mux0, NULL};
|
||||
static ROMInfo CTRL_MT32_V1_04_B = {32768, "fe8db469b5bfeb37edb269fd47e3ce6d91014652", ROMInfo::Control, "ctrl_mt32_1_04_b", "MT-32 Control v1.04", ROMInfo::Mux1, &CTRL_MT32_V1_04_A};
|
||||
static ROMInfo CTRL_MT32_V1_04 = {65536, "5a5cb5a77d7d55ee69657c2f870416daed52dea7", ROMInfo::Control, "ctrl_mt32_1_04", "MT-32 Control v1.04", ROMInfo::Full, NULL};
|
||||
static ROMInfo CTRL_MT32_V1_05_A = {32768, "57a09d80d2f7ca5b9734edbe9645e6e700f83701", ROMInfo::Control, "ctrl_mt32_1_05_a", "MT-32 Control v1.05", ROMInfo::Mux0, NULL};
|
||||
static ROMInfo CTRL_MT32_V1_05_B = {32768, "52e3c6666db9ef962591a8ee99be0cde17f3a6b6", ROMInfo::Control, "ctrl_mt32_1_05_b", "MT-32 Control v1.05", ROMInfo::Mux1, &CTRL_MT32_V1_05_A};
|
||||
static ROMInfo CTRL_MT32_V1_05 = {65536, "e17a3a6d265bf1fa150312061134293d2b58288c", ROMInfo::Control, "ctrl_mt32_1_05", "MT-32 Control v1.05", ROMInfo::Full, NULL};
|
||||
static ROMInfo CTRL_MT32_V1_06_A = {32768, "cc83bf23cee533097fb4c7e2c116e43b50ebacc8", ROMInfo::Control, "ctrl_mt32_1_06_a", "MT-32 Control v1.06", ROMInfo::Mux0, NULL};
|
||||
static ROMInfo CTRL_MT32_V1_06_B = {32768, "bf4f15666bc46679579498386704893b630c1171", ROMInfo::Control, "ctrl_mt32_1_06_b", "MT-32 Control v1.06", ROMInfo::Mux1, &CTRL_MT32_V1_06_A};
|
||||
static ROMInfo CTRL_MT32_V1_06 = {65536, "a553481f4e2794c10cfe597fef154eef0d8257de", ROMInfo::Control, "ctrl_mt32_1_06", "MT-32 Control v1.06", ROMInfo::Full, NULL};
|
||||
static ROMInfo CTRL_MT32_V1_07_A = {32768, "13f06b38f0d9e0fc050b6503ab777bb938603260", ROMInfo::Control, "ctrl_mt32_1_07_a", "MT-32 Control v1.07", ROMInfo::Mux0, NULL};
|
||||
static ROMInfo CTRL_MT32_V1_07_B = {32768, "c55e165487d71fa88bd8c5e9c083bc456c1a89aa", ROMInfo::Control, "ctrl_mt32_1_07_b", "MT-32 Control v1.07", ROMInfo::Mux1, &CTRL_MT32_V1_07_A};
|
||||
static ROMInfo CTRL_MT32_V1_07 = {65536, "b083518fffb7f66b03c23b7eb4f868e62dc5a987", ROMInfo::Control, "ctrl_mt32_1_07", "MT-32 Control v1.07", ROMInfo::Full, NULL};
|
||||
static ROMInfo CTRL_MT32_BLUER_A = {32768, "11a6ae5d8b6ee328b371af7f1e40b82125aa6b4d", ROMInfo::Control, "ctrl_mt32_bluer_a", "MT-32 Control BlueRidge", ROMInfo::Mux0, NULL};
|
||||
static ROMInfo CTRL_MT32_BLUER_B = {32768, "e0934320d7cbb5edfaa29e0d01ae835ef620085b", ROMInfo::Control, "ctrl_mt32_bluer_b", "MT-32 Control BlueRidge", ROMInfo::Mux1, &CTRL_MT32_BLUER_A};
|
||||
static ROMInfo CTRL_MT32_BLUER = {65536, "7b8c2a5ddb42fd0732e2f22b3340dcf5360edf92", ROMInfo::Control, "ctrl_mt32_bluer", "MT-32 Control BlueRidge", ROMInfo::Full, NULL};
|
||||
|
||||
static const ROMInfo CTRL_MT32_V2_03 = {131072, "5837064c9df4741a55f7c4d8787ac158dff2d3ce", ROMInfo::Control, "ctrl_mt32_2_03", "MT-32 Control v2.03", ROMInfo::Full, NULL};
|
||||
static const ROMInfo CTRL_MT32_V2_04 = {131072, "2c16432b6c73dd2a3947cba950a0f4c19d6180eb", ROMInfo::Control, "ctrl_mt32_2_04", "MT-32 Control v2.04", ROMInfo::Full, NULL};
|
||||
static const ROMInfo CTRL_MT32_V2_06 = {131072, "2869cf4c235d671668cfcb62415e2ce8323ad4ed", ROMInfo::Control, "ctrl_mt32_2_06", "MT-32 Control v2.06", ROMInfo::Full, NULL};
|
||||
static const ROMInfo CTRL_MT32_V2_07 = {131072, "47b52adefedaec475c925e54340e37673c11707c", ROMInfo::Control, "ctrl_mt32_2_07", "MT-32 Control v2.07", ROMInfo::Full, NULL};
|
||||
static const ROMInfo CTRL_CM32L_V1_00 = {65536, "73683d585cd6948cc19547942ca0e14a0319456d", ROMInfo::Control, "ctrl_cm32l_1_00", "CM-32L/LAPC-I Control v1.00", ROMInfo::Full, NULL};
|
||||
static const ROMInfo CTRL_CM32L_V1_02 = {65536, "a439fbb390da38cada95a7cbb1d6ca199cd66ef8", ROMInfo::Control, "ctrl_cm32l_1_02", "CM-32L/LAPC-I Control v1.02", ROMInfo::Full, NULL};
|
||||
static const ROMInfo CTRL_CM32LN_V1_00 = {65536, "dc1c5b1b90a4646d00f7daf3679733c7badc7077", ROMInfo::Control, "ctrl_cm32ln_1_00", "CM-32LN/CM-500/LAPC-N Control v1.00", ROMInfo::Full, NULL};
|
||||
|
||||
static const ROMInfo PCM_MT32 = {524288, "f6b1eebc4b2d200ec6d3d21d51325d5b48c60252", ROMInfo::PCM, "pcm_mt32", "MT-32 PCM ROM", ROMInfo::Full, NULL};
|
||||
static const ROMInfo PCM_CM32L = {1048576, "289cc298ad532b702461bfc738009d9ebe8025ea", ROMInfo::PCM, "pcm_cm32l", "CM-32L/CM-64/LAPC-I PCM ROM", ROMInfo::Full, NULL};
|
||||
static ROMInfo PCM_MT32_L = {262144, "3a1e19b0cd4036623fd1d1d11f5f25995585962b", ROMInfo::PCM, "pcm_mt32_l", "MT-32 PCM ROM", ROMInfo::FirstHalf, NULL};
|
||||
static ROMInfo PCM_MT32_H = {262144, "2cadb99d21a6a4a6f5b61b6218d16e9b43f61d01", ROMInfo::PCM, "pcm_mt32_h", "MT-32 PCM ROM", ROMInfo::SecondHalf, &PCM_MT32_L};
|
||||
static ROMInfo PCM_MT32 = {524288, "f6b1eebc4b2d200ec6d3d21d51325d5b48c60252", ROMInfo::PCM, "pcm_mt32", "MT-32 PCM ROM", ROMInfo::Full, NULL};
|
||||
// Alias of PCM_MT32 ROM, only useful for pairing with PCM_CM32L_H.
|
||||
static ROMInfo PCM_CM32L_L = {524288, "f6b1eebc4b2d200ec6d3d21d51325d5b48c60252", ROMInfo::PCM, "pcm_cm32l_l", "CM-32L/CM-64/LAPC-I PCM ROM", ROMInfo::FirstHalf, NULL};
|
||||
static ROMInfo PCM_CM32L_H = {524288, "3ad889fde5db5b6437cbc2eb6e305312fec3df93", ROMInfo::PCM, "pcm_cm32l_h", "CM-32L/CM-64/LAPC-I PCM ROM", ROMInfo::SecondHalf, &PCM_CM32L_L};
|
||||
static ROMInfo PCM_CM32L = {1048576, "289cc298ad532b702461bfc738009d9ebe8025ea", ROMInfo::PCM, "pcm_cm32l", "CM-32L/CM-64/LAPC-I PCM ROM", ROMInfo::Full, NULL};
|
||||
|
||||
static const ROMInfo * const ROM_INFOS[] = {
|
||||
static const ROMInfo * const FULL_ROM_INFOS[] = {
|
||||
&CTRL_MT32_V1_04,
|
||||
&CTRL_MT32_V1_05,
|
||||
&CTRL_MT32_V1_06,
|
||||
&CTRL_MT32_V1_07,
|
||||
&CTRL_MT32_BLUER,
|
||||
&CTRL_MT32_V2_03,
|
||||
&CTRL_MT32_V2_04,
|
||||
&CTRL_MT32_V2_06,
|
||||
&CTRL_MT32_V2_07,
|
||||
&CTRL_CM32L_V1_00,
|
||||
&CTRL_CM32L_V1_02,
|
||||
&CTRL_CM32LN_V1_00,
|
||||
&PCM_MT32,
|
||||
&PCM_CM32L,
|
||||
NULL};
|
||||
NULL
|
||||
};
|
||||
static const ROMInfo * const PARTIAL_ROM_INFOS[] = {
|
||||
&CTRL_MT32_V1_04_A, &CTRL_MT32_V1_04_B,
|
||||
&CTRL_MT32_V1_05_A, &CTRL_MT32_V1_05_B,
|
||||
&CTRL_MT32_V1_06_A, &CTRL_MT32_V1_06_B,
|
||||
&CTRL_MT32_V1_07_A, &CTRL_MT32_V1_07_B,
|
||||
&CTRL_MT32_BLUER_A, &CTRL_MT32_BLUER_B,
|
||||
&PCM_MT32_L, &PCM_MT32_H,
|
||||
&PCM_CM32L_L, &PCM_CM32L_H,
|
||||
NULL
|
||||
};
|
||||
static const ROMInfo *ALL_ROM_INFOS[_CALC_ARRAY_LENGTH(FULL_ROM_INFOS) + _CALC_ARRAY_LENGTH(PARTIAL_ROM_INFOS) + 1];
|
||||
|
||||
return ROM_INFOS[index];
|
||||
if (CTRL_MT32_V1_04_A.pairROMInfo == NULL) {
|
||||
CTRL_MT32_V1_04_A.pairROMInfo = &CTRL_MT32_V1_04_B;
|
||||
CTRL_MT32_V1_05_A.pairROMInfo = &CTRL_MT32_V1_05_B;
|
||||
CTRL_MT32_V1_06_A.pairROMInfo = &CTRL_MT32_V1_06_B;
|
||||
CTRL_MT32_V1_07_A.pairROMInfo = &CTRL_MT32_V1_07_B;
|
||||
CTRL_MT32_BLUER_A.pairROMInfo = &CTRL_MT32_BLUER_B;
|
||||
PCM_MT32_L.pairROMInfo = &PCM_MT32_H;
|
||||
PCM_CM32L_L.pairROMInfo = &PCM_CM32L_H;
|
||||
|
||||
memcpy(&ALL_ROM_INFOS[0], FULL_ROM_INFOS, sizeof FULL_ROM_INFOS);
|
||||
memcpy(&ALL_ROM_INFOS[_CALC_ARRAY_LENGTH(FULL_ROM_INFOS)], PARTIAL_ROM_INFOS, sizeof PARTIAL_ROM_INFOS); // Includes NULL terminator.
|
||||
}
|
||||
|
||||
static const ROMInfo * const MT32_V1_04_ROMS[] = {&CTRL_MT32_V1_04, &PCM_MT32, &CTRL_MT32_V1_04_A, &CTRL_MT32_V1_04_B, &PCM_MT32_L, &PCM_MT32_H, NULL};
|
||||
static const ROMInfo * const MT32_V1_05_ROMS[] = {&CTRL_MT32_V1_05, &PCM_MT32, &CTRL_MT32_V1_05_A, &CTRL_MT32_V1_05_B, &PCM_MT32_L, &PCM_MT32_H, NULL};
|
||||
static const ROMInfo * const MT32_V1_06_ROMS[] = {&CTRL_MT32_V1_06, &PCM_MT32, &CTRL_MT32_V1_06_A, &CTRL_MT32_V1_06_B, &PCM_MT32_L, &PCM_MT32_H, NULL};
|
||||
static const ROMInfo * const MT32_V1_07_ROMS[] = {&CTRL_MT32_V1_07, &PCM_MT32, &CTRL_MT32_V1_07_A, &CTRL_MT32_V1_07_B, &PCM_MT32_L, &PCM_MT32_H, NULL};
|
||||
static const ROMInfo * const MT32_BLUER_ROMS[] = {&CTRL_MT32_BLUER, &PCM_MT32, &CTRL_MT32_BLUER_A, &CTRL_MT32_BLUER_B, &PCM_MT32_L, &PCM_MT32_H, NULL};
|
||||
static const ROMInfo * const MT32_V2_03_ROMS[] = {&CTRL_MT32_V2_03, &PCM_MT32, &PCM_MT32_L, &PCM_MT32_H, NULL};
|
||||
static const ROMInfo * const MT32_V2_04_ROMS[] = {&CTRL_MT32_V2_04, &PCM_MT32, &PCM_MT32_L, &PCM_MT32_H, NULL};
|
||||
static const ROMInfo * const MT32_V2_06_ROMS[] = {&CTRL_MT32_V2_06, &PCM_MT32, &PCM_MT32_L, &PCM_MT32_H, NULL};
|
||||
static const ROMInfo * const MT32_V2_07_ROMS[] = {&CTRL_MT32_V2_07, &PCM_MT32, &PCM_MT32_L, &PCM_MT32_H, NULL};
|
||||
static const ROMInfo * const CM32L_V1_00_ROMS[] = {&CTRL_CM32L_V1_00, &PCM_CM32L, &PCM_CM32L_L, &PCM_CM32L_H, NULL};
|
||||
static const ROMInfo * const CM32L_V1_02_ROMS[] = {&CTRL_CM32L_V1_02, &PCM_CM32L, &PCM_CM32L_L, &PCM_CM32L_H, NULL};
|
||||
static const ROMInfo * const CM32LN_V1_00_ROMS[] = {&CTRL_CM32LN_V1_00, &PCM_CM32L, NULL};
|
||||
|
||||
static const ROMInfoLists romInfoLists = {
|
||||
{MT32_V1_04_ROMS, _CALC_ARRAY_LENGTH(MT32_V1_04_ROMS)},
|
||||
{MT32_V1_05_ROMS, _CALC_ARRAY_LENGTH(MT32_V1_05_ROMS)},
|
||||
{MT32_V1_06_ROMS, _CALC_ARRAY_LENGTH(MT32_V1_06_ROMS)},
|
||||
{MT32_V1_07_ROMS, _CALC_ARRAY_LENGTH(MT32_V1_07_ROMS)},
|
||||
{MT32_BLUER_ROMS, _CALC_ARRAY_LENGTH(MT32_BLUER_ROMS)},
|
||||
{MT32_V2_03_ROMS, _CALC_ARRAY_LENGTH(MT32_V2_03_ROMS)},
|
||||
{MT32_V2_04_ROMS, _CALC_ARRAY_LENGTH(MT32_V2_04_ROMS)},
|
||||
{MT32_V2_06_ROMS, _CALC_ARRAY_LENGTH(MT32_V2_06_ROMS)},
|
||||
{MT32_V2_07_ROMS, _CALC_ARRAY_LENGTH(MT32_V2_07_ROMS)},
|
||||
{CM32L_V1_00_ROMS, _CALC_ARRAY_LENGTH(CM32L_V1_00_ROMS)},
|
||||
{CM32L_V1_02_ROMS, _CALC_ARRAY_LENGTH(CM32L_V1_02_ROMS)},
|
||||
{CM32LN_V1_00_ROMS, _CALC_ARRAY_LENGTH(CM32LN_V1_00_ROMS)},
|
||||
{FULL_ROM_INFOS, _CALC_ARRAY_LENGTH(FULL_ROM_INFOS)},
|
||||
{PARTIAL_ROM_INFOS, _CALC_ARRAY_LENGTH(PARTIAL_ROM_INFOS)},
|
||||
{ALL_ROM_INFOS, _CALC_ARRAY_LENGTH(ALL_ROM_INFOS)}
|
||||
};
|
||||
return romInfoLists;
|
||||
}
|
||||
|
||||
const ROMInfo* ROMInfo::getROMInfo(File *file) {
|
||||
static const ROMInfo * const *getKnownROMInfoList() {
|
||||
return getROMInfoLists().allROMInfos.romInfos;
|
||||
}
|
||||
|
||||
static const ROMInfo *getKnownROMInfoFromList(Bit32u index) {
|
||||
return getKnownROMInfoList()[index];
|
||||
}
|
||||
|
||||
const ROMInfo *ROMInfo::getROMInfo(File *file) {
|
||||
return getROMInfo(file, getKnownROMInfoList());
|
||||
}
|
||||
|
||||
const ROMInfo *ROMInfo::getROMInfo(File *file, const ROMInfo * const *romInfos) {
|
||||
size_t fileSize = file->getSize();
|
||||
for (Bit32u i = 0; getKnownROMInfoFromList(i) != NULL; i++) {
|
||||
const ROMInfo *romInfo = getKnownROMInfoFromList(i);
|
||||
for (Bit32u i = 0; romInfos[i] != NULL; i++) {
|
||||
const ROMInfo *romInfo = romInfos[i];
|
||||
if (fileSize == romInfo->fileSize && !strcmp(file->getSHA1(), romInfo->sha1Digest)) {
|
||||
return romInfo;
|
||||
}
|
||||
@@ -69,17 +188,11 @@ void ROMInfo::freeROMInfo(const ROMInfo *romInfo) {
|
||||
(void) romInfo;
|
||||
}
|
||||
|
||||
static Bit32u getROMCount() {
|
||||
Bit32u count;
|
||||
for(count = 0; getKnownROMInfoFromList(count) != NULL; count++) {
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
const ROMInfo** ROMInfo::getROMInfoList(Bit32u types, Bit32u pairTypes) {
|
||||
const ROMInfo **romInfoList = new const ROMInfo*[getROMCount() + 1];
|
||||
const ROMInfo **ROMInfo::getROMInfoList(Bit32u types, Bit32u pairTypes) {
|
||||
Bit32u romCount = getROMInfoLists().allROMInfos.itemCount; // Excludes the NULL terminator.
|
||||
const ROMInfo **romInfoList = new const ROMInfo*[romCount + 1];
|
||||
const ROMInfo **currentROMInList = romInfoList;
|
||||
for (Bit32u i = 0; getKnownROMInfoFromList(i) != NULL; i++) {
|
||||
for (Bit32u i = 0; i < romCount; i++) {
|
||||
const ROMInfo *romInfo = getKnownROMInfoFromList(i);
|
||||
if ((types & (1 << romInfo->type)) && (pairTypes & (1 << romInfo->pairType))) {
|
||||
*currentROMInList++ = romInfo;
|
||||
@@ -93,27 +206,157 @@ void ROMInfo::freeROMInfoList(const ROMInfo **romInfoList) {
|
||||
delete[] romInfoList;
|
||||
}
|
||||
|
||||
ROMImage::ROMImage(File *useFile) : file(useFile), romInfo(ROMInfo::getROMInfo(file))
|
||||
const ROMInfo * const *ROMInfo::getAllROMInfos(Bit32u *itemCount) {
|
||||
if (itemCount != NULL) *itemCount = getROMInfoLists().allROMInfos.itemCount;
|
||||
return getROMInfoLists().allROMInfos.romInfos;
|
||||
}
|
||||
|
||||
const ROMInfo * const *ROMInfo::getFullROMInfos(Bit32u *itemCount) {
|
||||
if (itemCount != NULL) *itemCount = getROMInfoLists().fullROMInfos.itemCount;
|
||||
return getROMInfoLists().fullROMInfos.romInfos;
|
||||
}
|
||||
|
||||
const ROMInfo * const *ROMInfo::getPartialROMInfos(Bit32u *itemCount) {
|
||||
if (itemCount != NULL) *itemCount = getROMInfoLists().partialROMInfos.itemCount;
|
||||
return getROMInfoLists().partialROMInfos.romInfos;
|
||||
}
|
||||
|
||||
const ROMImage *ROMImage::makeFullROMImage(Bit8u *data, size_t dataSize) {
|
||||
return new ROMImage(new ArrayFile(data, dataSize), true, getKnownROMInfoList());
|
||||
}
|
||||
|
||||
const ROMImage *ROMImage::appendImages(const ROMImage *romImageLow, const ROMImage *romImageHigh) {
|
||||
const Bit8u *romDataLow = romImageLow->getFile()->getData();
|
||||
const Bit8u *romDataHigh = romImageHigh->getFile()->getData();
|
||||
size_t partSize = romImageLow->getFile()->getSize();
|
||||
Bit8u *data = new Bit8u[2 * partSize];
|
||||
memcpy(data, romDataLow, partSize);
|
||||
memcpy(data + partSize, romDataHigh, partSize);
|
||||
const ROMImage *romImageFull = makeFullROMImage(data, 2 * partSize);
|
||||
if (romImageFull->getROMInfo() == NULL) {
|
||||
freeROMImage(romImageFull);
|
||||
return NULL;
|
||||
}
|
||||
return romImageFull;
|
||||
}
|
||||
|
||||
const ROMImage *ROMImage::interleaveImages(const ROMImage *romImageEven, const ROMImage *romImageOdd) {
|
||||
const Bit8u *romDataEven = romImageEven->getFile()->getData();
|
||||
const Bit8u *romDataOdd = romImageOdd->getFile()->getData();
|
||||
size_t partSize = romImageEven->getFile()->getSize();
|
||||
Bit8u *data = new Bit8u[2 * partSize];
|
||||
Bit8u *writePtr = data;
|
||||
for (size_t romDataIx = 0; romDataIx < partSize; romDataIx++) {
|
||||
*(writePtr++) = romDataEven[romDataIx];
|
||||
*(writePtr++) = romDataOdd[romDataIx];
|
||||
}
|
||||
const ROMImage *romImageFull = makeFullROMImage(data, 2 * partSize);
|
||||
if (romImageFull->getROMInfo() == NULL) {
|
||||
freeROMImage(romImageFull);
|
||||
return NULL;
|
||||
}
|
||||
return romImageFull;
|
||||
}
|
||||
|
||||
ROMImage::ROMImage(File *useFile, bool useOwnFile, const ROMInfo * const *romInfos) :
|
||||
file(useFile), ownFile(useOwnFile), romInfo(ROMInfo::getROMInfo(file, romInfos))
|
||||
{}
|
||||
|
||||
ROMImage::~ROMImage() {
|
||||
ROMInfo::freeROMInfo(romInfo);
|
||||
if (ownFile) {
|
||||
const Bit8u *data = file->getData();
|
||||
delete file;
|
||||
delete[] data;
|
||||
}
|
||||
}
|
||||
|
||||
const ROMImage* ROMImage::makeROMImage(File *file) {
|
||||
return new ROMImage(file);
|
||||
const ROMImage *ROMImage::makeROMImage(File *file) {
|
||||
return new ROMImage(file, false, getKnownROMInfoList());
|
||||
}
|
||||
|
||||
const ROMImage *ROMImage::makeROMImage(File *file, const ROMInfo * const *romInfos) {
|
||||
return new ROMImage(file, false, romInfos);
|
||||
}
|
||||
|
||||
const ROMImage *ROMImage::makeROMImage(File *file1, File *file2) {
|
||||
const ROMInfo * const *partialROMInfos = getROMInfoLists().partialROMInfos.romInfos;
|
||||
const ROMImage *image1 = makeROMImage(file1, partialROMInfos);
|
||||
const ROMImage *image2 = makeROMImage(file2, partialROMInfos);
|
||||
const ROMImage *fullImage = image1->getROMInfo() == NULL || image2->getROMInfo() == NULL ? NULL : mergeROMImages(image1, image2);
|
||||
freeROMImage(image1);
|
||||
freeROMImage(image2);
|
||||
return fullImage;
|
||||
}
|
||||
|
||||
void ROMImage::freeROMImage(const ROMImage *romImage) {
|
||||
delete romImage;
|
||||
}
|
||||
|
||||
File* ROMImage::getFile() const {
|
||||
const ROMImage *ROMImage::mergeROMImages(const ROMImage *romImage1, const ROMImage *romImage2) {
|
||||
if (romImage1->romInfo->pairROMInfo != romImage2->romInfo) {
|
||||
return NULL;
|
||||
}
|
||||
switch (romImage1->romInfo->pairType) {
|
||||
case ROMInfo::FirstHalf:
|
||||
return appendImages(romImage1, romImage2);
|
||||
case ROMInfo::SecondHalf:
|
||||
return appendImages(romImage2, romImage1);
|
||||
case ROMInfo::Mux0:
|
||||
return interleaveImages(romImage1, romImage2);
|
||||
case ROMInfo::Mux1:
|
||||
return interleaveImages(romImage2, romImage1);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
File *ROMImage::getFile() const {
|
||||
return file;
|
||||
}
|
||||
|
||||
const ROMInfo* ROMImage::getROMInfo() const {
|
||||
bool ROMImage::isFileUserProvided() const {
|
||||
return !ownFile;
|
||||
}
|
||||
|
||||
const ROMInfo *ROMImage::getROMInfo() const {
|
||||
return romInfo;
|
||||
}
|
||||
|
||||
const MachineConfiguration * const *MachineConfiguration::getAllMachineConfigurations(Bit32u *itemCount) {
|
||||
static const ROMInfoLists &romInfoLists = getROMInfoLists();
|
||||
static const MachineConfiguration MT32_1_04 = MachineConfiguration("mt32_1_04", romInfoLists.mt32_1_04.romInfos, romInfoLists.mt32_1_04.itemCount);
|
||||
static const MachineConfiguration MT32_1_05 = MachineConfiguration("mt32_1_05", romInfoLists.mt32_1_05.romInfos, romInfoLists.mt32_1_05.itemCount);
|
||||
static const MachineConfiguration MT32_1_06 = MachineConfiguration("mt32_1_06", romInfoLists.mt32_1_06.romInfos, romInfoLists.mt32_1_06.itemCount);
|
||||
static const MachineConfiguration MT32_1_07 = MachineConfiguration("mt32_1_07", romInfoLists.mt32_1_07.romInfos, romInfoLists.mt32_1_07.itemCount);
|
||||
static const MachineConfiguration MT32_BLUER = MachineConfiguration("mt32_bluer", romInfoLists.mt32_bluer.romInfos, romInfoLists.mt32_bluer.itemCount);
|
||||
static const MachineConfiguration MT32_2_03 = MachineConfiguration("mt32_2_03", romInfoLists.mt32_2_03.romInfos, romInfoLists.mt32_2_03.itemCount);
|
||||
static const MachineConfiguration MT32_2_04 = MachineConfiguration("mt32_2_04", romInfoLists.mt32_2_04.romInfos, romInfoLists.mt32_2_04.itemCount);
|
||||
static const MachineConfiguration MT32_2_06 = MachineConfiguration("mt32_2_06", romInfoLists.mt32_2_06.romInfos, romInfoLists.mt32_2_06.itemCount);
|
||||
static const MachineConfiguration MT32_2_07 = MachineConfiguration("mt32_2_07", romInfoLists.mt32_2_07.romInfos, romInfoLists.mt32_2_07.itemCount);
|
||||
static const MachineConfiguration CM32L_1_00 = MachineConfiguration("cm32l_1_00", romInfoLists.cm32l_1_00.romInfos, romInfoLists.cm32l_1_00.itemCount);
|
||||
static const MachineConfiguration CM32L_1_02 = MachineConfiguration("cm32l_1_02", romInfoLists.cm32l_1_02.romInfos, romInfoLists.cm32l_1_02.itemCount);
|
||||
static const MachineConfiguration CM32LN_1_00 = MachineConfiguration("cm32ln_1_00", romInfoLists.cm32ln_1_00.romInfos, romInfoLists.cm32ln_1_00.itemCount);
|
||||
static const MachineConfiguration * const MACHINE_CONFIGURATIONS[] = {
|
||||
&MT32_1_04, &MT32_1_05, &MT32_1_06, &MT32_1_07, &MT32_BLUER, &MT32_2_03, &MT32_2_04, &MT32_2_06, &MT32_2_07, &CM32L_1_00, &CM32L_1_02, &CM32LN_1_00, NULL
|
||||
};
|
||||
|
||||
if (itemCount != NULL) *itemCount = _CALC_ARRAY_LENGTH(MACHINE_CONFIGURATIONS);
|
||||
return MACHINE_CONFIGURATIONS;
|
||||
}
|
||||
|
||||
MachineConfiguration::MachineConfiguration(const char *useMachineID, const ROMInfo * const *useROMInfos, Bit32u useROMInfosCount) :
|
||||
machineID(useMachineID), romInfos(useROMInfos), romInfosCount(useROMInfosCount)
|
||||
{}
|
||||
|
||||
const char *MachineConfiguration::getMachineID() const {
|
||||
return machineID;
|
||||
}
|
||||
|
||||
const ROMInfo * const *MachineConfiguration::getCompatibleROMInfos(Bit32u *itemCount) const {
|
||||
if (itemCount != NULL) *itemCount = romInfosCount;
|
||||
return romInfos;
|
||||
}
|
||||
|
||||
} // namespace MT32Emu
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
@@ -34,11 +34,28 @@ public:
|
||||
enum Type {PCM, Control, Reverb} type;
|
||||
const char *shortName;
|
||||
const char *description;
|
||||
enum PairType {Full, FirstHalf, SecondHalf, Mux0, Mux1} pairType;
|
||||
ROMInfo *pairROMInfo;
|
||||
enum PairType {
|
||||
// Complete ROM image ready to use with Synth.
|
||||
Full,
|
||||
// ROM image contains data that occupies lower addresses. Needs pairing before use.
|
||||
FirstHalf,
|
||||
// ROM image contains data that occupies higher addresses. Needs pairing before use.
|
||||
SecondHalf,
|
||||
// ROM image contains data that occupies even addresses. Needs pairing before use.
|
||||
Mux0,
|
||||
// ROM image contains data that occupies odd addresses. Needs pairing before use.
|
||||
Mux1
|
||||
} pairType;
|
||||
// NULL for Full images or a pointer to the corresponding other image for pairing.
|
||||
const ROMInfo *pairROMInfo;
|
||||
|
||||
// Returns a ROMInfo struct by inspecting the size and the SHA1 hash
|
||||
MT32EMU_EXPORT static const ROMInfo* getROMInfo(File *file);
|
||||
// Returns a ROMInfo struct by inspecting the size and the SHA1 hash of the file
|
||||
// among all the known ROMInfos.
|
||||
MT32EMU_EXPORT static const ROMInfo *getROMInfo(File *file);
|
||||
|
||||
// Returns a ROMInfo struct by inspecting the size and the SHA1 hash of the file
|
||||
// among the ROMInfos listed in the NULL-terminated list romInfos.
|
||||
MT32EMU_EXPORT_V(2.5) static const ROMInfo *getROMInfo(File *file, const ROMInfo * const *romInfos);
|
||||
|
||||
// Currently no-op
|
||||
MT32EMU_EXPORT static void freeROMInfo(const ROMInfo *romInfo);
|
||||
@@ -46,33 +63,111 @@ public:
|
||||
// Allows retrieving a NULL-terminated list of ROMInfos for a range of types and pairTypes
|
||||
// (specified by bitmasks)
|
||||
// Useful for GUI/console app to output information on what ROMs it supports
|
||||
MT32EMU_EXPORT static const ROMInfo** getROMInfoList(Bit32u types, Bit32u pairTypes);
|
||||
// The caller must free the returned list with freeROMInfoList when finished.
|
||||
MT32EMU_EXPORT static const ROMInfo **getROMInfoList(Bit32u types, Bit32u pairTypes);
|
||||
|
||||
// Frees the list of ROMInfos given
|
||||
// Frees the list of ROMInfos given that has been created by getROMInfoList.
|
||||
MT32EMU_EXPORT static void freeROMInfoList(const ROMInfo **romInfos);
|
||||
|
||||
// Returns an immutable NULL-terminated list of all (full and partial) supported ROMInfos.
|
||||
// For convenience, this method also can fill the number of non-NULL items present in the list
|
||||
// if a non-NULL value is provided in optional argument itemCount.
|
||||
MT32EMU_EXPORT_V(2.5) static const ROMInfo * const *getAllROMInfos(Bit32u *itemCount = NULL);
|
||||
// Returns an immutable NULL-terminated list of all supported full ROMInfos.
|
||||
// For convenience, this method also can fill the number of non-NULL items present in the list
|
||||
// if a non-NULL value is provided in optional argument itemCount.
|
||||
MT32EMU_EXPORT_V(2.5) static const ROMInfo * const *getFullROMInfos(Bit32u *itemCount = NULL);
|
||||
// Returns an immutable NULL-terminated list of all supported partial ROMInfos.
|
||||
// For convenience, this method also can fill the number of non-NULL items present in the list
|
||||
// if a non-NULL value is provided in optional argument itemCount.
|
||||
MT32EMU_EXPORT_V(2.5) static const ROMInfo * const *getPartialROMInfos(Bit32u *itemCount = NULL);
|
||||
};
|
||||
|
||||
// Synth::open() is to require a full control ROMImage and a full PCM ROMImage to work
|
||||
// Synth::open() requires a full control ROMImage and a compatible full PCM ROMImage to work
|
||||
|
||||
class ROMImage {
|
||||
private:
|
||||
File * const file;
|
||||
const ROMInfo * const romInfo;
|
||||
|
||||
ROMImage(File *file);
|
||||
~ROMImage();
|
||||
|
||||
public:
|
||||
// Creates a ROMImage object given a ROMInfo and a File. Keeps a reference
|
||||
// to the File and ROMInfo given, which must be freed separately by the user
|
||||
// after the ROMImage is freed
|
||||
MT32EMU_EXPORT static const ROMImage* makeROMImage(File *file);
|
||||
// after the ROMImage is freed.
|
||||
// CAVEAT: This method always prefers full ROM images over partial ones.
|
||||
// Because the lower half of CM-32L/CM-64/LAPC-I PCM ROM is essentially the full
|
||||
// MT-32 PCM ROM, it is therefore aliased. In this case a partial image can only be
|
||||
// created by the overridden method makeROMImage(File *, const ROMInfo * const *).
|
||||
MT32EMU_EXPORT static const ROMImage *makeROMImage(File *file);
|
||||
|
||||
// Same as the method above but only permits creation of a ROMImage if the file content
|
||||
// matches one of the ROMs described in a NULL-terminated list romInfos. This list can be
|
||||
// created using e.g. method ROMInfo::getROMInfoList.
|
||||
MT32EMU_EXPORT_V(2.5) static const ROMImage *makeROMImage(File *file, const ROMInfo * const *romInfos);
|
||||
|
||||
// Creates a ROMImage object given a couple of files that contain compatible partial ROM images.
|
||||
// The files aren't referenced by the resulting ROMImage and may be freed anytime afterwards.
|
||||
// The file in the resulting image will be automatically freed along with the ROMImage.
|
||||
// If the given files contain incompatible partial images, NULL is returned.
|
||||
MT32EMU_EXPORT_V(2.5) static const ROMImage *makeROMImage(File *file1, File *file2);
|
||||
|
||||
// Must only be done after all Synths using the ROMImage are deleted
|
||||
MT32EMU_EXPORT static void freeROMImage(const ROMImage *romImage);
|
||||
|
||||
// Checks whether the given ROMImages are pairable and merges them into a full image, if possible.
|
||||
// If the check fails, NULL is returned.
|
||||
MT32EMU_EXPORT_V(2.5) static const ROMImage *mergeROMImages(const ROMImage *romImage1, const ROMImage *romImage2);
|
||||
|
||||
MT32EMU_EXPORT File *getFile() const;
|
||||
|
||||
// Returns true in case this ROMImage is built with a user provided File that has to be deallocated separately.
|
||||
// For a ROMImage created via merging two partial ROMImages, this method returns false.
|
||||
MT32EMU_EXPORT_V(2.5) bool isFileUserProvided() const;
|
||||
MT32EMU_EXPORT const ROMInfo *getROMInfo() const;
|
||||
|
||||
private:
|
||||
static const ROMImage *makeFullROMImage(Bit8u *data, size_t dataSize);
|
||||
static const ROMImage *appendImages(const ROMImage *romImageLow, const ROMImage *romImageHigh);
|
||||
static const ROMImage *interleaveImages(const ROMImage *romImageEven, const ROMImage *romImageOdd);
|
||||
|
||||
File * const file;
|
||||
const bool ownFile;
|
||||
const ROMInfo * const romInfo;
|
||||
|
||||
ROMImage(File *file, bool ownFile, const ROMInfo * const *romInfos);
|
||||
~ROMImage();
|
||||
|
||||
// Make ROMIMage an identity class.
|
||||
ROMImage(const ROMImage &);
|
||||
ROMImage &operator=(const ROMImage &);
|
||||
};
|
||||
|
||||
class MachineConfiguration {
|
||||
public:
|
||||
// Returns an immutable NULL-terminated list of all supported machine configurations.
|
||||
// For convenience, this method also can fill the number of non-NULL items present in the list
|
||||
// if a non-NULL value is provided in optional argument itemCount.
|
||||
MT32EMU_EXPORT_V(2.5) static const MachineConfiguration * const *getAllMachineConfigurations(Bit32u *itemCount = NULL);
|
||||
|
||||
// Returns a string identifier of this MachineConfiguration.
|
||||
MT32EMU_EXPORT_V(2.5) const char *getMachineID() const;
|
||||
|
||||
// Returns an immutable NULL-terminated list of ROMInfos that are compatible with this
|
||||
// MachineConfiguration. That means the respective ROMImages can be successfully used together
|
||||
// by the emulation engine. Calling ROMInfo::getROMInfo or ROMImage::makeROMImage with this list
|
||||
// supplied enables identification of all files containing desired ROM images while filtering out
|
||||
// any incompatible ones.
|
||||
// For convenience, this method also can fill the number of non-NULL items present in the list
|
||||
// if a non-NULL value is provided in optional argument itemCount.
|
||||
MT32EMU_EXPORT_V(2.5) const ROMInfo * const *getCompatibleROMInfos(Bit32u *itemCount = NULL) const;
|
||||
|
||||
private:
|
||||
const char * const machineID;
|
||||
const ROMInfo * const * const romInfos;
|
||||
const Bit32u romInfosCount;
|
||||
|
||||
MachineConfiguration(const char *machineID, const ROMInfo * const *romInfos, Bit32u romInfosCount);
|
||||
|
||||
// Make MachineConfiguration an identity class.
|
||||
MachineConfiguration(const MachineConfiguration &);
|
||||
~MachineConfiguration() {}
|
||||
MachineConfiguration &operator=(const MachineConfiguration &);
|
||||
};
|
||||
|
||||
} // namespace MT32Emu
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2015-2020 Sergey V. Mikayev
|
||||
/* Copyright (C) 2015-2022 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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2015-2020 Sergey V. Mikayev
|
||||
/* Copyright (C) 2015-2022 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
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
/* Copyright (C) 2015-2017 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 <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <86box/plat.h>
|
||||
#include "SampleRateConverter.h"
|
||||
|
||||
#include "Synth.h"
|
||||
|
||||
using namespace MT32Emu;
|
||||
|
||||
static inline void *createDelegate(UNUSED(Synth &synth), UNUSED(double targetSampleRate), UNUSED(SamplerateConversionQuality quality)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
AnalogOutputMode SampleRateConverter::getBestAnalogOutputMode(UNUSED(double targetSampleRate)) {
|
||||
return AnalogOutputMode_COARSE;
|
||||
}
|
||||
|
||||
SampleRateConverter::SampleRateConverter(Synth &useSynth, double targetSampleRate, SamplerateConversionQuality useQuality) :
|
||||
synthInternalToTargetSampleRateRatio(SAMPLE_RATE / targetSampleRate),
|
||||
useSynthDelegate(useSynth.getStereoOutputSampleRate() == targetSampleRate),
|
||||
srcDelegate(useSynthDelegate ? &useSynth : createDelegate(useSynth, targetSampleRate, useQuality))
|
||||
{}
|
||||
|
||||
SampleRateConverter::~SampleRateConverter() {
|
||||
}
|
||||
|
||||
void SampleRateConverter::getOutputSamples(float *buffer, unsigned int length) {
|
||||
if (useSynthDelegate) {
|
||||
static_cast<Synth *>(srcDelegate)->render(buffer, length);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void SampleRateConverter::getOutputSamples(Bit16s *outBuffer, unsigned int length) {
|
||||
if (useSynthDelegate) {
|
||||
static_cast<Synth *>(srcDelegate)->render(outBuffer, length);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
double SampleRateConverter::convertOutputToSynthTimestamp(double outputTimestamp) const {
|
||||
return outputTimestamp * synthInternalToTargetSampleRateRatio;
|
||||
}
|
||||
|
||||
double SampleRateConverter::convertSynthToOutputTimestamp(double synthTimestamp) const {
|
||||
return synthTimestamp / synthInternalToTargetSampleRateRatio;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
@@ -191,6 +191,9 @@ struct ControlROMFeatureSet {
|
||||
unsigned int quirkPanMult : 1;
|
||||
unsigned int quirkKeyShift : 1;
|
||||
unsigned int quirkTVFBaseCutoffLimit : 1;
|
||||
unsigned int quirkFastPitchChanges : 1;
|
||||
unsigned int quirkDisplayCustomMessagePriority : 1;
|
||||
unsigned int oldMT32DisplayFeatures : 1;
|
||||
|
||||
// Features below don't actually depend on control ROM version, which is used to identify hardware model
|
||||
unsigned int defaultReverbMT32Compatible : 1;
|
||||
@@ -221,6 +224,8 @@ struct ControlROMMap {
|
||||
Bit16u timbreMaxTable; // 72 bytes
|
||||
Bit16u soundGroupsTable; // 14 bytes each entry
|
||||
Bit16u soundGroupsCount;
|
||||
Bit16u startupMessage; // 20 characters + NULL terminator
|
||||
Bit16u sysexErrorMessage; // 20 characters + NULL terminator
|
||||
};
|
||||
|
||||
struct ControlROMPCMStruct {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "Synth.h"
|
||||
#include "Analog.h"
|
||||
#include "BReverbModel.h"
|
||||
#include "Display.h"
|
||||
#include "File.h"
|
||||
#include "MemoryRegion.h"
|
||||
#include "MidiEventQueue.h"
|
||||
@@ -41,19 +42,35 @@ namespace MT32Emu {
|
||||
// MIDI interface data transfer rate in samples. Used to simulate the transfer delay.
|
||||
static const double MIDI_DATA_TRANSFER_RATE = double(SAMPLE_RATE) / 31250.0 * 8.0;
|
||||
|
||||
// FIXME: there should be more specific feature sets for various MT-32 control ROM versions
|
||||
static const ControlROMFeatureSet OLD_MT32_COMPATIBLE = {
|
||||
true, // quirkBasePitchOverflow
|
||||
true, // quirkPitchEnvelopeOverflow
|
||||
true, // quirkRingModulationNoMix
|
||||
true, // quirkTVAZeroEnvLevels
|
||||
true, // quirkPanMult
|
||||
true, // quirkKeyShift
|
||||
true, // quirkTVFBaseCutoffLimit
|
||||
true, // defaultReverbMT32Compatible
|
||||
true // oldMT32AnalogLPF
|
||||
static const ControlROMFeatureSet OLD_MT32_ELDER = {
|
||||
true, // quirkBasePitchOverflow
|
||||
true, // quirkPitchEnvelopeOverflow
|
||||
true, // quirkRingModulationNoMix
|
||||
true, // quirkTVAZeroEnvLevels
|
||||
true, // quirkPanMult
|
||||
true, // quirkKeyShift
|
||||
true, // quirkTVFBaseCutoffLimit
|
||||
false, // quirkFastPitchChanges
|
||||
true, // quirkDisplayCustomMessagePriority
|
||||
true, // oldMT32DisplayFeatures
|
||||
true, // defaultReverbMT32Compatible
|
||||
true // oldMT32AnalogLPF
|
||||
};
|
||||
static const ControlROMFeatureSet CM32L_COMPATIBLE = {
|
||||
static const ControlROMFeatureSet OLD_MT32_LATER = {
|
||||
true, // quirkBasePitchOverflow
|
||||
true, // quirkPitchEnvelopeOverflow
|
||||
true, // quirkRingModulationNoMix
|
||||
true, // quirkTVAZeroEnvLevels
|
||||
true, // quirkPanMult
|
||||
true, // quirkKeyShift
|
||||
true, // quirkTVFBaseCutoffLimit
|
||||
false, // quirkFastPitchChanges
|
||||
false, // quirkDisplayCustomMessagePriority
|
||||
true, // oldMT32DisplayFeatures
|
||||
true, // defaultReverbMT32Compatible
|
||||
true // oldMT32AnalogLPF
|
||||
};
|
||||
static const ControlROMFeatureSet NEW_MT32_COMPATIBLE = {
|
||||
false, // quirkBasePitchOverflow
|
||||
false, // quirkPitchEnvelopeOverflow
|
||||
false, // quirkRingModulationNoMix
|
||||
@@ -61,20 +78,41 @@ static const ControlROMFeatureSet CM32L_COMPATIBLE = {
|
||||
false, // quirkPanMult
|
||||
false, // quirkKeyShift
|
||||
false, // quirkTVFBaseCutoffLimit
|
||||
false, // quirkFastPitchChanges
|
||||
false, // quirkDisplayCustomMessagePriority
|
||||
false, // oldMT32DisplayFeatures
|
||||
false, // defaultReverbMT32Compatible
|
||||
false // oldMT32AnalogLPF
|
||||
false // oldMT32AnalogLPF
|
||||
};
|
||||
static const ControlROMFeatureSet CM32LN_COMPATIBLE = {
|
||||
false, // quirkBasePitchOverflow
|
||||
false, // quirkPitchEnvelopeOverflow
|
||||
false, // quirkRingModulationNoMix
|
||||
false, // quirkTVAZeroEnvLevels
|
||||
false, // quirkPanMult
|
||||
false, // quirkKeyShift
|
||||
false, // quirkTVFBaseCutoffLimit
|
||||
true, // quirkFastPitchChanges
|
||||
false, // quirkDisplayCustomMessagePriority
|
||||
false, // oldMT32DisplayFeatures
|
||||
false, // defaultReverbMT32Compatible
|
||||
false // oldMT32AnalogLPF
|
||||
};
|
||||
|
||||
static const ControlROMMap ControlROMMaps[8] = {
|
||||
// ID Features PCMmap PCMc tmbrA tmbrAO, tmbrAC tmbrB tmbrBO tmbrBC tmbrR trC rhythm rhyC rsrv panpot prog rhyMax patMax sysMax timMax sndGrp sGC
|
||||
{ "ctrl_mt32_1_04", OLD_MT32_COMPATIBLE, 0x3000, 128, 0x8000, 0x0000, false, 0xC000, 0x4000, false, 0x3200, 30, 0x73A6, 85, 0x57C7, 0x57E2, 0x57D0, 0x5252, 0x525E, 0x526E, 0x520A, 0x7064, 19 },
|
||||
{ "ctrl_mt32_1_05", OLD_MT32_COMPATIBLE, 0x3000, 128, 0x8000, 0x0000, false, 0xC000, 0x4000, false, 0x3200, 30, 0x7414, 85, 0x57C7, 0x57E2, 0x57D0, 0x5252, 0x525E, 0x526E, 0x520A, 0x70CA, 19 },
|
||||
{ "ctrl_mt32_1_06", OLD_MT32_COMPATIBLE, 0x3000, 128, 0x8000, 0x0000, false, 0xC000, 0x4000, false, 0x3200, 30, 0x7414, 85, 0x57D9, 0x57F4, 0x57E2, 0x5264, 0x5270, 0x5280, 0x521C, 0x70CA, 19 },
|
||||
{ "ctrl_mt32_1_07", OLD_MT32_COMPATIBLE, 0x3000, 128, 0x8000, 0x0000, false, 0xC000, 0x4000, false, 0x3200, 30, 0x73fe, 85, 0x57B1, 0x57CC, 0x57BA, 0x523C, 0x5248, 0x5258, 0x51F4, 0x70B0, 19 }, // MT-32 revision 1
|
||||
{"ctrl_mt32_bluer", OLD_MT32_COMPATIBLE, 0x3000, 128, 0x8000, 0x0000, false, 0xC000, 0x4000, false, 0x3200, 30, 0x741C, 85, 0x57E5, 0x5800, 0x57EE, 0x5270, 0x527C, 0x528C, 0x5228, 0x70CE, 19 }, // MT-32 Blue Ridge mod
|
||||
{"ctrl_mt32_2_04", CM32L_COMPATIBLE, 0x8100, 128, 0x8000, 0x8000, true, 0x8080, 0x8000, true, 0x8500, 30, 0x8580, 85, 0x4F5D, 0x4F78, 0x4F66, 0x4899, 0x489D, 0x48B6, 0x48CD, 0x5A58, 19 },
|
||||
{"ctrl_cm32l_1_00", CM32L_COMPATIBLE, 0x8100, 256, 0x8000, 0x8000, true, 0x8080, 0x8000, true, 0x8500, 64, 0x8580, 85, 0x4F65, 0x4F80, 0x4F6E, 0x48A1, 0x48A5, 0x48BE, 0x48D5, 0x5A6C, 19 },
|
||||
{"ctrl_cm32l_1_02", CM32L_COMPATIBLE, 0x8100, 256, 0x8000, 0x8000, true, 0x8080, 0x8000, true, 0x8500, 64, 0x8580, 85, 0x4F93, 0x4FAE, 0x4F9C, 0x48CB, 0x48CF, 0x48E8, 0x48FF, 0x5A96, 19 } // CM-32L
|
||||
static const ControlROMMap ControlROMMaps[] = {
|
||||
// ID Features PCMmap PCMc tmbrA tmbrAO, tmbrAC tmbrB tmbrBO tmbrBC tmbrR trC rhythm rhyC rsrv panpot prog rhyMax patMax sysMax timMax sndGrp sGC stMsg sErMsg
|
||||
{"ctrl_mt32_1_04", OLD_MT32_ELDER, 0x3000, 128, 0x8000, 0x0000, false, 0xC000, 0x4000, false, 0x3200, 30, 0x73A6, 85, 0x57C7, 0x57E2, 0x57D0, 0x5252, 0x525E, 0x526E, 0x520A, 0x7064, 19, 0x217A, 0x4BB6},
|
||||
{"ctrl_mt32_1_05", OLD_MT32_ELDER, 0x3000, 128, 0x8000, 0x0000, false, 0xC000, 0x4000, false, 0x3200, 30, 0x7414, 85, 0x57C7, 0x57E2, 0x57D0, 0x5252, 0x525E, 0x526E, 0x520A, 0x70CA, 19, 0x217A, 0x4BB6},
|
||||
{"ctrl_mt32_1_06", OLD_MT32_LATER, 0x3000, 128, 0x8000, 0x0000, false, 0xC000, 0x4000, false, 0x3200, 30, 0x7414, 85, 0x57D9, 0x57F4, 0x57E2, 0x5264, 0x5270, 0x5280, 0x521C, 0x70CA, 19, 0x217A, 0x4BBA},
|
||||
{"ctrl_mt32_1_07", OLD_MT32_LATER, 0x3000, 128, 0x8000, 0x0000, false, 0xC000, 0x4000, false, 0x3200, 30, 0x73fe, 85, 0x57B1, 0x57CC, 0x57BA, 0x523C, 0x5248, 0x5258, 0x51F4, 0x70B0, 19, 0x217A, 0x4B92},
|
||||
{"ctrl_mt32_bluer", OLD_MT32_LATER, 0x3000, 128, 0x8000, 0x0000, false, 0xC000, 0x4000, false, 0x3200, 30, 0x741C, 85, 0x57E5, 0x5800, 0x57EE, 0x5270, 0x527C, 0x528C, 0x5228, 0x70CE, 19, 0x217A, 0x4BC6},
|
||||
{"ctrl_mt32_2_03", NEW_MT32_COMPATIBLE, 0x8100, 128, 0x8000, 0x8000, true, 0x8080, 0x8000, true, 0x8500, 64, 0x8580, 85, 0x4F49, 0x4F64, 0x4F52, 0x4885, 0x4889, 0x48A2, 0x48B9, 0x5A44, 19, 0x1EF0, 0x4066},
|
||||
{"ctrl_mt32_2_04", NEW_MT32_COMPATIBLE, 0x8100, 128, 0x8000, 0x8000, true, 0x8080, 0x8000, true, 0x8500, 64, 0x8580, 85, 0x4F5D, 0x4F78, 0x4F66, 0x4899, 0x489D, 0x48B6, 0x48CD, 0x5A58, 19, 0x1EF0, 0x406D},
|
||||
{"ctrl_mt32_2_06", NEW_MT32_COMPATIBLE, 0x8100, 128, 0x8000, 0x8000, true, 0x8080, 0x8000, true, 0x8500, 64, 0x8580, 85, 0x4F69, 0x4F84, 0x4F72, 0x48A5, 0x48A9, 0x48C2, 0x48D9, 0x5A64, 19, 0x1EF0, 0x4021},
|
||||
{"ctrl_mt32_2_07", NEW_MT32_COMPATIBLE, 0x8100, 128, 0x8000, 0x8000, true, 0x8080, 0x8000, true, 0x8500, 64, 0x8580, 85, 0x4F81, 0x4F9C, 0x4F8A, 0x48B9, 0x48BD, 0x48D6, 0x48ED, 0x5A78, 19, 0x1EE7, 0x4035},
|
||||
{"ctrl_cm32l_1_00", NEW_MT32_COMPATIBLE, 0x8100, 256, 0x8000, 0x8000, true, 0x8080, 0x8000, true, 0x8500, 64, 0x8580, 85, 0x4F65, 0x4F80, 0x4F6E, 0x48A1, 0x48A5, 0x48BE, 0x48D5, 0x5A6C, 19, 0x1EF0, 0x401D},
|
||||
{"ctrl_cm32l_1_02", NEW_MT32_COMPATIBLE, 0x8100, 256, 0x8000, 0x8000, true, 0x8080, 0x8000, true, 0x8500, 64, 0x8580, 85, 0x4F93, 0x4FAE, 0x4F9C, 0x48CB, 0x48CF, 0x48E8, 0x48FF, 0x5A96, 19, 0x1EE7, 0x4047},
|
||||
{"ctrl_cm32ln_1_00", CM32LN_COMPATIBLE, 0x8100, 256, 0x8000, 0x8000, true, 0x8080, 0x8000, true, 0x8500, 64, 0x8580, 85, 0x4EC7, 0x4EE2, 0x4ED0, 0x47FF, 0x4803, 0x481C, 0x4833, 0x55A2, 19, 0x1F59, 0x3F7C}
|
||||
// (Note that old MT-32 ROMs actually have 86 entries for rhythmTemp)
|
||||
};
|
||||
|
||||
@@ -138,6 +176,8 @@ protected:
|
||||
synth.renderedSampleCount += count;
|
||||
}
|
||||
|
||||
void updateDisplayState();
|
||||
|
||||
public:
|
||||
Renderer(Synth &useSynth) : synth(useSynth) {}
|
||||
|
||||
@@ -209,10 +249,16 @@ public:
|
||||
|
||||
Bit32u midiEventQueueSize;
|
||||
Bit32u midiEventQueueSysexStorageBufferSize;
|
||||
|
||||
Display *display;
|
||||
bool oldMT32DisplayFeatures;
|
||||
|
||||
ReportHandler2 defaultReportHandler;
|
||||
ReportHandler2 *reportHandler2;
|
||||
};
|
||||
|
||||
Bit32u Synth::getLibraryVersionInt() {
|
||||
return (MT32EMU_VERSION_MAJOR << 16) | (MT32EMU_VERSION_MINOR << 8) | (MT32EMU_VERSION_PATCH);
|
||||
return MT32EMU_CURRENT_VERSION_INT;
|
||||
}
|
||||
|
||||
const char *Synth::getLibraryVersionString() {
|
||||
@@ -244,13 +290,8 @@ Synth::Synth(ReportHandler *useReportHandler) :
|
||||
controlROMMap = NULL;
|
||||
controlROMFeatures = NULL;
|
||||
|
||||
if (useReportHandler == NULL) {
|
||||
reportHandler = new ReportHandler;
|
||||
isDefaultReportHandler = true;
|
||||
} else {
|
||||
reportHandler = useReportHandler;
|
||||
isDefaultReportHandler = false;
|
||||
}
|
||||
reportHandler = useReportHandler != NULL ? useReportHandler : &extensions.defaultReportHandler;
|
||||
extensions.reportHandler2 = &extensions.defaultReportHandler;
|
||||
|
||||
extensions.preallocatedReverbMemory = false;
|
||||
for (int i = REVERB_MODE_ROOM; i <= REVERB_MODE_TAP_DELAY; i++) {
|
||||
@@ -289,18 +330,27 @@ Synth::Synth(ReportHandler *useReportHandler) :
|
||||
lastReceivedMIDIEventTimestamp = 0;
|
||||
memset(parts, 0, sizeof(parts));
|
||||
renderedSampleCount = 0;
|
||||
extensions.display = NULL;
|
||||
extensions.oldMT32DisplayFeatures = false;
|
||||
}
|
||||
|
||||
Synth::~Synth() {
|
||||
close(); // Make sure we're closed and everything is freed
|
||||
if (isDefaultReportHandler) {
|
||||
delete reportHandler;
|
||||
}
|
||||
delete &mt32ram;
|
||||
delete &mt32default;
|
||||
delete &extensions;
|
||||
}
|
||||
|
||||
void Synth::setReportHandler2(ReportHandler2 *reportHandler2) {
|
||||
if (reportHandler2 != NULL) {
|
||||
reportHandler = reportHandler2;
|
||||
extensions.reportHandler2 = reportHandler2;
|
||||
} else {
|
||||
reportHandler = &extensions.defaultReportHandler;
|
||||
extensions.reportHandler2 = &extensions.defaultReportHandler;
|
||||
}
|
||||
}
|
||||
|
||||
void ReportHandler::showLCDMessage(const char *data) {
|
||||
printf("WRITE-LCD: %s\n", data);
|
||||
}
|
||||
@@ -310,26 +360,38 @@ void ReportHandler::printDebug(const char *fmt, va_list list) {
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void Synth::newTimbreSet(Bit8u partNum, Bit8u timbreGroup, Bit8u timbreNumber, const char patchName[]) {
|
||||
const char *soundGroupName;
|
||||
void Synth::rhythmNotePlayed() const {
|
||||
extensions.display->rhythmNotePlayed();
|
||||
}
|
||||
|
||||
void Synth::voicePartStateChanged(Bit8u partNum, bool partActivated) const {
|
||||
extensions.display->voicePartStateChanged(partNum, partActivated);
|
||||
}
|
||||
|
||||
void Synth::newTimbreSet(Bit8u partNum) const {
|
||||
const Part *part = getPart(partNum);
|
||||
reportHandler->onProgramChanged(partNum, getSoundGroupName(part), part->getCurrentInstr());
|
||||
}
|
||||
|
||||
const char *Synth::getSoundGroupName(const Part *part) const {
|
||||
const PatchParam &patch = part->getPatchTemp()->patch;
|
||||
return getSoundGroupName(patch.timbreGroup, patch.timbreNum);
|
||||
}
|
||||
|
||||
const char *Synth::getSoundGroupName(Bit8u timbreGroup, Bit8u timbreNumber) const {
|
||||
switch (timbreGroup) {
|
||||
case 1:
|
||||
timbreNumber += 64;
|
||||
// Fall-through
|
||||
case 0:
|
||||
soundGroupName = soundGroupNames[soundGroupIx[timbreNumber]];
|
||||
break;
|
||||
return soundGroupNames[soundGroupIx[timbreNumber]];
|
||||
case 2:
|
||||
soundGroupName = soundGroupNames[controlROMMap->soundGroupsCount - 2];
|
||||
break;
|
||||
return soundGroupNames[controlROMMap->soundGroupsCount - 2];
|
||||
case 3:
|
||||
soundGroupName = soundGroupNames[controlROMMap->soundGroupsCount - 1];
|
||||
break;
|
||||
return soundGroupNames[controlROMMap->soundGroupsCount - 1];
|
||||
default:
|
||||
soundGroupName = NULL;
|
||||
break;
|
||||
return NULL;
|
||||
}
|
||||
reportHandler->onProgramChanged(partNum, soundGroupName, patchName);
|
||||
}
|
||||
|
||||
#define MT32EMU_PRINT_DEBUG \
|
||||
@@ -450,6 +512,16 @@ float Synth::getReverbOutputGain() const {
|
||||
return reverbOutputGain;
|
||||
}
|
||||
|
||||
void Synth::setPartVolumeOverride(Bit8u partNumber, Bit8u volumeOverride) {
|
||||
if (opened && partNumber < 9) {
|
||||
parts[partNumber]->setVolumeOverride(volumeOverride);
|
||||
}
|
||||
}
|
||||
|
||||
Bit8u Synth::getPartVolumeOverride(Bit8u partNumber) const {
|
||||
return (!opened || partNumber > 8) ? 255 : parts[partNumber]->getVolumeOverride();
|
||||
}
|
||||
|
||||
void Synth::setReversedStereoEnabled(bool enabled) {
|
||||
reversedStereoEnabled = enabled;
|
||||
}
|
||||
@@ -542,7 +614,7 @@ bool Synth::loadPCMROM(const ROMImage &pcmROMImage) {
|
||||
int order[16] = {0, 9, 1, 2, 3, 4, 5, 6, 7, 10, 11, 12, 13, 14, 15, 8};
|
||||
|
||||
Bit16s log = 0;
|
||||
for (int u = 0; u < 15; u++) {
|
||||
for (int u = 0; u < 16; u++) {
|
||||
int bit;
|
||||
if (order[u] < 8) {
|
||||
bit = (s >> (7 - order[u])) & 0x1;
|
||||
@@ -717,6 +789,16 @@ bool Synth::open(const ROMImage &controlROMImage, const ROMImage &pcmROMImage, B
|
||||
return false;
|
||||
}
|
||||
|
||||
if (controlROMMap->timbreRCount == 30) {
|
||||
// We must initialise all 64 rhythm timbres to avoid undefined behaviour.
|
||||
// SEMI-CONFIRMED: Old-gen MT-32 units likely map timbres 30..59 to 0..29.
|
||||
// Attempts to play rhythm timbres 60..63 exhibit undefined behaviour.
|
||||
// We want to emulate the wrap around, so merely copy the entire set of standard
|
||||
// timbres once more. The last 4 dangerous timbres are zeroed out.
|
||||
memcpy(&mt32ram.timbres[222], &mt32ram.timbres[192], sizeof(*mt32ram.timbres) * 30);
|
||||
memset(&mt32ram.timbres[252], 0, sizeof(*mt32ram.timbres) * 4);
|
||||
}
|
||||
|
||||
#if MT32EMU_MONITOR_INIT
|
||||
printDebug("Initialising Timbre Bank M");
|
||||
#endif
|
||||
@@ -838,6 +920,9 @@ bool Synth::open(const ROMImage &controlROMImage, const ROMImage &pcmROMImage, B
|
||||
return false;
|
||||
}
|
||||
|
||||
extensions.display = new Display(*this);
|
||||
extensions.oldMT32DisplayFeatures = controlROMFeatures->oldMT32DisplayFeatures;
|
||||
|
||||
opened = true;
|
||||
activated = false;
|
||||
|
||||
@@ -850,6 +935,9 @@ bool Synth::open(const ROMImage &controlROMImage, const ROMImage &pcmROMImage, B
|
||||
void Synth::dispose() {
|
||||
opened = false;
|
||||
|
||||
delete extensions.display;
|
||||
extensions.display = NULL;
|
||||
|
||||
delete midiQueue;
|
||||
midiQueue = NULL;
|
||||
|
||||
@@ -1064,7 +1152,7 @@ void Synth::playMsgOnPart(Bit8u part, Bit8u code, Bit8u note, Bit8u velocity) {
|
||||
if (velocity == 0) {
|
||||
// MIDI defines note-on with velocity 0 as being the same as note-off with velocity 40
|
||||
parts[part]->noteOff(note);
|
||||
} else {
|
||||
} else if (parts[part]->getVolumeOverride() > 0) {
|
||||
parts[part]->noteOn(note, velocity);
|
||||
}
|
||||
break;
|
||||
@@ -1130,16 +1218,21 @@ void Synth::playMsgOnPart(Bit8u part, Bit8u code, Bit8u note, Bit8u velocity) {
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
extensions.display->midiMessagePlayed();
|
||||
break;
|
||||
case 0xC: // Program change
|
||||
//printDebug("Program change %01x", note);
|
||||
parts[part]->setProgram(note);
|
||||
if (part < 8) {
|
||||
extensions.display->midiMessagePlayed();
|
||||
extensions.display->programChanged(part);
|
||||
}
|
||||
break;
|
||||
case 0xE: // Pitch bender
|
||||
bend = (velocity << 7) | (note);
|
||||
//printDebug("Pitch bender %02x", bend);
|
||||
parts[part]->setBend(bend);
|
||||
extensions.display->midiMessagePlayed();
|
||||
break;
|
||||
default:
|
||||
#if MT32EMU_MONITOR_MIDI > 0
|
||||
@@ -1197,12 +1290,19 @@ void Synth::playSysexWithoutHeader(Bit8u device, Bit8u command, const Bit8u *sys
|
||||
printDebug("playSysexWithoutHeader: Message is not intended for this device ID (provided: %02x, expected: 0x10 or channel)", int(device));
|
||||
return;
|
||||
}
|
||||
// This is checked early in the real devices (before any sysex length checks or further processing)
|
||||
// FIXME: Response to SYSEX_CMD_DAT reset with partials active (and in general) is untested.
|
||||
if ((command == SYSEX_CMD_DT1 || command == SYSEX_CMD_DAT) && sysex[0] == 0x7F) {
|
||||
reset();
|
||||
|
||||
// All models process the checksum before anything else and ignore messages lacking the checksum, or containing the checksum only.
|
||||
if (len < 2) {
|
||||
printDebug("playSysexWithoutHeader: Message is too short (%d bytes)!", len);
|
||||
return;
|
||||
}
|
||||
Bit8u checksum = calcSysexChecksum(sysex, len - 1);
|
||||
if (checksum != sysex[len - 1]) {
|
||||
printDebug("playSysexWithoutHeader: Message checksum is incorrect (provided: %02x, expected: %02x)!", sysex[len - 1], checksum);
|
||||
if (opened) extensions.display->checksumErrorOccurred();
|
||||
return;
|
||||
}
|
||||
len -= 1; // Exclude checksum
|
||||
|
||||
if (command == SYSEX_CMD_EOD) {
|
||||
#if MT32EMU_MONITOR_SYSEX > 0
|
||||
@@ -1210,16 +1310,6 @@ void Synth::playSysexWithoutHeader(Bit8u device, Bit8u command, const Bit8u *sys
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
if (len < 4) {
|
||||
printDebug("playSysexWithoutHeader: Message is too short (%d bytes)!", len);
|
||||
return;
|
||||
}
|
||||
Bit8u checksum = calcSysexChecksum(sysex, len - 1);
|
||||
if (checksum != sysex[len - 1]) {
|
||||
printDebug("playSysexWithoutHeader: Message checksum is incorrect (provided: %02x, expected: %02x)!", sysex[len - 1], checksum);
|
||||
return;
|
||||
}
|
||||
len -= 1; // Exclude checksum
|
||||
switch (command) {
|
||||
case SYSEX_CMD_WSD:
|
||||
#if MT32EMU_MONITOR_SYSEX > 0
|
||||
@@ -1259,12 +1349,34 @@ void Synth::readSysex(Bit8u /*device*/, const Bit8u * /*sysex*/, Bit32u /*len*/)
|
||||
}
|
||||
|
||||
void Synth::writeSysex(Bit8u device, const Bit8u *sysex, Bit32u len) {
|
||||
if (!opened) return;
|
||||
if (!opened || len < 1) return;
|
||||
|
||||
// This is checked early in the real devices (before any sysex length checks or further processing)
|
||||
if (sysex[0] == 0x7F) {
|
||||
if (!isDisplayOldMT32Compatible()) extensions.display->midiMessagePlayed();
|
||||
reset();
|
||||
return;
|
||||
}
|
||||
|
||||
extensions.display->midiMessagePlayed();
|
||||
reportHandler->onMIDIMessagePlayed();
|
||||
|
||||
if (len < 3) {
|
||||
// A short message of just 1 or 2 bytes may be written to the display area yet it may cause a user-visible effect,
|
||||
// similarly to the reset area.
|
||||
if (sysex[0] == 0x20) {
|
||||
extensions.display->displayControlMessageReceived(sysex, len);
|
||||
return;
|
||||
}
|
||||
printDebug("writeSysex: Message is too short (%d bytes)!", len);
|
||||
return;
|
||||
}
|
||||
|
||||
Bit32u addr = (sysex[0] << 16) | (sysex[1] << 8) | (sysex[2]);
|
||||
addr = MT32EMU_MEMADDR(addr);
|
||||
sysex += 3;
|
||||
len -= 3;
|
||||
|
||||
//printDebug("Sysex addr: 0x%06x", MT32EMU_SYSEXMEMADDR(addr));
|
||||
// NOTE: Please keep both lower and upper bounds in each check, for ease of reading
|
||||
|
||||
@@ -1345,6 +1457,7 @@ void Synth::writeSysexGlobal(Bit32u addr, const Bit8u *sysex, Bit32u len) {
|
||||
|
||||
if (region == NULL) {
|
||||
printDebug("Sysex write to unrecognised address %06x, len %d", MT32EMU_SYSEXMEMADDR(addr), len);
|
||||
// FIXME: Real devices may respond differently to a long SysEx that covers adjacent regions.
|
||||
break;
|
||||
}
|
||||
writeMemoryRegion(region, addr, region->getClampedLen(addr, len), sysex);
|
||||
@@ -1663,7 +1776,10 @@ void Synth::writeMemoryRegion(const MemoryRegion *region, Bit32u addr, Bit32u le
|
||||
}
|
||||
break;
|
||||
case MR_Display:
|
||||
char buf[SYSEX_BUFFER_SIZE];
|
||||
if (len > Display::LCD_TEXT_SIZE) len = Display::LCD_TEXT_SIZE;
|
||||
if (!extensions.display->customDisplayMessageReceived(data, off, len)) break;
|
||||
// Holds zero-terminated string of the maximum length.
|
||||
char buf[Display::LCD_TEXT_SIZE + 1];
|
||||
memcpy(&buf, &data[0], len);
|
||||
buf[len] = 0;
|
||||
#if MT32EMU_MONITOR_SYSEX > 0
|
||||
@@ -1674,6 +1790,8 @@ void Synth::writeMemoryRegion(const MemoryRegion *region, Bit32u addr, Bit32u le
|
||||
case MR_Reset:
|
||||
reset();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1767,6 +1885,10 @@ void Synth::refreshSystemChanAssign(Bit8u firstPart, Bit8u lastPart) {
|
||||
}
|
||||
|
||||
void Synth::refreshSystemMasterVol() {
|
||||
// Note, this should only occur when the user turns the volume knob. When the master volume is set via a SysEx, display
|
||||
// doesn't actually update on all real devices. However, we anyway update the display, as we don't foresee a dedicated
|
||||
// API for setting the master volume yet it's rather dubious that one really needs this quirk to be fairly emulated.
|
||||
if (opened) extensions.display->masterVolumeChanged();
|
||||
#if MT32EMU_MONITOR_SYSEX > 0
|
||||
printDebug(" Master volume: %d", mt32ram.system.masterVol);
|
||||
#endif
|
||||
@@ -1816,6 +1938,32 @@ Bit32s Synth::getMasterTunePitchDelta() const {
|
||||
return extensions.masterTunePitchDelta;
|
||||
}
|
||||
|
||||
bool Synth::getDisplayState(char *targetBuffer, bool narrowLCD) const {
|
||||
if (!opened) {
|
||||
memset(targetBuffer, ' ', Display::LCD_TEXT_SIZE);
|
||||
targetBuffer[Display::LCD_TEXT_SIZE] = 0;
|
||||
return false;
|
||||
}
|
||||
return extensions.display->getDisplayState(targetBuffer, narrowLCD);
|
||||
}
|
||||
|
||||
void Synth::setMainDisplayMode() {
|
||||
if (opened) extensions.display->setMainDisplayMode();
|
||||
}
|
||||
|
||||
|
||||
void Synth::setDisplayCompatibility(bool oldMT32CompatibilityEnabled) {
|
||||
extensions.oldMT32DisplayFeatures = oldMT32CompatibilityEnabled;
|
||||
}
|
||||
|
||||
bool Synth::isDisplayOldMT32Compatible() const {
|
||||
return extensions.oldMT32DisplayFeatures;
|
||||
}
|
||||
|
||||
bool Synth::isDefaultDisplayOldMT32Compatible() const {
|
||||
return opened && controlROMFeatures->oldMT32DisplayFeatures;
|
||||
}
|
||||
|
||||
/** Defines an interface of a class that maintains storage of variable-sized data of SysEx messages. */
|
||||
class MidiEventQueue::SysexDataStorage {
|
||||
public:
|
||||
@@ -1994,6 +2142,15 @@ Bit32u Synth::getStereoOutputSampleRate() const {
|
||||
return (analog == NULL) ? SAMPLE_RATE : analog->getOutputSampleRate();
|
||||
}
|
||||
|
||||
void Renderer::updateDisplayState() {
|
||||
bool midiMessageLEDState;
|
||||
bool midiMessageLEDStateUpdated;
|
||||
bool lcdUpdated;
|
||||
synth.extensions.display->checkDisplayStateUpdated(midiMessageLEDState, midiMessageLEDStateUpdated, lcdUpdated);
|
||||
if (midiMessageLEDStateUpdated) synth.extensions.reportHandler2->onMidiMessageLEDStateUpdated(midiMessageLEDState);
|
||||
if (lcdUpdated) synth.extensions.reportHandler2->onLCDStateUpdated();
|
||||
}
|
||||
|
||||
template <class Sample>
|
||||
void RendererImpl<Sample>::doRender(Sample *stereoStream, Bit32u len) {
|
||||
if (!isActivated()) {
|
||||
@@ -2002,6 +2159,7 @@ void RendererImpl<Sample>::doRender(Sample *stereoStream, Bit32u len) {
|
||||
printDebug("RendererImpl: Invalid call to Analog::process()!\n");
|
||||
}
|
||||
Synth::muteSampleBuffer(stereoStream, len << 1);
|
||||
updateDisplayState();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2358,6 +2516,7 @@ void RendererImpl<Sample>::produceStreams(const DACOutputStreams<Sample> &stream
|
||||
|
||||
getPartialManager().clearAlreadyOutputed();
|
||||
incRenderedSampleCount(len);
|
||||
updateDisplayState();
|
||||
}
|
||||
|
||||
void Synth::printPartialUsage(Bit32u sampleOffset) {
|
||||
@@ -2468,6 +2627,26 @@ const char *Synth::getPatchName(Bit8u partNumber) const {
|
||||
return (!opened || partNumber > 8) ? NULL : parts[partNumber]->getCurrentInstr();
|
||||
}
|
||||
|
||||
bool Synth::getSoundGroupName(char *soundGroupName, Bit8u timbreGroup, Bit8u timbreNumber) const {
|
||||
if (!opened || 63 < timbreNumber) return false;
|
||||
const char *foundGroupName = getSoundGroupName(timbreGroup, timbreNumber);
|
||||
if (foundGroupName == NULL) return false;
|
||||
memcpy(soundGroupName, foundGroupName, 7);
|
||||
soundGroupName[7] = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Synth::getSoundName(char *soundName, Bit8u timbreGroup, Bit8u timbreNumber) const {
|
||||
if (!opened || 3 < timbreGroup) return false;
|
||||
Bit8u timbresInGroup = 3 == timbreGroup ? controlROMMap->timbreRCount : 64;
|
||||
if (timbresInGroup <= timbreNumber) return false;
|
||||
TimbreParam::CommonParam &timbreCommon = mt32ram.timbres[timbreGroup * 64 + timbreNumber].timbre.common;
|
||||
if (timbreCommon.partialMute == 0) return false;
|
||||
memcpy(soundName, timbreCommon.name, sizeof timbreCommon.name);
|
||||
soundName[sizeof timbreCommon.name] = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
const Part *Synth::getPart(Bit8u partNum) const {
|
||||
if (partNum > 8) {
|
||||
return NULL;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
@@ -69,6 +69,9 @@ const Bit8u SYSEX_CMD_EOD = 0x45; // End of data
|
||||
const Bit8u SYSEX_CMD_ERR = 0x4E; // Communications error
|
||||
const Bit8u SYSEX_CMD_RJC = 0x4F; // Rejection
|
||||
|
||||
// This value isn't quite correct: the new-gen MT-32 control ROMs (ver. 2.XX) are twice as big.
|
||||
// Nevertheless, this is still relevant for library internal usage because the higher half
|
||||
// of those ROMs only contains the demo songs in all cases.
|
||||
const Bit32u CONTROL_ROM_SIZE = 64 * 1024;
|
||||
|
||||
// Set of multiplexed output streams appeared at the DAC entrance.
|
||||
@@ -113,8 +116,21 @@ public:
|
||||
virtual void onProgramChanged(Bit8u /* partNum */, const char * /* soundGroupName */, const char * /* patchName */) {}
|
||||
};
|
||||
|
||||
// Extends ReportHandler, so that the client may supply callbacks for reporting signals about updated display state.
|
||||
class MT32EMU_EXPORT_V(2.6) ReportHandler2 : public ReportHandler {
|
||||
public:
|
||||
virtual ~ReportHandler2() {}
|
||||
|
||||
// Invoked to signal about a change of the emulated LCD state. Use method Synth::getDisplayState to retrieve the actual data.
|
||||
// This callback will not be invoked on further changes, until the client retrieves the LCD state.
|
||||
virtual void onLCDStateUpdated() {}
|
||||
// Invoked when the emulated MIDI MESSAGE LED changes state. The ledState parameter represents whether the LED is ON.
|
||||
virtual void onMidiMessageLEDStateUpdated(bool /* ledState */) {}
|
||||
};
|
||||
|
||||
class Synth {
|
||||
friend class DefaultMidiStreamParser;
|
||||
friend class Display;
|
||||
friend class MemoryRegion;
|
||||
friend class Part;
|
||||
friend class Partial;
|
||||
@@ -177,7 +193,7 @@ private:
|
||||
bool opened;
|
||||
bool activated;
|
||||
|
||||
bool isDefaultReportHandler;
|
||||
bool isDefaultReportHandler; // No longer used, retained for binary compatibility only.
|
||||
ReportHandler *reportHandler;
|
||||
|
||||
PartialManager *partialManager;
|
||||
@@ -227,7 +243,11 @@ private:
|
||||
|
||||
void printPartialUsage(Bit32u sampleOffset = 0);
|
||||
|
||||
void newTimbreSet(Bit8u partNum, Bit8u timbreGroup, Bit8u timbreNumber, const char patchName[]);
|
||||
void rhythmNotePlayed() const;
|
||||
void voicePartStateChanged(Bit8u partNum, bool activated) const;
|
||||
void newTimbreSet(Bit8u partNum) const;
|
||||
const char *getSoundGroupName(const Part *part) const;
|
||||
const char *getSoundGroupName(Bit8u timbreGroup, Bit8u timbreNumber) const;
|
||||
void printDebug(const char *fmt, ...);
|
||||
|
||||
// partNum should be 0..7 for Part 1..8, or 8 for Rhythm
|
||||
@@ -290,9 +310,13 @@ public:
|
||||
MT32EMU_EXPORT explicit Synth(ReportHandler *useReportHandler = NULL);
|
||||
MT32EMU_EXPORT ~Synth();
|
||||
|
||||
// Sets an implementation of ReportHandler2 interface for reporting various errors, information and debug messages.
|
||||
// If the argument is NULL, the default implementation is installed as a fallback.
|
||||
MT32EMU_EXPORT_V(2.6) void setReportHandler2(ReportHandler2 *reportHandler2);
|
||||
|
||||
// Used to initialise the MT-32. Must be called before any other function.
|
||||
// Returns true if initialization was sucessful, otherwise returns false.
|
||||
// controlROMImage and pcmROMImage represent Control and PCM ROM images for use by synth.
|
||||
// Returns true if initialization was successful, otherwise returns false.
|
||||
// controlROMImage and pcmROMImage represent full Control and PCM ROM images for use by synth.
|
||||
// usePartialCount sets the maximum number of partials playing simultaneously for this session (optional).
|
||||
// analogOutputMode sets the mode for emulation of analogue circuitry of the hardware units (optional).
|
||||
MT32EMU_EXPORT bool open(const ROMImage &controlROMImage, const ROMImage &pcmROMImage, Bit32u usePartialCount = DEFAULT_MAX_PARTIALS, AnalogOutputMode analogOutputMode = AnalogOutputMode_COARSE);
|
||||
@@ -391,7 +415,7 @@ public:
|
||||
MT32EMU_EXPORT bool isMT32ReverbCompatibilityMode() const;
|
||||
// Returns whether default reverb compatibility mode is the old MT-32 compatibility mode.
|
||||
MT32EMU_EXPORT bool isDefaultReverbMT32Compatible() const;
|
||||
// If enabled, reverb buffers for all modes are keept around allocated all the time to avoid memory
|
||||
// If enabled, reverb buffers for all modes are kept around allocated all the time to avoid memory
|
||||
// allocating/freeing in the rendering thread, which may be required for realtime operation.
|
||||
// Otherwise, reverb buffers that are not in use are deleted to save memory (the default behaviour).
|
||||
MT32EMU_EXPORT void preallocateReverbMemory(bool enabled);
|
||||
@@ -423,6 +447,22 @@ public:
|
||||
// Returns current output gain factor for reverb wet output channels.
|
||||
MT32EMU_EXPORT float getReverbOutputGain() const;
|
||||
|
||||
// Sets (or removes) an override for the current volume (output level) on a specific part.
|
||||
// When the part volume is overridden, the MIDI controller Volume (7) on the MIDI channel this part is assigned to
|
||||
// has no effect on the output level of this part. Similarly, the output level value set on this part via a SysEx that
|
||||
// modifies the Patch temp structure is disregarded.
|
||||
// To enable the override mode, argument volumeOverride should be in range 0..100, setting a value outside this range
|
||||
// disables the previously set override, if any.
|
||||
// Note: Setting volumeOverride to 0 mutes the part completely, meaning no sound is generated at all.
|
||||
// This is unlike the behaviour of real devices - setting 0 volume on a part may leave it still producing
|
||||
// sound at a very low level.
|
||||
// Argument partNumber should be 0..7 for Part 1..8, or 8 for Rhythm.
|
||||
MT32EMU_EXPORT_V(2.6) void setPartVolumeOverride(Bit8u partNumber, Bit8u volumeOverride);
|
||||
// Returns the overridden volume previously set on a specific part; a value outside the range 0..100 means no override
|
||||
// is currently in effect.
|
||||
// Argument partNumber should be 0..7 for Part 1..8, or 8 for Rhythm.
|
||||
MT32EMU_EXPORT_V(2.6) Bit8u getPartVolumeOverride(Bit8u partNumber) const;
|
||||
|
||||
// Swaps left and right output channels.
|
||||
MT32EMU_EXPORT void setReversedStereoEnabled(bool enabled);
|
||||
// Returns whether left and right output channels are swapped.
|
||||
@@ -529,10 +569,53 @@ public:
|
||||
|
||||
// Returns name of the patch set on the specified part.
|
||||
// Argument partNumber should be 0..7 for Part 1..8, or 8 for Rhythm.
|
||||
// The returned value is a null-terminated string which is guaranteed to remain valid until the next call to one of render methods.
|
||||
MT32EMU_EXPORT const char *getPatchName(Bit8u partNumber) const;
|
||||
|
||||
// Retrieves the name of the sound group the timbre identified by arguments timbreGroup and timbreNumber is associated with.
|
||||
// Values 0-3 of timbreGroup correspond to the timbre banks GROUP A, GROUP B, MEMORY and RHYTHM.
|
||||
// For all but the RHYTHM timbre bank, allowed values of timbreNumber are in range 0-63. The number of timbres
|
||||
// contained in the RHYTHM bank depends on the used control ROM version.
|
||||
// The argument soundGroupName must point to an array of at least 8 characters. The result is a null-terminated string.
|
||||
// Returns whether the specified timbre has been found and the result written in soundGroupName.
|
||||
MT32EMU_EXPORT_V(2.7) bool getSoundGroupName(char *soundGroupName, Bit8u timbreGroup, Bit8u timbreNumber) const;
|
||||
// Retrieves the name of the timbre identified by arguments timbreGroup and timbreNumber.
|
||||
// Values 0-3 of timbreGroup correspond to the timbre banks GROUP A, GROUP B, MEMORY and RHYTHM.
|
||||
// For all but the RHYTHM timbre bank, allowed values of timbreNumber are in range 0-63. The number of timbres
|
||||
// contained in the RHYTHM bank depends on the used control ROM version.
|
||||
// The argument soundName must point to an array of at least 11 characters. The result is a null-terminated string.
|
||||
// Returns whether the specified timbre has been found and the result written in soundName.
|
||||
MT32EMU_EXPORT_V(2.7) bool getSoundName(char *soundName, Bit8u timbreGroup, Bit8u timbreNumber) const;
|
||||
|
||||
// Stores internal state of emulated synth into an array provided (as it would be acquired from hardware).
|
||||
MT32EMU_EXPORT void readMemory(Bit32u addr, Bit32u len, Bit8u *data);
|
||||
|
||||
// Retrieves the current state of the emulated MT-32 display facilities.
|
||||
// Typically, the state is updated during the rendering. When that happens, a related callback from ReportHandler2 is invoked.
|
||||
// However, there might be no need to invoke this method after each update, e.g. when the render buffer is just a few milliseconds
|
||||
// long.
|
||||
// The argument targetBuffer must point to an array of at least 21 characters. The result is a null-terminated string.
|
||||
// The optional argument narrowLCD enables a condensed representation of the displayed information in some cases. This is mainly
|
||||
// intended to route the result to a hardware LCD that is only 16 characters wide. Automatic scrolling of longer strings
|
||||
// is not supported.
|
||||
// Returns whether the MIDI MESSAGE LED is ON and fills the targetBuffer parameter.
|
||||
MT32EMU_EXPORT_V(2.6) bool getDisplayState(char *targetBuffer, bool narrowLCD = false) const;
|
||||
|
||||
// Resets the emulated LCD to the main mode (Master Volume). This has the same effect as pressing the Master Volume button
|
||||
// while the display shows some other message. Useful for the new-gen devices as those require a special Display Reset SysEx
|
||||
// to return to the main mode e.g. from showing a custom display message or a checksum error.
|
||||
MT32EMU_EXPORT_V(2.6) void setMainDisplayMode();
|
||||
|
||||
// Permits to select an arbitrary display emulation model that does not necessarily match the actual behaviour implemented
|
||||
// in the control ROM version being used.
|
||||
// Invoking this method with the argument set to true forces emulation of the old-gen MT-32 display features.
|
||||
// Otherwise, emulation of the new-gen devices is enforced (these include CM-32L and LAPC-I as if these were connected to an LCD).
|
||||
MT32EMU_EXPORT_V(2.6) void setDisplayCompatibility(bool oldMT32CompatibilityEnabled);
|
||||
// Returns whether the currently configured features of the emulated display are compatible with the old-gen MT-32 devices.
|
||||
MT32EMU_EXPORT_V(2.6) bool isDisplayOldMT32Compatible() const;
|
||||
// Returns whether the emulated display features configured by default depending on the actual control ROM version
|
||||
// are compatible with the old-gen MT-32 devices.
|
||||
MT32EMU_EXPORT_V(2.6) bool isDefaultDisplayOldMT32Compatible() const;
|
||||
}; // class Synth
|
||||
|
||||
} // namespace MT32Emu
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
@@ -99,7 +99,7 @@ static int calcVeloAmpSubtraction(Bit8u veloSensitivity, unsigned int velocity)
|
||||
return absVelocityMult - (velocityMult >> 8); // PORTABILITY NOTE: Assumes arithmetic shift
|
||||
}
|
||||
|
||||
static int calcBasicAmp(const Tables *tables, const Partial *partial, const MemParams::System *system, const TimbreParam::PartialParam *partialParam, const MemParams::PatchTemp *patchTemp, const MemParams::RhythmTemp *rhythmTemp, int biasAmpSubtraction, int veloAmpSubtraction, Bit8u expression, bool hasRingModQuirk) {
|
||||
static int calcBasicAmp(const Tables *tables, const Partial *partial, const MemParams::System *system, const TimbreParam::PartialParam *partialParam, Bit8u partVolume, const MemParams::RhythmTemp *rhythmTemp, int biasAmpSubtraction, int veloAmpSubtraction, Bit8u expression, bool hasRingModQuirk) {
|
||||
int amp = 155;
|
||||
|
||||
if (!(hasRingModQuirk ? partial->isRingModulatingNoMix() : partial->isRingModulatingSlave())) {
|
||||
@@ -107,7 +107,7 @@ static int calcBasicAmp(const Tables *tables, const Partial *partial, const MemP
|
||||
if (amp < 0) {
|
||||
return 0;
|
||||
}
|
||||
amp -= tables->levelToAmpSubtraction[patchTemp->outputLevel];
|
||||
amp -= tables->levelToAmpSubtraction[partVolume];
|
||||
if (amp < 0) {
|
||||
return 0;
|
||||
}
|
||||
@@ -154,7 +154,6 @@ static int calcKeyTimeSubtraction(Bit8u envTimeKeyfollow, int key) {
|
||||
void TVA::reset(const Part *newPart, const TimbreParam::PartialParam *newPartialParam, const MemParams::RhythmTemp *newRhythmTemp) {
|
||||
part = newPart;
|
||||
partialParam = newPartialParam;
|
||||
patchTemp = newPart->getPatchTemp();
|
||||
rhythmTemp = newRhythmTemp;
|
||||
|
||||
playing = true;
|
||||
@@ -169,7 +168,7 @@ void TVA::reset(const Part *newPart, const TimbreParam::PartialParam *newPartial
|
||||
biasAmpSubtraction = calcBiasAmpSubtractions(partialParam, key);
|
||||
veloAmpSubtraction = calcVeloAmpSubtraction(partialParam->tva.veloSensitivity, velocity);
|
||||
|
||||
int newTarget = calcBasicAmp(tables, partial, system, partialParam, patchTemp, newRhythmTemp, biasAmpSubtraction, veloAmpSubtraction, part->getExpression(), partial->getSynth()->controlROMFeatures->quirkRingModulationNoMix);
|
||||
int newTarget = calcBasicAmp(tables, partial, system, partialParam, part->getVolume(), newRhythmTemp, biasAmpSubtraction, veloAmpSubtraction, part->getExpression(), partial->getSynth()->controlROMFeatures->quirkRingModulationNoMix);
|
||||
int newPhase;
|
||||
if (partialParam->tva.envTime[0] == 0) {
|
||||
// Initially go to the TVA_PHASE_ATTACK target amp, and spend the next phase going from there to the TVA_PHASE_2 target amp
|
||||
@@ -221,7 +220,7 @@ void TVA::recalcSustain() {
|
||||
}
|
||||
// We're sustaining. Recalculate all the values
|
||||
const Tables *tables = &Tables::getInstance();
|
||||
int newTarget = calcBasicAmp(tables, partial, system, partialParam, patchTemp, rhythmTemp, biasAmpSubtraction, veloAmpSubtraction, part->getExpression(), partial->getSynth()->controlROMFeatures->quirkRingModulationNoMix);
|
||||
int newTarget = calcBasicAmp(tables, partial, system, partialParam, part->getVolume(), rhythmTemp, biasAmpSubtraction, veloAmpSubtraction, part->getExpression(), partial->getSynth()->controlROMFeatures->quirkRingModulationNoMix);
|
||||
newTarget += partialParam->tva.envLevel[3];
|
||||
|
||||
// Although we're in TVA_PHASE_SUSTAIN at this point, we cannot be sure that there is no active ramp at the moment.
|
||||
@@ -271,10 +270,10 @@ void TVA::nextPhase() {
|
||||
}
|
||||
|
||||
bool allLevelsZeroFromNowOn = false;
|
||||
if (!partial->getSynth()->controlROMFeatures->quirkTVAZeroEnvLevels && partialParam->tva.envLevel[3] == 0) {
|
||||
if (partialParam->tva.envLevel[3] == 0) {
|
||||
if (newPhase == TVA_PHASE_4) {
|
||||
allLevelsZeroFromNowOn = true;
|
||||
} else if (partialParam->tva.envLevel[2] == 0) {
|
||||
} else if (!partial->getSynth()->controlROMFeatures->quirkTVAZeroEnvLevels && partialParam->tva.envLevel[2] == 0) {
|
||||
if (newPhase == TVA_PHASE_3) {
|
||||
allLevelsZeroFromNowOn = true;
|
||||
} else if (partialParam->tva.envLevel[1] == 0) {
|
||||
@@ -294,7 +293,7 @@ void TVA::nextPhase() {
|
||||
int envPointIndex = phase;
|
||||
|
||||
if (!allLevelsZeroFromNowOn) {
|
||||
newTarget = calcBasicAmp(tables, partial, system, partialParam, patchTemp, rhythmTemp, biasAmpSubtraction, veloAmpSubtraction, part->getExpression(), partial->getSynth()->controlROMFeatures->quirkRingModulationNoMix);
|
||||
newTarget = calcBasicAmp(tables, partial, system, partialParam, part->getVolume(), rhythmTemp, biasAmpSubtraction, veloAmpSubtraction, part->getExpression(), partial->getSynth()->controlROMFeatures->quirkRingModulationNoMix);
|
||||
|
||||
if (newPhase == TVA_PHASE_SUSTAIN || newPhase == TVA_PHASE_RELEASE) {
|
||||
if (partialParam->tva.envLevel[3] == 0) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
@@ -67,7 +67,6 @@ private:
|
||||
|
||||
const Part *part;
|
||||
const TimbreParam::PartialParam *partialParam;
|
||||
const MemParams::PatchTemp *patchTemp;
|
||||
const MemParams::RhythmTemp *rhythmTemp;
|
||||
|
||||
bool playing;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
@@ -206,6 +206,8 @@ void TVF::nextPhase() {
|
||||
}
|
||||
startRamp((levelMult * partialParam->tvf.envLevel[3]) >> 8, 0, newPhase);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
int envPointIndex = phase;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
@@ -54,13 +54,32 @@ static Bit16u keyToPitchTable[] = {
|
||||
// We want to do processing 4000 times per second. FIXME: This is pretty arbitrary.
|
||||
static const int NOMINAL_PROCESS_TIMER_PERIOD_SAMPLES = SAMPLE_RATE / 4000;
|
||||
|
||||
// The timer runs at 500kHz. This is how much to increment it after 8 samples passes.
|
||||
// We multiply by 8 to get rid of the fraction and deal with just integers.
|
||||
static const int PROCESS_TIMER_INCREMENT_x8 = 8 * 500000 / SAMPLE_RATE;
|
||||
// In all hardware units we emulate, the main clock frequency of the MCU is 12MHz.
|
||||
// However, the MCU used in the 3rd-gen sound modules (like CM-500 and LAPC-N)
|
||||
// is significantly faster. Importantly, the software timer also works faster,
|
||||
// yet this fact has been seemingly missed. To be more specific, the software timer
|
||||
// ticks each 8 "state times", and 1 state time equals to 3 clock periods
|
||||
// for 8095 and 8098 but 2 clock periods for 80C198. That is, on MT-32 and CM-32L,
|
||||
// the software timer tick rate is 12,000,000 / 3 / 8 = 500kHz, but on the 3rd-gen
|
||||
// devices it's 12,000,000 / 2 / 8 = 750kHz instead.
|
||||
|
||||
// For 1st- and 2nd-gen devices, the timer ticks at 500kHz. This is how much to increment
|
||||
// timeElapsed once 16 samples passes. We multiply by 16 to get rid of the fraction
|
||||
// and deal with just integers.
|
||||
static const int PROCESS_TIMER_TICKS_PER_SAMPLE_X16_1N2_GEN = (500000 << 4) / SAMPLE_RATE;
|
||||
// For 3rd-gen devices, the timer ticks at 750kHz. This is how much to increment
|
||||
// timeElapsed once 16 samples passes. We multiply by 16 to get rid of the fraction
|
||||
// and deal with just integers.
|
||||
static const int PROCESS_TIMER_TICKS_PER_SAMPLE_X16_3_GEN = (750000 << 4) / SAMPLE_RATE;
|
||||
|
||||
TVP::TVP(const Partial *usePartial) :
|
||||
partial(usePartial), system(&usePartial->getSynth()->mt32ram.system) {
|
||||
}
|
||||
partial(usePartial),
|
||||
system(&usePartial->getSynth()->mt32ram.system),
|
||||
processTimerTicksPerSampleX16(
|
||||
partial->getSynth()->controlROMFeatures->quirkFastPitchChanges
|
||||
? PROCESS_TIMER_TICKS_PER_SAMPLE_X16_3_GEN
|
||||
: PROCESS_TIMER_TICKS_PER_SAMPLE_X16_1N2_GEN)
|
||||
{}
|
||||
|
||||
static Bit16s keyToPitch(unsigned int key) {
|
||||
// We're using a table to do: return round_to_nearest_or_even((key - 60) * (4096.0 / 12.0))
|
||||
@@ -270,7 +289,7 @@ void TVP::setupPitchChange(int targetPitchOffset, Bit8u changeDuration) {
|
||||
pitchOffsetDelta = -pitchOffsetDelta;
|
||||
}
|
||||
// We want to maximise the number of bits of the Bit16s "pitchOffsetChangePerBigTick" we use in order to get the best possible precision later
|
||||
Bit32u absPitchOffsetDelta = pitchOffsetDelta << 16;
|
||||
Bit32u absPitchOffsetDelta = (pitchOffsetDelta & 0xFFFF) << 16;
|
||||
Bit8u normalisationShifts = normalise(absPitchOffsetDelta); // FIXME: Double-check: normalisationShifts is usually between 0 and 15 here, unless the delta is 0, in which case it's 31
|
||||
absPitchOffsetDelta = absPitchOffsetDelta >> 1; // Make room for the sign bit
|
||||
|
||||
@@ -301,7 +320,7 @@ void TVP::startDecay() {
|
||||
|
||||
Bit16u TVP::nextPitch() {
|
||||
// We emulate MCU software timer using these counter and processTimerIncrement variables.
|
||||
// The value of nominalProcessTimerPeriod approximates the period in samples
|
||||
// The value of NOMINAL_PROCESS_TIMER_PERIOD_SAMPLES approximates the period in samples
|
||||
// between subsequent firings of the timer that normally occur.
|
||||
// However, accurate emulation is quite complicated because the timer is not guaranteed to fire in time.
|
||||
// This makes pitch variations on real unit non-deterministic and dependent on various factors.
|
||||
@@ -309,7 +328,7 @@ Bit16u TVP::nextPitch() {
|
||||
timeElapsed = (timeElapsed + processTimerIncrement) & 0x00FFFFFF;
|
||||
// This roughly emulates pitch deviations observed on real units when playing a single partial that uses TVP/LFO.
|
||||
counter = NOMINAL_PROCESS_TIMER_PERIOD_SAMPLES + (rand() & 3);
|
||||
processTimerIncrement = (PROCESS_TIMER_INCREMENT_x8 * counter) >> 3;
|
||||
processTimerIncrement = (processTimerTicksPerSampleX16 * counter) >> 4;
|
||||
process();
|
||||
}
|
||||
counter--;
|
||||
@@ -337,13 +356,16 @@ void TVP::process() {
|
||||
return;
|
||||
}
|
||||
// FIXME: Write explanation for this stuff
|
||||
// NOTE: Value of shifts may happily exceed the maximum of 31 specified for the 8095 MCU.
|
||||
// We assume the device performs a shift with the rightmost 5 bits of the counter regardless of argument size,
|
||||
// since shift instructions of any size have the same maximum.
|
||||
int rightShifts = shifts;
|
||||
if (rightShifts > 13) {
|
||||
rightShifts -= 13;
|
||||
negativeBigTicksRemaining = negativeBigTicksRemaining >> rightShifts; // PORTABILITY NOTE: Assumes arithmetic shift
|
||||
negativeBigTicksRemaining = negativeBigTicksRemaining >> (rightShifts & 0x1F); // PORTABILITY NOTE: Assumes arithmetic shift
|
||||
rightShifts = 13;
|
||||
}
|
||||
int newResult = (negativeBigTicksRemaining * pitchOffsetChangePerBigTick) >> rightShifts; // PORTABILITY NOTE: Assumes arithmetic shift
|
||||
int newResult = (negativeBigTicksRemaining * pitchOffsetChangePerBigTick) >> (rightShifts & 0x1F); // PORTABILITY NOTE: Assumes arithmetic shift
|
||||
newResult += targetPitchOffsetWithoutLFO + lfoPitchOffset;
|
||||
currentPitchOffset = newResult;
|
||||
updatePitch();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
@@ -36,6 +36,7 @@ private:
|
||||
const TimbreParam::PartialParam *partialParam;
|
||||
const MemParams::PatchTemp *patchTemp;
|
||||
|
||||
const int processTimerTicksPerSampleX16;
|
||||
int processTimerIncrement;
|
||||
int counter;
|
||||
Bit32u timeElapsed;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
|
||||
32
src/sound/munt/VersionTagging.cpp
Normal file
32
src/sound/munt/VersionTagging.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2022 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"
|
||||
|
||||
extern "C" {
|
||||
// Here's a list of all tagged minor library versions through global (potentially versioned) symbols.
|
||||
// An application that's been linked with an older library version will be able to find a matching tag,
|
||||
// while for an application linked with a newer library version there will be no match.
|
||||
|
||||
MT32EMU_EXPORT_V(2.5) extern const volatile char mt32emu_2_5 = 0;
|
||||
MT32EMU_EXPORT_V(2.6) extern const volatile char mt32emu_2_6 = 0;
|
||||
MT32EMU_EXPORT_V(2.7) extern const volatile char mt32emu_2_7 = 0;
|
||||
|
||||
#if MT32EMU_VERSION_MAJOR > 2 || MT32EMU_VERSION_MINOR > 7
|
||||
#error "Missing version tag definition for current library version"
|
||||
#endif
|
||||
}
|
||||
60
src/sound/munt/VersionTagging.h
Normal file
60
src/sound/munt/VersionTagging.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2022 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_VERSION_TAG_H
|
||||
#define MT32EMU_VERSION_TAG_H
|
||||
|
||||
#include "globals.h"
|
||||
|
||||
/* This is intended to implement a simple check of a shared library version in runtime. Sadly, per-symbol versioning
|
||||
* is unavailable on many platforms, and even where it is, it's still not too easy to maintain for a C++ library.
|
||||
* Therefore, the goal here is just to ensure that the client application quickly bails out when attempted to run
|
||||
* with an older version of shared library, as well as to produce a more readable error message indicating a version mismatch
|
||||
* rather than a report about some missing symbols with unreadable mangled names.
|
||||
* This is an optional feature, since it adds some minor burden to both the library and client applications code,
|
||||
* albeit it is ought to work on platforms that do not implement symbol versioning.
|
||||
*/
|
||||
|
||||
#define MT32EMU_REALLY_BUILD_VERSION_TAG(major, minor) mt32emu_ ## major ## _ ## minor
|
||||
/* This macro expansion step permits resolution the actual version numbers. */
|
||||
#define MT32EMU_BUILD_VERSION_TAG(major, minor) MT32EMU_REALLY_BUILD_VERSION_TAG(major, minor)
|
||||
#define MT32EMU_VERSION_TAG MT32EMU_BUILD_VERSION_TAG(MT32EMU_VERSION_MAJOR, MT32EMU_VERSION_MINOR)
|
||||
|
||||
#if defined(__cplusplus)
|
||||
|
||||
extern "C" {
|
||||
MT32EMU_EXPORT extern const volatile char MT32EMU_VERSION_TAG;
|
||||
}
|
||||
// This pulls the external reference in yet prevents it from being optimised out.
|
||||
static const volatile char mt32emu_version_tag = MT32EMU_VERSION_TAG;
|
||||
|
||||
#else
|
||||
|
||||
static void mt32emu_refer_version_tag(void) {
|
||||
MT32EMU_EXPORT extern const volatile char MT32EMU_VERSION_TAG;
|
||||
(void)MT32EMU_VERSION_TAG;
|
||||
}
|
||||
|
||||
static void (*const volatile mt32emu_refer_version_tag_ref)(void) = mt32emu_refer_version_tag;
|
||||
|
||||
#endif
|
||||
|
||||
#undef MT32EMU_REALLY_BUILD_VERSION_TAG
|
||||
#undef MT32EMU_BUILD_VERSION_TAG
|
||||
#undef MT32EMU_VERSION_TAG
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
@@ -15,6 +15,8 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "../globals.h"
|
||||
#include "../Types.h"
|
||||
#include "../File.h"
|
||||
@@ -37,11 +39,11 @@ struct SamplerateConversionState {
|
||||
SampleRateConverter *src;
|
||||
};
|
||||
|
||||
static mt32emu_service_version getSynthVersionID(mt32emu_service_i) {
|
||||
static mt32emu_service_version MT32EMU_C_CALL getSynthVersionID(mt32emu_service_i) {
|
||||
return MT32EMU_SERVICE_VERSION_CURRENT;
|
||||
}
|
||||
|
||||
static const mt32emu_service_i_v3 SERVICE_VTABLE = {
|
||||
static const mt32emu_service_i_v6 SERVICE_VTABLE = {
|
||||
getSynthVersionID,
|
||||
mt32emu_get_supported_report_handler_version,
|
||||
mt32emu_get_supported_midi_receiver_version,
|
||||
@@ -118,13 +120,29 @@ static const mt32emu_service_i_v3 SERVICE_VTABLE = {
|
||||
mt32emu_set_nice_partial_mixing_enabled,
|
||||
mt32emu_is_nice_partial_mixing_enabled,
|
||||
mt32emu_preallocate_reverb_memory,
|
||||
mt32emu_configure_midi_event_queue_sysex_storage
|
||||
mt32emu_configure_midi_event_queue_sysex_storage,
|
||||
mt32emu_get_machine_ids,
|
||||
mt32emu_get_rom_ids,
|
||||
mt32emu_identify_rom_data,
|
||||
mt32emu_identify_rom_file,
|
||||
mt32emu_merge_and_add_rom_data,
|
||||
mt32emu_merge_and_add_rom_files,
|
||||
mt32emu_add_machine_rom_file,
|
||||
mt32emu_get_display_state,
|
||||
mt32emu_set_main_display_mode,
|
||||
mt32emu_set_display_compatibility,
|
||||
mt32emu_is_display_old_mt32_compatible,
|
||||
mt32emu_is_default_display_old_mt32_compatible,
|
||||
mt32emu_set_part_volume_override,
|
||||
mt32emu_get_part_volume_override,
|
||||
mt32emu_get_sound_group_name,
|
||||
mt32emu_get_sound_name
|
||||
};
|
||||
|
||||
} // namespace MT32Emu
|
||||
|
||||
struct mt32emu_data {
|
||||
ReportHandler *reportHandler;
|
||||
ReportHandler2 *reportHandler;
|
||||
Synth *synth;
|
||||
const ROMImage *controlROMImage;
|
||||
const ROMImage *pcmROMImage;
|
||||
@@ -138,16 +156,19 @@ struct mt32emu_data {
|
||||
|
||||
namespace MT32Emu {
|
||||
|
||||
class DelegatingReportHandlerAdapter : public ReportHandler {
|
||||
class DelegatingReportHandlerAdapter : public ReportHandler2 {
|
||||
public:
|
||||
DelegatingReportHandlerAdapter(mt32emu_report_handler_i useReportHandler, void *useInstanceData) :
|
||||
delegate(useReportHandler), instanceData(useInstanceData) {}
|
||||
|
||||
protected:
|
||||
private:
|
||||
const mt32emu_report_handler_i delegate;
|
||||
void * const instanceData;
|
||||
|
||||
private:
|
||||
bool isVersionLess(mt32emu_report_handler_version versionID) {
|
||||
return delegate.v0->getVersionID(delegate) < versionID;
|
||||
}
|
||||
|
||||
void printDebug(const char *fmt, va_list list) {
|
||||
if (delegate.v0->printDebug == NULL) {
|
||||
ReportHandler::printDebug(fmt, list);
|
||||
@@ -258,6 +279,22 @@ private:
|
||||
delegate.v0->onProgramChanged(instanceData, partNum, soundGroupName, patchName);
|
||||
}
|
||||
}
|
||||
|
||||
void onLCDStateUpdated() {
|
||||
if (isVersionLess(MT32EMU_REPORT_HANDLER_VERSION_1) || delegate.v1->onLCDStateUpdated == NULL) {
|
||||
ReportHandler2::onLCDStateUpdated();
|
||||
} else {
|
||||
delegate.v1->onLCDStateUpdated(instanceData);
|
||||
}
|
||||
}
|
||||
|
||||
void onMidiMessageLEDStateUpdated(bool ledState) {
|
||||
if (isVersionLess(MT32EMU_REPORT_HANDLER_VERSION_1) || delegate.v1->onMidiMessageLEDStateUpdated == NULL) {
|
||||
ReportHandler2::onMidiMessageLEDStateUpdated(ledState);
|
||||
} else {
|
||||
delegate.v1->onMidiMessageLEDStateUpdated(instanceData, ledState ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class DelegatingMidiStreamParser : public DefaultMidiStreamParser {
|
||||
@@ -295,30 +332,130 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
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);
|
||||
static void fillROMInfo(mt32emu_rom_info *rom_info, const ROMInfo *controlROMInfo, const ROMInfo *pcmROMInfo) {
|
||||
if (controlROMInfo != NULL) {
|
||||
rom_info->control_rom_id = controlROMInfo->shortName;
|
||||
rom_info->control_rom_description = controlROMInfo->description;
|
||||
rom_info->control_rom_sha1_digest = controlROMInfo->sha1Digest;
|
||||
} else {
|
||||
rom_info->control_rom_id = NULL;
|
||||
rom_info->control_rom_description = NULL;
|
||||
rom_info->control_rom_sha1_digest = NULL;
|
||||
}
|
||||
if (pcmROMInfo != NULL) {
|
||||
rom_info->pcm_rom_id = pcmROMInfo->shortName;
|
||||
rom_info->pcm_rom_description = pcmROMInfo->description;
|
||||
rom_info->pcm_rom_sha1_digest = pcmROMInfo->sha1Digest;
|
||||
} else {
|
||||
rom_info->pcm_rom_id = NULL;
|
||||
rom_info->pcm_rom_description = NULL;
|
||||
rom_info->pcm_rom_sha1_digest = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static const MachineConfiguration *findMachineConfiguration(const char *machine_id) {
|
||||
Bit32u configurationCount;
|
||||
const MachineConfiguration * const *configurations = MachineConfiguration::getAllMachineConfigurations(&configurationCount);
|
||||
for (Bit32u i = 0; i < configurationCount; i++) {
|
||||
if (!strcmp(configurations[i]->getMachineID(), machine_id)) return configurations[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static mt32emu_return_code identifyROM(mt32emu_rom_info *rom_info, File *romFile, const char *machineID) {
|
||||
const ROMInfo *romInfo;
|
||||
if (machineID == NULL) {
|
||||
romInfo = ROMInfo::getROMInfo(romFile);
|
||||
} else {
|
||||
const MachineConfiguration *configuration = findMachineConfiguration(machineID);
|
||||
if (configuration == NULL) {
|
||||
fillROMInfo(rom_info, NULL, NULL);
|
||||
return MT32EMU_RC_MACHINE_NOT_IDENTIFIED;
|
||||
}
|
||||
romInfo = ROMInfo::getROMInfo(romFile, configuration->getCompatibleROMInfos());
|
||||
}
|
||||
if (romInfo == NULL) {
|
||||
fillROMInfo(rom_info, NULL, NULL);
|
||||
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;
|
||||
if (romInfo->type == ROMInfo::Control) fillROMInfo(rom_info, romInfo, NULL);
|
||||
else if (romInfo->type == ROMInfo::PCM) fillROMInfo(rom_info, NULL, romInfo);
|
||||
else fillROMInfo(rom_info, NULL, NULL);
|
||||
return MT32EMU_RC_OK;
|
||||
}
|
||||
|
||||
static bool isROMInfoCompatible(const MachineConfiguration *machineConfiguration, const ROMInfo *romInfo) {
|
||||
Bit32u romCount;
|
||||
const ROMInfo * const *compatibleROMInfos = machineConfiguration->getCompatibleROMInfos(&romCount);
|
||||
for (Bit32u i = 0; i < romCount; i++) {
|
||||
if (romInfo == compatibleROMInfos[i]) return true;
|
||||
}
|
||||
ROMImage::freeROMImage(image);
|
||||
return MT32EMU_RC_OK; // No support for reverb ROM yet.
|
||||
return false;
|
||||
}
|
||||
|
||||
static mt32emu_return_code replaceOrMergeROMImage(const ROMImage *&contextROMImage, const ROMImage *newROMImage, const MachineConfiguration *machineConfiguration, mt32emu_return_code addedFullROM, mt32emu_return_code addedPartialROM) {
|
||||
if (contextROMImage != NULL) {
|
||||
if (machineConfiguration != NULL) {
|
||||
const ROMImage *mergedROMImage = ROMImage::mergeROMImages(contextROMImage, newROMImage);
|
||||
if (mergedROMImage != NULL) {
|
||||
if (newROMImage->isFileUserProvided()) delete newROMImage->getFile();
|
||||
ROMImage::freeROMImage(newROMImage);
|
||||
if (contextROMImage->isFileUserProvided()) delete contextROMImage->getFile();
|
||||
ROMImage::freeROMImage(contextROMImage);
|
||||
contextROMImage = mergedROMImage;
|
||||
return addedFullROM;
|
||||
}
|
||||
if (newROMImage->getROMInfo() == contextROMImage->getROMInfo()
|
||||
|| (newROMImage->getROMInfo()->pairType != ROMInfo::Full
|
||||
&& isROMInfoCompatible(machineConfiguration, contextROMImage->getROMInfo()))) {
|
||||
ROMImage::freeROMImage(newROMImage);
|
||||
return MT32EMU_RC_OK;
|
||||
}
|
||||
}
|
||||
if (contextROMImage->isFileUserProvided()) delete contextROMImage->getFile();
|
||||
ROMImage::freeROMImage(contextROMImage);
|
||||
}
|
||||
contextROMImage = newROMImage;
|
||||
return newROMImage->getROMInfo()->pairType == ROMInfo::Full ? addedFullROM: addedPartialROM;
|
||||
}
|
||||
|
||||
static mt32emu_return_code addROMFiles(mt32emu_data *data, File *file1, File *file2 = NULL, const MachineConfiguration *machineConfiguration = NULL) {
|
||||
const ROMImage *romImage;
|
||||
if (machineConfiguration != NULL) {
|
||||
romImage = ROMImage::makeROMImage(file1, machineConfiguration->getCompatibleROMInfos());
|
||||
} else {
|
||||
romImage = file2 == NULL ? ROMImage::makeROMImage(file1, ROMInfo::getFullROMInfos()) : ROMImage::makeROMImage(file1, file2);
|
||||
}
|
||||
if (romImage == NULL) return MT32EMU_RC_ROMS_NOT_PAIRABLE;
|
||||
const ROMInfo *info = romImage->getROMInfo();
|
||||
if (info == NULL) {
|
||||
ROMImage::freeROMImage(romImage);
|
||||
return MT32EMU_RC_ROM_NOT_IDENTIFIED;
|
||||
}
|
||||
switch (info->type) {
|
||||
case ROMInfo::Control:
|
||||
return replaceOrMergeROMImage(data->controlROMImage, romImage, machineConfiguration, MT32EMU_RC_ADDED_CONTROL_ROM, MT32EMU_RC_ADDED_PARTIAL_CONTROL_ROM);
|
||||
case ROMInfo::PCM:
|
||||
return replaceOrMergeROMImage(data->pcmROMImage, romImage, machineConfiguration, MT32EMU_RC_ADDED_PCM_ROM, MT32EMU_RC_ADDED_PARTIAL_PCM_ROM);
|
||||
default:
|
||||
ROMImage::freeROMImage(romImage);
|
||||
return MT32EMU_RC_OK; // No support for reverb ROM yet.
|
||||
}
|
||||
}
|
||||
|
||||
static mt32emu_return_code createFileStream(const char *filename, FileStream *&fileStream) {
|
||||
mt32emu_return_code rc;
|
||||
fileStream = new FileStream;
|
||||
if (!fileStream->open(filename)) {
|
||||
rc = MT32EMU_RC_FILE_NOT_FOUND;
|
||||
} else if (fileStream->getSize() == 0) {
|
||||
rc = MT32EMU_RC_FILE_NOT_LOADED;
|
||||
} else {
|
||||
return MT32EMU_RC_OK;
|
||||
}
|
||||
delete fileStream;
|
||||
fileStream = NULL;
|
||||
return rc;
|
||||
}
|
||||
|
||||
} // namespace MT32Emu
|
||||
@@ -327,40 +464,92 @@ static mt32emu_return_code addROMFile(mt32emu_data *data, File *file) {
|
||||
|
||||
extern "C" {
|
||||
|
||||
mt32emu_service_i mt32emu_get_service_i() {
|
||||
mt32emu_service_i MT32EMU_C_CALL mt32emu_get_service_i() {
|
||||
mt32emu_service_i i;
|
||||
i.v3 = &SERVICE_VTABLE;
|
||||
i.v6 = &SERVICE_VTABLE;
|
||||
return i;
|
||||
}
|
||||
|
||||
mt32emu_report_handler_version mt32emu_get_supported_report_handler_version() {
|
||||
mt32emu_report_handler_version MT32EMU_C_CALL mt32emu_get_supported_report_handler_version() {
|
||||
return MT32EMU_REPORT_HANDLER_VERSION_CURRENT;
|
||||
}
|
||||
|
||||
mt32emu_midi_receiver_version mt32emu_get_supported_midi_receiver_version() {
|
||||
mt32emu_midi_receiver_version MT32EMU_C_CALL mt32emu_get_supported_midi_receiver_version() {
|
||||
return MT32EMU_MIDI_RECEIVER_VERSION_CURRENT;
|
||||
}
|
||||
|
||||
mt32emu_bit32u mt32emu_get_library_version_int() {
|
||||
mt32emu_bit32u MT32EMU_C_CALL mt32emu_get_library_version_int() {
|
||||
return Synth::getLibraryVersionInt();
|
||||
}
|
||||
|
||||
const char *mt32emu_get_library_version_string() {
|
||||
const char * MT32EMU_C_CALL mt32emu_get_library_version_string() {
|
||||
return Synth::getLibraryVersionString();
|
||||
}
|
||||
|
||||
mt32emu_bit32u mt32emu_get_stereo_output_samplerate(const mt32emu_analog_output_mode analog_output_mode) {
|
||||
mt32emu_bit32u MT32EMU_C_CALL mt32emu_get_stereo_output_samplerate(const mt32emu_analog_output_mode analog_output_mode) {
|
||||
return Synth::getStereoOutputSampleRate(static_cast<AnalogOutputMode>(analog_output_mode));
|
||||
}
|
||||
|
||||
mt32emu_analog_output_mode mt32emu_get_best_analog_output_mode(const double target_samplerate) {
|
||||
mt32emu_analog_output_mode MT32EMU_C_CALL mt32emu_get_best_analog_output_mode(const double target_samplerate) {
|
||||
return mt32emu_analog_output_mode(SampleRateConverter::getBestAnalogOutputMode(target_samplerate));
|
||||
}
|
||||
|
||||
mt32emu_context mt32emu_create_context(mt32emu_report_handler_i report_handler, void *instance_data) {
|
||||
size_t MT32EMU_C_CALL mt32emu_get_machine_ids(const char **machine_ids, size_t machine_ids_size) {
|
||||
Bit32u configurationCount;
|
||||
const MachineConfiguration * const *configurations = MachineConfiguration::getAllMachineConfigurations(&configurationCount);
|
||||
if (machine_ids != NULL) {
|
||||
for (Bit32u i = 0; i < machine_ids_size; i++) {
|
||||
machine_ids[i] = i < configurationCount ? configurations[i]->getMachineID() : NULL;
|
||||
}
|
||||
}
|
||||
return configurationCount;
|
||||
}
|
||||
|
||||
size_t MT32EMU_C_CALL mt32emu_get_rom_ids(const char **rom_ids, size_t rom_ids_size, const char *machine_id) {
|
||||
const ROMInfo * const *romInfos;
|
||||
Bit32u romCount;
|
||||
if (machine_id != NULL) {
|
||||
const MachineConfiguration *configuration = findMachineConfiguration(machine_id);
|
||||
if (configuration != NULL) {
|
||||
romInfos = configuration->getCompatibleROMInfos(&romCount);
|
||||
} else {
|
||||
romInfos = NULL;
|
||||
romCount = 0U;
|
||||
}
|
||||
} else {
|
||||
romInfos = ROMInfo::getAllROMInfos(&romCount);
|
||||
}
|
||||
if (rom_ids != NULL) {
|
||||
for (size_t i = 0; i < rom_ids_size; i++) {
|
||||
rom_ids[i] = i < romCount ? romInfos[i]->shortName : NULL;
|
||||
}
|
||||
}
|
||||
return romCount;
|
||||
}
|
||||
|
||||
mt32emu_return_code MT32EMU_C_CALL mt32emu_identify_rom_data(mt32emu_rom_info *rom_info, const mt32emu_bit8u *data, size_t data_size, const char *machine_id) {
|
||||
ArrayFile romFile = ArrayFile(data, data_size);
|
||||
return identifyROM(rom_info, &romFile, machine_id);
|
||||
}
|
||||
|
||||
mt32emu_return_code MT32EMU_C_CALL mt32emu_identify_rom_file(mt32emu_rom_info *rom_info, const char *filename, const char *machine_id) {
|
||||
FileStream *fs;
|
||||
mt32emu_return_code rc = createFileStream(filename, fs);
|
||||
if (fs == NULL) return rc;
|
||||
rc = identifyROM(rom_info, fs, machine_id);
|
||||
delete fs;
|
||||
return rc;
|
||||
}
|
||||
|
||||
mt32emu_context MT32EMU_C_CALL 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->synth = new Synth;
|
||||
if (report_handler.v0 != NULL) {
|
||||
data->reportHandler = new DelegatingReportHandlerAdapter(report_handler, instance_data);
|
||||
data->synth->setReportHandler2(data->reportHandler);
|
||||
} else {
|
||||
data->reportHandler = NULL;
|
||||
}
|
||||
data->midiParser = new DefaultMidiStreamParser(*data->synth);
|
||||
data->controlROMImage = NULL;
|
||||
data->pcmROMImage = NULL;
|
||||
@@ -375,7 +564,7 @@ mt32emu_context mt32emu_create_context(mt32emu_report_handler_i report_handler,
|
||||
return data;
|
||||
}
|
||||
|
||||
void mt32emu_free_context(mt32emu_context data) {
|
||||
void MT32EMU_C_CALL mt32emu_free_context(mt32emu_context data) {
|
||||
if (data == NULL) return;
|
||||
|
||||
delete data->srcState->src;
|
||||
@@ -384,12 +573,12 @@ void mt32emu_free_context(mt32emu_context data) {
|
||||
data->srcState = NULL;
|
||||
|
||||
if (data->controlROMImage != NULL) {
|
||||
delete data->controlROMImage->getFile();
|
||||
if (data->controlROMImage->isFileUserProvided()) delete data->controlROMImage->getFile();
|
||||
ROMImage::freeROMImage(data->controlROMImage);
|
||||
data->controlROMImage = NULL;
|
||||
}
|
||||
if (data->pcmROMImage != NULL) {
|
||||
delete data->pcmROMImage->getFile();
|
||||
if (data->pcmROMImage->isFileUserProvided()) delete data->pcmROMImage->getFile();
|
||||
ROMImage::freeROMImage(data->pcmROMImage);
|
||||
data->pcmROMImage = NULL;
|
||||
}
|
||||
@@ -402,76 +591,86 @@ void mt32emu_free_context(mt32emu_context data) {
|
||||
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_C_CALL 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 addROMFiles(context, new ArrayFile(data, data_size));
|
||||
return addROMFiles(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;
|
||||
mt32emu_return_code MT32EMU_C_CALL mt32emu_add_rom_file(mt32emu_context context, const char *filename) {
|
||||
FileStream *fs;
|
||||
mt32emu_return_code rc = createFileStream(filename, fs);
|
||||
if (fs != NULL) rc = addROMFiles(context, fs);
|
||||
if (rc <= MT32EMU_RC_OK) 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;
|
||||
}
|
||||
mt32emu_return_code MT32EMU_C_CALL mt32emu_merge_and_add_rom_data(mt32emu_context context, const mt32emu_bit8u *part1_data, size_t part1_data_size, const mt32emu_sha1_digest *part1_sha1_digest, const mt32emu_bit8u *part2_data, size_t part2_data_size, const mt32emu_sha1_digest *part2_sha1_digest) {
|
||||
ArrayFile *file1 = part1_sha1_digest == NULL ? new ArrayFile(part1_data, part1_data_size) : new ArrayFile(part1_data, part1_data_size, *part1_sha1_digest);
|
||||
ArrayFile *file2 = part2_sha1_digest == NULL ? new ArrayFile(part2_data, part2_data_size) : new ArrayFile(part2_data, part2_data_size, *part2_sha1_digest);
|
||||
mt32emu_return_code rc = addROMFiles(context, file1, file2);
|
||||
delete file1;
|
||||
delete file2;
|
||||
return rc;
|
||||
}
|
||||
|
||||
void mt32emu_set_partial_count(mt32emu_context context, const mt32emu_bit32u partial_count) {
|
||||
mt32emu_return_code MT32EMU_C_CALL mt32emu_merge_and_add_rom_files(mt32emu_context context, const char *part1_filename, const char *part2_filename) {
|
||||
FileStream *fs1;
|
||||
mt32emu_return_code rc = createFileStream(part1_filename, fs1);
|
||||
if (fs1 != NULL) {
|
||||
FileStream *fs2;
|
||||
rc = createFileStream(part2_filename, fs2);
|
||||
if (fs2 != NULL) {
|
||||
rc = addROMFiles(context, fs1, fs2);
|
||||
delete fs2;
|
||||
}
|
||||
delete fs1;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
mt32emu_return_code MT32EMU_C_CALL mt32emu_add_machine_rom_file(mt32emu_context context, const char *machine_id, const char *filename) {
|
||||
const MachineConfiguration *machineConfiguration = findMachineConfiguration(machine_id);
|
||||
if (machineConfiguration == NULL) return MT32EMU_RC_MACHINE_NOT_IDENTIFIED;
|
||||
|
||||
FileStream *fs;
|
||||
mt32emu_return_code rc = createFileStream(filename, fs);
|
||||
if (fs == NULL) return rc;
|
||||
rc = addROMFiles(context, fs, NULL, machineConfiguration);
|
||||
if (rc <= MT32EMU_RC_OK) delete fs;
|
||||
return rc;
|
||||
}
|
||||
|
||||
void MT32EMU_C_CALL mt32emu_get_rom_info(mt32emu_const_context context, mt32emu_rom_info *rom_info) {
|
||||
const ROMInfo *controlROMInfo = context->controlROMImage == NULL ? NULL : context->controlROMImage->getROMInfo();
|
||||
const ROMInfo *pcmROMInfo = context->pcmROMImage == NULL ? NULL : context->pcmROMImage->getROMInfo();
|
||||
fillROMInfo(rom_info, controlROMInfo, pcmROMInfo);
|
||||
}
|
||||
|
||||
void MT32EMU_C_CALL 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) {
|
||||
void MT32EMU_C_CALL mt32emu_set_analog_output_mode(mt32emu_context context, const mt32emu_analog_output_mode analog_output_mode) {
|
||||
context->analogOutputMode = static_cast<AnalogOutputMode>(analog_output_mode);
|
||||
}
|
||||
|
||||
void mt32emu_set_stereo_output_samplerate(mt32emu_context context, const double samplerate) {
|
||||
void MT32EMU_C_CALL mt32emu_set_stereo_output_samplerate(mt32emu_context context, const double samplerate) {
|
||||
context->srcState->outputSampleRate = SampleRateConverter::getSupportedOutputSampleRate(samplerate);
|
||||
}
|
||||
|
||||
void mt32emu_set_samplerate_conversion_quality(mt32emu_context context, const mt32emu_samplerate_conversion_quality quality) {
|
||||
void MT32EMU_C_CALL mt32emu_set_samplerate_conversion_quality(mt32emu_context context, const mt32emu_samplerate_conversion_quality quality) {
|
||||
context->srcState->srcQuality = SamplerateConversionQuality(quality);
|
||||
}
|
||||
|
||||
void mt32emu_select_renderer_type(mt32emu_context context, const mt32emu_renderer_type renderer_type) {
|
||||
void MT32EMU_C_CALL mt32emu_select_renderer_type(mt32emu_context context, const mt32emu_renderer_type renderer_type) {
|
||||
context->synth->selectRendererType(static_cast<RendererType>(renderer_type));
|
||||
}
|
||||
|
||||
mt32emu_renderer_type mt32emu_get_selected_renderer_type(mt32emu_context context) {
|
||||
mt32emu_renderer_type MT32EMU_C_CALL mt32emu_get_selected_renderer_type(mt32emu_context context) {
|
||||
return static_cast<mt32emu_renderer_type>(context->synth->getSelectedRendererType());
|
||||
}
|
||||
|
||||
mt32emu_return_code mt32emu_open_synth(mt32emu_const_context context) {
|
||||
mt32emu_return_code MT32EMU_C_CALL mt32emu_open_synth(mt32emu_const_context context) {
|
||||
if ((context->controlROMImage == NULL) || (context->pcmROMImage == NULL)) {
|
||||
return MT32EMU_RC_MISSING_ROMS;
|
||||
}
|
||||
@@ -484,211 +683,219 @@ mt32emu_return_code mt32emu_open_synth(mt32emu_const_context context) {
|
||||
return MT32EMU_RC_OK;
|
||||
}
|
||||
|
||||
void mt32emu_close_synth(mt32emu_const_context context) {
|
||||
void MT32EMU_C_CALL mt32emu_close_synth(mt32emu_const_context context) {
|
||||
context->synth->close();
|
||||
delete context->srcState->src;
|
||||
context->srcState->src = NULL;
|
||||
}
|
||||
|
||||
mt32emu_boolean mt32emu_is_open(mt32emu_const_context context) {
|
||||
mt32emu_boolean MT32EMU_C_CALL 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) {
|
||||
mt32emu_bit32u MT32EMU_C_CALL mt32emu_get_actual_stereo_output_samplerate(mt32emu_const_context context) {
|
||||
if (context->srcState->src == NULL) {
|
||||
return context->synth->getStereoOutputSampleRate();
|
||||
}
|
||||
return mt32emu_bit32u(0.5 + context->srcState->src->convertSynthToOutputTimestamp(SAMPLE_RATE));
|
||||
}
|
||||
|
||||
mt32emu_bit32u mt32emu_convert_output_to_synth_timestamp(mt32emu_const_context context, mt32emu_bit32u output_timestamp) {
|
||||
mt32emu_bit32u MT32EMU_C_CALL mt32emu_convert_output_to_synth_timestamp(mt32emu_const_context context, mt32emu_bit32u output_timestamp) {
|
||||
if (context->srcState->src == NULL) {
|
||||
return output_timestamp;
|
||||
}
|
||||
return mt32emu_bit32u(0.5 + context->srcState->src->convertOutputToSynthTimestamp(output_timestamp));
|
||||
}
|
||||
|
||||
mt32emu_bit32u mt32emu_convert_synth_to_output_timestamp(mt32emu_const_context context, mt32emu_bit32u synth_timestamp) {
|
||||
mt32emu_bit32u MT32EMU_C_CALL mt32emu_convert_synth_to_output_timestamp(mt32emu_const_context context, mt32emu_bit32u synth_timestamp) {
|
||||
if (context->srcState->src == NULL) {
|
||||
return synth_timestamp;
|
||||
}
|
||||
return mt32emu_bit32u(0.5 + context->srcState->src->convertSynthToOutputTimestamp(synth_timestamp));
|
||||
}
|
||||
|
||||
void mt32emu_flush_midi_queue(mt32emu_const_context context) {
|
||||
void MT32EMU_C_CALL 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) {
|
||||
mt32emu_bit32u MT32EMU_C_CALL mt32emu_set_midi_event_queue_size(mt32emu_const_context context, const mt32emu_bit32u queue_size) {
|
||||
return context->synth->setMIDIEventQueueSize(queue_size);
|
||||
}
|
||||
|
||||
void mt32emu_configure_midi_event_queue_sysex_storage(mt32emu_const_context context, const mt32emu_bit32u storage_buffer_size) {
|
||||
return context->synth->configureMIDIEventQueueSysexStorage(storage_buffer_size);
|
||||
void MT32EMU_C_CALL mt32emu_configure_midi_event_queue_sysex_storage(mt32emu_const_context context, const mt32emu_bit32u storage_buffer_size) {
|
||||
context->synth->configureMIDIEventQueueSysexStorage(storage_buffer_size);
|
||||
}
|
||||
|
||||
void mt32emu_set_midi_receiver(mt32emu_context context, mt32emu_midi_receiver_i midi_receiver, void *instance_data) {
|
||||
void MT32EMU_C_CALL 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);
|
||||
}
|
||||
|
||||
mt32emu_bit32u mt32emu_get_internal_rendered_sample_count(mt32emu_const_context context) {
|
||||
mt32emu_bit32u MT32EMU_C_CALL mt32emu_get_internal_rendered_sample_count(mt32emu_const_context context) {
|
||||
return context->synth->getInternalRenderedSampleCount();
|
||||
}
|
||||
|
||||
void mt32emu_parse_stream(mt32emu_const_context context, const mt32emu_bit8u *stream, mt32emu_bit32u length) {
|
||||
void MT32EMU_C_CALL 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) {
|
||||
void MT32EMU_C_CALL 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) {
|
||||
void MT32EMU_C_CALL 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) {
|
||||
void MT32EMU_C_CALL 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) {
|
||||
mt32emu_return_code MT32EMU_C_CALL 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) {
|
||||
mt32emu_return_code MT32EMU_C_CALL 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) {
|
||||
mt32emu_return_code MT32EMU_C_CALL 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) {
|
||||
mt32emu_return_code MT32EMU_C_CALL 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) {
|
||||
void MT32EMU_C_CALL 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) {
|
||||
void MT32EMU_C_CALL 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) {
|
||||
void MT32EMU_C_CALL 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) {
|
||||
void MT32EMU_C_CALL 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) {
|
||||
void MT32EMU_C_CALL 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) {
|
||||
mt32emu_boolean MT32EMU_C_CALL 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) {
|
||||
void MT32EMU_C_CALL 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) {
|
||||
mt32emu_boolean MT32EMU_C_CALL 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) {
|
||||
void MT32EMU_C_CALL 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) {
|
||||
mt32emu_boolean MT32EMU_C_CALL 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) {
|
||||
mt32emu_boolean MT32EMU_C_CALL mt32emu_is_default_reverb_mt32_compatible(mt32emu_const_context context) {
|
||||
return context->synth->isDefaultReverbMT32Compatible() ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE;
|
||||
}
|
||||
|
||||
void mt32emu_preallocate_reverb_memory(mt32emu_const_context context, const mt32emu_boolean enabled) {
|
||||
return context->synth->preallocateReverbMemory(enabled != MT32EMU_BOOL_FALSE);
|
||||
void MT32EMU_C_CALL mt32emu_preallocate_reverb_memory(mt32emu_const_context context, const mt32emu_boolean enabled) {
|
||||
context->synth->preallocateReverbMemory(enabled != MT32EMU_BOOL_FALSE);
|
||||
}
|
||||
|
||||
void mt32emu_set_dac_input_mode(mt32emu_const_context context, const mt32emu_dac_input_mode mode) {
|
||||
void MT32EMU_C_CALL 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) {
|
||||
mt32emu_dac_input_mode MT32EMU_C_CALL 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) {
|
||||
void MT32EMU_C_CALL 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) {
|
||||
mt32emu_midi_delay_mode MT32EMU_C_CALL 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) {
|
||||
void MT32EMU_C_CALL mt32emu_set_output_gain(mt32emu_const_context context, float gain) {
|
||||
context->synth->setOutputGain(gain);
|
||||
}
|
||||
|
||||
float mt32emu_get_output_gain(mt32emu_const_context context) {
|
||||
float MT32EMU_C_CALL mt32emu_get_output_gain(mt32emu_const_context context) {
|
||||
return context->synth->getOutputGain();
|
||||
}
|
||||
|
||||
void mt32emu_set_reverb_output_gain(mt32emu_const_context context, float gain) {
|
||||
void MT32EMU_C_CALL 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) {
|
||||
float MT32EMU_C_CALL 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) {
|
||||
void MT32EMU_C_CALL mt32emu_set_part_volume_override(mt32emu_const_context context, mt32emu_bit8u part_number, mt32emu_bit8u volume_override) {
|
||||
context->synth->setPartVolumeOverride(part_number, volume_override);
|
||||
}
|
||||
|
||||
mt32emu_bit8u MT32EMU_C_CALL mt32emu_get_part_volume_override(mt32emu_const_context context, mt32emu_bit8u part_number) {
|
||||
return context->synth->getPartVolumeOverride(part_number);
|
||||
}
|
||||
|
||||
void MT32EMU_C_CALL 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) {
|
||||
mt32emu_boolean MT32EMU_C_CALL mt32emu_is_reversed_stereo_enabled(mt32emu_const_context context) {
|
||||
return context->synth->isReversedStereoEnabled() ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE;
|
||||
}
|
||||
|
||||
void mt32emu_set_nice_amp_ramp_enabled(mt32emu_const_context context, const mt32emu_boolean enabled) {
|
||||
void MT32EMU_C_CALL mt32emu_set_nice_amp_ramp_enabled(mt32emu_const_context context, const mt32emu_boolean enabled) {
|
||||
context->synth->setNiceAmpRampEnabled(enabled != MT32EMU_BOOL_FALSE);
|
||||
}
|
||||
|
||||
mt32emu_boolean mt32emu_is_nice_amp_ramp_enabled(mt32emu_const_context context) {
|
||||
mt32emu_boolean MT32EMU_C_CALL mt32emu_is_nice_amp_ramp_enabled(mt32emu_const_context context) {
|
||||
return context->synth->isNiceAmpRampEnabled() ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE;
|
||||
}
|
||||
|
||||
MT32EMU_EXPORT void mt32emu_set_nice_panning_enabled(mt32emu_const_context context, const mt32emu_boolean enabled) {
|
||||
void MT32EMU_C_CALL mt32emu_set_nice_panning_enabled(mt32emu_const_context context, const mt32emu_boolean enabled) {
|
||||
context->synth->setNicePanningEnabled(enabled != MT32EMU_BOOL_FALSE);
|
||||
}
|
||||
|
||||
MT32EMU_EXPORT mt32emu_boolean mt32emu_is_nice_panning_enabled(mt32emu_const_context context) {
|
||||
mt32emu_boolean MT32EMU_C_CALL mt32emu_is_nice_panning_enabled(mt32emu_const_context context) {
|
||||
return context->synth->isNicePanningEnabled() ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE;
|
||||
}
|
||||
|
||||
MT32EMU_EXPORT void mt32emu_set_nice_partial_mixing_enabled(mt32emu_const_context context, const mt32emu_boolean enabled) {
|
||||
void MT32EMU_C_CALL mt32emu_set_nice_partial_mixing_enabled(mt32emu_const_context context, const mt32emu_boolean enabled) {
|
||||
context->synth->setNicePartialMixingEnabled(enabled != MT32EMU_BOOL_FALSE);
|
||||
}
|
||||
|
||||
MT32EMU_EXPORT mt32emu_boolean mt32emu_is_nice_partial_mixing_enabled(mt32emu_const_context context) {
|
||||
mt32emu_boolean MT32EMU_C_CALL mt32emu_is_nice_partial_mixing_enabled(mt32emu_const_context context) {
|
||||
return context->synth->isNicePartialMixingEnabled() ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE;
|
||||
}
|
||||
|
||||
void mt32emu_render_bit16s(mt32emu_const_context context, mt32emu_bit16s *stream, mt32emu_bit32u len) {
|
||||
void MT32EMU_C_CALL mt32emu_render_bit16s(mt32emu_const_context context, mt32emu_bit16s *stream, mt32emu_bit32u len) {
|
||||
if (context->srcState->src != NULL) {
|
||||
context->srcState->src->getOutputSamples(stream, len);
|
||||
} else {
|
||||
@@ -696,7 +903,7 @@ void mt32emu_render_bit16s(mt32emu_const_context context, mt32emu_bit16s *stream
|
||||
}
|
||||
}
|
||||
|
||||
void mt32emu_render_float(mt32emu_const_context context, float *stream, mt32emu_bit32u len) {
|
||||
void MT32EMU_C_CALL mt32emu_render_float(mt32emu_const_context context, float *stream, mt32emu_bit32u len) {
|
||||
if (context->srcState->src != NULL) {
|
||||
context->srcState->src->getOutputSamples(stream, len);
|
||||
} else {
|
||||
@@ -704,44 +911,72 @@ void mt32emu_render_float(mt32emu_const_context context, float *stream, mt32emu_
|
||||
}
|
||||
}
|
||||
|
||||
void mt32emu_render_bit16s_streams(mt32emu_const_context context, const mt32emu_dac_output_bit16s_streams *streams, mt32emu_bit32u len) {
|
||||
void MT32EMU_C_CALL mt32emu_render_bit16s_streams(mt32emu_const_context context, const mt32emu_dac_output_bit16s_streams *streams, mt32emu_bit32u len) {
|
||||
context->synth->renderStreams(*reinterpret_cast<const DACOutputStreams<Bit16s> *>(streams), len);
|
||||
}
|
||||
|
||||
void mt32emu_render_float_streams(mt32emu_const_context context, const mt32emu_dac_output_float_streams *streams, mt32emu_bit32u len) {
|
||||
void MT32EMU_C_CALL mt32emu_render_float_streams(mt32emu_const_context context, const mt32emu_dac_output_float_streams *streams, mt32emu_bit32u len) {
|
||||
context->synth->renderStreams(*reinterpret_cast<const DACOutputStreams<float> *>(streams), len);
|
||||
}
|
||||
|
||||
mt32emu_boolean mt32emu_has_active_partials(mt32emu_const_context context) {
|
||||
mt32emu_boolean MT32EMU_C_CALL 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) {
|
||||
mt32emu_boolean MT32EMU_C_CALL 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) {
|
||||
mt32emu_bit32u MT32EMU_C_CALL mt32emu_get_partial_count(mt32emu_const_context context) {
|
||||
return context->synth->getPartialCount();
|
||||
}
|
||||
|
||||
mt32emu_bit32u mt32emu_get_part_states(mt32emu_const_context context) {
|
||||
mt32emu_bit32u MT32EMU_C_CALL 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) {
|
||||
void MT32EMU_C_CALL 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) {
|
||||
mt32emu_bit32u MT32EMU_C_CALL 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) {
|
||||
const char * MT32EMU_C_CALL 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) {
|
||||
mt32emu_boolean MT32EMU_C_CALL mt32emu_get_sound_group_name(mt32emu_const_context context, char *sound_group_name, mt32emu_bit8u timbre_group, mt32emu_bit8u timbre_number) {
|
||||
return context->synth->getSoundGroupName(sound_group_name, timbre_group, timbre_number) ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE;
|
||||
}
|
||||
|
||||
mt32emu_boolean MT32EMU_C_CALL mt32emu_get_sound_name(mt32emu_const_context context, char *sound_name, mt32emu_bit8u timbre_group, mt32emu_bit8u timbre_number) {
|
||||
return context->synth->getSoundName(sound_name, timbre_group, timbre_number) ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE;
|
||||
}
|
||||
|
||||
void MT32EMU_C_CALL mt32emu_read_memory(mt32emu_const_context context, mt32emu_bit32u addr, mt32emu_bit32u len, mt32emu_bit8u *data) {
|
||||
context->synth->readMemory(addr, len, data);
|
||||
}
|
||||
|
||||
mt32emu_boolean MT32EMU_C_CALL mt32emu_get_display_state(mt32emu_const_context context, char *target_buffer, const mt32emu_boolean narrow_lcd) {
|
||||
return context->synth->getDisplayState(target_buffer, narrow_lcd != MT32EMU_BOOL_FALSE) ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE;
|
||||
}
|
||||
|
||||
void MT32EMU_C_CALL mt32emu_set_main_display_mode(mt32emu_const_context context) {
|
||||
context->synth->setMainDisplayMode();
|
||||
}
|
||||
|
||||
void MT32EMU_C_CALL mt32emu_set_display_compatibility(mt32emu_const_context context, mt32emu_boolean old_mt32_compatibility_enabled) {
|
||||
context->synth->setDisplayCompatibility(old_mt32_compatibility_enabled != MT32EMU_BOOL_FALSE);
|
||||
}
|
||||
|
||||
mt32emu_boolean MT32EMU_C_CALL mt32emu_is_display_old_mt32_compatible(mt32emu_const_context context) {
|
||||
return context->synth->isDisplayOldMT32Compatible() ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE;
|
||||
}
|
||||
|
||||
mt32emu_boolean MT32EMU_C_CALL mt32emu_is_default_display_old_mt32_compatible(mt32emu_const_context context) {
|
||||
return context->synth->isDefaultDisplayOldMT32Compatible() ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
@@ -24,7 +24,9 @@
|
||||
#include "c_types.h"
|
||||
|
||||
#undef MT32EMU_EXPORT
|
||||
#undef MT32EMU_EXPORT_V
|
||||
#define MT32EMU_EXPORT MT32EMU_EXPORT_ATTRIBUTE
|
||||
#define MT32EMU_EXPORT_V(symbol_version_tag) MT32EMU_EXPORT
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -35,24 +37,28 @@ extern "C" {
|
||||
/* === Interface handling === */
|
||||
|
||||
/** Returns mt32emu_service_i interface. */
|
||||
MT32EMU_EXPORT mt32emu_service_i mt32emu_get_service_i(void);
|
||||
MT32EMU_EXPORT mt32emu_service_i MT32EMU_C_CALL mt32emu_get_service_i(void);
|
||||
|
||||
#if MT32EMU_EXPORTS_TYPE == 2
|
||||
#undef MT32EMU_EXPORT
|
||||
#undef MT32EMU_EXPORT_V
|
||||
#define MT32EMU_EXPORT
|
||||
#define MT32EMU_EXPORT_V(symbol_version_tag) 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(void);
|
||||
MT32EMU_EXPORT mt32emu_report_handler_version MT32EMU_C_CALL mt32emu_get_supported_report_handler_version(void);
|
||||
|
||||
/**
|
||||
* 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(void);
|
||||
MT32EMU_EXPORT mt32emu_midi_receiver_version MT32EMU_C_CALL mt32emu_get_supported_midi_receiver_version(void);
|
||||
|
||||
/* === Utility === */
|
||||
|
||||
/**
|
||||
* Returns library version as an integer in format: 0x00MMmmpp, where:
|
||||
@@ -60,67 +66,149 @@ MT32EMU_EXPORT mt32emu_midi_receiver_version mt32emu_get_supported_midi_receiver
|
||||
* mm - minor version number
|
||||
* pp - patch number
|
||||
*/
|
||||
MT32EMU_EXPORT mt32emu_bit32u mt32emu_get_library_version_int(void);
|
||||
MT32EMU_EXPORT mt32emu_bit32u MT32EMU_C_CALL mt32emu_get_library_version_int(void);
|
||||
|
||||
/**
|
||||
* Returns library version as a C-string in format: "MAJOR.MINOR.PATCH".
|
||||
*/
|
||||
MT32EMU_EXPORT const char *mt32emu_get_library_version_string(void);
|
||||
MT32EMU_EXPORT const char * MT32EMU_C_CALL mt32emu_get_library_version_string(void);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
MT32EMU_EXPORT mt32emu_bit32u MT32EMU_C_CALL mt32emu_get_stereo_output_samplerate(const mt32emu_analog_output_mode analog_output_mode);
|
||||
|
||||
/**
|
||||
* Returns the value of analog_output_mode for which the output signal may retain its full frequency spectrum
|
||||
* at the sample rate specified by the target_samplerate argument.
|
||||
* See comment for mt32emu_analog_output_mode.
|
||||
*/
|
||||
MT32EMU_EXPORT mt32emu_analog_output_mode mt32emu_get_best_analog_output_mode(const double target_samplerate);
|
||||
MT32EMU_EXPORT mt32emu_analog_output_mode MT32EMU_C_CALL mt32emu_get_best_analog_output_mode(const double target_samplerate);
|
||||
|
||||
/* === ROM handling === */
|
||||
|
||||
/**
|
||||
* Retrieves a list of identifiers (as C-strings) of supported machines. Argument machine_ids points to the array of size
|
||||
* machine_ids_size to be filled.
|
||||
* Returns the number of identifiers available for retrieval. The size of the target array to be allocated can be found
|
||||
* by passing NULL in argument machine_ids; argument machine_ids_size is ignored in this case.
|
||||
*/
|
||||
MT32EMU_EXPORT_V(2.5) size_t MT32EMU_C_CALL mt32emu_get_machine_ids(const char **machine_ids, size_t machine_ids_size);
|
||||
/**
|
||||
* Retrieves a list of identifiers (as C-strings) of supported ROM images. Argument rom_ids points to the array of size
|
||||
* rom_ids_size to be filled. Optional argument machine_id can be used to indicate a specific machine to retrieve ROM identifiers
|
||||
* for; if NULL, identifiers of all the ROM images supported by the emulation engine are retrieved.
|
||||
* Returns the number of ROM identifiers available for retrieval. The size of the target array to be allocated can be found
|
||||
* by passing NULL in argument rom_ids; argument rom_ids_size is ignored in this case. If argument machine_id contains
|
||||
* an unrecognised value, 0 is returned.
|
||||
*/
|
||||
MT32EMU_EXPORT_V(2.5) size_t MT32EMU_C_CALL mt32emu_get_rom_ids(const char **rom_ids, size_t rom_ids_size, const char *machine_id);
|
||||
|
||||
/**
|
||||
* Identifies a ROM image the provided data array contains by its SHA1 digest. Optional argument machine_id can be used to indicate
|
||||
* a specific machine to identify the ROM image for; if NULL, the ROM image is identified for any supported machine.
|
||||
* A mt32emu_rom_info structure supplied in argument rom_info is filled in accordance with the provided ROM image; unused fields
|
||||
* are filled with NULLs. If the content of the ROM image is not identified successfully (e.g. when the ROM image is incompatible
|
||||
* with the specified machine), all fields of rom_info are filled with NULLs.
|
||||
* Returns MT32EMU_RC_OK upon success or a negative error code otherwise.
|
||||
*/
|
||||
MT32EMU_EXPORT_V(2.5) mt32emu_return_code MT32EMU_C_CALL mt32emu_identify_rom_data(mt32emu_rom_info *rom_info, const mt32emu_bit8u *data, size_t data_size, const char *machine_id);
|
||||
/**
|
||||
* Loads the content of the file specified by argument filename and identifies a ROM image the file contains by its SHA1 digest.
|
||||
* Optional argument machine_id can be used to indicate a specific machine to identify the ROM image for; if NULL, the ROM image
|
||||
* is identified for any supported machine.
|
||||
* A mt32emu_rom_info structure supplied in argument rom_info is filled in accordance with the provided ROM image; unused fields
|
||||
* are filled with NULLs. If the content of the file is not identified successfully (e.g. when the ROM image is incompatible
|
||||
* with the specified machine), all fields of rom_info are filled with NULLs.
|
||||
* Returns MT32EMU_RC_OK upon success or a negative error code otherwise.
|
||||
*/
|
||||
MT32EMU_EXPORT_V(2.5) mt32emu_return_code MT32EMU_C_CALL mt32emu_identify_rom_file(mt32emu_rom_info *rom_info, const char *filename, const char *machine_id);
|
||||
|
||||
/* == 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);
|
||||
MT32EMU_EXPORT mt32emu_context MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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.
|
||||
* Adds a new full ROM data image 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().
|
||||
* The provided data array is NOT copied and used directly for efficiency. The caller should not deallocate it while the emulation
|
||||
* context is referring to the ROM data.
|
||||
* 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);
|
||||
MT32EMU_EXPORT mt32emu_return_code MT32EMU_C_CALL 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().
|
||||
* Loads a ROM file that contains a full ROM data image, identifies it by the 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);
|
||||
MT32EMU_EXPORT mt32emu_return_code MT32EMU_C_CALL mt32emu_add_rom_file(mt32emu_context context, const char *filename);
|
||||
|
||||
/**
|
||||
* Merges a pair of compatible ROM data image parts into a full image and adds it to the emulation context replacing previously
|
||||
* added ROM of the same type if any. Each partial image is identified by its SHA1 digest. Arguments partN_sha1_digest can be NULL,
|
||||
* in this case the digest will be computed using the actual ROM data. If a non-NULL SHA1 value is provided, it is assumed being
|
||||
* correct and will not be recomputed. The provided data arrays may be deallocated as soon as the function completes.
|
||||
* 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_V(2.5) mt32emu_return_code MT32EMU_C_CALL mt32emu_merge_and_add_rom_data(mt32emu_context context, const mt32emu_bit8u *part1_data, size_t part1_data_size, const mt32emu_sha1_digest *part1_sha1_digest, const mt32emu_bit8u *part2_data, size_t part2_data_size, const mt32emu_sha1_digest *part2_sha1_digest);
|
||||
|
||||
/**
|
||||
* Loads a pair of files that contains compatible parts of a full ROM image, identifies them by the SHA1 digest, merges these
|
||||
* parts into a full ROM image 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_V(2.5) mt32emu_return_code MT32EMU_C_CALL mt32emu_merge_and_add_rom_files(mt32emu_context context, const char *part1_filename, const char *part2_filename);
|
||||
|
||||
/**
|
||||
* Loads a file that contains a ROM image of a specific machine, identifies it by the SHA1 digest, and adds it to the emulation
|
||||
* context. The ROM image can only be identified successfully if it is compatible with the specified machine.
|
||||
* Full and partial ROM images are supported and handled according to the following rules:
|
||||
* - a file with any compatible ROM image is added if none (of the same type) exists in the emulation context;
|
||||
* - a file with any compatible ROM image replaces any image of the same type that is incompatible with the specified machine;
|
||||
* - a file with a full ROM image replaces the previously added partial ROM of the same type;
|
||||
* - a file with a partial ROM image is merged with the previously added ROM image if pairable;
|
||||
* - otherwise, the file is ignored.
|
||||
* The described behaviour allows the caller application to traverse a directory with ROM files attempting to add each one in turn.
|
||||
* As soon as both the full control and the full PCM ROM images are added and / or merged, the iteration can be stopped.
|
||||
* This function doesn't immediately change the state of already opened synth. Newly added ROMs will take effect upon next call of
|
||||
* mt32emu_open_synth().
|
||||
* Returns a positive value in case changes have been made, MT32EMU_RC_OK if the file has been ignored or a negative error code
|
||||
* upon failure.
|
||||
*/
|
||||
MT32EMU_EXPORT_V(2.5) mt32emu_return_code MT32EMU_C_CALL mt32emu_add_machine_rom_file(mt32emu_context context, const char *machine_id, 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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 value 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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 value 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_set_analog_output_mode(mt32emu_context context, const mt32emu_analog_output_mode analog_output_mode);
|
||||
|
||||
/**
|
||||
* Allows to convert the synthesiser output to any desired sample rate. The samplerate conversion
|
||||
@@ -131,7 +219,7 @@ MT32EMU_EXPORT void mt32emu_set_analog_output_mode(mt32emu_context context, cons
|
||||
* This function doesn't immediately change the state of already opened synth.
|
||||
* Newly set value will take effect upon next call of mt32emu_open_synth().
|
||||
*/
|
||||
MT32EMU_EXPORT void mt32emu_set_stereo_output_samplerate(mt32emu_context context, const double samplerate);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_set_stereo_output_samplerate(mt32emu_context context, const double samplerate);
|
||||
|
||||
/**
|
||||
* Several samplerate conversion quality options are provided which allow to trade-off the conversion speed vs.
|
||||
@@ -140,66 +228,66 @@ MT32EMU_EXPORT void mt32emu_set_stereo_output_samplerate(mt32emu_context context
|
||||
* This function doesn't immediately change the state of already opened synth.
|
||||
* Newly set value will take effect upon next call of mt32emu_open_synth().
|
||||
*/
|
||||
MT32EMU_EXPORT void mt32emu_set_samplerate_conversion_quality(mt32emu_context context, const mt32emu_samplerate_conversion_quality quality);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_set_samplerate_conversion_quality(mt32emu_context context, const mt32emu_samplerate_conversion_quality quality);
|
||||
|
||||
/**
|
||||
* Selects new type of the wave generator and renderer to be used during subsequent calls to mt32emu_open_synth().
|
||||
* By default, MT32EMU_RT_BIT16S is selected.
|
||||
* See mt32emu_renderer_type for details.
|
||||
*/
|
||||
MT32EMU_EXPORT void mt32emu_select_renderer_type(mt32emu_context context, const mt32emu_renderer_type renderer_type);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_select_renderer_type(mt32emu_context context, const mt32emu_renderer_type renderer_type);
|
||||
|
||||
/**
|
||||
* Returns previously selected type of the wave generator and renderer.
|
||||
* See mt32emu_renderer_type for details.
|
||||
*/
|
||||
MT32EMU_EXPORT mt32emu_renderer_type mt32emu_get_selected_renderer_type(mt32emu_context context);
|
||||
MT32EMU_EXPORT mt32emu_renderer_type MT32EMU_C_CALL mt32emu_get_selected_renderer_type(mt32emu_context context);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
MT32EMU_EXPORT mt32emu_return_code MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT mt32emu_boolean MT32EMU_C_CALL mt32emu_is_open(mt32emu_const_context context);
|
||||
|
||||
/**
|
||||
* Returns actual sample rate of the fully processed output stereo signal.
|
||||
* If samplerate conversion is used (i.e. when mt32emu_set_stereo_output_samplerate() has been invoked with a non-zero value),
|
||||
* the returned value is the desired output samplerate rounded down to the closest integer.
|
||||
* Otherwise, the output samplerate is choosen depending on the emulation mode of stereo analog circuitry of hardware units.
|
||||
* Otherwise, the output samplerate is chosen depending on the emulation mode of stereo analog circuitry of hardware units.
|
||||
* See comment for mt32emu_analog_output_mode for more info.
|
||||
*/
|
||||
MT32EMU_EXPORT mt32emu_bit32u mt32emu_get_actual_stereo_output_samplerate(mt32emu_const_context context);
|
||||
MT32EMU_EXPORT mt32emu_bit32u MT32EMU_C_CALL mt32emu_get_actual_stereo_output_samplerate(mt32emu_const_context context);
|
||||
|
||||
/**
|
||||
* Returns the number of samples produced at the internal synth sample rate (32000 Hz)
|
||||
* that correspond to the given number of samples at the output sample rate.
|
||||
* Intended to facilitate audio time synchronisation.
|
||||
*/
|
||||
MT32EMU_EXPORT mt32emu_bit32u mt32emu_convert_output_to_synth_timestamp(mt32emu_const_context context, mt32emu_bit32u output_timestamp);
|
||||
MT32EMU_EXPORT mt32emu_bit32u MT32EMU_C_CALL mt32emu_convert_output_to_synth_timestamp(mt32emu_const_context context, mt32emu_bit32u output_timestamp);
|
||||
|
||||
/**
|
||||
* Returns the number of samples produced at the output sample rate
|
||||
* that correspond to the given number of samples at the internal synth sample rate (32000 Hz).
|
||||
* Intended to facilitate audio time synchronisation.
|
||||
*/
|
||||
MT32EMU_EXPORT mt32emu_bit32u mt32emu_convert_synth_to_output_timestamp(mt32emu_const_context context, mt32emu_bit32u synth_timestamp);
|
||||
MT32EMU_EXPORT mt32emu_bit32u MT32EMU_C_CALL mt32emu_convert_synth_to_output_timestamp(mt32emu_const_context context, mt32emu_bit32u synth_timestamp);
|
||||
|
||||
/** All the enqueued events are processed by the synth immediately. */
|
||||
MT32EMU_EXPORT void mt32emu_flush_midi_queue(mt32emu_const_context context);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT mt32emu_bit32u MT32EMU_C_CALL mt32emu_set_midi_event_queue_size(mt32emu_const_context context, const mt32emu_bit32u queue_size);
|
||||
|
||||
/**
|
||||
* Configures the SysEx storage of the internal MIDI event queue.
|
||||
@@ -212,7 +300,7 @@ MT32EMU_EXPORT mt32emu_bit32u mt32emu_set_midi_event_queue_size(mt32emu_const_co
|
||||
* by a SysEx event, that has been processed and thus is no longer necessary, is disposed instantly.
|
||||
* Note, the queue is flushed and recreated in the process so that its size remains intact.
|
||||
*/
|
||||
void mt32emu_configure_midi_event_queue_sysex_storage(mt32emu_const_context context, const mt32emu_bit32u storage_buffer_size);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_configure_midi_event_queue_sysex_storage(mt32emu_const_context context, const mt32emu_bit32u storage_buffer_size);
|
||||
|
||||
/**
|
||||
* Installs custom MIDI receiver object intended for receiving MIDI messages generated by MIDI stream parser.
|
||||
@@ -220,13 +308,13 @@ void mt32emu_configure_midi_event_queue_sysex_storage(mt32emu_const_context cont
|
||||
* 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_set_midi_receiver(mt32emu_context context, mt32emu_midi_receiver_i midi_receiver, void *instance_data);
|
||||
|
||||
/**
|
||||
* Returns current value of the global counter of samples rendered since the synth was created (at the native sample rate 32000 Hz).
|
||||
* This method helps to compute accurate timestamp of a MIDI message to use with the methods below.
|
||||
*/
|
||||
MT32EMU_EXPORT mt32emu_bit32u mt32emu_get_internal_rendered_sample_count(mt32emu_const_context context);
|
||||
MT32EMU_EXPORT mt32emu_bit32u MT32EMU_C_CALL mt32emu_get_internal_rendered_sample_count(mt32emu_const_context context);
|
||||
|
||||
/* Enqueues a MIDI event for subsequent playback.
|
||||
* The MIDI event will be processed not before the specified timestamp.
|
||||
@@ -243,7 +331,7 @@ MT32EMU_EXPORT mt32emu_bit32u mt32emu_get_internal_rendered_sample_count(mt32emu
|
||||
* 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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.
|
||||
@@ -251,31 +339,31 @@ MT32EMU_EXPORT void mt32emu_parse_stream(mt32emu_const_context context, const mt
|
||||
* 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT mt32emu_return_code MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT mt32emu_return_code MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT mt32emu_return_code MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT mt32emu_return_code MT32EMU_C_CALL 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,
|
||||
@@ -287,73 +375,73 @@ MT32EMU_EXPORT mt32emu_return_code mt32emu_play_sysex_at(mt32emu_const_context c
|
||||
* 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT mt32emu_boolean MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT mt32emu_boolean MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT mt32emu_boolean MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT mt32emu_boolean MT32EMU_C_CALL mt32emu_is_default_reverb_mt32_compatible(mt32emu_const_context context);
|
||||
|
||||
/**
|
||||
* If enabled, reverb buffers for all modes are keept around allocated all the time to avoid memory
|
||||
* If enabled, reverb buffers for all modes are kept around allocated all the time to avoid memory
|
||||
* allocating/freeing in the rendering thread, which may be required for realtime operation.
|
||||
* Otherwise, reverb buffers that are not in use are deleted to save memory (the default behaviour).
|
||||
*/
|
||||
MT32EMU_EXPORT void mt32emu_preallocate_reverb_memory(mt32emu_const_context context, const mt32emu_boolean enabled);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_preallocate_reverb_memory(mt32emu_const_context context, const mt32emu_boolean enabled);
|
||||
|
||||
/** 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT mt32emu_dac_input_mode MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT mt32emu_midi_delay_mode MT32EMU_C_CALL 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.
|
||||
*/
|
||||
MT32EMU_EXPORT void mt32emu_set_output_gain(mt32emu_const_context context, float gain);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT float MT32EMU_C_CALL 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
|
||||
@@ -365,14 +453,34 @@ MT32EMU_EXPORT float mt32emu_get_output_gain(mt32emu_const_context context);
|
||||
* 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.
|
||||
*/
|
||||
MT32EMU_EXPORT void mt32emu_set_reverb_output_gain(mt32emu_const_context context, float gain);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT float MT32EMU_C_CALL mt32emu_get_reverb_output_gain(mt32emu_const_context context);
|
||||
|
||||
/**
|
||||
* Sets (or removes) an override for the current volume (output level) on a specific part.
|
||||
* When the part volume is overridden, the MIDI controller Volume (7) on the MIDI channel this part is assigned to
|
||||
* has no effect on the output level of this part. Similarly, the output level value set on this part via a SysEx that
|
||||
* modifies the Patch temp structure is disregarded.
|
||||
* To enable the override mode, argument volumeOverride should be in range 0..100, setting a value outside this range
|
||||
* disables the previously set override, if any.
|
||||
* Note: Setting volumeOverride to 0 mutes the part completely, meaning no sound is generated at all.
|
||||
* This is unlike the behaviour of real devices - setting 0 volume on a part may leave it still producing
|
||||
* sound at a very low level.
|
||||
* Argument partNumber should be 0..7 for Part 1..8, or 8 for Rhythm.
|
||||
*/
|
||||
MT32EMU_EXPORT_V(2.6) void MT32EMU_C_CALL mt32emu_set_part_volume_override(mt32emu_const_context context, mt32emu_bit8u part_number, mt32emu_bit8u volume_override);
|
||||
/**
|
||||
* Returns the overridden volume previously set on a specific part; a value outside the range 0..100 means no override
|
||||
* is currently in effect.
|
||||
* Argument partNumber should be 0..7 for Part 1..8, or 8 for Rhythm.
|
||||
*/
|
||||
MT32EMU_EXPORT_V(2.6) mt32emu_bit8u MT32EMU_C_CALL mt32emu_get_part_volume_override(mt32emu_const_context context, mt32emu_bit8u part_number);
|
||||
|
||||
/** Swaps left and right output channels. */
|
||||
MT32EMU_EXPORT void mt32emu_set_reversed_stereo_enabled(mt32emu_const_context context, const mt32emu_boolean enabled);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT mt32emu_boolean MT32EMU_C_CALL mt32emu_is_reversed_stereo_enabled(mt32emu_const_context context);
|
||||
|
||||
/**
|
||||
* Allows to toggle the NiceAmpRamp mode.
|
||||
@@ -382,9 +490,9 @@ MT32EMU_EXPORT mt32emu_boolean mt32emu_is_reversed_stereo_enabled(mt32emu_const_
|
||||
* We also prefer the quality improvement over the emulation accuracy,
|
||||
* so this mode is enabled by default.
|
||||
*/
|
||||
MT32EMU_EXPORT void mt32emu_set_nice_amp_ramp_enabled(mt32emu_const_context context, const mt32emu_boolean enabled);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_set_nice_amp_ramp_enabled(mt32emu_const_context context, const mt32emu_boolean enabled);
|
||||
/** Returns whether NiceAmpRamp mode is enabled. */
|
||||
MT32EMU_EXPORT mt32emu_boolean mt32emu_is_nice_amp_ramp_enabled(mt32emu_const_context context);
|
||||
MT32EMU_EXPORT mt32emu_boolean MT32EMU_C_CALL mt32emu_is_nice_amp_ramp_enabled(mt32emu_const_context context);
|
||||
|
||||
/**
|
||||
* Allows to toggle the NicePanning mode.
|
||||
@@ -395,9 +503,9 @@ MT32EMU_EXPORT mt32emu_boolean mt32emu_is_nice_amp_ramp_enabled(mt32emu_const_co
|
||||
* making it smoother thus sacrificing the emulation accuracy.
|
||||
* This mode is disabled by default.
|
||||
*/
|
||||
MT32EMU_EXPORT void mt32emu_set_nice_panning_enabled(mt32emu_const_context context, const mt32emu_boolean enabled);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_set_nice_panning_enabled(mt32emu_const_context context, const mt32emu_boolean enabled);
|
||||
/** Returns whether NicePanning mode is enabled. */
|
||||
MT32EMU_EXPORT mt32emu_boolean mt32emu_is_nice_panning_enabled(mt32emu_const_context context);
|
||||
MT32EMU_EXPORT mt32emu_boolean MT32EMU_C_CALL mt32emu_is_nice_panning_enabled(mt32emu_const_context context);
|
||||
|
||||
/**
|
||||
* Allows to toggle the NicePartialMixing mode.
|
||||
@@ -409,9 +517,9 @@ MT32EMU_EXPORT mt32emu_boolean mt32emu_is_nice_panning_enabled(mt32emu_const_con
|
||||
* thus making the behaviour more predictable.
|
||||
* This mode is disabled by default.
|
||||
*/
|
||||
MT32EMU_EXPORT void mt32emu_set_nice_partial_mixing_enabled(mt32emu_const_context context, const mt32emu_boolean enabled);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_set_nice_partial_mixing_enabled(mt32emu_const_context context, const mt32emu_boolean enabled);
|
||||
/** Returns whether NicePartialMixing mode is enabled. */
|
||||
MT32EMU_EXPORT mt32emu_boolean mt32emu_is_nice_partial_mixing_enabled(mt32emu_const_context context);
|
||||
MT32EMU_EXPORT mt32emu_boolean MT32EMU_C_CALL mt32emu_is_nice_partial_mixing_enabled(mt32emu_const_context context);
|
||||
|
||||
/**
|
||||
* Renders samples to the specified output stream as if they were sampled at the analog stereo output at the desired sample rate.
|
||||
@@ -419,9 +527,9 @@ MT32EMU_EXPORT mt32emu_boolean mt32emu_is_nice_partial_mixing_enabled(mt32emu_co
|
||||
* mode of analog circuitry emulation. See mt32emu_analog_output_mode.
|
||||
* 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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.
|
||||
@@ -429,25 +537,25 @@ MT32EMU_EXPORT void mt32emu_render_float(mt32emu_const_context context, float *s
|
||||
* 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT mt32emu_boolean MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT mt32emu_boolean MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT mt32emu_bit32u MT32EMU_C_CALL 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);
|
||||
MT32EMU_EXPORT mt32emu_bit32u MT32EMU_C_CALL 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
|
||||
@@ -455,7 +563,7 @@ MT32EMU_EXPORT mt32emu_bit32u mt32emu_get_part_states(mt32emu_const_context cont
|
||||
* 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL 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
|
||||
@@ -463,16 +571,71 @@ MT32EMU_EXPORT void mt32emu_get_partial_states(mt32emu_const_context context, mt
|
||||
* 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);
|
||||
MT32EMU_EXPORT mt32emu_bit32u MT32EMU_C_CALL 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.
|
||||
* The returned value is a null-terminated string which is guaranteed to remain valid until the next call to one of functions
|
||||
* that perform sample rendering or immediate SysEx processing (e.g. mt32emu_play_sysex_now).
|
||||
*/
|
||||
MT32EMU_EXPORT const char *mt32emu_get_patch_name(mt32emu_const_context context, mt32emu_bit8u part_number);
|
||||
MT32EMU_EXPORT const char * MT32EMU_C_CALL mt32emu_get_patch_name(mt32emu_const_context context, mt32emu_bit8u part_number);
|
||||
|
||||
/**
|
||||
* Retrieves the name of the sound group the timbre identified by arguments timbre_group and timbre_number is associated with.
|
||||
* Values 0-3 of timbre_group correspond to the timbre banks GROUP A, GROUP B, MEMORY and RHYTHM.
|
||||
* For all but the RHYTHM timbre bank, allowed values of timbre_number are in range 0-63. The number of timbres
|
||||
* contained in the RHYTHM bank depends on the used control ROM version.
|
||||
* The argument sound_group_name must point to an array of at least 8 characters. The result is a null-terminated string.
|
||||
* Returns whether the specified timbre has been found and the result written in sound_group_name.
|
||||
*/
|
||||
MT32EMU_EXPORT_V(2.7) mt32emu_boolean MT32EMU_C_CALL mt32emu_get_sound_group_name(mt32emu_const_context context, char *sound_group_name, mt32emu_bit8u timbre_group, mt32emu_bit8u timbre_number);
|
||||
/**
|
||||
* Retrieves the name of the timbre identified by arguments timbre_group and timbre_number.
|
||||
* Values 0-3 of timbre_group correspond to the timbre banks GROUP A, GROUP B, MEMORY and RHYTHM.
|
||||
* For all but the RHYTHM timbre bank, allowed values of timbre_number are in range 0-63. The number of timbres
|
||||
* contained in the RHYTHM bank depends on the used control ROM version.
|
||||
* The argument sound_name must point to an array of at least 11 characters. The result is a null-terminated string.
|
||||
* Returns whether the specified timbre has been found and the result written in sound_name.
|
||||
*/
|
||||
MT32EMU_EXPORT_V(2.7) mt32emu_boolean MT32EMU_C_CALL mt32emu_get_sound_name(mt32emu_const_context context, char *sound_name, mt32emu_bit8u timbreGroup, mt32emu_bit8u timbreNumber);
|
||||
|
||||
/** 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);
|
||||
MT32EMU_EXPORT void MT32EMU_C_CALL mt32emu_read_memory(mt32emu_const_context context, mt32emu_bit32u addr, mt32emu_bit32u len, mt32emu_bit8u *data);
|
||||
|
||||
/**
|
||||
* Retrieves the current state of the emulated MT-32 display facilities.
|
||||
* Typically, the state is updated during the rendering. When that happens, a related callback from mt32emu_report_handler_i_v1
|
||||
* is invoked. However, there might be no need to invoke this method after each update, e.g. when the render buffer is just
|
||||
* a few milliseconds long.
|
||||
* The argument target_buffer must point to an array of at least 21 characters. The result is a null-terminated string.
|
||||
* The argument narrow_lcd enables a condensed representation of the displayed information in some cases. This is mainly intended
|
||||
* to route the result to a hardware LCD that is only 16 characters wide. Automatic scrolling of longer strings is not supported.
|
||||
* Returns whether the MIDI MESSAGE LED is ON and fills the target_buffer parameter.
|
||||
*/
|
||||
MT32EMU_EXPORT_V(2.6) mt32emu_boolean MT32EMU_C_CALL mt32emu_get_display_state(mt32emu_const_context context, char *target_buffer, const mt32emu_boolean narrow_lcd);
|
||||
|
||||
/**
|
||||
* Resets the emulated LCD to the main mode (Master Volume). This has the same effect as pressing the Master Volume button
|
||||
* while the display shows some other message. Useful for the new-gen devices as those require a special Display Reset SysEx
|
||||
* to return to the main mode e.g. from showing a custom display message or a checksum error.
|
||||
*/
|
||||
MT32EMU_EXPORT_V(2.6) void MT32EMU_C_CALL mt32emu_set_main_display_mode(mt32emu_const_context context);
|
||||
|
||||
/**
|
||||
* Permits to select an arbitrary display emulation model that does not necessarily match the actual behaviour implemented
|
||||
* in the control ROM version being used.
|
||||
* Invoking this method with the argument set to true forces emulation of the old-gen MT-32 display features.
|
||||
* Otherwise, emulation of the new-gen devices is enforced (these include CM-32L and LAPC-I as if these were connected to an LCD).
|
||||
*/
|
||||
MT32EMU_EXPORT_V(2.6) void MT32EMU_C_CALL mt32emu_set_display_compatibility(mt32emu_const_context context, mt32emu_boolean old_mt32_compatibility_enabled);
|
||||
/** Returns whether the currently configured features of the emulated display are compatible with the old-gen MT-32 devices. */
|
||||
MT32EMU_EXPORT_V(2.6) mt32emu_boolean MT32EMU_C_CALL mt32emu_is_display_old_mt32_compatible(mt32emu_const_context context);
|
||||
/**
|
||||
* Returns whether the emulated display features configured by default depending on the actual control ROM version
|
||||
* are compatible with the old-gen MT-32 devices.
|
||||
*/
|
||||
MT32EMU_EXPORT_V(2.6) mt32emu_boolean MT32EMU_C_CALL mt32emu_is_default_display_old_mt32_compatible(mt32emu_const_context context);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
@@ -27,6 +27,12 @@
|
||||
#include "../Enumerations.h"
|
||||
#undef MT32EMU_C_ENUMERATIONS
|
||||
|
||||
#ifdef _WIN32
|
||||
# define MT32EMU_C_CALL __cdecl
|
||||
#else
|
||||
# define MT32EMU_C_CALL
|
||||
#endif
|
||||
|
||||
typedef unsigned int mt32emu_bit32u;
|
||||
typedef signed int mt32emu_bit32s;
|
||||
typedef unsigned short int mt32emu_bit16u;
|
||||
@@ -45,6 +51,8 @@ typedef enum {
|
||||
MT32EMU_RC_OK = 0,
|
||||
MT32EMU_RC_ADDED_CONTROL_ROM = 1,
|
||||
MT32EMU_RC_ADDED_PCM_ROM = 2,
|
||||
MT32EMU_RC_ADDED_PARTIAL_CONTROL_ROM = 3,
|
||||
MT32EMU_RC_ADDED_PARTIAL_PCM_ROM = 4,
|
||||
|
||||
/* Definite error occurred. */
|
||||
MT32EMU_RC_ROM_NOT_IDENTIFIED = -1,
|
||||
@@ -53,6 +61,8 @@ typedef enum {
|
||||
MT32EMU_RC_MISSING_ROMS = -4,
|
||||
MT32EMU_RC_NOT_OPENED = -5,
|
||||
MT32EMU_RC_QUEUE_FULL = -6,
|
||||
MT32EMU_RC_ROMS_NOT_PAIRABLE = -7,
|
||||
MT32EMU_RC_MACHINE_NOT_IDENTIFIED = -8,
|
||||
|
||||
/* Undefined error occurred. */
|
||||
MT32EMU_RC_FAILED = -100
|
||||
@@ -107,7 +117,8 @@ typedef struct {
|
||||
/** 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_1 = 1,
|
||||
MT32EMU_REPORT_HANDLER_VERSION_CURRENT = MT32EMU_REPORT_HANDLER_VERSION_1
|
||||
} mt32emu_report_handler_version;
|
||||
|
||||
/** MIDI receiver interface versions */
|
||||
@@ -122,7 +133,10 @@ typedef enum {
|
||||
MT32EMU_SERVICE_VERSION_1 = 1,
|
||||
MT32EMU_SERVICE_VERSION_2 = 2,
|
||||
MT32EMU_SERVICE_VERSION_3 = 3,
|
||||
MT32EMU_SERVICE_VERSION_CURRENT = MT32EMU_SERVICE_VERSION_3
|
||||
MT32EMU_SERVICE_VERSION_4 = 4,
|
||||
MT32EMU_SERVICE_VERSION_5 = 5,
|
||||
MT32EMU_SERVICE_VERSION_6 = 6,
|
||||
MT32EMU_SERVICE_VERSION_CURRENT = MT32EMU_SERVICE_VERSION_6
|
||||
} mt32emu_service_version;
|
||||
|
||||
/* === Report Handler Interface === */
|
||||
@@ -130,42 +144,59 @@ typedef enum {
|
||||
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);
|
||||
#define MT32EMU_REPORT_HANDLER_I_V0 \
|
||||
/** Returns the actual interface version ID */ \
|
||||
mt32emu_report_handler_version (MT32EMU_C_CALL *getVersionID)(mt32emu_report_handler_i i); \
|
||||
\
|
||||
/** Callback for debug messages, in vprintf() format */ \
|
||||
void (MT32EMU_C_CALL *printDebug)(void *instance_data, const char *fmt, va_list list); \
|
||||
/** Callbacks for reporting errors */ \
|
||||
void (MT32EMU_C_CALL *onErrorControlROM)(void *instance_data); \
|
||||
void (MT32EMU_C_CALL *onErrorPCMROM)(void *instance_data); \
|
||||
/** Callback for reporting about displaying a new custom message on LCD */ \
|
||||
void (MT32EMU_C_CALL *showLCDMessage)(void *instance_data, const char *message); \
|
||||
/** Callback for reporting actual processing of a MIDI message */ \
|
||||
void (MT32EMU_C_CALL *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);
|
||||
*/ \
|
||||
mt32emu_boolean (MT32EMU_C_CALL *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);
|
||||
*/ \
|
||||
void (MT32EMU_C_CALL *onMIDISystemRealtime)(void *instance_data, mt32emu_bit8u system_realtime); \
|
||||
/** Callbacks for reporting system events */ \
|
||||
void (MT32EMU_C_CALL *onDeviceReset)(void *instance_data); \
|
||||
void (MT32EMU_C_CALL *onDeviceReconfig)(void *instance_data); \
|
||||
/** Callbacks for reporting changes of reverb settings */ \
|
||||
void (MT32EMU_C_CALL *onNewReverbMode)(void *instance_data, mt32emu_bit8u mode); \
|
||||
void (MT32EMU_C_CALL *onNewReverbTime)(void *instance_data, mt32emu_bit8u time); \
|
||||
void (MT32EMU_C_CALL *onNewReverbLevel)(void *instance_data, mt32emu_bit8u level); \
|
||||
/** Callbacks for reporting various information */ \
|
||||
void (MT32EMU_C_CALL *onPolyStateChanged)(void *instance_data, mt32emu_bit8u part_num); \
|
||||
void (MT32EMU_C_CALL *onProgramChanged)(void *instance_data, mt32emu_bit8u part_num, const char *sound_group_name, const char *patch_name);
|
||||
|
||||
#define MT32EMU_REPORT_HANDLER_I_V1 \
|
||||
/**
|
||||
* Invoked to signal about a change of the emulated LCD state. Use mt32emu_get_display_state to retrieve the actual data.
|
||||
* This callback will not be invoked on further changes, until the client retrieves the LCD state.
|
||||
*/ \
|
||||
void (MT32EMU_C_CALL *onLCDStateUpdated)(void *instance_data); \
|
||||
/** Invoked when the emulated MIDI MESSAGE LED changes state. The led_state parameter represents whether the LED is ON. */ \
|
||||
void (MT32EMU_C_CALL *onMidiMessageLEDStateUpdated)(void *instance_data, mt32emu_boolean led_state);
|
||||
|
||||
typedef struct {
|
||||
MT32EMU_REPORT_HANDLER_I_V0
|
||||
} mt32emu_report_handler_i_v0;
|
||||
|
||||
typedef struct {
|
||||
MT32EMU_REPORT_HANDLER_I_V0
|
||||
MT32EMU_REPORT_HANDLER_I_V1
|
||||
} mt32emu_report_handler_i_v1;
|
||||
|
||||
/**
|
||||
* Extensible interface for handling reported events.
|
||||
* Union intended to view an interface of any subsequent version as any parent interface not requiring a cast.
|
||||
@@ -173,8 +204,12 @@ typedef struct {
|
||||
*/
|
||||
union mt32emu_report_handler_i {
|
||||
const mt32emu_report_handler_i_v0 *v0;
|
||||
const mt32emu_report_handler_i_v1 *v1;
|
||||
};
|
||||
|
||||
#undef MT32EMU_REPORT_HANDLER_I_V0
|
||||
#undef MT32EMU_REPORT_HANDLER_I_V1
|
||||
|
||||
/* === MIDI Receiver Interface === */
|
||||
|
||||
typedef union mt32emu_midi_receiver_i mt32emu_midi_receiver_i;
|
||||
@@ -182,16 +217,16 @@ 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);
|
||||
mt32emu_midi_receiver_version (MT32EMU_C_CALL *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);
|
||||
void (MT32EMU_C_CALL *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);
|
||||
void (MT32EMU_C_CALL *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);
|
||||
void (MT32EMU_C_CALL *handleSystemRealtimeMessage)(void *instance_data, const mt32emu_bit8u realtime);
|
||||
} mt32emu_midi_receiver_i_v0;
|
||||
|
||||
/**
|
||||
@@ -216,101 +251,124 @@ typedef union mt32emu_service_i mt32emu_service_i;
|
||||
*/
|
||||
#define MT32EMU_SERVICE_I_V0 \
|
||||
/** Returns the actual interface version ID */ \
|
||||
mt32emu_service_version (*getVersionID)(mt32emu_service_i i); \
|
||||
mt32emu_report_handler_version (*getSupportedReportHandlerVersionID)(void); \
|
||||
mt32emu_midi_receiver_version (*getSupportedMIDIReceiverVersionID)(void); \
|
||||
mt32emu_service_version (MT32EMU_C_CALL *getVersionID)(mt32emu_service_i i); \
|
||||
mt32emu_report_handler_version (MT32EMU_C_CALL *getSupportedReportHandlerVersionID)(void); \
|
||||
mt32emu_midi_receiver_version (MT32EMU_C_CALL *getSupportedMIDIReceiverVersionID)(void); \
|
||||
\
|
||||
mt32emu_bit32u (*getLibraryVersionInt)(void); \
|
||||
const char *(*getLibraryVersionString)(void); \
|
||||
mt32emu_bit32u (MT32EMU_C_CALL *getLibraryVersionInt)(void); \
|
||||
const char *(MT32EMU_C_CALL *getLibraryVersionString)(void); \
|
||||
\
|
||||
mt32emu_bit32u (*getStereoOutputSamplerate)(const mt32emu_analog_output_mode analog_output_mode); \
|
||||
mt32emu_bit32u (MT32EMU_C_CALL *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); \
|
||||
mt32emu_context (MT32EMU_C_CALL *createContext)(mt32emu_report_handler_i report_handler, void *instance_data); \
|
||||
void (MT32EMU_C_CALL *freeContext)(mt32emu_context context); \
|
||||
mt32emu_return_code (MT32EMU_C_CALL *addROMData)(mt32emu_context context, const mt32emu_bit8u *data, size_t data_size, const mt32emu_sha1_digest *sha1_digest); \
|
||||
mt32emu_return_code (MT32EMU_C_CALL *addROMFile)(mt32emu_context context, const char *filename); \
|
||||
void (MT32EMU_C_CALL *getROMInfo)(mt32emu_const_context context, mt32emu_rom_info *rom_info); \
|
||||
void (MT32EMU_C_CALL *setPartialCount)(mt32emu_context context, const mt32emu_bit32u partial_count); \
|
||||
void (MT32EMU_C_CALL *setAnalogOutputMode)(mt32emu_context context, const mt32emu_analog_output_mode analog_output_mode); \
|
||||
mt32emu_return_code (MT32EMU_C_CALL *openSynth)(mt32emu_const_context context); \
|
||||
void (MT32EMU_C_CALL *closeSynth)(mt32emu_const_context context); \
|
||||
mt32emu_boolean (MT32EMU_C_CALL *isOpen)(mt32emu_const_context context); \
|
||||
mt32emu_bit32u (MT32EMU_C_CALL *getActualStereoOutputSamplerate)(mt32emu_const_context context); \
|
||||
void (MT32EMU_C_CALL *flushMIDIQueue)(mt32emu_const_context context); \
|
||||
mt32emu_bit32u (MT32EMU_C_CALL *setMIDIEventQueueSize)(mt32emu_const_context context, const mt32emu_bit32u queue_size); \
|
||||
void (MT32EMU_C_CALL *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 (MT32EMU_C_CALL *parseStream)(mt32emu_const_context context, const mt32emu_bit8u *stream, mt32emu_bit32u length); \
|
||||
void (MT32EMU_C_CALL *parseStream_At)(mt32emu_const_context context, const mt32emu_bit8u *stream, mt32emu_bit32u length, mt32emu_bit32u timestamp); \
|
||||
void (MT32EMU_C_CALL *playShortMessage)(mt32emu_const_context context, mt32emu_bit32u message); \
|
||||
void (MT32EMU_C_CALL *playShortMessageAt)(mt32emu_const_context context, mt32emu_bit32u message, mt32emu_bit32u timestamp); \
|
||||
mt32emu_return_code (MT32EMU_C_CALL *playMsg)(mt32emu_const_context context, mt32emu_bit32u msg); \
|
||||
mt32emu_return_code (MT32EMU_C_CALL *playSysex)(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len); \
|
||||
mt32emu_return_code (MT32EMU_C_CALL *playMsgAt)(mt32emu_const_context context, mt32emu_bit32u msg, mt32emu_bit32u timestamp); \
|
||||
mt32emu_return_code (MT32EMU_C_CALL *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 (MT32EMU_C_CALL *playMsgNow)(mt32emu_const_context context, mt32emu_bit32u msg); \
|
||||
void (MT32EMU_C_CALL *playMsgOnPart)(mt32emu_const_context context, mt32emu_bit8u part, mt32emu_bit8u code, mt32emu_bit8u note, mt32emu_bit8u velocity); \
|
||||
void (MT32EMU_C_CALL *playSysexNow)(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len); \
|
||||
void (MT32EMU_C_CALL *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 (MT32EMU_C_CALL *setReverbEnabled)(mt32emu_const_context context, const mt32emu_boolean reverb_enabled); \
|
||||
mt32emu_boolean (MT32EMU_C_CALL *isReverbEnabled)(mt32emu_const_context context); \
|
||||
void (MT32EMU_C_CALL *setReverbOverridden)(mt32emu_const_context context, const mt32emu_boolean reverb_overridden); \
|
||||
mt32emu_boolean (MT32EMU_C_CALL *isReverbOverridden)(mt32emu_const_context context); \
|
||||
void (MT32EMU_C_CALL *setReverbCompatibilityMode)(mt32emu_const_context context, const mt32emu_boolean mt32_compatible_mode); \
|
||||
mt32emu_boolean (MT32EMU_C_CALL *isMT32ReverbCompatibilityMode)(mt32emu_const_context context); \
|
||||
mt32emu_boolean (MT32EMU_C_CALL *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 (MT32EMU_C_CALL *setDACInputMode)(mt32emu_const_context context, const mt32emu_dac_input_mode mode); \
|
||||
mt32emu_dac_input_mode (MT32EMU_C_CALL *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 (MT32EMU_C_CALL *setMIDIDelayMode)(mt32emu_const_context context, const mt32emu_midi_delay_mode mode); \
|
||||
mt32emu_midi_delay_mode (MT32EMU_C_CALL *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 (MT32EMU_C_CALL *setOutputGain)(mt32emu_const_context context, float gain); \
|
||||
float (MT32EMU_C_CALL *getOutputGain)(mt32emu_const_context context); \
|
||||
void (MT32EMU_C_CALL *setReverbOutputGain)(mt32emu_const_context context, float gain); \
|
||||
float (MT32EMU_C_CALL *getReverbOutputGain)(mt32emu_const_context context); \
|
||||
\
|
||||
void (*setReversedStereoEnabled)(mt32emu_const_context context, const mt32emu_boolean enabled); \
|
||||
mt32emu_boolean (*isReversedStereoEnabled)(mt32emu_const_context context); \
|
||||
void (MT32EMU_C_CALL *setReversedStereoEnabled)(mt32emu_const_context context, const mt32emu_boolean enabled); \
|
||||
mt32emu_boolean (MT32EMU_C_CALL *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); \
|
||||
void (MT32EMU_C_CALL *renderBit16s)(mt32emu_const_context context, mt32emu_bit16s *stream, mt32emu_bit32u len); \
|
||||
void (MT32EMU_C_CALL *renderFloat)(mt32emu_const_context context, float *stream, mt32emu_bit32u len); \
|
||||
void (MT32EMU_C_CALL *renderBit16sStreams)(mt32emu_const_context context, const mt32emu_dac_output_bit16s_streams *streams, mt32emu_bit32u len); \
|
||||
void (MT32EMU_C_CALL *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_boolean (MT32EMU_C_CALL *hasActivePartials)(mt32emu_const_context context); \
|
||||
mt32emu_boolean (MT32EMU_C_CALL *isActive)(mt32emu_const_context context); \
|
||||
mt32emu_bit32u (MT32EMU_C_CALL *getPartialCount)(mt32emu_const_context context); \
|
||||
mt32emu_bit32u (MT32EMU_C_CALL *getPartStates)(mt32emu_const_context context); \
|
||||
void (MT32EMU_C_CALL *getPartialStates)(mt32emu_const_context context, mt32emu_bit8u *partial_states); \
|
||||
mt32emu_bit32u (MT32EMU_C_CALL *getPlayingNotes)(mt32emu_const_context context, mt32emu_bit8u part_number, mt32emu_bit8u *keys, mt32emu_bit8u *velocities); \
|
||||
const char *(MT32EMU_C_CALL *getPatchName)(mt32emu_const_context context, mt32emu_bit8u part_number); \
|
||||
void (MT32EMU_C_CALL *readMemory)(mt32emu_const_context context, mt32emu_bit32u addr, mt32emu_bit32u len, mt32emu_bit8u *data);
|
||||
|
||||
#define MT32EMU_SERVICE_I_V1 \
|
||||
mt32emu_analog_output_mode (*getBestAnalogOutputMode)(const double target_samplerate); \
|
||||
void (*setStereoOutputSampleRate)(mt32emu_context context, const double samplerate); \
|
||||
void (*setSamplerateConversionQuality)(mt32emu_context context, const mt32emu_samplerate_conversion_quality quality); \
|
||||
void (*selectRendererType)(mt32emu_context context, mt32emu_renderer_type renderer_type); \
|
||||
mt32emu_renderer_type (*getSelectedRendererType)(mt32emu_context context); \
|
||||
mt32emu_bit32u (*convertOutputToSynthTimestamp)(mt32emu_const_context context, mt32emu_bit32u output_timestamp); \
|
||||
mt32emu_bit32u (*convertSynthToOutputTimestamp)(mt32emu_const_context context, mt32emu_bit32u synth_timestamp);
|
||||
mt32emu_analog_output_mode (MT32EMU_C_CALL *getBestAnalogOutputMode)(const double target_samplerate); \
|
||||
void (MT32EMU_C_CALL *setStereoOutputSampleRate)(mt32emu_context context, const double samplerate); \
|
||||
void (MT32EMU_C_CALL *setSamplerateConversionQuality)(mt32emu_context context, const mt32emu_samplerate_conversion_quality quality); \
|
||||
void (MT32EMU_C_CALL *selectRendererType)(mt32emu_context context, mt32emu_renderer_type renderer_type); \
|
||||
mt32emu_renderer_type (MT32EMU_C_CALL *getSelectedRendererType)(mt32emu_context context); \
|
||||
mt32emu_bit32u (MT32EMU_C_CALL *convertOutputToSynthTimestamp)(mt32emu_const_context context, mt32emu_bit32u output_timestamp); \
|
||||
mt32emu_bit32u (MT32EMU_C_CALL *convertSynthToOutputTimestamp)(mt32emu_const_context context, mt32emu_bit32u synth_timestamp);
|
||||
|
||||
#define MT32EMU_SERVICE_I_V2 \
|
||||
mt32emu_bit32u (*getInternalRenderedSampleCount)(mt32emu_const_context context); \
|
||||
void (*setNiceAmpRampEnabled)(mt32emu_const_context context, const mt32emu_boolean enabled); \
|
||||
mt32emu_boolean (*isNiceAmpRampEnabled)(mt32emu_const_context context);
|
||||
mt32emu_bit32u (MT32EMU_C_CALL *getInternalRenderedSampleCount)(mt32emu_const_context context); \
|
||||
void (MT32EMU_C_CALL *setNiceAmpRampEnabled)(mt32emu_const_context context, const mt32emu_boolean enabled); \
|
||||
mt32emu_boolean (MT32EMU_C_CALL *isNiceAmpRampEnabled)(mt32emu_const_context context);
|
||||
|
||||
#define MT32EMU_SERVICE_I_V3 \
|
||||
void (*setNicePanningEnabled)(mt32emu_const_context context, const mt32emu_boolean enabled); \
|
||||
mt32emu_boolean (*isNicePanningEnabled)(mt32emu_const_context context); \
|
||||
void (*setNicePartialMixingEnabled)(mt32emu_const_context context, const mt32emu_boolean enabled); \
|
||||
mt32emu_boolean (*isNicePartialMixingEnabled)(mt32emu_const_context context); \
|
||||
void (*preallocateReverbMemory)(mt32emu_const_context context, const mt32emu_boolean enabled); \
|
||||
void (*configureMIDIEventQueueSysexStorage)(mt32emu_const_context context, const mt32emu_bit32u storage_buffer_size);
|
||||
void (MT32EMU_C_CALL *setNicePanningEnabled)(mt32emu_const_context context, const mt32emu_boolean enabled); \
|
||||
mt32emu_boolean (MT32EMU_C_CALL *isNicePanningEnabled)(mt32emu_const_context context); \
|
||||
void (MT32EMU_C_CALL *setNicePartialMixingEnabled)(mt32emu_const_context context, const mt32emu_boolean enabled); \
|
||||
mt32emu_boolean (MT32EMU_C_CALL *isNicePartialMixingEnabled)(mt32emu_const_context context); \
|
||||
void (MT32EMU_C_CALL *preallocateReverbMemory)(mt32emu_const_context context, const mt32emu_boolean enabled); \
|
||||
void (MT32EMU_C_CALL *configureMIDIEventQueueSysexStorage)(mt32emu_const_context context, const mt32emu_bit32u storage_buffer_size);
|
||||
|
||||
#define MT32EMU_SERVICE_I_V4 \
|
||||
size_t (MT32EMU_C_CALL *getMachineIDs)(const char **machine_ids, size_t machine_ids_size); \
|
||||
size_t (MT32EMU_C_CALL *getROMIDs)(const char **rom_ids, size_t rom_ids_size, const char *machine_id); \
|
||||
mt32emu_return_code (MT32EMU_C_CALL *identifyROMData)(mt32emu_rom_info *rom_info, const mt32emu_bit8u *data, size_t data_size, const char *machine_id); \
|
||||
mt32emu_return_code (MT32EMU_C_CALL *identifyROMFile)(mt32emu_rom_info *rom_info, const char *filename, const char *machine_id); \
|
||||
\
|
||||
mt32emu_return_code (MT32EMU_C_CALL *mergeAndAddROMData)(mt32emu_context context, const mt32emu_bit8u *part1_data, size_t part1_data_size, const mt32emu_sha1_digest *part1_sha1_digest, const mt32emu_bit8u *part2_data, size_t part2_data_size, const mt32emu_sha1_digest *part2_sha1_digest); \
|
||||
mt32emu_return_code (MT32EMU_C_CALL *mergeAndAddROMFiles)(mt32emu_context context, const char *part1_filename, const char *part2_filename); \
|
||||
mt32emu_return_code (MT32EMU_C_CALL *addMachineROMFile)(mt32emu_context context, const char *machine_id, const char *filename);
|
||||
|
||||
#define MT32EMU_SERVICE_I_V5 \
|
||||
mt32emu_boolean (MT32EMU_C_CALL *getDisplayState)(mt32emu_const_context context, char *target_buffer, const mt32emu_boolean narrow_lcd); \
|
||||
void (MT32EMU_C_CALL *setMainDisplayMode)(mt32emu_const_context context); \
|
||||
void (MT32EMU_C_CALL *setDisplayCompatibility)(mt32emu_const_context context, mt32emu_boolean old_mt32_compatibility_enabled); \
|
||||
mt32emu_boolean (MT32EMU_C_CALL *isDisplayOldMT32Compatible)(mt32emu_const_context context); \
|
||||
mt32emu_boolean (MT32EMU_C_CALL *isDefaultDisplayOldMT32Compatible)(mt32emu_const_context context); \
|
||||
void (MT32EMU_C_CALL *setPartVolumeOverride)(mt32emu_const_context context, mt32emu_bit8u part_number, mt32emu_bit8u volume_override); \
|
||||
mt32emu_bit8u (MT32EMU_C_CALL *getPartVolumeOverride)(mt32emu_const_context context, mt32emu_bit8u part_number);
|
||||
|
||||
#define MT32EMU_SERVICE_I_V6 \
|
||||
mt32emu_boolean (MT32EMU_C_CALL *getSoundGroupName)(mt32emu_const_context context, char *sound_group_name, mt32emu_bit8u timbre_group, mt32emu_bit8u timbre_number); \
|
||||
mt32emu_boolean (MT32EMU_C_CALL *getSoundName)(mt32emu_const_context context, char *sound_name, mt32emu_bit8u timbre_group, mt32emu_bit8u timbre_number);
|
||||
|
||||
typedef struct {
|
||||
MT32EMU_SERVICE_I_V0
|
||||
@@ -334,6 +392,33 @@ typedef struct {
|
||||
MT32EMU_SERVICE_I_V3
|
||||
} mt32emu_service_i_v3;
|
||||
|
||||
typedef struct {
|
||||
MT32EMU_SERVICE_I_V0
|
||||
MT32EMU_SERVICE_I_V1
|
||||
MT32EMU_SERVICE_I_V2
|
||||
MT32EMU_SERVICE_I_V3
|
||||
MT32EMU_SERVICE_I_V4
|
||||
} mt32emu_service_i_v4;
|
||||
|
||||
typedef struct {
|
||||
MT32EMU_SERVICE_I_V0
|
||||
MT32EMU_SERVICE_I_V1
|
||||
MT32EMU_SERVICE_I_V2
|
||||
MT32EMU_SERVICE_I_V3
|
||||
MT32EMU_SERVICE_I_V4
|
||||
MT32EMU_SERVICE_I_V5
|
||||
} mt32emu_service_i_v5;
|
||||
|
||||
typedef struct {
|
||||
MT32EMU_SERVICE_I_V0
|
||||
MT32EMU_SERVICE_I_V1
|
||||
MT32EMU_SERVICE_I_V2
|
||||
MT32EMU_SERVICE_I_V3
|
||||
MT32EMU_SERVICE_I_V4
|
||||
MT32EMU_SERVICE_I_V5
|
||||
MT32EMU_SERVICE_I_V6
|
||||
} mt32emu_service_i_v6;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
@@ -344,11 +429,17 @@ union mt32emu_service_i {
|
||||
const mt32emu_service_i_v1 *v1;
|
||||
const mt32emu_service_i_v2 *v2;
|
||||
const mt32emu_service_i_v3 *v3;
|
||||
const mt32emu_service_i_v4 *v4;
|
||||
const mt32emu_service_i_v5 *v5;
|
||||
const mt32emu_service_i_v6 *v6;
|
||||
};
|
||||
|
||||
#undef MT32EMU_SERVICE_I_V0
|
||||
#undef MT32EMU_SERVICE_I_V1
|
||||
#undef MT32EMU_SERVICE_I_V2
|
||||
#undef MT32EMU_SERVICE_I_V3
|
||||
#undef MT32EMU_SERVICE_I_V4
|
||||
#undef MT32EMU_SERVICE_I_V5
|
||||
#undef MT32EMU_SERVICE_I_V6
|
||||
|
||||
#endif /* #ifndef MT32EMU_C_TYPES_H */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
@@ -41,10 +41,17 @@ mt32emu_service_i mt32emu_get_service_i();
|
||||
#define mt32emu_get_library_version_string i.v0->getLibraryVersionString
|
||||
#define mt32emu_get_stereo_output_samplerate i.v0->getStereoOutputSamplerate
|
||||
#define mt32emu_get_best_analog_output_mode iV1()->getBestAnalogOutputMode
|
||||
#define mt32emu_get_machine_ids iV4()->getMachineIDs
|
||||
#define mt32emu_get_rom_ids iV4()->getROMIDs
|
||||
#define mt32emu_identify_rom_data iV4()->identifyROMData
|
||||
#define mt32emu_identify_rom_file iV4()->identifyROMFile
|
||||
#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_merge_and_add_rom_data iV4()->mergeAndAddROMData
|
||||
#define mt32emu_merge_and_add_rom_files iV4()->mergeAndAddROMFiles
|
||||
#define mt32emu_add_machine_rom_file iV4()->addMachineROMFile
|
||||
#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
|
||||
@@ -91,6 +98,8 @@ mt32emu_service_i mt32emu_get_service_i();
|
||||
#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_part_volume_override iV5()->setPartVolumeOverride
|
||||
#define mt32emu_get_part_volume_override iV5()->getPartVolumeOverride
|
||||
#define mt32emu_set_reversed_stereo_enabled i.v0->setReversedStereoEnabled
|
||||
#define mt32emu_is_reversed_stereo_enabled i.v0->isReversedStereoEnabled
|
||||
#define mt32emu_set_nice_amp_ramp_enabled iV2()->setNiceAmpRampEnabled
|
||||
@@ -110,7 +119,14 @@ mt32emu_service_i mt32emu_get_service_i();
|
||||
#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_get_sound_group_name iV6()->getSoundGroupName
|
||||
#define mt32emu_get_sound_name iV6()->getSoundName
|
||||
#define mt32emu_read_memory i.v0->readMemory
|
||||
#define mt32emu_get_display_state iV5()->getDisplayState
|
||||
#define mt32emu_set_main_display_mode iV5()->setMainDisplayMode
|
||||
#define mt32emu_set_display_compatibility iV5()->setDisplayCompatibility
|
||||
#define mt32emu_is_display_old_mt32_compatible iV5()->isDisplayOldMT32Compatible
|
||||
#define mt32emu_is_default_display_old_mt32_compatible iV5()->isDefaultDisplayOldMT32Compatible
|
||||
|
||||
#else // #if MT32EMU_API_TYPE == 2
|
||||
|
||||
@@ -123,7 +139,7 @@ namespace MT32Emu {
|
||||
namespace CppInterfaceImpl {
|
||||
|
||||
static const mt32emu_report_handler_i NULL_REPORT_HANDLER = { NULL };
|
||||
static mt32emu_report_handler_i getReportHandlerThunk();
|
||||
static mt32emu_report_handler_i getReportHandlerThunk(mt32emu_report_handler_version);
|
||||
static mt32emu_midi_receiver_i getMidiReceiverThunk();
|
||||
|
||||
}
|
||||
@@ -136,8 +152,8 @@ static mt32emu_midi_receiver_i getMidiReceiverThunk();
|
||||
* 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.
|
||||
// Defines the interface for handling reported events (initial version).
|
||||
// Corresponds to the mt32emu_report_handler_i_v0 interface.
|
||||
class IReportHandler {
|
||||
public:
|
||||
virtual void printDebug(const char *fmt, va_list list) = 0;
|
||||
@@ -159,6 +175,17 @@ protected:
|
||||
~IReportHandler() {}
|
||||
};
|
||||
|
||||
// Extends IReportHandler, so that the client may supply callbacks for reporting signals about updated display state.
|
||||
// Corresponds to the mt32emu_report_handler_i_v1 interface.
|
||||
class IReportHandlerV1 : public IReportHandler {
|
||||
public:
|
||||
virtual void onLCDStateUpdated() = 0;
|
||||
virtual void onMidiMessageLEDStateUpdated(bool ledState) = 0;
|
||||
|
||||
protected:
|
||||
~IReportHandlerV1() {}
|
||||
};
|
||||
|
||||
// Defines the interface for receiving MIDI messages generated by MIDI stream parser.
|
||||
// Corresponds to the current version of mt32emu_midi_receiver_i interface.
|
||||
class IMidiReceiver {
|
||||
@@ -196,14 +223,24 @@ public:
|
||||
Bit32u getStereoOutputSamplerate(const AnalogOutputMode analog_output_mode) { return mt32emu_get_stereo_output_samplerate(static_cast<mt32emu_analog_output_mode>(analog_output_mode)); }
|
||||
AnalogOutputMode getBestAnalogOutputMode(const double target_samplerate) { return static_cast<AnalogOutputMode>(mt32emu_get_best_analog_output_mode(target_samplerate)); }
|
||||
|
||||
size_t getMachineIDs(const char **machine_ids, size_t machine_ids_size) { return mt32emu_get_machine_ids(machine_ids, machine_ids_size); }
|
||||
size_t getROMIDs(const char **rom_ids, size_t rom_ids_size, const char *machine_id) { return mt32emu_get_rom_ids(rom_ids, rom_ids_size, machine_id); }
|
||||
mt32emu_return_code identifyROMData(mt32emu_rom_info *rom_info, const Bit8u *data, size_t data_size, const char *machine_id) { return mt32emu_identify_rom_data(rom_info, data, data_size, machine_id); }
|
||||
mt32emu_return_code identifyROMFile(mt32emu_rom_info *rom_info, const char *filename, const char *machine_id) { return mt32emu_identify_rom_file(rom_info, filename, machine_id); }
|
||||
|
||||
// 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(IReportHandler &report_handler) { createContext(CppInterfaceImpl::getReportHandlerThunk(), &report_handler); }
|
||||
void createContext(IReportHandler &report_handler) { createContext(CppInterfaceImpl::getReportHandlerThunk(MT32EMU_REPORT_HANDLER_VERSION_0), &report_handler); }
|
||||
void createContext(IReportHandlerV1 &report_handler) { createContext(CppInterfaceImpl::getReportHandlerThunk(MT32EMU_REPORT_HANDLER_VERSION_1), &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); }
|
||||
mt32emu_return_code mergeAndAddROMData(const Bit8u *part1_data, size_t part1_data_size, const Bit8u *part2_data, size_t part2_data_size) { return mt32emu_merge_and_add_rom_data(c, part1_data, part1_data_size, NULL, part2_data, part2_data_size, NULL); }
|
||||
mt32emu_return_code mergeAndAddROMData(const Bit8u *part1_data, size_t part1_data_size, const mt32emu_sha1_digest *part1_sha1_digest, const Bit8u *part2_data, size_t part2_data_size, const mt32emu_sha1_digest *part2_sha1_digest) { return mt32emu_merge_and_add_rom_data(c, part1_data, part1_data_size, part1_sha1_digest, part2_data, part2_data_size, part2_sha1_digest); }
|
||||
mt32emu_return_code mergeAndAddROMFiles(const char *part1_filename, const char *part2_filename) { return mt32emu_merge_and_add_rom_files(c, part1_filename, part2_filename); }
|
||||
mt32emu_return_code addMachineROMFile(const char *machine_id, const char *filename) { return mt32emu_add_machine_rom_file(c, machine_id, 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)); }
|
||||
@@ -258,6 +295,9 @@ public:
|
||||
void setReverbOutputGain(float gain) { mt32emu_set_reverb_output_gain(c, gain); }
|
||||
float getReverbOutputGain() { return mt32emu_get_reverb_output_gain(c); }
|
||||
|
||||
void setPartVolumeOverride(Bit8u part_number, Bit8u volume_override) { mt32emu_set_part_volume_override(c, part_number, volume_override); }
|
||||
Bit8u getPartVolumeOverride(Bit8u part_number) { return mt32emu_get_part_volume_override(c, part_number); }
|
||||
|
||||
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; }
|
||||
|
||||
@@ -282,8 +322,17 @@ public:
|
||||
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); }
|
||||
bool getSoundGroupName(char *soundGroupName, Bit8u timbreGroup, Bit8u timbreNumber) { return mt32emu_get_sound_group_name(c, soundGroupName, timbreGroup, timbreNumber) != MT32EMU_BOOL_FALSE; }
|
||||
bool getSoundName(char *soundName, Bit8u timbreGroup, Bit8u timbreNumber) { return mt32emu_get_sound_name(c, soundName, timbreGroup, timbreNumber) != MT32EMU_BOOL_FALSE; }
|
||||
void readMemory(Bit32u addr, Bit32u len, Bit8u *data) { mt32emu_read_memory(c, addr, len, data); }
|
||||
|
||||
bool getDisplayState(char *target_buffer, const bool narrow_lcd) { return mt32emu_get_display_state(c, target_buffer, narrow_lcd ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE) != MT32EMU_BOOL_FALSE; }
|
||||
void setMainDisplayMode() { mt32emu_set_main_display_mode(c); }
|
||||
|
||||
void setDisplayCompatibility(const bool oldMT32CompatibilityEnabled) { mt32emu_set_display_compatibility(c, oldMT32CompatibilityEnabled ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE); }
|
||||
bool isDisplayOldMT32Compatible() { return mt32emu_is_display_old_mt32_compatible(c) != MT32EMU_BOOL_FALSE; }
|
||||
bool isDefaultDisplayOldMT32Compatible() { return mt32emu_is_default_display_old_mt32_compatible(c) != MT32EMU_BOOL_FALSE; }
|
||||
|
||||
private:
|
||||
#if MT32EMU_API_TYPE == 2
|
||||
const mt32emu_service_i i;
|
||||
@@ -294,108 +343,137 @@ private:
|
||||
const mt32emu_service_i_v1 *iV1() { return (getVersionID() < MT32EMU_SERVICE_VERSION_1) ? NULL : i.v1; }
|
||||
const mt32emu_service_i_v2 *iV2() { return (getVersionID() < MT32EMU_SERVICE_VERSION_2) ? NULL : i.v2; }
|
||||
const mt32emu_service_i_v3 *iV3() { return (getVersionID() < MT32EMU_SERVICE_VERSION_3) ? NULL : i.v3; }
|
||||
const mt32emu_service_i_v4 *iV4() { return (getVersionID() < MT32EMU_SERVICE_VERSION_4) ? NULL : i.v4; }
|
||||
const mt32emu_service_i_v5 *iV5() { return (getVersionID() < MT32EMU_SERVICE_VERSION_5) ? NULL : i.v5; }
|
||||
const mt32emu_service_i_v6 *iV6() { return (getVersionID() < MT32EMU_SERVICE_VERSION_6) ? NULL : i.v6; }
|
||||
#endif
|
||||
|
||||
Service(const Service &); // prevent copy-construction
|
||||
Service& operator=(const Service &); // prevent assignment
|
||||
};
|
||||
|
||||
namespace CppInterfaceImpl {
|
||||
|
||||
static mt32emu_report_handler_version getReportHandlerVersionID(mt32emu_report_handler_i) {
|
||||
return MT32EMU_REPORT_HANDLER_VERSION_CURRENT;
|
||||
}
|
||||
static mt32emu_report_handler_version MT32EMU_C_CALL getReportHandlerVersionID(mt32emu_report_handler_i);
|
||||
|
||||
static void printDebug(void *instance_data, const char *fmt, va_list list) {
|
||||
static void MT32EMU_C_CALL printDebug(void *instance_data, const char *fmt, va_list list) {
|
||||
static_cast<IReportHandler *>(instance_data)->printDebug(fmt, list);
|
||||
}
|
||||
|
||||
static void onErrorControlROM(void *instance_data) {
|
||||
static void MT32EMU_C_CALL onErrorControlROM(void *instance_data) {
|
||||
static_cast<IReportHandler *>(instance_data)->onErrorControlROM();
|
||||
}
|
||||
|
||||
static void onErrorPCMROM(void *instance_data) {
|
||||
static void MT32EMU_C_CALL onErrorPCMROM(void *instance_data) {
|
||||
static_cast<IReportHandler *>(instance_data)->onErrorPCMROM();
|
||||
}
|
||||
|
||||
static void showLCDMessage(void *instance_data, const char *message) {
|
||||
static void MT32EMU_C_CALL showLCDMessage(void *instance_data, const char *message) {
|
||||
static_cast<IReportHandler *>(instance_data)->showLCDMessage(message);
|
||||
}
|
||||
|
||||
static void onMIDIMessagePlayed(void *instance_data) {
|
||||
static void MT32EMU_C_CALL onMIDIMessagePlayed(void *instance_data) {
|
||||
static_cast<IReportHandler *>(instance_data)->onMIDIMessagePlayed();
|
||||
}
|
||||
|
||||
static mt32emu_boolean onMIDIQueueOverflow(void *instance_data) {
|
||||
static mt32emu_boolean MT32EMU_C_CALL onMIDIQueueOverflow(void *instance_data) {
|
||||
return static_cast<IReportHandler *>(instance_data)->onMIDIQueueOverflow() ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE;
|
||||
}
|
||||
|
||||
static void onMIDISystemRealtime(void *instance_data, mt32emu_bit8u system_realtime) {
|
||||
static void MT32EMU_C_CALL onMIDISystemRealtime(void *instance_data, mt32emu_bit8u system_realtime) {
|
||||
static_cast<IReportHandler *>(instance_data)->onMIDISystemRealtime(system_realtime);
|
||||
}
|
||||
|
||||
static void onDeviceReset(void *instance_data) {
|
||||
static void MT32EMU_C_CALL onDeviceReset(void *instance_data) {
|
||||
static_cast<IReportHandler *>(instance_data)->onDeviceReset();
|
||||
}
|
||||
|
||||
static void onDeviceReconfig(void *instance_data) {
|
||||
static void MT32EMU_C_CALL onDeviceReconfig(void *instance_data) {
|
||||
static_cast<IReportHandler *>(instance_data)->onDeviceReconfig();
|
||||
}
|
||||
|
||||
static void onNewReverbMode(void *instance_data, mt32emu_bit8u mode) {
|
||||
static void MT32EMU_C_CALL onNewReverbMode(void *instance_data, mt32emu_bit8u mode) {
|
||||
static_cast<IReportHandler *>(instance_data)->onNewReverbMode(mode);
|
||||
}
|
||||
|
||||
static void onNewReverbTime(void *instance_data, mt32emu_bit8u time) {
|
||||
static void MT32EMU_C_CALL onNewReverbTime(void *instance_data, mt32emu_bit8u time) {
|
||||
static_cast<IReportHandler *>(instance_data)->onNewReverbTime(time);
|
||||
}
|
||||
|
||||
static void onNewReverbLevel(void *instance_data, mt32emu_bit8u level) {
|
||||
static void MT32EMU_C_CALL onNewReverbLevel(void *instance_data, mt32emu_bit8u level) {
|
||||
static_cast<IReportHandler *>(instance_data)->onNewReverbLevel(level);
|
||||
}
|
||||
|
||||
static void onPolyStateChanged(void *instance_data, mt32emu_bit8u part_num) {
|
||||
static void MT32EMU_C_CALL onPolyStateChanged(void *instance_data, mt32emu_bit8u part_num) {
|
||||
static_cast<IReportHandler *>(instance_data)->onPolyStateChanged(part_num);
|
||||
}
|
||||
|
||||
static void onProgramChanged(void *instance_data, mt32emu_bit8u part_num, const char *sound_group_name, const char *patch_name) {
|
||||
static void MT32EMU_C_CALL onProgramChanged(void *instance_data, mt32emu_bit8u part_num, const char *sound_group_name, const char *patch_name) {
|
||||
static_cast<IReportHandler *>(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 void MT32EMU_C_CALL onLCDStateUpdated(void *instance_data) {
|
||||
static_cast<IReportHandlerV1 *>(instance_data)->onLCDStateUpdated();
|
||||
}
|
||||
|
||||
static mt32emu_midi_receiver_version getMidiReceiverVersionID(mt32emu_midi_receiver_i) {
|
||||
static void MT32EMU_C_CALL onMidiMessageLEDStateUpdated(void *instance_data, mt32emu_boolean led_state) {
|
||||
static_cast<IReportHandlerV1 *>(instance_data)->onMidiMessageLEDStateUpdated(led_state != MT32EMU_BOOL_FALSE);
|
||||
}
|
||||
|
||||
#define MT32EMU_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_v0 REPORT_HANDLER_V0_THUNK = {
|
||||
MT32EMU_REPORT_HANDLER_V0_THUNK
|
||||
};
|
||||
|
||||
static const mt32emu_report_handler_i_v1 REPORT_HANDLER_V1_THUNK = {
|
||||
MT32EMU_REPORT_HANDLER_V0_THUNK,
|
||||
onLCDStateUpdated,
|
||||
onMidiMessageLEDStateUpdated
|
||||
};
|
||||
|
||||
#undef MT32EMU_REPORT_HANDLER_THUNK_V0
|
||||
|
||||
static mt32emu_report_handler_version MT32EMU_C_CALL getReportHandlerVersionID(mt32emu_report_handler_i thunk) {
|
||||
if (thunk.v0 == &REPORT_HANDLER_V0_THUNK) return MT32EMU_REPORT_HANDLER_VERSION_0;
|
||||
return MT32EMU_REPORT_HANDLER_VERSION_CURRENT;
|
||||
}
|
||||
|
||||
static mt32emu_report_handler_i getReportHandlerThunk(mt32emu_report_handler_version versionID) {
|
||||
mt32emu_report_handler_i thunk;
|
||||
if (versionID == MT32EMU_REPORT_HANDLER_VERSION_0) thunk.v0 = &REPORT_HANDLER_V0_THUNK;
|
||||
else thunk.v1 = &REPORT_HANDLER_V1_THUNK;
|
||||
return thunk;
|
||||
}
|
||||
|
||||
static mt32emu_midi_receiver_version MT32EMU_C_CALL getMidiReceiverVersionID(mt32emu_midi_receiver_i) {
|
||||
return MT32EMU_MIDI_RECEIVER_VERSION_CURRENT;
|
||||
}
|
||||
|
||||
static void handleShortMessage(void *instance_data, const mt32emu_bit32u message) {
|
||||
static void MT32EMU_C_CALL handleShortMessage(void *instance_data, const mt32emu_bit32u message) {
|
||||
static_cast<IMidiReceiver *>(instance_data)->handleShortMessage(message);
|
||||
}
|
||||
|
||||
static void handleSysex(void *instance_data, const mt32emu_bit8u stream[], const mt32emu_bit32u length) {
|
||||
static void MT32EMU_C_CALL handleSysex(void *instance_data, const mt32emu_bit8u stream[], const mt32emu_bit32u length) {
|
||||
static_cast<IMidiReceiver *>(instance_data)->handleSysex(stream, length);
|
||||
}
|
||||
|
||||
static void handleSystemRealtimeMessage(void *instance_data, const mt32emu_bit8u realtime) {
|
||||
static void MT32EMU_C_CALL handleSystemRealtimeMessage(void *instance_data, const mt32emu_bit8u realtime) {
|
||||
static_cast<IMidiReceiver *>(instance_data)->handleSystemRealtimeMessage(realtime);
|
||||
}
|
||||
|
||||
@@ -424,10 +502,17 @@ static mt32emu_midi_receiver_i getMidiReceiverThunk() {
|
||||
#undef mt32emu_get_library_version_string
|
||||
#undef mt32emu_get_stereo_output_samplerate
|
||||
#undef mt32emu_get_best_analog_output_mode
|
||||
#undef mt32emu_get_machine_ids
|
||||
#undef mt32emu_get_rom_ids
|
||||
#undef mt32emu_identify_rom_data
|
||||
#undef mt32emu_identify_rom_file
|
||||
#undef mt32emu_create_context
|
||||
#undef mt32emu_free_context
|
||||
#undef mt32emu_add_rom_data
|
||||
#undef mt32emu_add_rom_file
|
||||
#undef mt32emu_merge_and_add_rom_data
|
||||
#undef mt32emu_merge_and_add_rom_files
|
||||
#undef mt32emu_add_machine_rom_file
|
||||
#undef mt32emu_get_rom_info
|
||||
#undef mt32emu_set_partial_count
|
||||
#undef mt32emu_set_analog_output_mode
|
||||
@@ -493,7 +578,14 @@ static mt32emu_midi_receiver_i getMidiReceiverThunk() {
|
||||
#undef mt32emu_get_partial_states
|
||||
#undef mt32emu_get_playing_notes
|
||||
#undef mt32emu_get_patch_name
|
||||
#undef mt32emu_get_sound_group_name
|
||||
#undef mt32emu_get_sound_name
|
||||
#undef mt32emu_read_memory
|
||||
#undef mt32emu_get_display_state
|
||||
#undef mt32emu_set_main_display_mode
|
||||
#undef mt32emu_set_display_compatibility
|
||||
#undef mt32emu_is_display_old_mt32_compatible
|
||||
#undef mt32emu_is_default_display_old_mt32_compatible
|
||||
|
||||
#endif // #if MT32EMU_API_TYPE == 2
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
@@ -18,9 +18,9 @@
|
||||
#ifndef MT32EMU_CONFIG_H
|
||||
#define MT32EMU_CONFIG_H
|
||||
|
||||
#define MT32EMU_VERSION "2.4.0"
|
||||
#define MT32EMU_VERSION "2.7.0"
|
||||
#define MT32EMU_VERSION_MAJOR 2
|
||||
#define MT32EMU_VERSION_MINOR 4
|
||||
#define MT32EMU_VERSION_MINOR 7
|
||||
#define MT32EMU_VERSION_PATCH 0
|
||||
|
||||
/* Library Exports Configuration
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
@@ -33,6 +33,35 @@
|
||||
* is exported, and thus the client application may ONLY use MT32EMU_API_TYPE 2.
|
||||
* 3: All the available API types are provided by the library build.
|
||||
*/
|
||||
#define MT32EMU_EXPORTS_TYPE @libmt32emu_EXPORTS_TYPE@
|
||||
#define MT32EMU_EXPORTS_TYPE @libmt32emu_EXPORTS_TYPE@
|
||||
|
||||
/* Type of library build.
|
||||
*
|
||||
* For shared library builds, MT32EMU_SHARED is defined, so that compiler-specific attributes are assigned
|
||||
* to all the exported symbols as appropriate. MT32EMU_SHARED is undefined for static library builds.
|
||||
*/
|
||||
@libmt32emu_SHARED_DEFINITION@
|
||||
|
||||
/* Whether the library is built as a shared object with a version tag to enable runtime version checks. */
|
||||
#define MT32EMU_WITH_VERSION_TAGGING @libmt32emu_RUNTIME_VERSION_CHECK@
|
||||
|
||||
/* Automatic runtime check of the shared library version in client applications.
|
||||
*
|
||||
* When the shared library is built with version tagging enabled, the client application may rely on an automatic
|
||||
* version check that ensures forward compatibility. See VersionTagging.h for more info.
|
||||
* 0: Disables the automatic runtime version check in the client application. Implied for static library builds
|
||||
* and when version tagging is not used in a shared object.
|
||||
* 1: Enables an automatic runtime version check in client applications that utilise low-level C++ API,
|
||||
* i.e. when MT32EMU_API_TYPE 0. Client applications that rely on the C-compatible API are supposed
|
||||
* to check the version of the shared object by other means (e.g. using versioned C symbols, etc.).
|
||||
* 2: Enables an automatic runtime version check for C++ and C client applications.
|
||||
*/
|
||||
#if MT32EMU_WITH_VERSION_TAGGING
|
||||
# ifndef MT32EMU_RUNTIME_VERSION_CHECK
|
||||
# define MT32EMU_RUNTIME_VERSION_CHECK @libmt32emu_RUNTIME_VERSION_CHECK@
|
||||
# endif
|
||||
#else
|
||||
# undef MT32EMU_RUNTIME_VERSION_CHECK
|
||||
#endif
|
||||
|
||||
#endif /* #ifndef MT32EMU_CONFIG_H */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
@@ -20,27 +20,35 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
/* Support for compiling shared library. */
|
||||
/* Support for compiling shared library.
|
||||
* MT32EMU_SHARED and mt32emu_EXPORTS are defined when building a shared library.
|
||||
* MT32EMU_SHARED should also be defined for Windows platforms that provides for a small performance benefit,
|
||||
* and it _must_ be defined along with MT32EMU_RUNTIME_VERSION_CHECK when using MSVC.
|
||||
*/
|
||||
#ifdef MT32EMU_SHARED
|
||||
#if defined _WIN32 || defined __CYGWIN__
|
||||
#ifdef _MSC_VER
|
||||
#ifdef mt32emu_EXPORTS
|
||||
#define MT32EMU_EXPORT_ATTRIBUTE _declspec(dllexport)
|
||||
#else /* #ifdef mt32emu_EXPORTS */
|
||||
#define MT32EMU_EXPORT_ATTRIBUTE _declspec(dllimport)
|
||||
#endif /* #ifdef mt32emu_EXPORTS */
|
||||
#else /* #ifdef _MSC_VER */
|
||||
#ifdef mt32emu_EXPORTS
|
||||
#define MT32EMU_EXPORT_ATTRIBUTE __attribute__ ((dllexport))
|
||||
#else /* #ifdef mt32emu_EXPORTS */
|
||||
#define MT32EMU_EXPORT_ATTRIBUTE __attribute__ ((dllimport))
|
||||
#endif /* #ifdef mt32emu_EXPORTS */
|
||||
#endif /* #ifdef _MSC_VER */
|
||||
#else /* #if defined _WIN32 || defined __CYGWIN__ */
|
||||
#define MT32EMU_EXPORT_ATTRIBUTE __attribute__ ((visibility("default")))
|
||||
#endif /* #if defined _WIN32 || defined __CYGWIN__ */
|
||||
# if defined _WIN32 || defined __CYGWIN__ || defined __OS2__
|
||||
# ifdef _MSC_VER
|
||||
# ifdef mt32emu_EXPORTS
|
||||
# define MT32EMU_EXPORT_ATTRIBUTE _declspec(dllexport)
|
||||
# else /* #ifdef mt32emu_EXPORTS */
|
||||
# define MT32EMU_EXPORT_ATTRIBUTE _declspec(dllimport)
|
||||
# endif /* #ifdef mt32emu_EXPORTS */
|
||||
# else /* #ifdef _MSC_VER */
|
||||
# ifdef mt32emu_EXPORTS
|
||||
# define MT32EMU_EXPORT_ATTRIBUTE __attribute__ ((dllexport))
|
||||
# else /* #ifdef mt32emu_EXPORTS */
|
||||
# define MT32EMU_EXPORT_ATTRIBUTE __attribute__ ((dllimport))
|
||||
# endif /* #ifdef mt32emu_EXPORTS */
|
||||
# endif /* #ifdef _MSC_VER */
|
||||
# else /* #if defined _WIN32 || defined __CYGWIN__ || defined __OS2__ */
|
||||
# ifdef mt32emu_EXPORTS
|
||||
# define MT32EMU_EXPORT_ATTRIBUTE __attribute__ ((visibility("default")))
|
||||
# else /* #ifdef mt32emu_EXPORTS */
|
||||
# define MT32EMU_EXPORT_ATTRIBUTE
|
||||
# endif /* #ifdef mt32emu_EXPORTS */
|
||||
# endif /* #if defined _WIN32 || defined __CYGWIN__ || defined __OS2__ */
|
||||
#else /* #ifdef MT32EMU_SHARED */
|
||||
#define MT32EMU_EXPORT_ATTRIBUTE
|
||||
# define MT32EMU_EXPORT_ATTRIBUTE
|
||||
#endif /* #ifdef MT32EMU_SHARED */
|
||||
|
||||
#if MT32EMU_EXPORTS_TYPE == 1 || MT32EMU_EXPORTS_TYPE == 2
|
||||
@@ -49,6 +57,33 @@
|
||||
#define MT32EMU_EXPORT MT32EMU_EXPORT_ATTRIBUTE
|
||||
#endif
|
||||
|
||||
/* Facilitates easier tracking of the library version when an external symbol was introduced.
|
||||
* Particularly useful for shared library builds on POSIX systems that support symbol versioning,
|
||||
* so that the version map file can be generated automatically.
|
||||
*/
|
||||
#define MT32EMU_EXPORT_V(symbol_version_tag) MT32EMU_EXPORT
|
||||
|
||||
/* Helpers for compile-time version checks */
|
||||
|
||||
/* Encodes the given version components to a single integer value to simplify further checks. */
|
||||
#define MT32EMU_VERSION_INT(major, minor, patch) ((major << 16) | (minor << 8) | patch)
|
||||
|
||||
/* The version of this library build, as an integer. */
|
||||
#define MT32EMU_CURRENT_VERSION_INT MT32EMU_VERSION_INT(MT32EMU_VERSION_MAJOR, MT32EMU_VERSION_MINOR, MT32EMU_VERSION_PATCH)
|
||||
|
||||
/* Compares the current library version with the given version components. Intended for feature checks. */
|
||||
#define MT32EMU_VERSION_ATLEAST(major, minor, patch) (MT32EMU_CURRENT_VERSION_INT >= MT32EMU_VERSION_INT(major, minor, patch))
|
||||
|
||||
/* Implements a simple version check that ensures full API compatibility of this library build
|
||||
* with the application requirements. The latter can be derived from the versions of used public symbols.
|
||||
*
|
||||
* Note: This macro is intended for a quick compile-time check. To ensure compatibility of an application
|
||||
* linked with a shared library, an automatic version check can be engaged with help of the build option
|
||||
* libmt32emu_WITH_VERSION_TAGGING. For a fine-grained feature checking in run-time, see functions
|
||||
* mt32emu_get_library_version_int and Synth::getLibraryVersionInt.
|
||||
*/
|
||||
#define MT32EMU_IS_COMPATIBLE(major, minor) (MT32EMU_VERSION_MAJOR == major && MT32EMU_VERSION_MINOR >= minor)
|
||||
|
||||
/* Useful constants */
|
||||
|
||||
/* Sample rate to use in mixing. With the progress of development, we've found way too many thing dependent.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
|
||||
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
|
||||
* Copyright (C) 2011-2022 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
|
||||
@@ -37,28 +37,23 @@
|
||||
*/
|
||||
|
||||
#ifdef MT32EMU_API_TYPE
|
||||
#if MT32EMU_API_TYPE == 0 && (MT32EMU_EXPORTS_TYPE == 1 || MT32EMU_EXPORTS_TYPE == 2)
|
||||
#error Incompatible setting MT32EMU_API_TYPE=0
|
||||
#elif MT32EMU_API_TYPE == 1 && (MT32EMU_EXPORTS_TYPE == 0 || MT32EMU_EXPORTS_TYPE == 2)
|
||||
#error Incompatible setting MT32EMU_API_TYPE=1
|
||||
#elif MT32EMU_API_TYPE == 2 && (MT32EMU_EXPORTS_TYPE == 0)
|
||||
#error Incompatible setting MT32EMU_API_TYPE=2
|
||||
#elif MT32EMU_API_TYPE == 3 && (MT32EMU_EXPORTS_TYPE == 0 || MT32EMU_EXPORTS_TYPE == 2)
|
||||
#error Incompatible setting MT32EMU_API_TYPE=3
|
||||
#endif
|
||||
# if MT32EMU_API_TYPE == 0 && (MT32EMU_EXPORTS_TYPE == 1 || MT32EMU_EXPORTS_TYPE == 2)
|
||||
# error Incompatible setting MT32EMU_API_TYPE=0
|
||||
# elif MT32EMU_API_TYPE == 1 && (MT32EMU_EXPORTS_TYPE == 0 || MT32EMU_EXPORTS_TYPE == 2)
|
||||
# error Incompatible setting MT32EMU_API_TYPE=1
|
||||
# elif MT32EMU_API_TYPE == 2 && (MT32EMU_EXPORTS_TYPE == 0)
|
||||
# error Incompatible setting MT32EMU_API_TYPE=2
|
||||
# elif MT32EMU_API_TYPE == 3 && (MT32EMU_EXPORTS_TYPE == 0 || MT32EMU_EXPORTS_TYPE == 2)
|
||||
# error Incompatible setting MT32EMU_API_TYPE=3
|
||||
# endif
|
||||
#else /* #ifdef MT32EMU_API_TYPE */
|
||||
#if 0 < MT32EMU_EXPORTS_TYPE && MT32EMU_EXPORTS_TYPE < 3
|
||||
#define MT32EMU_API_TYPE MT32EMU_EXPORTS_TYPE
|
||||
#else
|
||||
#define MT32EMU_API_TYPE 0
|
||||
#endif
|
||||
# if 0 < MT32EMU_EXPORTS_TYPE && MT32EMU_EXPORTS_TYPE < 3
|
||||
# define MT32EMU_API_TYPE MT32EMU_EXPORTS_TYPE
|
||||
# else
|
||||
# define MT32EMU_API_TYPE 0
|
||||
# endif
|
||||
#endif /* #ifdef MT32EMU_API_TYPE */
|
||||
|
||||
/* MT32EMU_SHARED should be defined when building shared library, especially for Windows platforms. */
|
||||
/*
|
||||
#define MT32EMU_SHARED
|
||||
*/
|
||||
|
||||
#include "globals.h"
|
||||
|
||||
#if !defined(__cplusplus) || MT32EMU_API_TYPE == 1
|
||||
@@ -79,6 +74,14 @@
|
||||
#include "MidiStreamParser.h"
|
||||
#include "SampleRateConverter.h"
|
||||
|
||||
#if MT32EMU_RUNTIME_VERSION_CHECK == 1
|
||||
#include "VersionTagging.h"
|
||||
#endif
|
||||
|
||||
#endif /* #if !defined(__cplusplus) || MT32EMU_API_TYPE == 1 */
|
||||
|
||||
#if MT32EMU_RUNTIME_VERSION_CHECK == 2
|
||||
#include "VersionTagging.h"
|
||||
#endif
|
||||
|
||||
#endif /* #ifndef MT32EMU_MT32EMU_H */
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2015-2020 Sergey V. Mikayev
|
||||
/* Copyright (C) 2015-2022 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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2015-2020 Sergey V. Mikayev
|
||||
/* Copyright (C) 2015-2022 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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2015-2020 Sergey V. Mikayev
|
||||
/* Copyright (C) 2015-2022 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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2015-2020 Sergey V. Mikayev
|
||||
/* Copyright (C) 2015-2022 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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2015-2020 Sergey V. Mikayev
|
||||
/* Copyright (C) 2015-2022 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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2015-2020 Sergey V. Mikayev
|
||||
/* Copyright (C) 2015-2022 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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2015-2020 Sergey V. Mikayev
|
||||
/* Copyright (C) 2015-2022 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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2015-2020 Sergey V. Mikayev
|
||||
/* Copyright (C) 2015-2022 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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2015-2020 Sergey V. Mikayev
|
||||
/* Copyright (C) 2015-2022 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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2015-2020 Sergey V. Mikayev
|
||||
/* Copyright (C) 2015-2022 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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2015-2020 Sergey V. Mikayev
|
||||
/* Copyright (C) 2015-2022 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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2015-2020 Sergey V. Mikayev
|
||||
/* Copyright (C) 2015-2022 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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2015-2020 Sergey V. Mikayev
|
||||
/* Copyright (C) 2015-2022 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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2015-2020 Sergey V. Mikayev
|
||||
/* Copyright (C) 2015-2022 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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2015-2020 Sergey V. Mikayev
|
||||
/* Copyright (C) 2015-2022 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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2015-2020 Sergey V. Mikayev
|
||||
/* Copyright (C) 2015-2022 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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2015-2020 Sergey V. Mikayev
|
||||
/* Copyright (C) 2015-2022 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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2015-2020 Sergey V. Mikayev
|
||||
/* Copyright (C) 2015-2022 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
|
||||
|
||||
@@ -397,7 +397,7 @@ endif
|
||||
ifeq ($(MUNT), y)
|
||||
OPTS += -DUSE_MUNT
|
||||
MUNTOBJ := midi_mt32.o \
|
||||
Analog.o BReverbModel.o File.o FileStream.o LA32Ramp.o \
|
||||
Analog.o BReverbModel.o Display.o File.o FileStream.o LA32Ramp.o \
|
||||
LA32FloatWaveGenerator.o LA32WaveGenerator.o \
|
||||
MidiStreamParser.o Part.o Partial.o PartialManager.o \
|
||||
Poly.o ROMInfo.o SampleRateConverter.o \
|
||||
|
||||
Reference in New Issue
Block a user