mirror of
				https://github.com/godotengine/godot.git
				synced 2025-10-31 05:31:01 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			569 lines
		
	
	
	
		
			18 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			569 lines
		
	
	
	
		
			18 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*************************************************************************/
 | ||
| /*  reverb_sw.cpp                                                        */
 | ||
| /*************************************************************************/
 | ||
| /*                       This file is part of:                           */
 | ||
| /*                           GODOT ENGINE                                */
 | ||
| /*                    http://www.godotengine.org                         */
 | ||
| /*************************************************************************/
 | ||
| /* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur.                 */
 | ||
| /*                                                                       */
 | ||
| /* Permission is hereby granted, free of charge, to any person obtaining */
 | ||
| /* a copy of this software and associated documentation files (the       */
 | ||
| /* "Software"), to deal in the Software without restriction, including   */
 | ||
| /* without limitation the rights to use, copy, modify, merge, publish,   */
 | ||
| /* distribute, sublicense, and/or sell copies of the Software, and to    */
 | ||
| /* permit persons to whom the Software is furnished to do so, subject to */
 | ||
| /* the following conditions:                                             */
 | ||
| /*                                                                       */
 | ||
| /* The above copyright notice and this permission notice shall be        */
 | ||
| /* included in all copies or substantial portions of the Software.       */
 | ||
| /*                                                                       */
 | ||
| /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
 | ||
| /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
 | ||
| /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
 | ||
| /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
 | ||
| /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
 | ||
| /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
 | ||
| /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 | ||
| /*************************************************************************/
 | ||
| #include "reverb_sw.h"
 | ||
| #include "stdlib.h"
 | ||
| #include "print_string.h"
 | ||
| #define SETMIN( x, y ) (x) = MIN ( (x), (y) )
 | ||
| #define rangeloop( c, min, max )       \
 | ||
| 	for ( (c) = (min) ; (c) < (max) ; (c)++ )
 | ||
| 
 | ||
| #define ABSDIFF(x, y)\
 | ||
| 	( ((x) < (y)) ? ((y) - (x)) : ((x) - (y)) )
 | ||
| 
 | ||
| 
 | ||
| #ifdef bleh_MSC_VER
 | ||
| 
 | ||
| #if _MSC_VER >= 1400
 | ||
| 	_FORCE_INLINE_ int32_tMULSHIFT_S32 (
 | ||
| 		int32_t Factor1,
 | ||
| 		int32_t Factor2,
 | ||
| 		uint8_t Bits
 | ||
| 					) {
 | ||
| 
 | ||
| 			return __ll_rshift (
 | ||
| 					__emul ( Factor1, Factor2 ),
 | ||
| 			Bits
 | ||
| 						);
 | ||
| 					}
 | ||
| #endif
 | ||
| 
 | ||
| #else
 | ||
| #define MULSHIFT_S32( Factor1, Factor2, Bits )\
 | ||
| 			( (int) (( (int64_t)(Factor1) * (Factor2) ) >> (Bits)) )
 | ||
| #endif
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| struct ReverbParamsSW {
 | ||
| 	unsigned int BufferSize;		// Required buffer size
 | ||
| 	int gLPF;			// Coefficient
 | ||
| 	int gEcho0;			// Coefficient
 | ||
| 	int gEcho1;			// Coefficient
 | ||
| 	int gEcho2;			// Coefficient
 | ||
| 	int gEcho3;			// Coefficient
 | ||
| 	int gWall;			// Coefficient
 | ||
| 	int gReva;			// Coefficient
 | ||
| 	int gRevb;			// Coefficient
 | ||
| 	int gInputL;		// Coefficient
 | ||
| 	int gInputR;		// Coefficient
 | ||
| 	unsigned int nRevaOldL;		// Offset
 | ||
| 	unsigned int nRevaOldR;		// Offset
 | ||
| 	unsigned int nRevbOldL;		// Offset
 | ||
| 	unsigned int nRevbOldR;		// Offset
 | ||
| 	unsigned int nLwlNew;		// Offset
 | ||
| 	unsigned int nRwrNew;		// Offset
 | ||
| 	unsigned int nEcho0L;		// Offset
 | ||
| 	unsigned int nEcho0R;		// Offset
 | ||
| 	unsigned int nEcho1L;		// Offset
 | ||
| 	unsigned int nEcho1R;		// Offset
 | ||
| 	unsigned int nLwlOld;		// Offset
 | ||
| 	unsigned int nRwrOld;		// Offset
 | ||
| 	unsigned int nLwrNew;		// Offset
 | ||
| 	unsigned int nRwlNew;		// Offset
 | ||
| 	unsigned int nEcho2L;		// Offset
 | ||
| 	unsigned int nEcho2R;		// Offset
 | ||
| 	unsigned int nEcho3L;		// Offset
 | ||
| 	unsigned int nEcho3R;		// Offset
 | ||
| 	unsigned int nLwrOld;		// Offset
 | ||
| 	unsigned int nRwlOld;		// Offset
 | ||
| 	unsigned int nRevaNewL;		// Offset
 | ||
| 	unsigned int nRevaNewR;		// Offset
 | ||
| 	unsigned int nRevbNewL;		// Offset
 | ||
| 	unsigned int nRevbNewR;		// Offset
 | ||
| };
 | ||
