[Scummvm-git-logs] scummvm master -> 2c7d70ac105884c90a035226db2e78a20d2daea4

sev- noreply at scummvm.org
Tue Jun 30 23:13:27 UTC 2026


This automated email contains information about 3 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .

Summary:
b0728503c6 AUDIO: Add HMI Infinite Audio DSP library reimplementation
1759d44803 AUDIO: HMI: Infinite Audio clean-up
2c7d70ac10 AUDIO: HMI: Turn it into an optional component


Commit: b0728503c6482f4a7eae5716f51eb3b8af97236e
    https://github.com/scummvm/scummvm/commit/b0728503c6482f4a7eae5716f51eb3b8af97236e
Author: AndywinXp (andywinxp at gmail.com)
Date: 2026-07-01T01:13:22+02:00

Commit Message:
AUDIO: Add HMI Infinite Audio DSP library reimplementation

Changed paths:
  A audio/effects/hmi/hmi_interface.h
  A audio/effects/hmi/hmi_types.h
  A audio/effects/hmi/hmifxfp.cpp
  A audio/effects/hmi/hmifxfp.h
  A audio/effects/hmi/hmifxlib.cpp
  A audio/effects/hmi/hmifxlib.h
  A audio/effects/hmi/interfaces/envelope.cpp
  A audio/effects/hmi/interfaces/envelope.h
  A audio/effects/hmi/interfaces/filter1.cpp
  A audio/effects/hmi/interfaces/filter1.h
  A audio/effects/hmi/interfaces/mono_delay.cpp
  A audio/effects/hmi/interfaces/mono_delay.h
  A audio/effects/hmi/interfaces/phasor.cpp
  A audio/effects/hmi/interfaces/phasor.h
  A audio/effects/hmi/interfaces/resonator.cpp
  A audio/effects/hmi/interfaces/resonator.h
  A audio/effects/hmi/interfaces/reverb1.cpp
  A audio/effects/hmi/interfaces/reverb1.h
  A audio/effects/hmi/interfaces/reverb2.cpp
  A audio/effects/hmi/interfaces/reverb2.h
  A audio/effects/hmi/interfaces/ring_modulator.cpp
  A audio/effects/hmi/interfaces/ring_modulator.h
  A audio/effects/hmi/interfaces/stereo_delay.cpp
  A audio/effects/hmi/interfaces/stereo_delay.h
    audio/module.mk


