From df4a503622a524ad8ef47e1c325ac4a711549921 Mon Sep 17 00:00:00 2001 From: Colin Snover Date: Fri, 25 Nov 2016 12:24:08 -0600 Subject: Revert "MT32: Update Munt to 2.0.0" This reverts commit b4dbd6d3c275097b4be964b7da4478ff930cbaa7. --- COPYING.BSD | 28 - NEWS | 1 - audio/softsynth/mt32.cpp | 66 +-- audio/softsynth/mt32/Analog.cpp | 44 +- audio/softsynth/mt32/Analog.h | 15 +- audio/softsynth/mt32/BReverbModel.cpp | 97 ++-- audio/softsynth/mt32/BReverbModel.h | 42 +- audio/softsynth/mt32/Enumerations.h | 155 ----- audio/softsynth/mt32/File.cpp | 73 --- audio/softsynth/mt32/File.h | 73 --- audio/softsynth/mt32/FileStream.cpp | 83 --- audio/softsynth/mt32/FileStream.h | 46 -- audio/softsynth/mt32/LA32FloatWaveGenerator.cpp | 41 +- audio/softsynth/mt32/LA32FloatWaveGenerator.h | 22 +- audio/softsynth/mt32/LA32Ramp.cpp | 10 +- audio/softsynth/mt32/LA32Ramp.h | 9 +- audio/softsynth/mt32/LA32WaveGenerator.cpp | 18 +- audio/softsynth/mt32/LA32WaveGenerator.h | 22 +- audio/softsynth/mt32/MemoryRegion.h | 18 +- audio/softsynth/mt32/MidiEventQueue.h | 10 +- audio/softsynth/mt32/MidiStreamParser.cpp | 289 ---------- audio/softsynth/mt32/MidiStreamParser.h | 124 ---- audio/softsynth/mt32/Part.cpp | 34 +- audio/softsynth/mt32/Part.h | 16 +- audio/softsynth/mt32/Partial.cpp | 23 +- audio/softsynth/mt32/Partial.h | 26 +- audio/softsynth/mt32/PartialManager.cpp | 13 +- audio/softsynth/mt32/PartialManager.h | 15 +- audio/softsynth/mt32/Poly.cpp | 12 +- audio/softsynth/mt32/Poly.h | 19 +- audio/softsynth/mt32/ROMInfo.cpp | 90 +-- audio/softsynth/mt32/ROMInfo.h | 52 +- audio/softsynth/mt32/Structures.h | 41 +- audio/softsynth/mt32/Synth.cpp | 702 +++++++---------------- audio/softsynth/mt32/Synth.h | 388 ++++++------- audio/softsynth/mt32/TVA.cpp | 28 +- audio/softsynth/mt32/TVA.h | 16 +- audio/softsynth/mt32/TVF.cpp | 16 +- audio/softsynth/mt32/TVF.h | 15 +- audio/softsynth/mt32/TVP.cpp | 32 +- audio/softsynth/mt32/TVP.h | 17 +- audio/softsynth/mt32/Tables.cpp | 17 +- audio/softsynth/mt32/Tables.h | 11 +- audio/softsynth/mt32/Types.h | 10 +- audio/softsynth/mt32/c_interface/c_interface.cpp | 624 -------------------- audio/softsynth/mt32/c_interface/c_interface.h | 362 ------------ audio/softsynth/mt32/c_interface/c_types.h | 298 ---------- audio/softsynth/mt32/c_interface/cpp_interface.h | 436 -------------- audio/softsynth/mt32/config.h | 28 - audio/softsynth/mt32/globals.h | 119 ---- audio/softsynth/mt32/internals.h | 67 +-- audio/softsynth/mt32/mmath.h | 15 +- audio/softsynth/mt32/module.mk | 6 +- audio/softsynth/mt32/mt32emu.h | 96 ++-- audio/softsynth/mt32/sha1/sha1.cpp | 185 ------ audio/softsynth/mt32/sha1/sha1.h | 49 -- 56 files changed, 836 insertions(+), 4328 deletions(-) delete mode 100644 audio/softsynth/mt32/Enumerations.h delete mode 100644 audio/softsynth/mt32/File.cpp delete mode 100644 audio/softsynth/mt32/File.h delete mode 100644 audio/softsynth/mt32/FileStream.cpp delete mode 100644 audio/softsynth/mt32/FileStream.h delete mode 100644 audio/softsynth/mt32/MidiStreamParser.cpp delete mode 100644 audio/softsynth/mt32/MidiStreamParser.h delete mode 100644 audio/softsynth/mt32/c_interface/c_interface.cpp delete mode 100644 audio/softsynth/mt32/c_interface/c_interface.h delete mode 100644 audio/softsynth/mt32/c_interface/c_types.h delete mode 100644 audio/softsynth/mt32/c_interface/cpp_interface.h delete mode 100644 audio/softsynth/mt32/config.h delete mode 100644 audio/softsynth/mt32/globals.h delete mode 100644 audio/softsynth/mt32/sha1/sha1.cpp delete mode 100644 audio/softsynth/mt32/sha1/sha1.h diff --git a/COPYING.BSD b/COPYING.BSD index a46bb675ce..e67b79359a 100644 --- a/COPYING.BSD +++ b/COPYING.BSD @@ -91,31 +91,3 @@ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - - -Parts of the MT-32 emulator use the following license: - - Copyright (c) 2011, Micael Hildenborg - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of Micael Hildenborg nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY Micael Hildenborg ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL Micael Hildenborg BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/NEWS b/NEWS index 15f455df43..f1650f0b7e 100644 --- a/NEWS +++ b/NEWS @@ -7,7 +7,6 @@ For a more comprehensive changelog of the latest experimental code, see: the current or a specified directory. - Many options in GUI could be applied without closing the dialog. - On-the-fly language switching was implemented. - - Updated Munt MT-32 emulation code to version 2.0.0. AGOS: - Fixed subtitle speed setting in the Hebrew version of Simon the Sorcerer 1. diff --git a/audio/softsynth/mt32.cpp b/audio/softsynth/mt32.cpp index 8ed1e7cf71..aaf95b65da 100644 --- a/audio/softsynth/mt32.cpp +++ b/audio/softsynth/mt32.cpp @@ -20,18 +20,6 @@ * */ -#define FORBIDDEN_SYMBOL_EXCEPTION_FILE -#define FORBIDDEN_SYMBOL_EXCEPTION_fclose -#define FORBIDDEN_SYMBOL_EXCEPTION_fopen -#define FORBIDDEN_SYMBOL_EXCEPTION_fprintf -#define FORBIDDEN_SYMBOL_EXCEPTION_fread -#define FORBIDDEN_SYMBOL_EXCEPTION_fseek -#define FORBIDDEN_SYMBOL_EXCEPTION_fwrite -#define FORBIDDEN_SYMBOL_EXCEPTION_printf -#define FORBIDDEN_SYMBOL_EXCEPTION_vfprintf -#define FORBIDDEN_SYMBOL_EXCEPTION_vprintf -#define FORBIDDEN_SYMBOL_EXCEPTION_time_h - #include "common/scummsys.h" #include "common/system.h" @@ -39,7 +27,6 @@ #include "audio/softsynth/mt32/mt32emu.h" #include "audio/softsynth/mt32/ROMInfo.h" -#include "audio/softsynth/mt32/sha1/sha1.h" #include "audio/softsynth/emumidi.h" #include "audio/musicplugin.h" @@ -67,53 +54,6 @@ namespace MT32Emu { -class ScummVMFile : public MT32Emu::File { -public: - ScummVMFile() {} - - ~ScummVMFile() { - close(); - } - - bool open(const char *fileName) { - if (!_file.open(fileName)) { - return false; - } - - _data = (Bit8u *)malloc(getSize()); - _file.read(_data, getSize()); - - Bit8u rawHash[20]; - sha1::calc(_data, getSize(), rawHash); - sha1::toHexString(rawHash, _digest); - - return true; - } - - size_t getSize() { - return _file.size(); - } - - const Bit8u *getData() { - return _data; - } - - const SHA1Digest &getSHA1() { - return _digest; - } - - virtual void close() { - delete _data; - _data = nullptr; - _file.close(); - } - -private: - byte *_data; - Common::File _file; - SHA1Digest _digest; -}; - class ReportHandlerScummVM : public ReportHandler { friend class Synth; @@ -158,7 +98,7 @@ private: MT32Emu::Synth *_synth; MT32Emu::ReportHandlerScummVM *_reportHandler; const MT32Emu::ROMImage *_controlROM, *_pcmROM; - MT32Emu::ScummVMFile *_controlFile, *_pcmFile; + Common::File *_controlFile, *_pcmFile; void deleteMuntStructures(); int _outputRate; @@ -255,10 +195,10 @@ int MidiDriver_MT32::open() { _initializing = true; debug(4, _s("Initializing MT-32 Emulator")); - _controlFile = new MT32Emu::ScummVMFile(); + _controlFile = new Common::File(); if (!_controlFile->open("CM32L_CONTROL.ROM") && !_controlFile->open("MT32_CONTROL.ROM")) error("Error opening MT32_CONTROL.ROM / CM32L_CONTROL.ROM"); - _pcmFile = new MT32Emu::ScummVMFile(); + _pcmFile = new Common::File(); if (!_pcmFile->open("CM32L_PCM.ROM") && !_pcmFile->open("MT32_PCM.ROM")) error("Error opening MT32_PCM.ROM / CM32L_PCM.ROM"); _controlROM = MT32Emu::ROMImage::makeROMImage(_controlFile); diff --git a/audio/softsynth/mt32/Analog.cpp b/audio/softsynth/mt32/Analog.cpp index a345c77656..8ac28e401a 100644 --- a/audio/softsynth/mt32/Analog.cpp +++ b/audio/softsynth/mt32/Analog.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013, 2014 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,12 +15,8 @@ * along with this program. If not, see . */ -#include - -#include "internals.h" - +//#include #include "Analog.h" -#include "Synth.h" namespace MT32Emu { @@ -110,6 +106,7 @@ static const Bit32u ACCURATE_LPF_DELTAS_OVERSAMPLED[][ACCURATE_LPF_NUMBER_OF_PHA class AbstractLowPassFilter { public: static AbstractLowPassFilter &createLowPassFilter(AnalogOutputMode mode, bool oldMT32AnalogLPF); + static void muteRingBuffer(SampleEx *ringBuffer, unsigned int length); virtual ~AbstractLowPassFilter() {} virtual SampleEx process(SampleEx sample) = 0; @@ -155,9 +152,9 @@ public: void addPositionIncrement(unsigned int positionIncrement); }; -Analog::Analog(const AnalogOutputMode mode, const bool oldMT32AnalogLPF) : - leftChannelLPF(AbstractLowPassFilter::createLowPassFilter(mode, oldMT32AnalogLPF)), - rightChannelLPF(AbstractLowPassFilter::createLowPassFilter(mode, oldMT32AnalogLPF)), +Analog::Analog(const AnalogOutputMode mode, const ControlROMFeatureSet *controlROMFeatures) : + leftChannelLPF(AbstractLowPassFilter::createLowPassFilter(mode, controlROMFeatures->isOldMT32AnalogLPF())), + rightChannelLPF(AbstractLowPassFilter::createLowPassFilter(mode, controlROMFeatures->isOldMT32AnalogLPF())), synthGain(0), reverbGain(0) {} @@ -167,7 +164,7 @@ Analog::~Analog() { delete &rightChannelLPF; } -void Analog::process(Sample *outStream, const Sample *nonReverbLeft, const Sample *nonReverbRight, const Sample *reverbDryLeft, const Sample *reverbDryRight, const Sample *reverbWetLeft, const Sample *reverbWetRight, Bit32u outLength) { +void Analog::process(Sample **outStream, const Sample *nonReverbLeft, const Sample *nonReverbRight, const Sample *reverbDryLeft, const Sample *reverbDryRight, const Sample *reverbWetLeft, const Sample *reverbWetRight, Bit32u outLength) { if (outStream == NULL) { leftChannelLPF.addPositionIncrement(outLength); rightChannelLPF.addPositionIncrement(outLength); @@ -194,8 +191,8 @@ void Analog::process(Sample *outStream, const Sample *nonReverbLeft, const Sampl outSampleR = rightChannelLPF.process(inSampleR); } - *(outStream++) = Synth::clipSampleEx(outSampleL); - *(outStream++) = Synth::clipSampleEx(outSampleR); + *((*outStream)++) = Synth::clipSampleEx(outSampleL); + *((*outStream)++) = Synth::clipSampleEx(outSampleR); } } @@ -239,6 +236,23 @@ AbstractLowPassFilter &AbstractLowPassFilter::createLowPassFilter(AnalogOutputMo } } +void AbstractLowPassFilter::muteRingBuffer(SampleEx *ringBuffer, unsigned int length) { + +#if MT32EMU_USE_FLOAT_SAMPLES + + SampleEx *p = ringBuffer; + while (length--) { + *(p++) = 0.0f; + } + +#else + + memset(ringBuffer, 0, length * sizeof(SampleEx)); + +#endif + +} + bool AbstractLowPassFilter::hasNextSample() const { return false; } @@ -259,7 +273,7 @@ CoarseLowPassFilter::CoarseLowPassFilter(bool oldMT32AnalogLPF) : LPF_TAPS(oldMT32AnalogLPF ? COARSE_LPF_TAPS_MT32 : COARSE_LPF_TAPS_CM32L), ringBufferPosition(0) { - Synth::muteSampleBuffer(ringBuffer, COARSE_LPF_DELAY_LINE_LENGTH); + muteRingBuffer(ringBuffer, COARSE_LPF_DELAY_LINE_LENGTH); } SampleEx CoarseLowPassFilter::process(const SampleEx inSample) { @@ -289,7 +303,7 @@ AccurateLowPassFilter::AccurateLowPassFilter(const bool oldMT32AnalogLPF, const ringBufferPosition(0), phase(0) { - Synth::muteSampleBuffer(ringBuffer, ACCURATE_LPF_DELAY_LINE_LENGTH); + muteRingBuffer(ringBuffer, ACCURATE_LPF_DELAY_LINE_LENGTH); } SampleEx AccurateLowPassFilter::process(const SampleEx inSample) { @@ -331,4 +345,4 @@ void AccurateLowPassFilter::addPositionIncrement(const unsigned int positionIncr phase = (phase + positionIncrement * phaseIncrement) % ACCURATE_LPF_NUMBER_OF_PHASES; } -} // namespace MT32Emu +} diff --git a/audio/softsynth/mt32/Analog.h b/audio/softsynth/mt32/Analog.h index ee642f280d..a48db72485 100644 --- a/audio/softsynth/mt32/Analog.h +++ b/audio/softsynth/mt32/Analog.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013, 2014 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,10 +18,7 @@ #ifndef MT32EMU_ANALOG_H #define MT32EMU_ANALOG_H -#include "globals.h" -#include "internals.h" -#include "Types.h" -#include "Enumerations.h" +#include "mt32emu.h" namespace MT32Emu { @@ -38,9 +35,9 @@ class AbstractLowPassFilter; */ class Analog { public: - Analog(const AnalogOutputMode mode, const bool oldMT32AnalogLPF); + Analog(AnalogOutputMode mode, const ControlROMFeatureSet *controlROMFeatures); ~Analog(); - void process(Sample *outStream, const Sample *nonReverbLeft, const Sample *nonReverbRight, const Sample *reverbDryLeft, const Sample *reverbDryRight, const Sample *reverbWetLeft, const Sample *reverbWetRight, Bit32u outLength); + void process(Sample **outStream, const Sample *nonReverbLeft, const Sample *nonReverbRight, const Sample *reverbDryLeft, const Sample *reverbDryRight, const Sample *reverbWetLeft, const Sample *reverbWetRight, const Bit32u outLength); unsigned int getOutputSampleRate() const; Bit32u getDACStreamsLength(Bit32u outputLength) const; void setSynthOutputGain(float synthGain); @@ -55,6 +52,6 @@ private: Analog(Analog &); }; -} // namespace MT32Emu +} -#endif // #ifndef MT32EMU_ANALOG_H +#endif diff --git a/audio/softsynth/mt32/BReverbModel.cpp b/audio/softsynth/mt32/BReverbModel.cpp index 891678eabc..5e02db8f99 100644 --- a/audio/softsynth/mt32/BReverbModel.cpp +++ b/audio/softsynth/mt32/BReverbModel.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013, 2014 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,12 +15,9 @@ * along with this program. If not, see . */ -#include - -#include "internals.h" - +//#include +#include "mt32emu.h" #include "BReverbModel.h" -#include "Synth.h" // Analysing of state of reverb RAM address lines gives exact sizes of the buffers of filters used. This also indicates that // the reverb model implemented in the real devices consists of three series allpass filters preceded by a non-feedback comb (or a delay with a LPF) @@ -46,14 +43,14 @@ const BReverbSettings &BReverbModel::getCM32L_LAPCSettings(const ReverbMode mode static const Bit32u MODE_0_COMBS[] = {705 + PROCESS_DELAY, 2349, 2839, 3632}; static const Bit32u MODE_0_OUTL[] = {2349, 141, 1960}; static const Bit32u MODE_0_OUTR[] = {1174, 1570, 145}; - static const Bit8u MODE_0_COMB_FACTOR[] = {0xA0, 0x60, 0x60, 0x60}; - static const Bit8u MODE_0_COMB_FEEDBACK[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + static const Bit32u MODE_0_COMB_FACTOR[] = {0xA0, 0x60, 0x60, 0x60}; + static const Bit32u MODE_0_COMB_FEEDBACK[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x48, 0x60, 0x78, 0x80, 0x88, 0x90, 0x98, 0x28, 0x48, 0x60, 0x78, 0x80, 0x88, 0x90, 0x98, 0x28, 0x48, 0x60, 0x78, 0x80, 0x88, 0x90, 0x98}; - static const Bit8u MODE_0_DRY_AMP[] = {0xA0, 0xA0, 0xA0, 0xA0, 0xB0, 0xB0, 0xB0, 0xD0}; - static const Bit8u MODE_0_WET_AMP[] = {0x10, 0x30, 0x50, 0x70, 0x90, 0xC0, 0xF0, 0xF0}; - static const Bit8u MODE_0_LPF_AMP = 0x60; + static const Bit32u MODE_0_DRY_AMP[] = {0xA0, 0xA0, 0xA0, 0xA0, 0xB0, 0xB0, 0xB0, 0xD0}; + static const Bit32u MODE_0_WET_AMP[] = {0x10, 0x30, 0x50, 0x70, 0x90, 0xC0, 0xF0, 0xF0}; + static const Bit32u MODE_0_LPF_AMP = 0x60; static const Bit32u MODE_1_NUMBER_OF_ALLPASSES = 3; static const Bit32u MODE_1_ALLPASSES[] = {1324, 809, 176}; @@ -61,14 +58,14 @@ const BReverbSettings &BReverbModel::getCM32L_LAPCSettings(const ReverbMode mode static const Bit32u MODE_1_COMBS[] = {961 + PROCESS_DELAY, 2619, 3545, 4519}; static const Bit32u MODE_1_OUTL[] = {2618, 1760, 4518}; static const Bit32u MODE_1_OUTR[] = {1300, 3532, 2274}; - static const Bit8u MODE_1_COMB_FACTOR[] = {0x80, 0x60, 0x60, 0x60}; - static const Bit8u MODE_1_COMB_FEEDBACK[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + static const Bit32u MODE_1_COMB_FACTOR[] = {0x80, 0x60, 0x60, 0x60}; + static const Bit32u MODE_1_COMB_FEEDBACK[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x48, 0x60, 0x70, 0x78, 0x80, 0x90, 0x98, 0x28, 0x48, 0x60, 0x78, 0x80, 0x88, 0x90, 0x98, 0x28, 0x48, 0x60, 0x78, 0x80, 0x88, 0x90, 0x98}; - static const Bit8u MODE_1_DRY_AMP[] = {0xA0, 0xA0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xE0}; - static const Bit8u MODE_1_WET_AMP[] = {0x10, 0x30, 0x50, 0x70, 0x90, 0xC0, 0xF0, 0xF0}; - static const Bit8u MODE_1_LPF_AMP = 0x60; + static const Bit32u MODE_1_DRY_AMP[] = {0xA0, 0xA0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xE0}; + static const Bit32u MODE_1_WET_AMP[] = {0x10, 0x30, 0x50, 0x70, 0x90, 0xC0, 0xF0, 0xF0}; + static const Bit32u MODE_1_LPF_AMP = 0x60; static const Bit32u MODE_2_NUMBER_OF_ALLPASSES = 3; static const Bit32u MODE_2_ALLPASSES[] = {969, 644, 157}; @@ -76,25 +73,25 @@ const BReverbSettings &BReverbModel::getCM32L_LAPCSettings(const ReverbMode mode static const Bit32u MODE_2_COMBS[] = {116 + PROCESS_DELAY, 2259, 2839, 3539}; static const Bit32u MODE_2_OUTL[] = {2259, 718, 1769}; static const Bit32u MODE_2_OUTR[] = {1136, 2128, 1}; - static const Bit8u MODE_2_COMB_FACTOR[] = {0, 0x20, 0x20, 0x20}; - static const Bit8u MODE_2_COMB_FEEDBACK[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + static const Bit32u MODE_2_COMB_FACTOR[] = {0, 0x20, 0x20, 0x20}; + static const Bit32u MODE_2_COMB_FEEDBACK[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x58, 0x78, 0x88, 0xA0, 0xB8, 0xC0, 0xD0, 0x30, 0x58, 0x78, 0x88, 0xA0, 0xB8, 0xC0, 0xD0, 0x30, 0x58, 0x78, 0x88, 0xA0, 0xB8, 0xC0, 0xD0}; - static const Bit8u MODE_2_DRY_AMP[] = {0xA0, 0xA0, 0xB0, 0xB0, 0xB0, 0xB0, 0xC0, 0xE0}; - static const Bit8u MODE_2_WET_AMP[] = {0x10, 0x30, 0x50, 0x70, 0x90, 0xC0, 0xF0, 0xF0}; - static const Bit8u MODE_2_LPF_AMP = 0x80; + static const Bit32u MODE_2_DRY_AMP[] = {0xA0, 0xA0, 0xB0, 0xB0, 0xB0, 0xB0, 0xC0, 0xE0}; + static const Bit32u MODE_2_WET_AMP[] = {0x10, 0x30, 0x50, 0x70, 0x90, 0xC0, 0xF0, 0xF0}; + static const Bit32u MODE_2_LPF_AMP = 0x80; static const Bit32u MODE_3_NUMBER_OF_ALLPASSES = 0; static const Bit32u MODE_3_NUMBER_OF_COMBS = 1; static const Bit32u MODE_3_DELAY[] = {16000 + MODE_3_FEEDBACK_DELAY + PROCESS_DELAY + MODE_3_ADDITIONAL_DELAY}; static const Bit32u MODE_3_OUTL[] = {400, 624, 960, 1488, 2256, 3472, 5280, 8000}; static const Bit32u MODE_3_OUTR[] = {800, 1248, 1920, 2976, 4512, 6944, 10560, 16000}; - static const Bit8u MODE_3_COMB_FACTOR[] = {0x68}; - static const Bit8u MODE_3_COMB_FEEDBACK[] = {0x68, 0x60}; - static const Bit8u MODE_3_DRY_AMP[] = {0x20, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, + static const Bit32u MODE_3_COMB_FACTOR[] = {0x68}; + static const Bit32u MODE_3_COMB_FEEDBACK[] = {0x68, 0x60}; + static const Bit32u MODE_3_DRY_AMP[] = {0x20, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x20, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50}; - static const Bit8u MODE_3_WET_AMP[] = {0x18, 0x18, 0x28, 0x40, 0x60, 0x80, 0xA8, 0xF8}; + static const Bit32u MODE_3_WET_AMP[] = {0x18, 0x18, 0x28, 0x40, 0x60, 0x80, 0xA8, 0xF8}; static const BReverbSettings REVERB_MODE_0_SETTINGS = {MODE_0_NUMBER_OF_ALLPASSES, MODE_0_ALLPASSES, MODE_0_NUMBER_OF_COMBS, MODE_0_COMBS, MODE_0_OUTL, MODE_0_OUTR, MODE_0_COMB_FACTOR, MODE_0_COMB_FEEDBACK, MODE_0_DRY_AMP, MODE_0_WET_AMP, MODE_0_LPF_AMP}; static const BReverbSettings REVERB_MODE_1_SETTINGS = {MODE_1_NUMBER_OF_ALLPASSES, MODE_1_ALLPASSES, MODE_1_NUMBER_OF_COMBS, MODE_1_COMBS, MODE_1_OUTL, MODE_1_OUTR, MODE_1_COMB_FACTOR, MODE_1_COMB_FEEDBACK, MODE_1_DRY_AMP, MODE_1_WET_AMP, MODE_1_LPF_AMP}; @@ -115,14 +112,14 @@ const BReverbSettings &BReverbModel::getMT32Settings(const ReverbMode mode) { static const Bit32u MODE_0_COMBS[] = {575 + PROCESS_DELAY, 2040, 2752, 3629}; static const Bit32u MODE_0_OUTL[] = {2040, 687, 1814}; static const Bit32u MODE_0_OUTR[] = {1019, 2072, 1}; - static const Bit8u MODE_0_COMB_FACTOR[] = {0xB0, 0x60, 0x60, 0x60}; - static const Bit8u MODE_0_COMB_FEEDBACK[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + static const Bit32u MODE_0_COMB_FACTOR[] = {0xB0, 0x60, 0x60, 0x60}; + static const Bit32u MODE_0_COMB_FEEDBACK[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x48, 0x60, 0x70, 0x78, 0x80, 0x90, 0x98, 0x28, 0x48, 0x60, 0x78, 0x80, 0x88, 0x90, 0x98, 0x28, 0x48, 0x60, 0x78, 0x80, 0x88, 0x90, 0x98}; - static const Bit8u MODE_0_DRY_AMP[] = {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}; - static const Bit8u MODE_0_WET_AMP[] = {0x10, 0x20, 0x30, 0x40, 0x50, 0x70, 0xA0, 0xE0}; - static const Bit8u MODE_0_LPF_AMP = 0x80; + static const Bit32u MODE_0_DRY_AMP[] = {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}; + static const Bit32u MODE_0_WET_AMP[] = {0x10, 0x20, 0x30, 0x40, 0x50, 0x70, 0xA0, 0xE0}; + static const Bit32u MODE_0_LPF_AMP = 0x80; static const Bit32u MODE_1_NUMBER_OF_ALLPASSES = 3; static const Bit32u MODE_1_ALLPASSES[] = {1324, 809, 176}; @@ -130,14 +127,14 @@ const BReverbSettings &BReverbModel::getMT32Settings(const ReverbMode mode) { static const Bit32u MODE_1_COMBS[] = {961 + PROCESS_DELAY, 2619, 3545, 4519}; static const Bit32u MODE_1_OUTL[] = {2618, 1760, 4518}; static const Bit32u MODE_1_OUTR[] = {1300, 3532, 2274}; - static const Bit8u MODE_1_COMB_FACTOR[] = {0x90, 0x60, 0x60, 0x60}; - static const Bit8u MODE_1_COMB_FEEDBACK[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + static const Bit32u MODE_1_COMB_FACTOR[] = {0x90, 0x60, 0x60, 0x60}; + static const Bit32u MODE_1_COMB_FEEDBACK[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x48, 0x60, 0x70, 0x78, 0x80, 0x90, 0x98, 0x28, 0x48, 0x60, 0x78, 0x80, 0x88, 0x90, 0x98, 0x28, 0x48, 0x60, 0x78, 0x80, 0x88, 0x90, 0x98}; - static const Bit8u MODE_1_DRY_AMP[] = {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}; - static const Bit8u MODE_1_WET_AMP[] = {0x10, 0x20, 0x30, 0x40, 0x50, 0x70, 0xA0, 0xE0}; - static const Bit8u MODE_1_LPF_AMP = 0x80; + static const Bit32u MODE_1_DRY_AMP[] = {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}; + static const Bit32u MODE_1_WET_AMP[] = {0x10, 0x20, 0x30, 0x40, 0x50, 0x70, 0xA0, 0xE0}; + static const Bit32u MODE_1_LPF_AMP = 0x80; static const Bit32u MODE_2_NUMBER_OF_ALLPASSES = 3; static const Bit32u MODE_2_ALLPASSES[] = {969, 644, 157}; @@ -145,25 +142,25 @@ const BReverbSettings &BReverbModel::getMT32Settings(const ReverbMode mode) { static const Bit32u MODE_2_COMBS[] = {116 + PROCESS_DELAY, 2259, 2839, 3539}; static const Bit32u MODE_2_OUTL[] = {2259, 718, 1769}; static const Bit32u MODE_2_OUTR[] = {1136, 2128, 1}; - static const Bit8u MODE_2_COMB_FACTOR[] = {0, 0x60, 0x60, 0x60}; - static const Bit8u MODE_2_COMB_FEEDBACK[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + static const Bit32u MODE_2_COMB_FACTOR[] = {0, 0x60, 0x60, 0x60}; + static const Bit32u MODE_2_COMB_FEEDBACK[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x48, 0x60, 0x70, 0x78, 0x80, 0x90, 0x98, 0x28, 0x48, 0x60, 0x78, 0x80, 0x88, 0x90, 0x98, 0x28, 0x48, 0x60, 0x78, 0x80, 0x88, 0x90, 0x98}; - static const Bit8u MODE_2_DRY_AMP[] = {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}; - static const Bit8u MODE_2_WET_AMP[] = {0x10, 0x20, 0x30, 0x40, 0x50, 0x70, 0xA0, 0xE0}; - static const Bit8u MODE_2_LPF_AMP = 0x80; + static const Bit32u MODE_2_DRY_AMP[] = {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}; + static const Bit32u MODE_2_WET_AMP[] = {0x10, 0x20, 0x30, 0x40, 0x50, 0x70, 0xA0, 0xE0}; + static const Bit32u MODE_2_LPF_AMP = 0x80; static const Bit32u MODE_3_NUMBER_OF_ALLPASSES = 0; static const Bit32u MODE_3_NUMBER_OF_COMBS = 1; static const Bit32u MODE_3_DELAY[] = {16000 + MODE_3_FEEDBACK_DELAY + PROCESS_DELAY + MODE_3_ADDITIONAL_DELAY}; static const Bit32u MODE_3_OUTL[] = {400, 624, 960, 1488, 2256, 3472, 5280, 8000}; static const Bit32u MODE_3_OUTR[] = {800, 1248, 1920, 2976, 4512, 6944, 10560, 16000}; - static const Bit8u MODE_3_COMB_FACTOR[] = {0x68}; - static const Bit8u MODE_3_COMB_FEEDBACK[] = {0x68, 0x60}; - static const Bit8u MODE_3_DRY_AMP[] = {0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + static const Bit32u MODE_3_COMB_FACTOR[] = {0x68}; + static const Bit32u MODE_3_COMB_FEEDBACK[] = {0x68, 0x60}; + static const Bit32u MODE_3_DRY_AMP[] = {0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x10, 0x20, 0x20, 0x10, 0x20, 0x10, 0x20, 0x10}; - static const Bit8u MODE_3_WET_AMP[] = {0x08, 0x18, 0x28, 0x40, 0x60, 0x80, 0xA8, 0xF8}; + static const Bit32u MODE_3_WET_AMP[] = {0x08, 0x18, 0x28, 0x40, 0x60, 0x80, 0xA8, 0xF8}; static const BReverbSettings REVERB_MODE_0_SETTINGS = {MODE_0_NUMBER_OF_ALLPASSES, MODE_0_ALLPASSES, MODE_0_NUMBER_OF_COMBS, MODE_0_COMBS, MODE_0_OUTL, MODE_0_OUTR, MODE_0_COMB_FACTOR, MODE_0_COMB_FEEDBACK, MODE_0_DRY_AMP, MODE_0_WET_AMP, MODE_0_LPF_AMP}; static const BReverbSettings REVERB_MODE_1_SETTINGS = {MODE_1_NUMBER_OF_ALLPASSES, MODE_1_ALLPASSES, MODE_1_NUMBER_OF_COMBS, MODE_1_COMBS, MODE_1_OUTL, MODE_1_OUTR, MODE_1_COMB_FACTOR, MODE_1_COMB_FEEDBACK, MODE_1_DRY_AMP, MODE_1_WET_AMP, MODE_1_LPF_AMP}; @@ -255,7 +252,7 @@ Sample AllpassFilter::process(const Sample in) { #endif } -CombFilter::CombFilter(const Bit32u useSize, const Bit8u useFilterFactor) : RingBuffer(useSize), filterFactor(useFilterFactor) {} +CombFilter::CombFilter(const Bit32u useSize, const Bit32u useFilterFactor) : RingBuffer(useSize), filterFactor(useFilterFactor) {} void CombFilter::process(const Sample in) { // This model corresponds to the comb filter implementation of the real CM-32L device @@ -274,11 +271,11 @@ Sample CombFilter::getOutputAt(const Bit32u outIndex) const { return buffer[(size + index - outIndex) % size]; } -void CombFilter::setFeedbackFactor(const Bit8u useFeedbackFactor) { +void CombFilter::setFeedbackFactor(const Bit32u useFeedbackFactor) { feedbackFactor = useFeedbackFactor; } -DelayWithLowPassFilter::DelayWithLowPassFilter(const Bit32u useSize, const Bit8u useFilterFactor, const Bit8u useAmp) +DelayWithLowPassFilter::DelayWithLowPassFilter(const Bit32u useSize, const Bit32u useFilterFactor, const Bit32u useAmp) : CombFilter(useSize, useFilterFactor), amp(useAmp) {} void DelayWithLowPassFilter::process(const Sample in) { @@ -295,7 +292,7 @@ void DelayWithLowPassFilter::process(const Sample in) { buffer[index] = weirdMul(lpfOut, amp, 0xFF); } -TapDelayCombFilter::TapDelayCombFilter(const Bit32u useSize, const Bit8u useFilterFactor) : CombFilter(useSize, useFilterFactor) {} +TapDelayCombFilter::TapDelayCombFilter(const Bit32u useSize, const Bit32u useFilterFactor) : CombFilter(useSize, useFilterFactor) {} void TapDelayCombFilter::process(const Sample in) { // the previously stored value @@ -433,7 +430,7 @@ bool BReverbModel::isMT32Compatible(const ReverbMode mode) const { return ¤tSettings == &getMT32Settings(mode); } -void BReverbModel::process(const Sample *inLeft, const Sample *inRight, Sample *outLeft, Sample *outRight, Bit32u numSamples) { +void BReverbModel::process(const Sample *inLeft, const Sample *inRight, Sample *outLeft, Sample *outRight, unsigned long numSamples) { if (combs == NULL) { Synth::muteSampleBuffer(outLeft, numSamples); Synth::muteSampleBuffer(outRight, numSamples); @@ -528,4 +525,4 @@ void BReverbModel::process(const Sample *inLeft, const Sample *inRight, Sample * } } -} // namespace MT32Emu +} diff --git a/audio/softsynth/mt32/BReverbModel.h b/audio/softsynth/mt32/BReverbModel.h index 8cfc5da8a3..764daf1a9e 100644 --- a/audio/softsynth/mt32/BReverbModel.h +++ b/audio/softsynth/mt32/BReverbModel.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013, 2014 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,10 +18,6 @@ #ifndef MT32EMU_B_REVERB_MODEL_H #define MT32EMU_B_REVERB_MODEL_H -#include "globals.h" -#include "internals.h" -#include "Types.h" - namespace MT32Emu { struct BReverbSettings { @@ -31,11 +27,11 @@ struct BReverbSettings { const Bit32u * const combSizes; const Bit32u * const outLPositions; const Bit32u * const outRPositions; - const Bit8u * const filterFactors; - const Bit8u * const feedbackFactors; - const Bit8u * const dryAmps; - const Bit8u * const wetLevels; - const Bit8u lpfAmp; + const Bit32u * const filterFactors; + const Bit32u * const feedbackFactors; + const Bit32u * const dryAmps; + const Bit32u * const wetLevels; + const Bit32u lpfAmp; }; class RingBuffer { @@ -60,23 +56,23 @@ public: class CombFilter : public RingBuffer { protected: - const Bit8u filterFactor; - Bit8u feedbackFactor; + const Bit32u filterFactor; + Bit32u feedbackFactor; public: - CombFilter(const Bit32u size, const Bit8u useFilterFactor); + CombFilter(const Bit32u size, const Bit32u useFilterFactor); virtual void process(const Sample in); Sample getOutputAt(const Bit32u outIndex) const; - void setFeedbackFactor(const Bit8u useFeedbackFactor); + void setFeedbackFactor(const Bit32u useFeedbackFactor); }; class DelayWithLowPassFilter : public CombFilter { - Bit8u amp; + Bit32u amp; public: - DelayWithLowPassFilter(const Bit32u useSize, const Bit8u useFilterFactor, const Bit8u useAmp); + DelayWithLowPassFilter(const Bit32u useSize, const Bit32u useFilterFactor, const Bit32u useAmp); void process(const Sample in); - void setFeedbackFactor(const Bit8u) {} + void setFeedbackFactor(const Bit32u) {} }; class TapDelayCombFilter : public CombFilter { @@ -84,7 +80,7 @@ class TapDelayCombFilter : public CombFilter { Bit32u outR; public: - TapDelayCombFilter(const Bit32u useSize, const Bit8u useFilterFactor); + TapDelayCombFilter(const Bit32u useSize, const Bit32u useFilterFactor); void process(const Sample in); Sample getLeftOutput() const; Sample getRightOutput() const; @@ -97,8 +93,8 @@ class BReverbModel { const BReverbSettings ¤tSettings; const bool tapDelayMode; - Bit8u dryAmp; - Bit8u wetLevel; + Bit32u dryAmp; + Bit32u wetLevel; static const BReverbSettings &getCM32L_LAPCSettings(const ReverbMode mode); static const BReverbSettings &getMT32Settings(const ReverbMode mode); @@ -112,11 +108,11 @@ public: void close(); void mute(); void setParameters(Bit8u time, Bit8u level); - void process(const Sample *inLeft, const Sample *inRight, Sample *outLeft, Sample *outRight, Bit32u numSamples); + void process(const Sample *inLeft, const Sample *inRight, Sample *outLeft, Sample *outRight, unsigned long numSamples); bool isActive() const; bool isMT32Compatible(const ReverbMode mode) const; }; -} // namespace MT32Emu +} -#endif // #ifndef MT32EMU_B_REVERB_MODEL_H +#endif diff --git a/audio/softsynth/mt32/Enumerations.h b/audio/softsynth/mt32/Enumerations.h deleted file mode 100644 index 9b0a35d0bf..0000000000 --- a/audio/softsynth/mt32/Enumerations.h +++ /dev/null @@ -1,155 +0,0 @@ -/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 2.1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ - -/* Using two guards since this file may be included twice with different MT32EMU_C_ENUMERATIONS define. */ - -#if (!defined MT32EMU_CPP_ENUMERATIONS_H && !defined MT32EMU_C_ENUMERATIONS) || (!defined MT32EMU_C_ENUMERATIONS_H && defined MT32EMU_C_ENUMERATIONS) - -#ifdef MT32EMU_C_ENUMERATIONS - -#define MT32EMU_C_ENUMERATIONS_H - -#define MT32EMU_DAC_INPUT_MODE_NAME mt32emu_dac_input_mode -#define MT32EMU_DAC_INPUT_MODE(ident) MT32EMU_DAC_##ident - -#define MT32EMU_MIDI_DELAY_MODE_NAME mt32emu_midi_delay_mode -#define MT32EMU_MIDI_DELAY_MODE(ident) MT32EMU_MDM_##ident - -#define MT32EMU_ANALOG_OUTPUT_MODE_NAME mt32emu_analog_output_mode -#define MT32EMU_ANALOG_OUTPUT_MODE(ident) MT32EMU_AOM_##ident - -#define MT32EMU_PARTIAL_STATE_NAME mt32emu_partial_state -#define MT32EMU_PARTIAL_STATE(ident) MT32EMU_PS_##ident - -#else /* #ifdef MT32EMU_C_ENUMERATIONS */ - -#define MT32EMU_CPP_ENUMERATIONS_H - -#define MT32EMU_DAC_INPUT_MODE_NAME DACInputMode -#define MT32EMU_DAC_INPUT_MODE(ident) DACInputMode_##ident - -#define MT32EMU_MIDI_DELAY_MODE_NAME MIDIDelayMode -#define MT32EMU_MIDI_DELAY_MODE(ident) MIDIDelayMode_##ident - -#define MT32EMU_ANALOG_OUTPUT_MODE_NAME AnalogOutputMode -#define MT32EMU_ANALOG_OUTPUT_MODE(ident) AnalogOutputMode_##ident - -#define MT32EMU_PARTIAL_STATE_NAME PartialState -#define MT32EMU_PARTIAL_STATE(ident) PartialState_##ident - -namespace MT32Emu { - -#endif /* #ifdef MT32EMU_C_ENUMERATIONS */ - -/** - * 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 MT32EMU_DAC_INPUT_MODE_NAME { - /** - * 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 - */ - MT32EMU_DAC_INPUT_MODE(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 :) - */ - MT32EMU_DAC_INPUT_MODE(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 - */ - MT32EMU_DAC_INPUT_MODE(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 - */ - MT32EMU_DAC_INPUT_MODE(GENERATION2) -}; - -/** Methods for emulating the effective delay of incoming MIDI messages introduced by a MIDI interface. */ -enum MT32EMU_MIDI_DELAY_MODE_NAME { - /** Process incoming MIDI events immediately. */ - MT32EMU_MIDI_DELAY_MODE(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. - */ - MT32EMU_MIDI_DELAY_MODE(DELAY_SHORT_MESSAGES_ONLY), - - /** Delay all incoming MIDI events as if they where transferred via a MIDI cable to a real hardware unit.*/ - MT32EMU_MIDI_DELAY_MODE(DELAY_ALL) -}; - -/** Methods for emulating the effects of analogue circuits of real hardware units on the output signal. */ -enum MT32EMU_ANALOG_OUTPUT_MODE_NAME { - /** Only digital path is emulated. The output samples correspond to the digital signal at the DAC entrance. */ - MT32EMU_ANALOG_OUTPUT_MODE(DIGITAL_ONLY), - /** Coarse emulation of LPF circuit. High frequencies are boosted, sample rate remains unchanged. */ - MT32EMU_ANALOG_OUTPUT_MODE(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. - */ - MT32EMU_ANALOG_OUTPUT_MODE(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. - */ - MT32EMU_ANALOG_OUTPUT_MODE(OVERSAMPLED) -}; - -enum MT32EMU_PARTIAL_STATE_NAME { - MT32EMU_PARTIAL_STATE(INACTIVE), - MT32EMU_PARTIAL_STATE(ATTACK), - MT32EMU_PARTIAL_STATE(SUSTAIN), - MT32EMU_PARTIAL_STATE(RELEASE) -}; - -#ifndef MT32EMU_C_ENUMERATIONS - -} // namespace MT32Emu - -#endif - -#undef MT32EMU_DAC_INPUT_MODE_NAME -#undef MT32EMU_DAC_INPUT_MODE - -#undef MT32EMU_MIDI_DELAY_MODE_NAME -#undef MT32EMU_MIDI_DELAY_MODE - -#undef MT32EMU_ANALOG_OUTPUT_MODE_NAME -#undef MT32EMU_ANALOG_OUTPUT_MODE - -#undef MT32EMU_PARTIAL_STATE_NAME -#undef MT32EMU_PARTIAL_STATE - -#endif /* #if (!defined MT32EMU_CPP_ENUMERATIONS_H && !defined MT32EMU_C_ENUMERATIONS) || (!defined MT32EMU_C_ENUMERATIONS_H && defined MT32EMU_C_ENUMERATIONS) */ diff --git a/audio/softsynth/mt32/File.cpp b/audio/softsynth/mt32/File.cpp deleted file mode 100644 index 643019d0c2..0000000000 --- a/audio/softsynth/mt32/File.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 2.1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ - -#include - -#include "internals.h" - -#include "File.h" -#include "sha1/sha1.h" - -namespace MT32Emu { - -AbstractFile::AbstractFile() : sha1DigestCalculated(false), reserved(NULL) { - sha1Digest[0] = 0; -} - -AbstractFile::AbstractFile(const SHA1Digest &useSHA1Digest) : sha1DigestCalculated(true), reserved(NULL) { - memcpy(sha1Digest, useSHA1Digest, sizeof(SHA1Digest) - 1); - sha1Digest[sizeof(SHA1Digest) - 1] = 0; // Ensure terminator char. -} - -const File::SHA1Digest &AbstractFile::getSHA1() { - if (sha1DigestCalculated) { - return sha1Digest; - } - sha1DigestCalculated = true; - - size_t size = getSize(); - if (size == 0) { - return sha1Digest; - } - - const Bit8u *data = getData(); - if (data == NULL) { - return sha1Digest; - } - - unsigned char fileDigest[20]; - - sha1::calc(data, (int)size, fileDigest); - sha1::toHexString(fileDigest, sha1Digest); - return sha1Digest; -} - -ArrayFile::ArrayFile(const Bit8u *useData, size_t useSize) : data(useData), size(useSize) -{} - -ArrayFile::ArrayFile(const Bit8u *useData, size_t useSize, const SHA1Digest &useSHA1Digest) : AbstractFile(useSHA1Digest), data(useData), size(useSize) -{} - -size_t ArrayFile::getSize() { - return size; -} - -const Bit8u *ArrayFile::getData() { - return data; -} - -} // namespace MT32Emu diff --git a/audio/softsynth/mt32/File.h b/audio/softsynth/mt32/File.h deleted file mode 100644 index c9a7d582b4..0000000000 --- a/audio/softsynth/mt32/File.h +++ /dev/null @@ -1,73 +0,0 @@ -/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 2.1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ - -#ifndef MT32EMU_FILE_H -#define MT32EMU_FILE_H - -#include - -#include "globals.h" -#include "Types.h" - -namespace MT32Emu { - -class MT32EMU_EXPORT File { -public: - // Includes terminator char. - typedef char SHA1Digest[41]; - - virtual ~File() {} - virtual size_t getSize() = 0; - virtual const Bit8u *getData() = 0; - virtual const SHA1Digest &getSHA1() = 0; - - virtual void close() = 0; -}; - -class MT32EMU_EXPORT AbstractFile : public File { -public: - const SHA1Digest &getSHA1(); - -protected: - AbstractFile(); - AbstractFile(const SHA1Digest &sha1Digest); - -private: - bool sha1DigestCalculated; - SHA1Digest sha1Digest; - - // Binary compatibility helper. - void *reserved; -}; - -class MT32EMU_EXPORT ArrayFile : public AbstractFile { -public: - ArrayFile(const Bit8u *data, size_t size); - ArrayFile(const Bit8u *data, size_t size, const SHA1Digest &sha1Digest); - - size_t getSize(); - const Bit8u *getData(); - void close() {} - -private: - const Bit8u *data; - size_t size; -}; - -} // namespace MT32Emu - -#endif // #ifndef MT32EMU_FILE_H diff --git a/audio/softsynth/mt32/FileStream.cpp b/audio/softsynth/mt32/FileStream.cpp deleted file mode 100644 index 0ed38dfebc..0000000000 --- a/audio/softsynth/mt32/FileStream.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 2.1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ - -#include "internals.h" - -#include "FileStream.h" - -namespace MT32Emu { - -using std::ios_base; - -FileStream::FileStream() : ifsp(*new std::ifstream), data(NULL), size(0) -{} - -FileStream::~FileStream() { - // destructor closes ifsp - delete &ifsp; - delete[] data; -} - -size_t FileStream::getSize() { - if (size != 0) { - return size; - } - if (!ifsp.is_open()) { - return 0; - } - ifsp.seekg(0, ios_base::end); - size = (size_t)ifsp.tellg(); - return size; -} - -const Bit8u *FileStream::getData() { - if (data != NULL) { - return data; - } - if (!ifsp.is_open()) { - return NULL; - } - if (getSize() == 0) { - return NULL; - } - Bit8u *fileData = new Bit8u[size]; - if (fileData == NULL) { - return NULL; - } - ifsp.seekg(0); - ifsp.read((char *)fileData, (std::streamsize)size); - if ((size_t)ifsp.tellg() != size) { - delete[] fileData; - return NULL; - } - data = fileData; - close(); - return data; -} - -bool FileStream::open(const char *filename) { - ifsp.clear(); - ifsp.open(filename, ios_base::in | ios_base::binary); - return !ifsp.fail(); -} - -void FileStream::close() { - ifsp.close(); - ifsp.clear(); -} - -} // namespace MT32Emu diff --git a/audio/softsynth/mt32/FileStream.h b/audio/softsynth/mt32/FileStream.h deleted file mode 100644 index 2de6e801ff..0000000000 --- a/audio/softsynth/mt32/FileStream.h +++ /dev/null @@ -1,46 +0,0 @@ -/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 2.1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ - -#ifndef MT32EMU_FILE_STREAM_H -#define MT32EMU_FILE_STREAM_H - -#include - -#include "globals.h" -#include "Types.h" -#include "File.h" - -namespace MT32Emu { - -class FileStream : public AbstractFile { -public: - MT32EMU_EXPORT FileStream(); - MT32EMU_EXPORT ~FileStream(); - MT32EMU_EXPORT size_t getSize(); - MT32EMU_EXPORT const Bit8u *getData(); - MT32EMU_EXPORT bool open(const char *filename); - MT32EMU_EXPORT void close(); - -private: - std::ifstream &ifsp; - const Bit8u *data; - size_t size; -}; - -} // namespace MT32Emu - -#endif // #ifndef MT32EMU_FILE_STREAM_H diff --git a/audio/softsynth/mt32/LA32FloatWaveGenerator.cpp b/audio/softsynth/mt32/LA32FloatWaveGenerator.cpp index 824204e81b..42d820ebad 100644 --- a/audio/softsynth/mt32/LA32FloatWaveGenerator.cpp +++ b/audio/softsynth/mt32/LA32FloatWaveGenerator.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013, 2014 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,11 +15,10 @@ * along with this program. If not, see . */ -#ifndef MT32EMU_LA32_WAVE_GENERATOR_CPP -#error This file should be included from LA32WaveGenerator.cpp only. -#endif - +//#include +#include "mt32emu.h" #include "mmath.h" +#include "internals.h" namespace MT32Emu { @@ -39,10 +38,10 @@ float LA32WaveGenerator::getPCMSample(unsigned int position) { return ((pcmSample & 32768) == 0) ? sampleValue : -sampleValue; } -void LA32WaveGenerator::initSynth(const bool useSawtoothWaveform, const Bit8u usePulseWidth, const Bit8u useResonance) { - sawtoothWaveform = useSawtoothWaveform; - pulseWidth = usePulseWidth; - resonance = useResonance; +void LA32WaveGenerator::initSynth(const bool sawtoothWaveform, const Bit8u pulseWidth, const Bit8u resonance) { + this->sawtoothWaveform = sawtoothWaveform; + this->pulseWidth = pulseWidth; + this->resonance = resonance; wavePos = 0.0f; lastFreq = 0.0f; @@ -51,24 +50,24 @@ void LA32WaveGenerator::initSynth(const bool useSawtoothWaveform, const Bit8u us active = true; } -void LA32WaveGenerator::initPCM(const Bit16s * const usePCMWaveAddress, const Bit32u usePCMWaveLength, const bool usePCMWaveLooped, const bool usePCMWaveInterpolated) { - pcmWaveAddress = usePCMWaveAddress; - pcmWaveLength = usePCMWaveLength; - pcmWaveLooped = usePCMWaveLooped; - pcmWaveInterpolated = usePCMWaveInterpolated; +void LA32WaveGenerator::initPCM(const Bit16s * const pcmWaveAddress, const Bit32u pcmWaveLength, const bool pcmWaveLooped, const bool pcmWaveInterpolated) { + this->pcmWaveAddress = pcmWaveAddress; + this->pcmWaveLength = pcmWaveLength; + this->pcmWaveLooped = pcmWaveLooped; + this->pcmWaveInterpolated = pcmWaveInterpolated; pcmPosition = 0.0f; active = true; } -// ampVal - Logarithmic amp of the wave generator -// pitch - Logarithmic frequency of the resulting wave -// cutoffRampVal - Composed of the base cutoff in range [78..178] left-shifted by 18 bits and the TVF modifier float LA32WaveGenerator::generateNextSample(const Bit32u ampVal, const Bit16u pitch, const Bit32u cutoffRampVal) { if (!active) { return 0.0f; } + this->amp = amp; + this->pitch = pitch; + float sample = 0.0f; // SEMI-CONFIRMED: From sample analysis: @@ -285,9 +284,9 @@ bool LA32WaveGenerator::isPCMWave() const { return pcmWaveAddress != NULL; } -void LA32PartialPair::init(const bool useRingModulated, const bool useMixed) { - ringModulated = useRingModulated; - mixed = useMixed; +void LA32PartialPair::init(const bool ringModulated, const bool mixed) { + this->ringModulated = ringModulated; + this->mixed = mixed; masterOutputSample = 0.0f; slaveOutputSample = 0.0f; } @@ -355,4 +354,4 @@ bool LA32PartialPair::isActive(const PairType useMaster) const { return useMaster == MASTER ? master.isActive() : slave.isActive(); } -} // namespace MT32Emu +} diff --git a/audio/softsynth/mt32/LA32FloatWaveGenerator.h b/audio/softsynth/mt32/LA32FloatWaveGenerator.h index 89b6fe479a..329e5de258 100644 --- a/audio/softsynth/mt32/LA32FloatWaveGenerator.h +++ b/audio/softsynth/mt32/LA32FloatWaveGenerator.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013, 2014 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 @@ -16,15 +16,14 @@ */ #ifndef MT32EMU_LA32_WAVE_GENERATOR_H -#error This file should be included from LA32WaveGenerator.h only. -#endif +#define MT32EMU_LA32_WAVE_GENERATOR_H namespace MT32Emu { /** * LA32WaveGenerator is aimed to represent the exact model of LA32 wave generator. * The output square wave is created by adding high / low linear segments in-between - * the rising and falling cosine segments. Basically, it's very similar to the phase distortion synthesis. + * the rising and falling cosine segments. Basically, it’s very similar to the phase distortion synthesis. * Behaviour of a true resonance filter is emulated by adding decaying sine wave. * The beginning and the ending of the resonant sine is multiplied by a cosine window. * To synthesise sawtooth waves, the resulting square wave is multiplied by synchronous cosine wave. @@ -39,6 +38,12 @@ class LA32WaveGenerator { // True means the resulting square wave is to be multiplied by the synchronous cosine bool sawtoothWaveform; + // Logarithmic amp of the wave generator + Bit32u amp; + + // Logarithmic frequency of the resulting wave + Bit16u pitch; + // Values in range [1..31] // Value 1 correspong to the minimum resonance Bit8u resonance; @@ -48,6 +53,9 @@ class LA32WaveGenerator { // Value 255 corresponds to the maximum possible asymmetric of the resulting wave Bit8u pulseWidth; + // Composed of the base cutoff in range [78..178] left-shifted by 18 bits and the TVF modifier + Bit32u cutoffVal; + // Logarithmic PCM sample start address const Bit16s *pcmWaveAddress; @@ -88,7 +96,7 @@ public: // Return true if the WG engine generates PCM wave samples bool isPCMWave() const; -}; // class LA32WaveGenerator +}; // LA32PartialPair contains a structure of two partials being mixed / ring modulated class LA32PartialPair { @@ -127,6 +135,8 @@ public: // Return active state of the WG engine bool isActive(const PairType master) const; -}; // class LA32PartialPair +}; } // namespace MT32Emu + +#endif // #ifndef MT32EMU_LA32_WAVE_GENERATOR_H diff --git a/audio/softsynth/mt32/LA32Ramp.cpp b/audio/softsynth/mt32/LA32Ramp.cpp index a4da4f57a8..2b31a330d2 100644 --- a/audio/softsynth/mt32/LA32Ramp.cpp +++ b/audio/softsynth/mt32/LA32Ramp.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013, 2014 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 @@ -47,12 +47,12 @@ We haven't fully explored: - Values when ramping between levels (though this is probably correct). - Transition timing (may not be 100% accurate, especially for very fast ramps). */ +//#include +#include "mt32emu.h" +#include "mmath.h" #include "internals.h" -#include "LA32Ramp.h" -#include "Tables.h" - namespace MT32Emu { // SEMI-CONFIRMED from sample analysis. @@ -152,4 +152,4 @@ void LA32Ramp::reset() { interruptRaised = false; } -} // namespace MT32Emu +} diff --git a/audio/softsynth/mt32/LA32Ramp.h b/audio/softsynth/mt32/LA32Ramp.h index 5e4ddf720e..796b4d1eec 100644 --- a/audio/softsynth/mt32/LA32Ramp.h +++ b/audio/softsynth/mt32/LA32Ramp.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013, 2014 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,6 @@ #ifndef MT32EMU_LA32RAMP_H #define MT32EMU_LA32RAMP_H -#include "globals.h" -#include "Types.h" - namespace MT32Emu { class LA32Ramp { @@ -41,6 +38,6 @@ public: void reset(); }; -} // namespace MT32Emu +} -#endif // #ifndef MT32EMU_LA32RAMP_H +#endif /* TVA_H_ */ diff --git a/audio/softsynth/mt32/LA32WaveGenerator.cpp b/audio/softsynth/mt32/LA32WaveGenerator.cpp index 6a8a5b3998..765f75fa61 100644 --- a/audio/softsynth/mt32/LA32WaveGenerator.cpp +++ b/audio/softsynth/mt32/LA32WaveGenerator.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013, 2014 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,19 +15,15 @@ * along with this program. If not, see . */ -#include - -#include "internals.h" - -#include "LA32WaveGenerator.h" -#include "Tables.h" - #if MT32EMU_USE_FLOAT_SAMPLES -#define MT32EMU_LA32_WAVE_GENERATOR_CPP #include "LA32FloatWaveGenerator.cpp" -#undef MT32EMU_LA32_WAVE_GENERATOR_CPP #else +//#include +#include "mt32emu.h" +#include "mmath.h" +#include "internals.h" + namespace MT32Emu { static const Bit32u SINE_SEGMENT_RELATIVE_LENGTH = 1 << 18; @@ -427,6 +423,6 @@ bool LA32PartialPair::isActive(const PairType useMaster) const { return useMaster == MASTER ? master.isActive() : slave.isActive(); } -} // namespace MT32Emu +} #endif // #if MT32EMU_USE_FLOAT_SAMPLES diff --git a/audio/softsynth/mt32/LA32WaveGenerator.h b/audio/softsynth/mt32/LA32WaveGenerator.h index e60c9d75a7..212abe2b19 100644 --- a/audio/softsynth/mt32/LA32WaveGenerator.h +++ b/audio/softsynth/mt32/LA32WaveGenerator.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013, 2014 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,17 +15,13 @@ * along with this program. If not, see . */ -#ifndef MT32EMU_LA32_WAVE_GENERATOR_H -#define MT32EMU_LA32_WAVE_GENERATOR_H - -#include "globals.h" -#include "internals.h" -#include "Types.h" - #if MT32EMU_USE_FLOAT_SAMPLES #include "LA32FloatWaveGenerator.h" #else +#ifndef MT32EMU_LA32_WAVE_GENERATOR_H +#define MT32EMU_LA32_WAVE_GENERATOR_H + namespace MT32Emu { /** @@ -59,7 +55,7 @@ public: /** * LA32WaveGenerator is aimed to represent the exact model of LA32 wave generator. * The output square wave is created by adding high / low linear segments in-between - * the rising and falling cosine segments. Basically, it's very similar to the phase distortion synthesis. + * the rising and falling cosine segments. Basically, it’s very similar to the phase distortion synthesis. * Behaviour of a true resonance filter is emulated by adding decaying sine wave. * The beginning and the ending of the resonant sine is multiplied by a cosine window. * To synthesise sawtooth waves, the resulting square wave is multiplied by synchronous cosine wave. @@ -204,7 +200,7 @@ public: // Return current PCM interpolation factor Bit32u getPCMInterpolationFactor() const; -}; // class LA32WaveGenerator +}; // LA32PartialPair contains a structure of two partials being mixed / ring modulated class LA32PartialPair { @@ -243,10 +239,10 @@ public: // Return active state of the WG engine bool isActive(const PairType master) const; -}; // class LA32PartialPair +}; } // namespace MT32Emu -#endif // #if MT32EMU_USE_FLOAT_SAMPLES - #endif // #ifndef MT32EMU_LA32_WAVE_GENERATOR_H + +#endif // #if MT32EMU_USE_FLOAT_SAMPLES diff --git a/audio/softsynth/mt32/MemoryRegion.h b/audio/softsynth/mt32/MemoryRegion.h index f8d7da18f8..c0cb041e11 100644 --- a/audio/softsynth/mt32/MemoryRegion.h +++ b/audio/softsynth/mt32/MemoryRegion.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013, 2014 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,20 +18,12 @@ #ifndef MT32EMU_MEMORY_REGION_H #define MT32EMU_MEMORY_REGION_H -#include - -#include "globals.h" -#include "Types.h" -#include "Structures.h" - namespace MT32Emu { enum MemoryRegionType { MR_PatchTemp, MR_RhythmTemp, MR_TimbreTemp, MR_Patches, MR_Timbres, MR_System, MR_Display, MR_Reset }; -class Synth; - class MemoryRegion { private: Synth *synth; @@ -92,7 +84,7 @@ public: } void read(unsigned int entry, unsigned int off, Bit8u *dst, unsigned int len) const; void write(unsigned int entry, unsigned int off, const Bit8u *src, unsigned int len, bool init = false) const; -}; // class MemoryRegion +}; class PatchTempMemoryRegion : public MemoryRegion { public: @@ -120,13 +112,13 @@ public: }; class DisplayMemoryRegion : public MemoryRegion { public: - DisplayMemoryRegion(Synth *useSynth) : MemoryRegion(useSynth, NULL, NULL, MR_Display, MT32EMU_MEMADDR(0x200000), SYSEX_BUFFER_SIZE - 1, 1) {} + DisplayMemoryRegion(Synth *useSynth) : MemoryRegion(useSynth, NULL, NULL, MR_Display, MT32EMU_MEMADDR(0x200000), MAX_SYSEX_SIZE - 1, 1) {} }; class ResetMemoryRegion : public MemoryRegion { public: ResetMemoryRegion(Synth *useSynth) : MemoryRegion(useSynth, NULL, NULL, MR_Reset, MT32EMU_MEMADDR(0x7F0000), 0x3FFF, 1) {} }; -} // namespace MT32Emu +} -#endif // #ifndef MT32EMU_MEMORY_REGION_H +#endif diff --git a/audio/softsynth/mt32/MidiEventQueue.h b/audio/softsynth/mt32/MidiEventQueue.h index 1a5ff0ad33..b1948c5f8e 100644 --- a/audio/softsynth/mt32/MidiEventQueue.h +++ b/audio/softsynth/mt32/MidiEventQueue.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013, 2014 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,6 @@ #ifndef MT32EMU_MIDI_EVENT_QUEUE_H #define MT32EMU_MIDI_EVENT_QUEUE_H -#include "globals.h" -#include "Types.h" - namespace MT32Emu { /** @@ -63,9 +60,8 @@ public: const MidiEvent *peekMidiEvent(); void dropMidiEvent(); bool isFull() const; - bool inline isEmpty() const; }; -} // namespace MT32Emu +} -#endif // #ifndef MT32EMU_MIDI_EVENT_QUEUE_H +#endif diff --git a/audio/softsynth/mt32/MidiStreamParser.cpp b/audio/softsynth/mt32/MidiStreamParser.cpp deleted file mode 100644 index 74fa0c3e5a..0000000000 --- a/audio/softsynth/mt32/MidiStreamParser.cpp +++ /dev/null @@ -1,289 +0,0 @@ -/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 2.1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ - -#include -#include - -#include "internals.h" - -#include "MidiStreamParser.h" -#include "Synth.h" - -using namespace MT32Emu; - -DefaultMidiStreamParser::DefaultMidiStreamParser(Synth &useSynth, Bit32u initialStreamBufferCapacity) : - MidiStreamParser(initialStreamBufferCapacity), synth(useSynth), timestampSet(false) {} - -void DefaultMidiStreamParser::setTimestamp(const Bit32u useTimestamp) { - timestampSet = true; - timestamp = useTimestamp; -} - -void DefaultMidiStreamParser::resetTimestamp() { - timestampSet = false; -} - -void DefaultMidiStreamParser::handleShortMessage(const Bit32u message) { - do { - if (timestampSet) { - if (synth.playMsg(message, timestamp)) return; - } - else { - if (synth.playMsg(message)) return; - } - } while (synth.reportHandler->onMIDIQueueOverflow()); -} - -void DefaultMidiStreamParser::handleSysex(const Bit8u *stream, const Bit32u length) { - do { - if (timestampSet) { - if (synth.playSysex(stream, length, timestamp)) return; - } - else { - if (synth.playSysex(stream, length)) return; - } - } while (synth.reportHandler->onMIDIQueueOverflow()); -} - -void DefaultMidiStreamParser::handleSystemRealtimeMessage(const Bit8u realtime) { - synth.reportHandler->onMIDISystemRealtime(realtime); -} - -void DefaultMidiStreamParser::printDebug(const char *debugMessage) { - synth.printDebug("%s", debugMessage); -} - -MidiStreamParser::MidiStreamParser(Bit32u initialStreamBufferCapacity) : - MidiStreamParserImpl(*this, *this, initialStreamBufferCapacity) {} - -MidiStreamParserImpl::MidiStreamParserImpl(MidiReceiver &useReceiver, MidiReporter &useReporter, Bit32u initialStreamBufferCapacity) : - midiReceiver(useReceiver), midiReporter(useReporter) -{ - if (initialStreamBufferCapacity < (Bit32u)SYSEX_BUFFER_SIZE) initialStreamBufferCapacity = SYSEX_BUFFER_SIZE; - if (MAX_STREAM_BUFFER_SIZE < initialStreamBufferCapacity) initialStreamBufferCapacity = MAX_STREAM_BUFFER_SIZE; - streamBufferCapacity = initialStreamBufferCapacity; - streamBuffer = new Bit8u[streamBufferCapacity]; - streamBufferSize = 0; - runningStatus = 0; - - reserved = NULL; -} - -MidiStreamParserImpl::~MidiStreamParserImpl() { - delete[] streamBuffer; -} - -void MidiStreamParserImpl::parseStream(const Bit8u *stream, Bit32u length) { - while (length > 0) { - Bit32u parsedMessageLength = 0; - if (0xF8 <= *stream) { - // Process System Realtime immediately and go on - midiReceiver.handleSystemRealtimeMessage(*stream); - parsedMessageLength = 1; - // No effect on the running status - } else if (streamBufferSize > 0) { - // Check if there is something in streamBuffer waiting for being processed - if (*streamBuffer == 0xF0) { - parsedMessageLength = parseSysexFragment(stream, length); - } else { - parsedMessageLength = parseShortMessageDataBytes(stream, length); - } - } else { - if (*stream == 0xF0) { - runningStatus = 0; // SysEx clears the running status - parsedMessageLength = parseSysex(stream, length); - } else { - parsedMessageLength = parseShortMessageStatus(stream); - } - } - - // Parsed successfully - stream += parsedMessageLength; - length -= parsedMessageLength; - } -} - -void MidiStreamParserImpl::processShortMessage(const Bit32u message) { - // Adds running status to the MIDI message if it doesn't contain one - Bit8u status = (Bit8u)message; - if (0xF8 <= status) { - midiReceiver.handleSystemRealtimeMessage(status); - } else if (processStatusByte(status)) { - midiReceiver.handleShortMessage((message << 8) | status); - } else if (0x80 <= status) { // If no running status available yet, skip this message - midiReceiver.handleShortMessage(message); - } -} - -// We deal with SysEx messages below 512 bytes long in most cases. Nevertheless, it seems reasonable to support a possibility -// to load bulk dumps using a single message. However, this is known to fail with a real device due to limited input buffer size. -bool MidiStreamParserImpl::checkStreamBufferCapacity(const bool preserveContent) { - if (streamBufferSize < streamBufferCapacity) return true; - if (streamBufferCapacity < MAX_STREAM_BUFFER_SIZE) { - Bit8u *oldStreamBuffer = streamBuffer; - streamBufferCapacity = MAX_STREAM_BUFFER_SIZE; - streamBuffer = new Bit8u[streamBufferCapacity]; - if (preserveContent) memcpy(streamBuffer, oldStreamBuffer, streamBufferSize); - delete[] oldStreamBuffer; - return true; - } - return false; -} - -// Checks input byte whether it is a status byte. If not, replaces it with running status when available. -// Returns true if the input byte was changed to running status. -bool MidiStreamParserImpl::processStatusByte(Bit8u &status) { - if (status < 0x80) { - // First byte isn't status, try running status - if (runningStatus < 0x80) { - // No running status available yet - midiReporter.printDebug("processStatusByte: No valid running status yet, MIDI message ignored"); - return false; - } - status = runningStatus; - return true; - } else if (status < 0xF0) { - // Store current status as running for a Voice message - runningStatus = status; - } else if (status < 0xF8) { - // System Common clears running status - runningStatus = 0; - } // System Realtime doesn't affect running status - return false; -} - -// Returns # of bytes parsed -Bit32u MidiStreamParserImpl::parseShortMessageStatus(const Bit8u stream[]) { - Bit8u status = *stream; - Bit32u parsedLength = processStatusByte(status) ? 0 : 1; - if (0x80 <= status) { // If no running status available yet, skip one byte - *streamBuffer = status; - ++streamBufferSize; - } - return parsedLength; -} - -// Returns # of bytes parsed -Bit32u MidiStreamParserImpl::parseShortMessageDataBytes(const Bit8u stream[], Bit32u length) { - const Bit32u shortMessageLength = Synth::getShortMessageLength(*streamBuffer); - Bit32u parsedLength = 0; - - // Append incoming bytes to streamBuffer - while ((streamBufferSize < shortMessageLength) && (length-- > 0)) { - Bit8u dataByte = *(stream++); - if (dataByte < 0x80) { - // Add data byte to streamBuffer - streamBuffer[streamBufferSize++] = dataByte; - } else if (dataByte < 0xF8) { - // Discard invalid bytes and start over - char s[128]; - sprintf(s, "parseShortMessageDataBytes: Invalid short message: status %02x, expected length %i, actual %i -> ignored", *streamBuffer, shortMessageLength, streamBufferSize); - midiReporter.printDebug(s); - streamBufferSize = 0; // Clear streamBuffer - return parsedLength; - } else { - // Bypass System Realtime message - midiReceiver.handleSystemRealtimeMessage(dataByte); - } - ++parsedLength; - } - if (streamBufferSize < shortMessageLength) return parsedLength; // Still lacks data bytes - - // Assemble short message - Bit32u shortMessage = streamBuffer[0]; - for (Bit32u i = 1; i < shortMessageLength; ++i) { - shortMessage |= streamBuffer[i] << (i << 3); - } - midiReceiver.handleShortMessage(shortMessage); - streamBufferSize = 0; // Clear streamBuffer - return parsedLength; -} - -// Returns # of bytes parsed -Bit32u MidiStreamParserImpl::parseSysex(const Bit8u stream[], const Bit32u length) { - // Find SysEx length - Bit32u sysexLength = 1; - while (sysexLength < length) { - Bit8u nextByte = stream[sysexLength++]; - if (0x80 <= nextByte) { - if (nextByte == 0xF7) { - // End of SysEx - midiReceiver.handleSysex(stream, sysexLength); - return sysexLength; - } - if (0xF8 <= nextByte) { - // The System Realtime message must be processed right after return - // but the SysEx is actually fragmented and to be reconstructed in streamBuffer - --sysexLength; - break; - } - // Illegal status byte in SysEx message, aborting - midiReporter.printDebug("parseSysex: SysEx message lacks end-of-sysex (0xf7), ignored"); - // Continue parsing from that point - return sysexLength - 1; - } - } - - // Store incomplete SysEx message for further processing - streamBufferSize = sysexLength; - if (checkStreamBufferCapacity(false)) { - memcpy(streamBuffer, stream, sysexLength); - } else { - // Not enough buffer capacity, don't care about the real buffer content, just mark the first byte - *streamBuffer = *stream; - streamBufferSize = streamBufferCapacity; - } - return sysexLength; -} - -// Returns # of bytes parsed -Bit32u MidiStreamParserImpl::parseSysexFragment(const Bit8u stream[], const Bit32u length) { - Bit32u parsedLength = 0; - while (parsedLength < length) { - Bit8u nextByte = stream[parsedLength++]; - if (nextByte < 0x80) { - // Add SysEx data byte to streamBuffer - if (checkStreamBufferCapacity(true)) streamBuffer[streamBufferSize++] = nextByte; - continue; - } - if (0xF8 <= nextByte) { - // Bypass System Realtime message - midiReceiver.handleSystemRealtimeMessage(nextByte); - continue; - } - if (nextByte != 0xF7) { - // Illegal status byte in SysEx message, aborting - midiReporter.printDebug("parseSysexFragment: SysEx message lacks end-of-sysex (0xf7), ignored"); - // Clear streamBuffer and continue parsing from that point - streamBufferSize = 0; - --parsedLength; - break; - } - // End of SysEx - if (checkStreamBufferCapacity(true)) { - streamBuffer[streamBufferSize++] = nextByte; - midiReceiver.handleSysex(streamBuffer, streamBufferSize); - streamBufferSize = 0; // Clear streamBuffer - break; - } - // Encountered streamBuffer overrun - midiReporter.printDebug("parseSysexFragment: streamBuffer overrun while receiving SysEx message, ignored. Max allowed size of fragmented SysEx is 32768 bytes."); - streamBufferSize = 0; // Clear streamBuffer - break; - } - return parsedLength; -} diff --git a/audio/softsynth/mt32/MidiStreamParser.h b/audio/softsynth/mt32/MidiStreamParser.h deleted file mode 100644 index bd31b77c89..0000000000 --- a/audio/softsynth/mt32/MidiStreamParser.h +++ /dev/null @@ -1,124 +0,0 @@ -/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 2.1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ - -#ifndef MT32EMU_MIDI_STREAM_PARSER_H -#define MT32EMU_MIDI_STREAM_PARSER_H - -#include "globals.h" -#include "Types.h" - -namespace MT32Emu { - -class Synth; - -// Interface for a user-supplied class to receive parsed well-formed MIDI messages. -class MT32EMU_EXPORT MidiReceiver { -public: - // Invoked when a complete short MIDI message is parsed in the input MIDI stream. - virtual void handleShortMessage(const Bit32u message) = 0; - - // Invoked when a complete well-formed System Exclusive MIDI message is parsed in the input MIDI stream. - virtual void handleSysex(const Bit8u stream[], const Bit32u length) = 0; - - // Invoked when a System Realtime MIDI message is parsed in the input MIDI stream. - virtual void handleSystemRealtimeMessage(const Bit8u realtime) = 0; - -protected: - ~MidiReceiver() {} -}; - -// Interface for a user-supplied class to receive notifications of input MIDI stream parse errors. -class MT32EMU_EXPORT MidiReporter { -public: - // Invoked when an error occurs during processing the input MIDI stream. - virtual void printDebug(const char *debugMessage) = 0; - -protected: - ~MidiReporter() {} -}; - -// Provides a context for parsing a stream of MIDI events coming from a single source. -// There can be multiple MIDI sources feeding MIDI events to a single Synth object. -// NOTE: Calls from multiple threads which feed a single Synth object with data must be explicitly synchronised, -// although, no synchronisation is required with the rendering thread. -class MT32EMU_EXPORT MidiStreamParserImpl { -public: - // The first two arguments provide for implementations of essential interfaces needed. - // The third argument specifies streamBuffer initial capacity. The buffer capacity should be large enough to fit the longest SysEx expected. - // If a longer SysEx occurs, streamBuffer is reallocated to the maximum size of MAX_STREAM_BUFFER_SIZE (32768 bytes). - // Default capacity is SYSEX_BUFFER_SIZE (1000 bytes) which is enough to fit SysEx messages in common use. - MidiStreamParserImpl(MidiReceiver &, MidiReporter &, Bit32u initialStreamBufferCapacity = SYSEX_BUFFER_SIZE); - virtual ~MidiStreamParserImpl(); - - // Parses a block of raw MIDI bytes. All the parsed MIDI messages are sent in sequence to the user-supplied methods for further processing. - // SysEx messages are allowed to be fragmented across several calls to this method. Running status is also handled for short messages. - // NOTE: the total length of a SysEx message being fragmented shall not exceed MAX_STREAM_BUFFER_SIZE (32768 bytes). - void parseStream(const Bit8u *stream, Bit32u length); - - // Convenience method which accepts a Bit32u-encoded short MIDI message and sends it to the user-supplied method for further processing. - // The short MIDI message may contain no status byte, the running status is used in this case. - void processShortMessage(const Bit32u message); - -private: - Bit8u runningStatus; - Bit8u *streamBuffer; - Bit32u streamBufferCapacity; - Bit32u streamBufferSize; - MidiReceiver &midiReceiver; - MidiReporter &midiReporter; - - // Binary compatibility helper. - void *reserved; - - bool checkStreamBufferCapacity(const bool preserveContent); - bool processStatusByte(Bit8u &status); - Bit32u parseShortMessageStatus(const Bit8u stream[]); - Bit32u parseShortMessageDataBytes(const Bit8u stream[], Bit32u length); - Bit32u parseSysex(const Bit8u stream[], const Bit32u length); - Bit32u parseSysexFragment(const Bit8u stream[], const Bit32u length); -}; // class MidiStreamParserImpl - -// An abstract class that provides a context for parsing a stream of MIDI events coming from a single source. -class MT32EMU_EXPORT MidiStreamParser : public MidiStreamParserImpl, protected MidiReceiver, protected MidiReporter { -public: - // The argument specifies streamBuffer initial capacity. The buffer capacity should be large enough to fit the longest SysEx expected. - // If a longer SysEx occurs, streamBuffer is reallocated to the maximum size of MAX_STREAM_BUFFER_SIZE (32768 bytes). - // Default capacity is SYSEX_BUFFER_SIZE (1000 bytes) which is enough to fit SysEx messages in common use. - explicit MidiStreamParser(Bit32u initialStreamBufferCapacity = SYSEX_BUFFER_SIZE); -}; - -class MT32EMU_EXPORT DefaultMidiStreamParser : public MidiStreamParser { -public: - explicit DefaultMidiStreamParser(Synth &synth, Bit32u initialStreamBufferCapacity = SYSEX_BUFFER_SIZE); - void setTimestamp(const Bit32u useTimestamp); - void resetTimestamp(); - -protected: - void handleShortMessage(const Bit32u message); - void handleSysex(const Bit8u *stream, const Bit32u length); - void handleSystemRealtimeMessage(const Bit8u realtime); - void printDebug(const char *debugMessage); - -private: - Synth &synth; - bool timestampSet; - Bit32u timestamp; -}; - -} // namespace MT32Emu - -#endif // MT32EMU_MIDI_STREAM_PARSER_H diff --git a/audio/softsynth/mt32/Part.cpp b/audio/softsynth/mt32/Part.cpp index cba198d651..cffc3ed744 100644 --- a/audio/softsynth/mt32/Part.cpp +++ b/audio/softsynth/mt32/Part.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013, 2014 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,16 +15,12 @@ * along with this program. If not, see . */ -#include -#include +//#include +//#include +#include "mt32emu.h" #include "internals.h" - -#include "Part.h" -#include "Partial.h" #include "PartialManager.h" -#include "Poly.h" -#include "Synth.h" namespace MT32Emu { @@ -166,7 +162,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, patchTemp->patch.timbreGroup, currentInstr); updatePitchBenderRange(); } @@ -511,7 +507,7 @@ void Part::playPoly(const PatchCache cache[4], const MemParams::RhythmTemp *rhyt #if MT32EMU_MONITOR_PARTIALS > 1 synth->printPartialUsage(); #endif - synth->reportHandler->onPolyStateChanged((Bit8u)partNum); + synth->polyStateChanged(partNum); } void Part::allNotesOff() { @@ -597,14 +593,16 @@ void Part::partialDeactivated(Poly *poly) { if (!poly->isActive()) { activePolys.remove(poly); synth->partialManager->polyFreed(poly); - synth->reportHandler->onPolyStateChanged((Bit8u)partNum); + synth->polyStateChanged(partNum); } } +//#define POLY_LIST_DEBUG + PolyList::PolyList() : firstPoly(NULL), lastPoly(NULL) {} bool PolyList::isEmpty() const { -#ifdef MT32EMU_POLY_LIST_DEBUG +#ifdef POLY_LIST_DEBUG if ((firstPoly == NULL || lastPoly == NULL) && firstPoly != lastPoly) { printf("PolyList: desynchronised firstPoly & lastPoly pointers\n"); } @@ -621,7 +619,7 @@ Poly *PolyList::getLast() const { } void PolyList::prepend(Poly *poly) { -#ifdef MT32EMU_POLY_LIST_DEBUG +#ifdef POLY_LIST_DEBUG if (poly->getNext() != NULL) { printf("PolyList: Non-NULL next field in a Poly being prepended is ignored\n"); } @@ -634,14 +632,14 @@ void PolyList::prepend(Poly *poly) { } void PolyList::append(Poly *poly) { -#ifdef MT32EMU_POLY_LIST_DEBUG +#ifdef POLY_LIST_DEBUG if (poly->getNext() != NULL) { printf("PolyList: Non-NULL next field in a Poly being appended is ignored\n"); } #endif poly->setNext(NULL); if (lastPoly != NULL) { -#ifdef MT32EMU_POLY_LIST_DEBUG +#ifdef POLY_LIST_DEBUG if (lastPoly->getNext() != NULL) { printf("PolyList: Non-NULL next field in the lastPoly\n"); } @@ -658,7 +656,7 @@ Poly *PolyList::takeFirst() { Poly *oldFirst = firstPoly; firstPoly = oldFirst->getNext(); if (firstPoly == NULL) { -#ifdef MT32EMU_POLY_LIST_DEBUG +#ifdef POLY_LIST_DEBUG if (lastPoly != oldFirst) { printf("PolyList: firstPoly != lastPoly in a list with a single Poly\n"); } @@ -677,7 +675,7 @@ void PolyList::remove(Poly * const polyToRemove) { for (Poly *poly = firstPoly; poly != NULL; poly = poly->getNext()) { if (poly->getNext() == polyToRemove) { if (polyToRemove == lastPoly) { -#ifdef MT32EMU_POLY_LIST_DEBUG +#ifdef POLY_LIST_DEBUG if (lastPoly->getNext() != NULL) { printf("PolyList: Non-NULL next field in the lastPoly\n"); } @@ -691,4 +689,4 @@ void PolyList::remove(Poly * const polyToRemove) { } } -} // namespace MT32Emu +} diff --git a/audio/softsynth/mt32/Part.h b/audio/softsynth/mt32/Part.h index f5171589d6..b458fb3988 100644 --- a/audio/softsynth/mt32/Part.h +++ b/audio/softsynth/mt32/Part.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013, 2014 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,14 +18,9 @@ #ifndef MT32EMU_PART_H #define MT32EMU_PART_H -#include "globals.h" -#include "internals.h" -#include "Types.h" -#include "Structures.h" - namespace MT32Emu { -class Poly; +class PartialManager; class Synth; class PolyList { @@ -128,7 +123,7 @@ public: // Abort the first poly in PolyState_HELD, or if none exists, the first active poly in any state. bool abortFirstPolyPreferHeld(); bool abortFirstPoly(); -}; // class Part +}; class RhythmPart: public Part { // Pointer to the area of the MT-32's memory dedicated to rhythm @@ -148,6 +143,5 @@ public: void setProgram(unsigned int patchNum); }; -} // namespace MT32Emu - -#endif // #ifndef MT32EMU_PART_H +} +#endif diff --git a/audio/softsynth/mt32/Partial.cpp b/audio/softsynth/mt32/Partial.cpp index 563079ba79..7348087509 100644 --- a/audio/softsynth/mt32/Partial.cpp +++ b/audio/softsynth/mt32/Partial.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013, 2014 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,19 +15,14 @@ * along with this program. If not, see . */ -#include +//#include +//#include +//#include +#include "mt32emu.h" +#include "mmath.h" #include "internals.h" -#include "Partial.h" -#include "Part.h" -#include "Poly.h" -#include "Synth.h" -#include "Tables.h" -#include "TVA.h" -#include "TVF.h" -#include "TVP.h" - namespace MT32Emu { static const Bit8u PAN_NUMERATOR_MASTER[] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7}; @@ -59,7 +54,7 @@ int Partial::debugGetPartialNum() const { } // Only used for debugging purposes -Bit32u Partial::debugGetSampleNum() const { +unsigned long Partial::debugGetSampleNum() const { return sampleNum; } @@ -271,7 +266,7 @@ void Partial::backupCache(const PatchCache &cache) { } } -bool Partial::produceOutput(Sample *leftBuf, Sample *rightBuf, Bit32u length) { +bool Partial::produceOutput(Sample *leftBuf, Sample *rightBuf, unsigned long length) { if (!isActive() || alreadyOutputed || isRingModulatingSlave()) { return false; } @@ -346,4 +341,4 @@ void Partial::startDecayAll() { tvf->startDecay(); } -} // namespace MT32Emu +} diff --git a/audio/softsynth/mt32/Partial.h b/audio/softsynth/mt32/Partial.h index 187665de51..749468135d 100644 --- a/audio/softsynth/mt32/Partial.h +++ b/audio/softsynth/mt32/Partial.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013, 2014 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,21 +18,11 @@ #ifndef MT32EMU_PARTIAL_H #define MT32EMU_PARTIAL_H -#include "globals.h" -#include "internals.h" -#include "Types.h" -#include "Structures.h" -#include "LA32Ramp.h" -#include "LA32WaveGenerator.h" - namespace MT32Emu { -class Part; -class Poly; class Synth; +class Part; class TVA; -class TVF; -class TVP; struct ControlROMPCMStruct; // A partial represents one of up to four waveform generators currently playing within a poly. @@ -42,7 +32,7 @@ private: const int debugPartialNum; // Only used for debugging // Number of the sample currently being rendered by produceOutput(), or 0 if no run is in progress // This is only kept available for debugging purposes. - Bit32u sampleNum; + unsigned long sampleNum; // Actually, this is a 4-bit register but we abuse this to emulate inverted mixing. // Also we double the value to enable INACCURATE_SMOOTH_PAN, with respect to MoK. @@ -87,7 +77,7 @@ public: ~Partial(); int debugGetPartialNum() const; - Bit32u debugGetSampleNum() const; + unsigned long debugGetSampleNum() const; int getOwnerPart() const; const Poly *getPoly() const; @@ -110,9 +100,9 @@ public: // Returns true only if data written to buffer // This function (unlike the one below it) returns processed stereo samples // made from combining this single partial with its pair, if it has one. - bool produceOutput(Sample *leftBuf, Sample *rightBuf, Bit32u length); -}; // class Partial + bool produceOutput(Sample *leftBuf, Sample *rightBuf, unsigned long length); +}; -} // namespace MT32Emu +} -#endif // #ifndef MT32EMU_PARTIAL_H +#endif diff --git a/audio/softsynth/mt32/PartialManager.cpp b/audio/softsynth/mt32/PartialManager.cpp index 2c5bb62605..8ca6e4e3d7 100644 --- a/audio/softsynth/mt32/PartialManager.cpp +++ b/audio/softsynth/mt32/PartialManager.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013, 2014 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,16 +15,11 @@ * along with this program. If not, see . */ -#include -#include +//#include +#include "mt32emu.h" #include "internals.h" - #include "PartialManager.h" -#include "Part.h" -#include "Partial.h" -#include "Poly.h" -#include "Synth.h" namespace MT32Emu { @@ -291,4 +286,4 @@ void PartialManager::polyFreed(Poly *poly) { freePolys[firstFreePolyIndex] = poly; } -} // namespace MT32Emu +} diff --git a/audio/softsynth/mt32/PartialManager.h b/audio/softsynth/mt32/PartialManager.h index b2908a5c21..f2e8767bbb 100644 --- a/audio/softsynth/mt32/PartialManager.h +++ b/audio/softsynth/mt32/PartialManager.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013, 2014 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,15 +18,8 @@ #ifndef MT32EMU_PARTIALMANAGER_H #define MT32EMU_PARTIALMANAGER_H -#include "globals.h" -#include "internals.h" -#include "Types.h" - namespace MT32Emu { -class Part; -class Partial; -class Poly; class Synth; class PartialManager { @@ -56,8 +49,8 @@ public: const Partial *getPartial(unsigned int partialNum) const; Poly *assignPolyToPart(Part *part); void polyFreed(Poly *poly); -}; // class PartialManager +}; -} // namespace MT32Emu +} -#endif // #ifndef MT32EMU_PARTIALMANAGER_H +#endif diff --git a/audio/softsynth/mt32/Poly.cpp b/audio/softsynth/mt32/Poly.cpp index 9a3948cf11..badcd8fb96 100644 --- a/audio/softsynth/mt32/Poly.cpp +++ b/audio/softsynth/mt32/Poly.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013, 2014 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,15 +15,9 @@ * along with this program. If not, see . */ -#include - +#include "mt32emu.h" #include "internals.h" -#include "Poly.h" -#include "Part.h" -#include "Partial.h" -#include "Synth.h" - namespace MT32Emu { Poly::Poly() { @@ -187,4 +181,4 @@ void Poly::setNext(Poly *poly) { next = poly; } -} // namespace MT32Emu +} diff --git a/audio/softsynth/mt32/Poly.h b/audio/softsynth/mt32/Poly.h index 4b283231c8..e2614369bb 100644 --- a/audio/softsynth/mt32/Poly.h +++ b/audio/softsynth/mt32/Poly.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013, 2014 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,14 +18,17 @@ #ifndef MT32EMU_POLY_H #define MT32EMU_POLY_H -#include "globals.h" -#include "internals.h" - namespace MT32Emu { class Part; class Partial; -struct PatchCache; + +enum PolyState { + POLY_Playing, + POLY_Held, // This marks keys that have been released on the keyboard, but are being held by the pedal + POLY_Releasing, + POLY_Inactive +}; class Poly { private: @@ -63,8 +66,8 @@ public: Poly *getNext() const; void setNext(Poly *poly); -}; // class Poly +}; -} // namespace MT32Emu +} -#endif // #ifndef MT32EMU_POLY_H +#endif /* POLY_H_ */ diff --git a/audio/softsynth/mt32/ROMInfo.cpp b/audio/softsynth/mt32/ROMInfo.cpp index ce78e693aa..f6817c1a4d 100644 --- a/audio/softsynth/mt32/ROMInfo.cpp +++ b/audio/softsynth/mt32/ROMInfo.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013, 2014 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,27 +15,27 @@ * along with this program. If not, see . */ -#include - -#include "internals.h" - +//#include #include "ROMInfo.h" namespace MT32Emu { -static const ROMInfo *getKnownROMInfoFromList(Bit32u index) { +static const ROMInfo *getKnownROMInfoFromList(unsigned int index) { + static const ControlROMFeatureSet MT32_COMPATIBLE(true, true); + static const ControlROMFeatureSet CM32L_COMPATIBLE(false, false); + // 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}; + static const ROMInfo CTRL_MT32_V1_04 = {65536, "5a5cb5a77d7d55ee69657c2f870416daed52dea7", ROMInfo::Control, "ctrl_mt32_1_04", "MT-32 Control v1.04", ROMInfo::Full, NULL, &MT32_COMPATIBLE}; + static const ROMInfo CTRL_MT32_V1_05 = {65536, "e17a3a6d265bf1fa150312061134293d2b58288c", ROMInfo::Control, "ctrl_mt32_1_05", "MT-32 Control v1.05", ROMInfo::Full, NULL, &MT32_COMPATIBLE}; + static const ROMInfo CTRL_MT32_V1_06 = {65536, "a553481f4e2794c10cfe597fef154eef0d8257de", ROMInfo::Control, "ctrl_mt32_1_06", "MT-32 Control v1.06", ROMInfo::Full, NULL, &MT32_COMPATIBLE}; + static const ROMInfo CTRL_MT32_V1_07 = {65536, "b083518fffb7f66b03c23b7eb4f868e62dc5a987", ROMInfo::Control, "ctrl_mt32_1_07", "MT-32 Control v1.07", ROMInfo::Full, NULL, &MT32_COMPATIBLE}; + static const ROMInfo CTRL_MT32_BLUER = {65536, "7b8c2a5ddb42fd0732e2f22b3340dcf5360edf92", ROMInfo::Control, "ctrl_mt32_bluer", "MT-32 Control BlueRidge", ROMInfo::Full, NULL, &MT32_COMPATIBLE}; - 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_CM32L_V1_00 = {65536, "73683d585cd6948cc19547942ca0e14a0319456d", ROMInfo::Control, "ctrl_cm32l_1_00", "CM-32L/LAPC-I Control v1.00", ROMInfo::Full, NULL, &CM32L_COMPATIBLE}; + 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, &CM32L_COMPATIBLE}; - 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 const ROMInfo PCM_MT32 = {524288, "f6b1eebc4b2d200ec6d3d21d51325d5b48c60252", ROMInfo::PCM, "pcm_mt32", "MT-32 PCM ROM", ROMInfo::Full, NULL, NULL}; + static const ROMInfo PCM_CM32L = {1048576, "289cc298ad532b702461bfc738009d9ebe8025ea", ROMInfo::PCM, "pcm_cm32l", "CM-32L/CM-64/LAPC-I PCM ROM", ROMInfo::Full, NULL, NULL}; static const ROMInfo * const ROM_INFOS[] = { &CTRL_MT32_V1_04, @@ -52,11 +52,23 @@ static const ROMInfo *getKnownROMInfoFromList(Bit32u index) { return ROM_INFOS[index]; } -const ROMInfo* ROMInfo::getROMInfo(File *file) { - size_t fileSize = file->getSize(); - for (Bit32u i = 0; getKnownROMInfoFromList(i) != NULL; i++) { +const ROMInfo* ROMInfo::getROMInfo(Common::File *file) { + size_t fileSize = file->size(); + Common::String fileName = file->getName(); + fileName.toUppercase(); + bool isCM32LROM = fileName.hasPrefix("CM32L_"); + // We haven't added the SHA1 checksum code in ScummVM, as the file size + // and ROM name suffices for our needs for now. + //const char *fileDigest = file->getSHA1(); + for (int i = 0; getKnownROMInfoFromList(i) != NULL; i++) { const ROMInfo *romInfo = getKnownROMInfoFromList(i); - if (fileSize == romInfo->fileSize && !strcmp(file->getSHA1(), romInfo->sha1Digest)) { + if (fileSize == romInfo->fileSize /*&& !strcmp(fileDigest, romInfo->sha1Digest)*/) { + if (fileSize == 65536) { + // If we are looking for a CM-32L ROM, make sure we return the first matching + // CM-32L ROM from the list, instead of the first matching MT-32 ROM + if (isCM32LROM && romInfo->controlROMFeatures->isDefaultReverbMT32Compatible()) + continue; + } return romInfo; } } @@ -67,17 +79,17 @@ void ROMInfo::freeROMInfo(const ROMInfo *romInfo) { (void) romInfo; } -static Bit32u getROMCount() { - Bit32u count; +static int getROMCount() { + int count; for(count = 0; getKnownROMInfoFromList(count) != NULL; count++) { } return count; } -const ROMInfo** ROMInfo::getROMInfoList(Bit32u types, Bit32u pairTypes) { +const ROMInfo** ROMInfo::getROMInfoList(unsigned int types, unsigned int pairTypes) { const ROMInfo **romInfoList = new const ROMInfo*[getROMCount() + 1]; const ROMInfo **currentROMInList = romInfoList; - for (Bit32u i = 0; getKnownROMInfoFromList(i) != NULL; i++) { + for(int i = 0; getKnownROMInfoFromList(i) != NULL; i++) { const ROMInfo *romInfo = getKnownROMInfoFromList(i); if ((types & (1 << romInfo->type)) && (pairTypes & (1 << romInfo->pairType))) { *currentROMInList++ = romInfo; @@ -91,22 +103,19 @@ void ROMInfo::freeROMInfoList(const ROMInfo **romInfoList) { delete[] romInfoList; } -ROMImage::ROMImage(File *useFile) : file(useFile), romInfo(ROMInfo::getROMInfo(file)) -{} - -ROMImage::~ROMImage() { - ROMInfo::freeROMInfo(romInfo); -} - -const ROMImage* ROMImage::makeROMImage(File *file) { - return new ROMImage(file); +const ROMImage* ROMImage::makeROMImage(Common::File *file) { + ROMImage *romImage = new ROMImage; + romImage->file = file; + romImage->romInfo = ROMInfo::getROMInfo(romImage->file); + return romImage; } void ROMImage::freeROMImage(const ROMImage *romImage) { + ROMInfo::freeROMInfo(romImage->romInfo); delete romImage; } -File* ROMImage::getFile() const { +Common::File* ROMImage::getFile() const { return file; } @@ -114,4 +123,17 @@ const ROMInfo* ROMImage::getROMInfo() const { return romInfo; } -} // namespace MT32Emu +ControlROMFeatureSet::ControlROMFeatureSet(bool useDefaultReverbMT32Compatible, bool useOldMT32AnalogLPF) : + defaultReverbMT32Compatible(useDefaultReverbMT32Compatible), + oldMT32AnalogLPF(useOldMT32AnalogLPF) +{} + +bool ControlROMFeatureSet::isDefaultReverbMT32Compatible() const { + return defaultReverbMT32Compatible; +} + +bool ControlROMFeatureSet::isOldMT32AnalogLPF() const { + return oldMT32AnalogLPF; +} + +} diff --git a/audio/softsynth/mt32/ROMInfo.h b/audio/softsynth/mt32/ROMInfo.h index 8a5ad141b6..4682620a15 100644 --- a/audio/softsynth/mt32/ROMInfo.h +++ b/audio/softsynth/mt32/ROMInfo.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013, 2014 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,63 +18,73 @@ #ifndef MT32EMU_ROMINFO_H #define MT32EMU_ROMINFO_H -#include - -#include "globals.h" -#include "File.h" +//#include +#include "common/file.h" namespace MT32Emu { +struct ControlROMFeatureSet; + // Defines vital info about ROM file to be used by synth and applications struct ROMInfo { public: size_t fileSize; - const File::SHA1Digest &sha1Digest; + const char *sha1Digest; enum Type {PCM, Control, Reverb} type; const char *shortName; const char *description; enum PairType {Full, FirstHalf, SecondHalf, Mux0, Mux1} pairType; ROMInfo *pairROMInfo; + const ControlROMFeatureSet *controlROMFeatures; // Returns a ROMInfo struct by inspecting the size and the SHA1 hash - MT32EMU_EXPORT static const ROMInfo* getROMInfo(File *file); + static const ROMInfo* getROMInfo(Common::File *file); // Currently no-op - MT32EMU_EXPORT static void freeROMInfo(const ROMInfo *romInfo); + static void freeROMInfo(const ROMInfo *romInfo); // 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); + static const ROMInfo** getROMInfoList(unsigned int types, unsigned int pairTypes); // Frees the list of ROMInfos given - MT32EMU_EXPORT static void freeROMInfoList(const ROMInfo **romInfos); + static void freeROMInfoList(const ROMInfo **romInfos); }; // Synth::open() is to require a full control ROMImage and a full PCM ROMImage to work class ROMImage { private: - File * const file; - const ROMInfo * const romInfo; - - ROMImage(File *file); - ~ROMImage(); + Common::File *file; + const ROMInfo *romInfo; 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); + static const ROMImage* makeROMImage(Common::File *file); // Must only be done after all Synths using the ROMImage are deleted - MT32EMU_EXPORT static void freeROMImage(const ROMImage *romImage); + static void freeROMImage(const ROMImage *romImage); - MT32EMU_EXPORT File *getFile() const; - MT32EMU_EXPORT const ROMInfo *getROMInfo() const; + Common::File *getFile() const; + const ROMInfo *getROMInfo() const; +}; + +struct ControlROMFeatureSet { +private: + unsigned int defaultReverbMT32Compatible : 1; + unsigned int oldMT32AnalogLPF : 1; + +public: + ControlROMFeatureSet(bool defaultReverbMT32Compatible, bool oldMT32AnalogLPF); + bool isDefaultReverbMT32Compatible() const; + bool isOldMT32AnalogLPF() const; }; -} // namespace MT32Emu +} -#endif // #ifndef MT32EMU_ROMINFO_H +#endif diff --git a/audio/softsynth/mt32/Structures.h b/audio/softsynth/mt32/Structures.h index 6dcb9c86a9..4dada3a847 100644 --- a/audio/softsynth/mt32/Structures.h +++ b/audio/softsynth/mt32/Structures.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013, 2014 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,6 @@ #ifndef MT32EMU_STRUCTURES_H #define MT32EMU_STRUCTURES_H -#include "globals.h" -#include "Types.h" - namespace MT32Emu { // MT32EMU_MEMADDR() converts from sysex-padded, MT32EMU_SYSEXMEMADDR converts to it @@ -105,8 +102,8 @@ struct TimbreParam { Bit8u envTime[5]; // 0-100 Bit8u envLevel[4]; // 0-100 // [3]: SUSTAIN LEVEL } MT32EMU_ALIGN_PACKED tva; - } MT32EMU_ALIGN_PACKED partial[4]; // struct PartialParam -} MT32EMU_ALIGN_PACKED; // struct TimbreParam + } MT32EMU_ALIGN_PACKED partial[4]; +} MT32EMU_ALIGN_PACKED; struct PatchParam { Bit8u timbreGroup; // TIMBRE GROUP 0-3 (group A, group B, Memory, Rhythm) @@ -166,16 +163,7 @@ struct MemParams { Bit8u chanAssign[9]; // MIDI CHANNEL (PART1) 0-16 (1-16,OFF) Bit8u masterVol; // MASTER VOLUME 0-100 } MT32EMU_ALIGN_PACKED system; -}; // struct MemParams - -struct SoundGroup { - Bit8u timbreNumberTableAddrLow; - Bit8u timbreNumberTableAddrHigh; - Bit8u displayPosition; - Bit8u name[9]; - Bit8u timbreCount; - Bit8u pad; -} MT32EMU_ALIGN_PACKED; +}; #if defined(_MSC_VER) || defined(__MINGW32__) #pragma pack(pop) @@ -183,17 +171,10 @@ struct SoundGroup { #pragma pack() #endif -struct ControlROMFeatureSet { - unsigned int quirkPitchEnvelopeOverflow : 1; - - // Features below don't actually depend on control ROM version, which is used to identify hardware model - unsigned int defaultReverbMT32Compatible : 1; - unsigned int oldMT32AnalogLPF : 1; -}; - struct ControlROMMap { - const char *shortName; - const ControlROMFeatureSet &featureSet; + Bit16u idPos; + Bit16u idLen; + const char *idBytes; Bit16u pcmTable; // 4 * pcmCount bytes Bit16u pcmCount; Bit16u timbreAMap; // 128 bytes @@ -213,8 +194,6 @@ struct ControlROMMap { Bit16u patchMaxTable; // 16 bytes Bit16u systemMaxTable; // 23 bytes Bit16u timbreMaxTable; // 72 bytes - Bit16u soundGroupsTable; // 14 bytes each entry - Bit16u soundGroupsCount; }; struct ControlROMPCMStruct { @@ -236,7 +215,7 @@ struct PatchCache { bool playPartial; bool PCMPartial; int pcm; - Bit8u waveform; + char waveform; Bit32u structureMix; int structurePosition; @@ -254,6 +233,6 @@ struct PatchCache { const TimbreParam::PartialParam *partialParam; }; -} // namespace MT32Emu +} -#endif // #ifndef MT32EMU_STRUCTURES_H +#endif diff --git a/audio/softsynth/mt32/Synth.cpp b/audio/softsynth/mt32/Synth.cpp index ca28898205..6df7eb9e31 100644 --- a/audio/softsynth/mt32/Synth.cpp +++ b/audio/softsynth/mt32/Synth.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013, 2014 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,138 +15,42 @@ * along with this program. If not, see . */ -#include +//#include +//#include +//#include +//#include +#include "mt32emu.h" +#include "mmath.h" #include "internals.h" -#include "Synth.h" #include "Analog.h" #include "BReverbModel.h" -#include "File.h" #include "MemoryRegion.h" #include "MidiEventQueue.h" -#include "Part.h" -#include "Partial.h" #include "PartialManager.h" -#include "Poly.h" -#include "ROMInfo.h" -#include "TVA.h" 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, true, true }; -static const ControlROMFeatureSet CM32L_COMPATIBLE = { false, false, false }; - static const ControlROMMap ControlROMMaps[7] = { - // 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_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 + // ID IDc IDbytes PCMmap PCMc tmbrA tmbrAO, tmbrAC tmbrB tmbrBO, tmbrBC tmbrR trC rhythm rhyC rsrv panpot prog rhyMax patMax sysMax timMax + {0x4014, 22, "\000 ver1.04 14 July 87 ", 0x3000, 128, 0x8000, 0x0000, false, 0xC000, 0x4000, false, 0x3200, 30, 0x73A6, 85, 0x57C7, 0x57E2, 0x57D0, 0x5252, 0x525E, 0x526E, 0x520A}, + {0x4014, 22, "\000 ver1.05 06 Aug, 87 ", 0x3000, 128, 0x8000, 0x0000, false, 0xC000, 0x4000, false, 0x3200, 30, 0x7414, 85, 0x57C7, 0x57E2, 0x57D0, 0x5252, 0x525E, 0x526E, 0x520A}, + {0x4014, 22, "\000 ver1.06 31 Aug, 87 ", 0x3000, 128, 0x8000, 0x0000, false, 0xC000, 0x4000, false, 0x3200, 30, 0x7414, 85, 0x57D9, 0x57F4, 0x57E2, 0x5264, 0x5270, 0x5280, 0x521C}, + {0x4010, 22, "\000 ver1.07 10 Oct, 87 ", 0x3000, 128, 0x8000, 0x0000, false, 0xC000, 0x4000, false, 0x3200, 30, 0x73fe, 85, 0x57B1, 0x57CC, 0x57BA, 0x523C, 0x5248, 0x5258, 0x51F4}, // MT-32 revision 1 + {0x4010, 22, "\000verX.XX 30 Sep, 88 ", 0x3000, 128, 0x8000, 0x0000, false, 0xC000, 0x4000, false, 0x3200, 30, 0x741C, 85, 0x57E5, 0x5800, 0x57EE, 0x5270, 0x527C, 0x528C, 0x5228}, // MT-32 Blue Ridge mod + {0x2205, 22, "\000CM32/LAPC1.00 890404", 0x8100, 256, 0x8000, 0x8000, false, 0x8080, 0x8000, false, 0x8500, 64, 0x8580, 85, 0x4F65, 0x4F80, 0x4F6E, 0x48A1, 0x48A5, 0x48BE, 0x48D5}, + {0x2205, 22, "\000CM32/LAPC1.02 891205", 0x8100, 256, 0x8000, 0x8000, true, 0x8080, 0x8000, true, 0x8500, 64, 0x8580, 85, 0x4F93, 0x4FAE, 0x4F9C, 0x48CB, 0x48CF, 0x48E8, 0x48FF} // CM-32L // (Note that all but CM-32L ROM actually have 86 entries for rhythmTemp) }; -static const PartialState PARTIAL_PHASE_TO_STATE[8] = { - PartialState_ATTACK, PartialState_ATTACK, PartialState_ATTACK, PartialState_ATTACK, - PartialState_SUSTAIN, PartialState_SUSTAIN, PartialState_RELEASE, PartialState_INACTIVE -}; - -static inline PartialState getPartialState(PartialManager *partialManager, unsigned int partialNum) { - const Partial *partial = partialManager->getPartial(partialNum); - return partial->isActive() ? PARTIAL_PHASE_TO_STATE[partial->getTVA()->getPhase()] : PartialState_INACTIVE; -} - -static inline Bit16s convertSample(float sample) { - return Synth::clipSampleEx(Bit32s(sample * 16384.0f)); // This multiplier takes into account the DAC bit shift -} - -static inline float convertSample(Bit16s sample) { - return float(sample) / 16384.0f; // This multiplier takes into account the DAC bit shift -} - -class SampleFormatConverter { -protected: -#if MT32EMU_USE_FLOAT_SAMPLES - Bit16s *outBuffer; -#else - float *outBuffer; -#endif - -public: - Sample *sampleBuffer; - - SampleFormatConverter(Sample *buffer) : outBuffer(NULL), sampleBuffer(buffer) {} - - inline bool isConversionNeeded() { - return outBuffer != NULL; - } - - inline void convert(Bit32u len) { - if (sampleBuffer == NULL) return; - if (outBuffer == NULL) { - sampleBuffer += len; - return; - } - Sample *inBuffer = sampleBuffer; - while (len--) { - *(outBuffer++) = convertSample(*(inBuffer++)); - } - } - - inline void addSilence(Bit32u len) { - if (outBuffer != NULL) { - Synth::muteSampleBuffer(outBuffer, len); - outBuffer += len; - } else if (sampleBuffer != NULL) { - Synth::muteSampleBuffer(sampleBuffer, len); - sampleBuffer += len; - } - } -}; - -template -class BufferedSampleFormatConverter : public SampleFormatConverter { - Sample renderingBuffer[BUFFER_SIZE_MULTIPLIER * MAX_SAMPLES_PER_RUN]; - -public: -#if MT32EMU_USE_FLOAT_SAMPLES - BufferedSampleFormatConverter(Bit16s *buffer) -#else - BufferedSampleFormatConverter(float *buffer) -#endif - : SampleFormatConverter(renderingBuffer) - { - outBuffer = buffer; - if (buffer == NULL) sampleBuffer = NULL; +static inline void advanceStreamPosition(Sample *&stream, Bit32u posDelta) { + if (stream != NULL) { + stream += posDelta; } -}; - -class Renderer { - Synth &synth; - -public: - Renderer(Synth &useSynth) : synth(useSynth) {} - - void render(SampleFormatConverter &converter, Bit32u len); - void renderStreams(SampleFormatConverter &nonReverbLeft, SampleFormatConverter &nonReverbRight, SampleFormatConverter &reverbDryLeft, SampleFormatConverter &reverbDryRight, SampleFormatConverter &reverbWetLeft, SampleFormatConverter &reverbWetRight, Bit32u len); - void produceLA32Output(Sample *buffer, Bit32u len); - void convertSamplesToOutput(Sample *buffer, Bit32u len); - void doRenderStreams(Sample *nonReverbLeft, Sample *nonReverbRight, Sample *reverbDryLeft, Sample *reverbDryRight, Sample *reverbWetLeft, Sample *reverbWetRight, Bit32u len); -}; - -Bit32u Synth::getLibraryVersionInt() { - return (MT32EMU_VERSION_MAJOR << 16) | (MT32EMU_VERSION_MINOR << 8) | (MT32EMU_VERSION_PATCH); -} - -const char *Synth::getLibraryVersionString() { - return MT32EMU_VERSION; } Bit8u Synth::calcSysexChecksum(const Bit8u *data, const Bit32u len, const Bit8u initChecksum) { @@ -157,17 +61,10 @@ Bit8u Synth::calcSysexChecksum(const Bit8u *data, const Bit32u len, const Bit8u return Bit8u(checksum & 0x7f); } -Bit32u Synth::getStereoOutputSampleRate(AnalogOutputMode analogOutputMode) { - static const unsigned int SAMPLE_RATES[] = {SAMPLE_RATE, SAMPLE_RATE, SAMPLE_RATE * 3 / 2, SAMPLE_RATE * 3}; - - return SAMPLE_RATES[analogOutputMode]; -} - -Synth::Synth(ReportHandler *useReportHandler) : mt32ram(*new MemParams), mt32default(*new MemParams), renderer(*new Renderer(*this)) { - opened = false; +Synth::Synth(ReportHandler *useReportHandler) : mt32ram(*new MemParams()), mt32default(*new MemParams()) { + isOpen = false; reverbOverridden = false; partialCount = DEFAULT_MAX_PARTIALS; - controlROMMap = NULL; controlROMFeatures = NULL; if (useReportHandler == NULL) { @@ -188,27 +85,11 @@ Synth::Synth(ReportHandler *useReportHandler) : mt32ram(*new MemParams), mt32def setOutputGain(1.0f); setReverbOutputGain(1.0f); setReversedStereoEnabled(false); - - patchTempMemoryRegion = NULL; - rhythmTempMemoryRegion = NULL; - timbreTempMemoryRegion = NULL; - patchesMemoryRegion = NULL; - timbresMemoryRegion = NULL; - systemMemoryRegion = NULL; - displayMemoryRegion = NULL; - resetMemoryRegion = NULL; - paddedTimbreMaxTable = NULL; - partialManager = NULL; - pcmWaves = NULL; - pcmROMData = NULL; - soundGroupNames = NULL; midiQueue = NULL; lastReceivedMIDIEventTimestamp = 0; memset(parts, 0, sizeof(parts)); renderedSampleCount = 0; - - reserved = NULL; } Synth::~Synth() { @@ -218,52 +99,47 @@ Synth::~Synth() { } delete &mt32ram; delete &mt32default; - delete &renderer; } void ReportHandler::showLCDMessage(const char *data) { - printf("WRITE-LCD: %s\n", data); + // We cannot use printf here. Since we already implement our own + // ReportHandler we simply disable the default implementation since it is + // never called anyway. +#if 0 + printf("WRITE-LCD: %s", data); + printf("\n"); +#endif } void ReportHandler::printDebug(const char *fmt, va_list list) { + // We cannot use (v)printf here. Since we already implement our own + // ReportHandler we simply disable the default implementation since it is + // never called anyway. +#if 0 vprintf(fmt, list); printf("\n"); +#endif } -void Synth::newTimbreSet(Bit8u partNum, Bit8u timbreGroup, Bit8u timbreNumber, const char patchName[]) { - const char *soundGroupName; - switch (timbreGroup) { - case 1: - timbreNumber += 64; - // Fall-through - case 0: - soundGroupName = soundGroupNames[soundGroupIx[timbreNumber]]; - break; - case 2: - soundGroupName = soundGroupNames[controlROMMap->soundGroupsCount - 2]; - break; - case 3: - soundGroupName = soundGroupNames[controlROMMap->soundGroupsCount - 1]; - break; - default: - soundGroupName = NULL; - break; - } - reportHandler->onProgramChanged(partNum, soundGroupName, patchName); +void Synth::polyStateChanged(int partNum) { + reportHandler->onPolyStateChanged(partNum); +} + +void Synth::newTimbreSet(int partNum, Bit8u timbreGroup, const char patchName[]) { + reportHandler->onProgramChanged(partNum, timbreGroup, patchName); } void Synth::printDebug(const char *fmt, ...) { va_list ap; va_start(ap, fmt); #if MT32EMU_DEBUG_SAMPLESTAMPS > 0 - reportHandler->printDebug("[%u]", (va_list)&renderedSampleCount); + reportHandler->printDebug("[%u] ", (char *)&renderedSampleCount); #endif reportHandler->printDebug(fmt, ap); va_end(ap); } void Synth::setReverbEnabled(bool newReverbEnabled) { - if (!opened) return; if (isReverbEnabled() == newReverbEnabled) return; if (newReverbEnabled) { bool oldReverbOverridden = reverbOverridden; @@ -291,23 +167,30 @@ bool Synth::isReverbOverridden() const { } void Synth::setReverbCompatibilityMode(bool mt32CompatibleMode) { - if (!opened || (isMT32ReverbCompatibilityMode() == mt32CompatibleMode)) return; - bool oldReverbEnabled = isReverbEnabled(); - setReverbEnabled(false); - for (int i = 0; i < 4; i++) { - delete reverbModels[i]; + if (reverbModels[REVERB_MODE_ROOM] != NULL) { + if (isMT32ReverbCompatibilityMode() == mt32CompatibleMode) return; + setReverbEnabled(false); + for (int i = 0; i < 4; i++) { + delete reverbModels[i]; + } + } + reverbModels[REVERB_MODE_ROOM] = new BReverbModel(REVERB_MODE_ROOM, mt32CompatibleMode); + reverbModels[REVERB_MODE_HALL] = new BReverbModel(REVERB_MODE_HALL, mt32CompatibleMode); + reverbModels[REVERB_MODE_PLATE] = new BReverbModel(REVERB_MODE_PLATE, mt32CompatibleMode); + reverbModels[REVERB_MODE_TAP_DELAY] = new BReverbModel(REVERB_MODE_TAP_DELAY, mt32CompatibleMode); +#if !MT32EMU_REDUCE_REVERB_MEMORY + for (int i = REVERB_MODE_ROOM; i <= REVERB_MODE_TAP_DELAY; i++) { + reverbModels[i]->open(); + } +#endif + if (isOpen) { + setReverbOutputGain(reverbOutputGain); + setReverbEnabled(true); } - initReverbModels(mt32CompatibleMode); - setReverbEnabled(oldReverbEnabled); - setReverbOutputGain(reverbOutputGain); } bool Synth::isMT32ReverbCompatibilityMode() const { - return opened && (reverbModels[REVERB_MODE_ROOM]->isMT32Compatible(REVERB_MODE_ROOM)); -} - -bool Synth::isDefaultReverbMT32Compatible() const { - return opened && controlROMFeatures->defaultReverbMT32Compatible; + return isOpen && (reverbModels[REVERB_MODE_ROOM]->isMT32Compatible(REVERB_MODE_ROOM)); } void Synth::setDACInputMode(DACInputMode mode) { @@ -356,18 +239,22 @@ void Synth::setReversedStereoEnabled(bool enabled) { reversedStereoEnabled = enabled; } -bool Synth::isReversedStereoEnabled() const { +bool Synth::isReversedStereoEnabled() { return reversedStereoEnabled; } bool Synth::loadControlROM(const ROMImage &controlROMImage) { - File *file = controlROMImage.getFile(); + Common::File *file = controlROMImage.getFile(); const ROMInfo *controlROMInfo = controlROMImage.getROMInfo(); if ((controlROMInfo == NULL) || (controlROMInfo->type != ROMInfo::Control) || (controlROMInfo->pairType != ROMInfo::Full)) { + return false; + } + controlROMFeatures = controlROMImage.getROMInfo()->controlROMFeatures; + if (controlROMFeatures == NULL) { #if MT32EMU_MONITOR_INIT - printDebug("Invalid Control ROM Info provided"); + printDebug("Invalid Control ROM Info provided without feature set"); #endif return false; } @@ -375,16 +262,13 @@ bool Synth::loadControlROM(const ROMImage &controlROMImage) { #if MT32EMU_MONITOR_INIT printDebug("Found Control ROM: %s, %s", controlROMInfo->shortName, controlROMInfo->description); #endif - const Bit8u *fileData = file->getData(); - memcpy(controlROMData, fileData, CONTROL_ROM_SIZE); + file->read(controlROMData, CONTROL_ROM_SIZE); // Control ROM successfully loaded, now check whether it's a known type controlROMMap = NULL; - controlROMFeatures = NULL; for (unsigned int i = 0; i < sizeof(ControlROMMaps) / sizeof(ControlROMMaps[0]); i++) { - if (strcmp(controlROMInfo->shortName, ControlROMMaps[i].shortName) == 0) { + if (memcmp(&controlROMData[ControlROMMaps[i].idPos], ControlROMMaps[i].idBytes, ControlROMMaps[i].idLen) == 0) { controlROMMap = &ControlROMMaps[i]; - controlROMFeatures = &controlROMMap->featureSet; return true; } } @@ -395,7 +279,7 @@ bool Synth::loadControlROM(const ROMImage &controlROMImage) { } bool Synth::loadPCMROM(const ROMImage &pcmROMImage) { - File *file = pcmROMImage.getFile(); + Common::File *file = pcmROMImage.getFile(); const ROMInfo *pcmROMInfo = pcmROMImage.getROMInfo(); if ((pcmROMInfo == NULL) || (pcmROMInfo->type != ROMInfo::PCM) @@ -405,21 +289,24 @@ bool Synth::loadPCMROM(const ROMImage &pcmROMImage) { #if MT32EMU_MONITOR_INIT printDebug("Found PCM ROM: %s, %s", pcmROMInfo->shortName, pcmROMInfo->description); #endif - size_t fileSize = file->getSize(); + size_t fileSize = file->size(); if (fileSize != (2 * pcmROMSize)) { #if MT32EMU_MONITOR_INIT printDebug("PCM ROM file has wrong size (expected %d, got %d)", 2 * pcmROMSize, fileSize); #endif return false; } - const Bit8u *fileData = file->getData(); + + byte *buffer = new byte[file->size()]; + file->read(buffer, file->size()); + const byte *fileData = buffer; for (size_t i = 0; i < pcmROMSize; i++) { Bit8u s = *(fileData++); Bit8u c = *(fileData++); int order[16] = {0, 9, 1, 2, 3, 4, 5, 6, 7, 10, 11, 12, 13, 14, 15, 8}; - Bit16s log = 0; + signed short log = 0; for (int u = 0; u < 15; u++) { int bit; if (order[u] < 8) { @@ -427,10 +314,13 @@ bool Synth::loadPCMROM(const ROMImage &pcmROMImage) { } else { bit = (c >> (7 - (order[u] - 8))) & 0x1; } - log = log | (Bit16s)(bit << (15 - u)); + log = log | (short)(bit << (15 - u)); } pcmROMData[i] = log; } + + delete[] buffer; + return true; } @@ -455,7 +345,7 @@ bool Synth::initPCMList(Bit16u mapAddress, Bit16u count) { return false; } -bool Synth::initCompressedTimbre(Bit16u timbreNum, const Bit8u *src, Bit32u srcLen) { +bool Synth::initCompressedTimbre(int timbreNum, const Bit8u *src, unsigned int srcLen) { // "Compressed" here means that muted partials aren't present in ROM (except in the case of partial 0 being muted). // Instead the data from the previous unmuted partial is used. if (srcLen < sizeof(TimbreParam::CommonParam)) { @@ -479,7 +369,7 @@ bool Synth::initCompressedTimbre(Bit16u timbreNum, const Bit8u *src, Bit32u srcL return true; } -bool Synth::initTimbres(Bit16u mapAddress, Bit16u offset, Bit16u count, Bit16u startTimbre, bool compressed) { +bool Synth::initTimbres(Bit16u mapAddress, Bit16u offset, int count, int startTimbre, bool compressed) { const Bit8u *timbreMap = &controlROMData[mapAddress]; for (Bit16u i = 0; i < count * 2; i += 2) { Bit16u address = (timbreMap[i + 1] << 8) | timbreMap[i]; @@ -501,32 +391,12 @@ bool Synth::initTimbres(Bit16u mapAddress, Bit16u offset, Bit16u count, Bit16u s return true; } -void Synth::initReverbModels(bool mt32CompatibleMode) { - reverbModels[REVERB_MODE_ROOM] = new BReverbModel(REVERB_MODE_ROOM, mt32CompatibleMode); - reverbModels[REVERB_MODE_HALL] = new BReverbModel(REVERB_MODE_HALL, mt32CompatibleMode); - reverbModels[REVERB_MODE_PLATE] = new BReverbModel(REVERB_MODE_PLATE, mt32CompatibleMode); - reverbModels[REVERB_MODE_TAP_DELAY] = new BReverbModel(REVERB_MODE_TAP_DELAY, mt32CompatibleMode); -#if !MT32EMU_REDUCE_REVERB_MEMORY - for (int i = REVERB_MODE_ROOM; i <= REVERB_MODE_TAP_DELAY; i++) { - reverbModels[i]->open(); - } -#endif -} - -void Synth::initSoundGroups(char newSoundGroupNames[][9]) { - memcpy(soundGroupIx, &controlROMData[controlROMMap->soundGroupsTable - sizeof(soundGroupIx)], sizeof(soundGroupIx)); - const SoundGroup *table = (SoundGroup *)&controlROMData[controlROMMap->soundGroupsTable]; - for (unsigned int i = 0; i < controlROMMap->soundGroupsCount; i++) { - memcpy(&newSoundGroupNames[i][0], table[i].name, sizeof(table[i].name)); - } -} - bool Synth::open(const ROMImage &controlROMImage, const ROMImage &pcmROMImage, AnalogOutputMode analogOutputMode) { return open(controlROMImage, pcmROMImage, DEFAULT_MAX_PARTIALS, analogOutputMode); } bool Synth::open(const ROMImage &controlROMImage, const ROMImage &pcmROMImage, unsigned int usePartialCount, AnalogOutputMode analogOutputMode) { - if (opened) { + if (isOpen) { return false; } partialCount = usePartialCount; @@ -541,7 +411,6 @@ bool Synth::open(const ROMImage &controlROMImage, const ROMImage &pcmROMImage, u if (!loadControlROM(controlROMImage)) { printDebug("Init Error - Missing or invalid Control ROM image"); reportHandler->onErrorControlROM(); - dispose(); return false; } @@ -559,24 +428,22 @@ bool Synth::open(const ROMImage &controlROMImage, const ROMImage &pcmROMImage, u if (!loadPCMROM(pcmROMImage)) { printDebug("Init Error - Missing PCM ROM image"); reportHandler->onErrorPCMROM(); - dispose(); return false; } #if MT32EMU_MONITOR_INIT printDebug("Initialising Reverb Models"); #endif - bool mt32CompatibleReverb = controlROMFeatures->defaultReverbMT32Compatible; + bool mt32CompatibleReverb = controlROMFeatures->isDefaultReverbMT32Compatible(); #if MT32EMU_MONITOR_INIT printDebug("Using %s Compatible Reverb Models", mt32CompatibleReverb ? "MT-32" : "CM-32L"); #endif - initReverbModels(mt32CompatibleReverb); + setReverbCompatibilityMode(mt32CompatibleReverb); #if MT32EMU_MONITOR_INIT printDebug("Initialising Timbre Bank A"); #endif if (!initTimbres(controlROMMap->timbreAMap, controlROMMap->timbreAOffset, 0x40, 0, controlROMMap->timbreACompressed)) { - dispose(); return false; } @@ -584,7 +451,6 @@ bool Synth::open(const ROMImage &controlROMImage, const ROMImage &pcmROMImage, u printDebug("Initialising Timbre Bank B"); #endif if (!initTimbres(controlROMMap->timbreBMap, controlROMMap->timbreBOffset, 0x40, 64, controlROMMap->timbreBCompressed)) { - dispose(); return false; } @@ -592,7 +458,6 @@ bool Synth::open(const ROMImage &controlROMImage, const ROMImage &pcmROMImage, u printDebug("Initialising Timbre Bank R"); #endif if (!initTimbres(controlROMMap->timbreRMap, 0, controlROMMap->timbreRCount, 192, true)) { - dispose(); return false; } @@ -654,10 +519,6 @@ bool Synth::open(const ROMImage &controlROMImage, const ROMImage &pcmROMImage, u refreshSystem(); reverbOverridden = oldReverbOverridden; - char(*writableSoundGroupNames)[9] = new char[controlROMMap->soundGroupsCount][9]; - soundGroupNames = writableSoundGroupNames; - initSoundGroups(writableSoundGroupNames); - for (int i = 0; i < 9; i++) { MemParams::PatchTemp *patchTemp = &mt32ram.patchTemp[i]; @@ -689,12 +550,12 @@ bool Synth::open(const ROMImage &controlROMImage, const ROMImage &pcmROMImage, u midiQueue = new MidiEventQueue(); - analog = new Analog(analogOutputMode, controlROMFeatures->oldMT32AnalogLPF); + analog = new Analog(analogOutputMode, controlROMFeatures); setOutputGain(outputGain); setReverbOutputGain(reverbOutputGain); - opened = true; - activated = false; + isOpen = true; + isEnabled = false; #if MT32EMU_MONITOR_INIT printDebug("*** Initialisation complete ***"); @@ -702,8 +563,10 @@ bool Synth::open(const ROMImage &controlROMImage, const ROMImage &pcmROMImage, u return true; } -void Synth::dispose() { - opened = false; +void Synth::close(bool forced) { + if (!forced && !isOpen) { + return; + } delete midiQueue; midiQueue = NULL; @@ -719,14 +582,8 @@ void Synth::dispose() { parts[i] = NULL; } - delete[] soundGroupNames; - soundGroupNames = NULL; - delete[] pcmWaves; - pcmWaves = NULL; - delete[] pcmROMData; - pcmROMData = NULL; deleteMemoryRegions(); @@ -736,17 +593,7 @@ void Synth::dispose() { } reverbModel = NULL; controlROMFeatures = NULL; - controlROMMap = NULL; -} - -void Synth::close() { - if (opened) { - dispose(); - } -} - -bool Synth::isOpen() const { - return opened; + isOpen = false; } void Synth::flushMIDIQueue() { @@ -817,19 +664,12 @@ bool Synth::playMsg(Bit32u msg) { } bool Synth::playMsg(Bit32u msg, Bit32u timestamp) { - if ((msg & 0xF8) == 0xF8) { - reportHandler->onMIDISystemRealtime((Bit8u)msg); - return true; - } if (midiQueue == NULL) return false; if (midiDelayMode != MIDIDelayMode_IMMEDIATE) { timestamp = addMIDIInterfaceDelay(getShortMessageLength(msg), timestamp); } - if (!activated) activated = true; - do { - if (midiQueue->pushShortMessage(msg, timestamp)) return true; - } while (reportHandler->onMIDIQueueOverflow()); - return false; + if (!isEnabled) isEnabled = true; + return midiQueue->pushShortMessage(msg, timestamp); } bool Synth::playSysex(const Bit8u *sysex, Bit32u len) { @@ -841,28 +681,24 @@ bool Synth::playSysex(const Bit8u *sysex, Bit32u len, Bit32u timestamp) { if (midiDelayMode == MIDIDelayMode_DELAY_ALL) { timestamp = addMIDIInterfaceDelay(len, timestamp); } - if (!activated) activated = true; - do { - if (midiQueue->pushSysex(sysex, len, timestamp)) return true; - } while (reportHandler->onMIDIQueueOverflow()); - return false; + if (!isEnabled) isEnabled = true; + return midiQueue->pushSysex(sysex, len, timestamp); } void Synth::playMsgNow(Bit32u msg) { - if (!opened) return; - // NOTE: Active sense IS implemented in real hardware. However, realtime processing is clearly out of the library scope. // It is assumed that realtime consumers of the library respond to these MIDI events as appropriate. - Bit8u code = (Bit8u)((msg & 0x0000F0) >> 4); - Bit8u chan = (Bit8u)(msg & 0x00000F); - Bit8u note = (Bit8u)((msg & 0x007F00) >> 8); - Bit8u velocity = (Bit8u)((msg & 0x7F0000) >> 16); + unsigned char code = (unsigned char)((msg & 0x0000F0) >> 4); + unsigned char chan = (unsigned char)(msg & 0x00000F); + unsigned char note = (unsigned char)((msg & 0x007F00) >> 8); + unsigned char velocity = (unsigned char)((msg & 0x7F0000) >> 16); + if (!isEnabled) isEnabled = true; //printDebug("Playing chan %d, code 0x%01x note: 0x%02x", chan, code, note); - Bit8u part = chantable[chan]; - if (part > 8) { + char part = chantable[chan]; + if (part < 0 || part > 8) { #if MT32EMU_MONITOR_MIDI > 0 printDebug("Play msg on unreg chan %d (%d): code=0x%01x, vel=%d", chan, part, code, velocity); #endif @@ -871,12 +707,9 @@ void Synth::playMsgNow(Bit32u msg) { playMsgOnPart(part, code, note, velocity); } -void Synth::playMsgOnPart(Bit8u part, Bit8u code, Bit8u note, Bit8u velocity) { - if (!opened) return; - +void Synth::playMsgOnPart(unsigned char part, unsigned char code, unsigned char note, unsigned char velocity) { Bit32u bend; - if (!activated) activated = true; //printDebug("Synth::playMsgOnPart(%02x, %02x, %02x, %02x)", part, code, note, velocity); switch (code) { case 0x8: @@ -1016,7 +849,7 @@ void Synth::playSysexWithoutFraming(const Bit8u *sysex, Bit32u len) { playSysexWithoutHeader(sysex[1], sysex[3], sysex + 4, len - 4); } -void Synth::playSysexWithoutHeader(Bit8u device, Bit8u command, const Bit8u *sysex, Bit32u len) { +void Synth::playSysexWithoutHeader(unsigned char device, unsigned char command, const Bit8u *sysex, Bit32u len) { if (device > 0x10) { // We have device ID 0x10 (default, but changeable, on real MT-32), < 0x10 is for channels printDebug("playSysexWithoutHeader: Message is not intended for this device ID (provided: %02x, expected: 0x10 or channel)", (int)device); @@ -1028,13 +861,6 @@ void Synth::playSysexWithoutHeader(Bit8u device, Bit8u command, const Bit8u *sys reset(); return; } - - if (command == SYSEX_CMD_EOD) { -#if MT32EMU_MONITOR_SYSEX > 0 - printDebug("playSysexWithoutHeader: Ignored unsupported command %02x", command); -#endif - return; - } if (len < 4) { printDebug("playSysexWithoutHeader: Message is too short (%d bytes)!", len); return; @@ -1046,19 +872,12 @@ void Synth::playSysexWithoutHeader(Bit8u device, Bit8u command, const Bit8u *sys } len -= 1; // Exclude checksum switch (command) { - case SYSEX_CMD_WSD: -#if MT32EMU_MONITOR_SYSEX > 0 - printDebug("playSysexWithoutHeader: Ignored unsupported command %02x", command); -#endif - break; case SYSEX_CMD_DAT: - /* Outcommented until we (ever) actually implement handshake communication if (hasActivePartials()) { printDebug("playSysexWithoutHeader: Got SYSEX_CMD_DAT but partials are active - ignoring"); // FIXME: We should send SYSEX_CMD_RJC in this case break; } - */ // Deliberate fall-through case SYSEX_CMD_DT1: writeSysex(device, sysex, len); @@ -1079,12 +898,11 @@ void Synth::playSysexWithoutHeader(Bit8u device, Bit8u command, const Bit8u *sys } } -void Synth::readSysex(Bit8u /*device*/, const Bit8u * /*sysex*/, Bit32u /*len*/) const { +void Synth::readSysex(unsigned char /*device*/, const Bit8u * /*sysex*/, Bit32u /*len*/) const { // NYI } -void Synth::writeSysex(Bit8u device, const Bit8u *sysex, Bit32u len) { - if (!opened) return; +void Synth::writeSysex(unsigned char device, const Bit8u *sysex, Bit32u len) { reportHandler->onMIDIMessagePlayed(); Bit32u addr = (sysex[0] << 16) | (sysex[1] << 8) | (sysex[2]); addr = MT32EMU_MEMADDR(addr); @@ -1100,7 +918,7 @@ void Synth::writeSysex(Bit8u device, const Bit8u *sysex, Bit32u len) { #endif if (/*addr >= MT32EMU_MEMADDR(0x000000) && */addr < MT32EMU_MEMADDR(0x010000)) { int offset; - if (chantable[device] > 8) { + if (chantable[device] == -1) { #if MT32EMU_MONITOR_SYSEX > 0 printDebug(" (Channel not mapped to a part... 0 offset)"); #endif @@ -1121,7 +939,7 @@ void Synth::writeSysex(Bit8u device, const Bit8u *sysex, Bit32u len) { addr += MT32EMU_MEMADDR(0x030110) - MT32EMU_MEMADDR(0x010000); } else if (/*addr >= MT32EMU_MEMADDR(0x020000) && */ addr < MT32EMU_MEMADDR(0x030000)) { int offset; - if (chantable[device] > 8) { + if (chantable[device] == -1) { #if MT32EMU_MONITOR_SYSEX > 0 printDebug(" (Channel not mapped to a part... 0 offset)"); #endif @@ -1168,7 +986,6 @@ void Synth::writeSysex(Bit8u device, const Bit8u *sysex, Bit32u len) { } void Synth::readMemory(Bit32u addr, Bit32u len, Bit8u *data) { - if (!opened) return; const MemoryRegion *region = findMemoryRegion(addr); if (region != NULL) { readMemoryRegion(region, addr, len, data); @@ -1462,16 +1279,16 @@ void Synth::writeMemoryRegion(const MemoryRegion *region, Bit32u addr, Bit32u le if(firstPart < 0) firstPart = 0; int lastPart = off + len - SYSTEM_CHAN_ASSIGN_START_OFF; - if(lastPart > 8) - lastPart = 8; - refreshSystemChanAssign((Bit8u)firstPart, (Bit8u)lastPart); + if(lastPart > 9) + lastPart = 9; + refreshSystemChanAssign(firstPart, lastPart); } if (off <= SYSTEM_MASTER_VOL_OFF && off + len > SYSTEM_MASTER_VOL_OFF) { refreshSystemMasterVol(); } break; case MR_Display: - char buf[SYSEX_BUFFER_SIZE]; + char buf[MAX_SYSEX_SIZE]; memcpy(&buf, &data[0], len); buf[len] = 0; #if MT32EMU_MONITOR_SYSEX > 0 @@ -1544,19 +1361,19 @@ void Synth::refreshSystemReserveSettings() { partialManager->setReserve(rset); } -void Synth::refreshSystemChanAssign(Bit8u firstPart, Bit8u lastPart) { - memset(chantable, 0xFF, sizeof(chantable)); +void Synth::refreshSystemChanAssign(unsigned int firstPart, unsigned int lastPart) { + memset(chantable, -1, sizeof(chantable)); // CONFIRMED: In the case of assigning a channel to multiple parts, the lower part wins. - for (Bit32u i = 0; i <= 8; i++) { + for (unsigned int i = 0; i <= 8; i++) { if (parts[i] != NULL && i >= firstPart && i <= lastPart) { // CONFIRMED: Decay is started for all polys, and all controllers are reset, for every part whose assignment was touched by the sysex write. parts[i]->allSoundOff(); parts[i]->resetAllControllers(); } - Bit8u chan = mt32ram.system.chanAssign[i]; - if (chan < 16 && chantable[chan] > 8) { - chantable[chan] = (Bit8u)i; + int chan = mt32ram.system.chanAssign[i]; + if (chan != 16 && chantable[chan] == -1) { + chantable[chan] = i; } } @@ -1581,7 +1398,6 @@ void Synth::refreshSystem() { } void Synth::reset() { - if (!opened) return; #if MT32EMU_MONITOR_SYSEX > 0 printDebug("RESET"); #endif @@ -1597,7 +1413,7 @@ void Synth::reset() { } } refreshSystem(); - isActive(); + isEnabled = false; } MidiEvent::~MidiEvent() { @@ -1661,7 +1477,7 @@ bool MidiEventQueue::pushSysex(const Bit8u *sysexData, Bit32u sysexLength, Bit32 } const MidiEvent *MidiEventQueue::peekMidiEvent() { - return isEmpty() ? NULL : &ringBuffer[startPosition]; + return (startPosition == endPosition) ? NULL : &ringBuffer[startPosition]; } void MidiEventQueue::dropMidiEvent() { @@ -1675,24 +1491,15 @@ bool MidiEventQueue::isFull() const { return startPosition == ((endPosition + 1) & ringBufferMask); } -bool MidiEventQueue::isEmpty() const { - return startPosition == endPosition; -} - -Bit32u Synth::getStereoOutputSampleRate() const { +unsigned int Synth::getStereoOutputSampleRate() const { return (analog == NULL) ? SAMPLE_RATE : analog->getOutputSampleRate(); } -void Renderer::render(SampleFormatConverter &converter, Bit32u len) { - if (!synth.opened) { - converter.addSilence(len << 1); - return; - } - - if (!synth.activated) { - synth.renderedSampleCount += synth.analog->getDACStreamsLength(len); - synth.analog->process(NULL, NULL, NULL, NULL, NULL, NULL, NULL, len); - converter.addSilence(len << 1); +void Synth::render(Sample *stream, Bit32u len) { + if (!isEnabled) { + renderedSampleCount += analog->getDACStreamsLength(len); + analog->process(NULL, NULL, NULL, NULL, NULL, NULL, NULL, len); + muteSampleBuffer(stream, len << 1); return; } @@ -1703,53 +1510,19 @@ void Renderer::render(SampleFormatConverter &converter, Bit32u len) { while (len > 0) { Bit32u thisPassLen = len > MAX_SAMPLES_PER_RUN ? MAX_SAMPLES_PER_RUN : len; - synth.renderStreams(tmpNonReverbLeft, tmpNonReverbRight, tmpReverbDryLeft, tmpReverbDryRight, tmpReverbWetLeft, tmpReverbWetRight, synth.analog->getDACStreamsLength(thisPassLen)); - synth.analog->process(converter.sampleBuffer, tmpNonReverbLeft, tmpNonReverbRight, tmpReverbDryLeft, tmpReverbDryRight, tmpReverbWetLeft, tmpReverbWetRight, thisPassLen); - converter.convert(thisPassLen << 1); + renderStreams(tmpNonReverbLeft, tmpNonReverbRight, tmpReverbDryLeft, tmpReverbDryRight, tmpReverbWetLeft, tmpReverbWetRight, analog->getDACStreamsLength(thisPassLen)); + analog->process(&stream, tmpNonReverbLeft, tmpNonReverbRight, tmpReverbDryLeft, tmpReverbDryRight, tmpReverbWetLeft, tmpReverbWetRight, thisPassLen); len -= thisPassLen; } } -void Synth::render(Bit16s *stream, Bit32u len) { -#if MT32EMU_USE_FLOAT_SAMPLES - BufferedSampleFormatConverter<2> converter(stream); -#else - SampleFormatConverter converter(stream); -#endif - renderer.render(converter, len); -} - -void Synth::render(float *stream, Bit32u len) { -#if MT32EMU_USE_FLOAT_SAMPLES - SampleFormatConverter converter(stream); -#else - BufferedSampleFormatConverter<2> converter(stream); -#endif - renderer.render(converter, len); -} - -void Renderer::renderStreams( - SampleFormatConverter &nonReverbLeft, SampleFormatConverter &nonReverbRight, - SampleFormatConverter &reverbDryLeft, SampleFormatConverter &reverbDryRight, - SampleFormatConverter &reverbWetLeft, SampleFormatConverter &reverbWetRight, - Bit32u len) -{ - if (!synth.opened) { - nonReverbLeft.addSilence(len); - nonReverbRight.addSilence(len); - reverbDryLeft.addSilence(len); - reverbDryRight.addSilence(len); - reverbWetLeft.addSilence(len); - reverbWetRight.addSilence(len); - return; - } - +void Synth::renderStreams(Sample *nonReverbLeft, Sample *nonReverbRight, Sample *reverbDryLeft, Sample *reverbDryRight, Sample *reverbWetLeft, Sample *reverbWetRight, Bit32u len) { while (len > 0) { // We need to ensure zero-duration notes will play so add minimum 1-sample delay. Bit32u thisLen = 1; - if (!synth.isAbortingPoly()) { - const MidiEvent *nextEvent = synth.midiQueue->peekMidiEvent(); - Bit32s samplesToNextEvent = (nextEvent != NULL) ? Bit32s(nextEvent->timestamp - synth.renderedSampleCount) : MAX_SAMPLES_PER_RUN; + if (!isAbortingPoly()) { + const MidiEvent *nextEvent = midiQueue->peekMidiEvent(); + Bit32s samplesToNextEvent = (nextEvent != NULL) ? Bit32s(nextEvent->timestamp - renderedSampleCount) : MAX_SAMPLES_PER_RUN; if (samplesToNextEvent > 0) { thisLen = len > MAX_SAMPLES_PER_RUN ? MAX_SAMPLES_PER_RUN : len; if (thisLen > (Bit32u)samplesToNextEvent) { @@ -1757,85 +1530,37 @@ void Renderer::renderStreams( } } else { if (nextEvent->sysexData == NULL) { - synth.playMsgNow(nextEvent->shortMessageData); + playMsgNow(nextEvent->shortMessageData); // If a poly is aborting we don't drop the event from the queue. // Instead, we'll return to it again when the abortion is done. - if (!synth.isAbortingPoly()) { - synth.midiQueue->dropMidiEvent(); + if (!isAbortingPoly()) { + midiQueue->dropMidiEvent(); } } else { - synth.playSysexNow(nextEvent->sysexData, nextEvent->sysexLength); - synth.midiQueue->dropMidiEvent(); + playSysexNow(nextEvent->sysexData, nextEvent->sysexLength); + midiQueue->dropMidiEvent(); } } } - doRenderStreams( - nonReverbLeft.sampleBuffer, nonReverbRight.sampleBuffer, - reverbDryLeft.sampleBuffer, reverbDryRight.sampleBuffer, - reverbWetLeft.sampleBuffer, reverbWetRight.sampleBuffer, - thisLen); - nonReverbLeft.convert(thisLen); - nonReverbRight.convert(thisLen); - reverbDryLeft.convert(thisLen); - reverbDryRight.convert(thisLen); - reverbWetLeft.convert(thisLen); - reverbWetRight.convert(thisLen); + doRenderStreams(nonReverbLeft, nonReverbRight, reverbDryLeft, reverbDryRight, reverbWetLeft, reverbWetRight, thisLen); + advanceStreamPosition(nonReverbLeft, thisLen); + advanceStreamPosition(nonReverbRight, thisLen); + advanceStreamPosition(reverbDryLeft, thisLen); + advanceStreamPosition(reverbDryRight, thisLen); + advanceStreamPosition(reverbWetLeft, thisLen); + advanceStreamPosition(reverbWetRight, thisLen); len -= thisLen; } } -void Synth::renderStreams( - Bit16s *nonReverbLeft, Bit16s *nonReverbRight, - Bit16s *reverbDryLeft, Bit16s *reverbDryRight, - Bit16s *reverbWetLeft, Bit16s *reverbWetRight, - Bit32u len) -{ -#if MT32EMU_USE_FLOAT_SAMPLES - BufferedSampleFormatConverter<> convNonReverbLeft(nonReverbLeft), convNonReverbRight(nonReverbRight); - BufferedSampleFormatConverter<> convReverbDryLeft(reverbDryLeft), convReverbDryRight(reverbDryRight); - BufferedSampleFormatConverter<> convReverbWetLeft(reverbWetLeft), convReverbWetRight(reverbWetRight); -#else - SampleFormatConverter convNonReverbLeft(nonReverbLeft), convNonReverbRight(nonReverbRight); - SampleFormatConverter convReverbDryLeft(reverbDryLeft), convReverbDryRight(reverbDryRight); - SampleFormatConverter convReverbWetLeft(reverbWetLeft), convReverbWetRight(reverbWetRight); -#endif - renderer.renderStreams( - convNonReverbLeft, convNonReverbRight, - convReverbDryLeft, convReverbDryRight, - convReverbWetLeft, convReverbWetRight, - len); -} - -void Synth::renderStreams( - float *nonReverbLeft, float *nonReverbRight, - float *reverbDryLeft, float *reverbDryRight, - float *reverbWetLeft, float *reverbWetRight, - Bit32u len) -{ -#if MT32EMU_USE_FLOAT_SAMPLES - SampleFormatConverter convNonReverbLeft(nonReverbLeft), convNonReverbRight(nonReverbRight); - SampleFormatConverter convReverbDryLeft(reverbDryLeft), convReverbDryRight(reverbDryRight); - SampleFormatConverter convReverbWetLeft(reverbWetLeft), convReverbWetRight(reverbWetRight); -#else - BufferedSampleFormatConverter<> convNonReverbLeft(nonReverbLeft), convNonReverbRight(nonReverbRight); - BufferedSampleFormatConverter<> convReverbDryLeft(reverbDryLeft), convReverbDryRight(reverbDryRight); - BufferedSampleFormatConverter<> convReverbWetLeft(reverbWetLeft), convReverbWetRight(reverbWetRight); -#endif - renderer.renderStreams( - convNonReverbLeft, convNonReverbRight, - convReverbDryLeft, convReverbDryRight, - convReverbWetLeft, convReverbWetRight, - len); -} - // In GENERATION2 units, the output from LA32 goes to the Boss chip already bit-shifted. // In NICE mode, it's also better to increase volume before the reverb processing to preserve accuracy. -void Renderer::produceLA32Output(Sample *buffer, Bit32u len) { +void Synth::produceLA32Output(Sample *buffer, Bit32u len) { #if MT32EMU_USE_FLOAT_SAMPLES (void)buffer; (void)len; #else - switch (synth.dacInputMode) { + switch (dacInputMode) { case DACInputMode_GENERATION2: while (len--) { *buffer = (*buffer & 0x8000) | ((*buffer << 1) & 0x7FFE) | ((*buffer >> 14) & 0x0001); @@ -1844,7 +1569,7 @@ void Renderer::produceLA32Output(Sample *buffer, Bit32u len) { break; case DACInputMode_NICE: while (len--) { - *buffer = Synth::clipSampleEx(SampleEx(*buffer) << 1); + *buffer = clipSampleEx(SampleEx(*buffer) << 1); ++buffer; } break; @@ -1854,12 +1579,12 @@ void Renderer::produceLA32Output(Sample *buffer, Bit32u len) { #endif } -void Renderer::convertSamplesToOutput(Sample *buffer, Bit32u len) { +void Synth::convertSamplesToOutput(Sample *buffer, Bit32u len) { #if MT32EMU_USE_FLOAT_SAMPLES (void)buffer; (void)len; #else - if (synth.dacInputMode == DACInputMode_GENERATION1) { + if (dacInputMode == DACInputMode_GENERATION1) { while (len--) { *buffer = Sample((*buffer & 0x8000) | ((*buffer << 1) & 0x7FFE)); ++buffer; @@ -1868,7 +1593,7 @@ void Renderer::convertSamplesToOutput(Sample *buffer, Bit32u len) { #endif } -void Renderer::doRenderStreams(Sample *nonReverbLeft, Sample *nonReverbRight, Sample *reverbDryLeft, Sample *reverbDryRight, Sample *reverbWetLeft, Sample *reverbWetRight, Bit32u len) { +void Synth::doRenderStreams(Sample *nonReverbLeft, Sample *nonReverbRight, Sample *reverbDryLeft, Sample *reverbDryRight, Sample *reverbWetLeft, Sample *reverbWetRight, Bit32u len) { // Even if LA32 output isn't desired, we proceed anyway with temp buffers Sample tmpBufNonReverbLeft[MAX_SAMPLES_PER_RUN], tmpBufNonReverbRight[MAX_SAMPLES_PER_RUN]; if (nonReverbLeft == NULL) nonReverbLeft = tmpBufNonReverbLeft; @@ -1878,30 +1603,30 @@ void Renderer::doRenderStreams(Sample *nonReverbLeft, Sample *nonReverbRight, Sa if (reverbDryLeft == NULL) reverbDryLeft = tmpBufReverbDryLeft; if (reverbDryRight == NULL) reverbDryRight = tmpBufReverbDryRight; - if (synth.activated) { - Synth::muteSampleBuffer(nonReverbLeft, len); - Synth::muteSampleBuffer(nonReverbRight, len); - Synth::muteSampleBuffer(reverbDryLeft, len); - Synth::muteSampleBuffer(reverbDryRight, len); + if (isEnabled) { + muteSampleBuffer(nonReverbLeft, len); + muteSampleBuffer(nonReverbRight, len); + muteSampleBuffer(reverbDryLeft, len); + muteSampleBuffer(reverbDryRight, len); - for (unsigned int i = 0; i < synth.getPartialCount(); i++) { - if (synth.partialManager->shouldReverb(i)) { - synth.partialManager->produceOutput(i, reverbDryLeft, reverbDryRight, len); + for (unsigned int i = 0; i < getPartialCount(); i++) { + if (partialManager->shouldReverb(i)) { + partialManager->produceOutput(i, reverbDryLeft, reverbDryRight, len); } else { - synth.partialManager->produceOutput(i, nonReverbLeft, nonReverbRight, len); + partialManager->produceOutput(i, nonReverbLeft, nonReverbRight, len); } } produceLA32Output(reverbDryLeft, len); produceLA32Output(reverbDryRight, len); - if (synth.isReverbEnabled()) { - synth.reverbModel->process(reverbDryLeft, reverbDryRight, reverbWetLeft, reverbWetRight, len); + if (isReverbEnabled()) { + reverbModel->process(reverbDryLeft, reverbDryRight, reverbWetLeft, reverbWetRight, len); if (reverbWetLeft != NULL) convertSamplesToOutput(reverbWetLeft, len); if (reverbWetRight != NULL) convertSamplesToOutput(reverbWetRight, len); } else { - Synth::muteSampleBuffer(reverbWetLeft, len); - Synth::muteSampleBuffer(reverbWetRight, len); + muteSampleBuffer(reverbWetLeft, len); + muteSampleBuffer(reverbWetRight, len); } // Don't bother with conversion if the output is going to be unused @@ -1917,32 +1642,29 @@ void Renderer::doRenderStreams(Sample *nonReverbLeft, Sample *nonReverbRight, Sa if (reverbDryRight != tmpBufReverbDryRight) convertSamplesToOutput(reverbDryRight, len); } else { // Avoid muting buffers that wasn't requested - if (nonReverbLeft != tmpBufNonReverbLeft) Synth::muteSampleBuffer(nonReverbLeft, len); - if (nonReverbRight != tmpBufNonReverbRight) Synth::muteSampleBuffer(nonReverbRight, len); - if (reverbDryLeft != tmpBufReverbDryLeft) Synth::muteSampleBuffer(reverbDryLeft, len); - if (reverbDryRight != tmpBufReverbDryRight) Synth::muteSampleBuffer(reverbDryRight, len); - Synth::muteSampleBuffer(reverbWetLeft, len); - Synth::muteSampleBuffer(reverbWetRight, len); + if (nonReverbLeft != tmpBufNonReverbLeft) muteSampleBuffer(nonReverbLeft, len); + if (nonReverbRight != tmpBufNonReverbRight) muteSampleBuffer(nonReverbRight, len); + if (reverbDryLeft != tmpBufReverbDryLeft) muteSampleBuffer(reverbDryLeft, len); + if (reverbDryRight != tmpBufReverbDryRight) muteSampleBuffer(reverbDryRight, len); + muteSampleBuffer(reverbWetLeft, len); + muteSampleBuffer(reverbWetRight, len); } - synth.partialManager->clearAlreadyOutputed(); - synth.renderedSampleCount += len; + partialManager->clearAlreadyOutputed(); + renderedSampleCount += len; } -void Synth::printPartialUsage(Bit32u sampleOffset) { +void Synth::printPartialUsage(unsigned long sampleOffset) { unsigned int partialUsage[9]; partialManager->getPerPartPartialUsage(partialUsage); if (sampleOffset > 0) { - printDebug("[+%u] Partial Usage: 1:%02d 2:%02d 3:%02d 4:%02d 5:%02d 6:%02d 7:%02d 8:%02d R: %02d TOTAL: %02d", sampleOffset, partialUsage[0], partialUsage[1], partialUsage[2], partialUsage[3], partialUsage[4], partialUsage[5], partialUsage[6], partialUsage[7], partialUsage[8], getPartialCount() - partialManager->getFreePartialCount()); + printDebug("[+%lu] Partial Usage: 1:%02d 2:%02d 3:%02d 4:%02d 5:%02d 6:%02d 7:%02d 8:%02d R: %02d TOTAL: %02d", sampleOffset, partialUsage[0], partialUsage[1], partialUsage[2], partialUsage[3], partialUsage[4], partialUsage[5], partialUsage[6], partialUsage[7], partialUsage[8], getPartialCount() - partialManager->getFreePartialCount()); } else { printDebug("Partial Usage: 1:%02d 2:%02d 3:%02d 4:%02d 5:%02d 6:%02d 7:%02d 8:%02d R: %02d TOTAL: %02d", partialUsage[0], partialUsage[1], partialUsage[2], partialUsage[3], partialUsage[4], partialUsage[5], partialUsage[6], partialUsage[7], partialUsage[8], getPartialCount() - partialManager->getFreePartialCount()); } } bool Synth::hasActivePartials() const { - if (!opened) { - return false; - } for (unsigned int partialNum = 0; partialNum < getPartialCount(); partialNum++) { if (partialManager->getPartial(partialNum)->isActive()) { return true; @@ -1951,76 +1673,46 @@ bool Synth::hasActivePartials() const { return false; } -bool Synth::isActive() { - if (!opened) { - return false; - } - if (!midiQueue->isEmpty() || hasActivePartials()) { +bool Synth::isAbortingPoly() const { + return abortingPoly != NULL; +} + +bool Synth::isActive() const { + if (hasActivePartials()) { return true; } - if (isReverbEnabled() && reverbModel->isActive()) { - return true; + if (isReverbEnabled()) { + return reverbModel->isActive(); } - activated = false; return false; } -Bit32u Synth::getPartialCount() const { +unsigned int Synth::getPartialCount() const { return partialCount; } void Synth::getPartStates(bool *partStates) const { - if (!opened) { - memset(partStates, 0, 9 * sizeof(bool)); - return; - } for (int partNumber = 0; partNumber < 9; partNumber++) { const Part *part = parts[partNumber]; partStates[partNumber] = part->getActiveNonReleasingPartialCount() > 0; } } -Bit32u Synth::getPartStates() const { - if (!opened) return 0; - bool partStates[9]; - getPartStates(partStates); - Bit32u bitSet = 0; - for (int partNumber = 8; partNumber >= 0; partNumber--) { - bitSet = (bitSet << 1) | (partStates[partNumber] ? 1 : 0); - } - return bitSet; -} - void Synth::getPartialStates(PartialState *partialStates) const { - if (!opened) { - memset(partialStates, 0, partialCount * sizeof(PartialState)); - return; - } - for (unsigned int partialNum = 0; partialNum < partialCount; partialNum++) { - partialStates[partialNum] = getPartialState(partialManager, partialNum); - } -} + static const PartialState partialPhaseToState[8] = { + PartialState_ATTACK, PartialState_ATTACK, PartialState_ATTACK, PartialState_ATTACK, + PartialState_SUSTAIN, PartialState_SUSTAIN, PartialState_RELEASE, PartialState_INACTIVE + }; -void Synth::getPartialStates(Bit8u *partialStates) const { - if (!opened) { - memset(partialStates, 0, ((partialCount + 3) >> 2)); - return; - } - for (unsigned int quartNum = 0; (4 * quartNum) < partialCount; quartNum++) { - Bit8u packedStates = 0; - for (unsigned int i = 0; i < 4; i++) { - unsigned int partialNum = (4 * quartNum) + i; - if (partialCount <= partialNum) break; - PartialState partialState = getPartialState(partialManager, partialNum); - packedStates |= (partialState & 3) << (2 * i); - } - partialStates[quartNum] = packedStates; + for (unsigned int partialNum = 0; partialNum < getPartialCount(); partialNum++) { + const Partial *partial = partialManager->getPartial(partialNum); + partialStates[partialNum] = partial->isActive() ? partialPhaseToState[partial->getTVA()->getPhase()] : PartialState_INACTIVE; } } -Bit32u Synth::getPlayingNotes(Bit8u partNumber, Bit8u *keys, Bit8u *velocities) const { - Bit32u playingNotes = 0; - if (opened && (partNumber < 9)) { +unsigned int Synth::getPlayingNotes(unsigned int partNumber, Bit8u *keys, Bit8u *velocities) const { + unsigned int playingNotes = 0; + if (isOpen && (partNumber < 9)) { const Part *part = parts[partNumber]; const Poly *poly = part->getFirstActivePoly(); while (poly != NULL) { @@ -2033,11 +1725,11 @@ Bit32u Synth::getPlayingNotes(Bit8u partNumber, Bit8u *keys, Bit8u *velocities) return playingNotes; } -const char *Synth::getPatchName(Bit8u partNumber) const { - return (!opened || partNumber > 8) ? NULL : parts[partNumber]->getCurrentInstr(); +const char *Synth::getPatchName(unsigned int partNumber) const { + return (!isOpen || partNumber > 8) ? NULL : parts[partNumber]->getCurrentInstr(); } -const Part *Synth::getPart(Bit8u partNum) const { +const Part *Synth::getPart(unsigned int partNum) const { if (partNum > 8) { return NULL; } @@ -2115,4 +1807,4 @@ void MemoryRegion::write(unsigned int entry, unsigned int off, const Bit8u *src, } } -} // namespace MT32Emu +} diff --git a/audio/softsynth/mt32/Synth.h b/audio/softsynth/mt32/Synth.h index 5561d8d5db..97d4644ee2 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-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013, 2014 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,13 +18,8 @@ #ifndef MT32EMU_SYNTH_H #define MT32EMU_SYNTH_H -#include -#include -#include - -#include "globals.h" -#include "Types.h" -#include "Enumerations.h" +//#include +//#include namespace MT32Emu { @@ -36,8 +31,6 @@ class Part; class Poly; class Partial; class PartialManager; -class Renderer; -class ROMImage; class PatchTempMemoryRegion; class RhythmTempMemoryRegion; @@ -48,11 +41,82 @@ 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; @@ -68,64 +132,47 @@ 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 Bit32u CONTROL_ROM_SIZE = 64 * 1024; - -// Set of multiplexed output streams appeared at the DAC entrance. -template -struct DACOutputStreams { - T *nonReverbLeft; - T *nonReverbRight; - T *reverbDryLeft; - T *reverbDryRight; - T *reverbWetLeft; - T *reverbWetRight; -}; +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; -// 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 errors + + // Callbacks for reporting various errors and information 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 */) {} - // Callbacks for reporting various information - virtual void onPolyStateChanged(Bit8u /* partNum */) {} - virtual void onProgramChanged(Bit8u /* partNum */, const char * /* soundGroupName */, const char * /* patchName */) {} + virtual void onPolyStateChanged(int /* partNum */) {} + virtual void onProgramChanged(int /* partNum */, int /* bankNum */, 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 Poly; -friend class Renderer; -friend class RhythmPart; +friend class Tables; +friend class MemoryRegion; friend class TVA; +friend class TVF; friend class TVP; - private: - // **************************** Implementation fields ************************** - PatchTempMemoryRegion *patchTempMemoryRegion; RhythmTempMemoryRegion *rhythmTempMemoryRegion; TimbreTempMemoryRegion *timbreTempMemoryRegion; @@ -137,6 +184,8 @@ private: Bit8u *paddedTimbreMaxTable; + bool isEnabled; + PCMWaveEntry *pcmWaves; // Array const ControlROMFeatureSet *controlROMFeatures; @@ -145,11 +194,8 @@ private: Bit16s *pcmROMData; size_t pcmROMSize; // This is in 16-bit samples, therefore half the number of bytes in the ROM - 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 + unsigned int partialCount; + Bit8s chantable[32]; // FIXME: Need explanation why 32 is set, obviously it should be 16 MidiEventQueue *midiQueue; volatile Bit32u lastReceivedMIDIEventTimestamp; @@ -169,8 +215,7 @@ private: bool reversedStereoEnabled; - bool opened; - bool activated; + bool isOpen; bool isDefaultReportHandler; ReportHandler *reportHandler; @@ -184,17 +229,15 @@ private: Poly *abortingPoly; Analog *analog; - Renderer &renderer; - - // Binary compatibility helper. - void *reserved; - - // **************************** Implementation methods ************************** Bit32u addMIDIInterfaceDelay(Bit32u len, Bit32u timestamp); - bool isAbortingPoly() const { return abortingPoly != NULL; } - void readSysex(Bit8u channel, const Bit8u *sysex, Bit32u len) const; + 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); + + void readSysex(unsigned char channel, const Bit8u *sysex, Bit32u len) const; void initMemoryRegions(); void deleteMemoryRegions(); MemoryRegion *findMemoryRegion(Bit32u addr); @@ -205,97 +248,79 @@ private: bool loadPCMROM(const ROMImage &pcmROMImage); bool initPCMList(Bit16u mapAddress, Bit16u count); - 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]); + bool initTimbres(Bit16u mapAddress, Bit16u offset, int timbreCount, int startTimbre, bool compressed); + bool initCompressedTimbre(int drumNum, const Bit8u *mem, unsigned int memLen); void refreshSystemMasterTune(); void refreshSystemReverbParameters(); void refreshSystemReserveSettings(); - void refreshSystemChanAssign(Bit8u firstPart, Bit8u lastPart); + void refreshSystemChanAssign(unsigned int firstPart, unsigned int lastPart); void refreshSystemMasterVol(); void refreshSystem(); void reset(); - void dispose(); - void printPartialUsage(Bit32u sampleOffset = 0); + void printPartialUsage(unsigned long sampleOffset = 0); - void newTimbreSet(Bit8u partNum, Bit8u timbreGroup, Bit8u timbreNumber, const char patchName[]); + void polyStateChanged(int partNum); + void newTimbreSet(int partNum, Bit8u timbreGroup, const char patchName[]); void printDebug(const char *fmt, ...); // partNum should be 0..7 for Part 1..8, or 8 for Rhythm - const Part *getPart(Bit8u partNum) const; + const Part *getPart(unsigned int partNum) const; public: - static inline Bit16s clipSampleEx(Bit32s sampleEx) { + static inline Sample clipSampleEx(SampleEx sampleEx) { +#if MT32EMU_USE_FLOAT_SAMPLES + return sampleEx; +#else // 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) ? 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; + //return ((sampleEx + 0x8000) & ~0xFFFF) ? (sampleEx >> 31) ^ 0x7FFF : (Sample)sampleEx; + return ((-0x8000 <= sampleEx) && (sampleEx <= 0x7FFF)) ? (Sample)sampleEx : (sampleEx >> 31) ^ 0x7FFF; +#endif } - template - static inline void muteSampleBuffer(S *buffer, Bit32u len) { + static inline void muteSampleBuffer(Sample *buffer, Bit32u len) { if (buffer == NULL) return; - memset(buffer, 0, len * sizeof(S)); - } - static inline void muteSampleBuffer(float *buffer, Bit32u len) { - if (buffer == NULL) return; +#if MT32EMU_USE_FLOAT_SAMPLES // 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 } - // 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); + static Bit32u getShortMessageLength(Bit32u msg); + static Bit8u calcSysexChecksum(const Bit8u *data, const Bit32u len, const Bit8u initChecksum = 0); // Optionally sets callbacks for reporting various errors, information and debug messages - MT32EMU_EXPORT explicit Synth(ReportHandler *useReportHandler = NULL); - MT32EMU_EXPORT ~Synth(); + Synth(ReportHandler *useReportHandler = NULL); + ~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). - MT32EMU_EXPORT bool open(const ROMImage &controlROMImage, const ROMImage &pcmROMImage, Bit32u usePartialCount = DEFAULT_MAX_PARTIALS, AnalogOutputMode analogOutputMode = AnalogOutputMode_COARSE); + bool open(const ROMImage &controlROMImage, const ROMImage &pcmROMImage, unsigned int usePartialCount = DEFAULT_MAX_PARTIALS, AnalogOutputMode analogOutputMode = AnalogOutputMode_COARSE); // Overloaded method which opens the synth with default partial count. - MT32EMU_EXPORT bool open(const ROMImage &controlROMImage, const ROMImage &pcmROMImage, AnalogOutputMode analogOutputMode); + bool open(const ROMImage &controlROMImage, const ROMImage &pcmROMImage, AnalogOutputMode analogOutputMode); // Closes the MT-32 and deallocates any memory used by the synthesizer - MT32EMU_EXPORT void close(); - - // Returns true if the synth is in completely initialized state, otherwise returns false. - MT32EMU_EXPORT bool isOpen() const; + void close(bool forced = false); // All the enqueued events are processed by the synth immediately. - MT32EMU_EXPORT void flushMIDIQueue(); + 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. - MT32EMU_EXPORT Bit32u setMIDIEventQueueSize(Bit32u); + Bit32u setMIDIEventQueueSize(Bit32u); // Enqueues a MIDI event for subsequent playback. // The MIDI event will be processed not before the specified timestamp. @@ -305,15 +330,14 @@ 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 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); + // 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 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); + // Overloaded methods for the MIDI events to be processed ASAP. + bool playMsg(Bit32u msg); + bool playSysex(const Bit8u *sysex, Bit32u len); // WARNING: // The methods below don't ensure minimum 1-sample delay between sequential MIDI events, @@ -321,60 +345,40 @@ 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. - // 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; + 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; // 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 setReverbOverridden(bool reverbOverridden); - // Returns whether reverb settings are overridden. - MT32EMU_EXPORT bool isReverbOverridden() const; + void setReverbOverridden(bool reverbOverridden); + 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). - 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; + void setReverbCompatibilityMode(bool mt32CompatibleMode); + bool isMT32ReverbCompatibilityMode() const; + void setDACInputMode(DACInputMode mode); + DACInputMode getDACInputMode() const; + void setMIDIDelayMode(MIDIDelayMode mode); + 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 - MT32EMU_EXPORT void setOutputGain(float gain); - // Returns current output gain factor for synth output channels. - MT32EMU_EXPORT float getOutputGain() const; + void setOutputGain(float); + 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 @@ -385,85 +389,59 @@ 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 - MT32EMU_EXPORT void setReverbOutputGain(float gain); - // Returns current output gain factor for reverb wet output channels. - MT32EMU_EXPORT float getReverbOutputGain() const; + void setReverbOutputGain(float); + float getReverbOutputGain() const; - // 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; + void setReversedStereoEnabled(bool enabled); + bool isReversedStereoEnabled(); // Returns actual sample rate used in emulation of stereo analog circuitry of hardware units. // See comment for render() below. - MT32EMU_EXPORT Bit32u getStereoOutputSampleRate() const; + unsigned int 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 (OVERSAMPLED), the output signal is upsampled to 48 (96) kHz in order + // When AnalogOutputMode is set to ACCURATE, the output signal is upsampled to 48 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). 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); + // The length is in frames, not bytes (in 16-bit stereo, one frame is 4 bytes). + void render(Sample *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 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 &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 &streams, Bit32u len) { - renderStreams(streams.nonReverbLeft, streams.nonReverbRight, streams.reverbDryLeft, streams.reverbDryRight, streams.reverbWetLeft, streams.reverbWetRight, len); - } + // 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); // Returns true when there is at least one active partial, otherwise false. - MT32EMU_EXPORT bool hasActivePartials() const; + bool hasActivePartials() 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 true if hasActivePartials() returns true, or reverb is (somewhat unreliably) detected as being active. + bool isActive() const; // Returns the maximum number of partials playing simultaneously. - MT32EMU_EXPORT Bit32u getPartialCount() const; + unsigned int 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. - 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; + void getPartStates(bool *partStates) 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. - 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; + void getPartialStates(PartialState *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. - MT32EMU_EXPORT Bit32u getPlayingNotes(Bit8u partNumber, Bit8u *keys, Bit8u *velocities) const; + unsigned int getPlayingNotes(unsigned int 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. - MT32EMU_EXPORT const char *getPatchName(Bit8u partNumber) const; + const char *getPatchName(unsigned int partNumber) 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); -}; // class Synth + void readMemory(Bit32u addr, Bit32u len, Bit8u *data); +}; -} // namespace MT32Emu +} -#endif // #ifndef MT32EMU_SYNTH_H +#endif diff --git a/audio/softsynth/mt32/TVA.cpp b/audio/softsynth/mt32/TVA.cpp index 465480a24e..894e53f14a 100644 --- a/audio/softsynth/mt32/TVA.cpp +++ b/audio/softsynth/mt32/TVA.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013, 2014 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,23 +19,19 @@ * This class emulates the calculations performed by the 8095 microcontroller in order to configure the LA-32's amplitude ramp for a single partial at each stage of its TVA envelope. * Unless we introduced bugs, it should be pretty much 100% accurate according to Mok's specifications. */ +//#include +#include "mt32emu.h" +#include "mmath.h" #include "internals.h" -#include "TVA.h" -#include "Part.h" -#include "Partial.h" -#include "Poly.h" -#include "Synth.h" -#include "Tables.h" - namespace MT32Emu { // CONFIRMED: Matches a table in ROM - haven't got around to coming up with a formula for it yet. static Bit8u biasLevelToAmpSubtractionCoeff[13] = {255, 187, 137, 100, 74, 54, 40, 29, 21, 15, 10, 5, 0}; TVA::TVA(const Partial *usePartial, LA32Ramp *useAmpRamp) : - partial(usePartial), ampRamp(useAmpRamp), system(&usePartial->getSynth()->mt32ram.system), phase(TVA_PHASE_DEAD) { + partial(usePartial), ampRamp(useAmpRamp), system_(&usePartial->getSynth()->mt32ram.system), phase(TVA_PHASE_DEAD) { } void TVA::startRamp(Bit8u newTarget, Bit8u newIncrement, int newPhase) { @@ -99,11 +95,11 @@ 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) { +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) { int amp = 155; if (!partial->isRingModulatingSlave()) { - amp -= tables->masterVolToAmpSubtraction[system->masterVol]; + amp -= tables->masterVolToAmpSubtraction[system_->masterVol]; if (amp < 0) { return 0; } @@ -144,7 +140,7 @@ static int calcBasicAmp(const Tables *tables, const Partial *partial, const MemP return amp; } -static int calcKeyTimeSubtraction(Bit8u envTimeKeyfollow, int key) { +int calcKeyTimeSubtraction(Bit8u envTimeKeyfollow, int key) { if (envTimeKeyfollow == 0) { return 0; } @@ -169,7 +165,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()); + int newTarget = calcBasicAmp(tables, partial, system_, partialParam, patchTemp, newRhythmTemp, biasAmpSubtraction, veloAmpSubtraction, part->getExpression()); 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 +217,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()); + int newTarget = calcBasicAmp(tables, partial, system_, partialParam, patchTemp, rhythmTemp, biasAmpSubtraction, veloAmpSubtraction, part->getExpression()); newTarget += partialParam->tva.envLevel[3]; // Since we're in TVA_PHASE_SUSTAIN at this point, we know that target has been reached and an interrupt fired, so we can rely on it being the current amp. int targetDelta = newTarget - target; @@ -283,7 +279,7 @@ void TVA::nextPhase() { int envPointIndex = phase; if (!allLevelsZeroFromNowOn) { - newTarget = calcBasicAmp(tables, partial, system, partialParam, patchTemp, rhythmTemp, biasAmpSubtraction, veloAmpSubtraction, part->getExpression()); + newTarget = calcBasicAmp(tables, partial, system_, partialParam, patchTemp, rhythmTemp, biasAmpSubtraction, veloAmpSubtraction, part->getExpression()); if (newPhase == TVA_PHASE_SUSTAIN || newPhase == TVA_PHASE_RELEASE) { if (partialParam->tva.envLevel[3] == 0) { @@ -367,4 +363,4 @@ void TVA::nextPhase() { startRamp((Bit8u)newTarget, (Bit8u)newIncrement, newPhase); } -} // namespace MT32Emu +} diff --git a/audio/softsynth/mt32/TVA.h b/audio/softsynth/mt32/TVA.h index f593b4e7d1..a100107a69 100644 --- a/audio/softsynth/mt32/TVA.h +++ b/audio/softsynth/mt32/TVA.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013, 2014 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,15 +18,9 @@ #ifndef MT32EMU_TVA_H #define MT32EMU_TVA_H -#include "globals.h" -#include "Types.h" -#include "Structures.h" - namespace MT32Emu { -class LA32Ramp; class Part; -class Partial; // Note that when entering nextPhase(), newPhase is set to phase + 1, and the descriptions/names below refer to // newPhase's value. @@ -63,7 +57,7 @@ class TVA { private: const Partial * const partial; LA32Ramp *ampRamp; - const MemParams::System * const system; + const MemParams::System * const system_; const Part *part; const TimbreParam::PartialParam *partialParam; @@ -93,8 +87,8 @@ public: bool isPlaying() const; int getPhase() const; -}; // class TVA +}; -} // namespace MT32Emu +} -#endif // #ifndef MT32EMU_TVA_H +#endif /* TVA_H_ */ diff --git a/audio/softsynth/mt32/TVF.cpp b/audio/softsynth/mt32/TVF.cpp index d603883bd4..164cf2b4cb 100644 --- a/audio/softsynth/mt32/TVF.cpp +++ b/audio/softsynth/mt32/TVF.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013, 2014 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,13 +15,11 @@ * along with this program. If not, see . */ -#include "internals.h" +//#include -#include "TVF.h" -#include "LA32Ramp.h" -#include "Partial.h" -#include "Poly.h" -#include "Tables.h" +#include "mt32emu.h" +#include "mmath.h" +#include "internals.h" namespace MT32Emu { @@ -77,7 +75,7 @@ static int calcBaseCutoff(const TimbreParam::PartialParam *partialParam, Bit32u // biasPoint range here: 64 to 127 int bias = biasPoint - 31 - key; // bias range here: -75 to 84 if (bias < 0) { - baseCutoff += bias * biasLevelToBiasMult[partialParam->tvf.biasLevel]; // Calculation range: -6375 to 6375 + baseCutoff += bias * biasLevelToBiasMult[partialParam->tvf.biasLevel]; // Calculation range: −6375 to 6375 // baseCutoff range now: -9399 to 9399 } } @@ -230,4 +228,4 @@ void TVF::nextPhase() { startRamp(newTarget, newIncrement, newPhase); } -} // namespace MT32Emu +} diff --git a/audio/softsynth/mt32/TVF.h b/audio/softsynth/mt32/TVF.h index 38dcef708c..1e2c6d1728 100644 --- a/audio/softsynth/mt32/TVF.h +++ b/audio/softsynth/mt32/TVF.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013, 2014 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,15 +18,8 @@ #ifndef MT32EMU_TVF_H #define MT32EMU_TVF_H -#include "globals.h" -#include "Types.h" -#include "Structures.h" - namespace MT32Emu { -class LA32Ramp; -class Partial; - class TVF { private: const Partial * const partial; @@ -54,8 +47,8 @@ public: Bit8u getBaseCutoff() const; void handleInterrupt(); void startDecay(); -}; // class TVF +}; -} // namespace MT32Emu +} -#endif // #ifndef MT32EMU_TVF_H +#endif diff --git a/audio/softsynth/mt32/TVP.cpp b/audio/softsynth/mt32/TVP.cpp index e1ecb0f681..a8003d96dc 100644 --- a/audio/softsynth/mt32/TVP.cpp +++ b/audio/softsynth/mt32/TVP.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013, 2014 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,17 +15,12 @@ * along with this program. If not, see . */ -#include +//#include +//#include +#include "mt32emu.h" #include "internals.h" -#include "TVP.h" -#include "Part.h" -#include "Partial.h" -#include "Poly.h" -#include "Synth.h" -#include "TVA.h" - namespace MT32Emu { // FIXME: Add Explanation @@ -52,7 +47,7 @@ static Bit16u keyToPitchTable[] = { }; TVP::TVP(const Partial *usePartial) : - partial(usePartial), system(&usePartial->getSynth()->mt32ram.system) { + partial(usePartial), system_(&usePartial->getSynth()->mt32ram.system) { // We want to do processing 4000 times per second. FIXME: This is pretty arbitrary. maxCounter = SAMPLE_RATE / 4000; // The timer runs at 500kHz. We only need to bother updating it every maxCounter samples, before we do processing. @@ -145,7 +140,7 @@ void TVP::reset(const Part *usePart, const TimbreParam::PartialParam *usePartial phase = 0; if (partialParam->pitchEnv.timeKeyfollow) { - timeKeyfollowSubtraction = (Bit32s)(key - 60) >> (5 - partialParam->pitchEnv.timeKeyfollow); // PORTABILITY NOTE: Assumes arithmetic shift + timeKeyfollowSubtraction = (key - 60) >> (5 - partialParam->pitchEnv.timeKeyfollow); // PORTABILITY NOTE: Assumes arithmetic shift } else { timeKeyfollowSubtraction = 0; } @@ -168,7 +163,7 @@ void TVP::updatePitch() { if (!partial->isPCM() || (partial->getControlROMPCMStruct()->len & 0x01) == 0) { // FIXME: Use !partial->pcmWaveEntry->unaffectedByMasterTune instead // FIXME: masterTune recalculation doesn't really happen here, and there are various bugs not yet emulated // 171 is ~half a semitone. - newPitch += ((system->masterTune - 64) * 171) >> 6; // PORTABILITY NOTE: Assumes arithmetic shift. + newPitch += ((system_->masterTune - 64) * 171) >> 6; // PORTABILITY NOTE: Assumes arithmetic shift. } if ((partialParam->wg.pitchBenderEnabled & 1) != 0) { newPitch += part->getPitchBend(); @@ -177,12 +172,13 @@ void TVP::updatePitch() { newPitch = 0; } - // Skipping this check seems about right emulation of MT-32 GEN0 quirk exploited in Colonel's Bequest timbre "Lightning" - if (partial->getSynth()->controlROMFeatures->quirkPitchEnvelopeOverflow == 0) { - if (newPitch > 59392) { - newPitch = 59392; - } +// Note: Temporary #ifdef until we have proper "quirk" configuration +// This is about right emulation of MT-32 GEN0 quirk exploited in Colonel's Bequest timbre "Lightning" +#ifndef MT32EMU_QUIRK_PITCH_ENVELOPE_OVERFLOW_MT32 + if (newPitch > 59392) { + newPitch = 59392; } +#endif pitch = (Bit16u)newPitch; // FIXME: We're doing this here because that's what the CM-32L does - we should probably move this somewhere more appropriate in future. @@ -327,4 +323,4 @@ void TVP::process() { updatePitch(); } -} // namespace MT32Emu +} diff --git a/audio/softsynth/mt32/TVP.h b/audio/softsynth/mt32/TVP.h index be90f0ff08..e9d05ffa7a 100644 --- a/audio/softsynth/mt32/TVP.h +++ b/audio/softsynth/mt32/TVP.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013, 2014 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,19 +18,12 @@ #ifndef MT32EMU_TVP_H #define MT32EMU_TVP_H -#include "globals.h" -#include "Types.h" -#include "Structures.h" - namespace MT32Emu { -class Part; -class Partial; - class TVP { private: const Partial * const partial; - const MemParams::System * const system; // FIXME: Only necessary because masterTune calculation is done in the wrong place atm. + const MemParams::System * const system_; // FIXME: Only necessary because masterTune calculation is done in the wrong place atm. const Part *part; const TimbreParam::PartialParam *partialParam; @@ -67,8 +60,8 @@ public: Bit32u getBasePitch() const; Bit16u nextPitch(); void startDecay(); -}; // class TVP +}; -} // namespace MT32Emu +} -#endif // #ifndef MT32EMU_TVP_H +#endif diff --git a/audio/softsynth/mt32/Tables.cpp b/audio/softsynth/mt32/Tables.cpp index d5dca83a00..7e165b5a7a 100644 --- a/audio/softsynth/mt32/Tables.cpp +++ b/audio/softsynth/mt32/Tables.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013, 2014 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,10 +15,11 @@ * along with this program. If not, see . */ -#include "internals.h" +//#include -#include "Tables.h" +#include "mt32emu.h" #include "mmath.h" +#include "Tables.h" namespace MT32Emu { @@ -47,9 +48,7 @@ Tables::Tables() { envLogarithmicTime[lf] = (Bit8u)ceil(64.0f + LOG2F((float)lf) * 8.0f); } -#if 0 - // The table below is to be used in conjunction with emulation of VCA of newer generation units which is currently missing. - // These relatively small values are rather intended to fine-tune the overall amplification of the VCA. +#ifdef EMULATE_LAPC_I // Dummy #ifdef - we'll have runtime emulation mode selection in future. // CONFIRMED: Based on a table found by Mok in the LAPC-I control ROM // Note that this matches the MT-32 table, but with the values clamped to a maximum of 8. memset(masterVolToAmpSubtraction, 8, 71); @@ -65,12 +64,12 @@ Tables::Tables() { // CONFIRMED: Based on a table found by Mok in the MT-32 control ROM masterVolToAmpSubtraction[0] = 255; for (int masterVol = 1; masterVol <= 100; masterVol++) { - masterVolToAmpSubtraction[masterVol] = (Bit8u)(106.31 - 16.0f * LOG2F((float)masterVol)); + masterVolToAmpSubtraction[masterVol] = (int)(106.31 - 16.0f * LOG2F((float)masterVol)); } #endif for (int i = 0; i <= 100; i++) { - pulseWidth100To255[i] = (Bit8u)(i * 255 / 100.0f + 0.5f); + pulseWidth100To255[i] = (int)(i * 255 / 100.0f + 0.5f); //synth->printDebug("%d: %d", i, pulseWidth100To255[i]); } @@ -95,4 +94,4 @@ Tables::Tables() { resAmpDecayFactor = resAmpDecayFactorTable; } -} // namespace MT32Emu +} diff --git a/audio/softsynth/mt32/Tables.h b/audio/softsynth/mt32/Tables.h index 249e32919a..8865c7fac8 100644 --- a/audio/softsynth/mt32/Tables.h +++ b/audio/softsynth/mt32/Tables.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013, 2014 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,6 @@ #ifndef MT32EMU_TABLES_H #define MT32EMU_TABLES_H -#include "globals.h" -#include "Types.h" - namespace MT32Emu { class Tables { @@ -55,8 +52,8 @@ public: Bit16u logsin9[512]; const Bit8u *resAmpDecayFactor; -}; // class Tables +}; -} // namespace MT32Emu +} -#endif // #ifndef MT32EMU_TABLES_H +#endif diff --git a/audio/softsynth/mt32/Types.h b/audio/softsynth/mt32/Types.h index f90dce19a4..934b1a1173 100644 --- a/audio/softsynth/mt32/Types.h +++ b/audio/softsynth/mt32/Types.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013, 2014 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,14 @@ typedef signed short int Bit16s; typedef unsigned char Bit8u; typedef signed char Bit8s; +#if MT32EMU_USE_FLOAT_SAMPLES +typedef float Sample; +typedef float SampleEx; +#else +typedef Bit16s Sample; +typedef Bit32s SampleEx; +#endif + } #endif diff --git a/audio/softsynth/mt32/c_interface/c_interface.cpp b/audio/softsynth/mt32/c_interface/c_interface.cpp deleted file mode 100644 index a13c88bbe8..0000000000 --- a/audio/softsynth/mt32/c_interface/c_interface.cpp +++ /dev/null @@ -1,624 +0,0 @@ -/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 2.1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ - -#include "../globals.h" -#include "../Types.h" -#include "../File.h" -#include "../FileStream.h" -#include "../ROMInfo.h" -#include "../Synth.h" -#include "../MidiStreamParser.h" - -#include "c_types.h" -#include "c_interface.h" - -using namespace MT32Emu; - -namespace MT32Emu { - -static mt32emu_service_version getSynthVersionID(mt32emu_service_i) { - return MT32EMU_SERVICE_VERSION_CURRENT; -} - -static const mt32emu_service_i_v0 SERVICE_VTABLE = { - getSynthVersionID, - mt32emu_get_supported_report_handler_version, - mt32emu_get_supported_midi_receiver_version, - mt32emu_get_library_version_int, - mt32emu_get_library_version_string, - mt32emu_get_stereo_output_samplerate, - mt32emu_create_context, - mt32emu_free_context, - mt32emu_add_rom_data, - mt32emu_add_rom_file, - mt32emu_get_rom_info, - mt32emu_set_partial_count, - mt32emu_set_analog_output_mode, - mt32emu_open_synth, - mt32emu_close_synth, - mt32emu_is_open, - mt32emu_get_actual_stereo_output_samplerate, - mt32emu_flush_midi_queue, - mt32emu_set_midi_event_queue_size, - mt32emu_set_midi_receiver, - mt32emu_parse_stream, - mt32emu_parse_stream_at, - mt32emu_play_short_message, - mt32emu_play_short_message_at, - mt32emu_play_msg, - mt32emu_play_sysex, - mt32emu_play_msg_at, - mt32emu_play_sysex_at, - mt32emu_play_msg_now, - mt32emu_play_msg_on_part, - mt32emu_play_sysex_now, - mt32emu_write_sysex, - mt32emu_set_reverb_enabled, - mt32emu_is_reverb_enabled, - mt32emu_set_reverb_overridden, - mt32emu_is_reverb_overridden, - mt32emu_set_reverb_compatibility_mode, - mt32emu_is_mt32_reverb_compatibility_mode, - mt32emu_is_default_reverb_mt32_compatible, - mt32emu_set_dac_input_mode, - mt32emu_get_dac_input_mode, - mt32emu_set_midi_delay_mode, - mt32emu_get_midi_delay_mode, - mt32emu_set_output_gain, - mt32emu_get_output_gain, - mt32emu_set_reverb_output_gain, - mt32emu_get_reverb_output_gain, - mt32emu_set_reversed_stereo_enabled, - mt32emu_is_reversed_stereo_enabled, - mt32emu_render_bit16s, - mt32emu_render_float, - mt32emu_render_bit16s_streams, - mt32emu_render_float_streams, - mt32emu_has_active_partials, - mt32emu_is_active, - mt32emu_get_partial_count, - mt32emu_get_part_states, - mt32emu_get_partial_states, - mt32emu_get_playing_notes, - mt32emu_get_patch_name, - mt32emu_read_memory -}; - -} // namespace MT32Emu - -struct mt32emu_data { - ReportHandler *reportHandler; - Synth *synth; - const ROMImage *controlROMImage; - const ROMImage *pcmROMImage; - DefaultMidiStreamParser *midiParser; - Bit32u partialCount; - AnalogOutputMode analogOutputMode; -}; - -// Internal C++ utility stuff - -namespace MT32Emu { - -class DelegatingReportHandlerAdapter : public ReportHandler { -public: - DelegatingReportHandlerAdapter(mt32emu_report_handler_i useReportHandler, void *useInstanceData) : - delegate(useReportHandler), instanceData(useInstanceData) {} - -protected: - const mt32emu_report_handler_i delegate; - void * const instanceData; - -private: - void printDebug(const char *fmt, va_list list) { - if (delegate.v0->printDebug == NULL) { - ReportHandler::printDebug(fmt, list); - } else { - delegate.v0->printDebug(instanceData, fmt, list); - } - } - - void onErrorControlROM() { - if (delegate.v0->onErrorControlROM == NULL) { - ReportHandler::onErrorControlROM(); - } else { - delegate.v0->onErrorControlROM(instanceData); - } - } - - void onErrorPCMROM() { - if (delegate.v0->onErrorPCMROM == NULL) { - ReportHandler::onErrorPCMROM(); - } else { - delegate.v0->onErrorPCMROM(instanceData); - } - } - - void showLCDMessage(const char *message) { - if (delegate.v0->showLCDMessage == NULL) { - ReportHandler::showLCDMessage(message); - } else { - delegate.v0->showLCDMessage(instanceData, message); - } - } - - void onMIDIMessagePlayed() { - if (delegate.v0->onMIDIMessagePlayed == NULL) { - ReportHandler::onMIDIMessagePlayed(); - } else { - delegate.v0->onMIDIMessagePlayed(instanceData); - } - } - - bool onMIDIQueueOverflow() { - if (delegate.v0->onMIDIQueueOverflow == NULL) { - return ReportHandler::onMIDIQueueOverflow(); - } - return delegate.v0->onMIDIQueueOverflow(instanceData) != MT32EMU_BOOL_FALSE; - } - - void onMIDISystemRealtime(Bit8u systemRealtime) { - if (delegate.v0->onMIDISystemRealtime == NULL) { - ReportHandler::onMIDISystemRealtime(systemRealtime); - } else { - delegate.v0->onMIDISystemRealtime(instanceData, systemRealtime); - } - } - - void onDeviceReset() { - if (delegate.v0->onDeviceReset == NULL) { - ReportHandler::onDeviceReset(); - } else { - delegate.v0->onDeviceReset(instanceData); - } - } - - void onDeviceReconfig() { - if (delegate.v0->onDeviceReconfig == NULL) { - ReportHandler::onDeviceReconfig(); - } else { - delegate.v0->onDeviceReconfig(instanceData); - } - } - - void onNewReverbMode(Bit8u mode) { - if (delegate.v0->onNewReverbMode == NULL) { - ReportHandler::onNewReverbMode(mode); - } else { - delegate.v0->onNewReverbMode(instanceData, mode); - } - } - - void onNewReverbTime(Bit8u time) { - if (delegate.v0->onNewReverbTime == NULL) { - ReportHandler::onNewReverbTime(time); - } else { - delegate.v0->onNewReverbTime(instanceData, time); - } - } - - void onNewReverbLevel(Bit8u level) { - if (delegate.v0->onNewReverbLevel == NULL) { - ReportHandler::onNewReverbLevel(level); - } else { - delegate.v0->onNewReverbLevel(instanceData, level); - } - } - - void onPolyStateChanged(Bit8u partNum) { - if (delegate.v0->onPolyStateChanged == NULL) { - ReportHandler::onPolyStateChanged(partNum); - } else { - delegate.v0->onPolyStateChanged(instanceData, partNum); - } - } - - void onProgramChanged(Bit8u partNum, const char *soundGroupName, const char *patchName) { - if (delegate.v0->onProgramChanged == NULL) { - ReportHandler::onProgramChanged(partNum, soundGroupName, patchName); - } else { - delegate.v0->onProgramChanged(instanceData, partNum, soundGroupName, patchName); - } - } -}; - -class DelegatingMidiStreamParser : public DefaultMidiStreamParser { -public: - DelegatingMidiStreamParser(const mt32emu_data *useData, mt32emu_midi_receiver_i useMIDIReceiver, void *useInstanceData) : - DefaultMidiStreamParser(*useData->synth), delegate(useMIDIReceiver), instanceData(useInstanceData) {} - -protected: - mt32emu_midi_receiver_i delegate; - void *instanceData; - -private: - void handleShortMessage(const Bit32u message) { - if (delegate.v0->handleShortMessage == NULL) { - DefaultMidiStreamParser::handleShortMessage(message); - } else { - delegate.v0->handleShortMessage(instanceData, message); - } - } - - void handleSysex(const Bit8u *stream, const Bit32u length) { - if (delegate.v0->handleSysex == NULL) { - DefaultMidiStreamParser::handleSysex(stream, length); - } else { - delegate.v0->handleSysex(instanceData, stream, length); - } - } - - void handleSystemRealtimeMessage(const Bit8u realtime) { - if (delegate.v0->handleSystemRealtimeMessage == NULL) { - DefaultMidiStreamParser::handleSystemRealtimeMessage(realtime); - } else { - delegate.v0->handleSystemRealtimeMessage(instanceData, realtime); - } - } -}; - -static mt32emu_return_code addROMFile(mt32emu_data *data, File *file) { - const ROMImage *image = ROMImage::makeROMImage(file); - const ROMInfo *info = image->getROMInfo(); - if (info == NULL) { - ROMImage::freeROMImage(image); - return MT32EMU_RC_ROM_NOT_IDENTIFIED; - } - if (info->type == ROMInfo::Control) { - if (data->controlROMImage != NULL) { - delete data->controlROMImage->getFile(); - ROMImage::freeROMImage(data->controlROMImage); - } - data->controlROMImage = image; - return MT32EMU_RC_ADDED_CONTROL_ROM; - } else if (info->type == ROMInfo::PCM) { - if (data->pcmROMImage != NULL) { - delete data->pcmROMImage->getFile(); - ROMImage::freeROMImage(data->pcmROMImage); - } - data->pcmROMImage = image; - return MT32EMU_RC_ADDED_PCM_ROM; - } - ROMImage::freeROMImage(image); - return MT32EMU_RC_OK; // No support for reverb ROM yet. -} - -} // namespace MT32Emu - -// C-visible implementation - -extern "C" { - -const mt32emu_service_i mt32emu_get_service_i() { - mt32emu_service_i i = { &SERVICE_VTABLE }; - return i; -} - -mt32emu_report_handler_version mt32emu_get_supported_report_handler_version() { - return MT32EMU_REPORT_HANDLER_VERSION_CURRENT; -} - -mt32emu_midi_receiver_version mt32emu_get_supported_midi_receiver_version() { - return MT32EMU_MIDI_RECEIVER_VERSION_CURRENT; -} - -mt32emu_bit32u mt32emu_get_library_version_int() { - return Synth::getLibraryVersionInt(); -} - -const char *mt32emu_get_library_version_string() { - return Synth::getLibraryVersionString(); -} - -mt32emu_bit32u mt32emu_get_stereo_output_samplerate(const mt32emu_analog_output_mode analog_output_mode) { - return Synth::getStereoOutputSampleRate(static_cast(analog_output_mode)); -} - -mt32emu_context mt32emu_create_context(mt32emu_report_handler_i report_handler, void *instance_data) { - mt32emu_data *data = new mt32emu_data; - data->reportHandler = (report_handler.v0 != NULL) ? new DelegatingReportHandlerAdapter(report_handler, instance_data) : new ReportHandler; - data->synth = new Synth(data->reportHandler); - data->midiParser = new DefaultMidiStreamParser(*data->synth); - data->controlROMImage = NULL; - data->pcmROMImage = NULL; - data->partialCount = DEFAULT_MAX_PARTIALS; - data->analogOutputMode = AnalogOutputMode_COARSE; - return data; -} - -void mt32emu_free_context(mt32emu_context data) { - if (data == NULL) return; - if (data->controlROMImage != NULL) { - delete data->controlROMImage->getFile(); - ROMImage::freeROMImage(data->controlROMImage); - data->controlROMImage = NULL; - } - if (data->pcmROMImage != NULL) { - delete data->pcmROMImage->getFile(); - ROMImage::freeROMImage(data->pcmROMImage); - data->pcmROMImage = NULL; - } - delete data->midiParser; - data->midiParser = NULL; - delete data->synth; - data->synth = NULL; - delete data->reportHandler; - data->reportHandler = NULL; - delete data; -} - -mt32emu_return_code mt32emu_add_rom_data(mt32emu_context context, const mt32emu_bit8u *data, size_t data_size, const mt32emu_sha1_digest *sha1_digest) { - if (sha1_digest == NULL) return addROMFile(context, new ArrayFile(data, data_size)); - return addROMFile(context, new ArrayFile(data, data_size, *sha1_digest)); -} - -mt32emu_return_code mt32emu_add_rom_file(mt32emu_context context, const char *filename) { - mt32emu_return_code rc = MT32EMU_RC_OK; - FileStream *fs = new FileStream; - if (fs->open(filename)) { - if (fs->getData() != NULL) { - rc = addROMFile(context, fs); - if (rc > 0) return rc; - } else { - rc = MT32EMU_RC_FILE_NOT_LOADED; - } - } else { - rc = MT32EMU_RC_FILE_NOT_FOUND; - } - delete fs; - return rc; -} - -void mt32emu_get_rom_info(mt32emu_const_context context, mt32emu_rom_info *rom_info) { - const ROMInfo *romInfo = context->controlROMImage == NULL ? NULL : context->controlROMImage->getROMInfo(); - if (romInfo != NULL) { - rom_info->control_rom_id = romInfo->shortName; - rom_info->control_rom_description = romInfo->description; - rom_info->control_rom_sha1_digest = romInfo->sha1Digest; - } else { - rom_info->control_rom_id = NULL; - rom_info->control_rom_description = NULL; - rom_info->control_rom_sha1_digest = NULL; - } - romInfo = context->pcmROMImage == NULL ? NULL : context->pcmROMImage->getROMInfo(); - if (romInfo != NULL) { - rom_info->pcm_rom_id = romInfo->shortName; - rom_info->pcm_rom_description = romInfo->description; - rom_info->pcm_rom_sha1_digest = romInfo->sha1Digest; - } else { - rom_info->pcm_rom_id = NULL; - rom_info->pcm_rom_description = NULL; - rom_info->pcm_rom_sha1_digest = NULL; - } -} - -void mt32emu_set_partial_count(mt32emu_context context, const mt32emu_bit32u partial_count) { - context->partialCount = partial_count; -} - -void mt32emu_set_analog_output_mode(mt32emu_context context, const mt32emu_analog_output_mode analog_output_mode) { - context->analogOutputMode = static_cast(analog_output_mode); -} - -mt32emu_return_code mt32emu_open_synth(mt32emu_const_context context) { - if ((context->controlROMImage == NULL) || (context->pcmROMImage == NULL)) { - return MT32EMU_RC_MISSING_ROMS; - } - if (context->synth->open(*context->controlROMImage, *context->pcmROMImage, context->partialCount, context->analogOutputMode)) { - return MT32EMU_RC_OK; - } - return MT32EMU_RC_FAILED; -} - -void mt32emu_close_synth(mt32emu_const_context context) { - context->synth->close(); -} - -mt32emu_boolean mt32emu_is_open(mt32emu_const_context context) { - return context->synth->isOpen() ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE; -} - -mt32emu_bit32u mt32emu_get_actual_stereo_output_samplerate(mt32emu_const_context context) { - return context->synth->getStereoOutputSampleRate(); -} - -void mt32emu_flush_midi_queue(mt32emu_const_context context) { - context->synth->flushMIDIQueue(); -} - -mt32emu_bit32u mt32emu_set_midi_event_queue_size(mt32emu_const_context context, const mt32emu_bit32u queue_size) { - return context->synth->setMIDIEventQueueSize(queue_size); -} - -void mt32emu_set_midi_receiver(mt32emu_context context, mt32emu_midi_receiver_i midi_receiver, void *instance_data) { - delete context->midiParser; - context->midiParser = (midi_receiver.v0 != NULL) ? new DelegatingMidiStreamParser(context, midi_receiver, instance_data) : new DefaultMidiStreamParser(*context->synth); -} - -void mt32emu_parse_stream(mt32emu_const_context context, const mt32emu_bit8u *stream, mt32emu_bit32u length) { - context->midiParser->resetTimestamp(); - context->midiParser->parseStream(stream, length); -} - -void mt32emu_parse_stream_at(mt32emu_const_context context, const mt32emu_bit8u *stream, mt32emu_bit32u length, mt32emu_bit32u timestamp) { - context->midiParser->setTimestamp(timestamp); - context->midiParser->parseStream(stream, length); -} - -void mt32emu_play_short_message(mt32emu_const_context context, mt32emu_bit32u message) { - context->midiParser->resetTimestamp(); - context->midiParser->processShortMessage(message); -} - -void mt32emu_play_short_message_at(mt32emu_const_context context, mt32emu_bit32u message, mt32emu_bit32u timestamp) { - context->midiParser->setTimestamp(timestamp); - context->midiParser->processShortMessage(message); -} - -mt32emu_return_code mt32emu_play_msg(mt32emu_const_context context, mt32emu_bit32u msg) { - if (!context->synth->isOpen()) return MT32EMU_RC_NOT_OPENED; - return (context->synth->playMsg(msg)) ? MT32EMU_RC_OK : MT32EMU_RC_QUEUE_FULL; -} - -mt32emu_return_code mt32emu_play_sysex(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len) { - if (!context->synth->isOpen()) return MT32EMU_RC_NOT_OPENED; - return (context->synth->playSysex(sysex, len)) ? MT32EMU_RC_OK : MT32EMU_RC_QUEUE_FULL; -} - -mt32emu_return_code mt32emu_play_msg_at(mt32emu_const_context context, mt32emu_bit32u msg, mt32emu_bit32u timestamp) { - if (!context->synth->isOpen()) return MT32EMU_RC_NOT_OPENED; - return (context->synth->playMsg(msg, timestamp)) ? MT32EMU_RC_OK : MT32EMU_RC_QUEUE_FULL; -} - -mt32emu_return_code mt32emu_play_sysex_at(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len, mt32emu_bit32u timestamp) { - if (!context->synth->isOpen()) return MT32EMU_RC_NOT_OPENED; - return (context->synth->playSysex(sysex, len, timestamp)) ? MT32EMU_RC_OK : MT32EMU_RC_QUEUE_FULL; -} - -void mt32emu_play_msg_now(mt32emu_const_context context, mt32emu_bit32u msg) { - context->synth->playMsgNow(msg); -} - -void mt32emu_play_msg_on_part(mt32emu_const_context context, mt32emu_bit8u part, mt32emu_bit8u code, mt32emu_bit8u note, mt32emu_bit8u velocity) { - context->synth->playMsgOnPart(part, code, note, velocity); -} - -void mt32emu_play_sysex_now(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len) { - context->synth->playSysexNow(sysex, len); -} - -void mt32emu_write_sysex(mt32emu_const_context context, mt32emu_bit8u channel, const mt32emu_bit8u *sysex, mt32emu_bit32u len) { - context->synth->writeSysex(channel, sysex, len); -} - -void mt32emu_set_reverb_enabled(mt32emu_const_context context, const mt32emu_boolean reverb_enabled) { - context->synth->setReverbEnabled(reverb_enabled != MT32EMU_BOOL_FALSE); -} - -mt32emu_boolean mt32emu_is_reverb_enabled(mt32emu_const_context context) { - return context->synth->isReverbEnabled() ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE; -} - -void mt32emu_set_reverb_overridden(mt32emu_const_context context, const mt32emu_boolean reverb_overridden) { - context->synth->setReverbOverridden(reverb_overridden != MT32EMU_BOOL_FALSE); -} - -mt32emu_boolean mt32emu_is_reverb_overridden(mt32emu_const_context context) { - return context->synth->isReverbOverridden() ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE; -} - -void mt32emu_set_reverb_compatibility_mode(mt32emu_const_context context, const mt32emu_boolean mt32_compatible_mode) { - context->synth->setReverbCompatibilityMode(mt32_compatible_mode != MT32EMU_BOOL_FALSE); -} - -mt32emu_boolean mt32emu_is_mt32_reverb_compatibility_mode(mt32emu_const_context context) { - return context->synth->isMT32ReverbCompatibilityMode() ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE; -} - -mt32emu_boolean mt32emu_is_default_reverb_mt32_compatible(mt32emu_const_context context) { - return context->synth->isDefaultReverbMT32Compatible() ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE; -} - -void mt32emu_set_dac_input_mode(mt32emu_const_context context, const mt32emu_dac_input_mode mode) { - context->synth->setDACInputMode(static_cast(mode)); -} - -mt32emu_dac_input_mode mt32emu_get_dac_input_mode(mt32emu_const_context context) { - return static_cast(context->synth->getDACInputMode()); -} - -void mt32emu_set_midi_delay_mode(mt32emu_const_context context, const mt32emu_midi_delay_mode mode) { - context->synth->setMIDIDelayMode(static_cast(mode)); -} - -mt32emu_midi_delay_mode mt32emu_get_midi_delay_mode(mt32emu_const_context context) { - return static_cast(context->synth->getMIDIDelayMode()); -} - -void mt32emu_set_output_gain(mt32emu_const_context context, float gain) { - context->synth->setOutputGain(gain); -} - -float mt32emu_get_output_gain(mt32emu_const_context context) { - return context->synth->getOutputGain(); -} - -void mt32emu_set_reverb_output_gain(mt32emu_const_context context, float gain) { - context->synth->setReverbOutputGain(gain); -} - -float mt32emu_get_reverb_output_gain(mt32emu_const_context context) { - return context->synth->getReverbOutputGain(); -} - -void mt32emu_set_reversed_stereo_enabled(mt32emu_const_context context, const mt32emu_boolean enabled) { - context->synth->setReversedStereoEnabled(enabled != MT32EMU_BOOL_FALSE); -} - -mt32emu_boolean mt32emu_is_reversed_stereo_enabled(mt32emu_const_context context) { - return context->synth->isReversedStereoEnabled() ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE; -} - -void mt32emu_render_bit16s(mt32emu_const_context context, mt32emu_bit16s *stream, mt32emu_bit32u len) { - context->synth->render(stream, len); -} - -void mt32emu_render_float(mt32emu_const_context context, float *stream, mt32emu_bit32u len) { - context->synth->render(stream, len); -} - -void mt32emu_render_bit16s_streams(mt32emu_const_context context, const mt32emu_dac_output_bit16s_streams *streams, mt32emu_bit32u len) { - context->synth->renderStreams(*(const DACOutputStreams *)streams, len); -} - -void mt32emu_render_float_streams(mt32emu_const_context context, const mt32emu_dac_output_float_streams *streams, mt32emu_bit32u len) { - context->synth->renderStreams(*(const DACOutputStreams *)streams, len); -} - -mt32emu_boolean mt32emu_has_active_partials(mt32emu_const_context context) { - return context->synth->hasActivePartials() ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE; -} - -mt32emu_boolean mt32emu_is_active(mt32emu_const_context context) { - return context->synth->isActive() ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE; -} - -mt32emu_bit32u mt32emu_get_partial_count(mt32emu_const_context context) { - return context->synth->getPartialCount(); -} - -mt32emu_bit32u mt32emu_get_part_states(mt32emu_const_context context) { - return context->synth->getPartStates(); -} - -void mt32emu_get_partial_states(mt32emu_const_context context, mt32emu_bit8u *partial_states) { - context->synth->getPartialStates(partial_states); -} - -mt32emu_bit32u mt32emu_get_playing_notes(mt32emu_const_context context, mt32emu_bit8u part_number, mt32emu_bit8u *keys, mt32emu_bit8u *velocities) { - return context->synth->getPlayingNotes(part_number, keys, velocities); -} - -const char *mt32emu_get_patch_name(mt32emu_const_context context, mt32emu_bit8u part_number) { - return context->synth->getPatchName(part_number); -} - -void mt32emu_read_memory(mt32emu_const_context context, mt32emu_bit32u addr, mt32emu_bit32u len, mt32emu_bit8u *data) { - context->synth->readMemory(addr, len, data); -} - -} // extern "C" diff --git a/audio/softsynth/mt32/c_interface/c_interface.h b/audio/softsynth/mt32/c_interface/c_interface.h deleted file mode 100644 index a2bdcb1254..0000000000 --- a/audio/softsynth/mt32/c_interface/c_interface.h +++ /dev/null @@ -1,362 +0,0 @@ -/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 2.1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ - -#ifndef MT32EMU_C_INTERFACE_H -#define MT32EMU_C_INTERFACE_H - -#include - -#include "../globals.h" -#include "c_types.h" - -#undef MT32EMU_EXPORT -#define MT32EMU_EXPORT MT32EMU_EXPORT_ATTRIBUTE - -#ifdef __cplusplus -extern "C" { -#endif - -/* == Context-independent functions == */ - -/* === Interface handling === */ - -/** Returns mt32emu_service_i interface. */ -MT32EMU_EXPORT const mt32emu_service_i mt32emu_get_service_i(); - -#if MT32EMU_EXPORTS_TYPE == 2 -#undef MT32EMU_EXPORT -#define MT32EMU_EXPORT -#endif - -/** - * Returns the version ID of mt32emu_report_handler_i interface the library has been compiled with. - * This allows a client to fall-back gracefully instead of silently not receiving expected event reports. - */ -MT32EMU_EXPORT mt32emu_report_handler_version mt32emu_get_supported_report_handler_version(); - -/** - * Returns the version ID of mt32emu_midi_receiver_version_i interface the library has been compiled with. - * This allows a client to fall-back gracefully instead of silently not receiving expected MIDI messages. - */ -MT32EMU_EXPORT mt32emu_midi_receiver_version mt32emu_get_supported_midi_receiver_version(); - -/** - * Returns library version as an integer in format: 0x00MMmmpp, where: - * MM - major version number - * mm - minor version number - * pp - patch number - */ -MT32EMU_EXPORT mt32emu_bit32u mt32emu_get_library_version_int(); - -/** - * Returns library version as a C-string in format: "MAJOR.MINOR.PATCH". - */ -MT32EMU_EXPORT const char *mt32emu_get_library_version_string(); - -/** - * Returns output sample rate used in emulation of stereo analog circuitry of hardware units for particular analog_output_mode. - * See comment for mt32emu_analog_output_mode. - */ -MT32EMU_EXPORT mt32emu_bit32u mt32emu_get_stereo_output_samplerate(const mt32emu_analog_output_mode analog_output_mode); - -/* == Context-dependent functions == */ - -/** Initialises a new emulation context and installs custom report handler if non-NULL. */ -MT32EMU_EXPORT mt32emu_context mt32emu_create_context(mt32emu_report_handler_i report_handler, void *instance_data); - -/** Closes and destroys emulation context. */ -MT32EMU_EXPORT void mt32emu_free_context(mt32emu_context context); - -/** - * Adds new ROM identified by its SHA1 digest to the emulation context replacing previously added ROM of the same type if any. - * Argument sha1_digest can be NULL, in this case the digest will be computed using the actual ROM data. - * If sha1_digest is set to non-NULL, it is assumed being correct and will not be recomputed. - * This function doesn't immediately change the state of already opened synth. Newly added ROM will take effect upon next call of mt32emu_open_synth(). - * Returns positive value upon success. - */ -MT32EMU_EXPORT mt32emu_return_code mt32emu_add_rom_data(mt32emu_context context, const mt32emu_bit8u *data, size_t data_size, const mt32emu_sha1_digest *sha1_digest); - -/** - * Loads a ROM file, identify it by SHA1 digest, and adds it to the emulation context replacing previously added ROM of the same type if any. - * This function doesn't immediately change the state of already opened synth. Newly added ROM will take effect upon next call of mt32emu_open_synth(). - * Returns positive value upon success. - */ -MT32EMU_EXPORT mt32emu_return_code mt32emu_add_rom_file(mt32emu_context context, const char *filename); - -/** - * Fills in mt32emu_rom_info structure with identifiers and descriptions of control and PCM ROM files identified and added to the synth context. - * If one of the ROM files is not loaded and identified yet, NULL is returned in the corresponding fields of the mt32emu_rom_info structure. - */ -MT32EMU_EXPORT void mt32emu_get_rom_info(mt32emu_const_context context, mt32emu_rom_info *rom_info); - -/** - * Allows to override the default maximum number of partials playing simultaneously within the emulation session. - * This function doesn't immediately change the state of already opened synth. Newly set vale will take effect upon next call of mt32emu_open_synth(). - */ -MT32EMU_EXPORT void mt32emu_set_partial_count(mt32emu_context context, const mt32emu_bit32u partial_count); - -/** - * Allows to override the default mode for emulation of analogue circuitry of the hardware units within the emulation session. - * This function doesn't immediately change the state of already opened synth. Newly set vale will take effect upon next call of mt32emu_open_synth(). - */ -MT32EMU_EXPORT void mt32emu_set_analog_output_mode(mt32emu_context context, const mt32emu_analog_output_mode analog_output_mode); - -/** - * Prepares the emulation context to receive MIDI messages and produce output audio data using aforehand added set of ROMs, - * and optionally set the maximum partial count and the analog output mode. - * Returns MT32EMU_RC_OK upon success. - */ -MT32EMU_EXPORT mt32emu_return_code mt32emu_open_synth(mt32emu_const_context context); - -/** Closes the emulation context freeing allocated resources. Added ROMs remain unaffected and ready for reuse. */ -MT32EMU_EXPORT void mt32emu_close_synth(mt32emu_const_context context); - -/** Returns true if the synth is in completely initialized state, otherwise returns false. */ -MT32EMU_EXPORT mt32emu_boolean mt32emu_is_open(mt32emu_const_context context); - -/** - * Returns actual output sample rate used in emulation of stereo analog circuitry of hardware units. - * See comment for mt32emu_analog_output_mode. - */ -MT32EMU_EXPORT mt32emu_bit32u mt32emu_get_actual_stereo_output_samplerate(mt32emu_const_context context); - -/** All the enqueued events are processed by the synth immediately. */ -MT32EMU_EXPORT void mt32emu_flush_midi_queue(mt32emu_const_context context); - -/** - * Sets size of the internal MIDI event queue. The queue size is set to the minimum power of 2 that is greater or equal to the size specified. - * The queue is flushed before reallocation. - * Returns the actual queue size being used. - */ -MT32EMU_EXPORT mt32emu_bit32u mt32emu_set_midi_event_queue_size(mt32emu_const_context context, const mt32emu_bit32u queue_size); - -/** - * Installs custom MIDI receiver object intended for receiving MIDI messages generated by MIDI stream parser. - * MIDI stream parser is involved when functions mt32emu_parse_stream() and mt32emu_play_short_message() or the likes are called. - * By default, parsed short MIDI messages and System Exclusive messages are sent to the synth input MIDI queue. - * This function allows to override default behaviour. If midi_receiver argument is set to NULL, the default behaviour is restored. - */ -MT32EMU_EXPORT void mt32emu_set_midi_receiver(mt32emu_context context, mt32emu_midi_receiver_i midi_receiver, void *instance_data); - -/* Enqueues a MIDI event for subsequent playback. - * The MIDI event will be processed not before the specified timestamp. - * The timestamp is measured as the global rendered sample count since the synth was created (at the native sample rate 32000 Hz). - * The minimum delay involves emulation of the delay introduced while the event is transferred via MIDI interface - * and emulation of the MCU busy-loop while it frees partials for use by a new Poly. - * Calls from multiple threads must be synchronised, although, no synchronisation is required with the rendering thread. - * onMIDIQueueOverflow callback is invoked when the MIDI event queue is full and the message cannot be enqueued. - */ - -/** - * Parses a block of raw MIDI bytes and enqueues parsed MIDI messages for further processing ASAP. - * SysEx messages are allowed to be fragmented across several calls to this method. Running status is also handled for short messages. - * When a System Realtime MIDI message is parsed, onMIDISystemRealtime callback is invoked. - * NOTE: the total length of a SysEx message being fragmented shall not exceed MT32EMU_MAX_STREAM_BUFFER_SIZE (32768 bytes). - */ -MT32EMU_EXPORT void mt32emu_parse_stream(mt32emu_const_context context, const mt32emu_bit8u *stream, mt32emu_bit32u length); - -/** - * Parses a block of raw MIDI bytes and enqueues parsed MIDI messages to play at specified time. - * SysEx messages are allowed to be fragmented across several calls to this method. Running status is also handled for short messages. - * When a System Realtime MIDI message is parsed, onMIDISystemRealtime callback is invoked. - * NOTE: the total length of a SysEx message being fragmented shall not exceed MT32EMU_MAX_STREAM_BUFFER_SIZE (32768 bytes). - */ -MT32EMU_EXPORT void mt32emu_parse_stream_at(mt32emu_const_context context, const mt32emu_bit8u *stream, mt32emu_bit32u length, mt32emu_bit32u timestamp); - -/** - * Enqueues a single mt32emu_bit32u-encoded short MIDI message with full processing ASAP. - * The short MIDI message may contain no status byte, the running status is used in this case. - * When the argument is a System Realtime MIDI message, onMIDISystemRealtime callback is invoked. - */ -MT32EMU_EXPORT void mt32emu_play_short_message(mt32emu_const_context context, mt32emu_bit32u message); - -/** - * Enqueues a single mt32emu_bit32u-encoded short MIDI message to play at specified time with full processing. - * The short MIDI message may contain no status byte, the running status is used in this case. - * When the argument is a System Realtime MIDI message, onMIDISystemRealtime callback is invoked. - */ -MT32EMU_EXPORT void mt32emu_play_short_message_at(mt32emu_const_context context, mt32emu_bit32u message, mt32emu_bit32u timestamp); - -/** Enqueues a single short MIDI message to be processed ASAP. The message must contain a status byte. */ -MT32EMU_EXPORT mt32emu_return_code mt32emu_play_msg(mt32emu_const_context context, mt32emu_bit32u msg); -/** Enqueues a single well formed System Exclusive MIDI message to be processed ASAP. */ -MT32EMU_EXPORT mt32emu_return_code mt32emu_play_sysex(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len); - -/** Enqueues a single short MIDI message to play at specified time. The message must contain a status byte. */ -MT32EMU_EXPORT mt32emu_return_code mt32emu_play_msg_at(mt32emu_const_context context, mt32emu_bit32u msg, mt32emu_bit32u timestamp); -/** Enqueues a single well formed System Exclusive MIDI message to play at specified time. */ -MT32EMU_EXPORT mt32emu_return_code mt32emu_play_sysex_at(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len, mt32emu_bit32u timestamp); - -/* WARNING: - * The methods below don't ensure minimum 1-sample delay between sequential MIDI events, - * and a sequence of NoteOn and immediately succeeding NoteOff messages is always silent. - * A thread that invokes these methods must be explicitly synchronised with the thread performing sample rendering. - */ - -/** - * Sends a short MIDI message to the synth for immediate playback. The message must contain a status byte. - * See the WARNING above. - */ -MT32EMU_EXPORT void mt32emu_play_msg_now(mt32emu_const_context context, mt32emu_bit32u msg); -/** - * Sends unpacked short MIDI message to the synth for immediate playback. The message must contain a status byte. - * See the WARNING above. - */ -MT32EMU_EXPORT void mt32emu_play_msg_on_part(mt32emu_const_context context, mt32emu_bit8u part, mt32emu_bit8u code, mt32emu_bit8u note, mt32emu_bit8u velocity); - -/** - * Sends a single well formed System Exclusive MIDI message for immediate processing. The length is in bytes. - * See the WARNING above. - */ -MT32EMU_EXPORT void mt32emu_play_sysex_now(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len); -/** - * Sends inner body of a System Exclusive MIDI message for direct processing. The length is in bytes. - * See the WARNING above. - */ -MT32EMU_EXPORT void mt32emu_write_sysex(mt32emu_const_context context, mt32emu_bit8u channel, const mt32emu_bit8u *sysex, mt32emu_bit32u len); - -/** Allows to disable wet reverb output altogether. */ -MT32EMU_EXPORT void mt32emu_set_reverb_enabled(mt32emu_const_context context, const mt32emu_boolean reverb_enabled); -/** Returns whether wet reverb output is enabled. */ -MT32EMU_EXPORT mt32emu_boolean mt32emu_is_reverb_enabled(mt32emu_const_context context); -/** - * Sets override reverb mode. In this mode, emulation ignores sysexes (or the related part of them) which control the reverb parameters. - * This mode is in effect until it is turned off. When the synth is re-opened, the override mode is unchanged but the state - * of the reverb model is reset to default. - */ -MT32EMU_EXPORT void mt32emu_set_reverb_overridden(mt32emu_const_context context, const mt32emu_boolean reverb_overridden); -/** Returns whether reverb settings are overridden. */ -MT32EMU_EXPORT mt32emu_boolean mt32emu_is_reverb_overridden(mt32emu_const_context context); -/** - * Forces reverb model compatibility mode. By default, the compatibility mode corresponds to the used control ROM version. - * Invoking this method with the argument set to true forces emulation of old MT-32 reverb circuit. - * When the argument is false, emulation of the reverb circuit used in new generation of MT-32 compatible modules is enforced - * (these include CM-32L and LAPC-I). - */ -MT32EMU_EXPORT void mt32emu_set_reverb_compatibility_mode(mt32emu_const_context context, const mt32emu_boolean mt32_compatible_mode); -/** Returns whether reverb is in old MT-32 compatibility mode. */ -MT32EMU_EXPORT mt32emu_boolean mt32emu_is_mt32_reverb_compatibility_mode(mt32emu_const_context context); -/** Returns whether default reverb compatibility mode is the old MT-32 compatibility mode. */ -MT32EMU_EXPORT mt32emu_boolean mt32emu_is_default_reverb_mt32_compatible(mt32emu_const_context context); - -/** Sets new DAC input mode. See mt32emu_dac_input_mode for details. */ -MT32EMU_EXPORT void mt32emu_set_dac_input_mode(mt32emu_const_context context, const mt32emu_dac_input_mode mode); -/** Returns current DAC input mode. See mt32emu_dac_input_mode for details. */ -MT32EMU_EXPORT mt32emu_dac_input_mode mt32emu_get_dac_input_mode(mt32emu_const_context context); - -/** Sets new MIDI delay mode. See mt32emu_midi_delay_mode for details. */ -MT32EMU_EXPORT void mt32emu_set_midi_delay_mode(mt32emu_const_context context, const mt32emu_midi_delay_mode mode); -/** Returns current MIDI delay mode. See mt32emu_midi_delay_mode for details. */ -MT32EMU_EXPORT mt32emu_midi_delay_mode mt32emu_get_midi_delay_mode(mt32emu_const_context context); - -/** - * Sets output gain factor for synth output channels. Applied to all output samples and unrelated with the synth's Master volume, - * it rather corresponds to the gain of the output analog circuitry of the hardware units. However, together with mt32emu_set_reverb_output_gain() - * it offers to the user a capability to control the gain of reverb and non-reverb output channels independently. - * Ignored in MT32EMU_DAC_PURE mode. - */ -MT32EMU_EXPORT void mt32emu_set_output_gain(mt32emu_const_context context, float gain); -/** Returns current output gain factor for synth output channels. */ -MT32EMU_EXPORT float mt32emu_get_output_gain(mt32emu_const_context context); - -/** - * Sets output gain factor for the reverb wet output channels. It rather corresponds to the gain of the output - * analog circuitry of the hardware units. However, together with mt32emu_set_output_gain() it offers to the user a capability - * to control the gain of reverb and non-reverb output channels independently. - * - * Note: We're currently emulate CM-32L/CM-64 reverb quite accurately and the reverb output level closely - * corresponds to the level of digital capture. Although, according to the CM-64 PCB schematic, - * there is a difference in the reverb analogue circuit, and the resulting output gain is 0.68 - * of that for LA32 analogue output. This factor is applied to the reverb output gain. - * Ignored in MT32EMU_DAC_PURE mode. - */ -MT32EMU_EXPORT void mt32emu_set_reverb_output_gain(mt32emu_const_context context, float gain); -/** Returns current output gain factor for reverb wet output channels. */ -MT32EMU_EXPORT float mt32emu_get_reverb_output_gain(mt32emu_const_context context); - -/** Swaps left and right output channels. */ -MT32EMU_EXPORT void mt32emu_set_reversed_stereo_enabled(mt32emu_const_context context, const mt32emu_boolean enabled); -/** Returns whether left and right output channels are swapped. */ -MT32EMU_EXPORT mt32emu_boolean mt32emu_is_reversed_stereo_enabled(mt32emu_const_context context); - -/** - * Renders samples to the specified output stream as if they were sampled at the analog stereo output. - * When mt32emu_analog_output_mode is set to ACCURATE (OVERSAMPLED), the output signal is upsampled to 48 (96) kHz in order - * to retain emulation accuracy in whole audible frequency spectra. Otherwise, native digital signal sample rate is retained. - * mt32emu_get_actual_stereo_output_samplerate() can be used to query actual sample rate of the output signal. - * The length is in frames, not bytes (in 16-bit stereo, one frame is 4 bytes). Uses NATIVE byte ordering. - */ -MT32EMU_EXPORT void mt32emu_render_bit16s(mt32emu_const_context context, mt32emu_bit16s *stream, mt32emu_bit32u len); -/** Same as above but outputs to a float stereo stream. */ -MT32EMU_EXPORT void mt32emu_render_float(mt32emu_const_context context, float *stream, mt32emu_bit32u len); - -/** - * Renders samples to the specified output streams as if they appeared at the DAC entrance. - * No further processing performed in analog circuitry emulation is applied to the signal. - * NULL may be specified in place of any or all of the stream buffers to skip it. - * The length is in samples, not bytes. Uses NATIVE byte ordering. - */ -MT32EMU_EXPORT void mt32emu_render_bit16s_streams(mt32emu_const_context context, const mt32emu_dac_output_bit16s_streams *streams, mt32emu_bit32u len); -/** Same as above but outputs to float streams. */ -MT32EMU_EXPORT void mt32emu_render_float_streams(mt32emu_const_context context, const mt32emu_dac_output_float_streams *streams, mt32emu_bit32u len); - -/** Returns true when there is at least one active partial, otherwise false. */ -MT32EMU_EXPORT mt32emu_boolean mt32emu_has_active_partials(mt32emu_const_context context); - -/** Returns true if mt32emu_has_active_partials() returns true, or reverb is (somewhat unreliably) detected as being active. */ -MT32EMU_EXPORT mt32emu_boolean mt32emu_is_active(mt32emu_const_context context); - -/** Returns the maximum number of partials playing simultaneously. */ -MT32EMU_EXPORT mt32emu_bit32u mt32emu_get_partial_count(mt32emu_const_context context); - -/** - * Returns current states of all the parts as a bit set. The least significant bit corresponds to the state of part 1, - * total of 9 bits hold the states of all the parts. If the returned bit for a part is set, there is at least one active - * non-releasing partial playing on this part. This info is useful in emulating behaviour of LCD display of the hardware units. - */ -MT32EMU_EXPORT mt32emu_bit32u mt32emu_get_part_states(mt32emu_const_context context); - -/** - * Fills in current states of all the partials into the array provided. Each byte in the array holds states of 4 partials - * starting from the least significant bits. The state of each partial is packed in a pair of bits. - * The array must be large enough to accommodate states of all the partials. - * @see getPartialCount() - */ -MT32EMU_EXPORT void mt32emu_get_partial_states(mt32emu_const_context context, mt32emu_bit8u *partial_states); - -/** - * Fills in information about currently playing notes on the specified part into the arrays provided. The arrays must be large enough - * to accommodate data for all the playing notes. The maximum number of simultaneously playing notes cannot exceed the number of partials. - * Argument partNumber should be 0..7 for Part 1..8, or 8 for Rhythm. - * Returns the number of currently playing notes on the specified part. - */ -MT32EMU_EXPORT mt32emu_bit32u mt32emu_get_playing_notes(mt32emu_const_context context, mt32emu_bit8u part_number, mt32emu_bit8u *keys, mt32emu_bit8u *velocities); - -/** - * Returns name of the patch set on the specified part. - * Argument partNumber should be 0..7 for Part 1..8, or 8 for Rhythm. - */ -MT32EMU_EXPORT const char *mt32emu_get_patch_name(mt32emu_const_context context, mt32emu_bit8u part_number); - -/** Stores internal state of emulated synth into an array provided (as it would be acquired from hardware). */ -MT32EMU_EXPORT void mt32emu_read_memory(mt32emu_const_context context, mt32emu_bit32u addr, mt32emu_bit32u len, mt32emu_bit8u *data); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* #ifndef MT32EMU_C_INTERFACE_H */ diff --git a/audio/softsynth/mt32/c_interface/c_types.h b/audio/softsynth/mt32/c_interface/c_types.h deleted file mode 100644 index 3cd8744235..0000000000 --- a/audio/softsynth/mt32/c_interface/c_types.h +++ /dev/null @@ -1,298 +0,0 @@ -/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 2.1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ - -#ifndef MT32EMU_C_TYPES_H -#define MT32EMU_C_TYPES_H - -#include -#include - -#include "../globals.h" - -#define MT32EMU_C_ENUMERATIONS -#include "../Enumerations.h" -#undef MT32EMU_C_ENUMERATIONS - -typedef unsigned int mt32emu_bit32u; -typedef signed int mt32emu_bit32s; -typedef unsigned short int mt32emu_bit16u; -typedef signed short int mt32emu_bit16s; -typedef unsigned char mt32emu_bit8u; -typedef signed char mt32emu_bit8s; - -typedef char mt32emu_sha1_digest[41]; - -typedef enum { - MT32EMU_BOOL_FALSE, MT32EMU_BOOL_TRUE -} mt32emu_boolean; - -typedef enum { - /* Operation completed normally. */ - MT32EMU_RC_OK = 0, - MT32EMU_RC_ADDED_CONTROL_ROM = 1, - MT32EMU_RC_ADDED_PCM_ROM = 2, - - /* Definite error occurred. */ - MT32EMU_RC_ROM_NOT_IDENTIFIED = -1, - MT32EMU_RC_FILE_NOT_FOUND = -2, - MT32EMU_RC_FILE_NOT_LOADED = -3, - MT32EMU_RC_MISSING_ROMS = -4, - MT32EMU_RC_NOT_OPENED = -5, - MT32EMU_RC_QUEUE_FULL = -6, - - /* Undefined error occurred. */ - MT32EMU_RC_FAILED = -100 -} mt32emu_return_code; - -/** Emulation context */ -typedef struct mt32emu_data *mt32emu_context; -typedef const struct mt32emu_data *mt32emu_const_context; - -/* Convenience aliases */ -#ifndef __cplusplus -typedef enum mt32emu_analog_output_mode mt32emu_analog_output_mode; -typedef enum mt32emu_dac_input_mode mt32emu_dac_input_mode; -typedef enum mt32emu_midi_delay_mode mt32emu_midi_delay_mode; -typedef enum mt32emu_partial_state mt32emu_partial_state; -#endif - -/** Contains identifiers and descriptions of ROM files being used. */ -typedef struct { - const char *control_rom_id; - const char *control_rom_description; - const char *control_rom_sha1_digest; - const char *pcm_rom_id; - const char *pcm_rom_description; - const char *pcm_rom_sha1_digest; -} mt32emu_rom_info; - -/** Set of multiplexed output bit16s streams appeared at the DAC entrance. */ -typedef struct { - mt32emu_bit16s *nonReverbLeft; - mt32emu_bit16s *nonReverbRight; - mt32emu_bit16s *reverbDryLeft; - mt32emu_bit16s *reverbDryRight; - mt32emu_bit16s *reverbWetLeft; - mt32emu_bit16s *reverbWetRight; -} mt32emu_dac_output_bit16s_streams; - -/** Set of multiplexed output float streams appeared at the DAC entrance. */ -typedef struct { - float *nonReverbLeft; - float *nonReverbRight; - float *reverbDryLeft; - float *reverbDryRight; - float *reverbWetLeft; - float *reverbWetRight; -} mt32emu_dac_output_float_streams; - -/* === Interface handling === */ - -/** Report handler interface versions */ -typedef enum { - MT32EMU_REPORT_HANDLER_VERSION_0 = 0, - MT32EMU_REPORT_HANDLER_VERSION_CURRENT = MT32EMU_REPORT_HANDLER_VERSION_0 -} mt32emu_report_handler_version; - -/** MIDI receiver interface versions */ -typedef enum { - MT32EMU_MIDI_RECEIVER_VERSION_0 = 0, - MT32EMU_MIDI_RECEIVER_VERSION_CURRENT = MT32EMU_MIDI_RECEIVER_VERSION_0 -} mt32emu_midi_receiver_version; - -/** Synth interface versions */ -typedef enum { - MT32EMU_SERVICE_VERSION_0 = 0, - MT32EMU_SERVICE_VERSION_CURRENT = MT32EMU_SERVICE_VERSION_0 -} mt32emu_service_version; - -/* === Report Handler Interface === */ - -typedef union mt32emu_report_handler_i mt32emu_report_handler_i; - -/** Interface for handling reported events (initial version) */ -typedef struct { - /** Returns the actual interface version ID */ - mt32emu_report_handler_version (*getVersionID)(mt32emu_report_handler_i i); - - /** Callback for debug messages, in vprintf() format */ - void (*printDebug)(void *instance_data, const char *fmt, va_list list); - /** Callbacks for reporting errors */ - void (*onErrorControlROM)(void *instance_data); - void (*onErrorPCMROM)(void *instance_data); - /** Callback for reporting about displaying a new custom message on LCD */ - void (*showLCDMessage)(void *instance_data, const char *message); - /** Callback for reporting actual processing of a MIDI message */ - void (*onMIDIMessagePlayed)(void *instance_data); - /** - * Callback for reporting an overflow of the input MIDI queue. - * Returns MT32EMU_BOOL_TRUE if a recovery action was taken - * and yet another attempt to enqueue the MIDI event is desired. - */ - mt32emu_boolean (*onMIDIQueueOverflow)(void *instance_data); - /** - * Callback invoked when a System Realtime MIDI message is detected in functions - * mt32emu_parse_stream and mt32emu_play_short_message and the likes. - */ - void (*onMIDISystemRealtime)(void *instance_data, mt32emu_bit8u system_realtime); - /** Callbacks for reporting system events */ - void (*onDeviceReset)(void *instance_data); - void (*onDeviceReconfig)(void *instance_data); - /** Callbacks for reporting changes of reverb settings */ - void (*onNewReverbMode)(void *instance_data, mt32emu_bit8u mode); - void (*onNewReverbTime)(void *instance_data, mt32emu_bit8u time); - void (*onNewReverbLevel)(void *instance_data, mt32emu_bit8u level); - /** Callbacks for reporting various information */ - void (*onPolyStateChanged)(void *instance_data, mt32emu_bit8u part_num); - void (*onProgramChanged)(void *instance_data, mt32emu_bit8u part_num, const char *sound_group_name, const char *patch_name); -} mt32emu_report_handler_i_v0; - -/** - * Extensible interface for handling reported events. - * Union intended to view an interface of any subsequent version as any parent interface not requiring a cast. - * Elements are to be addressed using the tag of the interface version when they were introduced. - */ -union mt32emu_report_handler_i { - const mt32emu_report_handler_i_v0 *v0; -}; - -/* === MIDI Receiver Interface === */ - -typedef union mt32emu_midi_receiver_i mt32emu_midi_receiver_i; - -/** Interface for receiving MIDI messages generated by MIDI stream parser (initial version) */ -typedef struct { - /** Returns the actual interface version ID */ - mt32emu_midi_receiver_version (*getVersionID)(mt32emu_midi_receiver_i i); - - /** Invoked when a complete short MIDI message is parsed in the input MIDI stream. */ - void (*handleShortMessage)(void *instance_data, const mt32emu_bit32u message); - - /** Invoked when a complete well-formed System Exclusive MIDI message is parsed in the input MIDI stream. */ - void (*handleSysex)(void *instance_data, const mt32emu_bit8u stream[], const mt32emu_bit32u length); - - /** Invoked when a System Realtime MIDI message is parsed in the input MIDI stream. */ - void (*handleSystemRealtimeMessage)(void *instance_data, const mt32emu_bit8u realtime); -} mt32emu_midi_receiver_i_v0; - -/** - * Extensible interface for receiving MIDI messages. - * Union intended to view an interface of any subsequent version as any parent interface not requiring a cast. - * Elements are to be addressed using the tag of the interface version when they were introduced. - */ -union mt32emu_midi_receiver_i { - const mt32emu_midi_receiver_i_v0 *v0; -}; - -/* === Service Interface === */ - -typedef union mt32emu_service_i mt32emu_service_i; - -/** - * Basic interface that defines all the library services (initial version). - * The members closely resemble C functions declared in c_interface.h, and the intention is to provide for easier - * access when the library is dynamically loaded in run-time, e.g. as a plugin. This way the client only needs - * to bind to mt32emu_get_service_i() function instead of binding to each function it needs to use. - * See c_interface.h for parameter description. - */ -typedef struct { - /** Returns the actual interface version ID */ - mt32emu_service_version (*getVersionID)(mt32emu_service_i i); - mt32emu_report_handler_version (*getSupportedReportHandlerVersionID)(); - mt32emu_midi_receiver_version (*getSupportedMIDIReceiverVersionID)(); - - mt32emu_bit32u (*getLibraryVersionInt)(); - const char *(*getLibraryVersionString)(); - - mt32emu_bit32u (*getStereoOutputSamplerate)(const mt32emu_analog_output_mode analog_output_mode); - - mt32emu_context (*createContext)(mt32emu_report_handler_i report_handler, void *instance_data); - void (*freeContext)(mt32emu_context context); - mt32emu_return_code (*addROMData)(mt32emu_context context, const mt32emu_bit8u *data, size_t data_size, const mt32emu_sha1_digest *sha1_digest); - mt32emu_return_code (*addROMFile)(mt32emu_context context, const char *filename); - void (*getROMInfo)(mt32emu_const_context context, mt32emu_rom_info *rom_info); - void (*setPartialCount)(mt32emu_context context, const mt32emu_bit32u partial_count); - void (*setAnalogOutputMode)(mt32emu_context context, const mt32emu_analog_output_mode analog_output_mode); - mt32emu_return_code (*openSynth)(mt32emu_const_context context); - void (*closeSynth)(mt32emu_const_context context); - mt32emu_boolean (*isOpen)(mt32emu_const_context context); - mt32emu_bit32u (*getActualStereoOutputSamplerate)(mt32emu_const_context context); - void (*flushMIDIQueue)(mt32emu_const_context context); - mt32emu_bit32u (*setMIDIEventQueueSize)(mt32emu_const_context context, const mt32emu_bit32u queue_size); - void (*setMIDIReceiver)(mt32emu_context context, mt32emu_midi_receiver_i midi_receiver, void *instance_data); - - void (*parseStream)(mt32emu_const_context context, const mt32emu_bit8u *stream, mt32emu_bit32u length); - void (*parseStream_At)(mt32emu_const_context context, const mt32emu_bit8u *stream, mt32emu_bit32u length, mt32emu_bit32u timestamp); - void (*playShortMessage)(mt32emu_const_context context, mt32emu_bit32u message); - void (*playShortMessageAt)(mt32emu_const_context context, mt32emu_bit32u message, mt32emu_bit32u timestamp); - mt32emu_return_code (*playMsg)(mt32emu_const_context context, mt32emu_bit32u msg); - mt32emu_return_code (*playSysex)(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len); - mt32emu_return_code (*playMsgAt)(mt32emu_const_context context, mt32emu_bit32u msg, mt32emu_bit32u timestamp); - mt32emu_return_code (*playSysexAt)(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len, mt32emu_bit32u timestamp); - - void (*playMsgNow)(mt32emu_const_context context, mt32emu_bit32u msg); - void (*playMsgOnPart)(mt32emu_const_context context, mt32emu_bit8u part, mt32emu_bit8u code, mt32emu_bit8u note, mt32emu_bit8u velocity); - void (*playSysexNow)(mt32emu_const_context context, const mt32emu_bit8u *sysex, mt32emu_bit32u len); - void (*writeSysex)(mt32emu_const_context context, mt32emu_bit8u channel, const mt32emu_bit8u *sysex, mt32emu_bit32u len); - - void (*setReverbEnabled)(mt32emu_const_context context, const mt32emu_boolean reverb_enabled); - mt32emu_boolean (*isReverbEnabled)(mt32emu_const_context context); - void (*setReverbOverridden)(mt32emu_const_context context, const mt32emu_boolean reverb_overridden); - mt32emu_boolean (*isReverbOverridden)(mt32emu_const_context context); - void (*setReverbCompatibilityMode)(mt32emu_const_context context, const mt32emu_boolean mt32_compatible_mode); - mt32emu_boolean (*isMT32ReverbCompatibilityMode)(mt32emu_const_context context); - mt32emu_boolean (*isDefaultReverbMT32Compatible)(mt32emu_const_context context); - - void (*setDACInputMode)(mt32emu_const_context context, const mt32emu_dac_input_mode mode); - mt32emu_dac_input_mode (*getDACInputMode)(mt32emu_const_context context); - - void (*setMIDIDelayMode)(mt32emu_const_context context, const mt32emu_midi_delay_mode mode); - mt32emu_midi_delay_mode (*getMIDIDelayMode)(mt32emu_const_context context); - - void (*setOutputGain)(mt32emu_const_context context, float gain); - float (*getOutputGain)(mt32emu_const_context context); - void (*setReverbOutputGain)(mt32emu_const_context context, float gain); - float (*getReverbOutputGain)(mt32emu_const_context context); - - void (*setReversedStereoEnabled)(mt32emu_const_context context, const mt32emu_boolean enabled); - mt32emu_boolean (*isReversedStereoEnabled)(mt32emu_const_context context); - - void (*renderBit16s)(mt32emu_const_context context, mt32emu_bit16s *stream, mt32emu_bit32u len); - void (*renderFloat)(mt32emu_const_context context, float *stream, mt32emu_bit32u len); - void (*renderBit16sStreams)(mt32emu_const_context context, const mt32emu_dac_output_bit16s_streams *streams, mt32emu_bit32u len); - void (*renderFloatStreams)(mt32emu_const_context context, const mt32emu_dac_output_float_streams *streams, mt32emu_bit32u len); - - mt32emu_boolean (*hasActivePartials)(mt32emu_const_context context); - mt32emu_boolean (*isActive)(mt32emu_const_context context); - mt32emu_bit32u (*getPartialCount)(mt32emu_const_context context); - mt32emu_bit32u (*getPartStates)(mt32emu_const_context context); - void (*getPartialStates)(mt32emu_const_context context, mt32emu_bit8u *partial_states); - mt32emu_bit32u (*getPlayingNotes)(mt32emu_const_context context, mt32emu_bit8u part_number, mt32emu_bit8u *keys, mt32emu_bit8u *velocities); - const char *(*getPatchName)(mt32emu_const_context context, mt32emu_bit8u part_number); - void (*readMemory)(mt32emu_const_context context, mt32emu_bit32u addr, mt32emu_bit32u len, mt32emu_bit8u *data); -} mt32emu_service_i_v0; - -/** - * Extensible interface for all the library services. - * Union intended to view an interface of any subsequent version as any parent interface not requiring a cast. - * Elements are to be addressed using the tag of the interface version when they were introduced. - */ -union mt32emu_service_i { - const mt32emu_service_i_v0 *v0; -}; - -#endif /* #ifndef MT32EMU_C_TYPES_H */ diff --git a/audio/softsynth/mt32/c_interface/cpp_interface.h b/audio/softsynth/mt32/c_interface/cpp_interface.h deleted file mode 100644 index 41ddebcc02..0000000000 --- a/audio/softsynth/mt32/c_interface/cpp_interface.h +++ /dev/null @@ -1,436 +0,0 @@ -/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 2.1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ - -#ifndef MT32EMU_CPP_INTERFACE_H -#define MT32EMU_CPP_INTERFACE_H - -#include - -#include "../globals.h" -#include "c_types.h" - -#include "../Types.h" -#include "../Enumerations.h" - -#if MT32EMU_API_TYPE == 2 - -#define mt32emu_get_supported_report_handler_version i.v0->getSupportedReportHandlerVersionID -#define mt32emu_get_supported_midi_receiver_version i.v0->getSupportedMIDIReceiverVersionID -#define mt32emu_get_library_version_int i.v0->getLibraryVersionInt -#define mt32emu_get_library_version_string i.v0->getLibraryVersionString -#define mt32emu_get_stereo_output_samplerate i.v0->getStereoOutputSamplerate -#define mt32emu_create_context i.v0->createContext -#define mt32emu_free_context i.v0->freeContext -#define mt32emu_add_rom_data i.v0->addROMData -#define mt32emu_add_rom_file i.v0->addROMFile -#define mt32emu_get_rom_info i.v0->getROMInfo -#define mt32emu_set_partial_count i.v0->setPartialCount -#define mt32emu_set_analog_output_mode i.v0->setAnalogOutputMode -#define mt32emu_open_synth i.v0->openSynth -#define mt32emu_close_synth i.v0->closeSynth -#define mt32emu_is_open i.v0->isOpen -#define mt32emu_get_actual_stereo_output_samplerate i.v0->getActualStereoOutputSamplerate -#define mt32emu_flush_midi_queue i.v0->flushMIDIQueue -#define mt32emu_set_midi_event_queue_size i.v0->setMIDIEventQueueSize -#define mt32emu_set_midi_receiver i.v0->setMIDIReceiver -#define mt32emu_parse_stream i.v0->parseStream -#define mt32emu_parse_stream_at i.v0->parseStream_At -#define mt32emu_play_short_message i.v0->playShortMessage -#define mt32emu_play_short_message_at i.v0->playShortMessageAt -#define mt32emu_play_msg i.v0->playMsg -#define mt32emu_play_sysex i.v0->playSysex -#define mt32emu_play_msg_at i.v0->playMsgAt -#define mt32emu_play_sysex_at i.v0->playSysexAt -#define mt32emu_play_msg_now i.v0->playMsgNow -#define mt32emu_play_msg_on_part i.v0->playMsgOnPart -#define mt32emu_play_sysex_now i.v0->playSysexNow -#define mt32emu_write_sysex i.v0->writeSysex -#define mt32emu_set_reverb_enabled i.v0->setReverbEnabled -#define mt32emu_is_reverb_enabled i.v0->isReverbEnabled -#define mt32emu_set_reverb_overridden i.v0->setReverbOverridden -#define mt32emu_is_reverb_overridden i.v0->isReverbOverridden -#define mt32emu_set_reverb_compatibility_mode i.v0->setReverbCompatibilityMode -#define mt32emu_is_mt32_reverb_compatibility_mode i.v0->isMT32ReverbCompatibilityMode -#define mt32emu_is_default_reverb_mt32_compatible i.v0->isDefaultReverbMT32Compatible -#define mt32emu_set_dac_input_mode i.v0->setDACInputMode -#define mt32emu_get_dac_input_mode i.v0->getDACInputMode -#define mt32emu_set_midi_delay_mode i.v0->setMIDIDelayMode -#define mt32emu_get_midi_delay_mode i.v0->getMIDIDelayMode -#define mt32emu_set_output_gain i.v0->setOutputGain -#define mt32emu_get_output_gain i.v0->getOutputGain -#define mt32emu_set_reverb_output_gain i.v0->setReverbOutputGain -#define mt32emu_get_reverb_output_gain i.v0->getReverbOutputGain -#define mt32emu_set_reversed_stereo_enabled i.v0->setReversedStereoEnabled -#define mt32emu_is_reversed_stereo_enabled i.v0->isReversedStereoEnabled -#define mt32emu_render_bit16s i.v0->renderBit16s -#define mt32emu_render_float i.v0->renderFloat -#define mt32emu_render_bit16s_streams i.v0->renderBit16sStreams -#define mt32emu_render_float_streams i.v0->renderFloatStreams -#define mt32emu_has_active_partials i.v0->hasActivePartials -#define mt32emu_is_active i.v0->isActive -#define mt32emu_get_partial_count i.v0->getPartialCount -#define mt32emu_get_part_states i.v0->getPartStates -#define mt32emu_get_partial_states i.v0->getPartialStates -#define mt32emu_get_playing_notes i.v0->getPlayingNotes -#define mt32emu_get_patch_name i.v0->getPatchName -#define mt32emu_read_memory i.v0->readMemory - -#else // #if MT32EMU_API_TYPE == 2 - -#include "c_interface.h" - -#endif // #if MT32EMU_API_TYPE == 2 - -namespace MT32Emu { - -namespace CppInterfaceImpl { - -static const mt32emu_report_handler_i NULL_REPORT_HANDLER = { NULL }; -static mt32emu_report_handler_i getReportHandlerThunk(); -static mt32emu_midi_receiver_i getMidiReceiverThunk(); - -} - -/* - * The classes below correspond to the interfaces defined in c_types.h and provided for convenience when using C++. - * The approach used makes no assumption of any internal class data memory layout, since the C++ standard does not - * provide any detail in this area and leaves it up to the implementation. Therefore, this way portability is guaranteed, - * despite the implementation may be a little inefficient. - * See c_types.h and c_interface.h for description of the corresponding interface methods. - */ - -// Defines the interface for handling reported events. -// Corresponds to the current version of mt32emu_report_handler_i interface. -class ReportHandler { -public: - virtual void printDebug(const char *fmt, va_list list) = 0; - virtual void onErrorControlROM() = 0; - virtual void onErrorPCMROM() = 0; - virtual void showLCDMessage(const char *message) = 0; - virtual void onMIDIMessagePlayed() = 0; - virtual bool onMIDIQueueOverflow() = 0; - virtual void onMIDISystemRealtime(Bit8u system_realtime) = 0; - virtual void onDeviceReset() = 0; - virtual void onDeviceReconfig() = 0; - virtual void onNewReverbMode(Bit8u mode) = 0; - virtual void onNewReverbTime(Bit8u time) = 0; - virtual void onNewReverbLevel(Bit8u level) = 0; - virtual void onPolyStateChanged(Bit8u part_num) = 0; - virtual void onProgramChanged(Bit8u part_num, const char *sound_group_name, const char *patch_name) = 0; - -protected: - ~ReportHandler() {} -}; - -// Defines the interface for receiving MIDI messages generated by MIDI stream parser. -// Corresponds to the current version of mt32emu_midi_receiver_i interface. -class MidiReceiver { -public: - virtual void handleShortMessage(const Bit32u message) = 0; - virtual void handleSysex(const Bit8u stream[], const Bit32u length) = 0; - virtual void handleSystemRealtimeMessage(const Bit8u realtime) = 0; - -protected: - ~MidiReceiver() {} -}; - -// Defines all the library services. -// Corresponds to the current version of mt32emu_service_i interface. -class Service { -public: -#if MT32EMU_API_TYPE == 2 - explicit Service(mt32emu_service_i interface, mt32emu_context context = NULL) : i(interface), c(context) {} -#else - explicit Service(mt32emu_context context = NULL) : c(context) {} -#endif - ~Service() { if (c != NULL) mt32emu_free_context(c); } - - // Context-independent methods - -#if MT32EMU_API_TYPE == 2 - mt32emu_service_version getVersionID() { return i.v0->getVersionID(i); } -#endif - mt32emu_report_handler_version getSupportedReportHandlerVersionID() { return mt32emu_get_supported_report_handler_version(); } - mt32emu_midi_receiver_version getSupportedMIDIReceiverVersionID() { return mt32emu_get_supported_midi_receiver_version(); } - - Bit32u getLibraryVersionInt() { return mt32emu_get_library_version_int(); } - const char *getLibraryVersionString() { return mt32emu_get_library_version_string(); } - - Bit32u getStereoOutputSamplerate(const AnalogOutputMode analog_output_mode) { return mt32emu_get_stereo_output_samplerate(static_cast(analog_output_mode)); } - - // Context-dependent methods - - mt32emu_context getContext() { return c; } - void createContext(mt32emu_report_handler_i report_handler = CppInterfaceImpl::NULL_REPORT_HANDLER, void *instance_data = NULL) { freeContext(); c = mt32emu_create_context(report_handler, instance_data); } - void createContext(ReportHandler &report_handler) { createContext(CppInterfaceImpl::getReportHandlerThunk(), &report_handler); } - void freeContext() { if (c != NULL) { mt32emu_free_context(c); c = NULL; } } - mt32emu_return_code addROMData(const Bit8u *data, size_t data_size, const mt32emu_sha1_digest *sha1_digest = NULL) { return mt32emu_add_rom_data(c, data, data_size, sha1_digest); } - mt32emu_return_code addROMFile(const char *filename) { return mt32emu_add_rom_file(c, filename); } - void getROMInfo(mt32emu_rom_info *rom_info) { mt32emu_get_rom_info(c, rom_info); } - void setPartialCount(const Bit32u partial_count) { mt32emu_set_partial_count(c, partial_count); } - void setAnalogOutputMode(const AnalogOutputMode analog_output_mode) { mt32emu_set_analog_output_mode(c, static_cast(analog_output_mode)); } - mt32emu_return_code openSynth() { return mt32emu_open_synth(c); } - void closeSynth() { mt32emu_close_synth(c); } - bool isOpen() { return mt32emu_is_open(c) != MT32EMU_BOOL_FALSE; } - Bit32u getActualStereoOutputSamplerate() { return mt32emu_get_actual_stereo_output_samplerate(c); } - void flushMIDIQueue() { mt32emu_flush_midi_queue(c); } - Bit32u setMIDIEventQueueSize(const Bit32u queue_size) { return mt32emu_set_midi_event_queue_size(c, queue_size); } - void setMIDIReceiver(mt32emu_midi_receiver_i midi_receiver, void *instance_data) { mt32emu_set_midi_receiver(c, midi_receiver, instance_data); } - void setMIDIReceiver(MidiReceiver &midi_receiver) { setMIDIReceiver(CppInterfaceImpl::getMidiReceiverThunk(), &midi_receiver); } - - void parseStream(const Bit8u *stream, Bit32u length) { mt32emu_parse_stream(c, stream, length); } - void parseStream_At(const Bit8u *stream, Bit32u length, Bit32u timestamp) { mt32emu_parse_stream_at(c, stream, length, timestamp); } - void playShortMessage(Bit32u message) { mt32emu_play_short_message(c, message); } - void playShortMessageAt(Bit32u message, Bit32u timestamp) { mt32emu_play_short_message_at(c, message, timestamp); } - mt32emu_return_code playMsg(Bit32u msg) { return mt32emu_play_msg(c, msg); } - mt32emu_return_code playSysex(const Bit8u *sysex, Bit32u len) { return mt32emu_play_sysex(c, sysex, len); } - mt32emu_return_code playMsgAt(Bit32u msg, Bit32u timestamp) { return mt32emu_play_msg_at(c, msg, timestamp); } - mt32emu_return_code playSysexAt(const Bit8u *sysex, Bit32u len, Bit32u timestamp) { return mt32emu_play_sysex_at(c, sysex, len, timestamp); } - - void playMsgNow(Bit32u msg) { mt32emu_play_msg_now(c, msg); } - void playMsgOnPart(Bit8u part, Bit8u code, Bit8u note, Bit8u velocity) { mt32emu_play_msg_on_part(c, part, code, note, velocity); } - void playSysexNow(const Bit8u *sysex, Bit32u len) { mt32emu_play_sysex_now(c, sysex, len); } - void writeSysex(Bit8u channel, const Bit8u *sysex, Bit32u len) { mt32emu_write_sysex(c, channel, sysex, len); } - - void setReverbEnabled(const bool reverb_enabled) { mt32emu_set_reverb_enabled(c, reverb_enabled ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE); } - bool isReverbEnabled() { return mt32emu_is_reverb_enabled(c) != MT32EMU_BOOL_FALSE; } - void setReverbOverridden(const bool reverb_overridden) { mt32emu_set_reverb_overridden(c, reverb_overridden ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE); } - bool isReverbOverridden() { return mt32emu_is_reverb_overridden(c) != MT32EMU_BOOL_FALSE; } - void setReverbCompatibilityMode(const bool mt32_compatible_mode) { mt32emu_set_reverb_compatibility_mode(c, mt32_compatible_mode ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE); } - bool isMT32ReverbCompatibilityMode() { return mt32emu_is_mt32_reverb_compatibility_mode(c) != MT32EMU_BOOL_FALSE; } - bool isDefaultReverbMT32Compatible() { return mt32emu_is_default_reverb_mt32_compatible(c) != MT32EMU_BOOL_FALSE; } - - void setDACInputMode(const DACInputMode mode) { mt32emu_set_dac_input_mode(c, static_cast(mode)); } - DACInputMode getDACInputMode() { return static_cast(mt32emu_get_dac_input_mode(c)); } - - void setMIDIDelayMode(const MIDIDelayMode mode) { mt32emu_set_midi_delay_mode(c, static_cast(mode)); } - MIDIDelayMode getMIDIDelayMode() { return static_cast(mt32emu_get_midi_delay_mode(c)); } - - void setOutputGain(float gain) { mt32emu_set_output_gain(c, gain); } - float getOutputGain() { return mt32emu_get_output_gain(c); } - void setReverbOutputGain(float gain) { mt32emu_set_reverb_output_gain(c, gain); } - float getReverbOutputGain() { return mt32emu_get_reverb_output_gain(c); } - - void setReversedStereoEnabled(const bool enabled) { mt32emu_set_reversed_stereo_enabled(c, enabled ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE); } - bool isReversedStereoEnabled() { return mt32emu_is_reversed_stereo_enabled(c) != MT32EMU_BOOL_FALSE; } - - void renderBit16s(Bit16s *stream, Bit32u len) { mt32emu_render_bit16s(c, stream, len); } - void renderFloat(float *stream, Bit32u len) { mt32emu_render_float(c, stream, len); } - void renderBit16sStreams(const mt32emu_dac_output_bit16s_streams *streams, Bit32u len) { mt32emu_render_bit16s_streams(c, streams, len); } - void renderFloatStreams(const mt32emu_dac_output_float_streams *streams, Bit32u len) { mt32emu_render_float_streams(c, streams, len); } - - bool hasActivePartials() { return mt32emu_has_active_partials(c) != MT32EMU_BOOL_FALSE; } - bool isActive() { return mt32emu_is_active(c) != MT32EMU_BOOL_FALSE; } - Bit32u getPartialCount() { return mt32emu_get_partial_count(c); } - Bit32u getPartStates() { return mt32emu_get_part_states(c); } - void getPartialStates(Bit8u *partial_states) { mt32emu_get_partial_states(c, partial_states); } - Bit32u getPlayingNotes(Bit8u part_number, Bit8u *keys, Bit8u *velocities) { return mt32emu_get_playing_notes(c, part_number, keys, velocities); } - const char *getPatchName(Bit8u part_number) { return mt32emu_get_patch_name(c, part_number); } - void readMemory(Bit32u addr, Bit32u len, Bit8u *data) { mt32emu_read_memory(c, addr, len, data); } - -private: -#if MT32EMU_API_TYPE == 2 - const mt32emu_service_i i; -#endif - mt32emu_context c; -}; - -namespace CppInterfaceImpl { - -static mt32emu_report_handler_version getReportHandlerVersionID(mt32emu_report_handler_i) { - return MT32EMU_REPORT_HANDLER_VERSION_CURRENT; -} - -static void printDebug(void *instance_data, const char *fmt, va_list list) { - ((ReportHandler *)instance_data)->printDebug(fmt, list); -} - -static void onErrorControlROM(void *instance_data) { - ((ReportHandler *)instance_data)->onErrorControlROM(); -} - -static void onErrorPCMROM(void *instance_data) { - ((ReportHandler *)instance_data)->onErrorPCMROM(); -} - -static void showLCDMessage(void *instance_data, const char *message) { - ((ReportHandler *)instance_data)->showLCDMessage(message); -} - -static void onMIDIMessagePlayed(void *instance_data) { - ((ReportHandler *)instance_data)->onMIDIMessagePlayed(); -} - -static mt32emu_boolean onMIDIQueueOverflow(void *instance_data) { - return ((ReportHandler *)instance_data)->onMIDIQueueOverflow() ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE; -} - -static void onMIDISystemRealtime(void *instance_data, mt32emu_bit8u system_realtime) { - ((ReportHandler *)instance_data)->onMIDISystemRealtime(system_realtime); -} - -static void onDeviceReset(void *instance_data) { - ((ReportHandler *)instance_data)->onDeviceReset(); -} - -static void onDeviceReconfig(void *instance_data) { - ((ReportHandler *)instance_data)->onDeviceReconfig(); -} - -static void onNewReverbMode(void *instance_data, mt32emu_bit8u mode) { - ((ReportHandler *)instance_data)->onNewReverbMode(mode); -} - -static void onNewReverbTime(void *instance_data, mt32emu_bit8u time) { - ((ReportHandler *)instance_data)->onNewReverbTime(time); -} - -static void onNewReverbLevel(void *instance_data, mt32emu_bit8u level) { - ((ReportHandler *)instance_data)->onNewReverbLevel(level); -} - -static void onPolyStateChanged(void *instance_data, mt32emu_bit8u part_num) { - ((ReportHandler *)instance_data)->onPolyStateChanged(part_num); -} - -static void onProgramChanged(void *instance_data, mt32emu_bit8u part_num, const char *sound_group_name, const char *patch_name) { - ((ReportHandler *)instance_data)->onProgramChanged(part_num, sound_group_name, patch_name); -} - -static mt32emu_report_handler_i getReportHandlerThunk() { - static const mt32emu_report_handler_i_v0 REPORT_HANDLER_V0_THUNK = { - getReportHandlerVersionID, - printDebug, - onErrorControlROM, - onErrorPCMROM, - showLCDMessage, - onMIDIMessagePlayed, - onMIDIQueueOverflow, - onMIDISystemRealtime, - onDeviceReset, - onDeviceReconfig, - onNewReverbMode, - onNewReverbTime, - onNewReverbLevel, - onPolyStateChanged, - onProgramChanged - }; - - static const mt32emu_report_handler_i REPORT_HANDLER_THUNK = { &REPORT_HANDLER_V0_THUNK }; - - return REPORT_HANDLER_THUNK; -} - -static mt32emu_midi_receiver_version getMidiReceiverVersionID(mt32emu_midi_receiver_i) { - return MT32EMU_MIDI_RECEIVER_VERSION_CURRENT; -} - -static void handleShortMessage(void *instance_data, const mt32emu_bit32u message) { - ((MidiReceiver *)instance_data)->handleShortMessage(message); -} - -static void handleSysex(void *instance_data, const mt32emu_bit8u stream[], const mt32emu_bit32u length) { - ((MidiReceiver *)instance_data)->handleSysex(stream, length); -} - -static void handleSystemRealtimeMessage(void *instance_data, const mt32emu_bit8u realtime) { - ((MidiReceiver *)instance_data)->handleSystemRealtimeMessage(realtime); -} - -static mt32emu_midi_receiver_i getMidiReceiverThunk() { - static const mt32emu_midi_receiver_i_v0 MIDI_RECEIVER_V0_THUNK = { - getMidiReceiverVersionID, - handleShortMessage, - handleSysex, - handleSystemRealtimeMessage - }; - - static const mt32emu_midi_receiver_i MIDI_RECEIVER_THUNK = { &MIDI_RECEIVER_V0_THUNK }; - - return MIDI_RECEIVER_THUNK; -} - -} // namespace CppInterfaceImpl - -} // namespace MT32Emu - -#if MT32EMU_API_TYPE == 2 - -#undef mt32emu_get_supported_report_handler_version -#undef mt32emu_get_supported_midi_receiver_version -#undef mt32emu_get_library_version_int -#undef mt32emu_get_library_version_string -#undef mt32emu_get_stereo_output_samplerate -#undef mt32emu_create_context -#undef mt32emu_free_context -#undef mt32emu_add_rom_data -#undef mt32emu_add_rom_file -#undef mt32emu_get_rom_info -#undef mt32emu_set_partial_count -#undef mt32emu_set_analog_output_mode -#undef mt32emu_open_synth -#undef mt32emu_close_synth -#undef mt32emu_is_open -#undef mt32emu_get_actual_stereo_output_samplerate -#undef mt32emu_flush_midi_queue -#undef mt32emu_set_midi_event_queue_size -#undef mt32emu_set_midi_receiver -#undef mt32emu_parse_stream -#undef mt32emu_parse_stream_at -#undef mt32emu_play_short_message -#undef mt32emu_play_short_message_at -#undef mt32emu_play_msg -#undef mt32emu_play_sysex -#undef mt32emu_play_msg_at -#undef mt32emu_play_sysex_at -#undef mt32emu_play_msg_now -#undef mt32emu_play_msg_on_part -#undef mt32emu_play_sysex_now -#undef mt32emu_write_sysex -#undef mt32emu_set_reverb_enabled -#undef mt32emu_is_reverb_enabled -#undef mt32emu_set_reverb_overridden -#undef mt32emu_is_reverb_overridden -#undef mt32emu_set_reverb_compatibility_mode -#undef mt32emu_is_mt32_reverb_compatibility_mode -#undef mt32emu_is_default_reverb_mt32_compatible -#undef mt32emu_set_dac_input_mode -#undef mt32emu_get_dac_input_mode -#undef mt32emu_set_midi_delay_mode -#undef mt32emu_get_midi_delay_mode -#undef mt32emu_set_output_gain -#undef mt32emu_get_output_gain -#undef mt32emu_set_reverb_output_gain -#undef mt32emu_get_reverb_output_gain -#undef mt32emu_set_reversed_stereo_enabled -#undef mt32emu_is_reversed_stereo_enabled -#undef mt32emu_render_bit16s -#undef mt32emu_render_float -#undef mt32emu_render_bit16s_streams -#undef mt32emu_render_float_streams -#undef mt32emu_has_active_partials -#undef mt32emu_is_active -#undef mt32emu_get_partial_count -#undef mt32emu_get_part_states -#undef mt32emu_get_partial_states -#undef mt32emu_get_playing_notes -#undef mt32emu_get_patch_name -#undef mt32emu_read_memory - -#endif // #if MT32EMU_API_TYPE == 2 - -#endif /* #ifndef MT32EMU_CPP_INTERFACE_H */ diff --git a/audio/softsynth/mt32/config.h b/audio/softsynth/mt32/config.h deleted file mode 100644 index c62ae6f23f..0000000000 --- a/audio/softsynth/mt32/config.h +++ /dev/null @@ -1,28 +0,0 @@ -/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 2.1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ - -#ifndef MT32EMU_CONFIG_H -#define MT32EMU_CONFIG_H - -#define MT32EMU_VERSION "2.0.0" -#define MT32EMU_VERSION_MAJOR 2 -#define MT32EMU_VERSION_MINOR 0 -#define MT32EMU_VERSION_PATCH 0 - -#define MT32EMU_EXPORTS_TYPE 0 - -#endif diff --git a/audio/softsynth/mt32/globals.h b/audio/softsynth/mt32/globals.h deleted file mode 100644 index 49a5ecc250..0000000000 --- a/audio/softsynth/mt32/globals.h +++ /dev/null @@ -1,119 +0,0 @@ -/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 2.1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ - -#ifndef MT32EMU_GLOBALS_H -#define MT32EMU_GLOBALS_H - -#include "config.h" - -/* Support for compiling shared library. */ -#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__ */ -#else /* #ifdef MT32EMU_SHARED */ -#define MT32EMU_EXPORT_ATTRIBUTE -#endif /* #ifdef MT32EMU_SHARED */ - -#if MT32EMU_EXPORTS_TYPE == 1 || MT32EMU_EXPORTS_TYPE == 2 -#define MT32EMU_EXPORT -#else -#define MT32EMU_EXPORT MT32EMU_EXPORT_ATTRIBUTE -#endif - -/* Useful constants */ - -/* Sample rate to use in mixing. With the progress of development, we've found way too many thing dependent. - * In order to achieve further advance in emulation accuracy, sample rate made fixed throughout the emulator, - * except the emulation of analogue path. - * The output from the synth is supposed to be resampled externally in order to convert to the desired sample rate. - */ -#define MT32EMU_SAMPLE_RATE 32000 - -/* The default value for the maximum number of partials playing simultaneously. */ -#define MT32EMU_DEFAULT_MAX_PARTIALS 32 - -/* The higher this number, the more memory will be used, but the more samples can be processed in one run - - * various parts of sample generation can be processed more efficiently in a single run. - * A run's maximum length is that given to Synth::render(), so giving a value here higher than render() is ever - * called with will give no gain (but simply waste the memory). - * Note that this value does *not* in any way impose limitations on the length given to render(), and has no effect - * on the generated audio. - * This value must be >= 1. - */ -#define MT32EMU_MAX_SAMPLES_PER_RUN 4096 - -/* The default size of the internal MIDI event queue. - * It holds the incoming MIDI events before the rendering engine actually processes them. - * The main goal is to fairly emulate the real hardware behaviour which obviously - * uses an internal MIDI event queue to gather incoming data as well as the delays - * introduced by transferring data via the MIDI interface. - * This also facilitates building of an external rendering loop - * as the queue stores timestamped MIDI events. - */ -#define MT32EMU_DEFAULT_MIDI_EVENT_QUEUE_SIZE 1024 - -/* Maximum allowed size of MIDI parser input stream buffer. - * Should suffice for any reasonable bulk dump SysEx, as the h/w units have only 32K of RAM onboard. - */ -#define MT32EMU_MAX_STREAM_BUFFER_SIZE 32768 - -/* This should correspond to the MIDI buffer size used in real h/w devices. - * CM-32L control ROM seems using 1000 bytes, old MT-32 isn't confirmed by now. - */ -#define MT32EMU_SYSEX_BUFFER_SIZE 1000 - -#if defined(__cplusplus) && MT32EMU_API_TYPE != 1 - -namespace MT32Emu -{ -const unsigned int SAMPLE_RATE = MT32EMU_SAMPLE_RATE; -#undef MT32EMU_SAMPLE_RATE - -const unsigned int DEFAULT_MAX_PARTIALS = MT32EMU_DEFAULT_MAX_PARTIALS; -#undef MT32EMU_DEFAULT_MAX_PARTIALS - -const unsigned int MAX_SAMPLES_PER_RUN = MT32EMU_MAX_SAMPLES_PER_RUN; -#undef MT32EMU_MAX_SAMPLES_PER_RUN - -const unsigned int DEFAULT_MIDI_EVENT_QUEUE_SIZE = MT32EMU_DEFAULT_MIDI_EVENT_QUEUE_SIZE; -#undef MT32EMU_DEFAULT_MIDI_EVENT_QUEUE_SIZE - -const unsigned int MAX_STREAM_BUFFER_SIZE = MT32EMU_MAX_STREAM_BUFFER_SIZE; -#undef MT32EMU_MAX_STREAM_BUFFER_SIZE - -const unsigned int SYSEX_BUFFER_SIZE = MT32EMU_SYSEX_BUFFER_SIZE; -#undef MT32EMU_SYSEX_BUFFER_SIZE -} - -#endif /* #if defined(__cplusplus) && MT32EMU_API_TYPE != 1 */ - -#endif /* #ifndef MT32EMU_GLOBALS_H */ diff --git a/audio/softsynth/mt32/internals.h b/audio/softsynth/mt32/internals.h index c64ba39212..ef56819a42 100644 --- a/audio/softsynth/mt32/internals.h +++ b/audio/softsynth/mt32/internals.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013, 2014 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,111 +18,66 @@ #ifndef MT32EMU_INTERNALS_H #define MT32EMU_INTERNALS_H -#include "Types.h" - // Debugging // 0: Standard debug output is not stamped with the rendered sample count // 1: Standard debug output is stamped with the rendered sample count // NOTE: The "samplestamp" corresponds to the end of the last completed rendering run. // This is important to bear in mind for debug output that occurs during a run. -#ifndef MT32EMU_DEBUG_SAMPLESTAMPS #define MT32EMU_DEBUG_SAMPLESTAMPS 0 -#endif // 0: No debug output for initialisation progress // 1: Debug output for initialisation progress -#ifndef MT32EMU_MONITOR_INIT #define MT32EMU_MONITOR_INIT 0 -#endif // 0: No debug output for MIDI events // 1: Debug output for weird MIDI events -#ifndef MT32EMU_MONITOR_MIDI #define MT32EMU_MONITOR_MIDI 0 -#endif // 0: No debug output for note on/off // 1: Basic debug output for note on/off // 2: Comprehensive debug output for note on/off -#ifndef MT32EMU_MONITOR_INSTRUMENTS #define MT32EMU_MONITOR_INSTRUMENTS 0 -#endif // 0: No debug output for partial allocations // 1: Show partial stats when an allocation fails // 2: Show partial stats with every new poly // 3: Show individual partial allocations/deactivations -#ifndef MT32EMU_MONITOR_PARTIALS #define MT32EMU_MONITOR_PARTIALS 0 -#endif // 0: No debug output for sysex // 1: Basic debug output for sysex -#ifndef MT32EMU_MONITOR_SYSEX #define MT32EMU_MONITOR_SYSEX 0 -#endif // 0: No debug output for sysex writes to the timbre areas // 1: Debug output with the name and location of newly-written timbres // 2: Complete dump of timbre parameters for newly-written timbres -#ifndef MT32EMU_MONITOR_TIMBRES #define MT32EMU_MONITOR_TIMBRES 0 -#endif // 0: No TVA/TVF-related debug output. // 1: Shows changes to TVA/TVF target, increment and phase. -#ifndef MT32EMU_MONITOR_TVA #define MT32EMU_MONITOR_TVA 0 -#endif -#ifndef MT32EMU_MONITOR_TVF #define MT32EMU_MONITOR_TVF 0 -#endif // Configuration -// 0: Use 16-bit signed samples and refined wave generator based on logarithmic fixed-point computations and LUTs. Maximum emulation accuracy and speed. -// 1: Use float samples in the wave generator and renderer. Maximum output quality and minimum noise. -#ifndef MT32EMU_USE_FLOAT_SAMPLES -#define MT32EMU_USE_FLOAT_SAMPLES 0 -#endif - // If non-zero, deletes reverb buffers that are not in use to save memory. // If zero, keeps reverb buffers for all modes around all the time to avoid allocating/freeing in the critical path. -#ifndef MT32EMU_REDUCE_REVERB_MEMORY #define MT32EMU_REDUCE_REVERB_MEMORY 1 -#endif // 0: Maximum speed at the cost of a bit lower emulation accuracy. // 1: Maximum achievable emulation accuracy. -#ifndef MT32EMU_BOSS_REVERB_PRECISE_MODE #define MT32EMU_BOSS_REVERB_PRECISE_MODE 0 -#endif -namespace MT32Emu { +#include "Structures.h" +#include "Tables.h" +#include "Poly.h" +#include "LA32Ramp.h" +#include "LA32WaveGenerator.h" +#include "TVA.h" +#include "TVP.h" +#include "TVF.h" +#include "Partial.h" +#include "Part.h" -enum PolyState { - POLY_Playing, - POLY_Held, // This marks keys that have been released on the keyboard, but are being held by the pedal - POLY_Releasing, - POLY_Inactive -}; - -enum ReverbMode { - REVERB_MODE_ROOM, - REVERB_MODE_HALL, - REVERB_MODE_PLATE, - REVERB_MODE_TAP_DELAY -}; - -#if MT32EMU_USE_FLOAT_SAMPLES -typedef float Sample; -typedef float SampleEx; -#else -typedef Bit16s Sample; -typedef Bit32s SampleEx; #endif - -} - -#endif // #ifndef MT32EMU_INTERNALS_H diff --git a/audio/softsynth/mt32/mmath.h b/audio/softsynth/mt32/mmath.h index f233bedcbb..602242e74f 100644 --- a/audio/softsynth/mt32/mmath.h +++ b/audio/softsynth/mt32/mmath.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013, 2014 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,7 +18,12 @@ #ifndef MT32EMU_MMATH_H #define MT32EMU_MMATH_H -#include +#define FIXEDPOINT_UDIV(x, y, point) (((x) << (point)) / ((y))) +#define FIXEDPOINT_SDIV(x, y, point) (((x) * (1 << point)) / ((y))) +#define FIXEDPOINT_UMULT(x, y, point) (((x) * (y)) >> point) +#define FIXEDPOINT_SMULT(x, y, point) (((x) * (y)) / (1 << point)) + +#define FIXEDPOINT_MAKE(x, point) ((Bit32u)((1 << point) * x)) namespace MT32Emu { @@ -41,7 +46,7 @@ static inline float EXPF(float x) { static inline float EXP2F(float x) { #ifdef __APPLE__ // on OSX exp2f() is 1.59 times faster than "exp() and the multiplication with FLOAT_LN_2" - return exp2f(x); + return exp2(x); #else return exp(FLOAT_LN_2 * x); #endif @@ -63,6 +68,6 @@ static inline float LOG10F(float x) { return log10(x); } -} // namespace MT32Emu +} -#endif // #ifndef MT32EMU_MMATH_H +#endif diff --git a/audio/softsynth/mt32/module.mk b/audio/softsynth/mt32/module.mk index b8e2adad7b..f966da8d08 100644 --- a/audio/softsynth/mt32/module.mk +++ b/audio/softsynth/mt32/module.mk @@ -3,11 +3,8 @@ MODULE := audio/softsynth/mt32 MODULE_OBJS := \ Analog.o \ BReverbModel.o \ - File.o \ - FileStream.o \ LA32Ramp.o \ LA32WaveGenerator.o \ - MidiStreamParser.o \ Part.o \ Partial.o \ PartialManager.o \ @@ -17,8 +14,7 @@ MODULE_OBJS := \ Tables.o \ TVA.o \ TVF.o \ - TVP.o \ - sha1/sha1.o + TVP.o # Include common rules include $(srcdir)/rules.mk diff --git a/audio/softsynth/mt32/mt32emu.h b/audio/softsynth/mt32/mt32emu.h index 9f2b058250..1574c08f0d 100644 --- a/audio/softsynth/mt32/mt32emu.h +++ b/audio/softsynth/mt32/mt32emu.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013, 2014 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,66 +18,44 @@ #ifndef MT32EMU_MT32EMU_H #define MT32EMU_MT32EMU_H -#include "config.h" - -/* API Configuration */ - -/* 0: Use full-featured C++ API. Well suitable when the library is to be linked statically. - * When the library is shared, ABI compatibility may be an issue. Therefore, it should - * only be used within a project comprising of several modules to share the library code. - * 1: Use C-compatible API. Make the library looks as a regular C library with well-defined ABI. - * This is also crucial when the library is to be linked with modules in a different - * language, either statically or dynamically. - * 2: Use plugin-like API via C-interface wrapped in a C++ class. This is mainly intended - * for a shared library being dynamically loaded in run-time. To get access to all the library - * services, a client application only needs to bind with a single factory function. - * 3: Use optimised C++ API compatible with the plugin API (type 2). The facade class also wraps - * the C functions but they are invoked directly. This enables the compiler to generate better - * code for the library when linked statically yet being consistent with the plugin-like API. - */ - -#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) -#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 -#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 - -#include "c_interface/c_interface.h" - -#elif MT32EMU_API_TYPE == 2 || MT32EMU_API_TYPE == 3 - -#include "c_interface/cpp_interface.h" - -#else /* #if !defined(__cplusplus) || MT32EMU_API_TYPE == 1 */ +// Configuration + +// 0: Use 16-bit signed samples and refined wave generator based on logarithmic fixed-point computations and LUTs. Maximum emulation accuracy and speed. +// 1: Use float samples in the wave generator and renderer. Maximum output quality and minimum noise. +#define MT32EMU_USE_FLOAT_SAMPLES 0 + +namespace MT32Emu +{ +// Sample rate to use in mixing. With the progress of development, we've found way too many thing dependent. +// In order to achieve further advance in emulation accuracy, sample rate made fixed throughout the emulator, +// except the emulation of analogue path. +// The output from the synth is supposed to be resampled externally in order to convert to the desired sample rate. +const unsigned int SAMPLE_RATE = 32000; + +// The default value for the maximum number of partials playing simultaneously. +const unsigned int DEFAULT_MAX_PARTIALS = 32; + +// The higher this number, the more memory will be used, but the more samples can be processed in one run - +// various parts of sample generation can be processed more efficiently in a single run. +// A run's maximum length is that given to Synth::render(), so giving a value here higher than render() is ever +// called with will give no gain (but simply waste the memory). +// Note that this value does *not* in any way impose limitations on the length given to render(), and has no effect +// on the generated audio. +// This value must be >= 1. +const unsigned int MAX_SAMPLES_PER_RUN = 4096; + +// The default size of the internal MIDI event queue. +// It holds the incoming MIDI events before the rendering engine actually processes them. +// The main goal is to fairly emulate the real hardware behaviour which obviously +// uses an internal MIDI event queue to gather incoming data as well as the delays +// introduced by transferring data via the MIDI interface. +// This also facilitates building of an external rendering loop +// as the queue stores timestamped MIDI events. +const unsigned int DEFAULT_MIDI_EVENT_QUEUE_SIZE = 1024; +} #include "Types.h" -#include "File.h" -#include "FileStream.h" #include "ROMInfo.h" #include "Synth.h" -#include "MidiStreamParser.h" - -#endif /* #if !defined(__cplusplus) || MT32EMU_API_TYPE == 1 */ -#endif /* #ifndef MT32EMU_MT32EMU_H */ +#endif diff --git a/audio/softsynth/mt32/sha1/sha1.cpp b/audio/softsynth/mt32/sha1/sha1.cpp deleted file mode 100644 index a0c5e13a36..0000000000 --- a/audio/softsynth/mt32/sha1/sha1.cpp +++ /dev/null @@ -1,185 +0,0 @@ -/* - Copyright (c) 2011, Micael Hildenborg - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of Micael Hildenborg nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY Micael Hildenborg ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL Micael Hildenborg BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - Contributors: - Gustav - Several members in the gamedev.se forum. - Gregory Petrosyan - */ - -#include "sha1.h" - -namespace sha1 -{ - namespace // local - { - // Rotate an integer value to left. - inline unsigned int rol(const unsigned int value, - const unsigned int steps) - { - return ((value << steps) | (value >> (32 - steps))); - } - - // Sets the first 16 integers in the buffert to zero. - // Used for clearing the W buffert. - inline void clearWBuffert(unsigned int* buffert) - { - for (int pos = 16; --pos >= 0;) - { - buffert[pos] = 0; - } - } - - void innerHash(unsigned int* result, unsigned int* w) - { - unsigned int a = result[0]; - unsigned int b = result[1]; - unsigned int c = result[2]; - unsigned int d = result[3]; - unsigned int e = result[4]; - - int round = 0; - - #define sha1macro(func,val) \ - { \ - const unsigned int t = rol(a, 5) + (func) + e + val + w[round]; \ - e = d; \ - d = c; \ - c = rol(b, 30); \ - b = a; \ - a = t; \ - } - - while (round < 16) - { - sha1macro((b & c) | (~b & d), 0x5a827999) - ++round; - } - while (round < 20) - { - w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1); - sha1macro((b & c) | (~b & d), 0x5a827999) - ++round; - } - while (round < 40) - { - w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1); - sha1macro(b ^ c ^ d, 0x6ed9eba1) - ++round; - } - while (round < 60) - { - w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1); - sha1macro((b & c) | (b & d) | (c & d), 0x8f1bbcdc) - ++round; - } - while (round < 80) - { - w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1); - sha1macro(b ^ c ^ d, 0xca62c1d6) - ++round; - } - - #undef sha1macro - - result[0] += a; - result[1] += b; - result[2] += c; - result[3] += d; - result[4] += e; - } - } // namespace - - void calc(const void* src, const int bytelength, unsigned char* hash) - { - // Init the result array. - unsigned int result[5] = { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 }; - - // Cast the void src pointer to be the byte array we can work with. - const unsigned char* sarray = (const unsigned char*) src; - - // The reusable round buffer - unsigned int w[80]; - - // Loop through all complete 64byte blocks. - const int endOfFullBlocks = bytelength - 64; - int endCurrentBlock; - int currentBlock = 0; - - while (currentBlock <= endOfFullBlocks) - { - endCurrentBlock = currentBlock + 64; - - // Init the round buffer with the 64 byte block data. - for (int roundPos = 0; currentBlock < endCurrentBlock; currentBlock += 4) - { - // This line will swap endian on big endian and keep endian on little endian. - w[roundPos++] = (unsigned int) sarray[currentBlock + 3] - | (((unsigned int) sarray[currentBlock + 2]) << 8) - | (((unsigned int) sarray[currentBlock + 1]) << 16) - | (((unsigned int) sarray[currentBlock]) << 24); - } - innerHash(result, w); - } - - // Handle the last and not full 64 byte block if existing. - endCurrentBlock = bytelength - currentBlock; - clearWBuffert(w); - int lastBlockBytes = 0; - for (;lastBlockBytes < endCurrentBlock; ++lastBlockBytes) - { - w[lastBlockBytes >> 2] |= (unsigned int) sarray[lastBlockBytes + currentBlock] << ((3 - (lastBlockBytes & 3)) << 3); - } - w[lastBlockBytes >> 2] |= 0x80 << ((3 - (lastBlockBytes & 3)) << 3); - if (endCurrentBlock >= 56) - { - innerHash(result, w); - clearWBuffert(w); - } - w[15] = bytelength << 3; - innerHash(result, w); - - // Store hash in result pointer, and make sure we get in in the correct order on both endian models. - for (int hashByte = 20; --hashByte >= 0;) - { - hash[hashByte] = (result[hashByte >> 2] >> (((3 - hashByte) & 0x3) << 3)) & 0xff; - } - } - - void toHexString(const unsigned char* hash, char* hexstring) - { - const char hexDigits[] = { "0123456789abcdef" }; - - for (int hashByte = 20; --hashByte >= 0;) - { - hexstring[hashByte << 1] = hexDigits[(hash[hashByte] >> 4) & 0xf]; - hexstring[(hashByte << 1) + 1] = hexDigits[hash[hashByte] & 0xf]; - } - hexstring[40] = 0; - } -} // namespace sha1 diff --git a/audio/softsynth/mt32/sha1/sha1.h b/audio/softsynth/mt32/sha1/sha1.h deleted file mode 100644 index 96d8ce4da6..0000000000 --- a/audio/softsynth/mt32/sha1/sha1.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - Copyright (c) 2011, Micael Hildenborg - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of Micael Hildenborg nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY Micael Hildenborg ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL Micael Hildenborg BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef SHA1_DEFINED -#define SHA1_DEFINED - -namespace sha1 -{ - - /** - @param src points to any kind of data to be hashed. - @param bytelength the number of bytes to hash from the src pointer. - @param hash should point to a buffer of at least 20 bytes of size for storing the sha1 result in. - */ - void calc(const void* src, const int bytelength, unsigned char* hash); - - /** - @param hash is 20 bytes of sha1 hash. This is the same data that is the result from the calc function. - @param hexstring should point to a buffer of at least 41 bytes of size for storing the hexadecimal representation of the hash. A zero will be written at position 40, so the buffer will be a valid zero ended string. - */ - void toHexString(const unsigned char* hash, char* hexstring); - -} // namespace sha1 - -#endif // SHA1_DEFINED -- cgit v1.2.3