| 
 | ||
| static ReverbParamsSW reverb_params_Room = {
 | ||
| 	0x26C0/2,
 | ||
| //	gLPF		gEcho0		gEcho1		gEcho2		gEcho3		gWall
 | ||
| 	0x6D80,		0x54B8,		-0x4130,	0x0000,		0x0000,		-0x4580,
 | ||
| //	gReva		gRevb		gInputL		gInputR
 | ||
| 	0x5800,		0x5300,		-0x8000,	-0x8000,
 | ||
| //	nRevaOldL			nRevaOldR			nRevbOldL			nRevbOldR
 | ||
| 	0x01B4 - 0x007D,	0x0136 - 0x007D,	0x00B8 - 0x005B,	0x005C - 0x005B,
 | ||
| //	nLwlNew		nRwrNew		nEcho0L		nEcho0R		nEcho1L		nEcho1R
 | ||
| 	0x04D6,		0x0333,		0x03F0,		0x0227,		0x0374,		0x01EF,
 | ||
| //	nLwlOld		nRwrOld		nLwrNew		nRwlNew		nEcho2L		nEcho2R		nEcho3L		nEcho3R
 | ||
| 	0x0334,		0x01B5,		0x0000,		0x0000,		0x0000,		0x0000,		0x0000,		0x0000,
 | ||
| //	nLwrOld		nRwlOld		nRevaNewL	nRevaNewR	nRevbNewL	nRevbNewR
 | ||
| 	0x0000,		0x0000,		0x01B4,		0x0136,		0x00B8,		0x005C
 | ||
| };
 | ||
| 
 | ||
| static ReverbParamsSW reverb_params_StudioSmall = {
 | ||
| 	0x1F40/2,
 | ||
| //	gLPF		gEcho0		gEcho1		gEcho2		gEcho3		gWall
 | ||
| 	0x70F0,		0x4FA8,		-0x4320,	0x4410,		-0x3F10,	-0x6400,
 | ||
| //	gReva		gRevb		gInputL		gInputR
 | ||
| 	0x5280,		0x4EC0,		-0x8000,	-0x8000,
 | ||
| //	nRevaOldL			nRevaOldR			nRevbOldL			nRevbOldR
 | ||
| 	0x00B4 - 0x0033,	0x0080 - 0x0033,	0x004C - 0x0025,	0x0026 - 0x0025,
 | ||
| //	nLwlNew		nRwrNew		nEcho0L		nEcho0R		nEcho1L		nEcho1R
 | ||
| 	0x03E4,		0x031B,		0x03A4,		0x02AF,		0x0372,		0x0266,
 | ||
| //	nLwlOld		nRwrOld		nLwrNew		nRwlNew		nEcho2L		nEcho2R		nEcho3L		nEcho3R
 | ||
| 	0x031C,		0x025D,		0x025C,		0x018E,		0x022F,		0x0135,		0x01D2,		0x00B7,
 | ||
| //	nLwrOld		nRwlOld		nRevaNewL	nRevaNewR	nRevbNewL	nRevbNewR
 | ||
| 	0x018F,		0x00B5,		0x00B4,		0x0080,		0x004C,		0x0026
 | ||
| };
 | ||
| 
 | ||
| static ReverbParamsSW reverb_params_StudioMedium = {
 | ||
| 	0x4840/2,
 | ||
| //	gLPF		gEcho0		gEcho1		gEcho2		gEcho3		gWall
 | ||
| 	0x70F0,		0x4FA8,		-0x4320,	0x4510,		-0x4110,	-0x4B40,
 | ||
| //	gReva		gRevb		gInputL		gInputR
 | ||
| 	0x5280,		0x4EC0,		-0x8000,	-0x8000,
 | ||
| //	nRevaOldL			nRevaOldR			nRevbOldL			nRevbOldR
 | ||
| 	0x0264 - 0x00B1,	0x01B2 - 0x00B1,	0x0100 - 0x007F,	0x0080 - 0x007F,
 | ||
| //	nLwlNew		nRwrNew		nEcho0L		nEcho0R		nEcho1L		nEcho1R
 | ||
| 	0x0904,		0x076B,		0x0824,		0x065F,		0x07A2,		0x0616,
 | ||
| //	nLwlOld		nRwrOld		nLwrNew		nRwlNew		nEcho2L		nEcho2R		nEcho3L		nEcho3R
 | ||
| 	0x076C,		0x05ED,		0x05EC,		0x042E,		0x050F,		0x0305,		0x0462,		0x02B7,
 | ||
| //	nLwrOld		nRwlOld		nRevaNewL	nRevaNewR	nRevbNewL	nRevbNewR
 | ||
| 	0x042F,		0x0265,		0x0264,		0x01B2,		0x0100,		0x0080
 | ||
| };
 | ||