diff --git a/audio/effects/hmi/hmi_interface.h b/audio/effects/hmi/hmi_interface.h
new file mode 100644
index 00000000000..e3f0fdc9f4f
--- /dev/null
+++ b/audio/effects/hmi/hmi_interface.h
@@ -0,0 +1,79 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef AUDIO_EFFECTS_HMI_INTERFACE_H
+#define AUDIO_EFFECTS_HMI_INTERFACE_H
+
+#include "audio/effects/hmi/hmi_types.h"
+
+namespace Audio {
+
+typedef const char *const *HMIParamNames;
+
+class HMIInterface {
+public:
+	virtual ~HMIInterface() {}
+
+	virtual int init(HMIPreset *, HMIEffectNode *) = 0;
+	virtual int uninit(HMIPreset *, HMIEffectNode *) = 0;
+	virtual int getMinDuration(HMIEffectNode *, uint32 *);
+	virtual int processBlock(HMIPreset *, HMIEffectNode *) = 0;
+	virtual int initEffect(HMIPreset *, HMIEffectNode *) = 0;
+	virtual int getEffectParam(HMIEffectNode *, int, float *, int *) = 0;
+	virtual int setEffectParam(HMIEffectNode *, int, float) = 0;
+
+	int effectStructSize() const { return _effectStructSize; }
+	int outChannels() const { return _outChannels; }
+	const char *interfaceName() const { return _interfaceName; }
+	HMIParamNames effectParams() const { return _effectParams; }
+	const float *paramMinValues() const { return _paramMinValues; }
+	const float *paramMaxValues() const { return _paramMaxValues; }
+	const float *paramDefaultValues() const { return _paramDefaultValues; }
+	const char *presetName() const { return _presetName; }
+	int presetId() const { return _presetId; }
+	int paramCount() const { return _paramCount; }
+
+protected:
+	static const double kHmiPi;
+	static const double kHmiTwoPi;
+	static const double kHmiMillis;
+
+	HMIInterface(int size, int channels,
+				 const char *dialogName, HMIParamNames params, const float *mins,
+				 const float *maxs, const float *defaults, const char *name, int id,
+				 int paramCount);
+
+private:
+	int _effectStructSize;
+	int _outChannels;
+	const char *_interfaceName;
+	HMIParamNames _effectParams;
+	const float *_paramMinValues;
+	const float *_paramMaxValues;
+	const float *_paramDefaultValues;
+	char _presetName[64];
+	int _presetId;
+	int _paramCount;
+};
+
+} // End of namespace Audio
+
+#endif
diff --git a/audio/effects/hmi/hmi_types.h b/audio/effects/hmi/hmi_types.h
new file mode 100644
index 00000000000..0368330cc64
--- /dev/null
+++ b/audio/effects/hmi/hmi_types.h
@@ -0,0 +1,287 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef AUDIO_EFFECTS_HMI_TYPES_H
+#define AUDIO_EFFECTS_HMI_TYPES_H
+
+#include "common/scummsys.h"
+
+namespace Audio {
+
+/* HMIPreset::flags */
+#define HMI_PRESET_FLAG_UNKNOWN_28          0x10000000U
+#define HMI_PRESET_FLAG_EFFECTS_INITIALIZED 0x20000000U
+#define HMI_PRESET_FLAG_USE_MALLOC          0x80000000U
+
+/* HMIProcessRequest::flags */
+#define HMI_PROCESS_USE_PRESET              0x00000001U
+#define HMI_PROCESS_FIND_PRESET_BY_NAME     0x00000002U
+#define HMI_PROCESS_ALLOCATE_OUTPUT         0x00000004U
+#define HMI_PROCESS_OVERRIDE_INPUT_FORMAT   0x00000008U
+#define HMI_PROCESS_OVERRIDE_OUTPUT_FORMAT  0x00000010U
+#define HMI_PROCESS_LOOKUP_ONLY             0x00000020U
+#define HMI_PROCESS_QUERY_OUTPUT_SIZE       0x00000040U
+#define HMI_PROCESS_INCLUDE_TAIL            0x00000080U
+#define HMI_PROCESS_DERIVE_OUTPUT_FORMAT    0x00000200U
+#define HMI_PROCESS_DISABLE_CLAMPING        0x00000400U
+
+/* HMIEffectNode::channelMode */
+#define HMI_EFFECT_CHANNEL_MONO             0x00000001U
+#define HMI_EFFECT_CHANNEL_STEREO           0x00000002U
+#define HMI_EFFECT_STEREO_ROUTING_MASK      0x0000000AU
+
+/* HMIFileDescriptor::fileFlags */
+#define HMI_FILE_FLAG_DIRTY                 0x00008000U
+
+class HMIInterface;
+
+struct HMIFormat;
+struct HMIEffectNode;
+struct HMIPreset;
+
+struct HMIFormat {
+	uint16 fmtBeginSection;
+	uint16 numChannels;
+	uint32 sampleRate;
+	uint32 byteRate;
+	uint16 blockAlign;
+	uint16 bitsPerSample;
+	uint16 fmtEndSection;
+};
+
+struct HMIEffectNode {
+	uint32 flags;
+	int outputBus;
+	int sendChannel;
+	uint32 channelMode;
+	int outputBufSize;
+	HMIInterface *interface;
+	HMIEffectNode *next;
+};
+
+#define HMI_EFFECT_NODE_HEADER \
+	uint32 flags;              \
+	int outputBus;             \
+	int sendChannel;           \
+	uint32 channelMode;        \
+	int outputBufSize;         \
+	HMIInterface *interface;   \
+	HMIEffectNode *next
+
+struct HMIPreset {
+	uint32 flags;
+	char name[64];
+	int chunkSizeInMs;
+	float *floatBufLeftActive;
+	float *floatBufRightActive;
+	float *floatBufLeftAlt;
+	float *floatBufRightAlt;
+	float *floatBufLeft0;
+	float *floatBufLeft1;
+	float *floatBufRight0;
+	float *floatBufRight1;
+	int pingPongIndex;
+	uint32 chunkSizeInSamples;
+	uint32 chunkSize;
+	int lockLevel;
+	int allocatedHeapSize;
+	uint8 reserved[980];
+	HMIEffectNode *effectChain;
+	HMIFormat *outputFmt;
+	HMIFormat *inputFmt;
+	HMIPreset *next;
+};
+
+struct HMIInitData {
+	uint32 *a;
+	uint32 *b;
+	int heapSize;
+	void *heapPtr;
+	void *(*mallocFunc)(size_t);
+	void (*freeFunc)(void *);
+};
+
+struct HMILibrary {
+	char description[64];
+	char authorName[64];
+	uint8 data[20];
+	HMIPreset *effectPtr;
+	HMIFormat inputFmt;
+	HMIFormat outputFmt;
+};
+
+struct HMIProcessRequest {
+	uint32 flags;
+	HMIPreset *presetPtr;
+	char *effectName;
+	uint8 *dstBuf;
+	uint32 dstLen;
+	uint8 *srcBuf;
+	uint32 srcLen;
+	HMIFormat *inputFmt;
+	HMIFormat *outputFmt;
+};
+
+struct HMIFileDescriptor {
+	int fileFlags;
+	char filename[128];
+	uint8 *fileBuffer;
+	int fileSize;
+	int fileSizeExp;
+	uint8 *ptrToDescription;
+	int firstPresetPos;
+	uint8 *ptrToFirstPresetSection;
+	uint8 *ptrToFirstEffectSection;
+	uint8 *ptrToEffectParams;
+	uint8 *currentPos;
+	uint8 *anotherPtrToDescription;
+};
+
+struct HMIFilter1Node {
+	HMI_EFFECT_NODE_HEADER;
+	int filterType;
+	float cutoffFrequency;
+	float centerFrequency;
+	float bandWidth;
+	float coeff_b0, coeff_b1, coeff_b2, coeff_a1, coeff_a2;
+	float state_x1, state_x2, state_x3, state_y1;
+	float state_x1b, state_x2b, state_x3b, state_y1b;
+};
+
+struct HMIRingModulatorNode {
+	HMI_EFFECT_NODE_HEADER;
+	float frequency;
+	float modulatorType;
+	float modulateOutOfPhase;
+	float dryOut;
+	float wetOut;
+	float phase;
+};
+
+struct HMIResonatorNode {
+	HMI_EFFECT_NODE_HEADER;
+	float cutoffFrequency;
+	float bandWidth;
+	float resonance;
+	float coeff1;
+	float coeff2;
+	float stateX1;
+	float stateX2;
+};
+
+struct HMIReverbEchoStage {
+	float *buffer;
+	int writeHead;
+	int readHead;
+	int bufSizeInSamples;
+	float lastOutput;
+	float decayCoeff;
+};
+
+struct HMIReverb1Node {
+	HMI_EFFECT_NODE_HEADER;
+	float reverbMax;
+	float reverbTime;
+	float preDelay;
+	int preDelaySamples;
+	int bufSizeBytes;
+	HMIReverbEchoStage echoStages[4];
+	float dryOut;
+	float wetOut;
+};
+
+struct HMIReverb2Node {
+	HMI_EFFECT_NODE_HEADER;
+	float reverbMax;
+	float reverbTime;
+	float preDelay;
+	int preDelaySamples;
+	int bufSizeBytes;
+	HMIReverbEchoStage echoStages[6];
+	float dryOut;
+	float wetOut;
+};
+
+struct HMIPhasorNode {
+	HMI_EFFECT_NODE_HEADER;
+	float rate;
+	float depth;
+	float centerFrequency;
+	float feedback;
+	float dryOut;
+	float wetOut;
+	float phase;
+	float b0, b1, a1;
+	float state_x1L, state_y1L, state_x1R, state_y1R;
+	float state_x2L, state_y2L, state_x2R, state_y2R;
+	float coeff;
+	float modPhase;
+};
+
+struct HMIEnvelopeNode {
+	HMI_EFFECT_NODE_HEADER;
+	float envPoints;
+	float pointTime[8];
+	float pointAmp[8];
+	float initGuard;
+	int segRemaining[8];
+	int currentSegment;
+	float currentAmp;
+	float segSlopes[8];
+};
+
+struct HMIMonoDelayNode {
+	HMI_EFFECT_NODE_HEADER;
+	float maxDelayTime;
+	float delayTime;
+	float unused0;
+	float feedback;
+	float dryOut;
+	float wetOut;
+	float *delayBuf;
+	int unused1;
+	int bufSizeBytes;
+	int unused2;
+	int writeIndex;
+	int pad;
+};
+
+struct HMIStereoDelayNode {
+	HMI_EFFECT_NODE_HEADER;
+	float maxDelayTime;
+	float delayTimeL;
+	float delayTimeR;
+	float feedback;
+	float dryOut;
+	float wetOut;
+	float *delayBufL;
+	float *delayBufR;
+	int bufSizeBytesL;
+	int bufSizeBytesR;
+	int writeIndexL;
+	int writeIndexR;
+};
+
+#undef HMI_EFFECT_NODE_HEADER
+
+} // End of namespace Audio
+
+#endif
diff --git a/audio/effects/hmi/hmifxfp.cpp b/audio/effects/hmi/hmifxfp.cpp
new file mode 100644
index 00000000000..d4719bdc139
--- /dev/null
+++ b/audio/effects/hmi/hmifxfp.cpp
@@ -0,0 +1,79 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "audio/effects/hmi/hmifxfp.h"
+
+namespace Audio {
+
+const double HMIInterface::kHmiPi = 3.14159265;
+const double HMIInterface::kHmiTwoPi = 6.2831853;
+const double HMIInterface::kHmiMillis = 0.001;
+
+static void copyName(char *dst, const char *src) {
+	int i = 0;
+	while (i != 63 && src[i]) {
+		dst[i] = src[i];
+		++i;
+	}
+
+	dst[i] = 0;
+	while (++i != 64)
+		dst[i] = 0;
+}
+
+HMIInterface::HMIInterface(int size, int channels,
+						   const char *dialogName, HMIParamNames params, const float *mins,
+						   const float *maxs, const float *defaults, const char *name, int id,
+						   int paramCount)
+	: _effectStructSize(size), _outChannels(channels),
+	  _interfaceName(dialogName), _effectParams(params), _paramMinValues(mins),
+	  _paramMaxValues(maxs), _paramDefaultValues(defaults),
+	  _presetId(id), _paramCount(paramCount) {
+	copyName(_presetName, name);
+}
+
+int HMIInterface::getMinDuration(HMIEffectNode *, uint32 *duration) {
+	*duration = 0;
+	return 0;
+}
+
+HMIFxFp::HMIFxFp() { initializeInterfaces(); }
+
+void HMIFxFp::initializeInterfaces() {
+	/* Original interface-list order at 0x10012A70. */
+	_interfaceList[0] = &_monoDelay;
+	_interfaceList[1] = &_stereoDelay;
+	_interfaceList[2] = &_reverb1;
+	_interfaceList[3] = &_filter1;
+	_interfaceList[4] = &_ringModulator;
+	_interfaceList[5] = &_envelope;
+	_interfaceList[6] = &_resonator;
+	_interfaceList[7] = &_phasor;
+	_interfaceList[8] = &_reverb2;
+	_interfaceList[9] = nullptr;
+}
+
+int HMIFxFp::hmiFXGetInterfaceList(HMIInterface ***outList) {
+	*outList = _interfaceList;
+	return 0;
+}
+
+} // End of namespace Audio
diff --git a/audio/effects/hmi/hmifxfp.h b/audio/effects/hmi/hmifxfp.h
new file mode 100644
index 00000000000..8e7d200388a
--- /dev/null
+++ b/audio/effects/hmi/hmifxfp.h
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef AUDIO_EFFECTS_HMI_HMIFXFP_H
+#define AUDIO_EFFECTS_HMI_HMIFXFP_H
+
+#include "audio/effects/hmi/interfaces/envelope.h"
+#include "audio/effects/hmi/interfaces/filter1.h"
+#include "audio/effects/hmi/interfaces/mono_delay.h"
+#include "audio/effects/hmi/interfaces/phasor.h"
+#include "audio/effects/hmi/interfaces/resonator.h"
+#include "audio/effects/hmi/interfaces/reverb1.h"
+#include "audio/effects/hmi/interfaces/reverb2.h"
+#include "audio/effects/hmi/interfaces/ring_modulator.h"
+#include "audio/effects/hmi/interfaces/stereo_delay.h"
+
+namespace Audio {
+
+class HMIFxFp {
+public:
+	HMIFxFp();
+	int hmiFXGetInterfaceList(HMIInterface ***outList);
+
+private:
+	void initializeInterfaces();
+
+	HMIMonoDelay _monoDelay;
+	HMIStereoDelay _stereoDelay;
+	HMIReverb1 _reverb1;
+	HMIFilter1 _filter1;
+	HMIRingModulator _ringModulator;
+	HMIEnvelope _envelope;
+	HMIResonator _resonator;
+	HMIPhasor _phasor;
+	HMIReverb2 _reverb2;
+	HMIInterface *_interfaceList[10];
+};
+
+} // End of namespace Audio
+
+#endif
diff --git a/audio/effects/hmi/hmifxlib.cpp b/audio/effects/hmi/hmifxlib.cpp
new file mode 100644
index 00000000000..d89385c4e69
--- /dev/null
+++ b/audio/effects/hmi/hmifxlib.cpp
@@ -0,0 +1,959 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "audio/effects/hmi/hmifxlib.h"
+
+#include "common/file.h"
+#include "common/str.h"
+#include "common/stream.h"
+
+namespace Audio {
+
+/*
+ * This deliberately is not a plain integer cast. With the DLL's default x87
+ * control word, FISTP rounds to nearest with ties going to the even integer:
+ * 1.6 becomes 2, 2.5 stays 2, and 3.5 becomes 4. A C++ cast would instead
+ * truncate toward zero. FISTP also produces its integer-indefinite value for
+ * NaN and out-of-range inputs, so preserve that behavior here as well.
+ * AFAIK, we have no rounding helper that provides this exact combination of
+ * nearest-even rounding and fixed-width x87 overflow behavior. AFAIK.
+ */
+static int32 hmiFistp32(float value) {
+	if (value != value || value < -2147483648.0f || value >= 2147483648.0f)
+		return -2147483647 - 1;
+
+	int32 result = (int32)value;
+	float fraction = value - (float)result;
+
+	if (fraction > 0.5f || (fraction == 0.5f && (result % 2))) {
+		++result;
+	} else if (fraction < -0.5f || (fraction == -0.5f && (result % 2))) {
+		--result;
+	}
+
+	return result;
+}
+
+static int16 hmiFistp16(float value) {
+	int32 result = hmiFistp32(value);
+	if (result < -32768 || result > 32767)
+		return -32768;
+
+	return (int16)result;
+}
+
+HMIFxLib::HMIFxLib()
+	: _numLoadedInterfaces(0), _curInterfaceIndex(0), _systemHeap(0),
+	  _heapCursor(0), _heapEnd(0), _mallocFunc(malloc), _freeFunc(free) {
+	memset(_loadedInterfaces, 0, sizeof(_loadedInterfaces));
+	HMIInterface **list = nullptr;
+	_fxFp.hmiFXGetInterfaceList(&list);
+
+	while (_numLoadedInterfaces != 1024 && list[_numLoadedInterfaces]) {
+		_loadedInterfaces[_numLoadedInterfaces] = list[_numLoadedInterfaces];
+		++_numLoadedInterfaces;
+	}
+
+	if (_numLoadedInterfaces != 1024)
+		_loadedInterfaces[_numLoadedInterfaces] = nullptr;
+}
+
+HMIFxLib::~HMIFxLib() {}
+
+HMIFxFp *HMIFxLib::effects() {
+	return &_fxFp;
+}
+
+int HMIFxLib::hmiFXInitSystem(HMIInitData *initData) {
+	if (initData->mallocFunc && initData->freeFunc) {
+		_mallocFunc = initData->mallocFunc;
+		_freeFunc = initData->freeFunc;
+	} else {
+		_mallocFunc = malloc;
+		_freeFunc = free;
+	}
+
+	initData->heapPtr = hmiFXMalloc((size_t)initData->heapSize);
+	if (!initData->heapPtr)
+		return 1;
+
+	hmiFXHeapInit(initData);
+	return 0;
+}
+
+int HMIFxLib::hmiFXUnInitSystem(HMIInitData *initData) {
+	if (initData->heapPtr)
+		hmiFXFree(initData->heapPtr);
+
+	initData->heapPtr = nullptr;
+	_systemHeap = _heapCursor = _heapEnd = nullptr;
+	return 0;
+}
+
+int HMIFxLib::hmiFXGetInterface(int interfaceId, HMIInterface **outInterface) {
+	for (unsigned int i = 0; i != _numLoadedInterfaces; ++i) {
+		if (_loadedInterfaces[i]->presetId() == interfaceId) {
+			*outInterface = _loadedInterfaces[i];
+			return 0;
+		}
+	}
+
+	return 7;
+}
+
+unsigned int HMIFxLib::hmiFXGenerateQueryString(char *buffer, const char *prefix, unsigned int id) {
+	if (id < 10)
+		return (unsigned int)snprintf(buffer, 32, "%s000%d", prefix, id);
+
+	if (id < 100)
+		return (unsigned int)snprintf(buffer, 32, "%s00%d", prefix, id);
+
+	if (id < 1000)
+		return (unsigned int)snprintf(buffer, 32, "%s0%d", prefix, id);
+
+	if (id < 10000)
+		return (unsigned int)snprintf(buffer, 32, "%s%d", prefix, id);
+
+	return id;
+}
+
+int HMIFxLib::hmiFXGetFirstInterface(HMIInterface **outInterface) {
+	if (!_numLoadedInterfaces)
+		return 7;
+
+	_curInterfaceIndex = 1;
+	*outInterface = _loadedInterfaces[0];
+	return 0;
+}
+
+int HMIFxLib::hmiFXGetNextInterface(HMIInterface **outInterface) {
+	if (_curInterfaceIndex == _numLoadedInterfaces)
+		return 7;
+
+	*outInterface = _loadedInterfaces[_curInterfaceIndex++];
+	return 0;
+}
+
+void *HMIFxLib::hmiFXHeapAlloc(int size) {
+	uint8 *result = _heapCursor;
+	if (!result || result + size > _heapEnd)
+		return nullptr;
+	_heapCursor += size;
+	return result;
+}
+
+void HMIFxLib::hmiFXHeapFree(void *) {}
+
+int HMIFxLib::hmiFXHeapInit(HMIInitData *data) {
+	_systemHeap = (uint8 *)data->heapPtr;
+	_heapCursor = _systemHeap;
+	_heapEnd = _systemHeap + data->heapSize;
+	return 0;
+}
+
+void *HMIFxLib::hmiFXHeapReset() {
+	_heapCursor = _systemHeap;
+	return _systemHeap;
+}
+
+void *HMIFxLib::hmiFXMalloc(size_t size) {
+	return _mallocFunc(size);
+}
+
+void HMIFxLib::hmiFXFree(void *ptr) {
+	_freeFunc(ptr);
+}
+
+int HMIFxLib::convertPCMToFloat(HMIPreset *preset, const uint8 *buffer, int samples) {
+	float *left = preset->floatBufLeftActive;
+	float *right = preset->floatBufRightActive;
+
+	if (preset->inputFmt->bitsPerSample == 8) {
+		if (preset->inputFmt->numChannels == 1) {
+			for (int i = 0; i != samples; ++i) {
+				left[i] = (float)((double)buffer[i] - 127.0);
+			}
+		} else {
+			for (int i = 0; i != samples; ++i) {
+				left[i] = (float)((double)buffer[i * 2] - 127.0);
+				right[i] = (float)((double)buffer[i * 2 + 1] - 127.0);
+			}
+		}
+	} else if (preset->inputFmt->bitsPerSample == 16) {
+		const int16 *input = (const int16 *)buffer;
+		if (preset->inputFmt->numChannels == 1) {
+			for (int i = 0; i != samples; ++i) {
+				left[i] = (float)input[i];
+			}
+		} else {
+			for (int i = 0; i != samples; ++i) {
+				left[i] = (float)input[i * 2];
+				right[i] = (float)input[i * 2 + 1];
+			}
+		}
+	}
+
+	return 0;
+}
+
+int HMIFxLib::convertFloatToPCM(HMIPreset *preset, uint8 *buffer, int samples, int clampOutput) {
+	float *left = preset->floatBufLeftAlt;
+	float *right = preset->floatBufRightAlt;
+
+	if (preset->outputFmt->bitsPerSample == 8) {
+		if (preset->outputFmt->numChannels == 1) {
+			for (int i = 0; i != samples; ++i) {
+				if (left[i] > 127.0f) {
+					buffer[i] = 255;
+				} else if (left[i] <= -128.0f) {
+					buffer[i] = 0;
+				} else {
+					buffer[i] = (uint8)((int64)((double)left[i] + 128.0));
+				}
+			}
+		} else {
+			for (int i = 0; i != samples; ++i) {
+				float values[2] = {left[i], right[i]};
+				for (int c = 0; c != 2; ++c) {
+					if (values[c] > 127.0f) {
+						buffer[i * 2 + c] = 255;
+					} else if (values[c] <= -128.0f) {
+						buffer[i * 2 + c] = 0;
+					} else {
+						buffer[i * 2 + c] = (uint8)(((int64)values[c]) ^ 0x80);
+					}
+				}
+			}
+		}
+	} else if (preset->outputFmt->bitsPerSample == 16) {
+		int16 *output = (int16 *)buffer;
+		int channels = preset->outputFmt->numChannels == 1 ? 1 : 2;
+		for (int i = 0; i != samples; ++i) {
+			for (int c = 0; c != channels; ++c) {
+				float value = c ? right[i] : left[i];
+				if (!clampOutput) {
+					output[i * channels + c] = hmiFistp16(value);
+					continue;
+				}
+
+				int converted = hmiFistp32(value);
+				if (converted > 32767) {
+					converted = 32767;
+				} else if (converted < -32767) {
+					converted = -32767;
+				}
+
+				output[i * channels + c] = (int16)converted;
+			}
+		}
+	}
+
+	return 0;
+}
+
+int HMIFxLib::hmiFXPresetCreate(HMIPreset *preset) {
+	hmiFXHeapReset();
+
+	uint32 samples = preset->inputFmt->sampleRate * preset->chunkSizeInMs / 1000U;
+	int segmentBytes = 4 * (int)samples + 1024;
+	preset->chunkSizeInSamples = samples;
+	float *block = (float *)((preset->flags & HMI_PRESET_FLAG_USE_MALLOC) ? hmiFXMalloc(4 * segmentBytes)
+																		  : hmiFXHeapAlloc(4 * segmentBytes));
+	if (!block)
+		return 1;
+
+	preset->floatBufLeft0 = block;
+	preset->floatBufLeft1 = (float *)((uint8 *)block + segmentBytes);
+	preset->floatBufRight0 = (float *)((uint8 *)block + segmentBytes * 2);
+	preset->floatBufRight1 = (float *)((uint8 *)block + segmentBytes * 3);
+
+	resetMixBuffers(preset);
+	preset->effectChain = nullptr;
+	return 0;
+}
+
+void HMIFxLib::resetMixBuffers(HMIPreset *preset) {
+	preset->floatBufLeftActive = preset->floatBufLeft0;
+	preset->floatBufRightActive = preset->floatBufRight0;
+	preset->floatBufLeftAlt = preset->floatBufLeft1;
+	preset->floatBufRightAlt = preset->floatBufRight1;
+	preset->pingPongIndex = 0;
+}
+
+int HMIFxLib::hmiFXPresetDestroy(HMIPreset *preset) {
+	for (HMIEffectNode *node = preset->effectChain; node; node = node->next)
+		node->interface->uninit(preset, node);
+
+	if (preset->flags & HMI_PRESET_FLAG_USE_MALLOC)
+		hmiFXFree(preset->floatBufLeft0);
+
+	return 0;
+}
+
+int HMIFxLib::hmiFXPresetAddEffect(HMIPreset *preset, HMIEffectNode *newNode) {
+	int result = newNode->interface->init(preset, newNode);
+	if (result)
+		return result;
+
+	HMIEffectNode *tail = preset->effectChain;
+	if (!tail) {
+		preset->effectChain = newNode;
+	} else {
+		while (tail->next)
+			tail = tail->next;
+
+		tail->next = newNode;
+	}
+	
+	newNode->next = nullptr;
+	preset->allocatedHeapSize = _systemHeap ? (int)(_heapCursor - _systemHeap) : 0;
+	return 0;
+}
+
+int HMIFxLib::hmiFXPresetGetByName(HMILibrary *library, const char *name, HMIPreset **outPreset) {
+	HMIPreset *preset = library->effectPtr;
+	if (!preset)
+		return 12;
+
+	*outPreset = nullptr;
+	while (preset && scumm_stricmp(preset->name, name)) {
+		preset = preset->next;
+	}
+
+	if (!preset)
+		return 13;
+
+	*outPreset = preset;
+	return 0;
+}
+
+int HMIFxLib::hmiFXPresetLock(HMIPreset *preset) {
+	if (!preset)
+		return 15;
+
+	if (preset->lockLevel) {
+		++preset->lockLevel;
+		return 0;
+	}
+
+	preset->lockLevel = 1;
+
+	preset->flags &= ~(HMI_PRESET_FLAG_USE_MALLOC | HMI_PRESET_FLAG_EFFECTS_INITIALIZED);
+	for (HMIEffectNode *n = preset->effectChain; n; n = n->next)
+		n->interface->uninit(preset, n);
+
+	preset->flags |= HMI_PRESET_FLAG_USE_MALLOC;
+	for (HMIEffectNode *n = preset->effectChain; n; n = n->next)
+		n->interface->init(preset, n);
+
+	return 0;
+}
+
+int HMIFxLib::hmiFXPresetRelease(HMIPreset *preset) {
+	if (!preset)
+		return 15;
+
+	if (--preset->lockLevel == 0) {
+		for (HMIEffectNode *n = preset->effectChain; n; n = n->next)
+			n->interface->uninit(preset, n);
+
+		HMIEffectNode *chain = preset->effectChain;
+		preset->flags &= ~HMI_PRESET_FLAG_USE_MALLOC;
+		hmiFXPresetCreate(preset);
+		preset->effectChain = chain;
+
+		for (HMIEffectNode *n = chain; n; n = n->next)
+			n->interface->init(preset, n);
+	}
+
+	return 0;
+}
+
+int HMIFxLib::hmiFXPresetGetRouting(HMIPreset *preset, uint32 *routingOut) {
+	if (!preset)
+		return 15;
+
+	if (!preset->effectChain)
+		return 6;
+
+	HMIEffectNode *n = preset->effectChain;
+	while (n->next)
+		n = n->next;
+
+	*routingOut = (n->channelMode & HMI_EFFECT_STEREO_ROUTING_MASK) ? 2 : 1;
+	return 0;
+}
+
+void HMIFxLib::hmiFXSetWaveFmtEx(HMIFormat *f, int rate, uint16 bits, uint16 channels) {
+	f->numChannels = channels;
+	f->bitsPerSample = bits;
+	f->sampleRate = rate;
+	f->blockAlign = (uint16)(bits * channels / 8);
+	f->byteRate = f->blockAlign * rate;
+	f->fmtBeginSection = 1;
+	f->fmtEndSection = 0;
+}
+
+int HMIFxLib::hmiFXPresetCreateInstance(HMIPreset *source, HMIPreset **outInstance) {
+	if (!source)
+		return 15;
+
+	HMIPreset *copy = (HMIPreset *)hmiFXMalloc(sizeof(HMIPreset));
+	if (!copy) {
+		*outInstance = nullptr;
+		return 1;
+	}
+
+	memcpy(copy, source, sizeof(HMIPreset));
+	copy->effectChain = nullptr;
+	copy->flags = (copy->flags & ~(HMI_PRESET_FLAG_USE_MALLOC | HMI_PRESET_FLAG_EFFECTS_INITIALIZED | HMI_PRESET_FLAG_UNKNOWN_28)) | HMI_PRESET_FLAG_USE_MALLOC;
+
+	HMIEffectNode *previous = nullptr;
+	for (HMIEffectNode *src = source->effectChain; src; src = src->next) {
+		HMIEffectNode *node = (HMIEffectNode *)hmiFXMalloc(src->interface->effectStructSize());
+		if (!node) {
+			hmiFXPresetDestroyInstance(copy);
+			*outInstance = nullptr;
+			return 1;
+		}
+
+		memcpy(node, src, src->interface->effectStructSize());
+		node->next = nullptr;
+		node->interface->init(copy, node);
+
+		if (previous) {
+			previous->next = node;
+		} else {
+			copy->effectChain = node;
+		}
+
+		previous = node;
+	}
+
+	*outInstance = copy;
+	return 0;
+}
+
+int HMIFxLib::hmiFXPresetDestroyInstance(HMIPreset *preset) {
+	if (!preset)
+		return 15;
+
+	HMIEffectNode *node = preset->effectChain;
+	while (node) {
+		node->interface->uninit(preset, node);
+		HMIEffectNode *next = node->next;
+		hmiFXFree(node);
+		node = next;
+	}
+
+	hmiFXFree(preset);
+	return 0;
+}
+
+void HMIFxLib::processEffectChain(HMIPreset *preset) {
+	HMIEffectNode *node = preset->effectChain;
+	while (node) {
+		node->interface->processBlock(preset, node);
+		node = node->next;
+
+		if (node) {
+			preset->pingPongIndex ^= 1;
+			int active = preset->pingPongIndex;
+			preset->floatBufLeftActive = active ? preset->floatBufLeft1 : preset->floatBufLeft0;
+			preset->floatBufRightActive = active ? preset->floatBufRight1 : preset->floatBufRight0;
+			preset->floatBufLeftAlt = active ? preset->floatBufLeft0 : preset->floatBufLeft1;
+			preset->floatBufRightAlt = active ? preset->floatBufRight0 : preset->floatBufRight1;
+		}
+	}
+}
+
+int HMIFxLib::processPreset(HMIPreset *preset, HMIProcessRequest *req) {
+	if (!preset->effectChain)
+		return 6;
+
+	HMIFormat *savedInput = preset->inputFmt;
+	HMIFormat *savedOutput = preset->outputFmt;
+
+	if (req->flags & HMI_PROCESS_OVERRIDE_INPUT_FORMAT)
+		preset->inputFmt = req->inputFmt;
+
+	if (req->flags & HMI_PROCESS_OVERRIDE_OUTPUT_FORMAT)
+		preset->outputFmt = req->outputFmt;
+
+	if (req->flags & HMI_PROCESS_DERIVE_OUTPUT_FORMAT) {
+		uint32 routing;
+		hmiFXPresetGetRouting(preset, &routing);
+		hmiFXSetWaveFmtEx(req->outputFmt, preset->inputFmt->sampleRate,
+						  preset->inputFmt->bitsPerSample, (uint16)routing);
+		preset->outputFmt = req->outputFmt;
+	}
+
+	preset->chunkSizeInSamples = preset->inputFmt->sampleRate * preset->chunkSizeInMs / 1000U;
+	uint32 sourceSamples = req->srcLen / preset->inputFmt->blockAlign;
+	uint32 tailMs = 0;
+
+	for (HMIEffectNode *n = preset->effectChain; n; n = n->next) {
+		uint32 value = 0;
+		n->interface->getMinDuration(n, &value);
+		if (tailMs <= value)
+			tailMs = value;
+	}
+
+	uint32 tailSamples = 0;
+	if (!(preset->flags & HMI_PRESET_FLAG_USE_MALLOC) || (req->flags & HMI_PROCESS_INCLUDE_TAIL))
+		tailSamples = (uint32)((double)preset->inputFmt->sampleRate * tailMs * 0.001);
+
+	uint32 outputBytes = (sourceSamples + tailSamples) * preset->outputFmt->blockAlign;
+	if (req->flags & HMI_PROCESS_QUERY_OUTPUT_SIZE) {
+		req->dstLen = outputBytes;
+
+		if (req->flags & HMI_PROCESS_OVERRIDE_INPUT_FORMAT)
+			preset->inputFmt = savedInput;
+
+		if (req->flags & HMI_PROCESS_OVERRIDE_OUTPUT_FORMAT)
+			preset->outputFmt = savedOutput;
+
+		if (req->flags & HMI_PROCESS_DERIVE_OUTPUT_FORMAT)
+			preset->outputFmt = savedOutput;
+
+		return 0;
+	}
+
+	if (req->flags & HMI_PROCESS_ALLOCATE_OUTPUT) {
+		req->dstBuf = (uint8 *)hmiFXMalloc(outputBytes);
+		if (!req->dstBuf)
+			return 1;
+
+		req->dstLen = outputBytes;
+	}
+
+	resetMixBuffers(preset);
+
+	if (!(preset->flags & HMI_PRESET_FLAG_USE_MALLOC) ||
+		!(preset->flags & HMI_PRESET_FLAG_EFFECTS_INITIALIZED)) {
+		for (HMIEffectNode *n = preset->effectChain; n; n = n->next) {
+			n->outputBufSize = (int)(sourceSamples + tailSamples + preset->chunkSizeInSamples);
+			n->interface->initEffect(preset, n);
+		}
+
+		if (preset->flags & HMI_PRESET_FLAG_USE_MALLOC)
+			preset->flags |= HMI_PRESET_FLAG_EFFECTS_INITIALIZED;
+	}
+
+	uint8 *src = req->srcBuf;
+	uint8 *dst = req->dstBuf;
+	uint32 remaining = sourceSamples;
+	int clamp = (req->flags & HMI_PROCESS_DISABLE_CLAMPING) == 0;
+
+	while (remaining) {
+		uint32 count = remaining < preset->chunkSizeInSamples ? remaining : preset->chunkSizeInSamples;
+		preset->chunkSize = count;
+		convertPCMToFloat(preset, src, count);
+		processEffectChain(preset);
+		convertFloatToPCM(preset, dst, count, clamp);
+		src += count * preset->inputFmt->blockAlign;
+		dst += count * preset->outputFmt->blockAlign;
+		remaining -= count;
+	}
+
+	remaining = tailSamples;
+	while (remaining) {
+		uint32 count = remaining < preset->chunkSizeInSamples ? remaining : preset->chunkSizeInSamples;
+		preset->chunkSize = count;
+		memset(preset->floatBufLeftActive, 0, count * sizeof(float));
+		memset(preset->floatBufRightActive, 0, count * sizeof(float));
+		processEffectChain(preset);
+		convertFloatToPCM(preset, dst, count, clamp);
+		dst += count * preset->outputFmt->blockAlign;
+		remaining -= count;
+	}
+
+	if (req->flags & HMI_PROCESS_OVERRIDE_INPUT_FORMAT)
+		preset->inputFmt = savedInput;
+
+	if (req->flags & HMI_PROCESS_OVERRIDE_OUTPUT_FORMAT)
+		preset->outputFmt = savedOutput;
+
+	if (req->flags & HMI_PROCESS_DERIVE_OUTPUT_FORMAT)
+		preset->outputFmt = savedOutput;
+
+	return 0;
+}
+
+int HMIFxLib::hmiFXPresetProcess(HMILibrary *library, HMIProcessRequest *req) {
+	if (req->flags & HMI_PROCESS_LOOKUP_ONLY) {
+		req->presetPtr = nullptr;
+		return hmiFXPresetGetByName(library, req->effectName, &req->presetPtr);
+	}
+
+	HMIPreset *preset = nullptr;
+	if (req->flags & HMI_PROCESS_USE_PRESET) {
+		preset = req->presetPtr;
+	} else if (req->flags & HMI_PROCESS_FIND_PRESET_BY_NAME) {
+		int result = hmiFXPresetGetByName(library, req->effectName, &preset);
+		if (result)
+			return result;
+
+	} else {
+		return 14;
+	}
+
+	return processPreset(preset, req);
+}
+
+int HMIFxLib::hmiFXPresetProcessEx(HMIProcessRequest *req) {
+	if (req->flags & HMI_PROCESS_LOOKUP_ONLY)
+		return 15;
+
+	if (!(req->flags & HMI_PROCESS_USE_PRESET))
+		return 14;
+
+	return processPreset(req->presetPtr, req);
+}
+
+int HMIFxLib::readFile(HMIFileDescriptor *d, Common::SeekableReadStream &stream) {
+	memset(d, 0, sizeof(*d));
+	const int64 streamSize = stream.size();
+	if (streamSize < 0 || streamSize > 0x7FFFFBFF)
+		return 0;
+
+	d->fileSize = (int)streamSize;
+	d->fileSizeExp = d->fileSize + 1024;
+	if (!stream.seek(0))
+		return 0;
+
+	d->fileBuffer = (uint8 *)malloc(d->fileSizeExp);
+	if (!d->fileBuffer)
+		return 0;
+
+	if ((int)stream.read(d->fileBuffer, d->fileSize) != d->fileSize) {
+		free(d->fileBuffer);
+		d->fileBuffer = nullptr;
+		return 0;
+	}
+
+	d->ptrToDescription = d->fileBuffer;
+	return 1;
+}
+
+int HMIFxLib::flushFile(HMIFileDescriptor *d) {
+	free(d->fileBuffer);
+	d->fileBuffer = nullptr;
+	return 1;
+}
+
+int HMIFxLib::findSection(HMIFileDescriptor *d, const char *section) {
+	uint8 *end = d->fileBuffer + d->fileSize;
+	for (uint8 *p = d->fileBuffer; p < end; ++p) {
+		if (*p != '[')
+			continue;
+
+		uint8 *name = p + 1;
+		const char *s = section;
+		while (name < end && *s && *name == (uint8)*s) {
+			++name;
+			++s;
+		}
+
+		if (!*s && name < end && *name == ']') {
+			while (name < end && *name != '\n')
+				++name;
+
+			if (name < end)
+				++name;
+
+			d->firstPresetPos = (int)(name - d->fileBuffer);
+			d->ptrToDescription = name;
+			d->anotherPtrToDescription = name;
+			d->ptrToFirstPresetSection = p;
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+int HMIFxLib::findKey(HMIFileDescriptor *d, const char *key) {
+	uint8 *p = d->ptrToDescription;
+	uint8 *end = d->fileBuffer + d->fileSize;
+
+	while (p < end && *p != '[') {
+		if (*p == (uint8)*key) {
+			uint8 *start = p;
+			const char *s = key;
+
+			while (p < end && *s && *p == (uint8)*s) {
+				++p;
+				++s;
+			}
+
+			if (!*s) {
+				while (p < end && *p != '=' && *p != '\r') {
+					++p;
+				}
+
+				d->ptrToEffectParams = p < end && *p == '=' ? p + 1 : nullptr;
+				d->currentPos = nullptr;
+				d->ptrToFirstEffectSection = start;
+				return 1;
+			}
+
+			p = start;
+		}
+
+		++p;
+	}
+
+	return 0;
+}
+
+int HMIFxLib::readInt(HMIFileDescriptor *d, int *value) {
+	uint8 *p = d->currentPos ? d->currentPos : d->ptrToEffectParams;
+	if (!p)
+		return 0;
+
+	while (*p == ' ')
+		++p;
+
+	if (*p == '\r' || *p == '\n' || !*p)
+		return 0;
+
+	char token[32];
+	int n = 0;
+	while (*p != ',' && *p != ' ' && *p != '\r' && *p != '\n' && n != 31)
+		token[n++] = (char)*p++;
+
+	token[n] = 0;
+
+	while (*p == ' ')
+		++p;
+
+	if (*p == ',')
+		++p;
+
+	d->currentPos = p;
+
+	if (!n)
+		return 0;
+
+	*value = (int)strtol(token, 0, token[0] == '0' && (token[1] == 'x' || token[1] == 'X') ? 16 : 10);
+	return 1;
+}
+
+int HMIFxLib::readCSV(HMIFileDescriptor *d, char *buffer, int size) {
+	uint8 *p = d->currentPos ? d->currentPos : d->ptrToEffectParams;
+	if (!p)
+		return 0;
+
+	while (*p == ' ')
+		++p;
+
+	int n = 0;
+	if (*p == '"') {
+		++p;
+		while (*p != '\r' && *p != '\n' && n != size - 1) {
+			if (*p == '"') {
+				if (p[1] != '"') {
+					++p;
+					break;
+				}
+
+				++p;
+			}
+
+			buffer[n++] = (char)*p++;
+		}
+	} else {
+		while (*p != ',' && *p != '\r' && *p != '\n' && n != size - 1)
+			buffer[n++] = (char)*p++;
+	}
+
+	buffer[n] = 0;
+
+	while (*p != ',' && *p != '\r' && *p != '\n')
+		++p;
+
+	if (*p == ',')
+		++p;
+
+	d->currentPos = p;
+	return 1;
+}
+
+int HMIFxLib::readSectionInt(HMIFileDescriptor *d, const char *key, int *value) {
+	return findKey(d, key) && readInt(d, value);
+}
+int HMIFxLib::readSectionString(HMIFileDescriptor *d, const char *key, char *value, int size) {
+	return findKey(d, key) && readCSV(d, value, size);
+}
+
+int HMIFxLib::hmiFXPresetLoadLibrary(HMILibrary **outLib, const char *fileName) {
+	Common::File file;
+
+	if (!file.open(fileName))
+		return 10;
+
+	return hmiFXPresetLoadLibrary(outLib, file);
+}
+
+int HMIFxLib::hmiFXPresetLoadLibrary(HMILibrary **outLib, Common::SeekableReadStream &stream) {
+	HMIFileDescriptor d;
+	if (!readFile(&d, stream))
+		return 10;
+
+	HMILibrary *library = (HMILibrary *)hmiFXMalloc(sizeof(HMILibrary));
+	if (!library) {
+		flushFile(&d);
+		return 1;
+	}
+
+	memset(library, 0, sizeof(*library));
+	*outLib = library;
+	if (findSection(&d, "LIBRARY")) {
+		readSectionString(&d, "Description", library->description, 64);
+		readSectionString(&d, "Author", library->authorName, 64);
+	}
+
+	int value;
+	if (findSection(&d, "INPUTFMT")) {
+		readSectionInt(&d, "Rate", &value);
+		library->inputFmt.sampleRate = value;
+		readSectionInt(&d, "BitsPerSample", &value);
+		library->inputFmt.bitsPerSample = (uint16)value;
+		readSectionInt(&d, "Channels", &value);
+		library->inputFmt.numChannels = (uint16)value;
+		hmiFXSetWaveFmtEx(&library->inputFmt, library->inputFmt.sampleRate,
+						  library->inputFmt.bitsPerSample, library->inputFmt.numChannels);
+	}
+
+	if (findSection(&d, "OUTPUTFMT")) {
+		readSectionInt(&d, "Rate", &value);
+		library->outputFmt.sampleRate = value;
+		readSectionInt(&d, "BitsPerSample", &value);
+		library->outputFmt.bitsPerSample = (uint16)value;
+		readSectionInt(&d, "Channels", &value);
+		library->outputFmt.numChannels = (uint16)value;
+		hmiFXSetWaveFmtEx(&library->outputFmt, library->outputFmt.sampleRate,
+						  library->outputFmt.bitsPerSample, library->outputFmt.numChannels);
+	}
+
+	HMIPreset *head = nullptr;
+	char query[64];
+
+	for (unsigned int presetId = 0;; ++presetId) {
+		hmiFXGenerateQueryString(query, "PRESET", presetId);
+		if (!findSection(&d, query))
+			break;
+
+		HMIPreset *preset = (HMIPreset *)hmiFXMalloc(sizeof(HMIPreset));
+		if (!preset) {
+			flushFile(&d);
+			return 1;
+		}
+
+		memset(preset, 0, sizeof(*preset));
+		preset->next = head;
+		readSectionString(&d, "Description", preset->name, 64);
+		readSectionInt(&d, "Flags", (int *)&preset->flags);
+		preset->inputFmt = &library->inputFmt;
+		preset->outputFmt = &library->outputFmt;
+		preset->chunkSizeInMs = 200;
+
+		if (hmiFXPresetCreate(preset)) {
+			flushFile(&d);
+			return 1;
+		}
+
+		for (unsigned int effectId = 0;; ++effectId) {
+			hmiFXGenerateQueryString(query, "Effect", effectId);
+			if (!findKey(&d, query))
+				break;
+
+			int interfaceId;
+			if (!readInt(&d, &interfaceId))
+				break;
+
+			HMIInterface *interface;
+			if (hmiFXGetInterface(interfaceId, &interface)) {
+				flushFile(&d);
+				return 7;
+			}
+
+			HMIEffectNode *node = (HMIEffectNode *)hmiFXMalloc(interface->effectStructSize());
+			if (!node) {
+				flushFile(&d);
+				return 1;
+			}
+
+			memset(node, 0, interface->effectStructSize());
+			node->interface = interface;
+			readInt(&d, &node->outputBus);
+			readInt(&d, (int *)&node->channelMode);
+			readInt(&d, &node->sendChannel);
+
+			char token[64];
+			int param = 0;
+
+			while (readCSV(&d, token, 64) && token[0])
+				interface->setEffectParam(node, param++, (float)atof(token));
+
+			int result = hmiFXPresetAddEffect(preset, node);
+			if (result) {
+				flushFile(&d);
+				return result;
+			}
+		}
+
+		head = preset;
+	}
+
+	library->effectPtr = head;
+	flushFile(&d);
+	return head ? 0 : 12;
+}
+
+int HMIFxLib::hmiFXPresetFreeLibrary(HMILibrary *library) {
+	if (!library)
+		return 12;
+
+	HMIPreset *preset = library->effectPtr;
+	while (preset) {
+		HMIEffectNode *node = preset->effectChain;
+		while (node) {
+			node->interface->uninit(preset, node);
+			HMIEffectNode *next = node->next;
+			hmiFXFree(node);
+			node = next;
+		}
+
+		if (preset->flags & HMI_PRESET_FLAG_USE_MALLOC)
+			hmiFXFree(preset->floatBufLeft0);
+
+		HMIPreset *next = preset->next;
+		hmiFXFree(preset);
+		preset = next;
+	}
+
+	hmiFXFree(library);
+	return 0;
+}
+
+} // End of namespace Audio
diff --git a/audio/effects/hmi/hmifxlib.h b/audio/effects/hmi/hmifxlib.h
new file mode 100644
index 00000000000..97674363f8b
--- /dev/null
+++ b/audio/effects/hmi/hmifxlib.h
@@ -0,0 +1,100 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef AUDIO_EFFECTS_HMI_HMIFXLIB_H
+#define AUDIO_EFFECTS_HMI_HMIFXLIB_H
+
+#include "audio/effects/hmi/hmifxfp.h"
+
+namespace Common {
+class SeekableReadStream;
+}
+
+namespace Audio {
+
+class HMIFxLib {
+public:
+	HMIFxLib();
+	~HMIFxLib();
+
+	HMIFxFp *effects();
+
+	int hmiFXInitSystem(HMIInitData *initData);
+	int hmiFXUnInitSystem(HMIInitData *initData);
+	int hmiFXGetInterface(int interfaceId, HMIInterface **outInterface);
+	unsigned int hmiFXGenerateQueryString(char *buffer, const char *prefix, unsigned int id);
+	int hmiFXGetFirstInterface(HMIInterface **outInterface);
+	int hmiFXGetNextInterface(HMIInterface **outInterface);
+
+	int hmiFXPresetCreate(HMIPreset *preset);
+	int hmiFXPresetDestroy(HMIPreset *preset);
+	int hmiFXPresetAddEffect(HMIPreset *preset, HMIEffectNode *newNode);
+	int hmiFXPresetLoadLibrary(HMILibrary **outLib, const char *fileName);
+	int hmiFXPresetLoadLibrary(HMILibrary **outLib, Common::SeekableReadStream &stream);
+	int hmiFXPresetFreeLibrary(HMILibrary *library);
+	int hmiFXPresetProcess(HMILibrary *library, HMIProcessRequest *request);
+	int hmiFXPresetGetByName(HMILibrary *library, const char *name, HMIPreset **outPreset);
+	int hmiFXPresetLock(HMIPreset *preset);
+	int hmiFXPresetRelease(HMIPreset *preset);
+	int hmiFXPresetGetRouting(HMIPreset *preset, uint32 *routingOut);
+	void hmiFXSetWaveFmtEx(HMIFormat *format, int sampleRate, uint16 bitsPerSample, uint16 channels);
+	int hmiFXPresetCreateInstance(HMIPreset *source, HMIPreset **outInstance);
+	int hmiFXPresetDestroyInstance(HMIPreset *instance);
+	int hmiFXPresetProcessEx(HMIProcessRequest *request);
+
+	void *hmiFXHeapAlloc(int size);
+	void hmiFXHeapFree(void *ptr);
+	int hmiFXHeapInit(HMIInitData *initData);
+	void *hmiFXHeapReset();
+	void *hmiFXMalloc(size_t size);
+	void hmiFXFree(void *ptr);
+
+private:
+	int convertPCMToFloat(HMIPreset *preset, const uint8 *buffer, int samples);
+	int convertFloatToPCM(HMIPreset *preset, uint8 *buffer, int samples, int clampOutput);
+	int processPreset(HMIPreset *preset, HMIProcessRequest *request);
+	void resetMixBuffers(HMIPreset *preset);
+	void processEffectChain(HMIPreset *preset);
+
+	int readFile(HMIFileDescriptor *desc, Common::SeekableReadStream &stream);
+	int flushFile(HMIFileDescriptor *desc);
+	int findSection(HMIFileDescriptor *desc, const char *section);
+	int findKey(HMIFileDescriptor *desc, const char *key);
+	int readInt(HMIFileDescriptor *desc, int *value);
+	int readCSV(HMIFileDescriptor *desc, char *buffer, int size);
+	int readSectionInt(HMIFileDescriptor *desc, const char *key, int *value);
+	int readSectionString(HMIFileDescriptor *desc, const char *key, char *value, int size);
+
+	HMIFxFp _fxFp;
+	HMIInterface *_loadedInterfaces[1024];
+	unsigned int _numLoadedInterfaces;
+	unsigned int _curInterfaceIndex;
+
+	uint8 *_systemHeap;
+	uint8 *_heapCursor;
+	uint8 *_heapEnd;
+	void *(*_mallocFunc)(size_t);
+	void (*_freeFunc)(void *);
+};
+
+} // End of namespace Audio
+
+#endif
diff --git a/audio/effects/hmi/interfaces/envelope.cpp b/audio/effects/hmi/interfaces/envelope.cpp
new file mode 100644
index 00000000000..7537a10e827
--- /dev/null
+++ b/audio/effects/hmi/interfaces/envelope.cpp
@@ -0,0 +1,132 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "audio/effects/hmi/interfaces/envelope.h"
+
+namespace Audio {
+
+const char *const HMIEnvelope::kEnvelopeParams[] = {"Envelope Points", "Envelope Duration"};
+const float HMIEnvelope::kEnvelopeMin[] = {2.0f, 0.0f, 0.0f, 0.5f, 1.0f, 0.5f, -1.0f, 0.0f};
+const float HMIEnvelope::kEnvelopeMax[] = {2.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
+const float HMIEnvelope::kEnvelopeDefault[] = {8.0f, 1000.0f, 1.0f, 1.0f, 1.0f, 1.0f};
+
+HMIEnvelope::HMIEnvelope()
+	: HMIInterface(sizeof(HMIEnvelopeNode), 1, "DLGEnvelope",
+				   kEnvelopeParams, kEnvelopeMin, kEnvelopeMax, kEnvelopeDefault,
+				   "Envelope", 2910, 18) {}
+
+int HMIEnvelope::init(HMIPreset *, HMIEffectNode *) {
+	return 0;
+}
+
+int HMIEnvelope::uninit(HMIPreset *, HMIEffectNode *) {
+	return 0;
+}
+
+int HMIEnvelope::initEffect(HMIPreset *, HMIEffectNode *base) {
+	HMIEnvelopeNode *n = (HMIEnvelopeNode *)base;
+
+	if (n->initGuard == 0.0f) {
+		n->currentAmp = n->pointAmp[0];
+		n->currentSegment = 0;
+
+		for (int i = 1; (double)(uint32)i < n->envPoints; ++i) {
+			int samples = (int)((double)n->pointTime[i] * (uint32)n->outputBufSize - (double)n->pointTime[i - 1] * (uint32)n->outputBufSize);
+			n->segRemaining[i] = samples;
+			n->segSlopes[i] = (float)(((double)n->pointAmp[i] - n->pointAmp[i - 1]) / (uint32)samples);
+		}
+	}
+
+	return 0;
+}
+
+int HMIEnvelope::processBlock(HMIPreset *preset, HMIEffectNode *base) {
+	HMIEnvelopeNode *n = (HMIEnvelopeNode *)base;
+	float *in = preset->floatBufLeftActive;
+	float *out = preset->floatBufLeftAlt;
+	int remainingChunk = (int)preset->chunkSize;
+	int segment = n->currentSegment;
+	int remaining = n->segRemaining[segment];
+
+	for (;;) {
+		int left = remainingChunk;
+		while (left) {
+			if (!remaining--)
+				break;
+
+			*out++ = (float)((double)*in++ * n->currentAmp);
+			n->currentAmp = n->segSlopes[segment] + n->currentAmp;
+			--left;
+		}
+
+		if (!left)
+			break;
+
+		segment = ++n->currentSegment;
+		remainingChunk = left;
+		remaining = n->segRemaining[segment];
+	}
+
+	n->segRemaining[segment] = remaining;
+	return 0;
+}
+
+int HMIEnvelope::getEffectParam(HMIEffectNode *base, int p, float *v, int *type) {
+	HMIEnvelopeNode *n = (HMIEnvelopeNode *)base;
+	if (p == 0) {
+		*v = n->envPoints;
+	} else if (p == 1) {
+		*v = n->initGuard;
+		*type = 0;
+		return 0;
+	} else if (p >= 2 && p <= 17) {
+		int index = (p - 2) >> 1;
+		*v = (p & 1) ? n->pointAmp[index] : n->pointTime[index];
+	} else {
+		return 11;
+	}
+
+	*type = 3;
+	return 0;
+}
+
+int HMIEnvelope::setEffectParam(HMIEffectNode *base, int p, float v) {
+	HMIEnvelopeNode *n = (HMIEnvelopeNode *)base;
+	if (p == 0) {
+		n->envPoints = v;
+	} else if (p == 1) {
+		n->initGuard = v;
+	} else if (p >= 2 && p <= 17) {
+		int index = (p - 2) >> 1;
+
+		if (p & 1) {
+			n->pointAmp[index] = v;
+		} else {
+			n->pointTime[index] = v;
+		}
+	} else {
+		return 11;
+	}
+
+	return 0;
+}
+
+} // End of namespace Audio
diff --git a/audio/effects/hmi/interfaces/envelope.h b/audio/effects/hmi/interfaces/envelope.h
new file mode 100644
index 00000000000..30498868a1f
--- /dev/null
+++ b/audio/effects/hmi/interfaces/envelope.h
@@ -0,0 +1,48 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef AUDIO_EFFECTS_HMI_INTERFACES_ENVELOPE_H
+#define AUDIO_EFFECTS_HMI_INTERFACES_ENVELOPE_H
+
+#include "audio/effects/hmi/hmi_interface.h"
+
+namespace Audio {
+
+class HMIEnvelope : public HMIInterface {
+public:
+	HMIEnvelope();
+	int init(HMIPreset *, HMIEffectNode *) override;
+	int uninit(HMIPreset *, HMIEffectNode *) override;
+	int processBlock(HMIPreset *, HMIEffectNode *) override;
+	int initEffect(HMIPreset *, HMIEffectNode *) override;
+	int getEffectParam(HMIEffectNode *, int, float *, int *) override;
+	int setEffectParam(HMIEffectNode *, int, float) override;
+
+private:
+	static const char *const kEnvelopeParams[];
+	static const float kEnvelopeMin[];
+	static const float kEnvelopeMax[];
+	static const float kEnvelopeDefault[];
+};
+
+} // End of namespace Audio
+
+#endif
diff --git a/audio/effects/hmi/interfaces/filter1.cpp b/audio/effects/hmi/interfaces/filter1.cpp
new file mode 100644
index 00000000000..84003c28f48
--- /dev/null
+++ b/audio/effects/hmi/interfaces/filter1.cpp
@@ -0,0 +1,158 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "audio/effects/hmi/interfaces/filter1.h"
+
+namespace Audio {
+
+const char *const HMIFilter1::kFilter1Params[] = {"Filter Type", "Cutoff Frequency", "Center Frequency", "Band Width"};
+const float HMIFilter1::kFilter1Min[] = {1024.0f, 1000.0f, 0.0f, 0.0f, -1.0f, 0.0f};
+const float HMIFilter1::kFilter1Max[] = {1024.0f, 0.0f, 0.0f, 0.0f};
+const float HMIFilter1::kFilter1Default[] = {1026.0f, 10000.0f, 10000.0f, 2000.0f};
+
+HMIFilter1::HMIFilter1()
+	: HMIInterface(sizeof(HMIFilter1Node), 1, "DLGFilterMIMO",
+				   kFilter1Params, kFilter1Min, kFilter1Max, kFilter1Default,
+				   "Filter 1", 2300, 4) {}
+
+int HMIFilter1::init(HMIPreset *, HMIEffectNode *) {
+	return 0; 
+}
+
+int HMIFilter1::uninit(HMIPreset *, HMIEffectNode *) {
+	return 0; 
+}
+
+int HMIFilter1::initEffect(HMIPreset *preset, HMIEffectNode *base) {
+	HMIFilter1Node *node = (HMIFilter1Node *)base;
+
+	node->state_x1 = node->state_x2 = node->state_x3 = node->state_y1 = 0.0f;
+	node->state_x1b = node->state_x2b = node->state_x3b = node->state_y1b = 0.0f;
+	double sampleRate = (double)preset->inputFmt->sampleRate;
+
+	if (node->filterType == 1024 || node->filterType == 1025) {
+		double nyquist = (double)(preset->inputFmt->sampleRate >> 1);
+		double frequency = node->cutoffFrequency;
+
+		if (frequency >= nyquist)
+			frequency = nyquist;
+
+		double angle = frequency * kHmiPi / sampleRate;
+		double c = node->filterType == 1024 ? 1.0 / tan(angle) : tan(angle);
+		double c2 = c * c;
+		double root = sqrt(2.0) * c;
+
+		float gain = (float)(1.0 / (c2 + root + 1.0));
+		node->coeff_b0 = gain;
+		node->coeff_b1 = node->filterType == 1024 ? gain + gain : gain * -2.0f;
+		node->coeff_b2 = gain;
+
+		double a = node->filterType == 1024 ? 1.0 - c2 : c2 - 1.0;
+		node->coeff_a1 = (float)(a * gain + a * gain);
+		node->coeff_a2 = (float)((c2 - (root - 1.0)) * gain);
+	} else if (node->filterType == 1026) {
+		double c = 1.0 / tan((double)node->bandWidth * kHmiPi / sampleRate);
+		double cosine = cos((double)node->centerFrequency * kHmiTwoPi / sampleRate);
+		float gain = (float)(1.0 / (c + 1.0));
+
+		node->coeff_b0 = gain;
+		node->coeff_b1 = 0.0f;
+		node->coeff_b2 = -gain;
+		node->coeff_a1 = (float)(-((cosine + cosine) * c * gain));
+		node->coeff_a2 = (float)((c - 1.0) * gain);
+	} else if (node->filterType == 1027) {
+		float tangent = (float)tan((double)node->bandWidth * kHmiPi / sampleRate);
+		double twiceCosine = cos((double)node->centerFrequency * kHmiTwoPi / sampleRate) * 2.0;
+		float gain = (float)(1.0 / ((double)tangent + 1.0));
+		float a1 = (float)(-(twiceCosine * gain));
+
+		node->coeff_b0 = gain;
+		node->coeff_b1 = a1;
+		node->coeff_b2 = gain;
+		node->coeff_a1 = a1;
+		node->coeff_a2 = (1.0f - tangent) * gain;
+	}
+
+	return 0;
+}
+
+int HMIFilter1::processBlock(HMIPreset *preset, HMIEffectNode *base) {
+	HMIFilter1Node *n = (HMIFilter1Node *)base;
+
+	for (uint32 i = 0; i != preset->chunkSize; ++i) {
+		double input = preset->floatBufLeftActive[i];
+		float output = (float)(input * n->coeff_b0 + (double)n->state_x1 * n->coeff_b1 + (double)n->state_x2 * n->coeff_b2 - (double)n->coeff_a1 * n->state_x3 - (double)n->state_y1 * n->coeff_a2);
+		preset->floatBufLeftAlt[i] = output;
+		
+		float x1 = n->state_x1;
+		float y1 = n->state_x3;
+		
+		n->state_x1 = (float)input;
+		n->state_x2 = x1;
+		n->state_y1 = y1;
+		n->state_x3 = output;
+	}
+
+	return 0;
+}
+
+int HMIFilter1::getEffectParam(HMIEffectNode *base, int p, float *v, int *type) {
+	HMIFilter1Node *n = (HMIFilter1Node *)base;
+	
+	if (p == 0) {
+		*v = (float)(uint32)n->filterType;
+		*type = 3;
+		return 0;
+	}
+
+	if (p == 1) {
+		*v = n->cutoffFrequency;
+	} else if (p == 2) {
+		*v = n->centerFrequency;
+	} else if (p == 3) {
+		*v = n->bandWidth;
+	} else {
+		return 11;
+	}
+
+	*type = 1;
+	return 0;
+}
+
+int HMIFilter1::setEffectParam(HMIEffectNode *base, int p, float v) {
+	HMIFilter1Node *n = (HMIFilter1Node *)base;
+
+	if (p == 0) {
+		n->filterType = (int)(v);
+	} else if (p == 1) {
+		n->cutoffFrequency = v;
+	} else if (p == 2) {
+		n->centerFrequency = v;
+	} else if (p == 3) {
+		n->bandWidth = v;
+	} else {
+		return 11;
+	}
+
+	return 0;
+}
+
+} // End of namespace Audio
diff --git a/audio/effects/hmi/interfaces/filter1.h b/audio/effects/hmi/interfaces/filter1.h
new file mode 100644
index 00000000000..c6dcf4b1427
--- /dev/null
+++ b/audio/effects/hmi/interfaces/filter1.h
@@ -0,0 +1,48 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef AUDIO_EFFECTS_HMI_INTERFACES_FILTER1_H
+#define AUDIO_EFFECTS_HMI_INTERFACES_FILTER1_H
+
+#include "audio/effects/hmi/hmi_interface.h"
+
+namespace Audio {
+
+class HMIFilter1 : public HMIInterface {
+public:
+	HMIFilter1();
+	int init(HMIPreset *, HMIEffectNode *) override;
+	int uninit(HMIPreset *, HMIEffectNode *) override;
+	int processBlock(HMIPreset *, HMIEffectNode *) override;
+	int initEffect(HMIPreset *, HMIEffectNode *) override;
+	int getEffectParam(HMIEffectNode *, int, float *, int *) override;
+	int setEffectParam(HMIEffectNode *, int, float) override;
+
+private:
+	static const char *const kFilter1Params[];
+	static const float kFilter1Min[];
+	static const float kFilter1Max[];
+	static const float kFilter1Default[];
+};
+
+} // End of namespace Audio
+
+#endif
diff --git a/audio/effects/hmi/interfaces/mono_delay.cpp b/audio/effects/hmi/interfaces/mono_delay.cpp
new file mode 100644
index 00000000000..a06f5be5895
--- /dev/null
+++ b/audio/effects/hmi/interfaces/mono_delay.cpp
@@ -0,0 +1,133 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "audio/effects/hmi/interfaces/mono_delay.h"
+
+namespace Audio {
+
+const char *const HMIMonoDelay::kMonoDelayParams[] = {"Delay Max", "Delay Time", "Feedback", "Dry Out", "Wet Out"};
+const float HMIMonoDelay::kMonoDelayMin[] = {1000.0f, 100.0f, 0.5f, 0.9f, 0.9f, -1.0f};
+const float HMIMonoDelay::kMonoDelayMax[] = {1000.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
+const float HMIMonoDelay::kMonoDelayDefault[] = {1000.0f, 1000.0f, 1.0f, 1.0f, 1.0f, 0.0f};
+
+HMIMonoDelay::HMIMonoDelay()
+	: HMIInterface(sizeof(HMIMonoDelayNode), 1, "DLGDelayMIMO",
+				   kMonoDelayParams, kMonoDelayMin, kMonoDelayMax, kMonoDelayDefault,
+				   "Mono Delay 1", 2000, 5) {}
+
+int HMIMonoDelay::init(HMIPreset *preset, HMIEffectNode *base) {
+	HMIMonoDelayNode *n = (HMIMonoDelayNode *)base;
+
+	int bytes = 4 * (int)((double)preset->inputFmt->sampleRate * n->maxDelayTime * kHmiMillis);
+	n->bufSizeBytes = bytes;
+	n->delayBuf = (float *)malloc(bytes);
+
+	if (!n->delayBuf)
+		return 1;
+
+	n->writeIndex = 0;
+	return 0;
+}
+
+int HMIMonoDelay::uninit(HMIPreset *, HMIEffectNode *base) {
+	HMIMonoDelayNode *n = (HMIMonoDelayNode *)base;
+	free(n->delayBuf);
+	return 0;
+}
+
+int HMIMonoDelay::initEffect(HMIPreset *, HMIEffectNode *base) {
+	HMIMonoDelayNode *n = (HMIMonoDelayNode *)base;
+	n->writeIndex = 0;
+	memset(n->delayBuf, 0, n->bufSizeBytes);
+	return 0;
+}
+
+int HMIMonoDelay::getMinDuration(HMIEffectNode *base, uint32 *out) {
+	HMIMonoDelayNode *n = (HMIMonoDelayNode *)base;
+	*out = (uint32)(log(kHmiMillis) / log(n->feedback) * n->delayTime);
+	return 0;
+}
+
+int HMIMonoDelay::processBlock(HMIPreset *preset, HMIEffectNode *base) {
+	HMIMonoDelayNode *n = (HMIMonoDelayNode *)base;
+
+	int delaySamples = (int)((double)preset->inputFmt->sampleRate * n->delayTime * kHmiMillis);
+	int index = n->writeIndex;
+
+	for (uint32 i = 0; i != preset->chunkSize; ++i) {
+		double input = preset->floatBufLeftActive[i];
+		float delayed = n->delayBuf[index];
+		preset->floatBufLeftAlt[i] = (float)(input * n->dryOut + (double)delayed * n->wetOut);
+		n->delayBuf[index] = (float)((double)delayed * n->feedback + input);
+	
+		if (++index == delaySamples)
+			index = 0;
+	}
+
+	n->writeIndex = index;
+	return 0;
+}
+
+int HMIMonoDelay::getEffectParam(HMIEffectNode *base, int p, float *v, int *type) {
+	HMIMonoDelayNode *n = (HMIMonoDelayNode *)base;
+
+	if (p == 0) {
+		*v = n->maxDelayTime;
+		*type = 0;
+	} else if (p == 1) {
+		*v = n->delayTime;
+		*type = 0;
+	} else if (p == 2) {
+		*v = n->feedback;
+		*type = 2;
+	} else if (p == 3) {
+		*v = n->dryOut;
+		*type = 2;
+	} else if (p == 4) {
+		*v = n->wetOut;
+		*type = 2;
+	} else {
+		return 11;
+	}
+	return 0;
+}
+
+int HMIMonoDelay::setEffectParam(HMIEffectNode *base, int p, float v) {
+	HMIMonoDelayNode *n = (HMIMonoDelayNode *)base;
+
+	if (p == 0) {
+		n->maxDelayTime = v;
+	} else if (p == 1) {
+		n->delayTime = v;
+	} else if (p == 2) {
+		n->feedback = v;
+	} else if (p == 3) {
+		n->dryOut = v;
+	} else if (p == 4) {
+		n->wetOut = v;
+	} else {
+		return 11;
+	}
+
+	return 0;
+}
+
+} // End of namespace Audio
diff --git a/audio/effects/hmi/interfaces/mono_delay.h b/audio/effects/hmi/interfaces/mono_delay.h
new file mode 100644
index 00000000000..ce16bf68247
--- /dev/null
+++ b/audio/effects/hmi/interfaces/mono_delay.h
@@ -0,0 +1,49 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef AUDIO_EFFECTS_HMI_INTERFACES_MONO_DELAY_H
+#define AUDIO_EFFECTS_HMI_INTERFACES_MONO_DELAY_H
+
+#include "audio/effects/hmi/hmi_interface.h"
+
+namespace Audio {
+
+class HMIMonoDelay : public HMIInterface {
+public:
+	HMIMonoDelay();
+	int init(HMIPreset *, HMIEffectNode *) override;
+	int uninit(HMIPreset *, HMIEffectNode *) override;
+	int getMinDuration(HMIEffectNode *, uint32 *) override;
+	int processBlock(HMIPreset *, HMIEffectNode *) override;
+	int initEffect(HMIPreset *, HMIEffectNode *) override;
+	int getEffectParam(HMIEffectNode *, int, float *, int *) override;
+	int setEffectParam(HMIEffectNode *, int, float) override;
+
+private:
+	static const char *const kMonoDelayParams[];
+	static const float kMonoDelayMin[];
+	static const float kMonoDelayMax[];
+	static const float kMonoDelayDefault[];
+};
+
+} // End of namespace Audio
+
+#endif
diff --git a/audio/effects/hmi/interfaces/phasor.cpp b/audio/effects/hmi/interfaces/phasor.cpp
new file mode 100644
index 00000000000..1360b63fd65
--- /dev/null
+++ b/audio/effects/hmi/interfaces/phasor.cpp
@@ -0,0 +1,148 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "audio/effects/hmi/interfaces/phasor.h"
+
+namespace Audio {
+
+const char *const HMIPhasor::kPhasorParams[] = {
+	"Feedback", "Rate", "Range", "Base Frequency", "Dry Out", "Wet Out"};
+const float HMIPhasor::kPhasorMin[] = {0.8f, 2.0f, 1.0f, 100.0f, 0.5f, 0.9f, -1.0f, 0.0f};
+const float HMIPhasor::kPhasorMax[] = {0x7FC00000, 0x7FC00000, 0x7FC00000, 0x7FC00000, 0x7FC00000, 0x7FC00000}; // Meaning: NaN
+const float HMIPhasor::kPhasorDefault[] = {1.0f, 32.0f, 12.0f, 1000.0f, 1.0f, 1.0f};
+
+HMIPhasor::HMIPhasor()
+	: HMIInterface(sizeof(HMIPhasorNode), 1, "DLGPhasor",
+				   kPhasorParams, kPhasorMin, kPhasorMax, kPhasorDefault,
+				   "Phasor", 2375, 6) {}
+
+int HMIPhasor::init(HMIPreset *, HMIEffectNode *) {
+	return 0;
+}
+
+int HMIPhasor::uninit(HMIPreset *, HMIEffectNode *) {
+	return 0;
+}
+
+int HMIPhasor::initEffect(HMIPreset *preset, HMIEffectNode *base) {
+	HMIPhasorNode *n = (HMIPhasorNode *)base;
+
+	double rate = preset->inputFmt->sampleRate;
+	float lower = (float)((double)n->feedback * kHmiPi / rate);
+	n->phase = lower;
+	n->coeff = lower;
+	float top = (float)pow(2.0, (double)n->centerFrequency);
+	n->state_x2R = top;
+	n->modPhase = (float)((double)n->feedback * top * kHmiPi / rate);
+	float multiplier = (float)pow((double)top,
+								  (double)(n->depth / (double)(preset->inputFmt->sampleRate >> 1)));
+	n->state_y2R = multiplier;
+	n->state_y2L = multiplier;
+	n->b0 = n->b1 = n->a1 = 0.0f;
+	n->state_x1L = n->state_y1L = n->state_x1R = n->state_y1R = n->state_x2L = 0.0f;
+
+	return 0;
+}
+
+int HMIPhasor::processBlock(HMIPreset *preset, HMIEffectNode *base) {
+	HMIPhasorNode *n = (HMIPhasorNode *)base;
+
+	for (uint32 i = 0; i != preset->chunkSize; ++i) {
+		float input = preset->floatBufLeftActive[i];
+		double k = (1.0 - n->phase) / ((double)n->phase + 1.0);
+		double feedbackState = (double)n->state_x2L * n->rate + input;
+
+		float stage1 = (float)((feedbackState + n->b1) * k - n->b0);
+		n->b0 = (float)feedbackState;
+		n->b1 = stage1;
+
+		float stage2 = (float)(((double)n->b1 + n->state_x1L) * k - n->a1);
+		n->a1 = n->b1;
+		n->state_x1L = stage2;
+
+		float stage3 = (float)(((double)n->state_x1R + n->state_x1L) * k - n->state_y1L);
+		n->state_y1L = n->state_x1L;
+		n->state_x1R = stage3;
+
+		float stage4 = (float)(((double)n->state_x2L + n->state_x1R) * k - n->state_y1R);
+		n->state_y1R = n->state_x1R;
+		n->state_x2L = stage4;
+
+		preset->floatBufLeftAlt[i] = (float)((double)input * n->dryOut + (double)n->wetOut * stage4);
+		double phase = (double)n->state_y2L * n->phase;
+		n->phase = (float)phase;
+
+		if (phase > n->modPhase) {
+			n->state_y2L = 1.0f / n->state_y2R;
+		} else if (phase < n->coeff) {
+			n->state_y2L = n->state_y2R;
+		}
+	}
+
+	return 0;
+}
+
+int HMIPhasor::getEffectParam(HMIEffectNode *base, int p, float *v, int *type) {
+	HMIPhasorNode *n = (HMIPhasorNode *)base;
+
+	if (p == 0) {
+		*v = n->rate;
+	} else if (p == 1) {
+		*v = n->depth;
+	} else if (p == 2) {
+		*v = n->centerFrequency;
+	} else if (p == 3) {
+		*v = n->feedback;
+	} else if (p == 4) {
+		*v = n->dryOut;
+	} else if (p == 5) {
+		*v = n->wetOut;
+	} else {
+		return 11;
+	}
+
+	*type = 1;
+	return 0;
+}
+
+int HMIPhasor::setEffectParam(HMIEffectNode *base, int p, float v) {
+	HMIPhasorNode *n = (HMIPhasorNode *)base;
+
+	if (p == 0) {
+		n->rate = v;
+	} else if (p == 1) {
+		n->depth = v;
+	} else if (p == 2) {
+		n->centerFrequency = v;
+	} else if (p == 3) {
+		n->feedback = v;
+	} else if (p == 4) {
+		n->dryOut = v;
+	} else if (p == 5) {
+		n->wetOut = v;
+	} else {
+		return 11;
+	}
+
+	return 0;
+}
+
+} // End of namespace Audio
diff --git a/audio/effects/hmi/interfaces/phasor.h b/audio/effects/hmi/interfaces/phasor.h
new file mode 100644
index 00000000000..cc4b27c670b
--- /dev/null
+++ b/audio/effects/hmi/interfaces/phasor.h
@@ -0,0 +1,48 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef AUDIO_EFFECTS_HMI_INTERFACES_PHASOR_H
+#define AUDIO_EFFECTS_HMI_INTERFACES_PHASOR_H
+
+#include "audio/effects/hmi/hmi_interface.h"
+
+namespace Audio {
+
+class HMIPhasor : public HMIInterface {
+public:
+	HMIPhasor();
+	int init(HMIPreset *, HMIEffectNode *) override;
+	int uninit(HMIPreset *, HMIEffectNode *) override;
+	int processBlock(HMIPreset *, HMIEffectNode *) override;
+	int initEffect(HMIPreset *, HMIEffectNode *) override;
+	int getEffectParam(HMIEffectNode *, int, float *, int *) override;
+	int setEffectParam(HMIEffectNode *, int, float) override;
+
+private:
+	static const char *const kPhasorParams[];
+	static const float kPhasorMin[];
+	static const float kPhasorMax[];
+	static const float kPhasorDefault[];
+};
+
+} // End of namespace Audio
+
+#endif
diff --git a/audio/effects/hmi/interfaces/resonator.cpp b/audio/effects/hmi/interfaces/resonator.cpp
new file mode 100644
index 00000000000..8b32ba322f0
--- /dev/null
+++ b/audio/effects/hmi/interfaces/resonator.cpp
@@ -0,0 +1,104 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "audio/effects/hmi/interfaces/resonator.h"
+
+namespace Audio {
+
+const char *const HMIResonator::kResonatorParams[] = {"Center Frequency", "Band Width"};
+const float HMIResonator::kResonatorMin[] = {1000.0f, 200.0f, -1.0f, 0.0f};
+const float HMIResonator::kResonatorMax[] = {1.0f, 1.0f};
+const float HMIResonator::kResonatorDefault[] = {10000.0f, 3000.0f};
+
+HMIResonator::HMIResonator()
+	: HMIInterface(sizeof(HMIResonatorNode), 1, "DLGResonator",
+				   kResonatorParams, kResonatorMin, kResonatorMax, kResonatorDefault,
+				   "Resonator", 2350, 2) {}
+
+int HMIResonator::init(HMIPreset *, HMIEffectNode *) {
+	return 0;
+}
+
+int HMIResonator::uninit(HMIPreset *, HMIEffectNode *) {
+	return 0;
+}
+
+int HMIResonator::initEffect(HMIPreset *preset, HMIEffectNode *base) {
+	HMIResonatorNode *n = (HMIResonatorNode *)base;
+
+	double rate = (double)preset->inputFmt->sampleRate;
+	double radius = pow(2.0, n->bandWidth / rate * -kHmiTwoPi * 1.442695040888963407);
+	n->coeff2 = (float)radius;
+	n->stateX1 = 0.0f;
+	n->stateX2 = 0.0f;
+
+	double c = cos(n->cutoffFrequency / rate * kHmiTwoPi) * (radius * -4.0 / (radius + 1.0));
+	n->coeff1 = (float)c;
+	n->resonance = (float)(sqrt(1.0 - c * c / ((double)n->coeff2 * 4.0)) * (1.0 - n->coeff2));
+
+	return 0;
+}
+
+int HMIResonator::processBlock(HMIPreset *preset, HMIEffectNode *base) {
+	HMIResonatorNode *n = (HMIResonatorNode *)base;
+
+	for (uint32 i = 0; i != preset->chunkSize; ++i) {
+		double a = (double)preset->floatBufLeftActive[i] * n->resonance - (double)n->stateX1 * n->coeff1;
+		float output = (float)(a - (double)n->coeff2 * n->stateX2);
+		preset->floatBufLeftAlt[i] = output;
+		float previous = n->stateX1;
+		n->stateX1 = output;
+		n->stateX2 = previous;
+	}
+
+	return 0;
+}
+
+int HMIResonator::getEffectParam(HMIEffectNode *base, int p, float *v, int *type) {
+	HMIResonatorNode *n = (HMIResonatorNode *)base;
+
+	if (p == 0) {
+		*v = n->cutoffFrequency;
+	} else if (p == 1) {
+		*v = n->bandWidth;
+	} else {
+		return 11;
+	}
+
+	*type = 1;
+	return 0;
+}
+
+int HMIResonator::setEffectParam(HMIEffectNode *base, int p, float v) {
+	HMIResonatorNode *n = (HMIResonatorNode *)base;
+
+	if (p == 0) {
+		n->cutoffFrequency = v;
+	} else if (p == 1) {
+		n->bandWidth = v;
+	} else {
+		return 11;
+	}
+
+	return 0;
+}
+
+} // End of namespace Audio
diff --git a/audio/effects/hmi/interfaces/resonator.h b/audio/effects/hmi/interfaces/resonator.h
new file mode 100644
index 00000000000..faf4d0763c7
--- /dev/null
+++ b/audio/effects/hmi/interfaces/resonator.h
@@ -0,0 +1,48 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef AUDIO_EFFECTS_HMI_INTERFACES_RESONATOR_H
+#define AUDIO_EFFECTS_HMI_INTERFACES_RESONATOR_H
+
+#include "audio/effects/hmi/hmi_interface.h"
+
+namespace Audio {
+
+class HMIResonator : public HMIInterface {
+public:
+	HMIResonator();
+	int init(HMIPreset *, HMIEffectNode *) override;
+	int uninit(HMIPreset *, HMIEffectNode *) override;
+	int processBlock(HMIPreset *, HMIEffectNode *) override;
+	int initEffect(HMIPreset *, HMIEffectNode *) override;
+	int getEffectParam(HMIEffectNode *, int, float *, int *) override;
+	int setEffectParam(HMIEffectNode *, int, float) override;
+
+private:
+	static const char *const kResonatorParams[];
+	static const float kResonatorMin[];
+	static const float kResonatorMax[];
+	static const float kResonatorDefault[];
+};
+
+} // End of namespace Audio
+
+#endif
diff --git a/audio/effects/hmi/interfaces/reverb1.cpp b/audio/effects/hmi/interfaces/reverb1.cpp
new file mode 100644
index 00000000000..f4f7160d065
--- /dev/null
+++ b/audio/effects/hmi/interfaces/reverb1.cpp
@@ -0,0 +1,228 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "audio/effects/hmi/interfaces/reverb1.h"
+
+namespace Audio {
+
+const char *const HMIReverb1::kReverb1Params[] = {"Reverb Max", "Reverb Pre-Delay", "Reverb Time", "Dry Out", "Wet Out"};
+const float HMIReverb1::kReverb1Min[] = {1000.0f, 0.0f, 100.0f, 0.9f, 0.3f, -1.0f};
+const float HMIReverb1::kReverb1Max[] = {1000.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
+const float HMIReverb1::kReverb1Default[] = {1000.0f, 250.0f, 100.0f, 1.0f, 1.0f, 0.0f};
+
+HMIReverb1::HMIReverb1()
+	: HMIInterface(sizeof(HMIReverb1Node), 3, "DLGReverbMISO",
+				   kReverb1Params, kReverb1Min, kReverb1Max, kReverb1Default,
+				   "Reverb 1", 2101, 5) {}
+
+const float HMIReverb1::kReverb1Delay[4] = {0.16463099420070648f, 0.5134339928627014f, 1.0f, 0.8304839730262756f};
+
+int HMIReverb1::init(HMIPreset *preset, HMIEffectNode *base) {
+	HMIReverb1Node *n = (HMIReverb1Node *)base;
+
+	int bytes = 4 * (int)((double)preset->inputFmt->sampleRate * n->reverbMax * kHmiMillis);
+	n->bufSizeBytes = bytes;
+
+	for (int i = 0; i != 4; ++i) {
+		n->echoStages[i].buffer = (float *)malloc(bytes);
+		if (!n->echoStages[i].buffer) {
+			while (i) {
+				free(n->echoStages[--i].buffer);
+			}
+
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+int HMIReverb1::uninit(HMIPreset *, HMIEffectNode *base) {
+	HMIReverb1Node *n = (HMIReverb1Node *)base;
+
+	for (int i = 0; i != 4; ++i) {
+		free(n->echoStages[i].buffer);
+	}
+
+	return 0;
+}
+
+int HMIReverb1::initEffect(HMIPreset *preset, HMIEffectNode *base) {
+	HMIReverb1Node *n = (HMIReverb1Node *)base;
+
+	double total = (double)preset->inputFmt->sampleRate * n->reverbTime * kHmiMillis;
+
+	for (int i = 0; i != 4; ++i) {
+		HMIReverbEchoStage *s = &n->echoStages[i];
+		memset(s->buffer, 0, n->bufSizeBytes);
+		double samples = total * kReverb1Delay[i];
+		s->bufSizeInSamples = (int)(samples)-2;
+		s->writeHead = 0;
+		s->readHead = (int)(samples * 0.5);
+		s->lastOutput = 0.0f;
+	}
+
+	n->preDelaySamples = (int)((double)preset->inputFmt->sampleRate * n->preDelay * kHmiMillis);
+	return 0;
+}
+
+int HMIReverb1::getMinDuration(HMIEffectNode *base, uint32 *out) {
+	HMIReverb1Node *n = (HMIReverb1Node *)base;
+	uint32 duration = (uint32)(log(kHmiMillis) / log(0.7) * n->reverbTime);
+	*out = duration / 3;
+	return 0;
+}
+
+static float reverb1Stage(HMIReverbEchoStage *s, double input, double coefficient) {
+	double previous = s->lastOutput;
+	float written = (float)(previous * coefficient + input);
+	s->buffer[s->writeHead] = written;
+
+	if (++s->writeHead == s->bufSizeInSamples)
+		s->writeHead = 0;
+
+	s->lastOutput = s->buffer[s->readHead];
+
+	if (++s->readHead == s->bufSizeInSamples)
+		s->readHead = 0;
+
+	return (float)((double)written * -coefficient + previous);
+}
+
+static float reverb1DelayStage(HMIReverbEchoStage *s, double input, double coefficient) {
+	s->buffer[s->writeHead] = (float)((double)s->lastOutput * coefficient + input);
+
+	if (++s->writeHead == s->bufSizeInSamples)
+		s->writeHead = 0;
+
+	s->lastOutput = s->buffer[s->readHead];
+
+	if (++s->readHead == s->bufSizeInSamples)
+		s->readHead = 0;
+
+	return s->lastOutput;
+}
+
+static int reverb1Mono(HMIPreset *preset, HMIReverb1Node *n) {
+	uint32 outIndex = 0;
+	while (n->preDelaySamples && outIndex != preset->chunkSize) {
+		// The mono DLL path advances only the destination during pre-delay...
+		preset->floatBufLeftAlt[outIndex] = (float)((double)n->wetOut * preset->floatBufLeftActive[0]);
+		--n->preDelaySamples;
+		++outIndex;
+	}
+
+	uint32 inputIndex = 0;
+	for (; outIndex != preset->chunkSize; ++outIndex, ++inputIndex) {
+		float input = preset->floatBufLeftActive[inputIndex];
+		float a = reverb1Stage(&n->echoStages[0], input, 0.7);
+		float b = reverb1Stage(&n->echoStages[1], a, 0.7);
+		float wet = reverb1DelayStage(&n->echoStages[2], b, 0.62);
+		preset->floatBufLeftAlt[outIndex] = (float)((double)input * n->dryOut + (double)wet * n->wetOut);
+	}
+
+	return 0;
+}
+
+static int reverb1Stereo(HMIPreset *preset, HMIReverb1Node *n) {
+	uint32 i = 0;
+
+	while (n->preDelaySamples && i != preset->chunkSize) {
+		float output = (float)((double)preset->floatBufLeftActive[i] * n->wetOut);
+		preset->floatBufLeftAlt[i] = output;
+		preset->floatBufRightAlt[i] = output;
+		--n->preDelaySamples;
+		++i;
+	}
+
+	for (; i != preset->chunkSize; ++i) {
+		float input = preset->floatBufLeftActive[i];
+		float a = reverb1Stage(&n->echoStages[0], input, 0.7);
+		float b = reverb1Stage(&n->echoStages[1], a, 0.7);
+		float rightInput = (float)((double)n->echoStages[3].lastOutput * -0.71 + b);
+		float leftWet = reverb1DelayStage(&n->echoStages[2], b, 0.62);
+		float rightWet = reverb1DelayStage(&n->echoStages[3], rightInput, 0.0);
+		double dry = (double)input * n->dryOut;
+		preset->floatBufLeftAlt[i] = (float)(dry + (double)leftWet * n->wetOut);
+		preset->floatBufRightAlt[i] = (float)(dry + (double)rightWet * n->wetOut);
+	}
+
+	return 0;
+}
+
+int HMIReverb1::processBlock(HMIPreset *preset, HMIEffectNode *base) {
+	HMIReverb1Node *n = (HMIReverb1Node *)base;
+
+	if (n->channelMode & HMI_EFFECT_CHANNEL_MONO)
+		reverb1Mono(preset, n);
+
+	if (n->channelMode & HMI_EFFECT_CHANNEL_STEREO)
+		reverb1Stereo(preset, n);
+
+	return 0;
+}
+
+int HMIReverb1::getEffectParam(HMIEffectNode *base, int p, float *v, int *type) {
+	HMIReverb1Node *n = (HMIReverb1Node *)base;
+
+	if (p == 0) {
+		*v = n->reverbMax;
+	} else if (p == 1) {
+		*v = n->preDelay;
+	} else if (p == 2) {
+		*v = n->reverbTime;
+	} else if (p == 3) {
+		*v = n->dryOut;
+		*type = 2;
+		return 0;
+	} else if (p == 4) {
+		*v = n->wetOut;
+		*type = 2;
+		return 0;
+	} else {
+		return 11;
+	}
+
+	*type = 0;
+	return 0;
+}
+
+int HMIReverb1::setEffectParam(HMIEffectNode *base, int p, float v) {
+	HMIReverb1Node *n = (HMIReverb1Node *)base;
+
+	if (p == 0) {
+		n->reverbMax = v;
+	} else if (p == 1) {
+		n->preDelay = v;
+	} else if (p == 2) {
+		n->reverbTime = v;
+	} else if (p == 3) {
+		n->dryOut = v;
+	} else if (p == 4) {
+		n->wetOut = v;
+	} else {
+		return 11;
+	}
+
+	return 0;
+}
+
+} // End of namespace Audio
diff --git a/audio/effects/hmi/interfaces/reverb1.h b/audio/effects/hmi/interfaces/reverb1.h
new file mode 100644
index 00000000000..1db38c34fd6
--- /dev/null
+++ b/audio/effects/hmi/interfaces/reverb1.h
@@ -0,0 +1,50 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef AUDIO_EFFECTS_HMI_INTERFACES_REVERB1_H
+#define AUDIO_EFFECTS_HMI_INTERFACES_REVERB1_H
+
+#include "audio/effects/hmi/hmi_interface.h"
+
+namespace Audio {
+
+class HMIReverb1 : public HMIInterface {
+public:
+	HMIReverb1();
+	int init(HMIPreset *, HMIEffectNode *) override;
+	int uninit(HMIPreset *, HMIEffectNode *) override;
+	int getMinDuration(HMIEffectNode *, uint32 *) override;
+	int processBlock(HMIPreset *, HMIEffectNode *) override;
+	int initEffect(HMIPreset *, HMIEffectNode *) override;
+	int getEffectParam(HMIEffectNode *, int, float *, int *) override;
+	int setEffectParam(HMIEffectNode *, int, float) override;
+
+private:
+	static const char *const kReverb1Params[];
+	static const float kReverb1Min[];
+	static const float kReverb1Max[];
+	static const float kReverb1Default[];
+	static const float kReverb1Delay[4];
+};
+
+} // End of namespace Audio
+
+#endif
diff --git a/audio/effects/hmi/interfaces/reverb2.cpp b/audio/effects/hmi/interfaces/reverb2.cpp
new file mode 100644
index 00000000000..3607ef5d1f1
--- /dev/null
+++ b/audio/effects/hmi/interfaces/reverb2.cpp
@@ -0,0 +1,207 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "audio/effects/hmi/interfaces/reverb2.h"
+
+namespace Audio {
+
+const char *const HMIReverb2::kReverb2Params[] = {"Reverb Max", "Reverb Pre-Delay", "Reverb Time", "Dry Out", "Wet Out"};
+const float HMIReverb2::kReverb2Min[] = {5000.0f, 0.0f, 100.0f, 0.9f, 0.3f, -1.0f};
+const float HMIReverb2::kReverb2Max[] = {5000.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
+const float HMIReverb2::kReverb2Default[] = {5000.0f, 250.0f, 100.0f, 1.0f, 1.0f, 0.0f};
+
+HMIReverb2::HMIReverb2()
+	: HMIInterface(sizeof(HMIReverb2Node), 3, "DLGReverbMISO",
+				   kReverb2Params, kReverb2Min, kReverb2Max, kReverb2Default,
+				   "Reverb 2", 2103, 5) {}
+
+const float HMIReverb2::kReverb2Delay[6] = {
+	0.02969999983906746f, 0.03709999844431877f, 0.041099999099969864f,
+	0.043699998408555984f, 0.004999999888241291f, 0.0017000000225380063f
+};
+
+const float HMIReverb2::kReverb2Decay[6] = {
+	0.041099999099969864f, 0.043699998408555984f, 0.004999999888241291f,
+	0.0017000000225380063f, 0.09685350209474564f, 0.032924000173807144f
+};
+
+int HMIReverb2::init(HMIPreset *preset, HMIEffectNode *base) {
+	HMIReverb2Node *n = (HMIReverb2Node *)base;
+
+	double rate = preset->inputFmt->sampleRate;
+	n->bufSizeBytes = (int)(rate * 4.0);
+
+	for (int i = 0; i != 6; ++i) {
+		int bytes = 4 * (int)(rate * kReverb2Delay[i]);
+		n->echoStages[i].buffer = (float *)malloc(bytes);
+		if (!n->echoStages[i].buffer) {
+			while (i) {
+				free(n->echoStages[--i].buffer);
+			}
+
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+int HMIReverb2::uninit(HMIPreset *, HMIEffectNode *base) {
+	HMIReverb2Node *n = (HMIReverb2Node *)base;
+
+	for (int i = 0; i != 6; ++i) {
+		free(n->echoStages[i].buffer);
+	}
+
+	return 0;
+}
+
+int HMIReverb2::initEffect(HMIPreset *preset, HMIEffectNode *base) {
+	HMIReverb2Node *n = (HMIReverb2Node *)base;
+
+	float seconds = n->reverbTime * 0.001f;
+	float rate = (float)preset->inputFmt->sampleRate;
+
+	for (int i = 0; i != 6; ++i) {
+		int samples = (int)((double)rate * kReverb2Delay[i]);
+		n->echoStages[i].bufSizeInSamples = samples;
+		memset(n->echoStages[i].buffer, 0, 4 * samples);
+		n->echoStages[i].writeHead = 0;
+		double exponent = i >= 4 ? (double)kReverb2Delay[i] / kReverb2Decay[i]
+								 : (double)kReverb2Delay[i] / seconds;
+		n->echoStages[i].decayCoeff = (float)pow(kHmiMillis, (double)exponent);
+	}
+
+	n->preDelaySamples = (int)((double)preset->inputFmt->sampleRate * n->preDelay * kHmiMillis);
+	return 0;
+}
+
+int HMIReverb2::getMinDuration(HMIEffectNode *base, uint32 *out) {
+	HMIReverb2Node *n = (HMIReverb2Node *)base;
+
+	uint32 value = (uint32)(log(kHmiMillis) / log(0.7) * n->reverbTime);
+	*out = value / 3;
+	return 0;
+}
+
+static void advanceStage(HMIReverbEchoStage *s) {
+	if (++s->writeHead >= s->bufSizeInSamples)
+		s->writeHead = 0;
+}
+
+static void reverb2ProcessPath(HMIPreset *preset, HMIReverb2Node *n, int stereo) {
+	for (uint32 sample = 0; sample != preset->chunkSize; ++sample) {
+		double input = preset->floatBufLeftActive[sample];
+		double sum = 0.0;
+
+		for (int i = 0; i != 4; ++i) {
+			HMIReverbEchoStage *s = &n->echoStages[i];
+			float delayed = s->buffer[s->writeHead];
+			sum += delayed;
+			s->buffer[s->writeHead] = (float)((double)delayed * s->decayCoeff + input);
+			advanceStage(s);
+		}
+
+		HMIReverbEchoStage *a = &n->echoStages[4];
+		float oldA = a->buffer[a->writeHead];
+		float writtenA = (float)((double)oldA * a->decayCoeff + sum);
+		a->buffer[a->writeHead] = writtenA;
+		float first = (float)((double)oldA - (double)a->decayCoeff * writtenA);
+		advanceStage(a);
+
+		HMIReverbEchoStage *b = &n->echoStages[5];
+		float oldB = b->buffer[b->writeHead];
+		float monoIn = (float)((double)first * 0.25 + (double)oldB * b->decayCoeff);
+		float stereoIn = (float)((double)first * 0.35 + (double)oldB * b->decayCoeff);
+		float monoOut = (float)((double)oldB - (double)b->decayCoeff * monoIn);
+		float stereoOut = (float)((double)oldB - (double)b->decayCoeff * stereoIn);
+		b->buffer[b->writeHead] = monoIn;
+		advanceStage(b);
+
+		double dry = input * n->dryOut;
+
+		if (!stereo) {
+			preset->floatBufLeftAlt[sample] = (float)(dry + (double)monoOut * n->wetOut);
+		} else {
+			preset->floatBufLeftAlt[sample] = (float)(dry + (double)monoOut * n->wetOut);
+			preset->floatBufRightAlt[sample] = (float)(dry + (double)stereoOut * n->wetOut);
+		}
+	}
+}
+
+int HMIReverb2::processBlock(HMIPreset *preset, HMIEffectNode *base) {
+	HMIReverb2Node *n = (HMIReverb2Node *)base;
+
+	if (n->channelMode & HMI_EFFECT_CHANNEL_MONO)
+		reverb2ProcessPath(preset, n, 0);
+
+	if (n->channelMode & HMI_EFFECT_CHANNEL_STEREO)
+		reverb2ProcessPath(preset, n, 1);
+
+	return 0;
+}
+
+int HMIReverb2::getEffectParam(HMIEffectNode *base, int p, float *v, int *type) {
+	HMIReverb2Node *n = (HMIReverb2Node *)base;
+
+	if (p == 0) {
+		*v = n->reverbMax;
+	} else if (p == 1) {
+		*v = n->preDelay;
+	} else if (p == 2) {
+		*v = n->reverbTime;
+	} else if (p == 3) {
+		*v = n->dryOut;
+		*type = 2;
+		return 0;
+	} else if (p == 4) {
+		*v = n->wetOut;
+		*type = 2;
+		return 0;
+	} else {
+		return 11;
+	}
+
+	*type = 0;
+	return 0;
+}
+
+int HMIReverb2::setEffectParam(HMIEffectNode *base, int p, float v) {
+	HMIReverb2Node *n = (HMIReverb2Node *)base;
+
+	if (p == 0) {
+		n->reverbMax = v;
+	} else if (p == 1) {
+		n->preDelay = v;
+	} else if (p == 2) {
+		n->reverbTime = v;
+	} else if (p == 3) {
+		n->dryOut = v;
+	} else if (p == 4) {
+		n->wetOut = v;
+	} else {
+		return 11;
+	}
+
+	return 0;
+}
+
+} // End of namespace Audio
diff --git a/audio/effects/hmi/interfaces/reverb2.h b/audio/effects/hmi/interfaces/reverb2.h
new file mode 100644
index 00000000000..0b225fe0e06
--- /dev/null
+++ b/audio/effects/hmi/interfaces/reverb2.h
@@ -0,0 +1,51 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef AUDIO_EFFECTS_HMI_INTERFACES_REVERB2_H
+#define AUDIO_EFFECTS_HMI_INTERFACES_REVERB2_H
+
+#include "audio/effects/hmi/hmi_interface.h"
+
+namespace Audio {
+
+class HMIReverb2 : public HMIInterface {
+public:
+	HMIReverb2();
+	int init(HMIPreset *, HMIEffectNode *) override;
+	int uninit(HMIPreset *, HMIEffectNode *) override;
+	int getMinDuration(HMIEffectNode *, uint32 *) override;
+	int processBlock(HMIPreset *, HMIEffectNode *) override;
+	int initEffect(HMIPreset *, HMIEffectNode *) override;
+	int getEffectParam(HMIEffectNode *, int, float *, int *) override;
+	int setEffectParam(HMIEffectNode *, int, float) override;
+
+private:
+	static const char *const kReverb2Params[];
+	static const float kReverb2Min[];
+	static const float kReverb2Max[];
+	static const float kReverb2Default[];
+	static const float kReverb2Delay[6];
+	static const float kReverb2Decay[6];
+};
+
+} // End of namespace Audio
+
+#endif
diff --git a/audio/effects/hmi/interfaces/ring_modulator.cpp b/audio/effects/hmi/interfaces/ring_modulator.cpp
new file mode 100644
index 00000000000..9e22b7d8d03
--- /dev/null
+++ b/audio/effects/hmi/interfaces/ring_modulator.cpp
@@ -0,0 +1,123 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "audio/effects/hmi/interfaces/ring_modulator.h"
+
+namespace Audio {
+
+const char *const HMIRingModulator::kRingModulatorParams[] = {"Frequency", "Modulator Type", "Modulate Out Of Phase", "Dry Out", "Wet Out"};
+const float HMIRingModulator::kRingModulatorMin[] = {2.0f, 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 0.0f};
+const float HMIRingModulator::kRingModulatorMax[] = {0x7FC00000, 0x7FC00000, 0x7FC00000, 0x7FC00000, 0x7FC00000}; // Meaning: NaN
+const float HMIRingModulator::kRingModulatorDefault[] = {4000.0f, 0.0f, 1.0f, 1.0f, 1.0f};
+
+HMIRingModulator::HMIRingModulator()
+	: HMIInterface(sizeof(HMIRingModulatorNode), 3, "DLGRingMod",
+				   kRingModulatorParams, kRingModulatorMin, kRingModulatorMax,
+				   kRingModulatorDefault, "Ring Modulator", 2900, 5) {}
+
+int HMIRingModulator::init(HMIPreset *, HMIEffectNode *) {
+	return 0;
+}
+
+int HMIRingModulator::uninit(HMIPreset *, HMIEffectNode *) {
+	return 0;
+}
+
+int HMIRingModulator::initEffect(HMIPreset *, HMIEffectNode *base) {
+	((HMIRingModulatorNode *)base)->phase = 0.0f;
+	return 0;
+}
+
+int HMIRingModulator::processBlock(HMIPreset *preset, HMIEffectNode *base) {
+	HMIRingModulatorNode *n = (HMIRingModulatorNode *)base;
+
+	float step = (float)((double)n->frequency * kHmiTwoPi / (double)preset->inputFmt->sampleRate);
+	if (n->channelMode & HMI_EFFECT_CHANNEL_MONO) {
+		for (uint32 i = 0; i != preset->chunkSize; ++i) {
+			double input = preset->floatBufLeftActive[i];
+			double dry = input * n->dryOut;
+			double wet = sin((double)step * n->phase) * input * n->wetOut;
+			n->phase = n->phase + 1.0f;
+			preset->floatBufLeftAlt[i] = (float)(wet + dry);
+		}
+	}
+
+	if (n->channelMode & HMI_EFFECT_CHANNEL_STEREO) {
+		for (uint32 i = 0; i != preset->chunkSize; ++i) {
+			float input = preset->floatBufLeftActive[i];
+			double phase = (double)step * n->phase;
+			preset->floatBufLeftAlt[i] = (float)(sin(phase) * input * n->wetOut + (double)input * n->dryOut);
+			double dry = (double)input * n->dryOut;
+			double right = cos(phase) * input;
+			n->phase = n->phase + 1.0f;
+			preset->floatBufRightAlt[i] = (float)(right * n->wetOut + dry);
+		}
+	}
+
+	return 0;
+}
+
+int HMIRingModulator::getEffectParam(HMIEffectNode *base, int p, float *v, int *type) {
+	HMIRingModulatorNode *n = (HMIRingModulatorNode *)base;
+
+	if (p == 0) {
+		*v = n->frequency;
+		*type = 1;
+	} else if (p == 1) {
+		*v = n->modulatorType;
+		*type = 3;
+	} else if (p == 2) {
+		*v = n->modulateOutOfPhase;
+		*type = 3;
+	} else if (p == 3) {
+		*v = n->dryOut;
+		*type = 2;
+	} else if (p == 4) {
+		*v = n->wetOut;
+		*type = 2;
+	} else {
+		return 11;
+	}
+
+	return 0;
+}
+
+int HMIRingModulator::setEffectParam(HMIEffectNode *base, int p, float v) {
+	HMIRingModulatorNode *n = (HMIRingModulatorNode *)base;
+
+	if (p == 0) {
+		n->frequency = v;
+	} else if (p == 1) {
+		n->modulatorType = v;
+	} else if (p == 2) {
+		n->modulateOutOfPhase = v;
+	} else if (p == 3) {
+		n->dryOut = v;
+	} else if (p == 4) {
+		n->wetOut = v;
+	} else {
+		return 11;
+	}
+
+	return 0;
+}
+
+} // End of namespace Audio
diff --git a/audio/effects/hmi/interfaces/ring_modulator.h b/audio/effects/hmi/interfaces/ring_modulator.h
new file mode 100644
index 00000000000..102328ff7f1
--- /dev/null
+++ b/audio/effects/hmi/interfaces/ring_modulator.h
@@ -0,0 +1,48 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef AUDIO_EFFECTS_HMI_INTERFACES_RING_MODULATOR_H
+#define AUDIO_EFFECTS_HMI_INTERFACES_RING_MODULATOR_H
+
+#include "audio/effects/hmi/hmi_interface.h"
+
+namespace Audio {
+
+class HMIRingModulator : public HMIInterface {
+public:
+	HMIRingModulator();
+	int init(HMIPreset *, HMIEffectNode *) override;
+	int uninit(HMIPreset *, HMIEffectNode *) override;
+	int processBlock(HMIPreset *, HMIEffectNode *) override;
+	int initEffect(HMIPreset *, HMIEffectNode *) override;
+	int getEffectParam(HMIEffectNode *, int, float *, int *) override;
+	int setEffectParam(HMIEffectNode *, int, float) override;
+
+private:
+	static const char *const kRingModulatorParams[];
+	static const float kRingModulatorMin[];
+	static const float kRingModulatorMax[];
+	static const float kRingModulatorDefault[];
+};
+
+} // End of namespace Audio
+
+#endif
diff --git a/audio/effects/hmi/interfaces/stereo_delay.cpp b/audio/effects/hmi/interfaces/stereo_delay.cpp
new file mode 100644
index 00000000000..d76fc4f74f4
--- /dev/null
+++ b/audio/effects/hmi/interfaces/stereo_delay.cpp
@@ -0,0 +1,163 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "audio/effects/hmi/interfaces/stereo_delay.h"
+
+namespace Audio {
+
+const char *const HMIStereoDelay::kStereoDelayParams[] = {"Delay Max", "Delay Time L", "Delay Time R", "Feedback", "Dry Out", "Wet Out"};
+const float HMIStereoDelay::kStereoDelayMin[] = {1000.0f, 100.0f, 100.0f, 0.5f, 0.9f, 0.9f, -1.0f, 0.0f};
+const float HMIStereoDelay::kStereoDelayMax[] = {1000.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
+const float HMIStereoDelay::kStereoDelayDefault[] = {1000.0f, 1000.0f, 1000.0f, 1.0f, 1.0f, 1.0f};
+
+HMIStereoDelay::HMIStereoDelay()
+	: HMIInterface(sizeof(HMIStereoDelayNode), 2, "DLGDelayMISO",
+				   kStereoDelayParams, kStereoDelayMin, kStereoDelayMax,
+				   kStereoDelayDefault, "Stereo Delay", 2001, 6) {}
+
+int HMIStereoDelay::init(HMIPreset *preset, HMIEffectNode *base) {
+	HMIStereoDelayNode *n = (HMIStereoDelayNode *)base;
+
+	int bytes = 4 * (int)((double)preset->inputFmt->sampleRate * n->maxDelayTime * kHmiMillis);
+	n->bufSizeBytesL = bytes;
+	n->bufSizeBytesR = bytes;
+
+	n->delayBufL = (float *)malloc(bytes);
+	if (!n->delayBufL)
+		return 1;
+
+	n->delayBufR = (float *)malloc(bytes);
+	if (!n->delayBufR) {
+		free(n->delayBufL);
+		n->delayBufL = 0;
+		return 1;
+	}
+
+	n->writeIndexL = n->writeIndexR = 0;
+	return 0;
+}
+
+int HMIStereoDelay::uninit(HMIPreset *, HMIEffectNode *base) {
+	HMIStereoDelayNode *n = (HMIStereoDelayNode *)base;
+
+	free(n->delayBufL);
+	free(n->delayBufR);
+	return 0;
+}
+
+int HMIStereoDelay::initEffect(HMIPreset *, HMIEffectNode *base) {
+	HMIStereoDelayNode *n = (HMIStereoDelayNode *)base;
+
+	n->writeIndexL = n->writeIndexR = 0;
+	memset(n->delayBufL, 0, n->bufSizeBytesL);
+	memset(n->delayBufR, 0, n->bufSizeBytesR);
+	return 0;
+}
+
+int HMIStereoDelay::getMinDuration(HMIEffectNode *base, uint32 *out) {
+	HMIStereoDelayNode *n = (HMIStereoDelayNode *)base;
+
+	double delay = n->delayTimeL > n->delayTimeR ? n->delayTimeL : n->delayTimeR;
+	*out = (uint32)(log(kHmiMillis) / log(n->feedback) * delay);
+	return 0;
+}
+
+int HMIStereoDelay::processBlock(HMIPreset *preset, HMIEffectNode *base) {
+	HMIStereoDelayNode *n = (HMIStereoDelayNode *)base;
+
+	double rate = preset->inputFmt->sampleRate;
+	int sizeL = (int)(n->delayTimeL * rate * kHmiMillis);
+	int sizeR = (int)(n->delayTimeR * rate * kHmiMillis);
+	int indexL = n->writeIndexL;
+	int indexR = n->writeIndexR;
+
+	for (uint32 i = 0; i != preset->chunkSize; ++i) {
+		double input = preset->floatBufLeftActive[i];
+		float delayedL = n->delayBufL[indexL];
+		float delayedR = n->delayBufR[indexR];
+		preset->floatBufLeftAlt[i] = (float)(input * n->dryOut + (double)n->wetOut * delayedL);
+		preset->floatBufRightAlt[i] = (float)(input * n->dryOut + (double)n->wetOut * delayedR);
+		n->delayBufL[indexL] = (float)((double)n->feedback * delayedL + input);
+		n->delayBufR[indexR] = (float)((double)n->feedback * delayedR + input);
+
+		if (++indexL == sizeL)
+			indexL = 0;
+
+		if (++indexR == sizeR)
+			indexR = 0;
+	}
+
+	n->writeIndexL = indexL;
+	n->writeIndexR = indexR;
+	return 0;
+}
+
+int HMIStereoDelay::getEffectParam(HMIEffectNode *base, int p, float *v, int *type) {
+	HMIStereoDelayNode *n = (HMIStereoDelayNode *)base;
+
+	if (p == 0) {
+		*v = n->maxDelayTime;
+		*type = 0;
+	} else if (p == 1) {
+		*v = n->delayTimeL;
+		*type = 0;
+	} else if (p == 2) {
+		*v = n->delayTimeR;
+		*type = 0;
+	} else if (p == 3) {
+		*v = n->feedback;
+		*type = 2;
+	} else if (p == 4) {
+		*v = n->dryOut;
+		*type = 2;
+	} else if (p == 5) {
+		*v = n->wetOut;
+		*type = 2;
+	} else {
+		return 11;
+	}
+
+	return 0;
+}
+
+int HMIStereoDelay::setEffectParam(HMIEffectNode *base, int p, float v) {
+	HMIStereoDelayNode *n = (HMIStereoDelayNode *)base;
+
+	if (p == 0) {
+		n->maxDelayTime = v;
+	} else if (p == 1) {
+		n->delayTimeL = v;
+	} else if (p == 2) {
+		n->delayTimeR = v;
+	} else if (p == 3) {
+		n->feedback = v;
+	} else if (p == 4) {
+		n->dryOut = v;
+	} else if (p == 5) {
+		n->wetOut = v;
+	} else {
+		return 11;
+	}
+
+	return 0;
+}
+
+} // End of namespace Audio
diff --git a/audio/effects/hmi/interfaces/stereo_delay.h b/audio/effects/hmi/interfaces/stereo_delay.h
new file mode 100644
index 00000000000..fda43379f65
--- /dev/null
+++ b/audio/effects/hmi/interfaces/stereo_delay.h
@@ -0,0 +1,49 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef AUDIO_EFFECTS_HMI_INTERFACES_STEREO_DELAY_H
+#define AUDIO_EFFECTS_HMI_INTERFACES_STEREO_DELAY_H
+
+#include "audio/effects/hmi/hmi_interface.h"
+
+namespace Audio {
+
+class HMIStereoDelay : public HMIInterface {
+public:
+	HMIStereoDelay();
+	int init(HMIPreset *, HMIEffectNode *) override;
+	int uninit(HMIPreset *, HMIEffectNode *) override;
+	int getMinDuration(HMIEffectNode *, uint32 *) override;
+	int processBlock(HMIPreset *, HMIEffectNode *) override;
+	int initEffect(HMIPreset *, HMIEffectNode *) override;
+	int getEffectParam(HMIEffectNode *, int, float *, int *) override;
+	int setEffectParam(HMIEffectNode *, int, float) override;
+
+private:
+	static const char *const kStereoDelayParams[];
+	static const float kStereoDelayMin[];
+	static const float kStereoDelayMax[];
+	static const float kStereoDelayDefault[];
+};
+
+} // End of namespace Audio
+
+#endif
diff --git a/audio/module.mk b/audio/module.mk
index 54633bd7bfa..a52ee375df5 100644
--- a/audio/module.mk
+++ b/audio/module.mk
@@ -30,6 +30,17 @@ MODULE_OBJS := \
 	sid.o \
 	ym2149.o \
 	timestamp.o \
+	effects/hmi/interfaces/envelope.o \
+	effects/hmi/interfaces/filter1.o \
+	effects/hmi/hmifxfp.o \
+	effects/hmi/hmifxlib.o \
+	effects/hmi/interfaces/mono_delay.o \
+	effects/hmi/interfaces/phasor.o \
+	effects/hmi/interfaces/resonator.o \
+	effects/hmi/interfaces/reverb1.o \
+	effects/hmi/interfaces/reverb2.o \
+	effects/hmi/interfaces/ring_modulator.o \
+	effects/hmi/interfaces/stereo_delay.o \
 	decoders/3do.o \
 	decoders/aac.o \
 	decoders/adpcm.o \


Commit: 1759d44803454e9c5e7078f6d33478af650ab4b6
    https://github.com/scummvm/scummvm/commit/1759d44803454e9c5e7078f6d33478af650ab4b6
Author: AndywinXp (andywinxp at gmail.com)
Date: 2026-07-01T01:13:22+02:00

Commit Message:
AUDIO: HMI: Infinite Audio clean-up

Changed paths:
    audio/effects/hmi/hmi_interface.h
    audio/effects/hmi/hmi_types.h
    audio/effects/hmi/hmifxfp.cpp
    audio/effects/hmi/hmifxfp.h
    audio/effects/hmi/hmifxlib.cpp
    audio/effects/hmi/hmifxlib.h
    audio/effects/hmi/interfaces/envelope.cpp
    audio/effects/hmi/interfaces/envelope.h
    audio/effects/hmi/interfaces/filter1.cpp
    audio/effects/hmi/interfaces/filter1.h
    audio/effects/hmi/interfaces/mono_delay.cpp
    audio/effects/hmi/interfaces/mono_delay.h
    audio/effects/hmi/interfaces/phasor.cpp
    audio/effects/hmi/interfaces/phasor.h
    audio/effects/hmi/interfaces/resonator.cpp
    audio/effects/hmi/interfaces/resonator.h
    audio/effects/hmi/interfaces/reverb1.cpp
    audio/effects/hmi/interfaces/reverb1.h
    audio/effects/hmi/interfaces/reverb2.cpp
    audio/effects/hmi/interfaces/reverb2.h
    audio/effects/hmi/interfaces/ring_modulator.cpp
    audio/effects/hmi/interfaces/ring_modulator.h
    audio/effects/hmi/interfaces/stereo_delay.cpp
    audio/effects/hmi/interfaces/stereo_delay.h


diff --git a/audio/effects/hmi/hmi_interface.h b/audio/effects/hmi/hmi_interface.h
index e3f0fdc9f4f..cca4cc3120d 100644
--- a/audio/effects/hmi/hmi_interface.h
+++ b/audio/effects/hmi/hmi_interface.h
@@ -32,13 +32,13 @@ class HMIInterface {
 public:
 	virtual ~HMIInterface() {}
 
-	virtual int init(HMIPreset *, HMIEffectNode *) = 0;
-	virtual int uninit(HMIPreset *, HMIEffectNode *) = 0;
-	virtual int getMinDuration(HMIEffectNode *, uint32 *);
-	virtual int processBlock(HMIPreset *, HMIEffectNode *) = 0;
-	virtual int initEffect(HMIPreset *, HMIEffectNode *) = 0;
-	virtual int getEffectParam(HMIEffectNode *, int, float *, int *) = 0;
-	virtual int setEffectParam(HMIEffectNode *, int, float) = 0;
+	virtual int init(HMIPreset *preset, HMIEffectNode *base) = 0;
+	virtual int uninit(HMIPreset *preset, HMIEffectNode *base) = 0;
+	virtual int getMinDuration(HMIEffectNode *n, uint32 *out);
+	virtual int processBlock(HMIPreset *preset, HMIEffectNode *base) = 0;
+	virtual int initEffect(HMIPreset *preset, HMIEffectNode *base) = 0;
+	virtual int getEffectParam(HMIEffectNode *base, int param, float *value, int *type) = 0;
+	virtual int setEffectParam(HMIEffectNode *base, int param, float value) = 0;
 
 	int effectStructSize() const { return _effectStructSize; }
 	int outChannels() const { return _outChannels; }
@@ -62,16 +62,16 @@ protected:
 				 int paramCount);
 
 private:
-	int _effectStructSize;
-	int _outChannels;
-	const char *_interfaceName;
-	HMIParamNames _effectParams;
-	const float *_paramMinValues;
-	const float *_paramMaxValues;
-	const float *_paramDefaultValues;
-	char _presetName[64];
-	int _presetId;
-	int _paramCount;
+	int _effectStructSize = 0;
+	int _outChannels = 0;
+	const char *_interfaceName = nullptr;
+	HMIParamNames _effectParams = nullptr;
+	const float *_paramMinValues = nullptr;
+	const float *_paramMaxValues = nullptr;
+	const float *_paramDefaultValues = nullptr;
+	char _presetName[64] = {0};
+	int _presetId = 0;
+	int _paramCount = 0;
 };
 
 } // End of namespace Audio
diff --git a/audio/effects/hmi/hmi_types.h b/audio/effects/hmi/hmi_types.h
index 0368330cc64..db45f7120db 100644
--- a/audio/effects/hmi/hmi_types.h
+++ b/audio/effects/hmi/hmi_types.h
@@ -103,7 +103,6 @@ struct HMIPreset {
 	uint32 chunkSize;
 	int lockLevel;
 	int allocatedHeapSize;
-	uint8 reserved[980];
 	HMIEffectNode *effectChain;
 	HMIFormat *outputFmt;
 	HMIFormat *inputFmt;
@@ -111,12 +110,8 @@ struct HMIPreset {
 };
 
 struct HMIInitData {
-	uint32 *a;
-	uint32 *b;
 	int heapSize;
 	void *heapPtr;
-	void *(*mallocFunc)(size_t);
-	void (*freeFunc)(void *);
 };
 
 struct HMILibrary {
diff --git a/audio/effects/hmi/hmifxfp.cpp b/audio/effects/hmi/hmifxfp.cpp
index d4719bdc139..75dc4d35e7e 100644
--- a/audio/effects/hmi/hmifxfp.cpp
+++ b/audio/effects/hmi/hmifxfp.cpp
@@ -50,15 +50,16 @@ HMIInterface::HMIInterface(int size, int channels,
 	copyName(_presetName, name);
 }
 
-int HMIInterface::getMinDuration(HMIEffectNode *, uint32 *duration) {
+int HMIInterface::getMinDuration(HMIEffectNode *n, uint32 *duration) {
 	*duration = 0;
 	return 0;
 }
 
-HMIFxFp::HMIFxFp() { initializeInterfaces(); }
+HMIFxFp::HMIFxFp() { 
+	initializeInterfaces();
+}
 
 void HMIFxFp::initializeInterfaces() {
-	/* Original interface-list order at 0x10012A70. */
 	_interfaceList[0] = &_monoDelay;
 	_interfaceList[1] = &_stereoDelay;
 	_interfaceList[2] = &_reverb1;
diff --git a/audio/effects/hmi/hmifxfp.h b/audio/effects/hmi/hmifxfp.h
index 8e7d200388a..5dc09dbb62c 100644
--- a/audio/effects/hmi/hmifxfp.h
+++ b/audio/effects/hmi/hmifxfp.h
@@ -51,7 +51,7 @@ private:
 	HMIResonator _resonator;
 	HMIPhasor _phasor;
 	HMIReverb2 _reverb2;
-	HMIInterface *_interfaceList[10];
+	HMIInterface *_interfaceList[10] = {nullptr};
 };
 
 } // End of namespace Audio
diff --git a/audio/effects/hmi/hmifxlib.cpp b/audio/effects/hmi/hmifxlib.cpp
index d89385c4e69..b50fa5db68a 100644
--- a/audio/effects/hmi/hmifxlib.cpp
+++ b/audio/effects/hmi/hmifxlib.cpp
@@ -61,11 +61,13 @@ static int16 hmiFistp16(float value) {
 }
 
 HMIFxLib::HMIFxLib()
-	: _numLoadedInterfaces(0), _curInterfaceIndex(0), _systemHeap(0),
-	  _heapCursor(0), _heapEnd(0), _mallocFunc(malloc), _freeFunc(free) {
+	: _numLoadedInterfaces(0), _curInterfaceIndex(0), _systemHeap(nullptr), _heapCursor(nullptr), _heapEnd(nullptr) {
 	memset(_loadedInterfaces, 0, sizeof(_loadedInterfaces));
+
+	_fxFp = new HMIFxFp();
+	
 	HMIInterface **list = nullptr;
-	_fxFp.hmiFXGetInterfaceList(&list);
+	_fxFp->hmiFXGetInterfaceList(&list);
 
 	while (_numLoadedInterfaces != 1024 && list[_numLoadedInterfaces]) {
 		_loadedInterfaces[_numLoadedInterfaces] = list[_numLoadedInterfaces];
@@ -76,22 +78,16 @@ HMIFxLib::HMIFxLib()
 		_loadedInterfaces[_numLoadedInterfaces] = nullptr;
 }
 
-HMIFxLib::~HMIFxLib() {}
+HMIFxLib::~HMIFxLib() {
+	delete _fxFp;
+}
 
 HMIFxFp *HMIFxLib::effects() {
-	return &_fxFp;
+	return _fxFp;
 }
 
 int HMIFxLib::hmiFXInitSystem(HMIInitData *initData) {
-	if (initData->mallocFunc && initData->freeFunc) {
-		_mallocFunc = initData->mallocFunc;
-		_freeFunc = initData->freeFunc;
-	} else {
-		_mallocFunc = malloc;
-		_freeFunc = free;
-	}
-
-	initData->heapPtr = hmiFXMalloc((size_t)initData->heapSize);
+	initData->heapPtr = malloc((size_t)initData->heapSize);
 	if (!initData->heapPtr)
 		return 1;
 
@@ -101,7 +97,7 @@ int HMIFxLib::hmiFXInitSystem(HMIInitData *initData) {
 
 int HMIFxLib::hmiFXUnInitSystem(HMIInitData *initData) {
 	if (initData->heapPtr)
-		hmiFXFree(initData->heapPtr);
+		free(initData->heapPtr);
 
 	initData->heapPtr = nullptr;
 	_systemHeap = _heapCursor = _heapEnd = nullptr;
@@ -156,6 +152,7 @@ void *HMIFxLib::hmiFXHeapAlloc(int size) {
 	uint8 *result = _heapCursor;
 	if (!result || result + size > _heapEnd)
 		return nullptr;
+
 	_heapCursor += size;
 	return result;
 }
@@ -174,14 +171,6 @@ void *HMIFxLib::hmiFXHeapReset() {
 	return _systemHeap;
 }
 
-void *HMIFxLib::hmiFXMalloc(size_t size) {
-	return _mallocFunc(size);
-}
-
-void HMIFxLib::hmiFXFree(void *ptr) {
-	_freeFunc(ptr);
-}
-
 int HMIFxLib::convertPCMToFloat(HMIPreset *preset, const uint8 *buffer, int samples) {
 	float *left = preset->floatBufLeftActive;
 	float *right = preset->floatBufRightActive;
@@ -275,7 +264,7 @@ int HMIFxLib::hmiFXPresetCreate(HMIPreset *preset) {
 	uint32 samples = preset->inputFmt->sampleRate * preset->chunkSizeInMs / 1000U;
 	int segmentBytes = 4 * (int)samples + 1024;
 	preset->chunkSizeInSamples = samples;
-	float *block = (float *)((preset->flags & HMI_PRESET_FLAG_USE_MALLOC) ? hmiFXMalloc(4 * segmentBytes)
+	float *block = (float *)((preset->flags & HMI_PRESET_FLAG_USE_MALLOC) ? malloc(4 * segmentBytes)
 																		  : hmiFXHeapAlloc(4 * segmentBytes));
 	if (!block)
 		return 1;
@@ -303,7 +292,7 @@ int HMIFxLib::hmiFXPresetDestroy(HMIPreset *preset) {
 		node->interface->uninit(preset, node);
 
 	if (preset->flags & HMI_PRESET_FLAG_USE_MALLOC)
-		hmiFXFree(preset->floatBufLeft0);
+		free(preset->floatBufLeft0);
 
 	return 0;
 }
@@ -416,7 +405,7 @@ int HMIFxLib::hmiFXPresetCreateInstance(HMIPreset *source, HMIPreset **outInstan
 	if (!source)
 		return 15;
 
-	HMIPreset *copy = (HMIPreset *)hmiFXMalloc(sizeof(HMIPreset));
+	HMIPreset *copy = (HMIPreset *)malloc(sizeof(HMIPreset));
 	if (!copy) {
 		*outInstance = nullptr;
 		return 1;
@@ -428,7 +417,7 @@ int HMIFxLib::hmiFXPresetCreateInstance(HMIPreset *source, HMIPreset **outInstan
 
 	HMIEffectNode *previous = nullptr;
 	for (HMIEffectNode *src = source->effectChain; src; src = src->next) {
-		HMIEffectNode *node = (HMIEffectNode *)hmiFXMalloc(src->interface->effectStructSize());
+		HMIEffectNode *node = (HMIEffectNode *)malloc(src->interface->effectStructSize());
 		if (!node) {
 			hmiFXPresetDestroyInstance(copy);
 			*outInstance = nullptr;
@@ -460,11 +449,11 @@ int HMIFxLib::hmiFXPresetDestroyInstance(HMIPreset *preset) {
 	while (node) {
 		node->interface->uninit(preset, node);
 		HMIEffectNode *next = node->next;
-		hmiFXFree(node);
+		free(node);
 		node = next;
 	}
 
-	hmiFXFree(preset);
+	free(preset);
 	return 0;
 }
 
@@ -538,7 +527,7 @@ int HMIFxLib::processPreset(HMIPreset *preset, HMIProcessRequest *req) {
 	}
 
 	if (req->flags & HMI_PROCESS_ALLOCATE_OUTPUT) {
-		req->dstBuf = (uint8 *)hmiFXMalloc(outputBytes);
+		req->dstBuf = (uint8 *)malloc(outputBytes);
 		if (!req->dstBuf)
 			return 1;
 
@@ -819,7 +808,7 @@ int HMIFxLib::hmiFXPresetLoadLibrary(HMILibrary **outLib, Common::SeekableReadSt
 	if (!readFile(&d, stream))
 		return 10;
 
-	HMILibrary *library = (HMILibrary *)hmiFXMalloc(sizeof(HMILibrary));
+	HMILibrary *library = (HMILibrary *)malloc(sizeof(HMILibrary));
 	if (!library) {
 		flushFile(&d);
 		return 1;
@@ -863,7 +852,7 @@ int HMIFxLib::hmiFXPresetLoadLibrary(HMILibrary **outLib, Common::SeekableReadSt
 		if (!findSection(&d, query))
 			break;
 
-		HMIPreset *preset = (HMIPreset *)hmiFXMalloc(sizeof(HMIPreset));
+		HMIPreset *preset = (HMIPreset *)malloc(sizeof(HMIPreset));
 		if (!preset) {
 			flushFile(&d);
 			return 1;
@@ -897,7 +886,7 @@ int HMIFxLib::hmiFXPresetLoadLibrary(HMILibrary **outLib, Common::SeekableReadSt
 				return 7;
 			}
 
-			HMIEffectNode *node = (HMIEffectNode *)hmiFXMalloc(interface->effectStructSize());
+			HMIEffectNode *node = (HMIEffectNode *)malloc(interface->effectStructSize());
 			if (!node) {
 				flushFile(&d);
 				return 1;
@@ -940,19 +929,19 @@ int HMIFxLib::hmiFXPresetFreeLibrary(HMILibrary *library) {
 		while (node) {
 			node->interface->uninit(preset, node);
 			HMIEffectNode *next = node->next;
-			hmiFXFree(node);
+			free(node);
 			node = next;
 		}
 
 		if (preset->flags & HMI_PRESET_FLAG_USE_MALLOC)
-			hmiFXFree(preset->floatBufLeft0);
+			free(preset->floatBufLeft0);
 
 		HMIPreset *next = preset->next;
-		hmiFXFree(preset);
+		free(preset);
 		preset = next;
 	}
 
-	hmiFXFree(library);
+	free(library);
 	return 0;
 }
 
diff --git a/audio/effects/hmi/hmifxlib.h b/audio/effects/hmi/hmifxlib.h
index 97674363f8b..c978669c77d 100644
--- a/audio/effects/hmi/hmifxlib.h
+++ b/audio/effects/hmi/hmifxlib.h
@@ -64,8 +64,6 @@ public:
 	void hmiFXHeapFree(void *ptr);
 	int hmiFXHeapInit(HMIInitData *initData);
 	void *hmiFXHeapReset();
-	void *hmiFXMalloc(size_t size);
-	void hmiFXFree(void *ptr);
 
 private:
 	int convertPCMToFloat(HMIPreset *preset, const uint8 *buffer, int samples);
@@ -83,16 +81,14 @@ private:
 	int readSectionInt(HMIFileDescriptor *desc, const char *key, int *value);
 	int readSectionString(HMIFileDescriptor *desc, const char *key, char *value, int size);
 
-	HMIFxFp _fxFp;
+	HMIFxFp *_fxFp = nullptr;
 	HMIInterface *_loadedInterfaces[1024];
-	unsigned int _numLoadedInterfaces;
-	unsigned int _curInterfaceIndex;
+	unsigned int _numLoadedInterfaces = 0;
+	unsigned int _curInterfaceIndex = 0;
 
-	uint8 *_systemHeap;
-	uint8 *_heapCursor;
-	uint8 *_heapEnd;
-	void *(*_mallocFunc)(size_t);
-	void (*_freeFunc)(void *);
+	uint8 *_systemHeap = nullptr;
+	uint8 *_heapCursor = nullptr;
+	uint8 *_heapEnd = nullptr;
 };
 
 } // End of namespace Audio
diff --git a/audio/effects/hmi/interfaces/envelope.cpp b/audio/effects/hmi/interfaces/envelope.cpp
index 7537a10e827..cf7045116b2 100644
--- a/audio/effects/hmi/interfaces/envelope.cpp
+++ b/audio/effects/hmi/interfaces/envelope.cpp
@@ -33,15 +33,15 @@ HMIEnvelope::HMIEnvelope()
 				   kEnvelopeParams, kEnvelopeMin, kEnvelopeMax, kEnvelopeDefault,
 				   "Envelope", 2910, 18) {}
 
-int HMIEnvelope::init(HMIPreset *, HMIEffectNode *) {
+int HMIEnvelope::init(HMIPreset *preset, HMIEffectNode *base) {
 	return 0;
 }
 
-int HMIEnvelope::uninit(HMIPreset *, HMIEffectNode *) {
+int HMIEnvelope::uninit(HMIPreset *preset, HMIEffectNode *base) {
 	return 0;
 }
 
-int HMIEnvelope::initEffect(HMIPreset *, HMIEffectNode *base) {
+int HMIEnvelope::initEffect(HMIPreset *preset, HMIEffectNode *base) {
 	HMIEnvelopeNode *n = (HMIEnvelopeNode *)base;
 
 	if (n->initGuard == 0.0f) {
@@ -89,17 +89,17 @@ int HMIEnvelope::processBlock(HMIPreset *preset, HMIEffectNode *base) {
 	return 0;
 }
 
-int HMIEnvelope::getEffectParam(HMIEffectNode *base, int p, float *v, int *type) {
+int HMIEnvelope::getEffectParam(HMIEffectNode *base, int param, float *value, int *type) {
 	HMIEnvelopeNode *n = (HMIEnvelopeNode *)base;
-	if (p == 0) {
-		*v = n->envPoints;
-	} else if (p == 1) {
-		*v = n->initGuard;
+	if (param == 0) {
+		*value = n->envPoints;
+	} else if (param == 1) {
+		*value = n->initGuard;
 		*type = 0;
 		return 0;
-	} else if (p >= 2 && p <= 17) {
-		int index = (p - 2) >> 1;
-		*v = (p & 1) ? n->pointAmp[index] : n->pointTime[index];
+	} else if (param >= 2 && param <= 17) {
+		int index = (param - 2) >> 1;
+		*value = (param & 1) ? n->pointAmp[index] : n->pointTime[index];
 	} else {
 		return 11;
 	}
@@ -108,19 +108,19 @@ int HMIEnvelope::getEffectParam(HMIEffectNode *base, int p, float *v, int *type)
 	return 0;
 }
 
-int HMIEnvelope::setEffectParam(HMIEffectNode *base, int p, float v) {
+int HMIEnvelope::setEffectParam(HMIEffectNode *base, int param, float value) {
 	HMIEnvelopeNode *n = (HMIEnvelopeNode *)base;
-	if (p == 0) {
-		n->envPoints = v;
-	} else if (p == 1) {
-		n->initGuard = v;
-	} else if (p >= 2 && p <= 17) {
-		int index = (p - 2) >> 1;
-
-		if (p & 1) {
-			n->pointAmp[index] = v;
+	if (param == 0) {
+		n->envPoints = value;
+	} else if (param == 1) {
+		n->initGuard = value;
+	} else if (param >= 2 && param <= 17) {
+		int index = (param - 2) >> 1;
+
+		if (param & 1) {
+			n->pointAmp[index] = value;
 		} else {
-			n->pointTime[index] = v;
+			n->pointTime[index] = value;
 		}
 	} else {
 		return 11;
diff --git a/audio/effects/hmi/interfaces/envelope.h b/audio/effects/hmi/interfaces/envelope.h
index 30498868a1f..8c8a55e7e90 100644
--- a/audio/effects/hmi/interfaces/envelope.h
+++ b/audio/effects/hmi/interfaces/envelope.h
@@ -29,12 +29,12 @@ namespace Audio {
 class HMIEnvelope : public HMIInterface {
 public:
 	HMIEnvelope();
-	int init(HMIPreset *, HMIEffectNode *) override;
-	int uninit(HMIPreset *, HMIEffectNode *) override;
-	int processBlock(HMIPreset *, HMIEffectNode *) override;
-	int initEffect(HMIPreset *, HMIEffectNode *) override;
-	int getEffectParam(HMIEffectNode *, int, float *, int *) override;
-	int setEffectParam(HMIEffectNode *, int, float) override;
+	int init(HMIPreset *preset, HMIEffectNode *base) override;
+	int uninit(HMIPreset *preset, HMIEffectNode *base) override;
+	int processBlock(HMIPreset *preset, HMIEffectNode *base) override;
+	int initEffect(HMIPreset *preset, HMIEffectNode *base) override;
+	int getEffectParam(HMIEffectNode *base, int param, float *value, int *type) override;
+	int setEffectParam(HMIEffectNode *base, int param, float value) override;
 
 private:
 	static const char *const kEnvelopeParams[];
diff --git a/audio/effects/hmi/interfaces/filter1.cpp b/audio/effects/hmi/interfaces/filter1.cpp
index 84003c28f48..3fca14ab860 100644
--- a/audio/effects/hmi/interfaces/filter1.cpp
+++ b/audio/effects/hmi/interfaces/filter1.cpp
@@ -33,11 +33,11 @@ HMIFilter1::HMIFilter1()
 				   kFilter1Params, kFilter1Min, kFilter1Max, kFilter1Default,
 				   "Filter 1", 2300, 4) {}
 
-int HMIFilter1::init(HMIPreset *, HMIEffectNode *) {
+int HMIFilter1::init(HMIPreset *preset, HMIEffectNode *base) {
 	return 0; 
 }
 
-int HMIFilter1::uninit(HMIPreset *, HMIEffectNode *) {
+int HMIFilter1::uninit(HMIPreset *preset, HMIEffectNode *base) {
 	return 0; 
 }
 
@@ -114,21 +114,21 @@ int HMIFilter1::processBlock(HMIPreset *preset, HMIEffectNode *base) {
 	return 0;
 }
 
-int HMIFilter1::getEffectParam(HMIEffectNode *base, int p, float *v, int *type) {
+int HMIFilter1::getEffectParam(HMIEffectNode *base, int param, float *value, int *type) {
 	HMIFilter1Node *n = (HMIFilter1Node *)base;
 	
-	if (p == 0) {
-		*v = (float)(uint32)n->filterType;
+	if (param == 0) {
+		*value = (float)(uint32)n->filterType;
 		*type = 3;
 		return 0;
 	}
 
-	if (p == 1) {
-		*v = n->cutoffFrequency;
-	} else if (p == 2) {
-		*v = n->centerFrequency;
-	} else if (p == 3) {
-		*v = n->bandWidth;
+	if (param == 1) {
+		*value = n->cutoffFrequency;
+	} else if (param == 2) {
+		*value = n->centerFrequency;
+	} else if (param == 3) {
+		*value = n->bandWidth;
 	} else {
 		return 11;
 	}
@@ -137,17 +137,17 @@ int HMIFilter1::getEffectParam(HMIEffectNode *base, int p, float *v, int *type)
 	return 0;
 }
 
-int HMIFilter1::setEffectParam(HMIEffectNode *base, int p, float v) {
+int HMIFilter1::setEffectParam(HMIEffectNode *base, int param, float value) {
 	HMIFilter1Node *n = (HMIFilter1Node *)base;
 
-	if (p == 0) {
-		n->filterType = (int)(v);
-	} else if (p == 1) {
-		n->cutoffFrequency = v;
-	} else if (p == 2) {
-		n->centerFrequency = v;
-	} else if (p == 3) {
-		n->bandWidth = v;
+	if (param == 0) {
+		n->filterType = (int)(value);
+	} else if (param == 1) {
+		n->cutoffFrequency = value;
+	} else if (param == 2) {
+		n->centerFrequency = value;
+	} else if (param == 3) {
+		n->bandWidth = value;
 	} else {
 		return 11;
 	}
diff --git a/audio/effects/hmi/interfaces/filter1.h b/audio/effects/hmi/interfaces/filter1.h
index c6dcf4b1427..caf73c1abea 100644
--- a/audio/effects/hmi/interfaces/filter1.h
+++ b/audio/effects/hmi/interfaces/filter1.h
@@ -29,12 +29,12 @@ namespace Audio {
 class HMIFilter1 : public HMIInterface {
 public:
 	HMIFilter1();
-	int init(HMIPreset *, HMIEffectNode *) override;
-	int uninit(HMIPreset *, HMIEffectNode *) override;
-	int processBlock(HMIPreset *, HMIEffectNode *) override;
-	int initEffect(HMIPreset *, HMIEffectNode *) override;
-	int getEffectParam(HMIEffectNode *, int, float *, int *) override;
-	int setEffectParam(HMIEffectNode *, int, float) override;
+	int init(HMIPreset *preset, HMIEffectNode *base) override;
+	int uninit(HMIPreset *preset, HMIEffectNode *base) override;
+	int processBlock(HMIPreset *preset, HMIEffectNode *base) override;
+	int initEffect(HMIPreset *preset, HMIEffectNode *base) override;
+	int getEffectParam(HMIEffectNode *base, int param, float *value, int *type) override;
+	int setEffectParam(HMIEffectNode *base, int param, float value) override;
 
 private:
 	static const char *const kFilter1Params[];
diff --git a/audio/effects/hmi/interfaces/mono_delay.cpp b/audio/effects/hmi/interfaces/mono_delay.cpp
index a06f5be5895..92671b96509 100644
--- a/audio/effects/hmi/interfaces/mono_delay.cpp
+++ b/audio/effects/hmi/interfaces/mono_delay.cpp
@@ -47,13 +47,13 @@ int HMIMonoDelay::init(HMIPreset *preset, HMIEffectNode *base) {
 	return 0;
 }
 
-int HMIMonoDelay::uninit(HMIPreset *, HMIEffectNode *base) {
+int HMIMonoDelay::uninit(HMIPreset *preset, HMIEffectNode *base) {
 	HMIMonoDelayNode *n = (HMIMonoDelayNode *)base;
 	free(n->delayBuf);
 	return 0;
 }
 
-int HMIMonoDelay::initEffect(HMIPreset *, HMIEffectNode *base) {
+int HMIMonoDelay::initEffect(HMIPreset *preset, HMIEffectNode *base) {
 	HMIMonoDelayNode *n = (HMIMonoDelayNode *)base;
 	n->writeIndex = 0;
 	memset(n->delayBuf, 0, n->bufSizeBytes);
@@ -86,23 +86,23 @@ int HMIMonoDelay::processBlock(HMIPreset *preset, HMIEffectNode *base) {
 	return 0;
 }
 
-int HMIMonoDelay::getEffectParam(HMIEffectNode *base, int p, float *v, int *type) {
+int HMIMonoDelay::getEffectParam(HMIEffectNode *base, int param, float *value, int *type) {
 	HMIMonoDelayNode *n = (HMIMonoDelayNode *)base;
 
-	if (p == 0) {
-		*v = n->maxDelayTime;
+	if (param == 0) {
+		*value = n->maxDelayTime;
 		*type = 0;
-	} else if (p == 1) {
-		*v = n->delayTime;
+	} else if (param == 1) {
+		*value = n->delayTime;
 		*type = 0;
-	} else if (p == 2) {
-		*v = n->feedback;
+	} else if (param == 2) {
+		*value = n->feedback;
 		*type = 2;
-	} else if (p == 3) {
-		*v = n->dryOut;
+	} else if (param == 3) {
+		*value = n->dryOut;
 		*type = 2;
-	} else if (p == 4) {
-		*v = n->wetOut;
+	} else if (param == 4) {
+		*value = n->wetOut;
 		*type = 2;
 	} else {
 		return 11;
@@ -110,19 +110,19 @@ int HMIMonoDelay::getEffectParam(HMIEffectNode *base, int p, float *v, int *type
 	return 0;
 }
 
-int HMIMonoDelay::setEffectParam(HMIEffectNode *base, int p, float v) {
+int HMIMonoDelay::setEffectParam(HMIEffectNode *base, int param, float value) {
 	HMIMonoDelayNode *n = (HMIMonoDelayNode *)base;
 
-	if (p == 0) {
-		n->maxDelayTime = v;
-	} else if (p == 1) {
-		n->delayTime = v;
-	} else if (p == 2) {
-		n->feedback = v;
-	} else if (p == 3) {
-		n->dryOut = v;
-	} else if (p == 4) {
-		n->wetOut = v;
+	if (param == 0) {
+		n->maxDelayTime = value;
+	} else if (param == 1) {
+		n->delayTime = value;
+	} else if (param == 2) {
+		n->feedback = value;
+	} else if (param == 3) {
+		n->dryOut = value;
+	} else if (param == 4) {
+		n->wetOut = value;
 	} else {
 		return 11;
 	}
diff --git a/audio/effects/hmi/interfaces/mono_delay.h b/audio/effects/hmi/interfaces/mono_delay.h
index ce16bf68247..7c6cafd56b7 100644
--- a/audio/effects/hmi/interfaces/mono_delay.h
+++ b/audio/effects/hmi/interfaces/mono_delay.h
@@ -29,13 +29,13 @@ namespace Audio {
 class HMIMonoDelay : public HMIInterface {
 public:
 	HMIMonoDelay();
-	int init(HMIPreset *, HMIEffectNode *) override;
-	int uninit(HMIPreset *, HMIEffectNode *) override;
-	int getMinDuration(HMIEffectNode *, uint32 *) override;
-	int processBlock(HMIPreset *, HMIEffectNode *) override;
-	int initEffect(HMIPreset *, HMIEffectNode *) override;
-	int getEffectParam(HMIEffectNode *, int, float *, int *) override;
-	int setEffectParam(HMIEffectNode *, int, float) override;
+	int init(HMIPreset *preset, HMIEffectNode *base) override;
+	int uninit(HMIPreset *preset, HMIEffectNode *base) override;
+	int getMinDuration(HMIEffectNode *base, uint32 *out) override;
+	int processBlock(HMIPreset *preset, HMIEffectNode *base) override;
+	int initEffect(HMIPreset *preset, HMIEffectNode *base) override;
+	int getEffectParam(HMIEffectNode *base, int param, float *value, int *type) override;
+	int setEffectParam(HMIEffectNode *base, int param, float value) override;
 
 private:
 	static const char *const kMonoDelayParams[];
diff --git a/audio/effects/hmi/interfaces/phasor.cpp b/audio/effects/hmi/interfaces/phasor.cpp
index 1360b63fd65..fb83ae41df3 100644
--- a/audio/effects/hmi/interfaces/phasor.cpp
+++ b/audio/effects/hmi/interfaces/phasor.cpp
@@ -34,11 +34,11 @@ HMIPhasor::HMIPhasor()
 				   kPhasorParams, kPhasorMin, kPhasorMax, kPhasorDefault,
 				   "Phasor", 2375, 6) {}
 
-int HMIPhasor::init(HMIPreset *, HMIEffectNode *) {
+int HMIPhasor::init(HMIPreset *preset, HMIEffectNode *base) {
 	return 0;
 }
 
-int HMIPhasor::uninit(HMIPreset *, HMIEffectNode *) {
+int HMIPhasor::uninit(HMIPreset *preset, HMIEffectNode *base) {
 	return 0;
 }
 
@@ -100,21 +100,21 @@ int HMIPhasor::processBlock(HMIPreset *preset, HMIEffectNode *base) {
 	return 0;
 }
 
-int HMIPhasor::getEffectParam(HMIEffectNode *base, int p, float *v, int *type) {
+int HMIPhasor::getEffectParam(HMIEffectNode *base, int param, float *value, int *type) {
 	HMIPhasorNode *n = (HMIPhasorNode *)base;
 
-	if (p == 0) {
-		*v = n->rate;
-	} else if (p == 1) {
-		*v = n->depth;
-	} else if (p == 2) {
-		*v = n->centerFrequency;
-	} else if (p == 3) {
-		*v = n->feedback;
-	} else if (p == 4) {
-		*v = n->dryOut;
-	} else if (p == 5) {
-		*v = n->wetOut;
+	if (param == 0) {
+		*value = n->rate;
+	} else if (param == 1) {
+		*value = n->depth;
+	} else if (param == 2) {
+		*value = n->centerFrequency;
+	} else if (param == 3) {
+		*value = n->feedback;
+	} else if (param == 4) {
+		*value = n->dryOut;
+	} else if (param == 5) {
+		*value = n->wetOut;
 	} else {
 		return 11;
 	}
@@ -123,21 +123,21 @@ int HMIPhasor::getEffectParam(HMIEffectNode *base, int p, float *v, int *type) {
 	return 0;
 }
 
-int HMIPhasor::setEffectParam(HMIEffectNode *base, int p, float v) {
+int HMIPhasor::setEffectParam(HMIEffectNode *base, int param, float value) {
 	HMIPhasorNode *n = (HMIPhasorNode *)base;
 
-	if (p == 0) {
-		n->rate = v;
-	} else if (p == 1) {
-		n->depth = v;
-	} else if (p == 2) {
-		n->centerFrequency = v;
-	} else if (p == 3) {
-		n->feedback = v;
-	} else if (p == 4) {
-		n->dryOut = v;
-	} else if (p == 5) {
-		n->wetOut = v;
+	if (param == 0) {
+		n->rate = value;
+	} else if (param == 1) {
+		n->depth = value;
+	} else if (param == 2) {
+		n->centerFrequency = value;
+	} else if (param == 3) {
+		n->feedback = value;
+	} else if (param == 4) {
+		n->dryOut = value;
+	} else if (param == 5) {
+		n->wetOut = value;
 	} else {
 		return 11;
 	}
diff --git a/audio/effects/hmi/interfaces/phasor.h b/audio/effects/hmi/interfaces/phasor.h
index cc4b27c670b..37885777e3f 100644
--- a/audio/effects/hmi/interfaces/phasor.h
+++ b/audio/effects/hmi/interfaces/phasor.h
@@ -29,12 +29,12 @@ namespace Audio {
 class HMIPhasor : public HMIInterface {
 public:
 	HMIPhasor();
-	int init(HMIPreset *, HMIEffectNode *) override;
-	int uninit(HMIPreset *, HMIEffectNode *) override;
-	int processBlock(HMIPreset *, HMIEffectNode *) override;
-	int initEffect(HMIPreset *, HMIEffectNode *) override;
-	int getEffectParam(HMIEffectNode *, int, float *, int *) override;
-	int setEffectParam(HMIEffectNode *, int, float) override;
+	int init(HMIPreset *preset, HMIEffectNode *base) override;
+	int uninit(HMIPreset *preset, HMIEffectNode *base) override;
+	int processBlock(HMIPreset *preset, HMIEffectNode *base) override;
+	int initEffect(HMIPreset *preset, HMIEffectNode *base) override;
+	int getEffectParam(HMIEffectNode *base, int param, float *value, int *type) override;
+	int setEffectParam(HMIEffectNode *base, int param, float value) override;
 
 private:
 	static const char *const kPhasorParams[];
diff --git a/audio/effects/hmi/interfaces/resonator.cpp b/audio/effects/hmi/interfaces/resonator.cpp
index 8b32ba322f0..1ede966dc94 100644
--- a/audio/effects/hmi/interfaces/resonator.cpp
+++ b/audio/effects/hmi/interfaces/resonator.cpp
@@ -33,11 +33,11 @@ HMIResonator::HMIResonator()
 				   kResonatorParams, kResonatorMin, kResonatorMax, kResonatorDefault,
 				   "Resonator", 2350, 2) {}
 
-int HMIResonator::init(HMIPreset *, HMIEffectNode *) {
+int HMIResonator::init(HMIPreset *preset, HMIEffectNode *base) {
 	return 0;
 }
 
-int HMIResonator::uninit(HMIPreset *, HMIEffectNode *) {
+int HMIResonator::uninit(HMIPreset *preset, HMIEffectNode *base) {
 	return 0;
 }
 
@@ -72,13 +72,13 @@ int HMIResonator::processBlock(HMIPreset *preset, HMIEffectNode *base) {
 	return 0;
 }
 
-int HMIResonator::getEffectParam(HMIEffectNode *base, int p, float *v, int *type) {
+int HMIResonator::getEffectParam(HMIEffectNode *base, int param, float *value, int *type) {
 	HMIResonatorNode *n = (HMIResonatorNode *)base;
 
-	if (p == 0) {
-		*v = n->cutoffFrequency;
-	} else if (p == 1) {
-		*v = n->bandWidth;
+	if (param == 0) {
+		*value = n->cutoffFrequency;
+	} else if (param == 1) {
+		*value = n->bandWidth;
 	} else {
 		return 11;
 	}
@@ -87,13 +87,13 @@ int HMIResonator::getEffectParam(HMIEffectNode *base, int p, float *v, int *type
 	return 0;
 }
 
-int HMIResonator::setEffectParam(HMIEffectNode *base, int p, float v) {
+int HMIResonator::setEffectParam(HMIEffectNode *base, int param, float value) {
 	HMIResonatorNode *n = (HMIResonatorNode *)base;
 
-	if (p == 0) {
-		n->cutoffFrequency = v;
-	} else if (p == 1) {
-		n->bandWidth = v;
+	if (param == 0) {
+		n->cutoffFrequency = value;
+	} else if (param == 1) {
+		n->bandWidth = value;
 	} else {
 		return 11;
 	}
diff --git a/audio/effects/hmi/interfaces/resonator.h b/audio/effects/hmi/interfaces/resonator.h
index faf4d0763c7..4e3c8c42a02 100644
--- a/audio/effects/hmi/interfaces/resonator.h
+++ b/audio/effects/hmi/interfaces/resonator.h
@@ -29,12 +29,12 @@ namespace Audio {
 class HMIResonator : public HMIInterface {
 public:
 	HMIResonator();
-	int init(HMIPreset *, HMIEffectNode *) override;
-	int uninit(HMIPreset *, HMIEffectNode *) override;
-	int processBlock(HMIPreset *, HMIEffectNode *) override;
-	int initEffect(HMIPreset *, HMIEffectNode *) override;
-	int getEffectParam(HMIEffectNode *, int, float *, int *) override;
-	int setEffectParam(HMIEffectNode *, int, float) override;
+	int init(HMIPreset *preset, HMIEffectNode *base) override;
+	int uninit(HMIPreset *preset, HMIEffectNode *base) override;
+	int processBlock(HMIPreset *preset, HMIEffectNode *base) override;
+	int initEffect(HMIPreset *preset, HMIEffectNode *base) override;
+	int getEffectParam(HMIEffectNode *base, int param, float *value, int *type) override;
+	int setEffectParam(HMIEffectNode *base, int param, float value) override;
 
 private:
 	static const char *const kResonatorParams[];
diff --git a/audio/effects/hmi/interfaces/reverb1.cpp b/audio/effects/hmi/interfaces/reverb1.cpp
index f4f7160d065..14bd7e3787e 100644
--- a/audio/effects/hmi/interfaces/reverb1.cpp
+++ b/audio/effects/hmi/interfaces/reverb1.cpp
@@ -55,7 +55,7 @@ int HMIReverb1::init(HMIPreset *preset, HMIEffectNode *base) {
 	return 0;
 }
 
-int HMIReverb1::uninit(HMIPreset *, HMIEffectNode *base) {
+int HMIReverb1::uninit(HMIPreset *preset, HMIEffectNode *base) {
 	HMIReverb1Node *n = (HMIReverb1Node *)base;
 
 	for (int i = 0; i != 4; ++i) {
@@ -180,21 +180,21 @@ int HMIReverb1::processBlock(HMIPreset *preset, HMIEffectNode *base) {
 	return 0;
 }
 
-int HMIReverb1::getEffectParam(HMIEffectNode *base, int p, float *v, int *type) {
+int HMIReverb1::getEffectParam(HMIEffectNode *base, int param, float *value, int *type) {
 	HMIReverb1Node *n = (HMIReverb1Node *)base;
 
-	if (p == 0) {
-		*v = n->reverbMax;
-	} else if (p == 1) {
-		*v = n->preDelay;
-	} else if (p == 2) {
-		*v = n->reverbTime;
-	} else if (p == 3) {
-		*v = n->dryOut;
+	if (param == 0) {
+		*value = n->reverbMax;
+	} else if (param == 1) {
+		*value = n->preDelay;
+	} else if (param == 2) {
+		*value = n->reverbTime;
+	} else if (param == 3) {
+		*value = n->dryOut;
 		*type = 2;
 		return 0;
-	} else if (p == 4) {
-		*v = n->wetOut;
+	} else if (param == 4) {
+		*value = n->wetOut;
 		*type = 2;
 		return 0;
 	} else {
@@ -205,19 +205,19 @@ int HMIReverb1::getEffectParam(HMIEffectNode *base, int p, float *v, int *type)
 	return 0;
 }
 
-int HMIReverb1::setEffectParam(HMIEffectNode *base, int p, float v) {
+int HMIReverb1::setEffectParam(HMIEffectNode *base, int param, float value) {
 	HMIReverb1Node *n = (HMIReverb1Node *)base;
 
-	if (p == 0) {
-		n->reverbMax = v;
-	} else if (p == 1) {
-		n->preDelay = v;
-	} else if (p == 2) {
-		n->reverbTime = v;
-	} else if (p == 3) {
-		n->dryOut = v;
-	} else if (p == 4) {
-		n->wetOut = v;
+	if (param == 0) {
+		n->reverbMax = value;
+	} else if (param == 1) {
+		n->preDelay = value;
+	} else if (param == 2) {
+		n->reverbTime = value;
+	} else if (param == 3) {
+		n->dryOut = value;
+	} else if (param == 4) {
+		n->wetOut = value;
 	} else {
 		return 11;
 	}
diff --git a/audio/effects/hmi/interfaces/reverb1.h b/audio/effects/hmi/interfaces/reverb1.h
index 1db38c34fd6..79079222086 100644
--- a/audio/effects/hmi/interfaces/reverb1.h
+++ b/audio/effects/hmi/interfaces/reverb1.h
@@ -29,13 +29,13 @@ namespace Audio {
 class HMIReverb1 : public HMIInterface {
 public:
 	HMIReverb1();
-	int init(HMIPreset *, HMIEffectNode *) override;
-	int uninit(HMIPreset *, HMIEffectNode *) override;
-	int getMinDuration(HMIEffectNode *, uint32 *) override;
-	int processBlock(HMIPreset *, HMIEffectNode *) override;
-	int initEffect(HMIPreset *, HMIEffectNode *) override;
-	int getEffectParam(HMIEffectNode *, int, float *, int *) override;
-	int setEffectParam(HMIEffectNode *, int, float) override;
+	int init(HMIPreset *preset, HMIEffectNode *base) override;
+	int uninit(HMIPreset *preset, HMIEffectNode *base) override;
+	int getMinDuration(HMIEffectNode *base, uint32 *duration) override;
+	int processBlock(HMIPreset *preset, HMIEffectNode *base) override;
+	int initEffect(HMIPreset *preset, HMIEffectNode *base) override;
+	int getEffectParam(HMIEffectNode *base, int param, float *value, int *type) override;
+	int setEffectParam(HMIEffectNode *base, int param, float value) override;
 
 private:
 	static const char *const kReverb1Params[];
diff --git a/audio/effects/hmi/interfaces/reverb2.cpp b/audio/effects/hmi/interfaces/reverb2.cpp
index 3607ef5d1f1..22873ac0942 100644
--- a/audio/effects/hmi/interfaces/reverb2.cpp
+++ b/audio/effects/hmi/interfaces/reverb2.cpp
@@ -64,7 +64,7 @@ int HMIReverb2::init(HMIPreset *preset, HMIEffectNode *base) {
 	return 0;
 }
 
-int HMIReverb2::uninit(HMIPreset *, HMIEffectNode *base) {
+int HMIReverb2::uninit(HMIPreset *preset, HMIEffectNode *base) {
 	HMIReverb2Node *n = (HMIReverb2Node *)base;
 
 	for (int i = 0; i != 6; ++i) {
@@ -159,21 +159,21 @@ int HMIReverb2::processBlock(HMIPreset *preset, HMIEffectNode *base) {
 	return 0;
 }
 
-int HMIReverb2::getEffectParam(HMIEffectNode *base, int p, float *v, int *type) {
+int HMIReverb2::getEffectParam(HMIEffectNode *base, int param, float *value, int *type) {
 	HMIReverb2Node *n = (HMIReverb2Node *)base;
 
-	if (p == 0) {
-		*v = n->reverbMax;
-	} else if (p == 1) {
-		*v = n->preDelay;
-	} else if (p == 2) {
-		*v = n->reverbTime;
-	} else if (p == 3) {
-		*v = n->dryOut;
+	if (param == 0) {
+		*value = n->reverbMax;
+	} else if (param == 1) {
+		*value = n->preDelay;
+	} else if (param == 2) {
+		*value = n->reverbTime;
+	} else if (param == 3) {
+		*value = n->dryOut;
 		*type = 2;
 		return 0;
-	} else if (p == 4) {
-		*v = n->wetOut;
+	} else if (param == 4) {
+		*value = n->wetOut;
 		*type = 2;
 		return 0;
 	} else {
@@ -184,19 +184,19 @@ int HMIReverb2::getEffectParam(HMIEffectNode *base, int p, float *v, int *type)
 	return 0;
 }
 
-int HMIReverb2::setEffectParam(HMIEffectNode *base, int p, float v) {
+int HMIReverb2::setEffectParam(HMIEffectNode *base, int param, float value) {
 	HMIReverb2Node *n = (HMIReverb2Node *)base;
 
-	if (p == 0) {
-		n->reverbMax = v;
-	} else if (p == 1) {
-		n->preDelay = v;
-	} else if (p == 2) {
-		n->reverbTime = v;
-	} else if (p == 3) {
-		n->dryOut = v;
-	} else if (p == 4) {
-		n->wetOut = v;
+	if (param == 0) {
+		n->reverbMax = value;
+	} else if (param == 1) {
+		n->preDelay = value;
+	} else if (param == 2) {
+		n->reverbTime = value;
+	} else if (param == 3) {
+		n->dryOut = value;
+	} else if (param == 4) {
+		n->wetOut = value;
 	} else {
 		return 11;
 	}
diff --git a/audio/effects/hmi/interfaces/reverb2.h b/audio/effects/hmi/interfaces/reverb2.h
index 0b225fe0e06..0b7498263a8 100644
--- a/audio/effects/hmi/interfaces/reverb2.h
+++ b/audio/effects/hmi/interfaces/reverb2.h
@@ -29,13 +29,13 @@ namespace Audio {
 class HMIReverb2 : public HMIInterface {
 public:
 	HMIReverb2();
-	int init(HMIPreset *, HMIEffectNode *) override;
-	int uninit(HMIPreset *, HMIEffectNode *) override;
-	int getMinDuration(HMIEffectNode *, uint32 *) override;
-	int processBlock(HMIPreset *, HMIEffectNode *) override;
-	int initEffect(HMIPreset *, HMIEffectNode *) override;
-	int getEffectParam(HMIEffectNode *, int, float *, int *) override;
-	int setEffectParam(HMIEffectNode *, int, float) override;
+	int init(HMIPreset *preset, HMIEffectNode *base) override;
+	int uninit(HMIPreset *preset, HMIEffectNode *base) override;
+	int getMinDuration(HMIEffectNode *base, uint32 *duration) override;
+	int processBlock(HMIPreset *preset, HMIEffectNode *base) override;
+	int initEffect(HMIPreset *preset, HMIEffectNode *base) override;
+	int getEffectParam(HMIEffectNode *base, int param, float *value, int *type) override;
+	int setEffectParam(HMIEffectNode *base, int param, float value) override;
 
 private:
 	static const char *const kReverb2Params[];
diff --git a/audio/effects/hmi/interfaces/ring_modulator.cpp b/audio/effects/hmi/interfaces/ring_modulator.cpp
index 9e22b7d8d03..cbbef02065c 100644
--- a/audio/effects/hmi/interfaces/ring_modulator.cpp
+++ b/audio/effects/hmi/interfaces/ring_modulator.cpp
@@ -33,15 +33,15 @@ HMIRingModulator::HMIRingModulator()
 				   kRingModulatorParams, kRingModulatorMin, kRingModulatorMax,
 				   kRingModulatorDefault, "Ring Modulator", 2900, 5) {}
 
-int HMIRingModulator::init(HMIPreset *, HMIEffectNode *) {
+int HMIRingModulator::init(HMIPreset *preset, HMIEffectNode *base) {
 	return 0;
 }
 
-int HMIRingModulator::uninit(HMIPreset *, HMIEffectNode *) {
+int HMIRingModulator::uninit(HMIPreset *preset, HMIEffectNode *base) {
 	return 0;
 }
 
-int HMIRingModulator::initEffect(HMIPreset *, HMIEffectNode *base) {
+int HMIRingModulator::initEffect(HMIPreset *preset, HMIEffectNode *base) {
 	((HMIRingModulatorNode *)base)->phase = 0.0f;
 	return 0;
 }
@@ -75,23 +75,23 @@ int HMIRingModulator::processBlock(HMIPreset *preset, HMIEffectNode *base) {
 	return 0;
 }
 
-int HMIRingModulator::getEffectParam(HMIEffectNode *base, int p, float *v, int *type) {
+int HMIRingModulator::getEffectParam(HMIEffectNode *base, int param, float *value, int *type) {
 	HMIRingModulatorNode *n = (HMIRingModulatorNode *)base;
 
-	if (p == 0) {
-		*v = n->frequency;
+	if (param == 0) {
+		*value = n->frequency;
 		*type = 1;
-	} else if (p == 1) {
-		*v = n->modulatorType;
+	} else if (param == 1) {
+		*value = n->modulatorType;
 		*type = 3;
-	} else if (p == 2) {
-		*v = n->modulateOutOfPhase;
+	} else if (param == 2) {
+		*value = n->modulateOutOfPhase;
 		*type = 3;
-	} else if (p == 3) {
-		*v = n->dryOut;
+	} else if (param == 3) {
+		*value = n->dryOut;
 		*type = 2;
-	} else if (p == 4) {
-		*v = n->wetOut;
+	} else if (param == 4) {
+		*value = n->wetOut;
 		*type = 2;
 	} else {
 		return 11;
@@ -100,19 +100,19 @@ int HMIRingModulator::getEffectParam(HMIEffectNode *base, int p, float *v, int *
 	return 0;
 }
 
-int HMIRingModulator::setEffectParam(HMIEffectNode *base, int p, float v) {
+int HMIRingModulator::setEffectParam(HMIEffectNode *base, int param, float value) {
 	HMIRingModulatorNode *n = (HMIRingModulatorNode *)base;
 
-	if (p == 0) {
-		n->frequency = v;
-	} else if (p == 1) {
-		n->modulatorType = v;
-	} else if (p == 2) {
-		n->modulateOutOfPhase = v;
-	} else if (p == 3) {
-		n->dryOut = v;
-	} else if (p == 4) {
-		n->wetOut = v;
+	if (param == 0) {
+		n->frequency = value;
+	} else if (param == 1) {
+		n->modulatorType = value;
+	} else if (param == 2) {
+		n->modulateOutOfPhase = value;
+	} else if (param == 3) {
+		n->dryOut = value;
+	} else if (param == 4) {
+		n->wetOut = value;
 	} else {
 		return 11;
 	}
diff --git a/audio/effects/hmi/interfaces/ring_modulator.h b/audio/effects/hmi/interfaces/ring_modulator.h
index 102328ff7f1..b5704058565 100644
--- a/audio/effects/hmi/interfaces/ring_modulator.h
+++ b/audio/effects/hmi/interfaces/ring_modulator.h
@@ -29,12 +29,12 @@ namespace Audio {
 class HMIRingModulator : public HMIInterface {
 public:
 	HMIRingModulator();
-	int init(HMIPreset *, HMIEffectNode *) override;
-	int uninit(HMIPreset *, HMIEffectNode *) override;
-	int processBlock(HMIPreset *, HMIEffectNode *) override;
-	int initEffect(HMIPreset *, HMIEffectNode *) override;
-	int getEffectParam(HMIEffectNode *, int, float *, int *) override;
-	int setEffectParam(HMIEffectNode *, int, float) override;
+	int init(HMIPreset *preset, HMIEffectNode *base) override;
+	int uninit(HMIPreset *preset, HMIEffectNode *base) override;
+	int processBlock(HMIPreset *preset, HMIEffectNode *base) override;
+	int initEffect(HMIPreset *preset, HMIEffectNode *base) override;
+	int getEffectParam(HMIEffectNode *base, int param, float *value, int *type) override;
+	int setEffectParam(HMIEffectNode *base, int param, float value) override;
 
 private:
 	static const char *const kRingModulatorParams[];
diff --git a/audio/effects/hmi/interfaces/stereo_delay.cpp b/audio/effects/hmi/interfaces/stereo_delay.cpp
index d76fc4f74f4..5e66e25dbbc 100644
--- a/audio/effects/hmi/interfaces/stereo_delay.cpp
+++ b/audio/effects/hmi/interfaces/stereo_delay.cpp
@@ -55,7 +55,7 @@ int HMIStereoDelay::init(HMIPreset *preset, HMIEffectNode *base) {
 	return 0;
 }
 
-int HMIStereoDelay::uninit(HMIPreset *, HMIEffectNode *base) {
+int HMIStereoDelay::uninit(HMIPreset *preset, HMIEffectNode *base) {
 	HMIStereoDelayNode *n = (HMIStereoDelayNode *)base;
 
 	free(n->delayBufL);
@@ -63,7 +63,7 @@ int HMIStereoDelay::uninit(HMIPreset *, HMIEffectNode *base) {
 	return 0;
 }
 
-int HMIStereoDelay::initEffect(HMIPreset *, HMIEffectNode *base) {
+int HMIStereoDelay::initEffect(HMIPreset *preset, HMIEffectNode *base) {
 	HMIStereoDelayNode *n = (HMIStereoDelayNode *)base;
 
 	n->writeIndexL = n->writeIndexR = 0;
@@ -110,26 +110,26 @@ int HMIStereoDelay::processBlock(HMIPreset *preset, HMIEffectNode *base) {
 	return 0;
 }
 
-int HMIStereoDelay::getEffectParam(HMIEffectNode *base, int p, float *v, int *type) {
+int HMIStereoDelay::getEffectParam(HMIEffectNode *base, int param, float *value, int *type) {
 	HMIStereoDelayNode *n = (HMIStereoDelayNode *)base;
 
-	if (p == 0) {
-		*v = n->maxDelayTime;
+	if (param == 0) {
+		*value = n->maxDelayTime;
 		*type = 0;
-	} else if (p == 1) {
-		*v = n->delayTimeL;
+	} else if (param == 1) {
+		*value = n->delayTimeL;
 		*type = 0;
-	} else if (p == 2) {
-		*v = n->delayTimeR;
+	} else if (param == 2) {
+		*value = n->delayTimeR;
 		*type = 0;
-	} else if (p == 3) {
-		*v = n->feedback;
+	} else if (param == 3) {
+		*value = n->feedback;
 		*type = 2;
-	} else if (p == 4) {
-		*v = n->dryOut;
+	} else if (param == 4) {
+		*value = n->dryOut;
 		*type = 2;
-	} else if (p == 5) {
-		*v = n->wetOut;
+	} else if (param == 5) {
+		*value = n->wetOut;
 		*type = 2;
 	} else {
 		return 11;
@@ -138,21 +138,21 @@ int HMIStereoDelay::getEffectParam(HMIEffectNode *base, int p, float *v, int *ty
 	return 0;
 }
 
-int HMIStereoDelay::setEffectParam(HMIEffectNode *base, int p, float v) {
+int HMIStereoDelay::setEffectParam(HMIEffectNode *base, int param, float value) {
 	HMIStereoDelayNode *n = (HMIStereoDelayNode *)base;
 
-	if (p == 0) {
-		n->maxDelayTime = v;
-	} else if (p == 1) {
-		n->delayTimeL = v;
-	} else if (p == 2) {
-		n->delayTimeR = v;
-	} else if (p == 3) {
-		n->feedback = v;
-	} else if (p == 4) {
-		n->dryOut = v;
-	} else if (p == 5) {
-		n->wetOut = v;
+	if (param == 0) {
+		n->maxDelayTime = value;
+	} else if (param == 1) {
+		n->delayTimeL = value;
+	} else if (param == 2) {
+		n->delayTimeR = value;
+	} else if (param == 3) {
+		n->feedback = value;
+	} else if (param == 4) {
+		n->dryOut = value;
+	} else if (param == 5) {
+		n->wetOut = value;
 	} else {
 		return 11;
 	}
diff --git a/audio/effects/hmi/interfaces/stereo_delay.h b/audio/effects/hmi/interfaces/stereo_delay.h
index fda43379f65..62b382dcf6b 100644
--- a/audio/effects/hmi/interfaces/stereo_delay.h
+++ b/audio/effects/hmi/interfaces/stereo_delay.h
@@ -29,13 +29,13 @@ namespace Audio {
 class HMIStereoDelay : public HMIInterface {
 public:
 	HMIStereoDelay();
-	int init(HMIPreset *, HMIEffectNode *) override;
-	int uninit(HMIPreset *, HMIEffectNode *) override;
-	int getMinDuration(HMIEffectNode *, uint32 *) override;
-	int processBlock(HMIPreset *, HMIEffectNode *) override;
-	int initEffect(HMIPreset *, HMIEffectNode *) override;
-	int getEffectParam(HMIEffectNode *, int, float *, int *) override;
-	int setEffectParam(HMIEffectNode *, int, float) override;
+	int init(HMIPreset *preset, HMIEffectNode *base) override;
+	int uninit(HMIPreset *preset, HMIEffectNode *base) override;
+	int getMinDuration(HMIEffectNode *base, uint32 *out) override;
+	int processBlock(HMIPreset *preset, HMIEffectNode *base) override;
+	int initEffect(HMIPreset *preset, HMIEffectNode *base) override;
+	int getEffectParam(HMIEffectNode *base, int param, float *value, int *type) override;
+	int setEffectParam(HMIEffectNode *base, int param, float value) override;
 
 private:
 	static const char *const kStereoDelayParams[];


Commit: 2c7d70ac105884c90a035226db2e78a20d2daea4
    https://github.com/scummvm/scummvm/commit/2c7d70ac105884c90a035226db2e78a20d2daea4
Author: AndywinXp (andywinxp at gmail.com)
Date: 2026-07-01T01:13:22+02:00

Commit Message:
AUDIO: HMI: Turn it into an optional component

Grim is the only engine which will have to use it AFAIK.

Changed paths:
    audio/module.mk
    configure
    engines/grim/configure.engine


diff --git a/audio/module.mk b/audio/module.mk
index a52ee375df5..a5078213e6c 100644
--- a/audio/module.mk
+++ b/audio/module.mk
@@ -30,17 +30,6 @@ MODULE_OBJS := \
 	sid.o \
 	ym2149.o \
 	timestamp.o \
-	effects/hmi/interfaces/envelope.o \
-	effects/hmi/interfaces/filter1.o \
-	effects/hmi/hmifxfp.o \
-	effects/hmi/hmifxlib.o \
-	effects/hmi/interfaces/mono_delay.o \
-	effects/hmi/interfaces/phasor.o \
-	effects/hmi/interfaces/resonator.o \
-	effects/hmi/interfaces/reverb1.o \
-	effects/hmi/interfaces/reverb2.o \
-	effects/hmi/interfaces/ring_modulator.o \
-	effects/hmi/interfaces/stereo_delay.o \
 	decoders/3do.o \
 	decoders/aac.o \
 	decoders/adpcm.o \
@@ -83,6 +72,21 @@ MODULE_OBJS := \
 	softsynth/pcspk.o \
 	softsynth/ay8912.o
 
+ifdef USE_HMI_AUDIO
+MODULE_OBJS += \
+	effects/hmi/interfaces/envelope.o \
+	effects/hmi/interfaces/filter1.o \
+	effects/hmi/hmifxfp.o \
+	effects/hmi/hmifxlib.o \
+	effects/hmi/interfaces/mono_delay.o \
+	effects/hmi/interfaces/phasor.o \
+	effects/hmi/interfaces/resonator.o \
+	effects/hmi/interfaces/reverb1.o \
+	effects/hmi/interfaces/reverb2.o \
+	effects/hmi/interfaces/ring_modulator.o \
+	effects/hmi/interfaces/stereo_delay.o
+endif
+
 ifndef DISABLE_NUKED_OPL
 MODULE_OBJS += \
 	softsynth/opl/nuked.o
diff --git a/configure b/configure
index 3c9e0ed8d92..dc7aec30e11 100755
--- a/configure
+++ b/configure
@@ -304,6 +304,7 @@ _imgui=yes
 _cdtoons=auto
 _indeo3=auto
 _indeo45=auto
+_hmi_audio=auto
 _hnm=auto
 _jyv1=auto
 _qdm2=auto
@@ -341,6 +342,7 @@ add_component cdtoons "CDTOONS" "_cdtoons" "USE_CDTOONS"
 add_component enet "ENet" "_enet" "USE_ENET"
 add_component fmtowns_pc98_audio "FM-TOWNS/PC98 audio" "_fmtowns_pc98_audio" "USE_FMTOWNS_PC98_AUDIO"
 add_component gif "GIF" "_gif" "USE_GIF"
+add_component hmi_audio "HMI Infinite Audio" "_hmi_audio" "USE_HMI_AUDIO"
 add_component hnm "HNM" "_hnm" "USE_HNM"
 add_component imgui "Dear ImGui based debugger" "_imgui" "USE_IMGUI"
 add_component indeo3 "Indeo 3" "_indeo3" "USE_INDEO3"
diff --git a/engines/grim/configure.engine b/engines/grim/configure.engine
index e8d6a206224..b2976f745e0 100644
--- a/engines/grim/configure.engine
+++ b/engines/grim/configure.engine
@@ -1,4 +1,4 @@
 # This file is included from the main "configure" script
 # add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps] [components]
-add_engine grim "Grim" yes "monkey4" "Grim Fandango" "16bit 3d highres" "theoradec tinygl mpeg2"
+add_engine grim "Grim" yes "monkey4" "Grim Fandango" "16bit 3d highres hmi_audio" "theoradec tinygl mpeg2"
 add_engine monkey4 "Escape from Monkey Island" no "" "" "bink"




More information about the Scummvm-git-logs mailing list