aboutsummaryrefslogtreecommitdiff
path: root/audio/softsynth/mt32/Synth.h
diff options
context:
space:
mode:
Diffstat (limited to 'audio/softsynth/mt32/Synth.h')
-rw-r--r--audio/softsynth/mt32/Synth.h388
1 files changed, 205 insertions, 183 deletions
diff --git a/audio/softsynth/mt32/Synth.h b/audio/softsynth/mt32/Synth.h
index 97d4644ee2..5561d8d5db 100644
--- a/audio/softsynth/mt32/Synth.h
+++ b/audio/softsynth/mt32/Synth.h
@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
- * Copyright (C) 2011, 2012, 2013, 2014 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
+ * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
@@ -18,8 +18,13 @@
#ifndef MT32EMU_SYNTH_H
#define MT32EMU_SYNTH_H
-//#include <cstdarg>
-//#include <cstring>
+#include <cstdarg>
+#include <cstddef>
+#include <cstring>
+
+#include "globals.h"
+#include "Types.h"
+#include "Enumerations.h"
namespace MT32Emu {
@@ -31,6 +36,8 @@ class Part;
class Poly;
class Partial;
class PartialManager;
+class Renderer;
+class ROMImage;
class PatchTempMemoryRegion;
class RhythmTempMemoryRegion;
@@ -41,82 +48,11 @@ class SystemMemoryRegion;
class DisplayMemoryRegion;
class ResetMemoryRegion;
+struct ControlROMFeatureSet;
struct ControlROMMap;
struct PCMWaveEntry;
struct MemParams;
-/**
- * Methods for emulating the connection between the LA32 and the DAC, which involves
- * some hacks in the real devices for doubling the volume.
- * See also http://en.wikipedia.org/wiki/Roland_MT-32#Digital_overflow
- */
-enum DACInputMode {
- // Produces samples at double the volume, without tricks.
- // * Nicer overdrive characteristics than the DAC hacks (it simply clips samples within range)
- // * Higher quality than the real devices
- DACInputMode_NICE,
-
- // Produces samples that exactly match the bits output from the emulated LA32.
- // * Nicer overdrive characteristics than the DAC hacks (it simply clips samples within range)
- // * Much less likely to overdrive than any other mode.
- // * Half the volume of any of the other modes.
- // * Output gain is ignored for both LA32 and reverb output.
- // * Perfect for developers while debugging :)
- DACInputMode_PURE,
-
- // Re-orders the LA32 output bits as in early generation MT-32s (according to Wikipedia).
- // Bit order at DAC (where each number represents the original LA32 output bit number, and XX means the bit is always low):
- // 15 13 12 11 10 09 08 07 06 05 04 03 02 01 00 XX
- DACInputMode_GENERATION1,
-
- // Re-orders the LA32 output bits as in later generations (personally confirmed on my CM-32L - KG).
- // Bit order at DAC (where each number represents the original LA32 output bit number):
- // 15 13 12 11 10 09 08 07 06 05 04 03 02 01 00 14
- DACInputMode_GENERATION2
-};
-
-// Methods for emulating the effective delay of incoming MIDI messages introduced by a MIDI interface.
-enum MIDIDelayMode {
- // Process incoming MIDI events immediately.
- MIDIDelayMode_IMMEDIATE,
-
- // Delay incoming short MIDI messages as if they where transferred via a MIDI cable to a real hardware unit and immediate sysex processing.
- // This ensures more accurate timing of simultaneous NoteOn messages.
- MIDIDelayMode_DELAY_SHORT_MESSAGES_ONLY,
-
- // Delay all incoming MIDI events as if they where transferred via a MIDI cable to a real hardware unit.
- MIDIDelayMode_DELAY_ALL
-};
-
-// Methods for emulating the effects of analogue circuits of real hardware units on the output signal.
-enum AnalogOutputMode {
- // Only digital path is emulated. The output samples correspond to the digital signal at the DAC entrance.
- AnalogOutputMode_DIGITAL_ONLY,
- // Coarse emulation of LPF circuit. High frequencies are boosted, sample rate remains unchanged.
- AnalogOutputMode_COARSE,
- // Finer emulation of LPF circuit. Output signal is upsampled to 48 kHz to allow emulation of audible mirror spectra above 16 kHz,
- // which is passed through the LPF circuit without significant attenuation.
- AnalogOutputMode_ACCURATE,
- // Same as AnalogOutputMode_ACCURATE mode but the output signal is 2x oversampled, i.e. the output sample rate is 96 kHz.
- // This makes subsequent resampling easier. Besides, due to nonlinear passband of the LPF emulated, it takes fewer number of MACs
- // compared to a regular LPF FIR implementations.
- AnalogOutputMode_OVERSAMPLED
-};
-
-enum ReverbMode {
- REVERB_MODE_ROOM,
- REVERB_MODE_HALL,
- REVERB_MODE_PLATE,
- REVERB_MODE_TAP_DELAY
-};
-
-enum PartialState {
- PartialState_INACTIVE,
- PartialState_ATTACK,
- PartialState_SUSTAIN,
- PartialState_RELEASE
-};
-
const Bit8u SYSEX_MANUFACTURER_ROLAND = 0x41;
const Bit8u SYSEX_MDL_MT32 = 0x16;
@@ -132,47 +68,64 @@ const Bit8u SYSEX_CMD_EOD = 0x45; // End of data
const Bit8u SYSEX_CMD_ERR = 0x4E; // Communications error
const Bit8u SYSEX_CMD_RJC = 0x4F; // Rejection
-const int MAX_SYSEX_SIZE = 512; // FIXME: Does this correspond to a real MIDI buffer used in h/w devices?
-
-const unsigned int CONTROL_ROM_SIZE = 64 * 1024;
-
-class ReportHandler {
-friend class Synth;
+const Bit32u CONTROL_ROM_SIZE = 64 * 1024;
+
+// Set of multiplexed output streams appeared at the DAC entrance.
+template <class T>
+struct DACOutputStreams {
+ T *nonReverbLeft;
+ T *nonReverbRight;
+ T *reverbDryLeft;
+ T *reverbDryRight;
+ T *reverbWetLeft;
+ T *reverbWetRight;
+};
+// Class for the client to supply callbacks for reporting various errors and information
+class MT32EMU_EXPORT ReportHandler {
public:
virtual ~ReportHandler() {}
-protected:
-
// Callback for debug messages, in vprintf() format
virtual void printDebug(const char *fmt, va_list list);
-
- // Callbacks for reporting various errors and information
+ // Callbacks for reporting errors
virtual void onErrorControlROM() {}
virtual void onErrorPCMROM() {}
+ // Callback for reporting about displaying a new custom message on LCD
virtual void showLCDMessage(const char *message);
+ // Callback for reporting actual processing of a MIDI message
virtual void onMIDIMessagePlayed() {}
+ // Callback for reporting an overflow of the input MIDI queue.
+ // Returns true if a recovery action was taken and yet another attempt to enqueue the MIDI event is desired.
+ virtual bool onMIDIQueueOverflow() { return false; }
+ // Callback invoked when a System Realtime MIDI message is detected at the input.
+ virtual void onMIDISystemRealtime(Bit8u /* systemRealtime */) {}
+ // Callbacks for reporting system events
virtual void onDeviceReset() {}
virtual void onDeviceReconfig() {}
+ // Callbacks for reporting changes of reverb settings
virtual void onNewReverbMode(Bit8u /* mode */) {}
virtual void onNewReverbTime(Bit8u /* time */) {}
virtual void onNewReverbLevel(Bit8u /* level */) {}
- virtual void onPolyStateChanged(int /* partNum */) {}
- virtual void onProgramChanged(int /* partNum */, int /* bankNum */, const char * /* patchName */) {}
+ // Callbacks for reporting various information
+ virtual void onPolyStateChanged(Bit8u /* partNum */) {}
+ virtual void onProgramChanged(Bit8u /* partNum */, const char * /* soundGroupName */, const char * /* patchName */) {}
};
class Synth {
+friend class DefaultMidiStreamParser;
friend class Part;
-friend class RhythmPart;
-friend class Poly;
friend class Partial;
friend class PartialManager;
-friend class Tables;
-friend class MemoryRegion;
+friend class Poly;
+friend class Renderer;
+friend class RhythmPart;
friend class TVA;
-friend class TVF;
friend class TVP;
+
private:
+ // **************************** Implementation fields **************************
+
PatchTempMemoryRegion *patchTempMemoryRegion;
RhythmTempMemoryRegion *rhythmTempMemoryRegion;
TimbreTempMemoryRegion *timbreTempMemoryRegion;
@@ -184,8 +137,6 @@ private:
Bit8u *paddedTimbreMaxTable;
- bool isEnabled;
-
PCMWaveEntry *pcmWaves; // Array
const ControlROMFeatureSet *controlROMFeatures;
@@ -194,8 +145,11 @@ private:
Bit16s *pcmROMData;
size_t pcmROMSize; // This is in 16-bit samples, therefore half the number of bytes in the ROM
- unsigned int partialCount;
- Bit8s chantable[32]; // FIXME: Need explanation why 32 is set, obviously it should be 16
+ Bit8u soundGroupIx[128]; // For each standard timbre
+ const char (*soundGroupNames)[9]; // Array
+
+ Bit32u partialCount;
+ Bit8u chantable[16]; // NOTE: value above 8 means that the channel is not assigned
MidiEventQueue *midiQueue;
volatile Bit32u lastReceivedMIDIEventTimestamp;
@@ -215,7 +169,8 @@ private:
bool reversedStereoEnabled;
- bool isOpen;
+ bool opened;
+ bool activated;
bool isDefaultReportHandler;
ReportHandler *reportHandler;
@@ -229,15 +184,17 @@ private:
Poly *abortingPoly;
Analog *analog;
+ Renderer &renderer;
- Bit32u addMIDIInterfaceDelay(Bit32u len, Bit32u timestamp);
+ // Binary compatibility helper.
+ void *reserved;
- void produceLA32Output(Sample *buffer, Bit32u len);
- void convertSamplesToOutput(Sample *buffer, Bit32u len);
- bool isAbortingPoly() const;
- void doRenderStreams(Sample *nonReverbLeft, Sample *nonReverbRight, Sample *reverbDryLeft, Sample *reverbDryRight, Sample *reverbWetLeft, Sample *reverbWetRight, Bit32u len);
+ // **************************** Implementation methods **************************
- void readSysex(unsigned char channel, const Bit8u *sysex, Bit32u len) const;
+ Bit32u addMIDIInterfaceDelay(Bit32u len, Bit32u timestamp);
+ bool isAbortingPoly() const { return abortingPoly != NULL; }
+
+ void readSysex(Bit8u channel, const Bit8u *sysex, Bit32u len) const;
void initMemoryRegions();
void deleteMemoryRegions();
MemoryRegion *findMemoryRegion(Bit32u addr);
@@ -248,79 +205,97 @@ private:
bool loadPCMROM(const ROMImage &pcmROMImage);
bool initPCMList(Bit16u mapAddress, Bit16u count);
- bool initTimbres(Bit16u mapAddress, Bit16u offset, int timbreCount, int startTimbre, bool compressed);
- bool initCompressedTimbre(int drumNum, const Bit8u *mem, unsigned int memLen);
+ bool initTimbres(Bit16u mapAddress, Bit16u offset, Bit16u timbreCount, Bit16u startTimbre, bool compressed);
+ bool initCompressedTimbre(Bit16u drumNum, const Bit8u *mem, Bit32u memLen);
+ void initReverbModels(bool mt32CompatibleMode);
+ void initSoundGroups(char newSoundGroupNames[][9]);
void refreshSystemMasterTune();
void refreshSystemReverbParameters();
void refreshSystemReserveSettings();
- void refreshSystemChanAssign(unsigned int firstPart, unsigned int lastPart);
+ void refreshSystemChanAssign(Bit8u firstPart, Bit8u lastPart);
void refreshSystemMasterVol();
void refreshSystem();
void reset();
+ void dispose();
- void printPartialUsage(unsigned long sampleOffset = 0);
+ void printPartialUsage(Bit32u sampleOffset = 0);
- void polyStateChanged(int partNum);
- void newTimbreSet(int partNum, Bit8u timbreGroup, const char patchName[]);
+ void newTimbreSet(Bit8u partNum, Bit8u timbreGroup, Bit8u timbreNumber, const char patchName[]);
void printDebug(const char *fmt, ...);
// partNum should be 0..7 for Part 1..8, or 8 for Rhythm
- const Part *getPart(unsigned int partNum) const;
+ const Part *getPart(Bit8u partNum) const;
public:
- static inline Sample clipSampleEx(SampleEx sampleEx) {
-#if MT32EMU_USE_FLOAT_SAMPLES
- return sampleEx;
-#else
+ static inline Bit16s clipSampleEx(Bit32s sampleEx) {
// Clamp values above 32767 to 32767, and values below -32768 to -32768
// FIXME: Do we really need this stuff? I think these branches are very well predicted. Instead, this introduces a chain.
// The version below is actually a bit faster on my system...
- //return ((sampleEx + 0x8000) & ~0xFFFF) ? (sampleEx >> 31) ^ 0x7FFF : (Sample)sampleEx;
- return ((-0x8000 <= sampleEx) && (sampleEx <= 0x7FFF)) ? (Sample)sampleEx : (sampleEx >> 31) ^ 0x7FFF;
-#endif
+ //return ((sampleEx + 0x8000) & ~0xFFFF) ? Bit16s((sampleEx >> 31) ^ 0x7FFF) : (Bit16s)sampleEx;
+ return ((-0x8000 <= sampleEx) && (sampleEx <= 0x7FFF)) ? Bit16s(sampleEx) : Bit16s((sampleEx >> 31) ^ 0x7FFF);
+ }
+
+ static inline float clipSampleEx(float sampleEx) {
+ return sampleEx;
}
- static inline void muteSampleBuffer(Sample *buffer, Bit32u len) {
+ template <class S>
+ static inline void muteSampleBuffer(S *buffer, Bit32u len) {
if (buffer == NULL) return;
+ memset(buffer, 0, len * sizeof(S));
+ }
-#if MT32EMU_USE_FLOAT_SAMPLES
+ static inline void muteSampleBuffer(float *buffer, Bit32u len) {
+ if (buffer == NULL) return;
// FIXME: Use memset() where compatibility is guaranteed (if this turns out to be a win)
while (len--) {
*(buffer++) = 0.0f;
}
-#else
- memset(buffer, 0, len * sizeof(Sample));
-#endif
}
- static Bit32u getShortMessageLength(Bit32u msg);
- static Bit8u calcSysexChecksum(const Bit8u *data, const Bit32u len, const Bit8u initChecksum = 0);
+ // Returns library version as an integer in format: 0x00MMmmpp, where:
+ // MM - major version number
+ // mm - minor version number
+ // pp - patch number
+ MT32EMU_EXPORT static Bit32u getLibraryVersionInt();
+ // Returns library version as a C-string in format: "MAJOR.MINOR.PATCH"
+ MT32EMU_EXPORT static const char *getLibraryVersionString();
+
+ MT32EMU_EXPORT static Bit32u getShortMessageLength(Bit32u msg);
+ MT32EMU_EXPORT static Bit8u calcSysexChecksum(const Bit8u *data, const Bit32u len, const Bit8u initChecksum = 0);
+
+ // Returns output sample rate used in emulation of stereo analog circuitry of hardware units.
+ // See comment for AnalogOutputMode.
+ MT32EMU_EXPORT static Bit32u getStereoOutputSampleRate(AnalogOutputMode analogOutputMode);
// Optionally sets callbacks for reporting various errors, information and debug messages
- Synth(ReportHandler *useReportHandler = NULL);
- ~Synth();
+ MT32EMU_EXPORT explicit Synth(ReportHandler *useReportHandler = NULL);
+ MT32EMU_EXPORT ~Synth();
// 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.
// 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).
- bool open(const ROMImage &controlROMImage, const ROMImage &pcmROMImage, unsigned int usePartialCount = DEFAULT_MAX_PARTIALS, AnalogOutputMode analogOutputMode = AnalogOutputMode_COARSE);
+ MT32EMU_EXPORT bool open(const ROMImage &controlROMImage, const ROMImage &pcmROMImage, Bit32u usePartialCount = DEFAULT_MAX_PARTIALS, AnalogOutputMode analogOutputMode = AnalogOutputMode_COARSE);
// Overloaded method which opens the synth with default partial count.
- bool open(const ROMImage &controlROMImage, const ROMImage &pcmROMImage, AnalogOutputMode analogOutputMode);
+ MT32EMU_EXPORT bool open(const ROMImage &controlROMImage, const ROMImage &pcmROMImage, AnalogOutputMode analogOutputMode);
// Closes the MT-32 and deallocates any memory used by the synthesizer
- void close(bool forced = false);
+ MT32EMU_EXPORT void close();
+
+ // Returns true if the synth is in completely initialized state, otherwise returns false.
+ MT32EMU_EXPORT bool isOpen() const;
// All the enqueued events are processed by the synth immediately.
- void flushMIDIQueue();
+ MT32EMU_EXPORT void flushMIDIQueue();
// 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.
- Bit32u setMIDIEventQueueSize(Bit32u);
+ MT32EMU_EXPORT Bit32u setMIDIEventQueueSize(Bit32u);
// Enqueues a MIDI event for subsequent playback.
// The MIDI event will be processed not before the specified timestamp.
@@ -330,14 +305,15 @@ public:
// Calls from multiple threads must be synchronised, although, no synchronisation is required with the rendering thread.
// The methods return false if the MIDI event queue is full and the message cannot be enqueued.
- // Enqueues a single short MIDI message. The message must contain a status byte.
- bool playMsg(Bit32u msg, Bit32u timestamp);
- // Enqueues a single well formed System Exclusive MIDI message.
- bool playSysex(const Bit8u *sysex, Bit32u len, Bit32u timestamp);
+ // Enqueues a single short MIDI message to play at specified time. The message must contain a status byte.
+ MT32EMU_EXPORT bool playMsg(Bit32u msg, Bit32u timestamp);
+ // Enqueues a single well formed System Exclusive MIDI message to play at specified time.
+ MT32EMU_EXPORT bool playSysex(const Bit8u *sysex, Bit32u len, Bit32u timestamp);
- // Overloaded methods for the MIDI events to be processed ASAP.
- bool playMsg(Bit32u msg);
- bool playSysex(const Bit8u *sysex, Bit32u len);
+ // Enqueues a single short MIDI message to be processed ASAP. The message must contain a status byte.
+ MT32EMU_EXPORT bool playMsg(Bit32u msg);
+ // Enqueues a single well formed System Exclusive MIDI message to be processed ASAP.
+ MT32EMU_EXPORT bool playSysex(const Bit8u *sysex, Bit32u len);
// WARNING:
// The methods below don't ensure minimum 1-sample delay between sequential MIDI events,
@@ -345,40 +321,60 @@ public:
// A thread that invokes these methods must be explicitly synchronised with the thread performing sample rendering.
// Sends a short MIDI message to the synth for immediate playback. The message must contain a status byte.
- void playMsgNow(Bit32u msg);
- void playMsgOnPart(unsigned char part, unsigned char code, unsigned char note, unsigned char velocity);
-
- // Sends a string of Sysex commands to the MT-32 for immediate interpretation
- // The length is in bytes
- void playSysexNow(const Bit8u *sysex, Bit32u len);
- void playSysexWithoutFraming(const Bit8u *sysex, Bit32u len);
- void playSysexWithoutHeader(unsigned char device, unsigned char command, const Bit8u *sysex, Bit32u len);
- void writeSysex(unsigned char channel, const Bit8u *sysex, Bit32u len);
-
- void setReverbEnabled(bool reverbEnabled);
- bool isReverbEnabled() const;
+ // See the WARNING above.
+ MT32EMU_EXPORT void playMsgNow(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 playMsgOnPart(Bit8u part, Bit8u code, Bit8u note, 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 playSysexNow(const Bit8u *sysex, 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 playSysexWithoutFraming(const Bit8u *sysex, 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 playSysexWithoutHeader(Bit8u device, Bit8u command, const Bit8u *sysex, 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 writeSysex(Bit8u channel, const Bit8u *sysex, Bit32u len);
+
+ // Allows to disable wet reverb output altogether.
+ MT32EMU_EXPORT void setReverbEnabled(bool reverbEnabled);
+ // Returns whether wet reverb output is enabled.
+ MT32EMU_EXPORT bool isReverbEnabled() const;
// 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.
- void setReverbOverridden(bool reverbOverridden);
- bool isReverbOverridden() const;
+ MT32EMU_EXPORT void setReverbOverridden(bool reverbOverridden);
+ // Returns whether reverb settings are overridden.
+ MT32EMU_EXPORT bool isReverbOverridden() const;
// 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).
- void setReverbCompatibilityMode(bool mt32CompatibleMode);
- bool isMT32ReverbCompatibilityMode() const;
- void setDACInputMode(DACInputMode mode);
- DACInputMode getDACInputMode() const;
- void setMIDIDelayMode(MIDIDelayMode mode);
- MIDIDelayMode getMIDIDelayMode() const;
+ MT32EMU_EXPORT void setReverbCompatibilityMode(bool mt32CompatibleMode);
+ // Returns whether reverb is in old MT-32 compatibility mode.
+ MT32EMU_EXPORT bool isMT32ReverbCompatibilityMode() const;
+ // Returns whether default reverb compatibility mode is the old MT-32 compatibility mode.
+ MT32EMU_EXPORT bool isDefaultReverbMT32Compatible() const;
+ // Sets new DAC input mode. See DACInputMode for details.
+ MT32EMU_EXPORT void setDACInputMode(DACInputMode mode);
+ // Returns current DAC input mode. See DACInputMode for details.
+ MT32EMU_EXPORT DACInputMode getDACInputMode() const;
+ // Sets new MIDI delay mode. See MIDIDelayMode for details.
+ MT32EMU_EXPORT void setMIDIDelayMode(MIDIDelayMode mode);
+ // Returns current MIDI delay mode. See MIDIDelayMode for details.
+ MT32EMU_EXPORT MIDIDelayMode getMIDIDelayMode() const;
// 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 setReverbOutputGain()
// it offers to the user a capability to control the gain of reverb and non-reverb output channels independently.
// Ignored in DACInputMode_PURE
- void setOutputGain(float);
- float getOutputGain() const;
+ MT32EMU_EXPORT void setOutputGain(float gain);
+ // Returns current output gain factor for synth output channels.
+ MT32EMU_EXPORT float getOutputGain() const;
// Sets output gain factor for the reverb wet output channels. It rather corresponds to the gain of the output
// analog circuitry of the hardware units. However, together with setOutputGain() it offers to the user a capability
@@ -389,59 +385,85 @@ public:
// there is a difference in the reverb analogue circuit, and the resulting output gain is 0.68
// of that for LA32 analogue output. This factor is applied to the reverb output gain.
// Ignored in DACInputMode_PURE
- void setReverbOutputGain(float);
- float getReverbOutputGain() const;
+ MT32EMU_EXPORT void setReverbOutputGain(float gain);
+ // Returns current output gain factor for reverb wet output channels.
+ MT32EMU_EXPORT float getReverbOutputGain() const;
- void setReversedStereoEnabled(bool enabled);
- bool isReversedStereoEnabled();
+ // Swaps left and right output channels.
+ MT32EMU_EXPORT void setReversedStereoEnabled(bool enabled);
+ // Returns whether left and right output channels are swapped.
+ MT32EMU_EXPORT bool isReversedStereoEnabled() const;
// Returns actual sample rate used in emulation of stereo analog circuitry of hardware units.
// See comment for render() below.
- unsigned int getStereoOutputSampleRate() const;
+ MT32EMU_EXPORT Bit32u getStereoOutputSampleRate() const;
// Renders samples to the specified output stream as if they were sampled at the analog stereo output.
- // When AnalogOutputMode is set to ACCURATE, the output signal is upsampled to 48 kHz in order
+ // When AnalogOutputMode is set to ACCURATE (OVERSAMPLED), the output signal is upsampled to 48 (96) kHz in order
// to retain emulation accuracy in whole audible frequency spectra. Otherwise, native digital signal sample rate is retained.
// getStereoOutputSampleRate() can be used to query actual sample rate of the output signal.
- // The length is in frames, not bytes (in 16-bit stereo, one frame is 4 bytes).
- void render(Sample *stream, Bit32u len);
+ // The length is in frames, not bytes (in 16-bit stereo, one frame is 4 bytes). Uses NATIVE byte ordering.
+ MT32EMU_EXPORT void render(Bit16s *stream, Bit32u len);
+ // Same as above but outputs to a float stereo stream.
+ MT32EMU_EXPORT void render(float *stream, Bit32u len);
// Renders samples to the specified output streams as if they appeared at the DAC entrance.
// No further processing performed in analog circuitry emulation is applied to the signal.
- // NULL may be specified in place of any or all of the stream buffers.
- // The length is in samples, not bytes.
- void renderStreams(Sample *nonReverbLeft, Sample *nonReverbRight, Sample *reverbDryLeft, Sample *reverbDryRight, Sample *reverbWetLeft, Sample *reverbWetRight, Bit32u len);
+ // 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 renderStreams(Bit16s *nonReverbLeft, Bit16s *nonReverbRight, Bit16s *reverbDryLeft, Bit16s *reverbDryRight, Bit16s *reverbWetLeft, Bit16s *reverbWetRight, Bit32u len);
+ void renderStreams(const DACOutputStreams<Bit16s> &streams, Bit32u len) {
+ renderStreams(streams.nonReverbLeft, streams.nonReverbRight, streams.reverbDryLeft, streams.reverbDryRight, streams.reverbWetLeft, streams.reverbWetRight, len);
+ }
+ // Same as above but outputs to float streams.
+ MT32EMU_EXPORT void renderStreams(float *nonReverbLeft, float *nonReverbRight, float *reverbDryLeft, float *reverbDryRight, float *reverbWetLeft, float *reverbWetRight, Bit32u len);
+ void renderStreams(const DACOutputStreams<float> &streams, Bit32u len) {
+ renderStreams(streams.nonReverbLeft, streams.nonReverbRight, streams.reverbDryLeft, streams.reverbDryRight, streams.reverbWetLeft, streams.reverbWetRight, len);
+ }
// Returns true when there is at least one active partial, otherwise false.
- bool hasActivePartials() const;
+ MT32EMU_EXPORT bool hasActivePartials() const;
- // Returns true if hasActivePartials() returns true, or reverb is (somewhat unreliably) detected as being active.
- bool isActive() const;
+ // Returns true if the synth is active and subsequent calls to render() may result in non-trivial output (i.e. silence).
+ // The synth is considered active when either there are pending MIDI events in the queue, there is at least one active partial,
+ // or the reverb is (somewhat unreliably) detected as being active.
+ MT32EMU_EXPORT bool isActive();
// Returns the maximum number of partials playing simultaneously.
- unsigned int getPartialCount() const;
+ MT32EMU_EXPORT Bit32u getPartialCount() const;
// Fills in current states of all the parts into the array provided. The array must have at least 9 entries to fit values for all the parts.
// If the value returned for a part is true, 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.
- void getPartStates(bool *partStates) const;
+ MT32EMU_EXPORT void getPartStates(bool *partStates) const;
+
+ // 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 Bit32u getPartStates() const;
// Fills in current states of all the partials into the array provided. The array must be large enough to accommodate states of all the partials.
- void getPartialStates(PartialState *partialStates) const;
+ MT32EMU_EXPORT void getPartialStates(PartialState *partialStates) const;
+
+ // Fills in current states of all the partials into the array provided. Each byte in the array holds states of 4 partials
+ // starting from the least significant bits. The state of each partial is packed in a pair of bits.
+ // The array must be large enough to accommodate states of all the partials (see getPartialCount()).
+ MT32EMU_EXPORT void getPartialStates(Bit8u *partialStates) const;
// Fills in information about currently playing notes on the specified part into the arrays provided. The arrays must be large enough
// to accommodate data for all the playing notes. The maximum number of simultaneously playing notes cannot exceed the number of partials.
// Argument partNumber should be 0..7 for Part 1..8, or 8 for Rhythm.
// Returns the number of currently playing notes on the specified part.
- unsigned int getPlayingNotes(unsigned int partNumber, Bit8u *keys, Bit8u *velocities) const;
+ MT32EMU_EXPORT Bit32u getPlayingNotes(Bit8u partNumber, Bit8u *keys, Bit8u *velocities) const;
// Returns name of the patch set on the specified part.
// Argument partNumber should be 0..7 for Part 1..8, or 8 for Rhythm.
- const char *getPatchName(unsigned int partNumber) const;
+ MT32EMU_EXPORT const char *getPatchName(Bit8u partNumber) const;
- void readMemory(Bit32u addr, Bit32u len, Bit8u *data);
-};
+ // 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);
+}; // class Synth
-}
+} // namespace MT32Emu
-#endif
+#endif // #ifndef MT32EMU_SYNTH_H