| 
 | ||
| static ReverbParamsSW reverb_params_StudioLarge = {
 | ||
| 	0x6FE0/2,
 | ||
| //	gLPF		gEcho0		gEcho1		gEcho2		gEcho3		gWall
 | ||
| 	0x6F60,		0x4FA8,		-0x4320,	0x4510,		-0x4110,	-0x5980,
 | ||
| //	gReva		gRevb		gInputL		gInputR
 | ||
| 	0x5680,		0x52C0,		-0x8000,	-0x8000,
 | ||
| //	nRevaOldL			nRevaOldR			nRevbOldL			nRevbOldR
 | ||
| 	0x031C - 0x00E3,	0x0238 - 0x00E3,	0x0154 -  0x00A9,	0x00AA - 0x00A9,
 | ||
| //	nLwlNew		nRwrNew		nEcho0L		nEcho0R		nEcho1L		nEcho1R
 | ||
| 	0x0DFB,		0x0B58,		0x0D09,		0x0A3C,		0x0BD9,		0x0973,
 | ||
| //	nLwlOld		nRwrOld		nLwrNew		nRwlNew		nEcho2L		nEcho2R		nEcho3L		nEcho3R
 | ||
| 	0x0B59,		0x08DA,		0x08D9,		0x05E9,		0x07EC,		0x04B0,		0x06EF,		0x03D2,
 | ||
| //	nLwrOld		nRwlOld		nRevaNewL	nRevaNewR	nRevbNewL	nRevbNewR
 | ||
| 	0x05EA,		0x031D,		0x031C,		0x0238,		0x0154,		0x00AA
 | ||
| };
 | ||
| 
 | ||
| static ReverbParamsSW reverb_params_Hall = {
 | ||
| 	0xADE0/2,
 | ||
| //	gLPF		gEcho0		gEcho1		gEcho2		gEcho3		gWall
 | ||
| 	0x6000,		0x5000,		0x4C00,		-0x4800,	-0x4400,	-0x4000,
 | ||
| //	gReva		gRevb		gInputL		gInputR
 | ||
| 	0x6000,		0x5C00,		-0x8000,	-0x8000,
 | ||
| //	nRevaOldL			nRevaOldR			nRevbOldL			nRevbOldR
 | ||
| 	0x05C0 - 0x01A5,	0x041A - 0x01A5,	0x0274 - 0x0139,	0x013A -  0x0139,
 | ||
| //	nLwlNew		nRwrNew		nEcho0L		nEcho0R		nEcho1L		nEcho1R
 | ||
| 	0x15BA,		0x11BB,		0x14C2,		0x10BD,		0x11BC,		0x0DC1,
 | ||
| //	nLwlOld		nRwrOld		nLwrNew		nRwlNew		nEcho2L		nEcho2R		nEcho3L		nEcho3R
 | ||
| 	0x11C0,		0x0DC3,		0x0DC0,		0x09C1,		0x0BC4,		0x07C1,		0x0A00,		0x06CD,
 | ||
| //	nLwrOld		nRwlOld		nRevaNewL	nRevaNewR	nRevbNewL	nRevbNewR
 | ||
| 	0x09C2,		0x05C1,		0x05C0,		0x041A,		0x0274,		0x013A
 | ||
| };
 | ||
| 
 | ||
| static ReverbParamsSW reverb_params_SpaceEcho = {
 | ||
| 	0xF6C0/2,
 | ||
| //	gLPF		gEcho0		gEcho1		gEcho2		gEcho3		gWall
 | ||
| 	0x7E00,		0x5000,		-0x4C00,	-0x5000,	0x4C00,		-0x5000,
 | ||
| //	gReva		gRevb		gInputL		gInputR
 | ||
| 	0x6000,		0x5400,		-0x8000,	-0x8000,
 | ||
| //	nRevaOldL			nRevaOldR			nRevbOldL			nRevbOldR
 | ||
| 	0x0AE0 - 0x033D,	0x07A2 - 0x033D,	0x0464 - 0x0231,	0x0232 - 0x0231,
 | ||
| //	nLwlNew		nRwrNew		nEcho0L		nEcho0R		nEcho1L		nEcho1R
 | ||
| 	0x1ED6,		0x1A31,		0x1D14,		0x183B,		0x1BC2,		0x16B2,
 | ||
| //	nLwlOld		nRwrOld		nLwrNew		nRwlNew		nEcho2L		nEcho2R		nEcho3L		nEcho3R
 | ||
| 	0x1A32,		0x15EF,		0x15EE,		0x1055,		0x1334,		0x0F2D,		0x11F6,		0x0C5D,
 | ||
| //	nLwrOld		nRwlOld		nRevaNewL	nRevaNewR	nRevbNewL	nRevbNewR
 | ||
| 	0x1056,		0x0AE1,		0x0AE0,		0x07A2,		0x0464,		0x0232
 | ||
| };
 | ||
| 
 | ||
| static ReverbParamsSW reverb_params_Echo = {
 | ||
| 	0x18040/2,
 | ||
| //	gLPF		gEcho0		gEcho1		gEcho2		gEcho3		gWall
 | ||
| 	0x7FFF,		0x7FFF,		0x0000,		0x0000,		0x0000,		-0x7F00,
 | ||
| //	gReva		gRevb		gInputL		gInputR
 | ||
| 	0x0000,		0x0000,		-0x8000,	-0x8000,
 | ||
| //	nRevaOldL			nRevaOldR			nRevbOldL			nRevbOldR
 | ||
| 	0x1004 - 0x0001,	0x1002 - 0x0001,	0x0004 - 0x0001,	0x0002 - 0x0001,
 | ||
| //	nLwlNew		nRwrNew		nEcho0L		nEcho0R		nEcho1L		nEcho1R
 | ||
| 	0x1FFF,		0x0FFF,		0x1005,		0x0005,		0x0000,		0x0000,
 | ||
| //	nLwlOld		nRwrOld		nLwrNew		nRwlNew		nEcho2L		nEcho2R		nEcho3L		nEcho3R
 | ||
| 	0x1005,		0x0005,		0x0000,		0x0000,		0x0000,		0x0000,		0x0000,		0x0000,
 | ||
| //	nLwrOld		nRwlOld		nRevaNewL	nRevaNewR	nRevbNewL	nRevbNewR
 | ||
| 	0x0000,		0x0000,		0x1004,		0x1002,		0x0004,		0x0002
 | ||
| };
 | ||
| 
 | ||
| static ReverbParamsSW reverb_params_Delay = {
 | ||
| 	0x18040/2,
 | ||
| //	gLPF		gEcho0		gEcho1		gEcho2		gEcho3		gWall
 | ||
| 	0x7FFF,		0x7FFF,		0x0000,		0x0000,		0x0000,		0x0000,
 | ||
| //	gReva		gRevb		gInputL		gInputR
 | ||
| 	0x0000,		0x0000,		-0x8000,	-0x8000,
 | ||
| //	nRevaOldL			nRevaOldR			nRevbOldL			nRevbOldR
 | ||
| 	0x1004 - 0x0001,	0x1002 - 0x0001,	0x0004 - 0x0001,	0x0002 - 0x0001,
 | ||
| //	nLwlNew		nRwrNew		nEcho0L		nEcho0R		nEcho1L		nEcho1R
 | ||
| 	0x1FFF,		0x0FFF,		0x1005,		0x0005,		0x0000,		0x0000,
 | ||
| //	nLwlOld		nRwrOld		nLwrNew		nRwlNew		nEcho2L		nEcho2R		nEcho3L		nEcho3R
 | ||
| 	0x1005,		0x0005,		0x0000,		0x0000,		0x0000,		0x0000,		0x0000,		0x0000,
 | ||
| //	nLwrOld		nRwlOld		nRevaNewL	nRevaNewR	nRevbNewL	nRevbNewR
 | ||
| 	0x0000,		0x0000,		0x1004,		0x1002,		0x0004,		0x0002
 | ||
| };
 | ||
| 
 | ||
| static ReverbParamsSW reverb_params_HalfEcho = {
 | ||
| 	0x3C00/2,
 | ||
| //	gLPF		gEcho0		gEcho1		gEcho2		gEcho3		gWall
 | ||
| 	0x70F0,		0x4FA8,		-0x4320,	0x4510,		-0x4110,	-0x7B00,
 | ||
| //	gReva		gRevb		gInputL		gInputR
 | ||
| 	0x5F80,		0x54C0,		-0x8000,	-0x8000,
 | ||
| //	nRevaOldL			nRevaOldR			nRevbOldL			nRevbOldR
 | ||
| 	0x0058 - 0x0017,	0x0040 - 0x0017,	0x0028 - 0x0013,	0x0014 - 0x0013,
 | ||
| //	nLwlNew		nRwrNew		nEcho0L		nEcho0R		nEcho1L		nEcho1R
 | ||
| 	0x0371,		0x02AF,		0x02E5,		0x01DF,		0x02B0,		0x01D7,
 | ||
| //	nLwlOld		nRwrOld		nLwrNew		nRwlNew		nEcho2L		nEcho2R		nEcho3L		nEcho3R
 | ||
| 	0x0358,		0x026A,		0x01D6,		0x011E,		0x012D,		0x00B1,		0x011F,		0x0059,
 | ||
| //	nLwrOld		nRwlOld		nRevaNewL	nRevaNewR	nRevbNewL	nRevbNewR
 | ||
| 	0x01A0,		0x00E3,		0x0058,		0x0040,		0x0028,		0x0014
 | ||
| };
 | ||
| 
 | ||
| 
 | ||
| static ReverbParamsSW * reverb_param_modes[] = {
 | ||
| 	&reverb_params_Room,
 | ||
| 	&reverb_params_StudioSmall,
 | ||
| 	&reverb_params_StudioMedium,
 | ||
| 	&reverb_params_StudioLarge,
 | ||
| 	&reverb_params_Hall,
 | ||
| 	&reverb_params_SpaceEcho,
 | ||
| 	&reverb_params_Echo,
 | ||
| 	&reverb_params_Delay,
 | ||
| 	&reverb_params_HalfEcho,
 | ||
| };
 | ||
| 
 | ||
| bool ReverbSW::process(int *p_input,int *p_output,int p_frames,int p_stereo_stride) {
 | ||
| 
 | ||
| 	if (!reverb_buffer)
 | ||
| 		return false;
 | ||
| 
 | ||
| 
 | ||
| 		//
 | ||
| 	// p_input must point to a non-looping buffer.
 | ||
| 	// BOTH p_input and p_output must be touched (use ClearModuleBuffer).
 | ||
| 
 | ||
| 	// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>LOCAL MACROS <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>۲
 | ||
| 
 | ||
| #undef LM_SETSRCOFFSET
 | ||
| #define LM_SETSRCOFFSET(x)								\
 | ||
| 			(x) = current_params->x + Offset;									\
 | ||
| 			if ( (x) >= reverb_buffer_size ) {						\
 | ||
| 				(x) -= reverb_buffer_size;							\
 | ||
| 	}												\
 | ||
| 			SETMIN ( aSample, reverb_buffer_size - (x) );
 | ||
| 
 | ||
| /*
 | ||
| #undef LM_SETSRCOFFSET2
 | ||
| #define LM_SETSRCOFFSET2(x,y)							\
 | ||
| 			(x) = ((y) << 3) >> HZShift;					\
 | ||
| 			(x) += Offset;									\
 | ||
| 			if ( (x) >= reverb_buffer_size ) {						\
 | ||
| 				(x) -= reverb_buffer_size;							\
 | ||
| 	}												\
 | ||
| 			SETMIN ( aSample, reverb_buffer_size - (x) );
 | ||
| */
 | ||
| #undef LM_SRCADVANCE
 | ||
| #define LM_SRCADVANCE(x)								\
 | ||
| 			(x) += aSample;
 | ||
| 
 | ||
| #undef LM_MUL
 | ||
| #define LM_MUL(x,y)										\
 | ||
| MULSHIFT_S32 ( x, current_params->y, 15 )
 | ||
| 
 | ||
| #undef LM_REVERB
 | ||
| #define LM_REVERB(x) reverb_buffer[ (x) + cSample ]
 | ||
| 
 | ||
| 	// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>LOCAL VARIABLES <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>۲
 | ||
| 
 | ||
| 	unsigned int Offset;
 | ||
| 
 | ||
| 	int lwl, lwr, rwl, rwr;
 | ||
| //	unsigned char HZShift;
 | ||
| 
 | ||
| 	// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>CODE <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>۲
 | ||
| 
 | ||
| 
 | ||
| 	lwl = state.lwl;
 | ||
| 	lwr = state.lwr;
 | ||
| 	rwl = state.rwl;
 | ||
| 	rwr = state.rwr;
 | ||
| 	Offset = state.Offset;
 | ||
| 
 | ||
| 	int max=0;
 | ||
| 
 | ||
| 	while ( p_frames ) {
 | ||
| 
 | ||
| 		// Offsets
 | ||
| 
 | ||
| 		unsigned int nLwlOld;
 | ||
| 		unsigned int nRwrOld;
 | ||
| 		unsigned int nLwlNew;
 | ||
| 		unsigned int nRwrNew;
 | ||
| 
 | ||
| 		unsigned int nLwrOld;
 | ||
| 		unsigned int nRwlOld;
 | ||
| 		unsigned int nLwrNew;
 | ||
| 		unsigned int nRwlNew;
 | ||
| 
 | ||
| 		unsigned int nEcho0L;
 | ||
| 		unsigned int nEcho1L;
 | ||
| 		unsigned int nEcho2L;
 | ||
| 		unsigned int nEcho3L;
 | ||
| 
 | ||
| 		unsigned int nEcho0R;
 | ||
| 		unsigned int nEcho1R;
 | ||
| 		unsigned int nEcho2R;
 | ||
| 		unsigned int nEcho3R;
 | ||
| 
 | ||
| 		unsigned int nRevaOldL;
 | ||
| 		unsigned int nRevaOldR;
 | ||
| 		unsigned int nRevbOldL;
 | ||
| 		unsigned int nRevbOldR;
 | ||
| 
 | ||
| 		unsigned int nRevaNewL;
 | ||
| 		unsigned int nRevaNewR;
 | ||
| 		unsigned int nRevbNewL;
 | ||
| 		unsigned int nRevbNewR;
 | ||
| 
 | ||
| 		// Other variables
 | ||
| 
 | ||
| 		unsigned int aSample = p_frames;
 | ||
| 
 | ||
| 		// Set initial offsets
 | ||
| 
 | ||
| 		LM_SETSRCOFFSET ( nLwlOld );
 | ||
| 		LM_SETSRCOFFSET ( nRwrOld );
 | ||
| 		LM_SETSRCOFFSET ( nLwlNew );
 | ||
| 		LM_SETSRCOFFSET ( nRwrNew );
 | ||
| 		LM_SETSRCOFFSET ( nLwrOld );
 | ||
| 		LM_SETSRCOFFSET ( nRwlOld );
 | ||
| 		LM_SETSRCOFFSET ( nLwrNew );
 | ||
| 		LM_SETSRCOFFSET ( nRwlNew );
 | ||
| 		LM_SETSRCOFFSET ( nEcho0L );
 | ||
| 		LM_SETSRCOFFSET ( nEcho1L );
 | ||
| 		LM_SETSRCOFFSET ( nEcho2L );
 | ||
| 		LM_SETSRCOFFSET ( nEcho3L );
 | ||
| 		LM_SETSRCOFFSET ( nEcho0R );
 | ||
| 		LM_SETSRCOFFSET ( nEcho1R );
 | ||
| 		LM_SETSRCOFFSET ( nEcho2R );
 | ||
| 		LM_SETSRCOFFSET ( nEcho3R );
 | ||
| 		LM_SETSRCOFFSET ( nRevaOldL );
 | ||
| 		LM_SETSRCOFFSET ( nRevaOldR );
 | ||
| 		LM_SETSRCOFFSET ( nRevbOldL );
 | ||
| 		LM_SETSRCOFFSET ( nRevbOldR );
 | ||
| 		LM_SETSRCOFFSET ( nRevaNewL );
 | ||
| 		LM_SETSRCOFFSET ( nRevaNewR );
 | ||
| 		LM_SETSRCOFFSET ( nRevbNewL );
 | ||
| 		LM_SETSRCOFFSET ( nRevbNewR );
 | ||
| 
 | ||
| 		//SETMIN ( aSample, p_output.Size - p_output.Offset );
 | ||
| 
 | ||
| 		for (unsigned int cSample=0;cSample<aSample;cSample++) {
 | ||
| 
 | ||
| 			int tempL0, tempL1, tempR0, tempR1;
 | ||
| 
 | ||
| 			tempL1 = p_input[(cSample<<p_stereo_stride)]>>8;
 | ||
| 			tempR1 = p_input[(cSample<<p_stereo_stride) + 1]>>8;
 | ||
| 
 | ||
| 			tempL0 = LM_MUL ( tempL1, gInputL );
 | ||
| 			tempR0 = LM_MUL ( tempR1, gInputR );
 | ||
| 
 | ||
| 			/*
 | ||
| 			Left -> Wall -> Left Reflection
 | ||
| 			*/
 | ||
| 			tempL1 = tempL0 + LM_MUL ( LM_REVERB( nLwlOld ), gWall );
 | ||
| 			tempR1 = tempR0 + LM_MUL ( LM_REVERB( nRwrOld ), gWall );
 | ||
| 			lwl += LM_MUL ( tempL1 - lwl, gLPF );
 | ||
| 			rwr += LM_MUL ( tempR1 - rwr, gLPF );
 | ||
| 			LM_REVERB( nLwlNew ) = lwl;
 | ||
| 			LM_REVERB( nRwrNew ) = rwr;
 | ||
| 			/*
 | ||
| 			Left -> Wall -> Right Reflection
 | ||
| 			*/
 | ||
| 			tempL1 = tempL0 + LM_MUL ( LM_REVERB( nRwlOld ), gWall );
 | ||
| 			tempR1 = tempR0 + LM_MUL ( LM_REVERB( nLwrOld ), gWall );
 | ||
| 			lwr += LM_MUL ( tempL1 - lwr, gLPF );
 | ||
| 			rwl += LM_MUL ( tempR1 - rwl, gLPF );
 | ||
| 			LM_REVERB( nLwrNew ) = lwr;
 | ||
| 			LM_REVERB( nRwlNew ) = rwl;
 | ||
| 			/*
 | ||
| 			Early Echo(Early Reflection)
 | ||
| 			*/
 | ||
| 			tempL0 =
 | ||
| 					LM_MUL ( LM_REVERB( nEcho0L ), gEcho0 ) +
 | ||
| 					LM_MUL ( LM_REVERB( nEcho1L ), gEcho1 ) +
 | ||
| 					LM_MUL ( LM_REVERB( nEcho2L ), gEcho2 ) +
 | ||
| 					LM_MUL ( LM_REVERB( nEcho3L ), gEcho3 );
 | ||
| 			tempR0 =
 | ||
| 					LM_MUL ( LM_REVERB( nEcho0R ), gEcho0 ) +
 | ||
| 					LM_MUL ( LM_REVERB( nEcho1R ), gEcho1 ) +
 | ||
| 					LM_MUL ( LM_REVERB( nEcho2R ), gEcho2 ) +
 | ||
| 					LM_MUL ( LM_REVERB( nEcho3R ), gEcho3 );
 | ||
| 			/*
 | ||
| 			Late Reverb
 | ||
| 			*/
 | ||
| 			tempL1 = LM_REVERB( nRevaOldL );
 | ||
| 			tempR1 = LM_REVERB( nRevaOldR );
 | ||
| 			tempL0 -= LM_MUL ( tempL1, gReva );
 | ||
| 			tempR0 -= LM_MUL ( tempR1, gReva );
 | ||
| 			LM_REVERB( nRevaNewL ) = tempL0;
 | ||
| 			LM_REVERB( nRevaNewR ) = tempR0;
 | ||
| 			tempL0 = LM_MUL ( tempL0, gReva ) + tempL1;
 | ||
| 			tempR0 = LM_MUL ( tempR0, gReva ) + tempR1;
 | ||
| 			tempL1 = LM_REVERB( nRevbOldL );
 | ||
| 			tempR1 = LM_REVERB( nRevbOldR );
 | ||
| 			tempL0 -= LM_MUL ( tempL1, gRevb );
 | ||
| 			tempR0 -= LM_MUL ( tempR1, gRevb );
 | ||
| 			LM_REVERB( nRevbNewL ) = tempL0;
 | ||
| 			LM_REVERB( nRevbNewR ) = tempR0;
 | ||
| 			tempL0 = LM_MUL ( tempL0, gRevb ) + tempL1;
 | ||
| 			tempR0 = LM_MUL ( tempR0, gRevb ) + tempR1;
 | ||
| 			/*
 | ||
| 			Output
 | ||
| 			*/
 | ||
| 
 | ||
| 			max|=abs(tempL0);
 | ||
| 			max|=abs(tempR0);
 | ||
| 
 | ||
| 			p_output[(cSample<<p_stereo_stride)] += tempL0<<8;
 | ||
| 			p_output[(cSample<<p_stereo_stride) + 1] += tempR0<<8;
 | ||
| 
 | ||
| 		}
 | ||
| 
 | ||
| 		// Advance offsets
 | ||
| 
 | ||
| 		Offset += aSample;
 | ||
| 		if ( Offset >= reverb_buffer_size ) { Offset -= reverb_buffer_size; }
 | ||
| 
 | ||
| 		p_input += aSample << p_stereo_stride;
 | ||
| 		p_output += aSample << p_stereo_stride;
 | ||
| 
 | ||
| 		p_frames -= aSample;
 | ||
| 	}
 | ||
| 
 | ||
| 	state.lwl = lwl;
 | ||
| 	state.lwr = lwr;
 | ||
| 	state.rwl = rwl;
 | ||
| 	state.rwr = rwr;
 | ||
| 	state.Offset = Offset;
 | ||
| 
 | ||
| 	return (max&0x7FFFFF00)!=0; // audio was mixed?
 | ||
| }
 | ||
| 
 | ||
| void ReverbSW::adjust_current_params() {
 | ||
| 
 | ||
| 	*current_params=*reverb_param_modes[mode];
 | ||
| 
 | ||
| 	uint32_t maxofs=0;
 | ||
| 
 | ||
| #define LM_CONFIG_PARAM( x )\
 | ||
| 	current_params->x=(int)( ( (int64_t)current_params->x*(int64_t)mix_rate*8L)/(int64_t)44100);\
 | ||
| 	if (current_params->x>maxofs)\
 | ||
| 		maxofs=current_params->x;
 | ||
| 
 | ||
| 
 | ||
| 	LM_CONFIG_PARAM ( nLwlOld );
 | ||
| 	LM_CONFIG_PARAM ( nRwrOld );
 | ||
| 	LM_CONFIG_PARAM ( nLwlNew );
 | ||
| 	LM_CONFIG_PARAM ( nRwrNew );
 | ||
| 	LM_CONFIG_PARAM ( nLwrOld );
 | ||
| 	LM_CONFIG_PARAM ( nRwlOld );
 | ||
| 	LM_CONFIG_PARAM ( nLwrNew );
 | ||
| 	LM_CONFIG_PARAM ( nRwlNew );
 | ||
| 	LM_CONFIG_PARAM ( nEcho0L );
 | ||
| 	LM_CONFIG_PARAM ( nEcho1L );
 | ||
| 	LM_CONFIG_PARAM ( nEcho2L );
 | ||
| 	LM_CONFIG_PARAM ( nEcho3L );
 | ||
| 	LM_CONFIG_PARAM ( nEcho0R );
 | ||
| 	LM_CONFIG_PARAM ( nEcho1R );
 | ||
| 	LM_CONFIG_PARAM ( nEcho2R );
 | ||
| 	LM_CONFIG_PARAM ( nEcho3R );
 | ||
| 	LM_CONFIG_PARAM ( nRevaOldL );
 | ||
| 	LM_CONFIG_PARAM ( nRevaOldR );
 | ||
| 	LM_CONFIG_PARAM ( nRevbOldL );
 | ||
| 	LM_CONFIG_PARAM ( nRevbOldR );
 | ||
| 	LM_CONFIG_PARAM ( nRevaNewL );
 | ||
| 	LM_CONFIG_PARAM ( nRevaNewR );
 | ||
| 	LM_CONFIG_PARAM ( nRevbNewL );
 | ||
| 	LM_CONFIG_PARAM ( nRevbNewR );
 | ||
| 
 | ||
| 	int needed_buffer_size=maxofs+1;
 | ||
| 	if (reverb_buffer)
 | ||
| 		memdelete_arr(reverb_buffer);
 | ||
| 
 | ||
| 	reverb_buffer = memnew_arr(int,needed_buffer_size);
 | ||
| 	reverb_buffer_size=needed_buffer_size;
 | ||
| 
 | ||
| 	for (uint32_t i=0;i<reverb_buffer_size;i++)
 | ||
| 		reverb_buffer[i]=0;
 | ||
| 
 | ||
| 	state.reset();
 | ||
| 
 | ||
| 
 | ||
| }
 | ||
| 
 | ||
| void ReverbSW::set_mode(ReverbMode p_mode) {
 | ||
| 
 | ||
| 	if (mode==p_mode)
 | ||
| 		return;
 | ||
| 
 | ||
| 	mode=p_mode;
 | ||
| 
 | ||
| 	adjust_current_params();
 | ||
| }
 | ||
| 
 | ||
| void ReverbSW::set_mix_rate(int p_mix_rate) {
 | ||
| 
 | ||
| 	if (p_mix_rate==mix_rate)
 | ||
| 		return;
 | ||
| 
 | ||
| 	mix_rate=p_mix_rate;
 | ||
| 
 | ||
| 	adjust_current_params();
 | ||
| 
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| ReverbSW::ReverbSW() {
 | ||
| 
 | ||
| 	reverb_buffer=0;
 | ||
| 	reverb_buffer_size=0;
 | ||
| 	mode=REVERB_MODE_ROOM;
 | ||
| 	mix_rate=1;
 | ||
| 	current_params = memnew(ReverbParamsSW);
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| ReverbSW::~ReverbSW() {
 | ||
| 
 | ||
| 
 | ||
| 	if (reverb_buffer)
 | ||
| 		memdelete_arr(reverb_buffer);
 | ||
| 
 | ||
| 	memdelete(current_params);
 | ||
| 
 | ||
| }
 | ||
| 
 | 
